X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Ffilter_avcolour_space.c;h=cce62c5ea2021e62b11db5f93290c1c2136c54f2;hb=4fd6c14958ac5bd739c8d2b66b86cbf99ae68c23;hp=b8685dcf20d01c7501cf0581e9751bf07f066977;hpb=a8222a55a6aa905237c9bb53268b1de5f09e62df;p=mlt diff --git a/src/modules/avformat/filter_avcolour_space.c b/src/modules/avformat/filter_avcolour_space.c index b8685dcf..cce62c5e 100644 --- a/src/modules/avformat/filter_avcolour_space.c +++ b/src/modules/avformat/filter_avcolour_space.c @@ -1,6 +1,6 @@ /* * filter_avcolour_space.c -- Colour space filter - * Copyright (C) 2004-2005 Ushodaya Enterprises Limited + * Copyright (C) 2004-2014 Ushodaya Enterprises Limited * Author: Charles Yates * * This library is free software; you can redistribute it and/or @@ -22,16 +22,11 @@ #include #include #include +#include // ffmpeg Header files #include -#ifdef SWSCALE #include -#endif - -#if LIBAVUTIL_VERSION_INT < (50<<16) -#define PIX_FMT_YUYV422 PIX_FMT_YUV422 -#endif #include #include @@ -65,59 +60,69 @@ static int convert_mlt_to_av_cs( mlt_image_format format ) case mlt_image_yuv420p: value = PIX_FMT_YUV420P; break; - case mlt_image_none: - mlt_log_error( NULL, "[filter avcolor_space] Invalid format\n" ); + default: + mlt_log_error( NULL, "[filter avcolor_space] Invalid format %s\n", + mlt_image_format_name( format ) ); break; } return value; } -static void set_luma_transfer( struct SwsContext *context, int colorspace, int use_full_range ) +static int set_luma_transfer( struct SwsContext *context, int src_colorspace, int dst_colorspace, int full_range ) { -#if defined(SWSCALE) && (LIBSWSCALE_VERSION_INT >= ((0<<16)+(7<<8)+2)) - int *coefficients; - const int *new_coefficients; - int full_range; - int brightness, contrast, saturation; - - if ( sws_getColorspaceDetails( context, &coefficients, &full_range, &coefficients, &full_range, - &brightness, &contrast, &saturation ) != -1 ) + const int *src_coefficients = sws_getCoefficients( SWS_CS_DEFAULT ); + const int *dst_coefficients = sws_getCoefficients( SWS_CS_DEFAULT ); + int brightness = 0; + int contrast = 1 << 16; + int saturation = 1 << 16; + + switch ( src_colorspace ) { - // Don't change these from defaults unless explicitly told to. - if ( use_full_range >= 0 ) - full_range = use_full_range; - switch ( colorspace ) - { - case 170: - case 470: - case 601: - case 624: - new_coefficients = sws_getCoefficients( SWS_CS_ITU601 ); - break; - case 240: - new_coefficients = sws_getCoefficients( SWS_CS_SMPTE240M ); - break; - case 709: - new_coefficients = sws_getCoefficients( SWS_CS_ITU709 ); - break; - default: - new_coefficients = coefficients; - break; - } - sws_setColorspaceDetails( context, new_coefficients, full_range, new_coefficients, full_range, - brightness, contrast, saturation ); + case 170: + case 470: + case 601: + case 624: + src_coefficients = sws_getCoefficients( SWS_CS_ITU601 ); + break; + case 240: + src_coefficients = sws_getCoefficients( SWS_CS_SMPTE240M ); + break; + case 709: + src_coefficients = sws_getCoefficients( SWS_CS_ITU709 ); + break; + default: + break; } -#endif + switch ( dst_colorspace ) + { + case 170: + case 470: + case 601: + case 624: + src_coefficients = sws_getCoefficients( SWS_CS_ITU601 ); + break; + case 240: + src_coefficients = sws_getCoefficients( SWS_CS_SMPTE240M ); + break; + case 709: + src_coefficients = sws_getCoefficients( SWS_CS_ITU709 ); + break; + default: + break; + } + return sws_setColorspaceDetails( context, src_coefficients, full_range, dst_coefficients, full_range, + 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 colorspace, int use_full_range ) +// returns set_lumage_transfer result +static int av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, + int width, int height, int src_colorspace, int dst_colorspace, int use_full_range ) { AVPicture input; AVPicture output; -#ifdef SWSCALE - int flags = SWS_BILINEAR | SWS_ACCURATE_RND; + int flags = SWS_BICUBIC | SWS_ACCURATE_RND; + int error = -1; if ( out_fmt == PIX_FMT_YUYV422 ) flags |= SWS_FULL_CHR_H_INP; @@ -129,20 +134,24 @@ static void av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt #ifdef USE_SSE flags |= SWS_CPU_CAPS_MMX2; #endif -#endif /* SWSCALE */ + if ( out_fmt == PIX_FMT_YUV420P && use_full_range ) + out_fmt = PIX_FMT_YUVJ420P; 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, flags, NULL, NULL, NULL); - set_luma_transfer( context, colorspace, use_full_range ); - sws_scale( context, (const uint8_t* const*) input.data, input.linesize, 0, height, - output.data, output.linesize); - sws_freeContext( context ); -#else - img_convert( &output, out_fmt, &input, in_fmt, width, height ); -#endif + if ( context ) + { + // libswscale wants the RGB colorspace to be SWS_CS_DEFAULT, which is = SWS_CS_ITU601. + if ( out_fmt == PIX_FMT_RGB24 || out_fmt == PIX_FMT_RGBA ) + dst_colorspace = 601; + error = set_luma_transfer( context, src_colorspace, dst_colorspace, use_full_range ); + sws_scale( context, (const uint8_t* const*) input.data, input.linesize, 0, height, + output.data, output.linesize); + sws_freeContext( context ); + } + return error; } /** Do it :-). @@ -157,16 +166,19 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo if ( *format != output_format ) { + mlt_profile profile = mlt_service_profile( + MLT_PRODUCER_SERVICE( mlt_frame_get_original_producer( frame ) ) ); int colorspace = mlt_properties_get_int( properties, "colorspace" ); - int force_full_luma = -1; + int force_full_luma = 0; - mlt_log_debug( NULL, "[filter avcolor_space] %s -> %s @ %dx%d space %d\n", + mlt_log_debug( NULL, "[filter avcolor_space] %s -> %s @ %dx%d space %d->%d\n", mlt_image_format_name( *format ), mlt_image_format_name( output_format ), - width, height, colorspace ); + width, height, colorspace, profile->colorspace ); int in_fmt = convert_mlt_to_av_cs( *format ); int out_fmt = convert_mlt_to_av_cs( output_format ); - int size = avpicture_get_size( out_fmt, width, height ); + int size = FFMAX( avpicture_get_size( out_fmt, width, height ), + mlt_image_format_size( output_format, width, height, NULL ) ); uint8_t *output = mlt_pool_alloc( size ); if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) @@ -195,7 +207,6 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo while ( --n > 0 ); } mlt_frame_set_alpha( frame, alpha, len, mlt_pool_release ); - frame->get_alpha_mask = NULL; } } @@ -206,10 +217,16 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo // By removing the frame property we only permit the luma to skip scaling once. // Thereafter, we let swscale scale the luma range as it pleases since it seems // we do not have control over the RGB to YUV conversion. - force_full_luma = mlt_properties_get_int( properties, "force_full_luma" ); + force_full_luma = mlt_properties_get_int( properties, "force_full_luma" ); mlt_properties_set( properties, "force_full_luma", NULL ); } - av_convert_image( output, *image, out_fmt, in_fmt, width, height, colorspace, force_full_luma ); + if ( !av_convert_image( output, *image, out_fmt, in_fmt, width, height, + colorspace, profile->colorspace, force_full_luma ) ) + { + // The new colorspace is only valid if destination is YUV. + if ( output_format == mlt_image_yuv422 || output_format == mlt_image_yuv420p ) + mlt_properties_set_int( properties, "colorspace", profile->colorspace ); + } *image = output; *format = output_format; mlt_frame_set_image( frame, output, size, mlt_pool_release ); @@ -248,8 +265,7 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo return error; } -/* TODO: The below is not working because swscale does not have - * adjustable coefficients yet for RGB->YUV */ +/* TODO: Enable this to force colorspace conversion. Cost is heavy due to RGB conversions. */ #if 0 static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { @@ -300,8 +316,9 @@ static mlt_frame filter_process( mlt_filter filter, mlt_frame frame ) if ( mlt_properties_get_int( properties, "colorspace" ) <= 0 ) mlt_properties_set_int( properties, "colorspace", mlt_service_profile( MLT_FILTER_SERVICE(filter) )->colorspace ); - frame->convert_image = convert_image; - + if ( !frame->convert_image ) + frame->convert_image = convert_image; + // Not working yet - see comment for get_image() above. // mlt_frame_push_service( frame, mlt_service_profile( MLT_FILTER_SERVICE( filter ) ) ); // mlt_frame_push_get_image( frame, get_image ); @@ -314,22 +331,19 @@ static mlt_frame filter_process( mlt_filter filter, mlt_frame frame ) 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 ) { - int width = (int) arg; - struct SwsContext *context = sws_getContext( width, width, PIX_FMT_RGB32, 64, 64, PIX_FMT_RGB32, SWS_BILINEAR, NULL, NULL, NULL); - if ( context ) - sws_freeContext( context ); - else - return NULL; - } -#else - return NULL; -#endif -#endif + int *width = (int*) arg; + if ( *width > 0 ) + { + struct SwsContext *context = sws_getContext( *width, *width, PIX_FMT_RGB32, 64, 64, PIX_FMT_RGB32, SWS_BILINEAR, NULL, NULL, NULL); + if ( context ) + sws_freeContext( context ); + else + return NULL; + } + } mlt_filter filter = mlt_filter_new( ); if ( filter != NULL ) filter->process = filter_process;