在使用ffmpeg进行数据处理的时候经常遇到一些函数总想知道是怎么实现的
av_image_copy这个经常看到
于是找到原型
//数据拷贝
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], const uint8_t *src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return; if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { av_image_copy_plane(dst_data[0], dst_linesizes[0], src_data[0], src_linesizes[0], width, height); /* copy the palette */ memcpy(dst_data[1], src_data[1], 4*256); } else { int i, planes_nb = 0; for (i = 0; i < desc->nb_components; i++) planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); for (i = 0; i < planes_nb; i++) { int h = height; int bwidth = av_image_get_linesize(pix_fmt, width, i); if (bwidth < 0) { av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); return; } if (i == 1 || i == 2) { h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h); } av_image_copy_plane(dst_data[i], dst_linesizes[i], src_data[i], src_linesizes[i], bwidth, h); } } }
//获取行数
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane) { 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 */ if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); av_image_fill_max_pixsteps(max_step, max_step_comp, desc); return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc); }
int image_get_linesize(int width, int plane, int max_step, int max_step_comp, const AVPixFmtDescriptor *desc) { int s, shifted_w, linesize; if (!desc) return AVERROR(EINVAL); if (width < 0) return AVERROR(EINVAL); s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0; shifted_w = ((width + (1 << s) - 1)) >> s; if (shifted_w && max_step > INT_MAX / shifted_w) return AVERROR(EINVAL); linesize = max_step * shifted_w; if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) linesize = (linesize + 7) >> 3; return linesize; }
void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], const AVPixFmtDescriptor *pixdesc) { int i; memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0])); if (max_pixstep_comps) memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0])); for (i = 0; i < 4; i++) { const AVComponentDescriptor *comp = &(pixdesc->comp[i]); if (comp->step > max_pixsteps[comp->plane]) { max_pixsteps[comp->plane] = comp->step; if (max_pixstep_comps) max_pixstep_comps[comp->plane] = i; } } }
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height) { if (!dst || !src) return; av_assert0(abs(src_linesize) >= bytewidth); av_assert0(abs(dst_linesize) >= bytewidth); for (;height > 0; height--) { memcpy(dst, src, bytewidth); dst += dst_linesize; src += src_linesize; } }
这里的每个函数的实现都把源码抠出来,以至于后面可以很容易的看到。并且类似这种数据拷贝在图像编解码的很多地方可以看到,只要是与数据块拷贝的基本上无法避免的。