I intend to write two articles to simply analyze FFmpeg's written files using 3 functions Avformat_write_header (), Av_write_frame () and Av_write_trailer (). This article continues to analyze Av_write_trailer ().
Av_write_trailer () is used to output the end of the file, and its declaration is in libavformat\avformat.h, as shown below.
/** * Write The stream trailer to a output media file and free the * file private data. * * May is 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 one parameter, which is the avformatcontext for the output.
The return value is equal to 0 after the function executes normally.
The most typical examples of these 2 functions can be consulted:
The simplest video encoder based on FFmpeg (YUV encoded as H.
Function call graph
The invocation relationship of Av_write_trailer () is as shown.
The definition of Av_write_trailer () Av_write_trailer () is located 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 file tail if (S->oformat->write_trailer) if (ret >= 0) {ret = S->oformat->write_traile R (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 can be seen Av_write_trailer () mainly completed the following two steps:
(1) Loop calls Interleave_packet () and Write_packet () to output the avpacket that have not yet been output.
(2) Call Avoutputformat's Write_trailer (), Output end of file.
The steps in the first and av_write_frame () are roughly the same (the Interleave_packet () section is not included in Av_write_frame (), but is contained in the 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 that points to the implementation function in a particular avoutputformat. Let's take a look at the definition of the FLV corresponding Avoutputformat, 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< c24/>= Avfmt_globalheader | Avfmt_variable_fps | Avfmt_ts_nonstrict,};
We can see from the definition of the AVOUTPUTFORMAT structure of the FLV that Write_trailer () points to the Flv_write_trailer () function.
Flv_write_trailer ()
The definition of the
Flv_write_trailer () function is located 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->co dec_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 wit H 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 (), you can see that the function does the following two steps:
(1) If the video stream is H. +, add the tag containing the EOS (End of Stream) Nalu.
(2) Update the length of the FLV information, as well as file size information.
where the Put_avc_eos_tag () function is used to add a tag containing the EOS Nalu (a previoustagsize that contains the end), 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 bits of timestamp in MS * /AVIO_W8 (Pb, (ts >>) & 0x7F);/* MSB of TS in MS * /AVIO_WB24 (p b, 0); /* Streamid = 0 * /avio_w8 (Pb, 23°c); /* 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, +); /* Size of FLV tag */}
You can refer to the FLV Encapsulation format to understand the above functions. Since the FLV encapsulation format has been described in the previous article, it is no longer repeated here, here only the format of the Avcvideopacket is recorded here, as shown below.
It can be seen that the avcpackettype of avcvideopacket containing EOS Nalu is 2. In this case, Avcvideopacket's Compositiontime field takes 0 and does not need to contain the data field.
Lei Huawei
[Email protected]
http://blog.csdn.net/leixiaohua1020
FFmpeg source code Simple analysis: Av_write_trailer ()