X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libswscale%2Fswscale_unscaled.c;h=c4dd8a4d8312bdd9c1aeaf301416572c87fbe729;hb=HEAD;hp=973fa4875f7e7822b89b93f644bb94ffc01aa521;hpb=022fa7a24ea8f5000e7b6a50e57cc752f417da47;p=ffmpeg diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 973fa4875f7..c4dd8a4d831 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -30,6 +30,7 @@ #include "libavutil/cpu.h" #include "libavutil/avutil.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "libavutil/bswap.h" #include "libavutil/pixdesc.h" #include "libavutil/avassert.h" @@ -150,10 +151,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,10 +172,51 @@ 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 planarToNv24Wrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t *dstParam[], + int dstStride[]) +{ + uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY; + + copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + dstParam[0], dstStride[0]); + + if (c->dstFormat == AV_PIX_FMT_NV24) + interleaveBytes(src[1], src[2], dst, c->chrSrcW, srcSliceH, + srcStride[1], srcStride[2], dstStride[1]); + else + interleaveBytes(src[2], src[1], dst, c->chrSrcW, srcSliceH, + srcStride[2], srcStride[1], dstStride[1]); + + return srcSliceH; +} + +static int nv24ToPlanarWrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t *dstParam[], + int dstStride[]) +{ + uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY; + uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY; + + copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + dstParam[0], dstStride[0]); + + if (c->srcFormat == AV_PIX_FMT_NV24) + deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, srcSliceH, + srcStride[1], dstStride[1], dstStride[2]); + else + deinterleaveBytes(src[1], dst2, dst1, c->chrSrcW, srcSliceH, srcStride[1], dstStride[2], dstStride[1]); return srcSliceH; @@ -423,7 +465,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[]) { @@ -450,6 +492,34 @@ static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[], return srcSliceH; } +static int bswap_32bpc(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + int i, j, p; + + for (p = 0; p < 4; p++) { + int srcstr = srcStride[p] / 4; + int dststr = dstStride[p] / 4; + uint32_t *dstPtr = (uint32_t *) dst[p]; + const uint32_t *srcPtr = (const uint32_t *) src[p]; + int min_stride = FFMIN(FFABS(srcstr), FFABS(dststr)); + if(!dstPtr || !srcPtr) + continue; + dstPtr += (srcSliceY >> c->chrDstVSubSample) * dststr; + for (i = 0; i < (srcSliceH >> c->chrDstVSubSample); i++) { + for (j = 0; j < min_stride; j++) { + dstPtr[j] = av_bswap32(srcPtr[j]); + } + srcPtr += srcstr; + dstPtr += dststr; + } + } + + return srcSliceH; +} + + static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) @@ -916,6 +986,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[]) @@ -1172,6 +1327,55 @@ static int bayer_to_rgb24_wrapper(SwsContext *c, const uint8_t* src[], int srcSt return srcSliceH; } +static int bayer_to_rgb48_wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, + int srcSliceH, uint8_t* dst[], int dstStride[]) +{ + uint8_t *dstPtr= dst[0] + srcSliceY * dstStride[0]; + const uint8_t *srcPtr= src[0]; + int i; + void (*copy) (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); + void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); + + switch(c->srcFormat) { +#define CASE(pixfmt, prefix) \ + case pixfmt: copy = bayer_##prefix##_to_rgb48_copy; \ + interpolate = bayer_##prefix##_to_rgb48_interpolate; \ + break; + CASE(AV_PIX_FMT_BAYER_BGGR8, bggr8) + CASE(AV_PIX_FMT_BAYER_BGGR16LE, bggr16le) + CASE(AV_PIX_FMT_BAYER_BGGR16BE, bggr16be) + CASE(AV_PIX_FMT_BAYER_RGGB8, rggb8) + CASE(AV_PIX_FMT_BAYER_RGGB16LE, rggb16le) + CASE(AV_PIX_FMT_BAYER_RGGB16BE, rggb16be) + CASE(AV_PIX_FMT_BAYER_GBRG8, gbrg8) + CASE(AV_PIX_FMT_BAYER_GBRG16LE, gbrg16le) + CASE(AV_PIX_FMT_BAYER_GBRG16BE, gbrg16be) + CASE(AV_PIX_FMT_BAYER_GRBG8, grbg8) + CASE(AV_PIX_FMT_BAYER_GRBG16LE, grbg16le) + CASE(AV_PIX_FMT_BAYER_GRBG16BE, grbg16be) +#undef CASE + default: return 0; + } + + av_assert0(srcSliceH > 1); + + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + srcPtr += 2 * srcStride[0]; + dstPtr += 2 * dstStride[0]; + + for (i = 2; i < srcSliceH - 2; i += 2) { + interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + srcPtr += 2 * srcStride[0]; + dstPtr += 2 * dstStride[0]; + } + + if (i + 1 == srcSliceH) { + copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW); + } else if (i < srcSliceH) + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + return srcSliceH; +} + static int bayer_to_yv12_wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]) { @@ -1602,7 +1806,7 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); int plane, i, j; - for (plane = 0; plane < 4; plane++) { + for (plane = 0; plane < 4 && dst[plane] != NULL; plane++) { int length = (plane == 0 || plane == 3) ? c->srcW : AV_CEIL_RSHIFT(c->srcW, c->chrDstHSubSample); int y = (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample); int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample); @@ -1610,8 +1814,6 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0); - if (!dst[plane]) - continue; // ignore palette for GRAY8 if (plane == 1 && !dst[2]) continue; if (!src[plane] || (plane == 1 && !src[2])) { @@ -1736,6 +1938,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], @@ -1779,11 +1989,21 @@ void ff_get_unscaled_swscale(SwsContext *c) (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) { c->swscale = planarToNv12Wrapper; } + /* yv24_to_nv24 */ + if ((srcFormat == AV_PIX_FMT_YUV444P || srcFormat == AV_PIX_FMT_YUVA444P) && + (dstFormat == AV_PIX_FMT_NV24 || dstFormat == AV_PIX_FMT_NV42)) { + c->swscale = planarToNv24Wrapper; + } /* nv12_to_yv12 */ if (dstFormat == AV_PIX_FMT_YUV420P && (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) { c->swscale = nv12ToPlanarWrapper; } + /* nv24_to_yv24 */ + if (dstFormat == AV_PIX_FMT_YUV444P && + (srcFormat == AV_PIX_FMT_NV24 || srcFormat == AV_PIX_FMT_NV42)) { + c->swscale = nv24ToPlanarWrapper; + } /* yuv2bgr */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && @@ -1837,6 +2057,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 || @@ -1846,6 +2069,7 @@ void ff_get_unscaled_swscale(SwsContext *c) dstFormat == AV_PIX_FMT_GBRP12LE || dstFormat == AV_PIX_FMT_GBRP12BE || dstFormat == AV_PIX_FMT_GBRP14LE || dstFormat == AV_PIX_FMT_GBRP14BE || dstFormat == AV_PIX_FMT_GBRP16LE || dstFormat == AV_PIX_FMT_GBRP16BE || + dstFormat == AV_PIX_FMT_GBRAP10LE || dstFormat == AV_PIX_FMT_GBRAP10BE || dstFormat == AV_PIX_FMT_GBRAP12LE || dstFormat == AV_PIX_FMT_GBRAP12BE || dstFormat == AV_PIX_FMT_GBRAP16LE || dstFormat == AV_PIX_FMT_GBRAP16BE )) c->swscale = Rgb16ToPlanarRgb16Wrapper; @@ -1855,6 +2079,7 @@ void ff_get_unscaled_swscale(SwsContext *c) srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE || srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE || srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE || + srcFormat == AV_PIX_FMT_GBRAP10LE || srcFormat == AV_PIX_FMT_GBRAP10BE || srcFormat == AV_PIX_FMT_GBRAP12LE || srcFormat == AV_PIX_FMT_GBRAP12BE || srcFormat == AV_PIX_FMT_GBRAP16LE || srcFormat == AV_PIX_FMT_GBRAP16BE) && (dstFormat == AV_PIX_FMT_RGB48LE || dstFormat == AV_PIX_FMT_RGB48BE || @@ -1870,6 +2095,8 @@ void ff_get_unscaled_swscale(SwsContext *c) if (isBayer(srcFormat)) { if (dstFormat == AV_PIX_FMT_RGB24) c->swscale = bayer_to_rgb24_wrapper; + else if (dstFormat == AV_PIX_FMT_RGB48) + c->swscale = bayer_to_rgb48_wrapper; else if (dstFormat == AV_PIX_FMT_YUV420P) c->swscale = bayer_to_yv12_wrapper; else if (!isBayer(dstFormat)) { @@ -1885,7 +2112,6 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_GRBG16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) || - IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || @@ -1901,11 +2127,11 @@ void ff_get_unscaled_swscale(SwsContext *c) IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP10) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) || - IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || @@ -1927,7 +2153,12 @@ 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; + + /* bswap 32 bits per pixel/component formats */ + if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRPF32) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAPF32)) + c->swscale = bswap_32bpc; if (usePal(srcFormat) && isByteRGB(dstFormat)) c->swscale = palToRgbWrapper;