FFMPEG:处理视频解码器的解析器

时间:2013-12-03 05:49:30

标签: c parsing video ffmpeg codec

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

我所知道的:

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

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

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

.parser_close -> points to a function that performs buffer deallocation.

以视频解码器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-> is a pointer that points to parsed frame data.

poutbuf_size-> contains the size of the data.

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

提前致谢。

-Regards

1 个答案:

答案 0 :(得分:3)

首先是免责声明:自从我上次查看这些内容以来已经有一段时间......

  

我的上述假设是否正确?

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

  

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

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

输出缓冲区将指向与输入缓冲区相同的分配,或指向解析器上下文所包含的内部缓冲区。因此,输出缓冲区将由于释放输入缓冲区而释放,或者在解析器上下文重新分配其缓冲区或被销毁时释放。

  

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

该功能有三个输出:

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

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

  

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

  • 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例程几乎看起来都一样,并且工作方式相同。