summaryrefslogtreecommitdiff
path: root/libswscale
diff options
context:
space:
mode:
authorSergey Lavrushkin <dualfal@gmail.com>2018-08-03 18:06:50 +0300
committerMichael Niedermayer <michael@niedermayer.cc>2018-08-14 18:22:39 +0200
commit582bc5a348f5cd12b6ad3be4ecbee71bc082ea32 (patch)
tree8d53324a7a2b107bf4541740c07a6fcc4640f3b1 /libswscale
parent551a029a181abe2b7b6f16e9631423a12e9fcae9 (diff)
downloadffmpeg-582bc5a348f5cd12b6ad3be4ecbee71bc082ea32.tar.gz
libswscale: Adds conversions from/to float gray format.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libswscale')
-rw-r--r--libswscale/input.c38
-rw-r--r--libswscale/output.c105
-rw-r--r--libswscale/ppc/swscale_altivec.c1
-rw-r--r--libswscale/swscale_internal.h9
-rw-r--r--libswscale/swscale_unscaled.c54
-rw-r--r--libswscale/utils.c20
-rw-r--r--libswscale/x86/swscale_template.c3
7 files changed, 226 insertions, 4 deletions
diff --git a/libswscale/input.c b/libswscale/input.c
index 3fd3a5d81e..4099c19c2b 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -942,6 +942,30 @@ static av_always_inline void planar_rgb16_to_uv(uint8_t *_dstU, uint8_t *_dstV,
}
#undef rdpx
+static av_always_inline void grayf32ToY16_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1,
+ const uint8_t *unused2, int width, uint32_t *unused)
+{
+ int i;
+ const float *src = (const float *)_src;
+ uint16_t *dst = (uint16_t *)_dst;
+
+ for (i = 0; i < width; ++i){
+ dst[i] = av_clip_uint16(lrintf(65535.0f * src[i]));
+ }
+}
+
+static av_always_inline void grayf32ToY16_bswap_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1,
+ const uint8_t *unused2, int width, uint32_t *unused)
+{
+ int i;
+ const uint32_t *src = (const uint32_t *)_src;
+ uint16_t *dst = (uint16_t *)_dst;
+
+ for (i = 0; i < width; ++i){
+ dst[i] = av_clip_uint16(lrintf(65535.0f * av_int2float(av_bswap32(src[i]))));
+ }
+}
+
#define rgb9plus_planar_funcs_endian(nbits, endian_name, endian) \
static void planar_rgb##nbits##endian_name##_to_y(uint8_t *dst, const uint8_t *src[4], \
int w, int32_t *rgb2yuv) \
@@ -1538,6 +1562,20 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
case AV_PIX_FMT_P010BE:
c->lumToYV12 = p010BEToY_c;
break;
+ case AV_PIX_FMT_GRAYF32LE:
+#if HAVE_BIGENDIAN
+ c->lumToYV12 = grayf32ToY16_bswap_c;
+#else
+ c->lumToYV12 = grayf32ToY16_c;
+#endif
+ break;
+ case AV_PIX_FMT_GRAYF32BE:
+#if HAVE_BIGENDIAN
+ c->lumToYV12 = grayf32ToY16_c;
+#else
+ c->lumToYV12 = grayf32ToY16_bswap_c;
+#endif
+ break;
}
if (c->needAlpha) {
if (is16BPS(srcFormat) || isNBPS(srcFormat)) {
diff --git a/libswscale/output.c b/libswscale/output.c
index 0af2fffea4..de8637aa3b 100644
--- a/libswscale/output.c
+++ b/libswscale/output.c
@@ -208,6 +208,105 @@ static void yuv2p016cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterS
}
}
+static av_always_inline void
+yuv2plane1_float_c_template(const int32_t *src, float *dest, int dstW)
+{
+ static const int big_endian = HAVE_BIGENDIAN;
+ static const int shift = 3;
+ static const float float_mult = 1.0f / 65535.0f;
+ int i, val;
+ uint16_t val_uint;
+
+ for (i = 0; i < dstW; ++i){
+ val = src[i] + (1 << (shift - 1));
+ output_pixel(&val_uint, val, 0, uint);
+ dest[i] = float_mult * (float)val_uint;
+ }
+}
+
+static av_always_inline void
+yuv2plane1_float_bswap_c_template(const int32_t *src, uint32_t *dest, int dstW)
+{
+ static const int big_endian = HAVE_BIGENDIAN;
+ static const int shift = 3;
+ static const float float_mult = 1.0f / 65535.0f;
+ int i, val;
+ uint16_t val_uint;
+
+ for (i = 0; i < dstW; ++i){
+ val = src[i] + (1 << (shift - 1));
+ output_pixel(&val_uint, val, 0, uint);
+ dest[i] = av_bswap32(av_float2int(float_mult * (float)val_uint));
+ }
+}
+
+static av_always_inline void
+yuv2planeX_float_c_template(const int16_t *filter, int filterSize, const int32_t **src,
+ float *dest, int dstW)
+{
+ static const int big_endian = HAVE_BIGENDIAN;
+ static const int shift = 15;
+ static const float float_mult = 1.0f / 65535.0f;
+ int i, j, val;
+ uint16_t val_uint;
+
+ for (i = 0; i < dstW; ++i){
+ val = (1 << (shift - 1)) - 0x40000000;
+ for (j = 0; j < filterSize; ++j){
+ val += src[j][i] * (unsigned)filter[j];
+ }
+ output_pixel(&val_uint, val, 0x8000, int);
+ dest[i] = float_mult * (float)val_uint;
+ }
+}
+
+static av_always_inline void
+yuv2planeX_float_bswap_c_template(const int16_t *filter, int filterSize, const int32_t **src,
+ uint32_t *dest, int dstW)
+{
+ static const int big_endian = HAVE_BIGENDIAN;
+ static const int shift = 15;
+ static const float float_mult = 1.0f / 65535.0f;
+ int i, j, val;
+ uint16_t val_uint;
+
+ for (i = 0; i < dstW; ++i){
+ val = (1 << (shift - 1)) - 0x40000000;
+ for (j = 0; j < filterSize; ++j){
+ val += src[j][i] * (unsigned)filter[j];
+ }
+ output_pixel(&val_uint, val, 0x8000, int);
+ dest[i] = av_bswap32(av_float2int(float_mult * (float)val_uint));
+ }
+}
+
+#define yuv2plane1_float(template, dest_type, BE_LE) \
+static void yuv2plane1_float ## BE_LE ## _c(const int16_t *src, uint8_t *dest, int dstW, \
+ const uint8_t *dither, int offset) \
+{ \
+ template((const int32_t *)src, (dest_type *)dest, dstW); \
+}
+
+#define yuv2planeX_float(template, dest_type, BE_LE) \
+static void yuv2planeX_float ## BE_LE ## _c(const int16_t *filter, int filterSize, \
+ const int16_t **src, uint8_t *dest, int dstW, \
+ const uint8_t *dither, int offset) \
+{ \
+ template(filter, filterSize, (const int32_t **)src, (dest_type *)dest, dstW); \
+}
+
+#if HAVE_BIGENDIAN
+yuv2plane1_float(yuv2plane1_float_c_template, float, BE)
+yuv2plane1_float(yuv2plane1_float_bswap_c_template, uint32_t, LE)
+yuv2planeX_float(yuv2planeX_float_c_template, float, BE)
+yuv2planeX_float(yuv2planeX_float_bswap_c_template, uint32_t, LE)
+#else
+yuv2plane1_float(yuv2plane1_float_c_template, float, LE)
+yuv2plane1_float(yuv2plane1_float_bswap_c_template, uint32_t, BE)
+yuv2planeX_float(yuv2planeX_float_c_template, float, LE)
+yuv2planeX_float(yuv2planeX_float_bswap_c_template, uint32_t, BE)
+#endif
+
#undef output_pixel
#define output_pixel(pos, val) \
@@ -2303,6 +2402,12 @@ av_cold void ff_sws_init_output_funcs(SwsContext *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;
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index 9438a63ff2..2fb2337769 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -339,6 +339,7 @@ av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
}
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 &&
!c->needAlpha) {
c->yuv2planeX = yuv2planeX_altivec;
}
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 1703856ab2..4fa59386a6 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -336,6 +336,8 @@ typedef struct SwsContext {
uint32_t pal_yuv[256];
uint32_t pal_rgb[256];
+ float uint2float_lut[256];
+
/**
* @name Scaled horizontal lines ring buffer.
* The horizontal scaler keeps just enough scaled lines in a ring buffer
@@ -764,6 +766,13 @@ static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
pix_fmt == AV_PIX_FMT_MONOBLACK || pix_fmt == AV_PIX_FMT_MONOWHITE;
}
+static av_always_inline int isFloat(enum AVPixelFormat pix_fmt)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+ av_assert0(desc);
+ return desc->flags & AV_PIX_FMT_FLAG_FLOAT;
+}
+
static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index 6480070cbf..973fa4875f 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -1467,6 +1467,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,
@@ -1899,6 +1939,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 */
@@ -1925,13 +1975,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 &&
- !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat)))
+ !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat))))
{
if (isPacked(c->srcFormat))
c->swscale = packedCopyWrapper;
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 61b47182f8..5e56371180 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -258,6 +258,8 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
[AV_PIX_FMT_P010BE] = { 1, 1 },
[AV_PIX_FMT_P016LE] = { 1, 1 },
[AV_PIX_FMT_P016BE] = { 1, 1 },
+ [AV_PIX_FMT_GRAYF32LE] = { 1, 1 },
+ [AV_PIX_FMT_GRAYF32BE] = { 1, 1 },
};
int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
@@ -1173,6 +1175,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
const AVPixFmtDescriptor *desc_dst;
int ret = 0;
enum AVPixelFormat tmpFmt;
+ static const float float_mult = 1.0f / 255.0f;
cpu_flags = av_get_cpu_flags();
flags = c->flags;
@@ -1537,6 +1540,19 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
}
}
+ if (unscaled && c->srcBpc == 8 && dstFormat == AV_PIX_FMT_GRAYF32){
+ for (i = 0; i < 256; ++i){
+ c->uint2float_lut[i] = (float)i * float_mult;
+ }
+ }
+
+ // float will be converted to uint16_t
+ if ((srcFormat == AV_PIX_FMT_GRAYF32BE || srcFormat == AV_PIX_FMT_GRAYF32LE) &&
+ (!unscaled || unscaled && dstFormat != srcFormat && (srcFormat != AV_PIX_FMT_GRAYF32 ||
+ dstFormat != AV_PIX_FMT_GRAY8))){
+ c->srcBpc = 16;
+ }
+
if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) {
enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat);
@@ -1793,7 +1809,9 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
/* unscaled special cases */
if (unscaled && !usesHFilter && !usesVFilter &&
- (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {
+ (c->srcRange == c->dstRange || isAnyRGB(dstFormat) ||
+ srcFormat == AV_PIX_FMT_GRAYF32 && dstFormat == AV_PIX_FMT_GRAY8 ||
+ srcFormat == AV_PIX_FMT_GRAY8 && dstFormat == AV_PIX_FMT_GRAYF32)) {
ff_get_unscaled_swscale(c);
if (c->swscale) {
diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c
index b8bdcd4d03..7c30470679 100644
--- a/libswscale/x86/swscale_template.c
+++ b/libswscale/x86/swscale_template.c
@@ -1500,7 +1500,8 @@ static av_cold void RENAME(sws_init_swscale)(SwsContext *c)
c->use_mmx_vfilter= 0;
if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && dstFormat != AV_PIX_FMT_NV12
- && dstFormat != AV_PIX_FMT_NV21 && !(c->flags & SWS_BITEXACT)) {
+ && dstFormat != AV_PIX_FMT_NV21 && 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)) {
switch (c->dstFormat) {