FFmpeg source code Simple analysis: Avformat_alloc_output_context2 ()

Source: Internet
Author: User

In this paper, a simple analysis of a function commonly used in FFmpeg: Avformat_alloc_output_context2 (). In a ffmpeg-based AV encoder program, this function is usually the first called function (except for the component registration function Av_register_all ()). The AVFORMAT_ALLOC_OUTPUT_CONTEXT2 () function Initializes a AVFORMATCONTEXT structure for output. Its declaration is located in Libavformat\avformat.h, as shown below.
/** * Allocate an avformatcontext for an output format. * Avformat_free_context () can is used to free the context and * everything allocated by the framework within it. * * @param *ctx is set to the created format context, or to NULL in * case of failure * @param oformat format Llocating the context, if NULL * format_name and filename are used instead * @param format_name the name of the output format To allocating the * context, if NULL filename was used instead * @param filename The name of the filename to use fo  R allocating the * context, May is NULL * @return >= 0 In case of success, a negative averror code in case of * failure */int avformat_alloc_output_context2 (Avformatcontext **ctx, Avoutputformat *oformat,                                   const char *format_name, const char *filename);

The English comments in the code are written in more detail, here is a brief description of Chinese.
CTX: Avformatcontext structure created after a successful function call.
Oformat: Specifies the Avoutputformat in Avformatcontext to determine the output format. If NULL is specified, the latter two parameters (Format_name or filename) can be set to guess the output format by FFmpeg.
PS: Using this parameter requires you to manually get Avoutputformat, which is a bit more cumbersome than using the latter two parameters.
Format_name: Specifies the name of the output format. Depending on the format name, FFmpeg will infer the output format. The output format can be "flv", "MKV" and so on.
FileName: Specifies the name of the output file. Depending on the file name, FFmpeg will infer the output format. The file name can be "xx.flv", "yy.mkv" and so on.

If the function executes successfully, its return value is greater than or equal to 0.

The most typical examples of this function are: The simplest ffmpeg-based video encoder (YUV code is h. a)


function call structure diagram

The final analysis of the function call structure is posted first, as shown below.



AVFORMAT_ALLOC_OUTPUT_CONTEXT2 () Take a look at the function definition of avformat_alloc_output_context2 (). The definition of the function is in libavformat\mux.c, as shown below.
int Avformat_alloc_output_context2 (Avformatcontext **avctx, Avoutputformat *oformat, con    St Char *format, const char *filename) {Avformatcontext *s = Avformat_alloc_context ();    int ret = 0;    *avctx = NULL;    if (!s) goto Nomem;            if (!oformat) {if (format) {Oformat = Av_guess_format (format, NULL, NULL); if (!oformat) {Av_log (S, av_log_error, "requested output format '%s ' is not a suitable output format\n", F                Ormat);                ret = Averror (EINVAL);            Goto error;            }} else {Oformat = Av_guess_format (null, filename, null);                if (!oformat) {ret = Averror (EINVAL);                Av_log (S, Av_log_error, "unable to find a suitable output format for '%s ' \ n", filename);            Goto error;    }}} S->oformat = Oformat; if (S->oformat->priv_data_size > 0) {s->priv_data = Av_mallocz (s->oformat->priv_data_size);        if (!s->priv_data) goto Nomem;            if (s->oformat->priv_class) {* (const avclass**) s->priv_data= s->oformat->priv_class;        Av_opt_set_defaults (S->priv_data);    }} else S->priv_data = NULL;    if (filename) av_strlcpy (s->filename, filename, sizeof (s->filename));    *avctx = s;    Return 0;nomem:av_log (S, Av_log_error, "Out of memory\n");    ret = Averror (ENOMEM); Error:avformat_free_context (s); return ret;}

As you can see from the code, the process of AVFORMAT_ALLOC_OUTPUT_CONTEXT2 () consists of the following 2 steps:
1) call Avformat_alloc_context () to initialize a default avformatcontext.

2) If the input avoutputformat is specified, the input avoutputformat is assigned directly to the Oformat of Avoutputformat. If you do not specify an input avoutputformat, you need to infer the output Avoutputformat based on the file format name or filename. Whether the output format is inferred from a file format name or a filename, a function Av_guess_format () is called.

Let's take a look at the two important functions mentioned in the previous steps: Avformat_alloc_context () and Av_guess_format ().


Avformat_alloc_context () Avformat_alloc_context () is a FFmpeg API, which is defined as follows.
Avformatcontext *avformat_alloc_context (void) {    avformatcontext *ic;    IC = Av_malloc (sizeof (Avformatcontext));    if (!ic) return IC;    Avformat_get_context_defaults (IC);    ic->internal = Av_mallocz (sizeof (*ic->internal));    if (!ic->internal) {        avformat_free_context (IC);        return NULL;    }    return IC;}

As you can see from the code, Avformat_alloc_context () first calls Av_malloc () to allocate a chunk of memory to Avformatcontext. A function avformat_get_context_defaults () is then called to set the default value for Avformatcontext. Avformat_get_context_defaults () is defined as follows.
static void Avformat_get_context_defaults (Avformatcontext *s) {    memset (s, 0, sizeof (avformatcontext));    S->av_class = &av_format_context_class;    Av_opt_set_defaults (s);}

