FFMPEG:将YUV数据转储为AVFrame结构

时间:2013-12-10 12:08:19

标签: ffmpeg yuv

我正在尝试将YUV420数据转储到FFMPEG的AVFrame结构中。从以下链接:

http://ffmpeg.org/doxygen/trunk/structAVFrame.html,我可以推断出我需要将数据放入

data[AV_NUM_DATA_POINTERS] 

使用

linesize [AV_NUM_DATA_POINTERS].

我试图转储的YUV数据是YUV420,图片大小是416x240.那么我如何将这个yuv数据转储/映射到AVFrame结构变量?我知道lineize表示步幅,即我想我的图片的宽度,我尝试了一些组合,但没有得到输出。我请求你帮我映射缓冲区。提前谢谢。

2 个答案:

答案 0 :(得分:18)

AVFrame可以解释为AVPicture,以填充datalinesize字段。填写这些字段的最简单方法是使用avpicture_fill函数。

要填写AVFrame的YU和V缓冲区,它取决于您的输入数据以及您想要对帧执行的操作(是否要写入AVFrame并删除初始数据?或保留拷贝)。

如果缓冲区足够大(Y数据至少为linesize[0] * height,U / V数据为linesize[1 or 2] * height/2),则可以直接使用输入缓冲区:

// Initialize the AVFrame
AVFrame* frame = avcodec_alloc_frame();
frame->width = width;
frame->height = height;
frame->format = AV_PIX_FMT_YUV420P;

// Initialize frame->linesize
avpicture_fill((AVPicture*)frame, NULL, frame->format, frame->width, frame->height);

// Set frame->data pointers manually
frame->data[0] = inputBufferY;
frame->data[1] = inputBufferU;
frame->data[2] = inputBufferV;

// Or if your Y, U, V buffers are contiguous and have the correct size, simply use:
// avpicture_fill((AVPicture*)frame, inputBufferYUV, frame->format, frame->width, frame->height);

如果您需要/需要操作输入数据的副本,您需要计算所需的缓冲区大小,并在其中复制输入数据。

// Initialize the AVFrame
AVFrame* frame = avcodec_alloc_frame();
frame->width = width;
frame->height = height;
frame->format = AV_PIX_FMT_YUV420P;

// Allocate a buffer large enough for all data
int size = avpicture_get_size(frame->format, frame->width, frame->height);
uint8_t* buffer = (uint8_t*)av_malloc(size);

// Initialize frame->linesize and frame->data pointers
avpicture_fill((AVPicture*)frame, buffer, frame->format, frame->width, frame->height);

// Copy data from the 3 input buffers
memcpy(frame->data[0], inputBufferY, frame->linesize[0] * frame->height);
memcpy(frame->data[1], inputBufferU, frame->linesize[1] * frame->height / 2);
memcpy(frame->data[2], inputBufferV, frame->linesize[2] * frame->height / 2);

完成AVFrame后,请不要忘记使用av_frame_free(以及av_malloc分配的任何缓冲区)释放它。

答案 1 :(得分:1)

FF_API int ff_get_format_plane_size(int fmt, int plane, int scanLine, int height)
{
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
    if (desc)
    {
            int h = height;
            if (plane == 1 || plane == 2)
            {
                h = FF_CEIL_RSHIFT(height, desc->log2_chroma_h);
            }
            return h*scanLine;
    }
    else
        return AVERROR(EINVAL);
}