我指的是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图像指针
分段错误(核心转储)
答案 0 :(得分:25)
我认为让你感到困惑的是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()
将帧转换为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或类似的库不会进行就地缓冲区转换。首先,它是关于不丢失原始数据和使用不同缓冲区的速度。其次,如果您进行了大量转换,则可以事先分配所需的缓冲区。