As you can see from the code, Avformat_alloc_context () first calls memset () to set the Avformatcontext memory to 0, and then specifies its avclass (after Avclass is specified, The struct supports and avoption related functions); finally call Av_opt_set_defaults () to set the default value for AVFORMATCONTEXT member variable (av_opt_set_defaults () is a function related to Avoption, which is designed to set default values for the specified struct, which is not analyzed here.


Av_guess_format ()

Av_guess_format () is an API for FFmpeg. Its declaration is as follows.

/** * Return The output format in the list of registered output formats * which best matches the provided parameters, or R Eturn NULL If * There is no match. * * @param short_name if non-null checks if short_name matches with the * names of the registered formats * @param Filenam  E If non-null checks if filename terminates with the * extensions of the registered formats * @param mime_type if non-null Checks if Mime_type matches with the * MIME type of the registered formats */avoutputformat *av_guess_format (const char * Short_name,                                const char *filename,                                const char *mime_type);

Take a simple explanation of the parameters in Chinese.
Short_name: The name of the format.
FileName: The name of the file.
The Mime_type:mime type.

Returns the most-matched Avoutputformat. If there is no matching avoutputformat, then NULL is returned.

The code for Av_guess_format () is shown below.

Avoutputformat *av_guess_format (const char *short_name, const char *filename, const char *M    Ime_type) {Avoutputformat *fmt = NULL, *fmt_found;    int Score_max, score; /* Specific test for image sequences */#if config_image2_muxer if (!short_name && filename && av _filename_number_test (filename) && ff_guess_image2_codec (filename)! = Av_codec_id_none) {return av_    Guess_format ("Image2", NULL, NULL); } #endif/* Find the proper file type.    */fmt_found = NULL;    Score_max = 0;        while (FMT = Av_oformat_next (FMT))) {score = 0;        if (fmt->name && short_name && av_match_name (short_name, fmt->name)) score + = 100;        if (fmt->mime_type && mime_type &&!strcmp (Fmt->mime_type, Mime_type)) score + = 10;      if (filename && fmt->extensions && av_match_ext (filename, fmt->extensions)) {      Score + = 5;            } if (Score > Score_max) {score_max = score;        Fmt_found = FMT; }} return fmt_found;}

As can be seen from the code, an integer variable score is used in Av_guess_format () to record the matching degree of each output format. The function contains a while () loop that takes advantage of the function av_oformat_next () to traverse all the Avoutputformat in the FFmpeg and calculates the score of each output format one at a time. The specific calculation process is divided into the following steps:
1) If the package format name matches, score increases by 100. The function av_match_name () is used in the match.
2) if the MIME type matches, score increases by 10. Match directly using the string comparison function strcmp ().
3) If the suffix of the file name matches, the score increases by 5. The function Av_match_ext () is used in the match.

At the end of the while () loop, you get the highest-scoring format, which is the most matched format.

Following the example of a avoutputformat, you can understand the concepts of "package format name", "Mine type", "File name suffix". The following is a variant ff_flv_muxer of the Avoutputformat format for the FLV format av multiplexer (muxer).

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,};

Here's a look at Av_guess_format () several functions involved in the process of matching the best format.


Av_oformat_next ()

Av_oformat_next () is an API function, declared in Libavformat\avformat.h, as shown below.

/** * If f is NULL, returns the first registered output format, * If f is non-null, returns the next registered output for Mat after F * or NULL if f are the last one. */avoutputformat *av_oformat_next (const avoutputformat *f);

The Av_oformat_next () parameter is not NULL when used to get the next Avoutputformat, otherwise the first Avoutputformat is obtained. Defined as follows.

Avoutputformat *av_oformat_next (const Avoutputformat *f) {    if (f)        return f->next;    else        return First_oformat;}


Av_match_name () Av_match_name () is used to compare the names of two formats. To put it simply, compare strings. Note that the string for the function is case-insensitive: the characters are converted to lowercase for comparison.
int av_match_name (const char *name, const char *names) {    const char *p;    int Len, Namelen;    if (!name | |!names)        return 0;    Namelen = strlen (name);    while (P = strchr (names, ', ')) {        len = Ffmax (P-names, Namelen);        if (!av_strncasecmp (name, names, Len))            return 1;        names = p + 1;    }    Return!av_strcasecmp (name, names);}

One more thing to note about the above functions is that a while () loop is used to search for ",". This is because there are some formats in ffmpeg that correspond to multiple format names, such as the MKV format of the MUX (Demuxer), as defined below.
Avinputformat ff_matroska_demuxer = {    . Name           = "MATROSKA,WEBM",    . Long_name      = Null_if_config_small (" MATROSKA/WEBM "),    . Extensions     =" Mkv,mk3d,mka,mks ",    . Priv_data_size = sizeof (Matroskademuxcontext),    . Read_probe     = Matroska_probe,    . Read_header    = Matroska_read_header,    . Read_packet    = Matroska_read_packet,    . Read_close     = Matroska_read_close,    . Read_seek      = Matroska_read_seek,    . Mime_type      = "Audio/webm,audio/x-matroska,video/webm,video/x-matroska"};

As you can see from the code, the Name field in Ff_matroska_demuxer corresponds to "MATROSKA,WEBM". The Av_match_name () function, for such a string, truncates it by "," to a package format name, which is then compared.


Av_match_ext () Av_match_ext () is used to compare the suffix of the file. The function first finds "." In the input file name by way of a reverse lookup, which can be obtained by getting "." The following string to get the suffix of the file. Then call Av_match_name () to compare two suffixes with a method that compares the format name.
int Av_match_ext (const char *filename, const char *extensions) {    const char *ext;    if (!filename)        return 0;    ext = STRRCHR (filename, '. ');    if (EXT)        return av_match_name (ext + 1, extensions);    return 0;}

After the steps above, Av_guess_format () can finally get the most appropriate Avoutputformat and return to AVFORMAT_ALLOC_OUTPUT_CONTEXT2 (). AVFORMAT_ALLOC_OUTPUT_CONTEXT2 () Next assigns the obtained Avoutputformat to the newly created Avformatcontext to complete the initialization work.

FFmpeg source code Simple analysis: Avformat_alloc_output_context2 ()

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.