FFMPEG:在解码视频时,是否可以将结果生成到用户提供的缓冲区?
FFMPEG: While decoding video, is possible to generate result to user's provided buffer?
在ffmpeg解码视频场景中,H264例如,通常我们分配一个AVFrame
并对压缩数据进行解码,然后从AVFrame
的成员data
和linesize
获得结果。如下代码:
// input setting: data and size are a H264 data.
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = const_cast<uint8_t*>(data);
avpkt.size = size;
// decode video: H264 ---> YUV420
AVFrame *picture = avcodec_alloc_frame();
int len = avcodec_decode_video2(context, picture, &got_picture, &avpkt);
我们可以使用结果来执行其他任务,例如,使用DirectX9进行渲染。也就是说,准备缓冲区(DirectX9纹理),并从解码结果中复制。
D3DLOCKED_RECT lrY;
D3DLOCKED_RECT lrU;
D3DLOCKED_RECT lrV;
textureY->LockRect(0, &lrY, NULL, 0);
textureU->LockRect(0, &lrU, NULL, 0);
textureV->LockRect(0, &lrV, NULL, 0);
// copy YUV420: picture->data ---> lr.pBits.
my_copy_image_function(picture->data[0], picture->linesize[0], lrY.pBits, lrY.Pitch, width, height);
my_copy_image_function(picture->data[1], picture->linesize[1], lrU.pBits, lrU.Pitch, width / 2, height / 2);
my_copy_image_function(picture->data[2], picture->linesize[2], lrV.pBits, lrV.Pitch, width / 2, height / 2);
该过程被认为发生了2次复制(将结果ffmpeg复制到picture->data,然后将picture->data复制到DirectX9-Texture)。
我的问题是:是否可以将流程改进为仅1个副本?另一方面,我们是否可以为ffmpeg提供缓冲区(pBits
,DirectX9纹理的缓冲区),并将函数结果解码到DirectX9质地的缓冲区,而不是AVFrame
的缓冲区?
我找到了出路。
AVCodecContext
有一个公共成员,get_buffer2,它是一个回调函数。在调用avcodec_decode_video2
时,会调用这个回调函数,这个回调函数负责将缓冲区和一些信息委托给AVFrame
,然后avcodec_decode_video2
将结果生成给AVFrame
的缓冲区。
回调函数get_buffer2默认设置为avcodec_default_get_buffer2
。但是,我们可以将其作为我们的特权函数来覆盖。例如:
void our_buffer_default_free(void *opaque, uint8_t *data)
{
// empty
}
int our_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
{
assert(c->codec_type == AVMEDIA_TYPE_VIDEO);
pic->data[0] = lrY.pBits;
pic->data[1] = lrU.pBits;
pic->data[2] = lrV.pBits;
picture->linesize[0] = lrY.Pitch;
picture->linesize[1] = lrU.Pitch;
picture->linesize[2] = lrV.Pitch;
pic->buf[0] = av_buffer_create(pic->data[0], pic->linesize[0] * pic->height, our_buffer_default_free, NULL, 0);
pic->buf[1] = av_buffer_create(pic->data[1], pic->linesize[1] * pic->height / 2, our_buffer_default_free, NULL, 0);
pic->buf[2] = av_buffer_create(pic->data[2], pic->linesize[2] * pic->height / 2, our_buffer_default_free, NULL, 0);
return 0;
}
在解码之前,我们覆盖回调函数:
context->get_buffer2 = our_get_buffer;
然后avcodec_decode_video2
将生成结果到我们提供的缓冲区。
顺便说一句,对于那些经常在类中实现这些过程的C++程序,我们可以先记录这个指针:
context->opaque = this;
并将重写的回调函数定义为静态成员:
static int myclass::my_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags)
{
auto this_pointer = static_cast<decode_context*>(c->opaque);
return this_pointer->my_get_buffer_real(c, pic, flags);
}
int myclass::my_get_buffer_real(struct AVCodecContext *c, AVFrame *pic, int flags)
{
// ditto with above our_get_buffer.
// ...
}
相关文章:
- C++字符*缓冲区的大小
- C++如何通过用户输入删除列表元素
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 如何使用用户输入在C++中正确填充2D数组
- C++MySQL C api用户输入行
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- 使用用户定义函数的字符串反转
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 用户定义函数中的指针和输入
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 如何只允许用户输入正整数
- Xaudio2在更改缓冲区或循环时弹出声音
- C++如何计算用户输入的数字中的偶数位数
- 如果用户输入两个或多个由空格分隔的字符串C++如何防止缓冲区溢出?
- FFMPEG:在解码视频时,是否可以将结果生成到用户提供的缓冲区?
- 为什么当我们从用户那里获得输入时我们需要一个缓冲区
- 清除c / c++中的用户输入缓冲区
- 用户空间缓冲区和内存映射文件之间的 DMA