switch( format )
{
case mlt_image_rgb24:
+ case mlt_image_rgb24_full:
value = PIX_FMT_RGB24;
break;
case mlt_image_rgb24a:
case mlt_image_opengl:
+ case mlt_image_rgb24a_full:
value = PIX_FMT_RGBA;
break;
case mlt_image_yuv422:
+ case mlt_image_yuv422_709:
value = PIX_FMT_YUYV422;
break;
case mlt_image_yuv420p:
return value;
}
-static void av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height )
+enum luma_scale {
+ LUMA_SCALE_AUTO = 0,
+ LUMA_SCALE_NONE,
+ LUMA_SCALE_OUT,
+ LUMA_SCALE_IN
+};
+
+static void set_luma_transfer( struct SwsContext *context, int is_709, enum luma_scale scale )
+{
+ int *coefficients;
+ int range_in, range_out;
+ int brightness, contrast, saturation;
+
+ if ( sws_getColorspaceDetails( context, &coefficients, &range_in, &coefficients, &range_out,
+ &brightness, &contrast, &saturation ) != -1 )
+ {
+ // Don't change these from defaults unless explicitly told to.
+ switch ( scale )
+ {
+ case LUMA_SCALE_NONE:
+ range_in = range_out = 1;
+ break;
+ case LUMA_SCALE_OUT:
+ range_in = 0;
+ range_out = 1;
+ break;
+ case LUMA_SCALE_IN:
+ range_in = 1;
+ range_out = 0;
+ break;
+ default:
+ break;
+ }
+ if ( is_709 )
+ coefficients = sws_getCoefficients( SWS_CS_ITU709 );
+ sws_setColorspaceDetails( context, coefficients, range_in, coefficients, range_out,
+ brightness, contrast, saturation );
+ }
+}
+
+static void av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt,
+ int width, int height, int is_709, int is_full )
{
AVPicture input;
AVPicture output;
+ int flags = SWS_BILINEAR | SWS_ACCURATE_RND;
+
+ if ( out_fmt == PIX_FMT_YUYV422 )
+ flags |= SWS_FULL_CHR_H_INP;
+ else
+ flags |= SWS_FULL_CHR_H_INT;
+#ifdef USE_MMX
+ flags |= SWS_CPU_CAPS_MMX;
+#endif
+#ifdef USE_SSE
+ flags |= SWS_CPU_CAPS_MMX2;
+#endif
+
avpicture_fill( &input, in, in_fmt, width, height );
avpicture_fill( &output, out, out_fmt, width, height );
#ifdef SWSCALE
struct SwsContext *context = sws_getContext( width, height, in_fmt,
- width, height, out_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
+ width, height, out_fmt, flags, NULL, NULL, NULL);
+ set_luma_transfer( context, is_709, is_full );
sws_scale( context, input.data, input.linesize, 0, height,
output.data, output.linesize);
sws_freeContext( context );
if ( *format != output_format )
{
- mlt_log_debug( NULL, "[filter avcolor_space] %s -> %s\n",
- mlt_image_format_name( *format ), mlt_image_format_name( output_format ) );
+ mlt_log_debug( NULL, "[filter avcolor_space] %s -> %s @ %dx%d\n",
+ mlt_image_format_name( *format ), mlt_image_format_name( output_format ),
+ width, height );
int in_fmt = convert_mlt_to_av_cs( *format );
int out_fmt = convert_mlt_to_av_cs( output_format );
}
// Update the output
- av_convert_image( output, *image, out_fmt, in_fmt, width, height );
+ int is_709 = output_format == mlt_image_yuv422 && width * height > 750000;
+ enum luma_scale luma = LUMA_SCALE_AUTO;
+ av_convert_image( output, *image, out_fmt, in_fmt, width, height, is_709, luma );
*image = output;
*format = output_format;
mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL );
mlt_properties_set_int( properties, "format", output_format );
+
+ if ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )
+ {
+ register int len = width * height;
+ int alpha_size = 0;
+ uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
+ mlt_properties_get_data( properties, "alpha", &alpha_size );
+
+ if ( alpha && alpha_size >= len )
+ {
+ // Merge the alpha mask from into the RGBA image using Duff's Device
+ register uint8_t *s = alpha;
+ register uint8_t *d = *image + 3; // start on the alpha component
+ register int n = ( len + 7 ) / 8;
+
+ switch ( len % 8 )
+ {
+ case 0: do { *d = *s++; d += 4;
+ case 7: *d = *s++; d += 4;
+ case 6: *d = *s++; d += 4;
+ case 5: *d = *s++; d += 4;
+ case 4: *d = *s++; d += 4;
+ case 3: *d = *s++; d += 4;
+ case 2: *d = *s++; d += 4;
+ case 1: *d = *s++; d += 4;
+ }
+ while ( --n > 0 );
+ }
+ }
+ }
}
return error;
}
mlt_filter filter_avcolour_space_init( void *arg )
{
+#ifdef SWSCALE
+#if (LIBSWSCALE_VERSION_INT >= ((0<<16)+(7<<8)+2))
// Test to see if swscale accepts the arg as resolution
if ( arg )
{
else
return NULL;
}
-
+#else
+ return NULL;
+#endif
+#endif
mlt_filter this = mlt_filter_new( );
if ( this != NULL )
this->process = filter_process;