FFmpeg源码:av_probe_input_format3函数和AVInputFormat结构体分析(FFmpeg源码5.0.3版本) [复制链接]
发表于 2026-4-24 09:30:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
=================================================================
FFmpeg源码:av_probe_input_format3函数分析:
FFmpeg源码:av_probe_input_format3函数和AVInputFormat结构体分析(FFmpeg源码5.0.3版本
7.0.1版本的FFmpeg源码中av_probe_input_format3函数和AVInputFormat结构体的改变
=================================================================



一、av_probe_input_format3函数的声明

av_probe_input_format3函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为5.0.3)的头文件libavformat/avformat.h中:
  1. /**
  2. * Guess the file format.
  3. *
  4. * @param is_opened Whether the file is already opened; determines whether
  5. *                  demuxers with or without AVFMT_NOFILE are probed.
  6. * @param score_ret The score of the best detection.
  7. */
  8. const AVInputFormat *av_probe_input_format3(const AVProbeData *pd,
  9.                                             int is_opened, int *score_ret);
复制代码

该函数在avformat_open_input函数内部被调用。其作用是:推测文件的格式。


形参pd:输入型参数,为AVProbeData范例的指针。
AVProbeData结构体声明在libavformat/avformat.h中:
  1. /**
  2. * This structure contains the data a format has to probe a file.
  3. */
  4. typedef struct AVProbeData {
  5.     const char *filename;
  6.     unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */
  7.     int buf_size;       /**< Size of buf except extra allocated bytes */
  8.     const char *mime_type; /**< mime_type, when known. */
  9. } AVProbeData;
复制代码
pd->filename为:须要被推测格式的文件的路径。
pd->buf:假如路径为pd->filename的文件还没被打开,pd->buf的值为NULL。假如路径为pd->filename的文件已经被打开,pd->buf指向“存放从该文件读取出来的二进制数据”的缓冲区。
pd->buf_size:缓冲区pd->buf的巨细,单位为字节。
pd->mime_type:一样平常为NULL,可忽略。

形参is_opened:输入型参数。值为0表现路径为pd->filename的文件还没被打开,值为1表现路径为pd->filename的文件已经被打开了。


形参score_ret:输出型参数,指向一个int型变量。实行av_probe_input_format3函数后,score_ret指向的int型变量的值会变为:最匹配“路径为pd->filename的文件”的格式的分值。
分值的范围为0到100分,值越大表现越匹配。分值对应的宏界说在头文件libavformat/avformat.h中被界说:
  1. #define AVPROBE_SCORE_EXTENSION  50 ///< score for file extension
  2. #define AVPROBE_SCORE_MIME       75 ///< score for file mime type
  3. #define AVPROBE_SCORE_MAX       100 ///< maximum score
复制代码


