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

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

时间:2022-12-19 09:55:24浏览次数:44  
标签:ffmpeg avcodec 体时 free avformat context 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.

Free it and all its contents and set *s to 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);
 }
  1. 我在程序中,直接将avformat_close_input函数所在的位置替换成以上函数,经过排查,发现是在内部调用avformat_free_context()函数时崩溃了。
  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)处发生崩溃错误,这时候我就疑惑了,为什么在释放这个参数时会崩溃,为什么呢?由于这些函数内部的参数太多,而且不好理解,我就没有深究下去了。

  1. 进而,我去百度"调用avformat_free_context崩溃",发现一篇博主文章

    里面说到一句话:

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

  • 因为你释放掉这个内存,里面的一些结构体没有被释放会导致程序崩溃。

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

  2. 为什么会这样呢,我带着问题去找答案。

原来要使用avcodec_free_context去释放解码器上下文,是需要在分配解码器上下文时搭配使用avcodec_alloc_context3()去分配

//通过传入的编码器名字查找编码器;
AVCodec *codec = avcodec_find_encoder_by_name(codec_name);
if (!codec) {
    fprintf(stderr, "Codec '%s' not found\n", codec_name);
    return -1;
}
 
//通过找到的AVCodec结构分配编码器上下文;
AVCodecContext *c = = avcodec_alloc_context3(codec);
if (!c) {
    fprintf(stderr, "Could not allocate video codec context\n");
    return -1;
}

而我自己使用的是旧的方式去分配解码器上下文

//分配视频解码器上下文
AVCodecContext * m_pVideoDecodeContext;
m_pVideoDecodeContext = m_pAvFormatContext->streams[m_iVideoStreamIndex]->codec;

//分配音频解码器上下文
AVCodecContext * m_pAudioDecodeContext;
m_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, &param)
//官方案例
av_dict_set(&opts, "b", "2.5M", 0);
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec)
    exit(1);
 
context = avcodec_alloc_context3(codec);
 
if (avcodec_open2(context, codec, opts) < 0)
    exit(1);

avcodec_open2官方的解释:

Initialize the AVCodecContext to use the given AVCodec.

Prior to using this function the context has to be allocated with avcodec_alloc_context3(). 

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

综上所述,是自己对于ffmpeg函数的使用还没有炉火纯青。

标签:ffmpeg,avcodec,体时,free,avformat,context,av,close
From: https://www.cnblogs.com/jj-Must-be-sucessful/p/16991504.html

相关文章

  • ffmpeg 移植到 android
    一:生成动态库(.so文件)-->环境:操作系统:Ubuntu9.10ffmpeg源码版本:ffmpeg-0.6.1(可以在​​http://ffmpeg.org/download.html​​ 下载源码)androidndk版本:android-ndk-r4b-linux......
  • ffmpeg-音频处理
    音频去除音频中1秒的空白ffmpeg.exe-i.\xy.m4a-afsilenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-30dBout.wav音频拼接ffmpeg-i"concat:a.m4......
  • linux 安装 ffmpeg
    windows上安装,直接下载压缩包解压。linux安装,找了半天各种技术文章,说最好编译安装,按照步骤安装编译环境编译成功了,但是使用的时候总要安装各种外部库,转码转不了等等问题.........
  • 通过ffmpeg将16k采样率的wav文件转换成采样率为8k的wav
    一安装win10的ffmpeg 二进入所在文件夹文件名字:temp.wavtrans_temp.pcmwav_name.wav先将wav转换成pcm文件ffmpeg-itemp.wav-acodecpcm_s16le-fs16l......
  • QT+FFmpeg4
    1Windows环境搭建FFMPEG官网:http://ffmpeg.org/下载4.2.1版本源码源码:https://ffmpeg.org/releases/ffmpeg-4.2.1.tar.bz2下载4.2.1编译好的文件下载已经编译好的FFM......
  • C# 使用多线程在关闭窗体时如何关闭所有线程,使程序退出不产生报错
    在winform开发中,程序内部使用了多线程或定时器等功能,在关闭窗体退出程序时,如果只有UI线程关闭,而托管线程还在运行就会报错。关闭线程的方法有以下几种,其中最彻底的方法为:S......
  • ffmpeg库安装及入门指南(Windows篇)- 2022年底钜献
    最近项目需要,使用了ffmpeg做摄像头视频采集和串流。这几天有点时间,打算把相关的一些知识记录分享一下。在撰写本文时,我又在另外一台电脑上把ffmpeg重新安装了一遍,所以......
  • Win10编译Android版本的FFmpeg库
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • Linux安装ffmpeg
    使用的机器是Ubuntu18.04下载安装环境进入官网http://ffmpeg.org/点击Download,找到适用自身系统的下载包,我这里下载的Ubuntu-Officialpackages得到一个ffmpeg_x.x.x.......
  • ffmpeg简单使用
    转换视频格式.avi转.mp4ffmpeg-iinput.avioutput.mp4提取音频默认mp4的audiocodec是aac,一般常见的音频都是aacffmpeg-iinput.mp4-acodecaac-vnoutput.aa......