avpicture_fill()的使用心得

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) 

ffmpeg4.2.2-avpicture_fill()的使用心得

1. avpicture_fill()的声明

/**
 * @deprecated use av_image_fill_arrays() instead.
 */
attribute_deprecated
int avpicture_fill(AVPicture *picture, const uint8_t *ptr,
                   enum AVPixelFormat pix_fmt, int width, int height);

FF_DISABLE_DEPRECATION_WARNINGS
int avpicture_fill(AVPicture *picture, const uint8_t *ptr,
                   enum AVPixelFormat pix_fmt, int width, int height)
{
    return av_image_fill_arrays(picture->data, picture->linesize,
                                ptr, pix_fmt, width, height, 1);
}

由上可见, avpicture_fill()函数在ffmpeg4.2.2中就已经被抛弃了, 取而代之的是av_image_fill_arrays()函数. avpicture_fill()中实际调用的也是av_image_fill_arrays()函数, 所以我们拿av_image_fill_arrays()来分析.

2. av_image_fill_arrays()的形参说明

@param dst_data			要填充的数据指针
@param dst_linesize		dst_data中要被填充的线条大小(即linesize, 行宽)
@param src				包含实际图像的缓冲区(可以为空).
@param pix_fmt			图像的像素格式
@param width         	图像的像素宽度
@param height        	图像的像素高度
@param align         	在src中用于行宽对齐的值

@return the size in bytes required for src, a negative error code in case of failure
	该函数返回src所需的大小(以字节为单位), 失败时返回一个负数(错误代码).

3. av_image_fill_arrays()的作用

  根据指定的图像参数和提供的数组设置数据指针和行宽(linesizes). avpicture_fill函数将ptr指向的数据填充到picture内,但并没有拷贝,只是将picture结构内的data指针指向了ptr的数据!

4. av_image_fill_arrays()的流程解析

// ffmpeg-4.2.2\libavutil\imgutils.c
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
                         const uint8_t *src, enum AVPixelFormat pix_fmt,
                         int width, int height, int align)
{
    int ret, i;

	// 检查输入的width和height是否可用.
    ret = av_image_check_size(width, height, 0, NULL);
    if (ret < 0)
        return ret;
	/**
	 * 1. memset(linesizes, 0, 4*sizeof(linesizes[0])); 将dst_linesize数组的内容清零;
	 * 2. 利用av_pix_fmt_desc_get函数得到输入格式的AVPixFmtDescriptor指针;
	 * 3. 最后利用image_get_linesize函数设置linesizes数组中每个元素的值.
	 * 
	 * 可见该函数是用于填充dst_linesize数组.
	 */
    ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
    if (ret < 0)
        return ret;

    for (i = 0; i < 4; i++)
    	/**
		 * 由上面的第一节avpicture_fill的实现中可知align=1, 故该宏返回的值还是linesizes[i].
		 */
        dst_linesize[i] = FFALIGN(dst_linesize[i], align);

	/**
	 * 1. memset(data, 0, sizeof(data[0])*4);	将data数组内的指针置空
	 * 2. data[i] = data[i-1] + size[i-1];		将data数组内的指针分别指向ptr内的数据
	*/ 
    return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
}

5. 以前对avpicture_fill()的错误理解

uint8_t *out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
AVFrame *pFrameRGB = av_frame_alloc();

ret = avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_RGB24,
                pCodecCtx->width, pCodecCtx->height);

错误理解:
  pFrameRGB和out_buffer都是已经申请到的一段内存, 会将pFrameRGB的数据按RGB24格式自动"关联(转换并放置)"到out_buffer。

正确理解:
  pFrameRGB和out_buffer都是已经申请到的一段内存, 但是pFrameRGB只是申请了一段结构体内存, 结构体里面的值是空的, 我们需要使用avpicture_fill()函数来使得pFrameRGB和out_buffer关联起来, pFrameRGB里面使用的是out_buffer所指向的内存空间.

发布了68 篇原创文章 · 获赞 22 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/MACMACip/article/details/105463390
今日推荐