返回值:为AVInputFormat范例的指针。假如形参is_opened的值为0(文件还没被打开),返回值为NULL;假如is_opened的值为1(文件已经被打开了),则返回最匹配“路径为pd->filename的文件”的格式的AVInputFormat结构体指针。
AVInputFormat结构体声明在libavformat/avformat.h中:
  1. /**
  2. * @addtogroup lavf_decoding
  3. * @{
  4. */
  5. typedef struct AVInputFormat {
  6.     /**
  7.      * A comma separated list of short names for the format. New names
  8.      * may be appended with a minor bump.
  9.      */
  10.     const char *name;
  11.     /**
  12.      * Descriptive name for the format, meant to be more human-readable
  13.      * than name. You should use the NULL_IF_CONFIG_SMALL() macro
  14.      * to define it.
  15.      */
  16.     const char *long_name;
  17.     /**
  18.      * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
  19.      * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
  20.      * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
  21.      */
  22.     int flags;
  23.     /**
  24.      * If extensions are defined, then no probe is done. You should
  25.      * usually not use extension format guessing because it is not
  26.      * reliable enough
  27.      */
  28.     const char *extensions;
  29.     const struct AVCodecTag * const *codec_tag;
  30.     const AVClass *priv_class; ///< AVClass for the private context
  31.     /**
  32.      * Comma-separated list of mime types.
  33.      * It is used check for matching mime types while probing.
  34.      * @see av_probe_input_format2
  35.      */
  36.     const char *mime_type;
  37.     /*****************************************************************
  38.      * No fields below this line are part of the public API. They
  39.      * may not be used outside of libavformat and can be changed and
  40.      * removed at will.
  41.      * New public fields should be added right above.
  42.      *****************************************************************
  43.      */
  44.     /**
  45.      * Raw demuxers store their codec ID here.
  46.      */
  47.     int raw_codec_id;
  48.     /**
  49.      * Size of private data so that it can be allocated in the wrapper.
  50.      */
  51.     int priv_data_size;
  52.     /**
  53.      * Internal flags. See FF_FMT_FLAG_* in internal.h.
  54.      */
  55.     int flags_internal;
  56.     /**
  57.      * Tell if a given file has a chance of being parsed as this format.
  58.      * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes
  59.      * big so you do not have to check for that unless you need more.
  60.      */
  61.     int (*read_probe)(const AVProbeData *);
  62.     /**
  63.      * Read the format header and initialize the AVFormatContext
  64.      * structure. Return 0 if OK. 'avformat_new_stream' should be
  65.      * called to create new streams.
  66.      */
  67.     int (*read_header)(struct AVFormatContext *);
  68.     /**
  69.      * Read one packet and put it in 'pkt'. pts and flags are also
  70.      * set. 'avformat_new_stream' can be called only if the flag
  71.      * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a
  72.      * background thread).
  73.      * @return 0 on success, < 0 on error.
  74.      *         Upon returning an error, pkt must be unreferenced by the caller.
  75.      */
  76.     int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
  77.     /**
  78.      * Close the stream. The AVFormatContext and AVStreams are not
  79.      * freed by this function
  80.      */
  81.     int (*read_close)(struct AVFormatContext *);
  82.     /**
  83.      * Seek to a given timestamp relative to the frames in
  84.      * stream component stream_index.
  85.      * @param stream_index Must not be -1.
  86.      * @param flags Selects which direction should be preferred if no exact
  87.      *              match is available.
  88.      * @return >= 0 on success (but not necessarily the new offset)
  89.      */
  90.     int (*read_seek)(struct AVFormatContext *,
  91.                      int stream_index, int64_t timestamp, int flags);
  92.     /**
  93.      * Get the next timestamp in stream[stream_index].time_base units.
  94.      * @return the timestamp or AV_NOPTS_VALUE if an error occurred
  95.      */
  96.     int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
  97.                               int64_t *pos, int64_t pos_limit);
  98.     /**
  99.      * Start/resume playing - only meaningful if using a network-based format
  100.      * (RTSP).
  101.      */
  102.     int (*read_play)(struct AVFormatContext *);
  103.     /**
  104.      * Pause playing - only meaningful if using a network-based format
  105.      * (RTSP).
  106.      */
  107.     int (*read_pause)(struct AVFormatContext *);
  108.     /**
  109.      * Seek to timestamp ts.
  110.      * Seeking will be done so that the point from which all active streams
  111.      * can be presented successfully will be closest to ts and within min/max_ts.
  112.      * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
  113.      */
  114.     int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
  115.     /**
  116.      * Returns device list with it properties.
  117.      * @see avdevice_list_devices() for more details.
  118.      */
  119.     int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
  120. } AVInputFormat;
复制代码
AVInputFormat是FFmpeg中的解复用器结构体,每种作为输入的封装格式(比方BMP、FLV、MP4、TS、H.264裸流文件等)都对应一种AVInputFormat 结构。

好比BMP这种图片的封装格式,它对应的AVInputFormat结构为:
  1. const AVInputFormat ff_image_bmp_pipe_demuxer = {
  2. .name           = "bmp_pipe",
  3. .long_name      = "piped bmp sequence",
  4. .priv_data_size = 1208,
  5. .read_probe     = bmp_probe,
  6. .read_header    = ff_img_read_header,
  7. .read_packet    = ff_img_read_packet,
  8. .priv_class     = &imagepipe_class,
  9. .flags          = 256,
  10. .raw_codec_id   = AV_CODEC_ID_BMP,
  11. };
复制代码

