2 * filter_swscale.c -- image scaling filter
3 * Copyright (C) 2008-2009 Ushodaya Enterprises Limited
4 * Author: Dan Dennedy <dan@dennedy.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <framework/mlt_filter.h>
22 #include <framework/mlt_frame.h>
23 #include <framework/mlt_factory.h>
24 #include <framework/mlt_producer.h>
27 // ffmpeg Header files
35 #if LIBAVUTIL_VERSION_INT < (50<<16)
36 #define PIX_FMT_RGB32 PIX_FMT_RGBA32
37 #define PIX_FMT_YUYV422 PIX_FMT_YUV422
40 static inline int convert_mlt_to_av_cs( mlt_image_format format )
47 value = PIX_FMT_RGB24;
49 case mlt_image_rgb24a:
50 case mlt_image_opengl:
51 value = PIX_FMT_RGB32;
53 case mlt_image_yuv422:
54 value = PIX_FMT_YUYV422;
56 case mlt_image_yuv420p:
57 value = PIX_FMT_YUV420P;
60 fprintf( stderr, "Invalid format...\n" );
67 static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight )
70 mlt_properties properties = MLT_FRAME_PROPERTIES( this );
72 // Get the requested interpolation method
73 char *interps = mlt_properties_get( properties, "rescale.interp" );
75 // Convert to the SwScale flag
76 int interp = SWS_BILINEAR;
77 if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
79 else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
80 interp = SWS_FAST_BILINEAR;
81 else if ( strcmp( interps, "bilinear" ) == 0 )
82 interp = SWS_BILINEAR;
83 else if ( strcmp( interps, "bicubic" ) == 0 )
85 else if ( strcmp( interps, "bicublin" ) == 0 )
86 interp = SWS_BICUBLIN;
87 else if ( strcmp( interps, "gauss" ) == 0 )
89 else if ( strcmp( interps, "sinc" ) == 0 )
91 else if ( strcmp( interps, "hyper" ) == 0 || strcmp( interps, "lanczos" ) == 0 )
93 else if ( strcmp( interps, "spline" ) == 0 )
95 interp |= SWS_ACCURATE_RND;
97 // Determine the bytes per pixel
101 case mlt_image_yuv422:
103 interp |= SWS_FULL_CHR_H_INP;
105 case mlt_image_rgb24:
107 interp |= SWS_FULL_CHR_H_INT;
109 case mlt_image_rgb24a:
110 case mlt_image_opengl:
112 interp |= SWS_FULL_CHR_H_INT;
115 // XXX: we only know how to rescale packed formats
119 interp |= SWS_CPU_CAPS_MMX;
122 interp |= SWS_CPU_CAPS_MMX2;
125 // Convert the pixel formats
126 int avformat = convert_mlt_to_av_cs( *format );
128 // Fill out the AVPictures
131 uint8_t *outbuf = mlt_pool_alloc( owidth * ( oheight + 1 ) * bpp );
132 avpicture_fill( &input, *image, avformat, iwidth, iheight );
133 avpicture_fill( &output, outbuf, avformat, owidth, oheight );
135 // Get the cached swscale context
136 mlt_producer producer = mlt_frame_get_original_producer( this );
137 mlt_properties prod_props = MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) );
138 struct SwsContext *context = mlt_properties_get_data( prod_props, "swscale.context", NULL );
140 // Create the context and output image
141 owidth = owidth > 5120 ? 5120 : owidth;
142 struct SwsContext *new_context = sws_getCachedContext( context, iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
145 owidth = owidth > 2048 ? 2048 : owidth;
146 new_context = sws_getCachedContext( context, iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
148 if ( new_context != context )
149 mlt_properties_set_data( properties, "swscale.context", new_context, 0, NULL, NULL );
152 // Perform the scaling
153 sws_scale( new_context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
155 // Now update the frame
156 mlt_properties_set_data( properties, "image", output.data[0], owidth * ( oheight + 1 ) * bpp, ( mlt_destructor )mlt_pool_release, NULL );
157 mlt_properties_set_int( properties, "width", owidth );
158 mlt_properties_set_int( properties, "height", oheight );
161 *image = output.data[0];
163 // Scale the alpha channel only if exists and not correct size
165 mlt_properties_get_data( properties, "alpha", &alpha_size );
166 if ( alpha_size > 0 && alpha_size != ( owidth * oheight ) )
168 // Create the context and output image
169 uint8_t *alpha = mlt_frame_get_alpha_mask( this );
172 context = mlt_properties_get_data( prod_props, "swscale.context2", NULL );
173 new_context = sws_getCachedContext( context, iwidth, iheight, avformat, owidth, oheight, avformat, interp, NULL, NULL, NULL);
174 if ( new_context != context )
175 mlt_properties_set_data( prod_props, "swscale.context2", new_context, 0, NULL, NULL );
177 avformat = PIX_FMT_GRAY8;
178 avpicture_fill( &input, alpha, avformat, iwidth, iheight );
179 outbuf = mlt_pool_alloc( owidth * oheight );
180 avpicture_fill( &output, outbuf, avformat, owidth, oheight );
182 // Perform the scaling
183 sws_scale( new_context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
185 // Set it back on the frame
186 mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "alpha", output.data[0], owidth * oheight, mlt_pool_release, NULL );
198 static void filter_close( mlt_filter filter )
200 struct SwsContext *context = mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "swscale.context", NULL );
201 sws_freeContext( context );
202 context = mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "swscale.context2", NULL );
203 sws_freeContext( context );
206 /** Constructor for the filter.
209 mlt_filter filter_swscale_init( mlt_profile profile, void *arg )
211 // Test to see if swscale accepts the arg as resolution
214 int width = (int) arg;
215 struct SwsContext *context = sws_getContext( width, width, PIX_FMT_RGB32, 64, 64, PIX_FMT_RGB32, SWS_BILINEAR, NULL, NULL, NULL);
217 sws_freeContext( context );
222 // Create a new scaler
223 mlt_filter this = mlt_factory_filter( profile, "rescale", NULL );
225 // If successful, then initialise it
228 // Get the properties
229 mlt_properties properties = MLT_FILTER_PROPERTIES( this );
231 // Set the inerpolation
232 mlt_properties_set( properties, "interpolation", "bilinear" );
235 mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
237 this->close = filter_close;