Source code analysis of the latest FFMPEG version 2: transcode () function

Source: Internet
Author: User

Let's take a look at the main function first: (omitted a lot of irrelevant code)

Int main (INT argc, char ** argv) <br/>{< br/> optionscontext o = {0}; <br/> int64_t Ti; </P> <p> // initialization of the structure related to the command line analysis. The reset_options (& O, 0 ); </P> <p> // set the log level <br/> av_log_set_flags (av_log_skip_repeated); <br/> parse_loglevel (argc, argv, options ); </P> <p> If (argc> 1 &&! Strcmp (argv [1], "-d") {<br/> run_as_daemon = 1; <br/> av_log_set_callback (log_callback_null); <br/> argc --; <br/> argv ++; <br/>}</P> <p> // register components <br/> avcodec_register_all (); <br/> # If config_avdevice <br/> avdevice_register_all (); <br/> # endif <br/> # If config_avfilter <br/> avfilter_register_all (); <br/> # endif <br/> av_register_all (); <br/> // initialize the network. For Windows, <br/> avformat_network_init (); </P> <p> show_banner (); </P> <p> term_init (); </P> <p> // analyze the parameters input by the command line <br/> parse_options (& O, argc, argv, options, opt_output_file ); </P> <p> // file conversion occurs in this function <br/> If (transcode (output_files, nb_output_files, input_files, nb_input_files) <0) <br/> exit_program (1); </P> <p> exit_program (0); <br/> return 0; <br/>}< br/>

The following is the transcode () function, and the conversion occurs in it. No nonsense. Let's take a look at the annotations. It should be very detailed.

Static int transcode (<br/> outputfile * output_files, // array of output files <br/> int nb_output_files, // number of output files <br/> inputfile * input_files, // input file array <br/> int nb_input_files) // number of input files <br/> {<br/> int ret, I; <br/> avformatcontext * Is, * OS; <br/> outputstream * ost; <br/> inputstream * IST; <br/> uint8_t * no_packet; <br/> int no_packet_count = 0; <br/> int64_t timer_start; <br/> int key; </P> <p> If (! (No_packet = av_mallocz (nb_input_files) <br/> exit_program (1); </P> <p> // sets encoding parameters to enable encoder of all output streams, open the decoder of all input streams and write the file header of all output files, so you have prepared <br/> ret = transcode_init (output_files, nb_output_files, input_files, nb_input_files ); <br/> If (Ret <0) <br/> goto fail; </P> <p> If (! Using_stdin) {<br/> av_log (null, av_log_info, "press [Q] to stop, [?] For Help \ n "); <br/>}</P> <p> timer_start = av_gettime (); </P> <p> // loop, exit after receiving the system signal <br/> for (; received_sigterm = 0;) <br/>{< br/> int file_index, ist_index; <br/> avpacket Pkt; <br/> int64_t ipts_min; <br/> double opts_min; <br/> int64_t cur_time = av_gettime (); </P> <p> ipts_min = int64_max; <br/> opts_min = 1e100; <br/>/* If 'q' pressed, exits */<br/> If (! Using_stdin) <br/>{< br/> // first, check the key that the user pressed and respond accordingly to the data key. <br/> static int64_t last_time; <br/> If (received_nb_signals) <br/> break; <br/>/* read_key () returns 0 on EOF */<br/> If (cur_time-last_time >=100000 &&! Run_as_daemon) {<br/> key = read_key (); <br/> last_time = cur_time; <br/>} else {<br/> ............................. .... <br/>}</P> <p>/* select the stream that we must read now by looking at the <br/> smallest output PTS */<br/>/ /The purpose of the following loop is to find the smallest output PTS (that is, the closest to the current one) <br/> file_index =-1; <br/> for (I = 0; I <nb_output_streams; I ++) {<br/> outputfile *; <br/> int64_t IPTS; <br/> double opts; <br/> Ost = & Output_streams [I]; // loop every output stream <br/> of = & output_files [Ost-> file_index]; // output file corresponding to the output stream <br/> OS = output_files [Ost-> file_index]. CTX; // formatcontext of the output stream <br/> ist = & input_streams [Ost-> source_index]; // input stream corresponding to the output stream </P> <p> If (Ost-> is_past_recording_time | // has the recording time passed? (You may have specified a recording time period) <br/> no_packet [ist-> file_index] | // No data in the corresponding input stream during this time period? <Br/> (OS-> Pb & avio_tell (OS-> Pb)> = of-> limit_filesize) // determines whether the recording range is exceeded (also specified by the user) <br/> continue; // Yes, match one of the preceding statements, then let's look at the next output stream. </P> <p> // determine whether the file of the current input stream can be used (I don't know) <br/> opts = Ost-> St-> PTS. val * av_q2d (Ost-> St-> time_base); <br/> IPTS = ist-> PTS; <br/> If (! Input_files [ist-> file_index]. eof_reached) {<br/> If (IPTS <ipts_min) {<br/> // record every time a smaller input stream of PTS is found, in this way, the minimum input stream <br/> // PTS and the serial number of the input file are found after all the output streams are cyclically. <br/> ipts_min = IPTS; <br/> If (input_sync) <br/> file_index = ist-> file_index; <br/>}< br/> If (OPTs <opts_min) {<br/> opts_min = opts; <br/> If (! Input_sync) <br/> file_index = ist-> file_index; <br/>}</P> <p> // does the following sentence mean: if the current output stream has received the number of frames, when the number of output frames specified by the user is exceeded, <br/> // all output streams corresponding to the output file of the current output stream are counted as exceeding the video recording time? <Br/> If (Ost-> frame_number> = Ost-> max_frames) {<br/> Int J; <br/> for (j = 0; j <of-> CTX-> nb_streams; j ++) <br/> output_streams [of-> ost_index + J]. is_past_recording_time = 1; <br/> continue; <br/>}< br/>/* If none, if is finished */<br/> If (file_index <0) {<br/> // if no suitable input file is found <br/> If (no_packet_count) {<br/> // if data is temporarily unavailable to some input files, it is still not an end <br/> no_packet_count = 0; <br/> memset (no_packet, 0, nb _ Input_files); <br/> usleep (10000); <br/> continue; <br/>}< br/> // The conversion is complete, jump out of the big loop <br/> break; <br/>}</P> <p> // read a frame from the found input file (either audio or video ), and put it in the FIFO queue <br/> is = input_files [file_index]. CTX; <br/> ret = av_read_frame (is, & Pkt); <br/> If (ret = averror (eagain )) {<br/> // when no data is available for the moment <br/> no_packet [file_index] = 1; <br/> no_packet_count ++; <br/> continue; <br/>}</P> <p> // the following code checks whether an input file exists. <br/> If (Ret <0) {<br/> in Put_files [file_index]. eof_reached = 1; <br/> If (opt_shortest) <br/> break; <br/> else <br/> continue; <br/>}</P> <p> no_packet_count = 0; <br/> memset (no_packet, 0, nb_input_files); </P> <p> If (do_pkt_dump) {<br/> av_pkt_dump_log2 (null, av_log_debug, & Pkt, do_hex_dump, <br/> is-> streams [Pkt. stream_index]); <br/>}< br/>/* the following test is needed in case new streams appear <br/> dynamically in Stream: W E ignore them */<br/> // If a stream suddenly pops up in the input file, we will not bird it <br/> If (Pkt. stream_index> = input_files [file_index]. nb_streams) <br/> goto discard_packet; </P> <p> // gets the input stream corresponding to the currently obtained frame <br/> ist_index = input_files [file_index]. ist_index + Pkt. stream_index; <br/> ist = & input_streams [ist_index]; <br/> If (IST-> discard) <br/> goto discard_packet; </P> <p> // repeat the frame timestamp <br/> If (Pkt. DTS! = Av_nopts_value) <br/> Pkt. DTS + = av_rescale_q (input_files [ist-> file_index]. ts_offset, <br/> av_time_base_q, ist-> St-> time_base); <br/> If (Pkt. PTS! = Av_nopts_value) <br/> Pkt. PTS + = av_rescale_q (input_files [ist-> file_index]. ts_offset, <br/> av_time_base_q, ist-> St-> time_base); </P> <p> If (Pkt. PTS! = Av_nopts_value) <br/> Pkt. PTs * = ist-> ts_scale; <br/> If (Pkt. DTS! = Av_nopts_value) <br/> Pkt. DTS * = ist-> ts_scale; </P> <p> If (Pkt. DTS! = Av_nopts_value & ist-> next_pts! = Av_nopts_value <br/> & (is-> iformat-> flags & avfmt_ts_discont) <br/>{< br/> int64_t pkt_dts = av_rescale_q (Pkt. DTS, ist-> St-> time_base, <br/> av_time_base_q); <br/> int64_t Delta = pkt_dts-ist-> next_pts; <br/> If (delta <-1ll * dts_delta_threshold * av_time_base <br/> | (delta> 1ll * dts_delta_threshold * av_time_base <br/> & ist-> st-> codec-> codec_type <br/>! = Avmedia_type_subtitle) <br/> | pkt_dts + 1 <ist-> PTS )&&! Copy_ts) <br/>{< br/> input_files [ist-> file_index]. ts_offset-= delta; <br/> av_log (null, av_log_debug, <br/> "timestamp discontinuity %" prid64 ", new offset = %" prid64 "\ n ", <br/> delta, input_files [ist-> file_index]. ts_offset); <br/> Pkt. DTS-= av_rescale_q (delta, av_time_base_q, ist-> St-> time_base); <br/> If (Pkt. PTS! = Av_nopts_value) <br/> Pkt. PTS-= av_rescale_q (delta, av_time_base_q, ist-> St-> time_base ); <br/>}</P> <p> // converts the frame and writes it to the output file. <br/> If (output_packet (IST, output_streams, nb_output_streams, & Pkt) <0) {<br/> av_log (null, av_log_error, <br/> "error while decoding stream # % d: % d \ n ", <br/> ist-> file_index, ist-> St-> index); <br/> If (exit_on_error) <br/> exit_program (1 ); <br/> av_free_packet (& Pkt); <br/> cont Inue; <br/>}</P> <p> discard_packet: <br/> av_free_packet (& Pkt ); </P> <p>/* dump report by using the output first video and audio streams */<br/> print_report (output_files, output_streams, nb_output_streams, 0, <br/> timer_start, cur_time); <br/>}</P> <p> // the file has been processed, write the remaining data in the buffer to the output file <br/> for (I = 0; I <nb_input_streams; I ++) {<br/> ist = & input_streams [I]; <br/> If (IST-> decoding_needed) {<br/> output_packet (IST, output_streams, nb_output_streams, null); <br/>}< br/> flush_encoders (output_streams, nb_output_streams ); </P> <p> term_exit (); </P> <p> // write the end of the output file (some do not need it ). <br/> for (I = 0; I <nb_output_files; I ++) {<br/> OS = output_files [I]. CTX; <br/> av_write_trailer (OS ); <br/>}</P> <p>/* dump report by using the first video and audio streams */<br/> print_report (output_files, output_streams, nb_output_stre AMS, 1, <br/> timer_start, av_gettime (); </P> <p> // disable all encoders <br/> for (I = 0; I <nb_output_streams; I ++) {<br/> Ost = & output_streams [I]; <br/> If (Ost-> encoding_needed) {<br/> av_freep (& Ost-> St-> codec-> stats_in); <br/> avcodec_close (Ost-> St-> codec ); <br/>}< br/> # If config_avfilter <br/> avfilter_graph_free (& Ost-> graph ); <br/> # endif <br/>}</P> <p> // disable all decoders <br/> for (I = 0; I <nb_input_streams; I ++) {<br /> Ist = & input_streams [I]; <br/> If (IST-> decoding_needed) {<br/> avcodec_close (IST-> St-> codec ); <br/>}</P> <p>/* finished! */<Br/> ret = 0; </P> <p> fail: av_freep (& bit_buffer); <br/> av_freep (& no_packet ); </P> <p> If (output_streams) {<br/> for (I = 0; I <nb_output_streams; I ++) {<br/> Ost = & output_streams [I]; <br/> If (OST) {<br/> If (Ost-> stream_copy) <br/> av_freep (& Ost-> St-> codec-> extradata); <br/> If (Ost-> logfile) {<br/> fclose (Ost-> logfile); <br/> Ost-> logfile = NULL; <br/>}< br/> av_1_o_free (Ost-> FIFO ); /* works even if FIFO is not <br/> initialized but set to zero */<br/> av_freep (& Ost-> St-> codec-> subtitle_header ); <br/> av_free (Ost-> resample_frame.data [0]); <br/> av_free (Ost-> forced_kf_pts); <br/> If (Ost-> video_resample) <br/> sws_freecontext (Ost-> img_resample_ctx); <br/> swr_free (& Ost-> SWR); <br/> av_dict_free (& Ost-> opts ); <br/>}< br/> return ret; <br/>}< br/>

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.