H.264裸流文件对应的AVInputFormat结构为:
  1. const AVInputFormat ff_h264_demuxer= {
  2. .name           = "h264",
  3. .long_name      = "raw H.264 video",
  4. .priv_data_size = 1208,
  5. .read_probe     = h264_probe,
  6. .read_header    = ff_raw_video_read_header,
  7. .read_packet    = ff_raw_read_partial_packet,
  8. .priv_class     = &ff_rawvideo_demuxer_class,
  9. .flags          = 256,
  10. .raw_codec_id   = AV_CODEC_ID_H264,
  11. };
复制代码



二、av_probe_input_format3函数的界说

av_probe_input_format3函数界说在源文件libavformat/format.c中:
  1. const AVInputFormat *av_probe_input_format3(const AVProbeData *pd,
  2.                                             int is_opened, int *score_ret)
  3. {
  4.     AVProbeData lpd = *pd;
  5.     const AVInputFormat *fmt1 = NULL;
  6.     const AVInputFormat *fmt = NULL;
  7.     int score, score_max = 0;
  8.     void *i = 0;
  9.     const static uint8_t zerobuffer[AVPROBE_PADDING_SIZE];
  10.     enum nodat {
  11.         NO_ID3,
  12.         ID3_ALMOST_GREATER_PROBE,
  13.         ID3_GREATER_PROBE,
  14.         ID3_GREATER_MAX_PROBE,
  15.     } nodat = NO_ID3;
  16.     if (!lpd.buf)
  17.         lpd.buf = (unsigned char *) zerobuffer;
  18.     if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) {
  19.         int id3len = ff_id3v2_tag_len(lpd.buf);
  20.         if (lpd.buf_size > id3len + 16) {
  21.             if (lpd.buf_size < 2LL*id3len + 16)
  22.                 nodat = ID3_ALMOST_GREATER_PROBE;
  23.             lpd.buf      += id3len;
  24.             lpd.buf_size -= id3len;
  25.         } else if (id3len >= PROBE_BUF_MAX) {
  26.             nodat = ID3_GREATER_MAX_PROBE;
  27.         } else
  28.             nodat = ID3_GREATER_PROBE;
  29.     }
  30.     while ((fmt1 = av_demuxer_iterate(&i))) {
  31.         if (fmt1->flags & AVFMT_EXPERIMENTAL)
  32.             continue;
  33.         if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2"))
  34.             continue;
  35.         score = 0;
  36.         if (fmt1->read_probe) {
  37.             score = fmt1->read_probe(&lpd);
  38.             if (score)
  39.                 av_log(NULL, AV_LOG_TRACE, "Probing %s score:%d size:%d\n", fmt1->name, score, lpd.buf_size);
  40.             if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) {
  41.                 switch (nodat) {
  42.                 case NO_ID3:
  43.                     score = FFMAX(score, 1);
  44.                     break;
  45.                 case ID3_GREATER_PROBE:
  46.                 case ID3_ALMOST_GREATER_PROBE:
  47.                     score = FFMAX(score, AVPROBE_SCORE_EXTENSION / 2 - 1);
  48.                     break;
  49.                 case ID3_GREATER_MAX_PROBE:
  50.                     score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
  51.                     break;
  52.                 }
  53.             }
  54.         } else if (fmt1->extensions) {
  55.             if (av_match_ext(lpd.filename, fmt1->extensions))
  56.                 score = AVPROBE_SCORE_EXTENSION;
  57.         }
  58.         if (av_match_name(lpd.mime_type, fmt1->mime_type)) {
  59.             if (AVPROBE_SCORE_MIME > score) {
  60.                 av_log(NULL, AV_LOG_DEBUG, "Probing %s score:%d increased to %d due to MIME type\n", fmt1->name, score, AVPROBE_SCORE_MIME);
  61.                 score = AVPROBE_SCORE_MIME;
  62.             }
  63.         }
  64.         if (score > score_max) {
  65.             score_max = score;
  66.             fmt       = fmt1;
  67.         } else if (score == score_max)
  68.             fmt = NULL;
  69.     }
  70.     if (nodat == ID3_GREATER_PROBE)
  71.         score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max);
  72.     *score_ret = score_max;
  73.     return fmt;
  74. }
复制代码



三、av_probe_input_format3函数的内部实现分析

