summaryrefslogtreecommitdiff
path: root/libswscale
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2019-05-09 21:02:09 -0700
committerPhilip Langdale <philipl@overt.org>2019-05-12 07:51:02 -0700
commitcd483180356c8f206f32393acc52a85c5b76758b (patch)
tree06d6ff23172861b896fe3de72b4a431192ed4522 /libswscale
parent5de4f1d871d60886b9630531fa8c34cad13cc9dd (diff)
swscale: Add support for NV24 and NV42
The implementation is pretty straight-forward. Most of the existing NV12 codepaths work regardless of subsampling and are re-used as is. Where necessary I wrote the slightly different NV24 versions. Finally, the one thing that confused me for a long time was the asm specific x86 path that did an explicit exclusion check for NV12. I replaced that with a semi-planar check and also updated the equivalent PPC code, which Lauri kindly checked.
Diffstat (limited to 'libswscale')
-rw-r--r--libswscale/input.c2
-rw-r--r--libswscale/output.c6
-rw-r--r--libswscale/ppc/swscale_altivec.c3
-rw-r--r--libswscale/ppc/swscale_vsx.c3
-rw-r--r--libswscale/swscale_unscaled.c51
-rw-r--r--libswscale/utils.c2
-rw-r--r--libswscale/version.h2
-rw-r--r--libswscale/x86/swscale_template.c4
8 files changed, 64 insertions, 9 deletions
diff --git a/libswscale/input.c b/libswscale/input.c
index c2dc356b5d..064f8da314 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -1020,9 +1020,11 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
c->chrToYV12 = uyvyToUV_c;
break;
case AV_PIX_FMT_NV12:
+ case AV_PIX_FMT_NV24:
c->chrToYV12 = nv12ToUV_c;
break;
case AV_PIX_FMT_NV21:
+ case AV_PIX_FMT_NV42:
c->chrToYV12 = nv21ToUV_c;
break;
case AV_PIX_FMT_RGB8:
diff --git a/libswscale/output.c b/libswscale/output.c
index d3401f0cd1..26b0ff3d48 100644
--- a/libswscale/output.c
+++ b/libswscale/output.c
@@ -410,7 +410,8 @@ static void yuv2nv12cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterS
const uint8_t *chrDither = c->chrDither8;
int i;
- if (dstFormat == AV_PIX_FMT_NV12)
+ 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;
@@ -2496,7 +2497,8 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
} else {
*yuv2plane1 = yuv2plane1_8_c;
*yuv2planeX = yuv2planeX_8_c;
- if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)
+ if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21 ||
+ dstFormat == AV_PIX_FMT_NV24 || dstFormat == AV_PIX_FMT_NV42)
*yuv2nv12cX = yuv2nv12cX_c;
}
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index 3cd9782da4..6b8cc2c194 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -247,8 +247,7 @@ av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
if (c->srcBpc == 8 && c->dstBpc <= 14) {
c->hyScale = c->hcScale = hScale_real_altivec;
}
- if (!is16BPS(dstFormat) && !isNBPS(dstFormat) &&
- dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
+ if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && !isSemiPlanarYUV(dstFormat) &&
dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE &&
!c->needAlpha) {
c->yuv2planeX = yuv2planeX_altivec;
diff --git a/libswscale/ppc/swscale_vsx.c b/libswscale/ppc/swscale_vsx.c
index a617f76741..75dee5ea58 100644
--- a/libswscale/ppc/swscale_vsx.c
+++ b/libswscale/ppc/swscale_vsx.c
@@ -2096,8 +2096,7 @@ av_cold void ff_sws_init_swscale_vsx(SwsContext *c)
: hScale16To15_vsx;
}
}
- if (!is16BPS(dstFormat) && !isNBPS(dstFormat) &&
- dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
+ if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && !isSemiPlanarYUV(dstFormat) &&
dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE &&
!c->needAlpha) {
c->yuv2planeX = yuv2planeX_vsx;
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index be04a236d8..e0b9e99373 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -180,6 +180,47 @@ static int nv12ToPlanarWrapper(SwsContext *c, const uint8_t *src[],
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;
+}
+
static int planarToP01xWrapper(SwsContext *c, const uint8_t *src8[],
int srcStride[], int srcSliceY,
int srcSliceH, uint8_t *dstParam8[],
@@ -1872,11 +1913,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) &&
diff --git a/libswscale/utils.c b/libswscale/utils.c
index df68bcc0d9..1b1f779532 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -264,6 +264,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
[AV_PIX_FMT_YUVA422P12LE] = { 1, 1 },
[AV_PIX_FMT_YUVA444P12BE] = { 1, 1 },
[AV_PIX_FMT_YUVA444P12LE] = { 1, 1 },
+ [AV_PIX_FMT_NV24] = { 1, 1 },
+ [AV_PIX_FMT_NV42] = { 1, 1 },
};
int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
diff --git a/libswscale/version.h b/libswscale/version.h
index 0e28a76e64..891c76d915 100644
--- a/libswscale/version.h
+++ b/libswscale/version.h
@@ -28,7 +28,7 @@
#define LIBSWSCALE_VERSION_MAJOR 5
#define LIBSWSCALE_VERSION_MINOR 4
-#define LIBSWSCALE_VERSION_MICRO 100
+#define LIBSWSCALE_VERSION_MICRO 101
#define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
LIBSWSCALE_VERSION_MINOR, \
diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c
index 7c30470679..823056c2ea 100644
--- a/libswscale/x86/swscale_template.c
+++ b/libswscale/x86/swscale_template.c
@@ -1499,8 +1499,8 @@ static av_cold void RENAME(sws_init_swscale)(SwsContext *c)
enum AVPixelFormat dstFormat = c->dstFormat;
c->use_mmx_vfilter= 0;
- if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && dstFormat != AV_PIX_FMT_NV12
- && dstFormat != AV_PIX_FMT_NV21 && dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE
+ if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && !isSemiPlanarYUV(dstFormat)
+ && dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE
&& !(c->flags & SWS_BITEXACT)) {
if (c->flags & SWS_ACCURATE_RND) {
if (!(c->flags & SWS_FULL_CHR_H_INT)) {