Skip to content

Commit f764720

Browse files
committed
1 parent 06c4785 commit f764720

4 files changed

Lines changed: 51 additions & 4 deletions

File tree

‎src/modules/gdk/producer_pixbuf.c‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ struct producer_pixbuf_s
7575
mlt_cache_item pixbuf_cache;
7676
GdkPixbuf *pixbuf;
7777
mlt_image_format format;
78+
int full_range;
79+
int colorspace;
7880
};
7981

8082
static void load_filenames(producer_pixbuf self, mlt_properties producer_properties);
@@ -583,10 +585,18 @@ static void refresh_image(
583585
self->pixbuf_idx,
584586
width);
585587

588+
// Y'CbCr formats are ambiguous without a color range, so a cached image must be
589+
// regenerated if the requested range changes even when the format does not.
590+
int dst_full_range = mlt_properties_get_int(properties, "full_range");
591+
int format_is_yuv = format == mlt_image_yuv422 || format == mlt_image_yuv420p
592+
|| format == mlt_image_yuv422p16 || format == mlt_image_yuv420p10
593+
|| format == mlt_image_yuv444p10;
594+
586595
// If we have a pixbuf and we need an image
587596
if (self->pixbuf
588597
&& (!self->image
589-
|| (format != mlt_image_none && format != mlt_image_movit && format != self->format))) {
598+
|| (format != mlt_image_none && format != mlt_image_movit && format != self->format)
599+
|| (format_is_yuv && format == self->format && dst_full_range != self->full_range))) {
590600
char *interps = mlt_properties_get(properties, "consumer.rescale");
591601
if (interps)
592602
interps = strdup(interps);
@@ -615,6 +625,9 @@ static void refresh_image(
615625
int src_stride = gdk_pixbuf_get_rowstride(pixbuf);
616626
int dst_stride = self->width * (has_alpha ? 4 : 3);
617627
self->format = has_alpha ? mlt_image_rgba : mlt_image_rgb;
628+
// RGB(A) is inherently full range.
629+
self->full_range = 1;
630+
self->colorspace = mlt_colorspace_rgb;
618631
int image_size = mlt_image_format_size(self->format, width, height, NULL);
619632
self->image = mlt_pool_alloc(image_size);
620633
self->alpha = NULL;
@@ -645,6 +658,13 @@ static void refresh_image(
645658
mlt_properties_set_int(properties, "format", self->format);
646659

647660
if (!mlt_frame_convert_image(frame, &self->image, &self->format, format)) {
661+
self->full_range = self->format == mlt_image_rgb
662+
|| self->format == mlt_image_rgba
663+
|| self->format == mlt_image_rgba64
664+
? 1
665+
: dst_full_range;
666+
// The converter records the colorspace it produced.
667+
self->colorspace = mlt_properties_get_int(properties, "colorspace");
648668
buffer = self->image;
649669
image_size
650670
= mlt_image_format_size(self->format, self->width, self->height, NULL);
@@ -719,13 +739,19 @@ static int producer_get_image(mlt_frame frame,
719739
self->alpha_cache = mlt_service_cache_get(MLT_PRODUCER_SERVICE(producer), "pixbuf.alpha");
720740
self->alpha = mlt_cache_item_data(self->alpha_cache, NULL);
721741

742+
const char *dst_color_range = mlt_properties_get(properties, "consumer.color_range");
743+
mlt_properties_set_int(properties, "full_range", mlt_image_full_range(dst_color_range));
744+
722745
// Refresh the image
723746
refresh_image(self, frame, *format, *width, *height);
724747

725748
// Get width and height (may have changed during the refresh)
726749
*width = self->width;
727750
*height = self->height;
728751
*format = self->format;
752+
// A reused image may hold a different color range than the consumer asked for.
753+
mlt_properties_set_int(properties, "full_range", self->full_range);
754+
mlt_properties_set_int(properties, "colorspace", self->colorspace);
729755

730756
// NB: Cloning is necessary with this producer (due to processing of images ahead of use)
731757
// The fault is not in the design of mlt, but in the implementation of the pixbuf producer...

‎src/modules/qt/producer_qimage.c‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,17 @@ static int producer_get_image(mlt_frame frame,
232232
self->current_alpha = mlt_cache_item_data(self->alpha_cache, &self->alpha_size);
233233

234234
const char *dst_color_range = mlt_properties_get(properties, "consumer.color_range");
235-
if (mlt_image_full_range(dst_color_range))
236-
mlt_properties_set_int(properties, "full_range", 1);
235+
mlt_properties_set_int(properties, "full_range", mlt_image_full_range(dst_color_range));
237236
}
238237
refresh_image(self, frame, *format, *width, *height, enable_caching);
239238

240239
// Get width and height (may have changed during the refresh)
241240
*width = mlt_properties_get_int(properties, "width");
242241
*height = mlt_properties_get_int(properties, "height");
243242
*format = self->format;
243+
// A reused image may hold a different color range than the consumer asked for.
244+
mlt_properties_set_int(properties, "full_range", self->full_range);
245+
mlt_properties_set_int(properties, "colorspace", self->colorspace);
244246

245247
// NB: Cloning is necessary with this producer (due to processing of images ahead of use)
246248
// The fault is not in the design of mlt, but in the implementation of the qimage producer...

‎src/modules/qt/qimage_wrapper.cpp‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,18 @@ void refresh_image(producer_qimage self,
223223
|| height != self->current_height)
224224
self->current_image = NULL;
225225

226+
// Y'CbCr formats are ambiguous without a color range, so a cached image must be
227+
// regenerated if the requested range changes even when the format does not.
228+
int dst_full_range = mlt_properties_get_int(properties, "full_range");
229+
bool format_is_yuv = format == mlt_image_yuv422 || format == mlt_image_yuv420p
230+
|| format == mlt_image_yuv422p16 || format == mlt_image_yuv420p10
231+
|| format == mlt_image_yuv444p10;
232+
226233
// If we have a qimage and need a new scaled image
227234
if (self->qimage
228235
&& (!self->current_image
229-
|| (format != mlt_image_none && format != mlt_image_movit && format != self->format))) {
236+
|| (format != mlt_image_none && format != mlt_image_movit && format != self->format)
237+
|| (format_is_yuv && format == self->format && dst_full_range != self->full_range))) {
230238
QString interps = mlt_properties_get(properties, "consumer.rescale");
231239
bool interp = (interps != "nearest") && (interps != "none");
232240
QImage *qimage = static_cast<QImage *>(self->qimage);
@@ -265,6 +273,9 @@ void refresh_image(producer_qimage self,
265273

266274
// Copy the image
267275
int image_size;
276+
// RGB(A) is inherently full range.
277+
self->full_range = 1;
278+
self->colorspace = mlt_colorspace_rgb;
268279
if (has_alpha) {
269280
self->format = mlt_image_rgba;
270281
scaled = scaled.convertToFormat(QImage::Format_RGBA8888);
@@ -298,6 +309,12 @@ void refresh_image(producer_qimage self,
298309
self->current_width = width;
299310
self->current_height = height;
300311
self->format = format;
312+
self->full_range = format == mlt_image_rgb || format == mlt_image_rgba
313+
|| format == mlt_image_rgba64
314+
? 1
315+
: dst_full_range;
316+
// The converter records the colorspace it produced.
317+
self->colorspace = mlt_properties_get_int(properties, "colorspace");
301318
image_size = mlt_image_format_size(format, width, height, NULL);
302319
self->current_image = (uint8_t *) mlt_pool_alloc(image_size);
303320
memcpy(self->current_image, buffer, image_size);

‎src/modules/qt/qimage_wrapper.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ struct producer_qimage_s
4545
mlt_cache_item qimage_cache;
4646
void *qimage;
4747
mlt_image_format format;
48+
int full_range;
49+
int colorspace;
4850
};
4951

5052
typedef struct producer_qimage_s *producer_qimage;

0 commit comments

Comments
 (0)