5

我指的是这个源代码。此处提供的代码片段来自代码中的第 (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 图像指针
分段错误(核心转储)

4

3 回答 3

28

我认为让您感到困惑的是,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 帧,这么宽,这么高,你需要的内存在‘缓冲区’中”。

然后,只有这样,您才能随心所欲地使用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().

要将帧转换为另一种格式,我们将源复制到不同的目标。这既是因为目标帧可能比源帧所能容纳的更大,而且因为某些转换算法需要在未转换的源的更大区域上进行操作,因此就地变形源会很尴尬。此外,源框架由库处理,并且可能无法安全写入。

更新(评论)

data[]pFrame/pFrameRGB 指向什么最初,什么都没有。它们为 NULL,这就是为什么使用未初始化的 AVframe 会导致核心转储。linesize[]您使用avpicture_fill(适合空缓冲区,加上图像格式和大小信息)或解码函数之一(执行相同操作)初始化它们(等)。

为什么 pFrame 不需要内存分配:好问题。答案在 used 函数的原型和布局中,其中图片参数是这样描述的:

将存储解码视频帧的 AVFrame。使用 avcodec_alloc_frame 获取 AVFrame,编解码器将为实际的位图分配内存。使用默认的 get/release_buffer(),解码器会释放/重用它认为合适的位图。使用覆盖的 get/release_buffer()(需要 CODEC_CAP_DR1),用户决定解码器解码到哪个缓冲区,一旦不再需要数据,解码器就会告诉用户,用户应用程序此时可以释放/重用/保留内存它认为合适。

于 2013-01-03T12:36:39.433 回答
1

ffmpeg 在帧缓冲区中以特定顺序存储帧的像素数据。存储取决于图片格式(YUV、RGB、)。

avpicture_fill() => 这个函数获取原始缓冲区并设置 AVPicture 结构的各种指针。

于 2013-01-03T12:43:21.817 回答
0

ffmpeg 或类似的库不会进行就地缓冲区转换。首先是关于不丢失原始数据和使用不同缓冲区的速度。其次,如果你做了很多转换,你可以预先分配需要的缓冲区。

于 2013-01-03T12:25:42.230 回答