当形参is_opened的值为1,也就是须要被推测格式的文件已经被打开时。函数av_probe_input_format3中,起首会通过语句:
  1. AVProbeData lpd = *pd;
复制代码
让lpd.buf指向“存放从该文件读取出来的二进制数据”的缓冲区,从而得到须要被推测格式的文件的二进制数据。


然后会循环实行:
  1. while ((fmt1 = av_demuxer_iterate(&i))) {
  2. //...
  3. }
复制代码


av_demuxer_iterate函数界说在libavformat/allformats.c中,作用是得到形参opaque(也就是i)对应的已被注册的解封装器,可以看到它内部获取了全局数组demuxer_list中的元素:
  1. const AVInputFormat *av_demuxer_iterate(void **opaque)
  2. {
  3.     static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1;
  4.     uintptr_t i = (uintptr_t)*opaque;
  5.     const AVInputFormat *f = NULL;
  6.     uintptr_t tmp;
  7.     if (i < size) {
  8.         f = demuxer_list[i];
  9.     } else if (tmp = atomic_load_explicit(&indev_list_intptr, memory_order_relaxed)) {
  10.         const AVInputFormat *const *indev_list = (const AVInputFormat *const *)tmp;
  11.         f = indev_list[i - size];
  12.     }
  13.     if (f)
  14.         *opaque = (void*)(i + 1);
  15.     return f;
  16. }
复制代码


