FFMPEG 内部 YUV444p-> NV12
1. vscale
int ff_init_vscale(SwsContext *c, SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst) { VScalerContext *lumCtx = NULL; VScalerContext *chrCtx = NULL; if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) { lumCtx = av_mallocz(sizeof(VScalerContext)); if (!lumCtx) return AVERROR(ENOMEM); desc[0].process = lum_planar_vscale;if (!isGray(c->dstFormat)) { chrCtx = av_mallocz(sizeof(VScalerContext)); if (!chrCtx) return AVERROR(ENOMEM); desc[1].process = chr_planar_vscale; desc[1].instance = chrCtx; desc[1].src = src; desc[1].dst = dst; } } else { lumCtx = av_mallocz_array(sizeof(VScalerContext), 2); if (!lumCtx) return AVERROR(ENOMEM); chrCtx = &lumCtx[1]; desc[0].process = c->yuv2packedX ? packed_vscale : any_vscale;
void ff_init_vscale_pfn(SwsContext *c, { VScalerContext *lumCtx = NULL; VScalerContext *chrCtx = NULL; int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1); //FIXME avoid hardcoding indexes if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) { if (!isGray(c->dstFormat)) { chrCtx = c->desc[idx].instance; chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter; chrCtx->filter_size = c->vChrFilterSize; chrCtx->filter_pos = c->vChrFilterPos; chrCtx->isMMX = use_mmx; --idx; if (yuv2nv12cX) chrCtx->pfn = yuv2nv12cX; else if (c->vChrFilterSize == 1) chrCtx->pfn = yuv2plane1; else chrCtx->pfn = yuv2planeX;
vcscale
static int chr_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
{
const int chrSkipMask = (1 << desc->dst->v_chr_sub_sample) - 1;
if (sliceY & chrSkipMask)
return 0;
else {
VScalerContext *inst = desc->instance;
int dstW = AV_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
int first = FFMAX(1-inst->filter_size, inst->filter_pos[chrSliceY]);
int sp1 = first - desc->src->plane[1].sliceY;
int sp2 = first - desc->src->plane[2].sliceY;
int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
uint8_t **src1 = desc->src->plane[1].line + sp1;
uint8_t **src2 = desc->src->plane[2].line + sp2;
uint8_t **dst1 = desc->dst->plane[1].line + dp1;
uint8_t **dst2 = desc->dst->plane[2].line + dp2;
uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size);
if (c->yuv2nv12cX) {
((yuv2interleavedX_fn)inst->pfn)(c, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW);
} else if (inst->filter_size == 1) {
((yuv2planar1_fn)inst->pfn)((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0);
((yuv2planar1_fn)inst->pfn)((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3);
} else {
((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src1, dst1[0], dstW, c->chrDither8, 0);
((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src2, dst2[0], dstW, c->chrDither8, inst->isMMX ? (c->uv_offx2 >> 1) : 3);
}
}
return 1;
}
av_cold void ff_sws_init_output_funcs(SwsContext *c, yuv2planar1_fn *yuv2plane1, yuv2planarX_fn *yuv2planeX, yuv2interleavedX_fn *yuv2nv12cX, yuv2packed1_fn *yuv2packed1, yuv2packed2_fn *yuv2packed2, yuv2packedX_fn *yuv2packedX, yuv2anyX_fn *yuv2anyX) { enum AVPixelFormat dstFormat = c->dstFormat; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); if (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P010BE) { *yuv2plane1 = isBE(dstFormat) ? yuv2p010l1_BE_c : yuv2p010l1_LE_c; *yuv2planeX = isBE(dstFormat) ? yuv2p010lX_BE_c : yuv2p010lX_LE_c; *yuv2nv12cX = yuv2p010cX_c; printf("1 \n"); } else if (is16BPS(dstFormat)) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE) { *yuv2nv12cX = yuv2p016cX_c; } } else if (isNBPS(dstFormat)) { if (desc->comp[0].depth == 9) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_9BE_c : yuv2planeX_9LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_9BE_c : yuv2plane1_9LE_c; } else if (desc->comp[0].depth == 10) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_10BE_c : yuv2planeX_10LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_10BE_c : yuv2plane1_10LE_c; } else if (desc->comp[0].depth == 12) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_12BE_c : yuv2planeX_12LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_12BE_c : yuv2plane1_12LE_c; } else if (desc->comp[0].depth == 14) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_14BE_c : yuv2planeX_14LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_14BE_c : yuv2plane1_14LE_c; } else av_assert0(0); } else if (dstFormat == AV_PIX_FMT_GRAYF32BE) { *yuv2planeX = yuv2planeX_floatBE_c; *yuv2plane1 = yuv2plane1_floatBE_c; } else if (dstFormat == AV_PIX_FMT_GRAYF32LE) { *yuv2planeX = yuv2planeX_floatLE_c; *yuv2plane1 = yuv2plane1_floatLE_c; } else { *yuv2plane1 = yuv2plane1_8_c; *yuv2planeX = yuv2planeX_8_c; if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21 || dstFormat == AV_PIX_FMT_NV24 || dstFormat == AV_PIX_FMT_NV42) *yuv2nv12cX = yuv2nv12cX_c; }
static void yuv2nv12cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize, const int16_t **chrUSrc, const int16_t **chrVSrc, uint8_t *dest, int chrDstW) { enum AVPixelFormat dstFormat = c->dstFormat; const uint8_t *chrDither = c->chrDither8; int i; if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV24) for (i=0; i<chrDstW; i++) { //960 int u = chrDither[i & 7] << 12; //0->6 0->6 ... int v = chrDither[(i + 3) & 7] << 12; //3->2 3->2 ... int j; for (j=0; j<chrFilterSize; j++) { u += chrUSrc[j][i] * chrFilter[j]; v += chrVSrc[j][i] * chrFilter[j]; } printed1 = 1; dest[2*i]= av_clip_uint8(u>>19); dest[2*i+1]= av_clip_uint8(v>>19); } else for (i=0; i<chrDstW; i++) { int u = chrDither[i & 7] << 12; int v = chrDither[(i + 3) & 7] << 12; int j; for (j=0; j<chrFilterSize; j++) { u += chrUSrc[j][i] * chrFilter[j]; v += chrVSrc[j][i] * chrFilter[j]; } dest[2*i]= av_clip_uint8(v>>19); dest[2*i+1]= av_clip_uint8(u>>19); } }
/** this is Y scale static void yuv2planeX_8_c(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset) { int i; for (i=0; i<dstW; i++) { int val = dither[(i + offset) & 7] << 12; int j; for (j=0; j<filterSize; j++) val += src[j][i] * filter[j]; dest[i]= av_clip_uint8(val>>19); } } **/
2. hscale
hcscale hyScale
static av_cold void sws_init_swscale(SwsContext *c) { enum AVPixelFormat srcFormat = c->srcFormat; ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX, &c->yuv2nv12cX, &c->yuv2packed1, &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX); ff_sws_init_input_funcs(c); if (c->srcBpc == 8) { if (c->dstBpc <= 14) { c->hyScale = c->hcScale = hScale8To15_c; if (c->flags & SWS_FAST_BILINEAR) { c->hyscale_fast = ff_hyscale_fast_c; c->hcscale_fast = ff_hcscale_fast_c; } } else { c->hyScale = c->hcScale = hScale8To19_c; } } else { c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c : hScale16To15_c; }
// bilinear / bicubic scaling static void hScale8To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize) { int i; for (i = 0; i < dstW; i++) { int j; int srcPos = filterPos[i]; int val = 0; for (j = 0; j < filterSize; j++) { val += ((int)src[srcPos + j]) * filter[filterSize * i + j]; } dst[i] = FFMIN(val >> 7, (1 << 15) - 1); // the cubic equation does overflow ... } }
3.
if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV24) for (i=0; i<chrDstW; i++) { int u = chrDither[i & 7] << 12; int v = chrDither[(i + 3) & 7] << 12; int j; for (j=0; j<chrFilterSize; j++) { u += chrUSrc[j][i] * chrFilter[j]; v += chrVSrc[j][i] * chrFilter[j]; } printed1 = 1; dest[2*i]= av_clip_uint8(u>>19); dest[2*i+1]= av_clip_uint8(v>>19); }
chrFilter = {2048, 1786, 492, -172, -58, 0, 0, 0}
chrDither = {64 64 64 ... } 8 个64
FFMPEG YUV444P -> NV12过程 未缩放
yuv2plane1 = 0x11758b0 <ff_yuv2plane1_8_avx>, ✔ 缩放y通道
yuv2planeX = 0x11751e0 <ff_yuv2planeX_8_avx>,
yuv2nv12cX = 0x113bac0 <yuv2nv12cX_c>, ✔ 将uv merge 起来
hyScale = 0x1180010 <ff_hscale8to15_4_ssse3>, ✔ 缩放y plane 的 水平方向
hcScale = 0x1180090 <ff_hscale8to15_8_ssse3>, ✔ 缩放 u plane 的水平方向 v plane 的水平方向
FFMPEG YUV444P16LE -> P010 过程
yuv2plane1 = 0x480860 <yuv2p010l1_LE_c>
yuv2planeX = 0x4a6580 <yuv2p010lX_LE_c>
yuv2nv12cX = 0x4806e0 <yuv2p010cX_c> chrFilter = {2048, 1786, 492, -172, -58, 0, 0, 0} int32_t
hyScale = 0x4c5520 <ff_hscale16to15_4_ssse3>
hcScale = 0x4c55a0 <ff_hscale16to15_8_ssse3>
FFMPEG YUV444P16LE -> P016 过程