【问题标题】:FFMPEG: Working of parser of a video decoderFFMPEG:视频解码器解析器的工作
【发布时间】:2013-12-19 01:51:35
【问题描述】:

我正在经历FFMPEG多媒体框架中H.263视频解码器解析器的工作。

我所知道的:

每个视频解码器都需要一个解析器从给定的输入流中获取帧,一旦获得与帧相关的数据,就会将其发送到解码器进行解码处理。

每个编解码器的解析器都需要定义一个AVCodecParser 类型的结构。这个结构有一个函数指针:

.parser_parse -> 指向处理解析功能的函数

.parser_close -> 指向一个执行缓冲区释放的函数。

以视频解码器H.264为例,其解析器功能如下图:

static int h263_parse(AVCodecParserContext *s,
                           AVCodecContext *avctx,
                           const uint8_t **poutbuf, int *poutbuf_size,
                           const uint8_t *buf, int buf_size)
{
    ParseContext *pc = s->priv_data;
    int next;

    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
        next = buf_size;
    } else {
        next= ff_h263_find_frame_end(pc, buf, buf_size);

        if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
            *poutbuf = NULL;
            *poutbuf_size = 0;
            return buf_size;
        }
    }

    *poutbuf = buf;
    *poutbuf_size = buf_size;
    return next;
}

谁能解释一下,上面函数的参数。

据我说:

poutbuf -> 是指向解析后的帧数据的指针。

poutbuf_size -> 包含数据的大小。

我的上述假设是否正确?哪个参数保存输入缓冲区数据?上面的解析函数返回什么?任何引用该帖子的人也将简要解释上述代码。任何与此相关的信息都会非常有帮助。

【问题讨论】:

    标签: c parsing video ffmpeg codec


    【解决方案1】:

    首先免责声明:自从我上次研究这些东西以来已经有一段时间了......

    我上面的假设对吗?

    是的,poutbuf 是指向帧数据(开始)的指针,poutbuf_size 包含帧数据的大小。

    哪个参数保存输入缓冲区数据?

    buf,大小为buf_size。请注意,解析器不一定会复制数据,因此bufpoutbuf 可能指向相同的分配。 (例如,跳过解析时)。 只是说,如果你想弄乱输出缓冲区,这也可能会修改输入缓冲区并产生意想不到的副作用。

    输出缓冲区要么指向与输入缓冲区相同的分配,要么指向解析器上下文保存的内部缓冲区。因此,输出缓冲区将作为释放输入缓冲区的结果被释放,或者在解析器上下文重新分配其缓冲区或被销毁时释放。

    上面的解析函数返回什么?

    函数有三个输出:

    • 实际返回值。此值指定下一次调用输入的相对偏移量。
    • poutbuf。实际的帧数据,如果有的话。如果跳过解析,则输入缓冲区。
    • poutbuf_size。实际帧数据的大小(如果有),或输入缓冲区大小(如果跳过解析)。

    一个不太明显的事情是这个解析器函数将重用指针变量bufbuf_size,但这些更改不会离开函数(按值传递等等)。

    对于上述代码的简要说明也将是指该帖子的任何人。

    • PARSER_FLAG_COMPLETE_FRAMES 这些天基本上意味着“不需要实际解析”(有关如何设置,请参阅 libavformat/utils.c)。因此,如果指定了标志,只需设置 `output = input 并返回完整的缓冲区大小作为下一个偏移量。
    • 如果未设置该标志,解析器将尝试查找帧尾 (ff_h263_find_frame_end(pc, buf, buf_size))
    • 接下来,它会将数据缓冲到找到的一端,如果没有找到端,则将整个数据缓冲(`ff_combine_frame')。

      • 如果帧仍然不完整(未找到帧结尾),该函数会将输出缓冲区和大小设置为 0,表示此调用未产生完整帧,并返回下一个偏移量。数据仍在缓冲中,因此可以在后续调用中完成该帧。
      • 如果帧无法组合,例如由于内存不足,ff_combine_frame 将丢弃缓冲的数据(和帧)并返回空缓冲区和buf_size 下一个偏移量。
    • 此时我们要么有一个完整的帧(或完全跳过解析),所以将输出缓冲区设置为帧缓冲区(和大小)并返回计算的偏移量(要么是帧结束,要么是整个未解析时的缓冲区)。

    那些*_parse 例程看起来几乎都一​​样,并且工作相同的 IIRC。

    【讨论】:

      猜你喜欢
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      • 2012-08-03
      • 2016-06-16
      相关资源
      最近更新 更多