下面来看当输入的不是文件而是数据流时,系统是如何获取输入数据格式的,如下代码所示,系统调用av_probe_input_format函数去定位输入流格式
fmt = av_probe_input_format(pd, 0);
而av_probe_input_format的函数调用如下所示

AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){
    int score=0;
    return av_probe_input_format2(pd, is_opened, &score);
}

score的权值设置为零,然后调用av_probe_input_format2

static AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
{
    AVInputFormat *fmt1, *fmt;
    int score;
    fmt = NULL;
    /*first_iformat是指向输入视频文件格式的指针,还记得ffmpeg.c中的main函数的开头有连续三个函数注册格式,编解码,协议等*/
    for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) {//扫描整个ffmpeg可识别的输入数据格式
        if (!is_opened == !(fmt1->flags & AVFMT_NOFILE))
//如果is_open没有打开,而且和当前查找的输入格式的标记应该属于AVFMT_NOFILE类型的,则继续和下一个音视频格式相比较。
           continue;
         //注意了这边用了一个很巧妙的办法来猜测文件的格式
         /*首先score_max是一个最大的权值,系统一般设为零,此时很多人会感觉很奇怪,其实这边用了一个边界,当你比一个边界值还大,
说明该格式更加符合,因此把最大边界值设为当前的格式和边界值,然后继续查找直到格式查找结束,一般来说按照扩展名找,输入格式链表中是不可能出现有两种一样的扩展名的,如果最后发现有两种扩展名可匹配,则score和*score_max相同,则对格式置空,相当于不可匹配*/
        score = 0;
        if (fmt1->read_probe) {
            score = fmt1->read_probe(pd);//读取查找文件格式的头数据
        } else if (fmt1->extensions) {//查找的文件格式中是否存在扩展名
            if (match_ext(pd->filename, fmt1->extensions)) {/*比较扩展名*/
                score = 50;//如果扩展名吻合,加权50
            }
        }
        if (score > *score_max) {//如果score大于*score_max,那么找到了,然后把score_max设为score,并且格式赋值给fmt
            *score_max = score;
            fmt = fmt1;
        }else if (score == *score_max)
            fmt = NULL;
    }
    return fmt;//查找结束,返回相应的格式
}

说到这里,来看看AVInputFormat数据结构

typedef struct AVOutputFormat {

    const char *name;

    /**

     * Descriptive name for the format, meant to be more human-readable

     * than \p name. You \e should use the NULL_IF_CONFIG_SMALL() macro

     * to define it.

     */

    const char *long_name;

    const char *mime_type;

    const char *extensions; /**< comma-separated filename extensions */

    /** size of private data so that it can be allocated in the wrapper */

    int priv_data_size;

    /* output support */

    enum CodecID audio_codec; /**< default audio codec */

    enum CodecID video_codec; /**< default video codec */

    int (*write_header)(struct AVFormatContext *);

    int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);

    int (*write_trailer)(struct AVFormatContext *);

    /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */

    int flags;

    /** Currently only used to set pixel format if not YUV420P. */

    int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *);

    int (*interleave_packet)(struct AVFormatContext *, AVPacket *out,

                             AVPacket *in, int flush);


    /**

     * List of supported codec_id-codec_tag pairs, ordered by "better

     * choice first". The arrays are all terminated by CODEC_ID_NONE.

     */

    const struct AVCodecTag * const *codec_tag;


    enum CodecID subtitle_codec; /**< default subtitle codec */


    const AVMetadataConv *metadata_conv;


    /* private fields */

    struct AVOutputFormat *next;

} AVOutputFormat;


typedef struct AVInputFormat {

    const char *name;

    /**

     * Descriptive name for the format, meant to be more human-readable

     * than \p name. You \e should use the NULL_IF_CONFIG_SMALL() macro

     * to define it.

     */

    const char *long_name;

    /** Size of private data so that it can be allocated in the wrapper. */

    int priv_data_size;

    /**

     * Tell if a given file has a chance of being parsed as this format.

     * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes

     * big so you do not have to check for that unless you need more.

     */

    int (*read_probe)(AVProbeData *);

    /** Read the format header and initialize the AVFormatContext

       structure. Return 0 if OK. 'ap' if non-NULL contains

       additional parameters. Only used in raw format right

       now. 'av_new_stream' should be called to create new streams.  */

    int (*read_header)(struct AVFormatContext *,

                       AVFormatParameters *ap);

    /** Read one packet and put it in 'pkt'. pts and flags are also

       set. 'av_new_stream' can be called only if the flag

       AVFMTCTX_NOHEADER is used.

       @return 0 on success, < 0 on error.

               When returning an error, pkt must not have been allocated

               or must be freed before returning */

    int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);

    /** Close the stream. The AVFormatContext and AVStreams are not

       freed by this function */

    int (*read_close)(struct AVFormatContext *);


#if LIBAVFORMAT_VERSION_MAJOR < 53

    /**

     * Seek to a given timestamp relative to the frames in

     * stream component stream_index.

     * @param stream_index Must not be -1.

     * @param flags Selects which direction should be preferred if no exact

     *              match is available.

     * @return >= 0 on success (but not necessarily the new offset)

     */

    int (*read_seek)(struct AVFormatContext *,

                     int stream_index, int64_t timestamp, int flags);

#endif

    /**

     * Gets the next timestamp in stream[stream_index].time_base units.

     * @return the timestamp or AV_NOPTS_VALUE if an error occurred

     */

    int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,

                              int64_t *pos, int64_t pos_limit);

    /** Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER. */

    int flags;

    /** If extensions are defined, then no probe is done. You should

       usually not use extension format guessing because it is not

       reliable enough */

    const char *extensions;

    /** General purpose read-only value that the format can use. */

    int value;


    /** Start/resume playing - only meaningful if using a network-based format

       (RTSP). */

    int (*read_play)(struct AVFormatContext *);


    /** Pause playing - only meaningful if using a network-based format

       (RTSP). */

    int (*read_pause)(struct AVFormatContext *);


    const struct AVCodecTag * const *codec_tag;


    /**

     * Seek to timestamp ts.

     * Seeking will be done so that the point from which all active streams

     * can be presented successfully will be closest to ts and within min/max_ts.

     * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.

     */

    int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);


    const AVMetadataConv *metadata_conv;


    /* private fields */

    struct AVInputFormat *next;

} AVInputFormat;

posted on 2010-03-29 23:20 seedshopezhong 阅读(2309) 评论(0)  编辑 收藏 引用 所属分类: ffmpeg study
只有注册用户登录后才能发表评论。