1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
From adc5a2284b3a1073cb364c5f07d1d7c97e94c937 Mon Sep 17 00:00:00 2001
From: Dan Dennedy <dan@dennedy.org>
Date: Fri, 30 Nov 2018 15:26:15 -0800
Subject: [PATCH] Fix color accuracy of RGB->YUV conversion.
Fixes https://github.com/mltframework/shotcut/issues/674
---
src/modules/avformat/common.c | 2 ++
src/modules/avformat/common.h | 1 +
src/modules/avformat/consumer_avformat.c | 7 +------
src/modules/avformat/filter_avcolour_space.c | 7 +------
src/modules/avformat/filter_swscale.c | 12 ++++--------
src/modules/avformat/producer_avformat.c | 12 ++++++------
6 files changed, 15 insertions(+), 26 deletions(-)
diff --git a/src/modules/avformat/common.c b/src/modules/avformat/common.c
index 2b1f1fd5d..dca9dbaee 100644
--- a/src/modules/avformat/common.c
+++ b/src/modules/avformat/common.c
@@ -22,6 +22,8 @@
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
+int mlt_default_sws_flags = SWS_BICUBIC | SWS_FULL_CHR_H_INP | SWS_FULL_CHR_H_INT | SWS_ACCURATE_RND;
+
int mlt_to_av_sample_format( mlt_audio_format format )
{
switch( format )
diff --git a/src/modules/avformat/common.h b/src/modules/avformat/common.h
index 54df63e93..ce0f0f079 100644
--- a/src/modules/avformat/common.h
+++ b/src/modules/avformat/common.h
@@ -29,5 +29,6 @@ mlt_channel_layout av_channel_layout_to_mlt( int64_t layout );
mlt_channel_layout get_channel_layout_or_default( const char* name, int channels );
int set_luma_transfer( struct SwsContext *context, int src_colorspace,
int dst_colorspace, int src_full_range, int dst_full_range );
+extern int mlt_default_sws_flags;
#endif // COMMON_H
diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c
index eab96271f..1e445ef76 100644
--- a/src/modules/avformat/consumer_avformat.c
+++ b/src/modules/avformat/consumer_avformat.c
@@ -1956,12 +1956,7 @@ static void *consumer_thread( void *arg )
mlt_image_format_planes( img_fmt, width, height, image, video_avframe.data, video_avframe.linesize );
// Do the colour space conversion
- int flags = SWS_BICUBIC | SWS_ACCURATE_RND;
- if ( pix_fmt == AV_PIX_FMT_YUYV422 || pix_fmt == AV_PIX_FMT_YUV422P16LE )
- flags |= SWS_FULL_CHR_H_INP;
- else
- flags |= SWS_FULL_CHR_H_INT;
-
+ int flags = mlt_default_sws_flags;
struct SwsContext *context = sws_getContext( width, height, pick_pix_fmt( img_fmt ),
width, height, pix_fmt, flags, NULL, NULL, NULL);
int src_colorspace = mlt_properties_get_int( frame_properties, "colorspace" );
diff --git a/src/modules/avformat/filter_avcolour_space.c b/src/modules/avformat/filter_avcolour_space.c
index f25cf092b..89ee6b522 100644
--- a/src/modules/avformat/filter_avcolour_space.c
+++ b/src/modules/avformat/filter_avcolour_space.c
@@ -84,14 +84,9 @@ static int av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt,
int in_stride[4];
uint8_t *out_data[4];
int out_stride[4];
- int flags = SWS_BICUBIC | SWS_ACCURATE_RND;
+ int flags = mlt_default_sws_flags;
int error = -1;
- if ( out_fmt == AV_PIX_FMT_YUYV422 || out_fmt == AV_PIX_FMT_YUV422P16LE )
- flags |= SWS_FULL_CHR_H_INP;
- else
- flags |= SWS_FULL_CHR_H_INT;
-
if ( in_fmt == AV_PIX_FMT_YUV422P16LE )
mlt_image_format_planes(mlt_image_yuv422p16, width, height, in, in_data, in_stride);
else
diff --git a/src/modules/avformat/filter_swscale.c b/src/modules/avformat/filter_swscale.c
index 475036a6f..52c165f9f 100644
--- a/src/modules/avformat/filter_swscale.c
+++ b/src/modules/avformat/filter_swscale.c
@@ -1,6 +1,6 @@
/*
* filter_swscale.c -- image scaling filter
- * Copyright (C) 2008-2017 Meltytech, LLC
+ * Copyright (C) 2008-2018 Meltytech, LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -88,23 +88,19 @@ static int filter_scale( mlt_frame frame, uint8_t **image, mlt_image_format *for
interp = SWS_LANCZOS;
else if ( strcmp( interps, "spline" ) == 0 )
interp = SWS_SPLINE;
- interp |= SWS_ACCURATE_RND;
+
+ // Set swscale flags to get good quality
+ interp |= SWS_FULL_CHR_H_INP | SWS_FULL_CHR_H_INT | SWS_ACCURATE_RND;
// Determine the output image size.
int out_size = mlt_image_format_size( *format, owidth, oheight, NULL );
- // Set swscale flags to get good quality
switch ( *format )
{
case mlt_image_yuv422:
- interp |= SWS_FULL_CHR_H_INP;
- break;
case mlt_image_rgb24:
- interp |= SWS_FULL_CHR_H_INT;
- break;
case mlt_image_rgb24a:
case mlt_image_opengl:
- interp |= SWS_FULL_CHR_H_INT;
break;
default:
// XXX: we only know how to rescale packed formats
diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c
index 9b96b4e5c..d24ca41e7 100644
--- a/src/modules/avformat/producer_avformat.c
+++ b/src/modules/avformat/producer_avformat.c
@@ -1281,7 +1281,7 @@ static int sliced_h_pix_fmt_conv_proc( int id, int idx, int jobs, void* cookie )
av_opt_set_int( sws, "dstw", slice_w, 0 );
av_opt_set_int( sws, "dsth", h, 0 );
av_opt_set_int( sws, "dst_format", ctx->dst_format, 0 );
- av_opt_set_int( sws, "sws_flags", ctx->flags | SWS_FULL_CHR_H_INP, 0 );
+ av_opt_set_int( sws, "sws_flags", ctx->flags, 0 );
av_opt_set_int( sws, "src_h_chr_pos", -513, 0 );
av_opt_set_int( sws, "src_v_chr_pos", src_v_chr_pos, 0 );
@@ -1338,7 +1338,7 @@ static int sliced_h_pix_fmt_conv_proc( int id, int idx, int jobs, void* cookie )
static int convert_image( producer_avformat self, AVFrame *frame, uint8_t *buffer, int pix_fmt,
mlt_image_format *format, int width, int height, uint8_t **alpha )
{
- int flags = SWS_BICUBIC | SWS_ACCURATE_RND;
+ int flags = mlt_default_sws_flags;
mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( self->parent ) );
int result = self->yuv_colorspace;
@@ -1400,7 +1400,7 @@ static int convert_image( producer_avformat self, AVFrame *frame, uint8_t *buffe
else if ( *format == mlt_image_rgb24 )
{
struct SwsContext *context = sws_getContext( width, height, src_pix_fmt,
- width, height, AV_PIX_FMT_RGB24, flags | SWS_FULL_CHR_H_INT, NULL, NULL, NULL);
+ width, height, AV_PIX_FMT_RGB24, flags, NULL, NULL, NULL);
uint8_t *out_data[4];
int out_stride[4];
av_image_fill_arrays(out_data, out_stride, buffer, AV_PIX_FMT_RGB24, width, height, IMAGE_ALIGN);
@@ -1413,7 +1413,7 @@ static int convert_image( producer_avformat self, AVFrame *frame, uint8_t *buffe
else if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl )
{
struct SwsContext *context = sws_getContext( width, height, src_pix_fmt,
- width, height, AV_PIX_FMT_RGBA, flags | SWS_FULL_CHR_H_INT, NULL, NULL, NULL);
+ width, height, AV_PIX_FMT_RGBA, flags, NULL, NULL, NULL);
uint8_t *out_data[4];
int out_stride[4];
av_image_fill_arrays(out_data, out_stride, buffer, AV_PIX_FMT_RGBA, width, height, IMAGE_ALIGN);
@@ -1475,10 +1475,10 @@ static int convert_image( producer_avformat self, AVFrame *frame, uint8_t *buffe
{
#if defined(FFUDIV) && (LIBAVFORMAT_VERSION_INT >= ((55<<16)+(48<<8)+100))
struct SwsContext *context = sws_getContext( width, height, src_pix_fmt,
- width, height, AV_PIX_FMT_YUYV422, flags | SWS_FULL_CHR_H_INP, NULL, NULL, NULL);
+ width, height, AV_PIX_FMT_YUYV422, flags, NULL, NULL, NULL);
#else
struct SwsContext *context = sws_getContext( width, height, pix_fmt,
- width, height, AV_PIX_FMT_YUYV422, flags | SWS_FULL_CHR_H_INP, NULL, NULL, NULL);
+ width, height, AV_PIX_FMT_YUYV422, flags, NULL, NULL, NULL);
#endif
AVPicture output;
avpicture_fill( &output, buffer, AV_PIX_FMT_YUYV422, width, height );
|