我指的是这个源代码。这里提供的代码片段来自代码中的第114-138行。这是使用ffmpeg库。谁能解释一下为什么程序中需要下面的代码?
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
在某种意义上,我理解下面的函数是将目标帧关联到缓冲区。但是必要性是什么呢?
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
PS:我试着删除缓冲区并编译程序。它被编译了。但是它显示了以下运行时错误。
[swscaler @ 0xa06d0a0]错误的DST图像指针
分段故障(堆芯转储)
我认为让你困惑的是AVFrame似乎有两个分配。
第一个是用avcodec_alloc_frame()
完成的,它为通用帧及其元数据分配空间。此时,保存帧所需的内存仍然未知。
然后从另一个源填充该帧,然后通过传递width
, height
和颜色深度来指定需要多少内存:
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
此时,框架和它的内容是两个独立的对象(AVFrame和它的缓冲区)。您将它们与以下代码放在一起,这实际上根本不是转换:
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
上面的代码所做的是"告诉"pFrameRGB
:"你是一个RGB-24帧,这么宽,这么高,你需要的内存在'buffer'"。
然后,只有在那时,你可以做任何你想要的pFrameRGB
。否则,如果你试图在没有画布的框架上作画,油漆就会溅下来——你会得到一个核心转储。
一旦你有了框架(AVFrame)和画布(缓冲区),你可以使用它:
// Read frames and save first five frames to disk
i=0;
while(av_read_frame(pFormatCtx, &packet)>=0) {
// Is this a packet from the video stream?
if(packet.stream_index==videoStream) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
&packet);
以上代码提取视频帧并解码为pFrame
(原生格式)。在这个阶段,我们可以将pFrame
保存到磁盘。如果我们不需要buffer
,那么我们就可以不使用pFrameRGB
。
我们使用sws_scale()
将帧转换为RGB-24。
要将一个帧转换为另一种格式,我们将源帧复制到不同的目标帧。这既是因为目标帧可能比源帧所能容纳的帧大,也是因为一些转换算法需要在未转换的源的更大区域上操作,因此就地转换源会很尴尬。此外,源帧由库处理,写入可能不安全。
更新(评论)
pFrame/pFrameRGB的data[]
最初指向: ,没有。它们是NULL,这就是为什么使用未初始化的AVframe会导致core dump的原因。您可以使用avpicture_fill
(适合空缓冲区,加上图像格式和大小信息)或解码函数之一(执行相同操作)初始化它们(以及linesize[]
等)。
为什么pFrame不需要内存分配:好问题。答案在所用函数的原型和布局中,其中picture参数是这样描述的:
存储解码后视频帧的AVFrame。使用avcodec_alloc_frame获取AVFrame, 编解码器将分配内存查看实际的位图。对于默认的get/release_buffer(),解码器释放/重用位图,因为它认为合适。与覆盖get/release_buffer()(需要CODEC_CAP_DR1)用户决定进入什么缓冲区解码器解码,一旦解码器解码,解码器就告诉用户不再需要数据,用户应用此时可以释放/重用/保留它认为合适的内存
ffmpeg在framebuffer中以特定的顺序存储帧的像素数据。存储取决于图片格式(YUV, RGB,)。
avpicture_fill() =>该函数获取原始缓冲区并设置AVPicture结构的各种指针。
ffmpeg或类似的库不会进行就地缓冲区转换。首先,它是关于不丢失原始数据和处理不同缓冲区的速度。其次,如果要进行大量转换,可以事先分配所需的缓冲区。