@@ -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
8082static 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...
0 commit comments