全局数组demuxer_list界说在libavformat/demuxer_list.c中,数组中的每个元素都对应一种AVInputFormat结构,也就是说数组中的每个元素都对应一种输入的封装格式(BMP、FLV、MP4、TS、H.264裸流文件等):
  1. static const AVInputFormat * const demuxer_list[] = {
  2.     &ff_aa_demuxer,
  3.     &ff_aac_demuxer,
  4.     &ff_aax_demuxer,
  5.     &ff_ac3_demuxer,
  6.     &ff_ace_demuxer,
  7.     &ff_acm_demuxer,
  8.     &ff_act_demuxer,
  9.     &ff_adf_demuxer,
  10.     &ff_adp_demuxer,
  11.     &ff_ads_demuxer,
  12.     &ff_adx_demuxer,
  13.     &ff_aea_demuxer,
  14.     &ff_afc_demuxer,
  15.     &ff_aiff_demuxer,
  16.     &ff_aix_demuxer,
  17.     &ff_alp_demuxer,
  18.     &ff_amr_demuxer,
  19.     &ff_amrnb_demuxer,
  20.     &ff_amrwb_demuxer,
  21.     &ff_anm_demuxer,
  22.     &ff_apc_demuxer,
  23.     &ff_ape_demuxer,
  24.     &ff_apm_demuxer,
  25.     &ff_apng_demuxer,
  26.     &ff_aptx_demuxer,
  27.     &ff_aptx_hd_demuxer,
  28.     &ff_aqtitle_demuxer,
  29.     &ff_argo_asf_demuxer,
  30.     &ff_argo_brp_demuxer,
  31.     &ff_argo_cvg_demuxer,
  32.     &ff_asf_demuxer,
  33.     &ff_asf_o_demuxer,
  34.     &ff_ass_demuxer,
  35.     &ff_ast_demuxer,
  36.     &ff_au_demuxer,
  37.     &ff_av1_demuxer,
  38.     &ff_avi_demuxer,
  39.     &ff_avr_demuxer,
  40.     &ff_avs_demuxer,
  41.     &ff_avs2_demuxer,
  42.     &ff_avs3_demuxer,
  43.     &ff_bethsoftvid_demuxer,
  44.     &ff_bfi_demuxer,
  45.     &ff_bintext_demuxer,
  46.     &ff_bink_demuxer,
  47.     &ff_binka_demuxer,
  48.     &ff_bit_demuxer,
  49.     &ff_bitpacked_demuxer,
  50.     &ff_bmv_demuxer,
  51.     &ff_bfstm_demuxer,
  52.     &ff_brstm_demuxer,
  53.     &ff_boa_demuxer,
  54.     &ff_c93_demuxer,
  55.     &ff_caf_demuxer,
  56.     &ff_cavsvideo_demuxer,
  57.     &ff_cdg_demuxer,
  58.     &ff_cdxl_demuxer,
  59.     &ff_cine_demuxer,
  60.     &ff_codec2_demuxer,
  61.     &ff_codec2raw_demuxer,
  62.     &ff_concat_demuxer,
  63.     &ff_data_demuxer,
  64.     &ff_daud_demuxer,
  65.     &ff_dcstr_demuxer,
  66.     &ff_derf_demuxer,
  67.     &ff_dfa_demuxer,
  68.     &ff_dhav_demuxer,
  69.     &ff_dirac_demuxer,
  70.     &ff_dnxhd_demuxer,
  71.     &ff_dsf_demuxer,
  72.     &ff_dsicin_demuxer,
  73.     &ff_dss_demuxer,
  74.     &ff_dts_demuxer,
  75.     &ff_dtshd_demuxer,
  76.     &ff_dv_demuxer,
  77.     &ff_dvbsub_demuxer,
  78.     &ff_dvbtxt_demuxer,
  79.     &ff_dxa_demuxer,
  80.     &ff_ea_demuxer,
  81.     &ff_ea_cdata_demuxer,
  82.     &ff_eac3_demuxer,
  83.     &ff_epaf_demuxer,
  84.     &ff_ffmetadata_demuxer,
  85.     &ff_filmstrip_demuxer,
  86.     &ff_fits_demuxer,
  87.     &ff_flac_demuxer,
  88.     &ff_flic_demuxer,
  89.     &ff_flv_demuxer,
  90.     &ff_live_flv_demuxer,
  91.     &ff_fourxm_demuxer,
  92.     &ff_frm_demuxer,
  93.     &ff_fsb_demuxer,
  94.     &ff_fwse_demuxer,
  95.     &ff_g722_demuxer,
  96.     &ff_g723_1_demuxer,
  97.     &ff_g726_demuxer,
  98.     &ff_g726le_demuxer,
  99.     &ff_g729_demuxer,
  100.     &ff_gdv_demuxer,
  101.     &ff_genh_demuxer,
  102.     &ff_gif_demuxer,
  103.     &ff_gsm_demuxer,
  104.     &ff_gxf_demuxer,
  105.     &ff_h261_demuxer,
  106.     &ff_h263_demuxer,
  107.     &ff_h264_demuxer,
  108.     &ff_hca_demuxer,
  109.     &ff_hcom_demuxer,
  110.     &ff_hevc_demuxer,
  111.     &ff_hls_demuxer,
  112.     &ff_hnm_demuxer,
  113.     &ff_ico_demuxer,
  114.     &ff_idcin_demuxer,
  115.     &ff_idf_demuxer,
  116.     &ff_iff_demuxer,
  117.     &ff_ifv_demuxer,
  118.     &ff_ilbc_demuxer,
  119.     &ff_image2_demuxer,
  120.     &ff_image2pipe_demuxer,
  121.     &ff_image2_alias_pix_demuxer,
  122.     &ff_image2_brender_pix_demuxer,
  123.     &ff_ingenient_demuxer,
  124.     &ff_ipmovie_demuxer,
  125.     &ff_ipu_demuxer,
  126.     &ff_ircam_demuxer,
  127.     &ff_iss_demuxer,
  128.     &ff_iv8_demuxer,
  129.     &ff_ivf_demuxer,
  130.     &ff_ivr_demuxer,
  131.     &ff_jacosub_demuxer,
  132.     &ff_jv_demuxer,
  133.     &ff_kux_demuxer,
  134.     &ff_kvag_demuxer,
  135.     &ff_lmlm4_demuxer,
  136.     &ff_loas_demuxer,
  137.     &ff_luodat_demuxer,
  138.     &ff_lrc_demuxer,
  139.     &ff_lvf_demuxer,
  140.     &ff_lxf_demuxer,
  141.     &ff_m4v_demuxer,
  142.     &ff_mca_demuxer,
  143.     &ff_mcc_demuxer,
  144.     &ff_matroska_demuxer,
  145.     &ff_mgsts_demuxer,
  146.     &ff_microdvd_demuxer,
  147.     &ff_mjpeg_demuxer,
  148.     &ff_mjpeg_2000_demuxer,
  149.     &ff_mlp_demuxer,
  150.     &ff_mlv_demuxer,
  151.     &ff_mm_demuxer,
  152.     &ff_mmf_demuxer,
  153.     &ff_mods_demuxer,
  154.     &ff_moflex_demuxer,
  155.     &ff_mov_demuxer,
  156.     &ff_mp3_demuxer,
  157.     &ff_mpc_demuxer,
  158.     &ff_mpc8_demuxer,
  159.     &ff_mpegps_demuxer,
  160.     &ff_mpegts_demuxer,
  161.     &ff_mpegtsraw_demuxer,
  162.     &ff_mpegvideo_demuxer,
  163.     &ff_mpjpeg_demuxer,
  164.     &ff_mpl2_demuxer,
  165.     &ff_mpsub_demuxer,
  166.     &ff_msf_demuxer,
  167.     &ff_msnwc_tcp_demuxer,
  168.     &ff_msp_demuxer,
  169.     &ff_mtaf_demuxer,
  170.     &ff_mtv_demuxer,
  171.     &ff_musx_demuxer,
  172.     &ff_mv_demuxer,
  173.     &ff_mvi_demuxer,
  174.     &ff_mxf_demuxer,
  175.     &ff_mxg_demuxer,
  176.     &ff_nc_demuxer,
  177.     &ff_nistsphere_demuxer,
  178.     &ff_nsp_demuxer,
  179.     &ff_nsv_demuxer,
  180.     &ff_nut_demuxer,
  181.     &ff_nuv_demuxer,
  182.     &ff_obu_demuxer,
  183.     &ff_ogg_demuxer,
  184.     &ff_oma_demuxer,
  185.     &ff_paf_demuxer,
  186.     &ff_pcm_alaw_demuxer,
  187.     &ff_pcm_mulaw_demuxer,
  188.     &ff_pcm_vidc_demuxer,
  189.     &ff_pcm_f64be_demuxer,
  190.     &ff_pcm_f64le_demuxer,
  191.     &ff_pcm_f32be_demuxer,
  192.     &ff_pcm_f32le_demuxer,
  193.     &ff_pcm_s32be_demuxer,
  194.     &ff_pcm_s32le_demuxer,
  195.     &ff_pcm_s24be_demuxer,
  196.     &ff_pcm_s24le_demuxer,
  197.     &ff_pcm_s16be_demuxer,
  198.     &ff_pcm_s16le_demuxer,
  199.     &ff_pcm_s8_demuxer,
  200.     &ff_pcm_u32be_demuxer,
  201.     &ff_pcm_u32le_demuxer,
  202.     &ff_pcm_u24be_demuxer,
  203.     &ff_pcm_u24le_demuxer,
  204.     &ff_pcm_u16be_demuxer,
  205.     &ff_pcm_u16le_demuxer,
  206.     &ff_pcm_u8_demuxer,
  207.     &ff_pjs_demuxer,
  208.     &ff_pmp_demuxer,
  209.     &ff_pp_bnk_demuxer,
  210.     &ff_pva_demuxer,
  211.     &ff_pvf_demuxer,
  212.     &ff_qcp_demuxer,
  213.     &ff_r3d_demuxer,
  214.     &ff_rawvideo_demuxer,
  215.     &ff_realtext_demuxer,
  216.     &ff_redspark_demuxer,
  217.     &ff_rl2_demuxer,
  218.     &ff_rm_demuxer,
  219.     &ff_roq_demuxer,
  220.     &ff_rpl_demuxer,
  221.     &ff_rsd_demuxer,
  222.     &ff_rso_demuxer,
  223.     &ff_rtp_demuxer,
  224.     &ff_rtsp_demuxer,
  225.     &ff_s337m_demuxer,
  226.     &ff_sami_demuxer,
  227.     &ff_sap_demuxer,
  228.     &ff_sbc_demuxer,
  229.     &ff_sbg_demuxer,
  230.     &ff_scc_demuxer,
  231.     &ff_scd_demuxer,
  232.     &ff_sdp_demuxer,
  233.     &ff_sdr2_demuxer,
  234.     &ff_sds_demuxer,
  235.     &ff_sdx_demuxer,
  236.     &ff_segafilm_demuxer,
  237.     &ff_ser_demuxer,
  238.     &ff_sga_demuxer,
  239.     &ff_shorten_demuxer,
  240.     &ff_siff_demuxer,
  241.     &ff_simbiosis_imx_demuxer,
  242.     &ff_sln_demuxer,
  243.     &ff_smacker_demuxer,
  244.     &ff_smjpeg_demuxer,
  245.     &ff_smush_demuxer,
  246.     &ff_sol_demuxer,
  247.     &ff_sox_demuxer,
  248.     &ff_spdif_demuxer,
  249.     &ff_srt_demuxer,
  250.     &ff_str_demuxer,
  251.     &ff_stl_demuxer,
  252.     &ff_subviewer1_demuxer,
  253.     &ff_subviewer_demuxer,
  254.     &ff_sup_demuxer,
  255.     &ff_svag_demuxer,
  256.     &ff_svs_demuxer,
  257.     &ff_swf_demuxer,
  258.     &ff_tak_demuxer,
  259.     &ff_tedcaptions_demuxer,
  260.     &ff_thp_demuxer,
  261.     &ff_threedostr_demuxer,
  262.     &ff_tiertexseq_demuxer,
  263.     &ff_tmv_demuxer,
  264.     &ff_truehd_demuxer,
  265.     &ff_tta_demuxer,
  266.     &ff_txd_demuxer,
  267.     &ff_tty_demuxer,
  268.     &ff_ty_demuxer,
  269.     &ff_v210_demuxer,
  270.     &ff_v210x_demuxer,
  271.     &ff_vag_demuxer,
  272.     &ff_vc1_demuxer,
  273.     &ff_vc1t_demuxer,
  274.     &ff_vividas_demuxer,
  275.     &ff_vivo_demuxer,
  276.     &ff_vmd_demuxer,
  277.     &ff_vobsub_demuxer,
  278.     &ff_voc_demuxer,
  279.     &ff_vpk_demuxer,
  280.     &ff_vplayer_demuxer,
  281.     &ff_vqf_demuxer,
  282.     &ff_w64_demuxer,
  283.     &ff_wav_demuxer,
  284.     &ff_wc3_demuxer,
  285.     &ff_webm_dash_manifest_demuxer,
  286.     &ff_webvtt_demuxer,
  287.     &ff_wsaud_demuxer,
  288.     &ff_wsd_demuxer,
  289.     &ff_wsvqa_demuxer,
  290.     &ff_wtv_demuxer,
  291.     &ff_wve_demuxer,
  292.     &ff_wv_demuxer,
  293.     &ff_xa_demuxer,
  294.     &ff_xbin_demuxer,
  295.     &ff_xmv_demuxer,
  296.     &ff_xvag_demuxer,
  297.     &ff_xwma_demuxer,
  298.     &ff_yop_demuxer,
  299.     &ff_yuv4mpegpipe_demuxer,
  300.     &ff_image_bmp_pipe_demuxer,
  301.     &ff_image_cri_pipe_demuxer,
  302.     &ff_image_dds_pipe_demuxer,
  303.     &ff_image_dpx_pipe_demuxer,
  304.     &ff_image_exr_pipe_demuxer,
  305.     &ff_image_gem_pipe_demuxer,
  306.     &ff_image_gif_pipe_demuxer,
  307.     &ff_image_j2k_pipe_demuxer,
  308.     &ff_image_jpeg_pipe_demuxer,
  309.     &ff_image_jpegls_pipe_demuxer,
  310.     &ff_image_pam_pipe_demuxer,
  311.     &ff_image_pbm_pipe_demuxer,
  312.     &ff_image_pcx_pipe_demuxer,
  313.     &ff_image_pgmyuv_pipe_demuxer,
  314.     &ff_image_pgm_pipe_demuxer,
  315.     &ff_image_pgx_pipe_demuxer,
  316.     &ff_image_photocd_pipe_demuxer,
  317.     &ff_image_pictor_pipe_demuxer,
  318.     &ff_image_png_pipe_demuxer,
  319.     &ff_image_ppm_pipe_demuxer,
  320.     &ff_image_psd_pipe_demuxer,
  321.     &ff_image_qdraw_pipe_demuxer,
  322.     &ff_image_sgi_pipe_demuxer,
  323.     &ff_image_svg_pipe_demuxer,
  324.     &ff_image_sunrast_pipe_demuxer,
  325.     &ff_image_tiff_pipe_demuxer,
  326.     &ff_image_webp_pipe_demuxer,
  327.     &ff_image_xbm_pipe_demuxer,
  328.     &ff_image_xpm_pipe_demuxer,
  329.     &ff_image_xwd_pipe_demuxer,
  330.     NULL };
