为什么在将AVFrame从一种格式转换为另一种格式时需要缓冲区?

时间:2013-01-03 12:14:53

标签: c ffmpeg

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

3 个答案:

答案 0 :(得分:25)

我认为让你感到困惑的是AVFrame似乎有两个分配。

第一个用avcodec_alloc_frame()完成,为通用框架及其元数据分配空间。此时,保持框架正确所需的内存仍然是未知的。

然后从另一个源填充该帧,然后通过传递widthheight和颜色深度来指定所需的内存:

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()将帧转换为RGB-24。

要将帧转换为其他格式,我们会将源复制到其他目标。这是因为目标帧可能比源帧可以容纳的更大,并且因为一些转换算法需要在未转换源的更大区域上操作,所以在原位转换源是不方便的。此外,源帧由库处理,可能无法安全地写入。

更新(评论)

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

为什么pFrame不需要内存分配:好问题。答案在使用的函数prototype and layout中,其中描述了图片参数:

  

将存储解码视频帧的AVFrame。使用   avcodec_alloc_frame获取AVFrame,编解码器将分配内存   对于实际的位图。使用默认的get / release_buffer(),解码器   释放/重用它认为合适的位图。被覆盖   get / release_buffer()(需要CODEC_CAP_DR1)用户决定什么   缓冲解码器解码,解码器一旦告知用户   不再需要数据,此时用户应用程序可以   free / reuse /保留内存,因为它看起来合适。

答案 1 :(得分:1)

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

avpicture_fill()=>此函数接受原始缓冲区并设置AVPicture结构的各种指针。

答案 2 :(得分:0)

ffmpeg或类似的库不会进行就地缓冲区转换。首先,它是关于不丢失原始数据和使用不同缓冲区的速度。其次,如果您进行了大量转换,则可以事先分配所需的缓冲区。