X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libswscale%2Fswscale_unscaled.c;h=be04a236d87c4abf03e138d622d3df614b2e6f7c;hb=4eec0082599adf4b7a25ce6e6ec761f6849783a3;hp=5ec2116bcfa8db2ebf50911e68e1d6febfcd4939;hpb=f61cf0e4df52130c138ee55691409044ab2e9833;p=ffmpeg diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 5ec2116bcfa..be04a236d87 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -150,10 +150,10 @@ static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[], dstParam[0], dstStride[0]); if (c->dstFormat == AV_PIX_FMT_NV12) - interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2, + interleaveBytes(src[1], src[2], dst, c->chrSrcW, (srcSliceH + 1) / 2, srcStride[1], srcStride[2], dstStride[1]); else - interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2, + interleaveBytes(src[2], src[1], dst, c->chrSrcW, (srcSliceH + 1) / 2, srcStride[2], srcStride[1], dstStride[1]); return srcSliceH; @@ -171,25 +171,37 @@ static int nv12ToPlanarWrapper(SwsContext *c, const uint8_t *src[], dstParam[0], dstStride[0]); if (c->srcFormat == AV_PIX_FMT_NV12) - deinterleaveBytes(src[1], dst1, dst2,c->srcW / 2, srcSliceH / 2, + deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, (srcSliceH + 1) / 2, srcStride[1], dstStride[1], dstStride[2]); else - deinterleaveBytes(src[1], dst2, dst1, c->srcW / 2, srcSliceH / 2, + deinterleaveBytes(src[1], dst2, dst1, c->chrSrcW, (srcSliceH + 1) / 2, srcStride[1], dstStride[2], dstStride[1]); return srcSliceH; } -static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[], +static int planarToP01xWrapper(SwsContext *c, const uint8_t *src8[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dstParam8[], int dstStride[]) { + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); const uint16_t **src = (const uint16_t**)src8; uint16_t *dstY = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY); uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2); int x, y; + /* Calculate net shift required for values. */ + const int shift[3] = { + dst_format->comp[0].depth + dst_format->comp[0].shift - + src_format->comp[0].depth - src_format->comp[0].shift, + dst_format->comp[1].depth + dst_format->comp[1].shift - + src_format->comp[1].depth - src_format->comp[1].shift, + dst_format->comp[2].depth + dst_format->comp[2].shift - + src_format->comp[2].depth - src_format->comp[2].shift, + }; + av_assert0(!(srcStride[0] % 2 || srcStride[1] % 2 || srcStride[2] % 2 || dstStride[0] % 2 || dstStride[1] % 2)); @@ -197,7 +209,7 @@ static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[], uint16_t *tdstY = dstY; const uint16_t *tsrc0 = src[0]; for (x = c->srcW; x > 0; x--) { - *tdstY++ = *tsrc0++ << 6; + *tdstY++ = *tsrc0++ << shift[0]; } src[0] += srcStride[0] / 2; dstY += dstStride[0] / 2; @@ -207,8 +219,8 @@ static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[], const uint16_t *tsrc1 = src[1]; const uint16_t *tsrc2 = src[2]; for (x = c->srcW / 2; x > 0; x--) { - *tdstUV++ = *tsrc1++ << 6; - *tdstUV++ = *tsrc2++ << 6; + *tdstUV++ = *tsrc1++ << shift[1]; + *tdstUV++ = *tsrc2++ << shift[2]; } src[1] += srcStride[1] / 2; src[2] += srcStride[2] / 2; @@ -411,7 +423,7 @@ static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, } } -static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[], +static int bswap_16bpc(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { @@ -904,6 +916,91 @@ static void gbr24ptopacked32(const uint8_t *src[], int srcStride[], } } +static void gbraptopacked32(const uint8_t *src[], int srcStride[], + uint8_t *dst, int dstStride, int srcSliceH, + int alpha_first, int width) +{ + int x, h, i; + for (h = 0; h < srcSliceH; h++) { + uint8_t *dest = dst + dstStride * h; + + if (alpha_first) { + for (x = 0; x < width; x++) { + *dest++ = src[3][x]; + *dest++ = src[0][x]; + *dest++ = src[1][x]; + *dest++ = src[2][x]; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = src[0][x]; + *dest++ = src[1][x]; + *dest++ = src[2][x]; + *dest++ = src[3][x]; + } + } + + for (i = 0; i < 4; i++) + src[i] += srcStride[i]; + } +} + +static int planarRgbaToRgbWrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + int alpha_first = 0; + const uint8_t *src102[] = { src[1], src[0], src[2], src[3] }; + const uint8_t *src201[] = { src[2], src[0], src[1], src[3] }; + int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] }; + int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] }; + + if (c->srcFormat != AV_PIX_FMT_GBRAP) { + av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", + av_get_pix_fmt_name(c->srcFormat), + av_get_pix_fmt_name(c->dstFormat)); + return srcSliceH; + } + + switch (c->dstFormat) { + case AV_PIX_FMT_BGR24: + gbr24ptopacked24(src102, stride102, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, c->srcW); + break; + + case AV_PIX_FMT_RGB24: + gbr24ptopacked24(src201, stride201, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, c->srcW); + break; + + case AV_PIX_FMT_ARGB: + alpha_first = 1; + case AV_PIX_FMT_RGBA: + gbraptopacked32(src201, stride201, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, alpha_first, c->srcW); + break; + + case AV_PIX_FMT_ABGR: + alpha_first = 1; + case AV_PIX_FMT_BGRA: + gbraptopacked32(src102, stride102, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, alpha_first, c->srcW); + break; + + default: + av_log(c, AV_LOG_ERROR, + "unsupported planar RGB conversion %s -> %s\n", + av_get_pix_fmt_name(c->srcFormat), + av_get_pix_fmt_name(c->dstFormat)); + } + + return srcSliceH; +} + static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) @@ -1455,6 +1552,46 @@ static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[], return srcSliceH; } +static int uint_y_to_float_y_wrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t *dst[], int dstStride[]) +{ + int y, x; + ptrdiff_t dstStrideFloat = dstStride[0] >> 2; + const uint8_t *srcPtr = src[0]; + float *dstPtr = (float *)(dst[0] + dstStride[0] * srcSliceY); + + for (y = 0; y < srcSliceH; ++y){ + for (x = 0; x < c->srcW; ++x){ + dstPtr[x] = c->uint2float_lut[srcPtr[x]]; + } + srcPtr += srcStride[0]; + dstPtr += dstStrideFloat; + } + + return srcSliceH; +} + +static int float_y_to_uint_y_wrapper(SwsContext *c, const uint8_t* src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t* dst[], int dstStride[]) +{ + int y, x; + ptrdiff_t srcStrideFloat = srcStride[0] >> 2; + const float *srcPtr = (const float *)src[0]; + uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; + + for (y = 0; y < srcSliceH; ++y){ + for (x = 0; x < c->srcW; ++x){ + dstPtr[x] = av_clip_uint8(lrintf(255.0f * srcPtr[x])); + } + srcPtr += srcStrideFloat; + dstPtr += dstStride[0]; + } + + return srcSliceH; +} + /* unscaled copy like stuff (assumes nearly identical formats) */ static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, @@ -1684,6 +1821,14 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], srcPtr += srcStride[plane]; dstPtr += dstStride[plane]; } + } else if (isFloat(c->srcFormat) && isFloat(c->dstFormat) && + isBE(c->srcFormat) != isBE(c->dstFormat)) { /* swap float plane */ + for (i = 0; i < height; i++) { + for (j = 0; j < length; j++) + ((uint32_t *) dstPtr)[j] = av_bswap32(((const uint32_t *) srcPtr)[j]); + srcPtr += srcStride[plane]; + dstPtr += dstStride[plane]; + } } else if (dstStride[plane] == srcStride[plane] && srcStride[plane] > 0 && srcStride[plane] == length) { memcpy(dst[plane] + dstStride[plane] * y, src[plane], @@ -1738,14 +1883,17 @@ void ff_get_unscaled_swscale(SwsContext *c) !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) { c->swscale = ff_yuv2rgb_get_func_ptr(c); } - /* yuv420p10_to_p010 */ - if ((srcFormat == AV_PIX_FMT_YUV420P10 || srcFormat == AV_PIX_FMT_YUVA420P10) && - dstFormat == AV_PIX_FMT_P010) { - c->swscale = planarToP010Wrapper; + /* yuv420p1x_to_p01x */ + if ((srcFormat == AV_PIX_FMT_YUV420P10 || srcFormat == AV_PIX_FMT_YUVA420P10 || + srcFormat == AV_PIX_FMT_YUV420P12 || + srcFormat == AV_PIX_FMT_YUV420P14 || + srcFormat == AV_PIX_FMT_YUV420P16 || srcFormat == AV_PIX_FMT_YUVA420P16) && + (dstFormat == AV_PIX_FMT_P010 || dstFormat == AV_PIX_FMT_P016)) { + c->swscale = planarToP01xWrapper; } - /* yuv420p_to_p010le */ + /* yuv420p_to_p01xle */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) && - dstFormat == AV_PIX_FMT_P010LE) { + (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P016LE)) { c->swscale = planar8ToP01xleWrapper; } @@ -1782,6 +1930,9 @@ void ff_get_unscaled_swscale(SwsContext *c) if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat)) c->swscale = planarRgbToRgbWrapper; + if (srcFormat == AV_PIX_FMT_GBRAP && isByteRGB(dstFormat)) + c->swscale = planarRgbaToRgbWrapper; + if ((srcFormat == AV_PIX_FMT_RGB48LE || srcFormat == AV_PIX_FMT_RGB48BE || srcFormat == AV_PIX_FMT_BGR48LE || srcFormat == AV_PIX_FMT_BGR48BE || srcFormat == AV_PIX_FMT_RGBA64LE || srcFormat == AV_PIX_FMT_RGBA64BE || @@ -1837,6 +1988,7 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY9) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY10) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY12) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY14) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YA16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_AYUV64) || @@ -1871,7 +2023,7 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P14) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P16)) - c->swscale = packed_16bpc_bswap; + c->swscale = bswap_16bpc; if (usePal(srcFormat) && isByteRGB(dstFormat)) c->swscale = palToRgbWrapper; @@ -1883,6 +2035,16 @@ void ff_get_unscaled_swscale(SwsContext *c) c->swscale = yuv422pToUyvyWrapper; } + /* uint Y to float Y */ + if (srcFormat == AV_PIX_FMT_GRAY8 && dstFormat == AV_PIX_FMT_GRAYF32){ + c->swscale = uint_y_to_float_y_wrapper; + } + + /* float Y to uint Y */ + if (srcFormat == AV_PIX_FMT_GRAYF32 && dstFormat == AV_PIX_FMT_GRAY8){ + c->swscale = float_y_to_uint_y_wrapper; + } + /* LQ converters if -sws 0 or -sws 4*/ if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) { /* yv12_to_yuy2 */ @@ -1909,18 +2071,13 @@ void ff_get_unscaled_swscale(SwsContext *c) if ( srcFormat == dstFormat || (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) || (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) || - (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) || + (isFloat(srcFormat) == isFloat(dstFormat)) && ((isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) || (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) || (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && c->chrDstHSubSample == c->chrSrcHSubSample && c->chrDstVSubSample == c->chrSrcVSubSample && - dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 && - dstFormat != AV_PIX_FMT_P010LE && dstFormat != AV_PIX_FMT_P010BE && - dstFormat != AV_PIX_FMT_P016LE && dstFormat != AV_PIX_FMT_P016BE && - srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 && - srcFormat != AV_PIX_FMT_P010LE && srcFormat != AV_PIX_FMT_P010BE && - srcFormat != AV_PIX_FMT_P016LE && srcFormat != AV_PIX_FMT_P016BE)) + !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat)))) { if (isPacked(c->srcFormat)) c->swscale = packedCopyWrapper;