复制代码


以是下面语句现实上是循环得到全局数组demuxer_list中的下标为i的元素,也就是得到demuxer_list对应的AVInputFormat结构。实行该语句后fmt1指向i对应的AVInputFormat结构,i的值会加1。通过该语句可以把FFmpeg中全部被注册的文件格式都遍历一遍:
  1. while ((fmt1 = av_demuxer_iterate(&i))) {
  2. //...
  3. }
复制代码


在上述循环中通过下面语句实行差异文件格式对应的分析函数,得到分值。read_probe是函数指针,实行fmt1->read_probe语句会调用差异文件格式对应的分析函数。好比对于BMP图片,会实行bmp_probe函数,对于H.264裸流文件,会实行h264_probe函数。实行完后会得到分值,表现跟该文件格式的匹配水平:
  1. score = fmt1->read_probe(&lpd);
复制代码


循环分析全部格式的文件的过程中,不绝将最高分存贮到变量score_max中,让指针fmt指向最高分对应的AVInputFormat结构。从而在实行完全部差异文件格式对应的分析函数后,可以得到最匹配的文件格式:
  1. if (score > score_max) {
  2.             score_max = score;
  3.             fmt       = fmt1;
  4.         } else if (score == score_max)
  5.             fmt = NULL;
复制代码



