]> git.sesse.net Git - mlt/blob - src/modules/core/filter_resize.c
Cleanup license declarations and remove dv1394d references.
[mlt] / src / modules / core / filter_resize.c
1 /*
2  * filter_resize.c -- resizing filter
3  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4  * Author: Charles Yates <charles.yates@pandora.be>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "filter_resize.h"
22
23 #include <framework/mlt_frame.h>
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <math.h>
29
30 /** Swapbytes inline.
31 */
32
33 static inline void swap_bytes( uint8_t *upper, uint8_t *lower )
34 {
35         uint8_t t = *lower;
36         *lower = *upper;
37         *upper = t;
38 }
39
40 /** Do it :-).
41 */
42
43 static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
44 {
45         int error = 0;
46
47         // Get the properties from the frame
48         mlt_properties properties = MLT_FRAME_PROPERTIES( this );
49
50         // Pop the top of stack now
51         mlt_filter filter = mlt_frame_pop_service( this );
52
53         // Retrieve the aspect ratio
54         double aspect_ratio = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( this ) );
55
56         // Assign requested width/height from our subordinate
57         int owidth = *width;
58         int oheight = *height;
59
60         // Check for the special case - no aspect ratio means no problem :-)
61         if ( aspect_ratio == 0.0 )
62                 aspect_ratio = mlt_properties_get_double( properties, "consumer_aspect_ratio" );
63
64         // Reset the aspect ratio
65         mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );
66
67         // Hmmm...
68         char *rescale = mlt_properties_get( properties, "rescale.interp" );
69         if ( rescale != NULL && !strcmp( rescale, "none" ) )
70                 return mlt_frame_get_image( this, image, format, width, height, writable );
71
72         if ( mlt_properties_get_int( properties, "distort" ) == 0 )
73         {
74                 // Normalise the input and out display aspect
75                 int normalised_width = mlt_properties_get_int( properties, "normalised_width" );
76                 int normalised_height = mlt_properties_get_int( properties, "normalised_height" );
77                 int real_width = mlt_properties_get_int( properties, "real_width" );
78                 int real_height = mlt_properties_get_int( properties, "real_height" );
79                 if ( real_width == 0 )
80                         real_width = mlt_properties_get_int( properties, "width" );
81                 if ( real_height == 0 )
82                         real_height = mlt_properties_get_int( properties, "height" );
83                 double input_ar = aspect_ratio * real_width / real_height;
84                 double output_ar = mlt_properties_get_double( properties, "consumer_aspect_ratio" ) * owidth / oheight;
85                 
86                 //fprintf( stderr, "normalised %dx%d output %dx%d %f %f\n", normalised_width, normalised_height, owidth, oheight, ( float )output_ar, ( float )mlt_properties_get_double( properties, "consumer_aspect_ratio" ) * owidth / oheight );
87
88                 // Optimised for the input_ar > output_ar case (e.g. widescreen on standard)
89                 int scaled_width = rint( 0.5 + ( input_ar * normalised_width ) / output_ar );
90                 int scaled_height = normalised_height;
91
92                 // Now ensure that our images fit in the output frame
93                 if ( scaled_width > normalised_width )
94                 {
95                         scaled_width = normalised_width;
96                         scaled_height = rint( 0.5 + ( output_ar * normalised_height ) / input_ar );
97                 }
98
99                 // Now calculate the actual image size that we want
100                 owidth = rint( 0.5 + scaled_width * owidth / normalised_width );
101                 oheight = rint( 0.5 + scaled_height * oheight / normalised_height );
102
103                 // Tell frame we have conformed the aspect to the consumer
104                 mlt_frame_set_aspect_ratio( this, mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
105         }
106
107         mlt_properties_set_int( properties, "distort", 0 );
108
109         // Now pass on the calculations down the line
110         mlt_properties_set_int( properties, "resize_width", *width );
111         mlt_properties_set_int( properties, "resize_height", *height );
112
113         // Now get the image
114         error = mlt_frame_get_image( this, image, format, &owidth, &oheight, writable );
115
116         // We only know how to process yuv422 at the moment
117         if ( error == 0 && *format == mlt_image_yuv422 && *image != NULL )
118         {
119                 // Get the requested scale operation
120                 char *op = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "scale" );
121
122                 // Provides a manual override for misreported field order
123                 if ( mlt_properties_get( properties, "meta.top_field_first" ) )
124                         mlt_properties_set( properties, "top_field_first", mlt_properties_get_int( properties, "meta.top_field_first" ) );
125
126                 // Correct field order if needed
127                 if ( mlt_properties_get_int( properties, "top_field_first" ) == 1 )
128                 {
129                         // Get the input image, width and height
130                         int size;
131                         uint8_t *image = mlt_properties_get_data( properties, "image", &size );
132                         uint8_t *ptr = image + owidth * 2;
133                         int h = oheight / 2;
134                         int w = owidth;
135
136                         // Swap the lines around
137                         while( h -- )
138                         {
139                                 w = owidth;
140                                 while( w -- )
141                                 {
142                                         swap_bytes( image ++, ptr ++ );
143                                         swap_bytes( image ++, ptr ++ );
144                                 }
145                                 image += owidth * 2;
146                                 ptr += owidth * 2;
147                         }
148
149                         // Set the normalised field order
150                         mlt_properties_set_int( properties, "top_field_first", 0 );
151                         mlt_properties_set_int( properties, "meta.top_field_first", 0 );
152                 }
153
154                 if ( !strcmp( op, "affine" ) )
155                 {
156                         *image = mlt_frame_rescale_yuv422( this, *width, *height );
157                 }
158                 else if ( strcmp( op, "none" ) != 0 )
159                 {
160                         *image = mlt_frame_resize_yuv422( this, *width, *height );
161                 }
162                 else
163                 {
164                         *width = owidth;
165                         *height = oheight;
166                 }
167         }
168
169         return error;
170 }
171
172 /** Filter processing.
173 */
174
175 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
176 {
177         // Store the aspect ratio reported by the source
178         mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( frame ), mlt_frame_get_aspect_ratio( frame ) );
179
180         // Push this on to the service stack
181         mlt_frame_push_service( frame, this );
182
183         // Push the get_image method on to the stack
184         mlt_frame_push_get_image( frame, filter_get_image );
185
186         return frame;
187 }
188
189 /** Constructor for the filter.
190 */
191
192 mlt_filter filter_resize_init( char *arg )
193 {
194         mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
195         if ( mlt_filter_init( this, this ) == 0 )
196         {
197                 this->process = filter_process;
198                 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "scale", arg == NULL ? "off" : arg );
199         }
200         return this;
201 }