我正在了解 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
-> 包含数据的大小。
我的上述假设正确吗?哪个参数保存输入缓冲区数据?上面的解析函数返回什么?任何引用该帖子的人都会对上述代码进行简要解释。任何有关相同内容的信息都会非常有帮助。
最佳答案
首先免责声明:自从我上次研究这个东西以来已经有一段时间了......
Are my above assumptions right?
是的,poutbuf
是指向帧数据(开始)的指针,poutbuf_size
包含帧数据的大小。
Which parameter holds the input buffer data?
buf
,大小为 buf_size
。请注意,解析器不一定会复制数据,因此 buf 和 poutbuf 可能指向相同的分配。 (例如,当跳过解析时)。
只是说,如果您想弄乱输出缓冲区,这也可能会修改输入缓冲区并产生意想不到的副作用。
输出缓冲区将指向与输入缓冲区相同的分配,或者指向解析器上下文保存的内部缓冲区。因此,输出缓冲区将因释放输入缓冲区而被释放,或者当解析器上下文重新分配其缓冲区或被销毁时被释放。
And what is the above parse function returning?
该函数有三个输出:
- 实际返回值。该值指定下一次调用的输入的相对偏移量。
poutbuf
。实际的帧数据(如果有)。或者如果跳过解析则输入缓冲区。poutbuf_size
。实际帧数据的大小(如果有),或输入缓冲区大小(如果跳过解析)。
一个不太明显的事情是,这个解析器函数将重用指针变量 buf
和 buf_size
,但这些更改不会离开函数(按值传递)等等)。
Also a brief explanation for the above code will be anyone who is referring to the post.
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 上。
关于c - FFMPEG:视频解码器解析器的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20343821/