首页 > 其他分享 >ffmpeg使用avformat_close_input()函数释放结构体时崩溃的问题

ffmpeg使用avformat_close_input()函数释放结构体时崩溃的问题

时间:2023-08-11 18:33:38浏览次数:108  
标签:ffmpeg avcodec 体时 free avformat av close 上下文

先看一下我调试时,发现程序崩溃的代码位置

 
  //这是我的程序释放流上下文时的操作
  if(m_pAvFormatContext)
  {
  //释放视频解码器上下文
  if(m_iVideoStreamIndex >= 0)
  avcodec_free_context(&m_pVideoDecodeContext); //此处是发生崩溃的根本原因
   
  //释放音频解码器上下文
  if(m_iAudioStreamIndex >= 0)
  avcodec_free_context(&m_pAudioDecodeContext); //此处是发生崩溃的根本原因
   
  //释放文件流上下文(发生崩溃)
  avformat_close_input(&m_pAvFormatContext);
  avformat_free_context(m_pAvFormatContext);
  m_pAvFormatContext = YNULL;
  }
 

1. 在一次释放文件流上下文的调试中,发现调用avformat_close_input函数时程序崩溃退出。查看函数内部

功能

  • Close an opened input AVFormatContext.(关闭打开的输入AVFormatContext)
  • Free it and all its contents and set s to NULL.(释放它和它的所有内容,并设置为NULL)
 
  void avformat_close_input(AVFormatContext **ps)
  {
  AVFormatContext *s;
  AVIOContext *pb;
   
  if (!ps || !*ps)
  return;
   
  s = *ps;
  pb = s->pb;
   
  if ((s->iformat && strcmp(s->iformat->name, "image2") && s->iformat->flags & AVFMT_NOFILE) ||
  (s->flags & AVFMT_FLAG_CUSTOM_IO))
  pb = NULL;
   
  if (s->iformat)
  if (s->iformat->read_close)
  s->iformat->read_close(s);
   
  avformat_free_context(s);
   
  *ps = NULL;
   
  avio_close(pb);
  }
 

2. 经过排查,发现是在内部调用avformat_free_context()函数时崩溃了, 查看avformat_free_context源码

 
  void avformat_free_context(AVFormatContext *s)
  {
  FFFormatContext *si;
   
  if (!s)
  return;
  si = ffformatcontext(s);
   
  if (s->oformat && s->oformat->deinit && si->initialized)
  s->oformat->deinit(s);
   
  av_opt_free(s);
  if (s->iformat && s->iformat->priv_class && s->priv_data)
  av_opt_free(s->priv_data);
  if (s->oformat && s->oformat->priv_class && s->priv_data)
  av_opt_free(s->priv_data);
   
  for (unsigned i = 0; i < s->nb_streams; i++)
  ff_free_stream(&s->streams[i]);
  s->nb_streams = 0;
   
  for (unsigned i = 0; i < s->nb_programs; i++) {
  av_dict_free(&s->programs[i]->metadata);
  av_freep(&s->programs[i]->stream_index);
  av_freep(&s->programs[i]);
  }
  s->nb_programs = 0;
   
  av_freep(&s->programs);
  av_freep(&s->priv_data);
  while (s->nb_chapters--) {
  av_dict_free(&s->chapters[s->nb_chapters]->metadata);
  av_freep(&s->chapters[s->nb_chapters]);
  }
  av_freep(&s->chapters);
  av_dict_free(&s->metadata);
  av_dict_free(&si->id3v2_meta);
  av_packet_free(&si->pkt);
  av_packet_free(&si->parse_pkt);
  av_freep(&s->streams);
  ff_flush_packet_queue(s);
  av_freep(&s->url);
  av_free(s);
  }
 

初步发现是在avformat_free_context内部的av_packet_free(&si->parse_pkt)处发生崩溃错误。为什么在释放这个参数时会崩溃?由于这些函数内部的参数太多且不好理解,我没有深究下去

