av_write_trailer()

来源:互联网 发布:网络盒子看电视不清晰 编辑:程序博客网 时间:2024/06/07 20:09

首先编码的大致流程如下:
(1)avformat_alloc_output_context2()
(2)avfomat_write_header()
(3)avcodec_send_frame()/avcodec_receive_packet()
(4)av_write_frame()
(5)av_write_trailer()
av_write_trailer()用于输出文件尾,它的声明位于libavformat\avformat.h,如下所示。

/**  * Write the stream trailer to an output media file and free the  * file private data.  *  * May only be called after a successful call to avformat_write_header.  *  * @param s media file handle  * @return 0 if OK, AVERROR_xxx on error  */  int av_write_trailer(AVFormatContext *s);  

它只需要指定一个参数,即用于输出的AVFormatContext。
函数正常执行后返回值等于0。
av_write_trailer()的调用关系如下图所示。
这里写图片描述

av_write_trailer()的定义位于libavformat\mux.c,如下所示。

int av_write_trailer(AVFormatContext *s)  {      int ret, i;       for (;; ) {          AVPacket pkt;          ret = interleave_packet(s, &pkt, NULL, 1);          if (ret < 0)              goto fail;          if (!ret)              break;          //写入AVPacket          ret = write_packet(s, &pkt);          if (ret >= 0)              s->streams[pkt.stream_index]->nb_frames++;           av_free_packet(&pkt);          if (ret < 0)              goto fail;          if(s->pb && s->pb->error)              goto fail;      }   fail:      //写文件尾      if (s->oformat->write_trailer)          if (ret >= 0) {          ret = s->oformat->write_trailer(s);          } else {              s->oformat->write_trailer(s);          }     if (s->pb)         avio_flush(s->pb);      if (ret == 0)         ret = s->pb ? s->pb->error : 0;      for (i = 0; i < s->nb_streams; i++) {          av_freep(&s->streams[i]->priv_data);          av_freep(&s->streams[i]->index_entries);      }      if (s->oformat->priv_class)          av_opt_free(s->priv_data);      av_freep(&s->priv_data);      return ret;  }  

从源代码可以看出av_write_trailer()主要完成了以下两步工作:
(1)循环调用interleave_packet()以及write_packet(),将还未输出的AVPacket输出出来。
(2)调用AVOutputFormat的write_trailer(),输出文件尾。
其中第一步和av_write_frame()中的步骤大致是一样的(interleave_packet()这一部分在并不包含在av_write_frame()中,而是包含在av_interleaved_write_frame()中,这一部分源代码还没有分析)。下面分析一下第二步
AVOutputFormat的write_trailer()是一个函数指针,指向特定的AVOutputFormat中的实现函数。我们以FLV对应的AVOutputFormat为例,看一下它的定义,如下所示。

AVOutputFormat ff_flv_muxer = {      .name           = "flv",      .long_name      = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),      .mime_type      = "video/x-flv",      .extensions     = "flv",      .priv_data_size = sizeof(FLVContext),      .audio_codec    = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF,      .video_codec    = AV_CODEC_ID_FLV1,      .write_header   = flv_write_header,      .write_packet   = flv_write_packet,      .write_trailer  = flv_write_trailer,      .codec_tag      = (const AVCodecTag* const []) {                            flv_video_codec_ids, flv_audio_codec_ids, 0                        },      .flags          = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |                        AVFMT_TS_NONSTRICT,  };  

write_trailer = flv_write_trailer,write_trailer()最终会调用flv_write_trailer()函数。