四、av_probe_input_format3函数的调用堆栈

av_probe_input_format3函数的调用堆栈为:
int avformat_open_input(AVFormatContext **ps, const char *filename,const AVInputFormat *fmt, AVDictionary **options) ->
static int init_input(AVFormatContext *s, const char *filename,AVDictionary **options) ->
int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt,const char *filename, void *logctx,unsigned int offset, unsigned int max_probe_size) ->
const AVInputFormat *av_probe_input_format2(const AVProbeData *pd,int is_opened, int *score_max) ->
const AVInputFormat *av_probe_input_format3(const AVProbeData *pd,int is_opened, int *score_ret)


以是avformat_open_input函数内部调用了init_input函数,init_input函数内部又调用了av_probe_input_buffer2函数,av_probe_input_buffer2函数内部调用av_probe_input_format2函数,av_probe_input_format2函数内部调用av_probe_input_format3函数。


由于:
  1. static int init_input(AVFormatContext *s, const char *filename,
  2.                       AVDictionary **options)
  3. {
  4. //...
  5.     return av_probe_input_buffer2(s->pb, &s->iformat, filename,
  6.                                   s, 0, s->format_probesize);
  7. }
复制代码

  1. int av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt,
  2.                            const char *filename, void *logctx,
  3.                            unsigned int offset, unsigned int max_probe_size)
  4. {
  5. //...
  6.         *fmt = av_probe_input_format2(&pd, 1, &score);
  7. //...
  8. }
复制代码

  1. const AVInputFormat *av_probe_input_format2(const AVProbeData *pd,
  2.                                             int is_opened, int *score_max)
  3. {
  4. //...
  5.     const AVInputFormat *fmt = av_probe_input_format3(pd, is_opened, &score_ret);
  6. //...
  7.     return fmt;
  8. }
复制代码

以是调用完av_probe_input_format3函数后,s->iformat(AVFormatContext的iformat成员变量)会得到最匹配该文件格式的AVInputFormat结构体指针。



五、总结

av_probe_input_format3函数是FFmpeg中实现容器格式检测的函数,其内部通过循环while ((fmt1 = av_demuxer_iterate(&i))) 拿到全部容器格式对应的AVInputFormat结构,然后通过score = fmt1->read_probe(&lpd)语句实行差异容器格式对应的分析函数,根据是否能被分析,以及匹配水平,来判断出这是哪种容器格式。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表