3. 百度"调用avformat_free_context崩溃",发现一篇博主文章 [ 关于avformat_free_context释放流上下文的一些问题 ]里面说到一句话:

 
  //下面是释放上下文的步骤顺序
  sws_freeContext(pSwsContext);
  av_frame_free(&pAVFrame);
  avcodec_close(pAVCodecContext);
  avformat_close_input(&pAVFormatContext);
 
  • 释放顺序不能错,如果想关闭一个取流地址不能单独调用avformat_close_input(&pAVFormatContext);

  • 因为调用avformat_close_input释放文件流上下文时,如果里面的一些结构体在之前没有被提前释放掉,会导致程序崩溃。

4. 打开代码调试,查看调用顺序,经过一番查找后,发现没有调用顺序没有问题。但是有一个地方是跟上面代码不同的地方,是释放解码器上下文时,我使用到新的API接口avcodec_free_context而不是avcodec_close,于是尝试换成avcodec_close重新运行,发现没有问题了!

 
  //这是我的程序释放流上下文时的操作
  if(m_pAvFormatContext)
  {
  //释放视频解码器上下文
  if(m_iVideoStreamIndex >= 0)
  avcodec_close(&m_pVideoDecodeContext); //修改此处则可以正常运行
   
  //释放音频解码器上下文
  if(m_iAudioStreamIndex >= 0)
  avcodec_close(&m_pAudioDecodeContext); //修改此处则可以正常运行
   
  //释放文件流上下文
  avformat_close_input(&m_pAvFormatContext);
  avformat_free_context(m_pAvFormatContext);
  m_pAvFormatContext = YNULL;
  }
 

5. 去ffmpeg官网查看函数解析

AVCodecContext* avcodec_alloc_context3 (const AVCodec * codec)

功能

  • 分配一个AVCodecContext,并将其字段设置为默认值。
  • 结果由avcodec_free_context()释放

参数

  • 如果非null,分配私有数据并初始化给定编解码器的默认值。使用不同的编解码器调用avcodec_open2()是非法的。
  • 如果为NULL,那么特定于编解码器的默认值将不会被初始化,这可能会导致默认设置不理想(这对于编码器(例如libx264)尤为重要)。

返回值

  • 一个用默认值填充的AVCodecContext,失败时返回NULL。
 
  //通过传入的音频、视频编码器名字查找编码器
  AVCodec * codec = avcodec_find_decoder(AV_CODEC_ID_H264);
  if (!codec)
  exit(1);
   
  //分配音频、视频编码器上下文,并初始化
  AVCodecContext * context = avcodec_alloc_context3(codec);
  if (avcodec_open2(context, codec, YNULL) < 0)
  exit(1);
   
  //释放音频、视频解码器上下文
  avcodec_free_context(c);
 

avcodec_open2函数介绍:
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

功能

  • 初始化AVCodecContext以使用给定的AVCodec
  • 在使用此函数之前,必须为上下文分配avcodec_alloc_context3()

6. 我使用另外一种方式去分配解码器上下文,则使用avcodec_close()释放解码器上下文

 
  //分配视频解码器上下文
  AVCodecContext * pVideoDecodeContext = YNULL;
  pVideoDecodeContext = m_pAvFormatContext->streams[m_iVideoStreamIndex]->codec;
   
  //分配音频解码器上下文
  AVCodecContext * pAudioDecodeContext = YNULL;
  pAudioDecodeContext= m_pAvFormatContext->streams[m_iAudioStreamIndex]->codec;
   
  //初始化解码器
  AVCodec * pVideoCodec = YNULL;
  pVideoCodec = avcodec_find_decoder_by_name("h264_rkmpp_dec"); //arm的显示卡
   
  avcodec_open2(m_pVideoDecodeContext, pVideoCodec, YNULL)
   
  //释放音频、视频解码器
  avcodec_close(m_pVideoDecodeContext);
 
C++ 复制 全屏

