// Need two av pictures for converting
AVFrame *output = NULL;
AVFrame *input = alloc_picture( PIX_FMT_YUYV422, width, height );
+#ifdef SWSCALE
+ struct SwsContext *swscale = NULL;
+ int swscale_flags = SWS_BILINEAR;
+#ifdef USE_MMX
+ swscale_flags |= SWS_CPU_CAPS_MMX;
+#endif
+#ifdef USE_SSE
+ swscale_flags |= SWS_CPU_CAPS_MMX2;
+#endif
+#endif
// For receiving images from an mlt_frame
uint8_t *image;
// Do the colour space conversion
#ifdef SWSCALE
- int flags = SWS_BILINEAR;
-#ifdef USE_MMX
- flags |= SWS_CPU_CAPS_MMX;
-#endif
-#ifdef USE_SSE
- flags |= SWS_CPU_CAPS_MMX2;
-#endif
- struct SwsContext *context = sws_getContext( width, height, PIX_FMT_YUYV422,
- width, height, video_st->codec->pix_fmt, flags, NULL, NULL, NULL);
- sws_scale( context, input->data, input->linesize, 0, height,
+ swscale = sws_getCachedContext( swscale, width, height, PIX_FMT_YUYV422,
+ width, height, video_st->codec->pix_fmt, swscale_flags, NULL, NULL, NULL);
+ sws_scale( swscale, input->data, input->linesize, 0, height,
output->data, output->linesize);
- sws_freeContext( context );
#else
img_convert( ( AVPicture * )output, video_st->codec->pix_fmt, ( AVPicture * )input, PIX_FMT_YUYV422, width, height );
#endif
av_free( video_outbuf );
av_free( audio_buf_1 );
av_free( audio_buf_2 );
+#ifdef SWSCALE
+ sws_freeContext( swscale );
+#endif
// Free the stream
av_free( oc );
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
#include <framework/mlt_log.h>
+#include <framework/mlt_producer.h>
// ffmpeg Header files
#include <avformat.h>
return value;
}
-static void av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height )
+static void av_convert_image( mlt_properties properties, uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height )
{
AVPicture input;
AVPicture output;
+ avpicture_fill( &input, in, in_fmt, width, height );
+ avpicture_fill( &output, out, out_fmt, width, height );
+
+#ifdef SWSCALE
int flags = SWS_BILINEAR | SWS_ACCURATE_RND;
+ struct SwsContext *context = mlt_properties_get_data( properties, "avcolorspace.swscale", NULL );
+ struct SwsContext *new_context;
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;
+ flags |= SWS_CPU_CAPS_MMX;
#endif
#ifdef USE_SSE
- flags |= SWS_CPU_CAPS_MMX2;
+ 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,
+ new_context = sws_getCachedContext( context, width, height, in_fmt,
width, height, out_fmt, flags, NULL, NULL, NULL);
- sws_scale( context, input.data, input.linesize, 0, height,
+ if ( new_context != context )
+ mlt_properties_set_data( properties, "avcolorspace.swscale", new_context, 0, NULL, NULL );
+ sws_scale( new_context, 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
}
// Update the output
- av_convert_image( output, *image, out_fmt, in_fmt, width, height );
+ mlt_producer producer = mlt_frame_get_original_producer( frame );
+ mlt_properties prod_props = MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) );
+ av_convert_image( prod_props, output, *image, out_fmt, in_fmt, width, height );
*image = output;
*format = output_format;
mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL );
return frame;
}
+static void filter_close( mlt_filter filter )
+{
+#ifdef SWSCALE
+ struct SwsContext *context = mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "avcolorspace.swscale", NULL );
+ sws_freeContext( context );
+#endif
+}
+
/** Constructor for the filter.
*/
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;
+ this->close = filter_close;
+ }
return this;
-#else
- return NULL;
-#endif
}
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
#include <framework/mlt_factory.h>
-#include <framework/mlt_factory.h>
+#include <framework/mlt_producer.h>
// ffmpeg Header files
avpicture_fill( &input, *image, avformat, iwidth, iheight );
avpicture_fill( &output, outbuf, avformat, owidth, oheight );
+ // Get the cached swscale context
+ mlt_producer producer = mlt_frame_get_original_producer( this );
+ mlt_properties prod_props = MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) );
+ struct SwsContext *context = mlt_properties_get_data( prod_props, "swscale.context", NULL );
+
// Create the context and output image
owidth = owidth > 5120 ? 5120 : owidth;
- struct SwsContext *context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
- if ( !context )
+ struct SwsContext *new_context = sws_getCachedContext( context, iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
+ if ( !new_context )
{
owidth = owidth > 2048 ? 2048 : owidth;
- context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
+ new_context = sws_getCachedContext( context, iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
}
- if ( context )
+ if ( new_context != context )
+ mlt_properties_set_data( properties, "swscale.context", new_context, 0, NULL, NULL );
+ if ( new_context )
{
// Perform the scaling
- sws_scale( context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
- sws_freeContext( context );
+ sws_scale( new_context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
// Now update the frame
mlt_properties_set_data( properties, "image", output.data[0], owidth * ( oheight + 1 ) * bpp, ( mlt_destructor )mlt_pool_release, NULL );
uint8_t *alpha = mlt_frame_get_alpha_mask( this );
if ( alpha )
{
+ context = mlt_properties_get_data( prod_props, "swscale.context2", NULL );
+ new_context = sws_getCachedContext( context, iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
+ if ( new_context != context )
+ mlt_properties_set_data( properties, "swscale.context2", new_context, 0, NULL, NULL );
+
avformat = PIX_FMT_GRAY8;
- struct SwsContext *context = sws_getContext( iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
avpicture_fill( &input, alpha, avformat, iwidth, iheight );
outbuf = mlt_pool_alloc( owidth * oheight );
avpicture_fill( &output, outbuf, avformat, owidth, oheight );
}
}
+static void filter_close( mlt_filter filter )
+{
+ struct SwsContext *context = mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "swscale.context", NULL );
+ sws_freeContext( context );
+ context = mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "swscale.context2", NULL );
+ sws_freeContext( context );
+}
+
/** Constructor for the filter.
*/
// Set the method
mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
+
+ this->close = filter_close;
}
return this;
uint8_t *buffer;
} *vdpau;
#endif
+#ifdef SWSCALE
+ struct SwsContext *swscale;
+#else
+ void *swscale;
+#endif
};
typedef struct producer_avformat_s *producer_avformat;
this->resample_factor = 1.0;
}
-static inline void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt, mlt_image_format *format, int width, int height )
+static inline void convert_image( void **ctx, AVFrame *frame, uint8_t *buffer, int pix_fmt, mlt_image_format *format, int width, int height )
{
#ifdef SWSCALE
+ struct SwsContext **context = ctx;
int flags = SWS_BILINEAR | SWS_ACCURATE_RND;
#ifdef USE_MMX
if ( pix_fmt == PIX_FMT_RGB32 )
{
*format = mlt_image_rgb24a;
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
+ *context = sws_getCachedContext( *context, width, height, pix_fmt,
width, height, PIX_FMT_RGBA, flags, NULL, NULL, NULL);
AVPicture output;
avpicture_fill( &output, buffer, PIX_FMT_RGBA, width, height );
- sws_scale( context, frame->data, frame->linesize, 0, height,
+ sws_scale( *context, frame->data, frame->linesize, 0, height,
output.data, output.linesize);
- sws_freeContext( context );
}
else if ( *format == mlt_image_yuv420p )
{
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
+ *context = sws_getCachedContext( *context, width, height, pix_fmt,
width, height, PIX_FMT_YUV420P, flags, NULL, NULL, NULL);
AVPicture output;
output.data[0] = buffer;
output.linesize[0] = width;
output.linesize[1] = width >> 1;
output.linesize[2] = width >> 1;
- sws_scale( context, frame->data, frame->linesize, 0, height,
+ sws_scale( *context, frame->data, frame->linesize, 0, height,
output.data, output.linesize);
- sws_freeContext( context );
}
else if ( *format == mlt_image_rgb24 )
{
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
+ *context = sws_getCachedContext( *context, width, height, pix_fmt,
width, height, PIX_FMT_RGB24, flags | SWS_FULL_CHR_H_INT, NULL, NULL, NULL);
AVPicture output;
avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height );
- sws_scale( context, frame->data, frame->linesize, 0, height,
+ sws_scale( *context, frame->data, frame->linesize, 0, height,
output.data, output.linesize);
- sws_freeContext( context );
}
else if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl )
{
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
+ *context = sws_getCachedContext( *context, width, height, pix_fmt,
width, height, PIX_FMT_RGBA, flags | SWS_FULL_CHR_H_INT, NULL, NULL, NULL);
AVPicture output;
avpicture_fill( &output, buffer, PIX_FMT_RGBA, width, height );
- sws_scale( context, frame->data, frame->linesize, 0, height,
+ sws_scale( *context, frame->data, frame->linesize, 0, height,
output.data, output.linesize);
- sws_freeContext( context );
}
else
{
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
+ *context = sws_getCachedContext( *context, width, height, pix_fmt,
width, height, PIX_FMT_YUYV422, flags | SWS_FULL_CHR_H_INP, NULL, NULL, NULL);
AVPicture output;
avpicture_fill( &output, buffer, PIX_FMT_YUYV422, width, height );
- sws_scale( context, frame->data, frame->linesize, 0, height,
+ sws_scale( *context, frame->data, frame->linesize, 0, height,
output.data, output.linesize);
- sws_freeContext( context );
}
#else
if ( *format == mlt_image_yuv420p )
avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height );
img_convert( &output, PIX_FMT_RGB24, (AVPicture *)frame, pix_fmt, width, height );
}
- else if ( format == mlt_image_rgb24a || format == mlt_image_opengl )
+ else if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl )
{
AVPicture output;
avpicture_fill( &output, buffer, PIX_FMT_RGB32, width, height );
if ( this->image_cache )
{
mlt_cache_item item = mlt_cache_get( this->image_cache, (void*) position );
- *buffer = mlt_cache_item_data( item, format );
+ *buffer = mlt_cache_item_data( item, (int*) format );
if ( *buffer )
{
// Set the resolution
picture.linesize[0] = codec_context->width;
picture.linesize[1] = codec_context->width / 2;
picture.linesize[2] = codec_context->width / 2;
- convert_image( (AVFrame*) &picture, *buffer, PIX_FMT_YUV420P, format, *width, *height );
+ convert_image( (void**) &this->swscale, (AVFrame*) &picture, *buffer, PIX_FMT_YUV420P, format, *width, *height );
}
else
#endif
- convert_image( this->av_frame, *buffer, codec_context->pix_fmt, format, *width, *height );
+ convert_image( (void**) &this->swscale, this->av_frame, *buffer, codec_context->pix_fmt, format, *width, *height );
else
mlt_frame_get_image( frame, buffer, format, width, height, writable );
}
VdpStatus status = vdp_surface_get_bits( render->surface, dest_format, planes, pitches );
if ( status == VDP_STATUS_OK )
{
- convert_image( (AVFrame*) &picture, *buffer, PIX_FMT_YUV420P, format, *width, *height );
+ convert_image( (void**) &this->swscale, (AVFrame*) &picture, *buffer, PIX_FMT_YUV420P, format, *width, *height );
}
else
{
}
else
#endif
- convert_image( this->av_frame, *buffer, codec_context->pix_fmt, format, *width, *height );
+ convert_image( (void**) &this->swscale, this->av_frame, *buffer, codec_context->pix_fmt, format, *width, *height );
this->top_field_first |= this->av_frame->top_field_first;
this->current_position = int_position;
this->got_picture = 1;
avformat_unlock();
#ifdef VDPAU
vdpau_producer_close( this );
+#endif
+#ifdef SWSCALE
+ sws_freeContext( this->swscale );
#endif
if ( this->image_cache )
mlt_cache_close( this->image_cache );