简介
avpicture_fill函数将ptr指向的数据填充到picture内,但并没有拷贝,只是将picture结构内的data指针指向了ptr的数据。其实现如下:
avpiture_fill
avpiture_fill直接调用av_image_fill_arrays函数。
// libavcodec/avpicture.c 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); }
av_image_fill_arrays
// 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; ret = av_image_check_size(width, height, 0, NULL); if (ret < 0) return ret; ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width); if (ret < 0) return ret; for (i = 0; i < 4; i++) dst_linesize[i] = FFALIGN(dst_linesize[i], align); return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize); }
其中av_image_check_size用来检测输入的widht和height是否可用,判断条件如下:
if ((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8) return 0;
av_image_fill_linesizes
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width) { int i, ret; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int max_step [4]; /* max pixel step for each plane */ int max_step_comp[4]; /* the component for each plane which has the max pixel step */ memset(linesizes, 0, 4*sizeof(linesizes[0])); if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); av_image_fill_max_pixsteps(max_step, max_step_comp, desc); for (i = 0; i < 4; i++) { if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0) return ret; linesizes[i] = ret; } return 0; }
- 将linsizes数组的内容置为0;
- 利用av_pix_fmt_desc_get函数得到输入格式的AVPixFmtDescriptor指针;
-
最后利用image_get_linesize函数获得linesizes数组中每个元素的值;
FFALIGN
由于在afpicture_fill中填充的align为1, 故该宏返回的值还是linesizes[i];
// libavutil/common.h #define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
av_image_fill_pointers
int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, uint8_t *ptr, const int linesizes[4]) { int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 }; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); memset(data , 0, sizeof(data[0])*4); if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); data[0] = ptr; if (linesizes[0] > (INT_MAX - 1024) / height) return AVERROR(EINVAL); size[0] = linesizes[0] * height; if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { size[0] = (size[0] + 3) & ~3; data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */ return size[0] + 256 * 4; } for (i = 0; i < 4; i++) has_plane[desc->comp[i].plane] = 1; total_size = size[0]; for (i = 1; i < 4 && has_plane[i]; i++) { int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; data[i] = data[i-1] + size[i-1]; h = (height + (1 << s) - 1) >> s; if (linesizes[i] > INT_MAX / h) return AVERROR(EINVAL); size[i] = h * linesizes[i]; if (total_size > INT_MAX - size[i]) return AVERROR(EINVAL); total_size += size[i]; } return total_size; }
将data数组内的指针分别指向ptr内的数据。