@@ -59,8 +59,8 @@ static const AVOption swscale_options[] = {
{ "dsth", "destination height", OFFSET(dstH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE },
{ "src_format", "source format", OFFSET(srcFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT }, 0, INT_MAX, VE },
{ "dst_format", "destination format", OFFSET(dstFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT }, 0, INT_MAX, VE },
- { "src_range", "source is full range", OFFSET(srcRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE },
- { "dst_range", "destination is full range", OFFSET(dstRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE },
+ { "src_range", "source is full range", OFFSET(exported_srcRange), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE },
+ { "dst_range", "destination is full range", OFFSET(exported_dstRange), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE },
{ "param0", "scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE },
{ "param1", "scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE },
@@ -625,6 +625,9 @@ typedef struct SwsContext {
SwsDither dither;
SwsAlphaBlend alphablend;
+
+ int exported_srcRange;
+ int exported_dstRange;
} SwsContext;
//FIXME check init (where 0)
@@ -864,6 +864,69 @@ static void fill_xyztables(struct SwsContext *c)
}
}
+static int handle_jpeg(enum AVPixelFormat *format)
+{
+ switch (*format) {
+ case AV_PIX_FMT_YUVJ420P:
+ *format = AV_PIX_FMT_YUV420P;
+ return 1;
+ case AV_PIX_FMT_YUVJ411P:
+ *format = AV_PIX_FMT_YUV411P;
+ return 1;
+ case AV_PIX_FMT_YUVJ422P:
+ *format = AV_PIX_FMT_YUV422P;
+ return 1;
+ case AV_PIX_FMT_YUVJ444P:
+ *format = AV_PIX_FMT_YUV444P;
+ return 1;
+ case AV_PIX_FMT_YUVJ440P:
+ *format = AV_PIX_FMT_YUV440P;
+ return 1;
+ case AV_PIX_FMT_GRAY8:
+ case AV_PIX_FMT_YA8:
+ case AV_PIX_FMT_GRAY9LE:
+ case AV_PIX_FMT_GRAY9BE:
+ case AV_PIX_FMT_GRAY10LE:
+ case AV_PIX_FMT_GRAY10BE:
+ case AV_PIX_FMT_GRAY12LE:
+ case AV_PIX_FMT_GRAY12BE:
+ case AV_PIX_FMT_GRAY14LE:
+ case AV_PIX_FMT_GRAY14BE:
+ case AV_PIX_FMT_GRAY16LE:
+ case AV_PIX_FMT_GRAY16BE:
+ case AV_PIX_FMT_YA16BE:
+ case AV_PIX_FMT_YA16LE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int check_format_range(SwsContext *c, enum AVPixelFormat *format,
+ int range, const char *descriptor)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*format);
+ int default_range = handle_jpeg(format);
+ av_assert0(desc);
+
+ if (isAnyRGB(*format) && !range) {
+ // first, handle the special case of limited range RGB
+ av_log(c, AV_LOG_WARNING,
+ "%s range set to limited for %s, unsupported! "
+ "Overriding to full range.\n",
+ descriptor ? descriptor : "Color", desc->name);
+
+ return 1;
+ }
+
+
+ if (range != -1)
+ // for YCbCr and gray, we return the value if set
+ return range;
+
+ return isAnyRGB(*format) ? 1 : default_range;
+}
+
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
int srcRange, const int table[4], int dstRange,
int brightness, int contrast, int saturation)
@@ -876,10 +939,23 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
desc_dst = av_pix_fmt_desc_get(c->dstFormat);
desc_src = av_pix_fmt_desc_get(c->srcFormat);
- if(!isYUV(c->dstFormat) && !isGray(c->dstFormat))
- dstRange = 0;
- if(!isYUV(c->srcFormat) && !isGray(c->srcFormat))
- srcRange = 0;
+ if (dstRange == -1) {
+ dstRange = c->dstRange;
+ } else {
+ c->exported_dstRange = check_format_range(c, &c->dstFormat,
+ dstRange,
+ "Destination");
+ dstRange = isAnyRGB(c->dstFormat) ? 0 : c->exported_dstRange;
+ }
+
+ if (srcRange == -1) {
+ srcRange = c->srcRange;
+ } else {
+ c->exported_srcRange = check_format_range(c, &c->srcFormat,
+ srcRange,
+ "Source");
+ srcRange = isAnyRGB(c->srcFormat) ? 0 : c->exported_srcRange;
+ }
if (c->srcRange != srcRange ||
c->dstRange != dstRange ||
@@ -911,7 +987,7 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
if (c->cascaded_context[c->cascaded_mainindex])
- return sws_setColorspaceDetails(c->cascaded_context[c->cascaded_mainindex],inv_table, srcRange,table, dstRange, brightness, contrast, saturation);
+ return sws_setColorspaceDetails(c->cascaded_context[c->cascaded_mainindex],inv_table, c->exported_srcRange,table, c->exported_dstRange, brightness, contrast, saturation);
if (!need_reinit)
return 0;
@@ -968,7 +1044,8 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
return ret;
//we set both src and dst depending on that the RGB side will be ignored
sws_setColorspaceDetails(c->cascaded_context[0], inv_table,
- srcRange, table, dstRange,
+ c->exported_srcRange, table,
+ c->exported_dstRange,
brightness, contrast, saturation);
c->cascaded_context[1] = sws_getContext(tmp_width, tmp_height, tmp_format,
@@ -977,7 +1054,8 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
if (!c->cascaded_context[1])
return -1;
sws_setColorspaceDetails(c->cascaded_context[1], inv_table,
- srcRange, table, dstRange,
+ c->exported_srcRange, table,
+ c->exported_dstRange,
0, 1 << 16, 1 << 16);
return 0;
}
@@ -1008,8 +1086,8 @@ int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
*inv_table = c->srcColorspaceTable;
*table = c->dstColorspaceTable;
- *srcRange = c->srcRange;
- *dstRange = c->dstRange;
+ *srcRange = c->exported_srcRange;
+ *dstRange = c->exported_dstRange;
*brightness = c->brightness;
*contrast = c->contrast;
*saturation = c->saturation;
@@ -1017,44 +1095,6 @@ int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
return 0;
}
-static int handle_jpeg(enum AVPixelFormat *format)
-{
- switch (*format) {
- case AV_PIX_FMT_YUVJ420P:
- *format = AV_PIX_FMT_YUV420P;
- return 1;
- case AV_PIX_FMT_YUVJ411P:
- *format = AV_PIX_FMT_YUV411P;
- return 1;
- case AV_PIX_FMT_YUVJ422P:
- *format = AV_PIX_FMT_YUV422P;
- return 1;
- case AV_PIX_FMT_YUVJ444P:
- *format = AV_PIX_FMT_YUV444P;
- return 1;
- case AV_PIX_FMT_YUVJ440P:
- *format = AV_PIX_FMT_YUV440P;
- return 1;
- case AV_PIX_FMT_GRAY8:
- case AV_PIX_FMT_YA8:
- case AV_PIX_FMT_GRAY9LE:
- case AV_PIX_FMT_GRAY9BE:
- case AV_PIX_FMT_GRAY10LE:
- case AV_PIX_FMT_GRAY10BE:
- case AV_PIX_FMT_GRAY12LE:
- case AV_PIX_FMT_GRAY12BE:
- case AV_PIX_FMT_GRAY14LE:
- case AV_PIX_FMT_GRAY14BE:
- case AV_PIX_FMT_GRAY16LE:
- case AV_PIX_FMT_GRAY16BE:
- case AV_PIX_FMT_YA16BE:
- case AV_PIX_FMT_YA16LE:
- return 1;
- default:
- return 0;
- }
-}
-
static int handle_0alpha(enum AVPixelFormat *format)
{
switch (*format) {
@@ -1200,16 +1240,28 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
unscaled = (srcW == dstW && srcH == dstH);
- c->srcRange |= handle_jpeg(&c->srcFormat);
- c->dstRange |= handle_jpeg(&c->dstFormat);
+ av_log(c, AV_LOG_VERBOSE, "Initial configured range values: src: %d, dst: %d\n",
+ c->exported_srcRange, c->exported_dstRange);
+
+ c->exported_srcRange = check_format_range(c, &c->srcFormat,
+ c->exported_srcRange,
+ "Source");
+ c->exported_dstRange = check_format_range(c, &c->dstFormat,
+ c->exported_dstRange,
+ "Destination");
+
+ // convert exported range to internal
+ c->srcRange = isAnyRGB(srcFormat) ? 0 : c->exported_srcRange;
+ c->dstRange = isAnyRGB(dstFormat) ? 0 : c->exported_dstRange;
if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat)
av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
if (!c->contrast && !c->saturation && !c->dstFormatBpp)
- sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
+ sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
+ c->exported_srcRange,
ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
- c->dstRange, 0, 1 << 16, 1 << 16);
+ c->exported_dstRange, 0, 1 << 16, 1 << 16);
handle_formats(c);
srcFormat = c->srcFormat;