综上所述,是因为不正常释放解码器上下文导致的崩溃。

标签:ffmpeg,avcodec,体时,free,avformat,av,close,上下文
From: https://www.cnblogs.com/lidabo/p/17623716.html

相关文章

  • C# 使用FFmpeg.Autogen对byte[]进行编解码
    C#使用FFmpeg.Autogen对byte[]进行编解码,参考:https://github.com/vanjoge/CSharpVideoDemo入口调用类:usingSystem;usingSystem.IO;usingSystem.Drawing;usingSystem.Runtime.InteropServices;usingFFmpeg.AutoGen;namespaceFFmpegAnalyzer{publicclassFFm......
  • rocky linux:安装ffmpeg(ffmpeg 5.1.3/rocky linux 9.2)
    一,ffmpeg官网:网址:http://ffmpeg.org/如图:说明:最新版本出到了6.0,我们从dnf通道安装,版本可能略低二,安装rpmfusion库[root@img~]#dnfinstall--nogpgcheckhttps://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm[root@img~]#dnfinstall......
  • 解决winform调用wpf窗体时原窗体缩小的问题
    在使用winform调用wpf窗体时,原来的winform窗体会缩小,同时分辨率会发生变化,用如下方法来解决这个问题。首先找到winform项目中的Properties ==>AssemblyInfo.cs,打开该文件,在末尾加入如下代码,之后重新运行即可。[assembly:System.Windows.Media.DisableDpiAwareness]//禁用WPF......
  • clang 静态编译 ffmpeg
    文档说明:只记录关键的地方;发文时间:2023-08-06意义:静态编译ffmpeg,可自由裁剪,使用libc构建;支持macos、linux构建;生成库依赖库图环境:alpine:3.17dockerclang备注:大部分软件源代码来源于github.com,下载过程断断续续的。请自备代理借助swoole-cli已经编写好......
  • JPA配置实体时 insertable = false, updatable = false
    @Excel(name="创建时间",format="yyyy-MM-ddHH:mm:ss",width=20)@Column(name="created_time",insertable=false,columnDefinition="timestampdefaultcurrent_timestamp")@Temporal(TemporalType.TIMES......
  • FFmpeg方法用法大全【欢迎补充】
    1.定义FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开......
  • ffmpeg视频处理
    CMakeLists.txtcmake_minimum_required(VERSION3.25)project(test)set(CMAKE_CXX_STANDARD17)set(CMAKE_CXX_STANDARD14)set(FFMPEG_DIR/usr/local/ffmpeg)set(FFMPEG_INCLUDE_DIR${FFMPEG_DIR}/include)set(FFMPEG_LIBRARY_DIR${FFMPEG_DIR}/lib)include_......
  • clion搭建ffmpeg环境
    配置链接库路径sudovim/etc/ld.so.conf.d/ffmpeg.conf/usr/local/ffmpeg/lib/编写CMakeLists.txtcmake_minimum_required(VERSION3.25)project(test)set(CMAKE_CXX_STANDARD17)set(CMAKE_CXX_STANDARD14)set(FFMPEG_DIR/usr/local/ffmpeg)set(FFMPEG_INCL......
  • ffmpeg + SDL2播放音频示例
    在网上搜罗了各种各样的样例代码,都存在各种各样的问题,调了好长时间终于能无杂音播放了由于个人场景需要本样例加了选择扬声器的功能不过有的可能还会有问题,目前ogg的文件都能播,mp3有的不行写一下网上的其他代码可能存在的问题和我的修改注:代码是C++17,如果编不过需要小改一下......
  • ffmpeg合并音频和视频
    ffmpeg合并音频和视频命令行ffmpeg-ivideo.m4s-iaudio.m4s-acodeccopy-vcodeccopyout.mp4使用ffmpeg的apiextern"C"{#include"libavformat/avformat.h"#include"libavutil/dict.h"#include"libavutil/opt.h"#include&quo......