Starting from opening the file, the entry function is avformat_open_input (). The following is an analysis of this function.
// The parameter PS contains all media-related context structures. If you enable the media successfully, this function returns an avformatcontext instance. // The filename parameter is the media file name or URL. // The FMT parameter is the operation structure of the media format to be opened. Because it is read, it is inputformat. here, you can pass in an inputformat defined by the caller, which corresponds to the-f xxx segment in the command line. If it is specified, // The actual format of the file will not be detected when the file is opened, take it as the standard. // The Parameter options is an operation in a certain format. It is created to pass in special operation parameters in different formats in the command line. To understand the process, you can ignore it. int avformat_open_input (avformatcontext ** ps, const char * filename, avinputformat * FMT, avdictionary ** options) {avformatcon Text * s = * pS; int ret = 0; avformatparameters ap = {0 }}; avdictionary * TMP = NULL; // create the context structure if (! S &&! (S = avformat_alloc_context () return averror (enomem); // If the User specifies the input format, directly use it if (FMT) S-> iformat = FMT; // ignore if (options) av_dict_copy (& TMP, * options, 0); If (ret = av_opt_set_dict (S, & TMP) <0) goto fail; // open the input media (if needed) and initialize all media read and write structures, such as // aviocontext, avinputformat, and so on if (ret = init_input (S, filename )) <0) goto fail; // after this function is executed, S-> Pb and S-> iformat both point to a valid instance. PB is used to read and write data. It // uses media data as a stream to read and write data. No matter what media format, iformat reads petabytes of data. Analysis is performed based on a certain media lattice //, that is, PB is at the underlying layer, and iformat is at the upper layer. // a large number of static image file formats are processed in a single format. For example, to open a. JPEG file, the format is required. // The name is image2. the details are not very detailed here. /* Check filename in case an image number is expected */If (S-> iformat-> flags & avfmt_neednumber) {If (! Av_filename_number_test (filename) {ret = averror (einval); goto fail;} s-> duration = s-> start_time = av_nopts_value; // save the file name av_strlcpy (S-> filename, filename, sizeof (S-> filename) in the context;/* allocate private data * // allocate private data for the current format, the private structure used for read/write operations in a certain format. // The size of this structure is specified when avinputformat is defined. if (S-> iformat-> priv_data_size> 0) {If (! (S-> priv_data = av_mallocz (S-> iformat-> priv_data_size) {ret = averror (enomem); goto fail ;} // you do not need to worry about it first. If (S-> iformat-> priv_class) {* (const avclass **) S-> priv_data = s-> iformat-> priv_class; av_opt_set_defaults (S-> priv_data); If (ret = av_opt_set_dict (S-> priv_data, & TMP) <0) goto fail ;}/ * e.g. avfmt_nofile formats will not have a aviocontext * // read and save ID3 data from the MP3 file. if (S-> Pb) ff_id3v2_read (S, id3v2_def Ault_magic); // read the Media Header. In read_header (), initialize the media in a certain format, such as filling your own // Private structure, allocate and initialize the stream structure based on the number of streams, and point the file pointer to the beginning of the Data zone. if (! (S-> flags & avfmt_flag_priv_opt) & S-> iformat-> read_header) if (ret = s-> iformat-> read_header (S, & AP) <0) goto fail; // Save the IF (! (S-> flags & avfmt_flag_priv_opt) & S-> Pb &&! S-> data_offset) S-> data_offset = avio_tell (S-> Pb); s-> raw_packet_buffer_remaining_size = raw_packet_buffer_size; If (options) {av_dict_free (options ); * Options = TMP;} * PS = s; // return 0 after successful execution; // failed execution fail: av_dict_free (& TMP); If (S-> Pb &&! (S-> flags & avfmt_flag_custom_io) avio_close (S-> Pb); avformat_free_context (s); * PS = NULL; return ret ;}
The following is an analysis of init_input ():
// Open the input media and fill in its avinputformat structure static int init_input (avformatcontext * s, const char * filename) {int ret; avprobedata Pd = {filename, null, 0 }; // when the caller has specified Pb (data acquisition method), this is generally not the case. if (S-> Pb) {S-> flags | = avfmt_flag_custom_io; If (! S-> iformat) // if PB is specified but iformat is not specified, the media data is read as Pb for detection and obtained. obtain the iformat. return av_probe_input_buffer (S-> Pb, & S-> iformat, filename, S, 0, 0); else if (S-> iformat-> flags & avfmt_nofile) // if you have specified Pb AND iformat, but you have specified unnecessary files (including URLs), this is a conflict, // PB is not required at this time, because the file does not need to be operated, and it is not an error. av_log (S, av_log_warning, "Custom aviocontext makes no sense and" "will be ignored with avfmt_nofile format. \ n "); Return 0;} // It is generally executed here if (S-> iform At & S-> iformat-> flags & avfmt_nofile) | (! S-> iformat & (S-> iformat = av_probe_input_format (& PD, 0) // If iformat is specified and no file is required, PB is not required, you can directly return // If iformat is not specified, but you can guess the iformat from the file name. return 0; // if the media format cannot be guessed from the file name, you can only open this file for detection. open the file if (ret = avio_open (& S-> Pb, filename, avio_flag_read) <0) return ret; If (S-> iformat) return 0; // return av_probe_input_buffer (S-> Pb, & S-> iformat, filename, s, 0, 0 );}
Let's take a look at the file opening process:
// Open the media int avio_open (aviocontext ** S, const char * filename, int flags) pointed to by an address {// urlcontext indicates the media file pointed to by a URL address, the local path is also considered a type. it encapsulates // The data related to a media file. The most important thing is the prot variable, which is urlprotocol-type. // The prot represents a specific type of coordination and Protocol operation functions. urlcontext contains different Prot. // you can use different protocols to read and write media data through urlcontext, such as TCP, HTTP, the file protocol is used for local // files. urlcontext * h; int err; // create and initialize urlcontext. Its Prot is determined by the file name. then open the media file err = ffurl_open (& H, filename, flags); If (ERR <0) return err; // The file has actually been opened on it. here we only fill in aviocontext. it records the // urlcontext and the function pointer that fills in the read/write data. err = ffio_fdopen (S, H); If (ERR <0) {ffurl_close (h); Return err;} return 0 ;}
Below are the probe Functions
Int av_probe_input_buffer (aviocontext * pb, avinputformat ** FMT, const char * filename, void * logctx, unsigned int offset, unsigned int max_probe_size) {avprobedata Pd = {filename? Filename: "", null,-offset}; unsigned char * Buf = NULL; int ret = 0, probe_size; // calculates the maximum number of bytes of the test data if (! Max_probe_size) {max_probe_size = response;} else if (max_probe_size> probe_buf_max) {max_probe_size = response;} else if (max_probe_size <response) {return averror (einval );} if (offset >=max_probe_size) {return averror (einval) ;}// loop until the specified data is detected for (probe_size = probe_buf_min; probe_size <= max_probe_size &&! * FMT; probe_size = ffmin (probe_size <1, ffmax (max_probe_size, probe_size + 1) {int score = probe_size <max_probe_size? Avprobe_score_max/4: 0; int buf_offset = (probe_size = probe_buf_min )? 0: probe_size> 1; void * buftmp; If (probe_size <OFFSET) {continue ;} /* read probe data * // allocate the buffer buftmp = av_realloc (BUF, probe_size + avprobe_padding_size) for reading data; If (! Buftmp) {av_free (BUF); Return averror (enomem);} Buf = buftmp; // read data to the buffer space using PB if (ret = avio_read (Pb, BUF + buf_offset, probe_size-buf_offset) <0) {/* fail if error was not end of file, otherwise, lower score */If (Ret! = Averror_eof) {av_free (BUF); return ret;} score = 0; ret = 0;/* error was end of file, nothing read */} PD. buf_size + = ret; PD. buf = & Buf [offset]; // clear the zero memset (PD. BUF + PD. buf_size, 0, avprobe_padding_size);/* Guess file format * // only test the media format from an opened file * FMt = av_probe_input_format2 (& PD, 1, & score ); if (* FMT) {If (score <= avprobe_score_max/4) {// This can only be true in the last iterationav_log (Lo Gctx, av_log_warning, "format % s detected only with low score of % d, misdetection possible! \ N ", (* FMT)-> name, score);} elseav_log (logctx, av_log_debug, "format % s probed with size = % d and score = % d \ n", (* FMT)-> name, probe_size, score);} // failed, continue} If (! * FMT) {av_free (BUF); Return averror_invaliddata;}/* rewind. reuse probe buffer to avoid seeking * // Save the data read during the probe to petabytes for immediate use during real read. if (ret = ffio_rewind_with_probe_data (Pb, Buf, PD. buf_size) <0) av_free (BUF); return ret ;}