Simple Analysis of FFmpeg source code: av_write_trailer (),

Source: Internet
Author: User

Simple Analysis of FFmpeg source code: av_write_trailer (),
I plan to write two articles to analyze the three functions avformat_write_header (), av_write_frame (), and av_write_trailer () used to write FFmpeg files (). This article continues to analyze av_write_trailer ().

Av_write_trailer () is used at the end of the output file. Its declaration is in libavformat \ avformat. h, as shown below.

/** * 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);

It only needs to specify a parameter, that is, AVFormatContext for output.
After the function is executed normally, the return value is equal to 0.

For the most typical examples of these two functions, refer:

The simplest Video Encoder Based on FFMPEG (YUV encoding: H.264)


Function call Relationship Diagram

Shows the call relationship of av_write_trailer.



Av_write_trailer () is defined in libavformat \ mux. c, as shown below.
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; // write 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: // write the end Of the file 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 ;}

From the source code, we can see that av_write_trailer () has completed the following two steps:

(1) Call interleave_packet () and write_packet () cyclically to output AVPacket that has not yet been output.

(2) Call write_trailer () of AVOutputFormat to end the output file.

The steps in the first step and av_write_frame () are roughly the same (interleave_packet (). This part is not included in av_write_frame (), but included in av_interleaved_write_frame, this part of the source code has not been analyzed), you can refer to the article "FFmpeg source code simple analysis: av_write_frame ()". The second step is analyzed below.


AVOutputFormat-> write_trailer () AVOutputFormat write_trailer () is a function pointer pointing to the implementation function in a specific AVOutputFormat. Take the AVOutputFormat corresponding to FLV as an example. Let's take a look at its definition, as shown below.
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,};

From the definition of the AVOutputFormat struct corresponding to FLV, we can see that write_trailer () points to the flv_write_trailer () function.


Flv_write_trailer ()

The flv_write_trailer () function is defined in libavformat \ flvenc. c, as shown below.

static int flv_write_trailer(AVFormatContext *s){    int64_t file_size;    AVIOContext *pb = s->pb;    FLVContext *flv = s->priv_data;    int i;    /* Add EOS tag */    for (i = 0; i < s->nb_streams; i++) {        AVCodecContext *enc = s->streams[i]->codec;        FLVStreamContext *sc = s->streams[i]->priv_data;        if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&                (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4))            put_avc_eos_tag(pb, sc->last_ts);    }    file_size = avio_tell(pb);    /* update information */    if (avio_seek(pb, flv->duration_offset, SEEK_SET) < 0)        av_log(s, AV_LOG_WARNING, "Failed to update header with correct duration.\n");    else        put_amf_double(pb, flv->duration / (double)1000);    if (avio_seek(pb, flv->filesize_offset, SEEK_SET) < 0)        av_log(s, AV_LOG_WARNING, "Failed to update header with correct filesize.\n");    else        put_amf_double(pb, file_size);    avio_seek(pb, file_size, SEEK_SET);    return 0;}

From the source code of flv_write_trailer (), we can see that the function has done the following two steps:
(1) If the video Stream is H.264, add a Tag containing the EOS (End Of Stream) NALU.
(2) Update the FLV duration and file size.
The put_avc_eos_tag () function is used to add a Tag containing the eos nalu (including a PreviousTagSize ending with it), as shown below.
static void put_avc_eos_tag(AVIOContext *pb, unsigned ts){    avio_w8(pb, FLV_TAG_TYPE_VIDEO);    avio_wb24(pb, 5);               /* Tag Data Size */    avio_wb24(pb, ts);              /* lower 24 bits of timestamp in ms */    avio_w8(pb, (ts >> 24) & 0x7F); /* MSB of ts in ms */    avio_wb24(pb, 0);               /* StreamId = 0 */    avio_w8(pb, 23);                /* ub[4] FrameType = 1, ub[4] CodecId = 7 */    avio_w8(pb, 2);                 /* AVC end of sequence */    avio_wb24(pb, 0);               /* Always 0 for AVC EOS. */    avio_wb32(pb, 16);              /* Size of FLV tag */}

You can refer to the FLV Encapsulation Format to understand the above functions. Because the FLV Encapsulation Format has been described in the previous article, we will not repeat it here. Here we only record the AVCVIDEOPACKET format, as shown below.
 

We can see that AVCVIDEOPACKET containing eos nalu has a AVCPacketType of 2. In this case, the value of the CompositionTime field of AVCVIDEOPACKET is 0, and the Data field does not need to be included.


Lei Xiaohua
Leixiaohua1020@126.com
Http://blog.csdn.net/leixiaohua1020



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.