ffmpeg分析系列之六(再次探测输入的格式)

ffmpeg分析系列之六(再次探测输入的格式)  


void *logctx= ap && ap->prealloced_context ? *ic_ptr : NULL; // 因为 ap == NULL, 所以 logctx 也 == NULL.

    if (!fmt && (err = ff_probe_input_buffer(&pb, &fmt, filename, logctx, 0,
        logctx ? (*ic_ptr)->probesize : 0)) < 0) {
        goto fail;
    }
    // fmt == NULL 时才执行 ff_probe_input_buffer 函数, 因为 fmt 就等于NULL, 成立.


ff_probe_input_buffer函数的原型:

int ff_probe_input_buffer(ByteIOContext **pb, // 字节IO上下文, 执行url_fopen得到的
                          AVInputFormat **fmt, // 输出参数: 输入的格式
                          const char *filename, // 文件名
                          void *logctx, // NULL
                          unsigned int offset, // 0
                          unsigned int max_probe_size
 // 0


关键的代码片断:

        /* 读待探测的数据 */
        buf = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE);
        if ((ret = get_buffer(*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];

        memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE);

        /* 猜测文件格式 */
        *fmt = av_probe_input_format2(&pd, 1, &score);


get_buffer函数, 有两处比较关键:

int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
{

        /* 省略部分代码 */
        /* 读包 */
        if(s->read_packet)
           len = s->read_packet(s->opaque, buf, size);


        /* 省略部分代码 */

        /* 填充缓冲 */

        fill_buffer(s);

        /* 省略部分代码 */

}


fill_buffer函数 , 有一处比较关键:

static void fill_buffer(ByteIOContext *s)
{
        /* 省略部分代码 */
        /* 读包 */
        if(s->read_packet)
           len = s->read_packet(s->opaque, dst, len);

        /* 省略部分代码 */
}


好了, 到第二次探测输入格式的地方了:

*fmt = av_probe_input_format2(&pd, 1, &score);


进入av_probe_input_format2函数:

AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
{
    AVInputFormat *fmt1, *fmt;
    int score;

    fmt = NULL;
    for(fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) {
        if (!is_opened == !(fmt1->flags & AVFMT_NOFILE))
            continue;

/* 这次 is_opened == 1, fmt1->flags设置AVFMT_NOFILE标志才时成立 */

/* 由于 h264_demuxer.flags == AVFMT_GENERIC_INDEX, 所以上面不成立, 继续执行 */
        score = 0;
        if (fmt1->read_probe) {
            score = fmt1->read_probe(pd)/* 调用h264_demuxer.h264_probe */
        } else if (fmt1->extensions) {
            if (av_match_ext(pd->filename, fmt1->extensions)) /* 文件名和格式扩展名的匹配 */

/* h264_demuxer.extensions = "h26l,h264,264" */
                score = 50;
            }
        }
        if (score > *score_max) {
            *score_max = score;
            fmt = fmt1;
        }else if (score == *score_max)
            fmt = NULL;
    }
    return fmt;
}


av_match_ext函数:

int av_match_ext(const char *filename, const char *extensions)
{
    const char *ext, *p;
    char ext1[32], *q;

    if(!filename)
        return 0;

    ext = strrchr(filename, '.');
    if (ext) {
        ext++;
        p = extensions;
        for(;;) {
            q = ext1;
            while (*!= '\0' && *!= ',' && q-ext1<sizeof(ext1)-1)
                *q++ = *p++;
            *= '\0';
            if (!strcasecmp(ext1, ext))
                return 1;
            if (*== '\0')
                break;
            p++;
        }
    }
    return 0;
}


总算探测到输入格式了.

你可能感兴趣的:(ffmpeg分析系列之六(再次探测输入的格式))