]> git.sesse.net Git - mlt/blob - src/framework/mlt_frame.c
move binary modules to libdir - affects MLT_REPOSITORY
[mlt] / src / framework / mlt_frame.c
1 /*
2  * mlt_frame.c -- interface for all frame classes
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 "mlt_frame.h"
22 #include "mlt_producer.h"
23 #include "mlt_factory.h"
24 #include "mlt_profile.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30
31 /** Constructor for a frame.
32 */
33
34 mlt_frame mlt_frame_init( mlt_service service )
35 {
36         // Allocate a frame
37         mlt_frame this = calloc( sizeof( struct mlt_frame_s ), 1 );
38
39         if ( this != NULL )
40         {
41                 mlt_profile profile = mlt_service_profile( service );
42
43                 // Initialise the properties
44                 mlt_properties properties = &this->parent;
45                 mlt_properties_init( properties, this );
46
47                 // Set default properties on the frame
48                 mlt_properties_set_position( properties, "_position", 0.0 );
49                 mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
50                 mlt_properties_set_int( properties, "width", profile? profile->width : 720 );
51                 mlt_properties_set_int( properties, "height", profile? profile->height : 576 );
52                 mlt_properties_set_int( properties, "normalised_width", profile? profile->width : 720 );
53                 mlt_properties_set_int( properties, "normalised_height", profile? profile->height : 576 );
54                 mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( NULL ) );
55                 mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
56                 mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
57
58                 // Construct stacks for frames and methods
59                 this->stack_image = mlt_deque_init( );
60                 this->stack_audio = mlt_deque_init( );
61                 this->stack_service = mlt_deque_init( );
62         }
63
64         return this;
65 }
66
67 /** Fetch the frames properties.
68 */
69
70 mlt_properties mlt_frame_properties( mlt_frame this )
71 {
72         return this != NULL ? &this->parent : NULL;
73 }
74
75 /** Check if we have a way to derive something other than a test card.
76 */
77
78 int mlt_frame_is_test_card( mlt_frame this )
79 {
80         return mlt_deque_count( this->stack_image ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "test_image" );
81 }
82
83 /** Check if we have a way to derive something other than test audio.
84 */
85
86 int mlt_frame_is_test_audio( mlt_frame this )
87 {
88         return mlt_deque_count( this->stack_audio ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "test_audio" );
89 }
90
91 /** Get the aspect ratio of the frame.
92 */
93
94 double mlt_frame_get_aspect_ratio( mlt_frame this )
95 {
96         return mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "aspect_ratio" );
97 }
98
99 /** Set the aspect ratio of the frame.
100 */
101
102 int mlt_frame_set_aspect_ratio( mlt_frame this, double value )
103 {
104         return mlt_properties_set_double( MLT_FRAME_PROPERTIES( this ), "aspect_ratio", value );
105 }
106
107 /** Get the position of this frame.
108 */
109
110 mlt_position mlt_frame_get_position( mlt_frame this )
111 {
112         int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( this ), "_position" );
113         return pos < 0 ? 0 : pos;
114 }
115
116 /** Set the position of this frame.
117 */
118
119 int mlt_frame_set_position( mlt_frame this, mlt_position value )
120 {
121         return mlt_properties_set_position( MLT_FRAME_PROPERTIES( this ), "_position", value );
122 }
123
124 /** Stack a get_image callback.
125 */
126
127 int mlt_frame_push_get_image( mlt_frame this, mlt_get_image get_image )
128 {
129         return mlt_deque_push_back( this->stack_image, get_image );
130 }
131
132 /** Pop a get_image callback.
133 */
134
135 mlt_get_image mlt_frame_pop_get_image( mlt_frame this )
136 {
137         return mlt_deque_pop_back( this->stack_image );
138 }
139
140 /** Push a frame.
141 */
142
143 int mlt_frame_push_frame( mlt_frame this, mlt_frame that )
144 {
145         return mlt_deque_push_back( this->stack_image, that );
146 }
147
148 /** Pop a frame.
149 */
150
151 mlt_frame mlt_frame_pop_frame( mlt_frame this )
152 {
153         return mlt_deque_pop_back( this->stack_image );
154 }
155
156 /** Push a service.
157 */
158
159 int mlt_frame_push_service( mlt_frame this, void *that )
160 {
161         return mlt_deque_push_back( this->stack_image, that );
162 }
163
164 /** Pop a service.
165 */
166
167 void *mlt_frame_pop_service( mlt_frame this )
168 {
169         return mlt_deque_pop_back( this->stack_image );
170 }
171
172 /** Push a service.
173 */
174
175 int mlt_frame_push_service_int( mlt_frame this, int that )
176 {
177         return mlt_deque_push_back_int( this->stack_image, that );
178 }
179
180 /** Pop a service.
181 */
182
183 int mlt_frame_pop_service_int( mlt_frame this )
184 {
185         return mlt_deque_pop_back_int( this->stack_image );
186 }
187
188 /** Push an audio item on the stack.
189 */
190
191 int mlt_frame_push_audio( mlt_frame this, void *that )
192 {
193         return mlt_deque_push_back( this->stack_audio, that );
194 }
195
196 /** Pop an audio item from the stack
197 */
198
199 void *mlt_frame_pop_audio( mlt_frame this )
200 {
201         return mlt_deque_pop_back( this->stack_audio );
202 }
203
204 /** Return the service stack
205 */
206
207 mlt_deque mlt_frame_service_stack( mlt_frame this )
208 {
209         return this->stack_service;
210 }
211
212 /** Replace image stack with the information provided.
213
214         This might prove to be unreliable and restrictive - the idea is that a transition
215         which normally uses two images may decide to only use the b frame (ie: in the case
216         of a composite where the b frame completely obscures the a frame).
217
218         The image must be writable and the destructor for the image itself must be taken
219         care of on another frame and that frame cannot have a replace applied to it... 
220         Further it assumes that no alpha mask is in use.
221
222         For these reasons, it can only be used in a specific situation - when you have 
223         multiple tracks each with their own transition and these transitions are applied
224         in a strictly reversed order (ie: highest numbered [lowest track] is processed 
225         first).
226
227         More reliable approach - the cases should be detected during the process phase
228         and the upper tracks should simply not be invited to stack...
229 */
230
231 void mlt_frame_replace_image( mlt_frame this, uint8_t *image, mlt_image_format format, int width, int height )
232 {
233         // Remove all items from the stack
234         while( mlt_deque_pop_back( this->stack_image ) ) ;
235
236         // Update the information 
237         mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", image, 0, NULL, NULL );
238         mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "width", width );
239         mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "height", height );
240         mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "format", format );
241         this->get_alpha_mask = NULL;
242 }
243
244 /** Get the image associated to the frame.
245 */
246
247 int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
248 {
249         mlt_properties properties = MLT_FRAME_PROPERTIES( this );
250         mlt_get_image get_image = mlt_frame_pop_get_image( this );
251         mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
252         int error = 0;
253
254         if ( get_image != NULL )
255         {
256                 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
257                 mlt_position position = mlt_frame_get_position( this );
258                 error = get_image( this, buffer, format, width, height, writable );
259                 mlt_properties_set_int( properties, "width", *width );
260                 mlt_properties_set_int( properties, "height", *height );
261                 mlt_properties_set_int( properties, "format", *format );
262                 mlt_frame_set_position( this, position );
263         }
264         else if ( mlt_properties_get_data( properties, "image", NULL ) != NULL )
265         {
266                 *format = mlt_properties_get_int( properties, "format" );
267                 *buffer = mlt_properties_get_data( properties, "image", NULL );
268                 *width = mlt_properties_get_int( properties, "width" );
269                 *height = mlt_properties_get_int( properties, "height" );
270         }
271         else if ( producer != NULL )
272         {
273                 mlt_frame test_frame = NULL;
274                 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
275                 if ( test_frame != NULL )
276                 {
277                         mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
278                         mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
279                         mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
280                         mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
281                         mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
282                         mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
283                         mlt_properties_set_int( properties, "width", *width );
284                         mlt_properties_set_int( properties, "height", *height );
285                         mlt_properties_set_int( properties, "format", *format );
286                         mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
287                 }
288                 else
289                 {
290                         mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
291                         mlt_frame_get_image( this, buffer, format, width, height, writable );
292                 }
293         }
294         else
295         {
296                 register uint8_t *p;
297                 register uint8_t *q;
298                 int size = 0;
299
300                 *width = *width == 0 ? 720 : *width;
301                 *height = *height == 0 ? 576 : *height;
302                 size = *width * *height;
303
304                 mlt_properties_set_int( properties, "format", *format );
305                 mlt_properties_set_int( properties, "width", *width );
306                 mlt_properties_set_int( properties, "height", *height );
307                 mlt_properties_set_int( properties, "aspect_ratio", 0 );
308
309                 switch( *format )
310                 {
311                         case mlt_image_none:
312                                 size = 0;
313                                 *buffer = NULL;
314                                 break;
315                         case mlt_image_rgb24:
316                                 size *= 3;
317                                 size += *width * 3;
318                                 *buffer = mlt_pool_alloc( size );
319                                 if ( *buffer )
320                                         memset( *buffer, 255, size );
321                                 break;
322                         case mlt_image_rgb24a:
323                         case mlt_image_opengl:
324                                 size *= 4;
325                                 size += *width * 4;
326                                 *buffer = mlt_pool_alloc( size );
327                                 if ( *buffer )
328                                         memset( *buffer, 255, size );
329                                 break;
330                         case mlt_image_yuv422:
331                                 size *= 2;
332                                 size += *width * 2;
333                                 *buffer = mlt_pool_alloc( size );
334                                 p = *buffer;
335                                 q = p + size;
336                                 while ( p != NULL && p != q )
337                                 {
338                                         *p ++ = 235;
339                                         *p ++ = 128;
340                                 }
341                                 break;
342                         case mlt_image_yuv420p:
343                                 size = size * 3 / 2;
344                                 *buffer = mlt_pool_alloc( size );
345                                 if ( *buffer )
346                                         memset( *buffer, 255, size );
347                                 break;
348                 }
349
350                 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
351                 mlt_properties_set_int( properties, "test_image", 1 );
352         }
353
354         mlt_properties_set_int( properties, "scaled_width", *width );
355         mlt_properties_set_int( properties, "scaled_height", *height );
356
357         return error;
358 }
359
360 uint8_t *mlt_frame_get_alpha_mask( mlt_frame this )
361 {
362         uint8_t *alpha = NULL;
363         if ( this != NULL )
364         {
365                 if ( this->get_alpha_mask != NULL )
366                         alpha = this->get_alpha_mask( this );
367                 if ( alpha == NULL )
368                         alpha = mlt_properties_get_data( &this->parent, "alpha", NULL );
369                 if ( alpha == NULL )
370                 {
371                         int size = mlt_properties_get_int( &this->parent, "scaled_width" ) * mlt_properties_get_int( &this->parent, "scaled_height" );
372                         alpha = mlt_pool_alloc( size );
373                         memset( alpha, 255, size );
374                         mlt_properties_set_data( &this->parent, "alpha", alpha, size, mlt_pool_release, NULL );
375                 }
376         }
377         return alpha;
378 }
379
380 int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
381 {
382         mlt_get_audio get_audio = mlt_frame_pop_audio( this );
383         mlt_properties properties = MLT_FRAME_PROPERTIES( this );
384         int hide = mlt_properties_get_int( properties, "test_audio" );
385
386         if ( hide == 0 && get_audio != NULL )
387         {
388                 mlt_position position = mlt_frame_get_position( this );
389                 get_audio( this, buffer, format, frequency, channels, samples );
390                 mlt_frame_set_position( this, position );
391         }
392         else if ( mlt_properties_get_data( properties, "audio", NULL ) )
393         {
394                 *buffer = mlt_properties_get_data( properties, "audio", NULL );
395                 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
396                 *channels = mlt_properties_get_int( properties, "audio_channels" );
397                 *samples = mlt_properties_get_int( properties, "audio_samples" );
398         }
399         else
400         {
401                 int size = 0;
402                 *samples = *samples <= 0 ? 1920 : *samples;
403                 *channels = *channels <= 0 ? 2 : *channels;
404                 *frequency = *frequency <= 0 ? 48000 : *frequency;
405                 size = *samples * *channels * sizeof( int16_t );
406                 *buffer = mlt_pool_alloc( size );
407                 if ( *buffer != NULL )
408                         memset( *buffer, 0, size );
409                 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
410                 mlt_properties_set_int( properties, "test_audio", 1 );
411         }
412
413         mlt_properties_set_int( properties, "audio_frequency", *frequency );
414         mlt_properties_set_int( properties, "audio_channels", *channels );
415         mlt_properties_set_int( properties, "audio_samples", *samples );
416
417         if ( mlt_properties_get( properties, "meta.volume" ) )
418         {
419                 double value = mlt_properties_get_double( properties, "meta.volume" );
420
421                 if ( value == 0.0 )
422                 {
423                         memset( *buffer, 0, *samples * *channels * 2 );
424                 }
425                 else if ( value != 1.0 )
426                 {
427                         int total = *samples * *channels;
428                         int16_t *p = *buffer;
429                         while ( total -- )
430                         {
431                                 *p = *p * value;
432                                 p ++;
433                         }
434                 }
435
436                 mlt_properties_set( properties, "meta.volume", NULL );
437         }
438
439         return 0;
440 }
441
442 unsigned char *mlt_frame_get_waveform( mlt_frame this, int w, int h )
443 {
444         int16_t *pcm = NULL;
445         mlt_properties properties = MLT_FRAME_PROPERTIES( this );
446         mlt_audio_format format = mlt_audio_pcm;
447         int frequency = 32000; // lower frequency available?
448         int channels = 2;
449         double fps = mlt_profile_fps( NULL );
450         int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( this ) );
451         
452         // Get the pcm data
453         mlt_frame_get_audio( this, &pcm, &format, &frequency, &channels, &samples );
454         
455         // Make an 8-bit buffer large enough to hold rendering
456         int size = w * h;
457         unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
458         if ( bitmap != NULL )
459                 memset( bitmap, 0, size );
460         mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
461         
462         // Render vertical lines
463         int16_t *ubound = pcm + samples * channels;
464         int skip = samples / w - 1;
465         int i, j, k;
466         
467         // Iterate sample stream and along x coordinate
468         for ( i = 0; i < w && pcm < ubound; i++ )
469         {
470                 // pcm data has channels interleaved
471                 for ( j = 0; j < channels; j++ )
472                 {
473                         // Determine sample's magnitude from 2s complement;
474                         int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
475                         // The height of a line is the ratio of the magnitude multiplied by 
476                         // half the vertical resolution
477                         int height = ( int )( ( double )( pcm_magnitude ) / 32768 * h / 2 );
478                         // Determine the starting y coordinate - left channel above center,
479                         // right channel below - currently assumes 2 channels
480                         int displacement = ( h / 2 ) - ( 1 - j ) * height;
481                         // Position buffer pointer using y coordinate, stride, and x coordinate
482                         unsigned char *p = &bitmap[ i + displacement * w ];
483                         
484                         // Draw vertical line
485                         for ( k = 0; k < height; k++ )
486                                 p[ w * k ] = 0xFF;
487                         
488                         pcm++;
489                 }
490                 pcm += skip * channels;
491         }
492
493         return bitmap;
494 }
495
496 mlt_producer mlt_frame_get_original_producer( mlt_frame this )
497 {
498         if ( this != NULL )
499                 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( this ), "_producer", NULL );
500         return NULL;
501 }
502
503 void mlt_frame_close( mlt_frame this )
504 {
505         if ( this != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( this ) ) <= 0 )
506         {
507                 mlt_deque_close( this->stack_image );
508                 mlt_deque_close( this->stack_audio );
509                 while( mlt_deque_peek_back( this->stack_service ) )
510                         mlt_service_close( mlt_deque_pop_back( this->stack_service ) );
511                 mlt_deque_close( this->stack_service );
512                 mlt_properties_close( &this->parent );
513                 free( this );
514         }
515 }
516
517 /***** convenience functions *****/
518
519 int mlt_convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total )
520 {
521         int ret = 0;
522         int yy, uu, vv;
523         int r,g,b;
524         total /= 2;
525         while (total--) 
526         {
527                 yy = yuv[0];
528                 uu = yuv[1];
529                 vv = yuv[3];
530                 YUV2RGB(yy, uu, vv, r, g, b);
531                 rgba[0] = r;
532                 rgba[1] = g;
533                 rgba[2] = b;
534                 rgba[3] = 255;
535                 yy = yuv[2];
536                 YUV2RGB(yy, uu, vv, r, g, b);
537                 rgba[4] = r;
538                 rgba[5] = g;
539                 rgba[6] = b;
540                 rgba[7] = 255;
541                 yuv += 4;
542                 rgba += 8;
543         }
544         return ret;
545 }
546
547 int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
548 {
549         int ret = 0;
550         register int y0, y1, u0, u1, v0, v1;
551         register int r, g, b;
552         register uint8_t *d = yuv;
553         register int i, j;
554
555         if ( alpha )
556         for ( i = 0; i < height; i++ )
557         {
558                 register uint8_t *s = rgba + ( stride * i );
559                 for ( j = 0; j < ( width / 2 ); j++ )
560                 {
561                         r = *s++;
562                         g = *s++;
563                         b = *s++;
564                         *alpha++ = *s++;
565                         RGB2YUV (r, g, b, y0, u0 , v0);
566                         r = *s++;
567                         g = *s++;
568                         b = *s++;
569                         *alpha++ = *s++;
570                         RGB2YUV (r, g, b, y1, u1 , v1);
571                         *d++ = y0;
572                         *d++ = (u0+u1) >> 1;
573                         *d++ = y1;
574                         *d++ = (v0+v1) >> 1;
575                 }
576                 if ( width % 2 )
577                 {
578                         r = *s++;
579                         g = *s++;
580                         b = *s++;
581                         *alpha++ = *s++;
582                         RGB2YUV (r, g, b, y0, u0 , v0);
583                         *d++ = y0;
584                         *d++ = u0;
585                 }
586         }
587         else
588         for ( i = 0; i < height; i++ )
589         {
590                 register uint8_t *s = rgba + ( stride * i );
591                 for ( j = 0; j < ( width / 2 ); j++ )
592                 {
593                         r = *s++;
594                         g = *s++;
595                         b = *s++;
596                         s++;
597                         RGB2YUV (r, g, b, y0, u0 , v0);
598                         r = *s++;
599                         g = *s++;
600                         b = *s++;
601                         s++;
602                         RGB2YUV (r, g, b, y1, u1 , v1);
603                         *d++ = y0;
604                         *d++ = (u0+u1) >> 1;
605                         *d++ = y1;
606                         *d++ = (v0+v1) >> 1;
607                 }
608                 if ( width % 2 )
609                 {
610                         r = *s++;
611                         g = *s++;
612                         b = *s++;
613                         s++;
614                         RGB2YUV (r, g, b, y0, u0 , v0);
615                         *d++ = y0;
616                         *d++ = u0;
617                 }
618         }
619
620         return ret;
621 }
622
623 int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
624 {
625         int ret = 0;
626         register int y0, y1, u0, u1, v0, v1;
627         register int r, g, b;
628         register uint8_t *d = yuv;
629         register int i, j;
630
631         for ( i = 0; i < height; i++ )
632         {
633                 register uint8_t *s = rgb + ( stride * i );
634                 for ( j = 0; j < ( width / 2 ); j++ )
635                 {
636                         r = *s++;
637                         g = *s++;
638                         b = *s++;
639                         RGB2YUV (r, g, b, y0, u0 , v0);
640                         r = *s++;
641                         g = *s++;
642                         b = *s++;
643                         RGB2YUV (r, g, b, y1, u1 , v1);
644                         *d++ = y0;
645                         *d++ = (u0+u1) >> 1;
646                         *d++ = y1;
647                         *d++ = (v0+v1) >> 1;
648                 }
649                 if ( width % 2 )
650                 {
651                         r = *s++;
652                         g = *s++;
653                         b = *s++;
654                         RGB2YUV (r, g, b, y0, u0 , v0);
655                         *d++ = y0;
656                         *d++ = u0;
657                 }
658         }
659         return ret;
660 }
661
662 int mlt_convert_bgr24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
663 {
664         int ret = 0;
665         register int y0, y1, u0, u1, v0, v1;
666         register int r, g, b;
667         register uint8_t *d = yuv;
668         register int i, j;
669
670         if ( alpha )
671         for ( i = 0; i < height; i++ )
672         {
673                 register uint8_t *s = rgba + ( stride * i );
674                 for ( j = 0; j < ( width / 2 ); j++ )
675                 {
676                         b = *s++;
677                         g = *s++;
678                         r = *s++;
679                         *alpha++ = *s++;
680                         RGB2YUV (r, g, b, y0, u0 , v0);
681                         b = *s++;
682                         g = *s++;
683                         r = *s++;
684                         *alpha++ = *s++;
685                         RGB2YUV (r, g, b, y1, u1 , v1);
686                         *d++ = y0;
687                         *d++ = (u0+u1) >> 1;
688                         *d++ = y1;
689                         *d++ = (v0+v1) >> 1;
690                 }
691                 if ( width % 2 )
692                 {
693                         b = *s++;
694                         g = *s++;
695                         r = *s++;
696                         *alpha++ = *s++;
697                         RGB2YUV (r, g, b, y0, u0 , v0);
698                         *d++ = y0;
699                         *d++ = u0;
700                 }
701         }
702         else
703         for ( i = 0; i < height; i++ )
704         {
705                 register uint8_t *s = rgba + ( stride * i );
706                 for ( j = 0; j < ( width / 2 ); j++ )
707                 {
708                         b = *s++;
709                         g = *s++;
710                         r = *s++;
711                         s++;
712                         RGB2YUV (r, g, b, y0, u0 , v0);
713                         b = *s++;
714                         g = *s++;
715                         r = *s++;
716                         s++;
717                         RGB2YUV (r, g, b, y1, u1 , v1);
718                         *d++ = y0;
719                         *d++ = (u0+u1) >> 1;
720                         *d++ = y1;
721                         *d++ = (v0+v1) >> 1;
722                 }
723                 if ( width % 2 )
724                 {
725                         b = *s++;
726                         g = *s++;
727                         r = *s++;
728                         s++;
729                         RGB2YUV (r, g, b, y0, u0 , v0);
730                         *d++ = y0;
731                         *d++ = u0;
732                 }
733         }
734         return ret;
735 }
736
737 int mlt_convert_bgr24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
738 {
739         int ret = 0;
740         register int y0, y1, u0, u1, v0, v1;
741         register int r, g, b;
742         register uint8_t *d = yuv;
743         register int i, j;
744
745         for ( i = 0; i < height; i++ )
746         {
747                 register uint8_t *s = rgb + ( stride * i );
748                 for ( j = 0; j < ( width / 2 ); j++ )
749                 {
750                         b = *s++;
751                         g = *s++;
752                         r = *s++;
753                         RGB2YUV (r, g, b, y0, u0 , v0);
754                         b = *s++;
755                         g = *s++;
756                         r = *s++;
757                         RGB2YUV (r, g, b, y1, u1 , v1);
758                         *d++ = y0;
759                         *d++ = (u0+u1) >> 1;
760                         *d++ = y1;
761                         *d++ = (v0+v1) >> 1;
762                 }
763                 if ( width % 2 )
764                 {
765                         b = *s++;
766                         g = *s++;
767                         r = *s++;
768                         RGB2YUV (r, g, b, y0, u0 , v0);
769                         *d++ = y0;
770                         *d++ = u0;
771                 }
772         }
773         return ret;
774 }
775
776 int mlt_convert_argb_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
777 {
778         int ret = 0;
779         register int y0, y1, u0, u1, v0, v1;
780         register int r, g, b;
781         register uint8_t *d = yuv;
782         register int i, j;
783
784         if ( alpha )
785         for ( i = 0; i < height; i++ )
786         {
787                 register uint8_t *s = rgba + ( stride * i );
788                 for ( j = 0; j < ( width / 2 ); j++ )
789                 {
790                         *alpha++ = *s++;
791                         r = *s++;
792                         g = *s++;
793                         b = *s++;
794                         RGB2YUV (r, g, b, y0, u0 , v0);
795                         *alpha++ = *s++;
796                         r = *s++;
797                         g = *s++;
798                         b = *s++;
799                         RGB2YUV (r, g, b, y1, u1 , v1);
800                         *d++ = y0;
801                         *d++ = (u0+u1) >> 1;
802                         *d++ = y1;
803                         *d++ = (v0+v1) >> 1;
804                 }
805                 if ( width % 2 )
806                 {
807                         *alpha++ = *s++;
808                         r = *s++;
809                         g = *s++;
810                         b = *s++;
811                         RGB2YUV (r, g, b, y0, u0 , v0);
812                         *d++ = y0;
813                         *d++ = u0;
814                 }
815         }
816         else
817         for ( i = 0; i < height; i++ )
818         {
819                 register uint8_t *s = rgba + ( stride * i );
820                 for ( j = 0; j < ( width / 2 ); j++ )
821                 {
822                         s++;
823                         r = *s++;
824                         g = *s++;
825                         b = *s++;
826                         RGB2YUV (r, g, b, y0, u0 , v0);
827                         s++;
828                         r = *s++;
829                         g = *s++;
830                         b = *s++;
831                         RGB2YUV (r, g, b, y1, u1 , v1);
832                         *d++ = y0;
833                         *d++ = (u0+u1) >> 1;
834                         *d++ = y1;
835                         *d++ = (v0+v1) >> 1;
836                 }
837                 if ( width % 2 )
838                 {
839                         s++;
840                         r = *s++;
841                         g = *s++;
842                         b = *s++;
843                         RGB2YUV (r, g, b, y0, u0 , v0);
844                         *d++ = y0;
845                         *d++ = u0;
846                 }
847         }
848         return ret;
849 }
850
851 int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv )
852 {
853         int ret = 0;
854         register int i, j;
855
856         int half = width >> 1;
857
858         uint8_t *Y = yuv420p;
859         uint8_t *U = Y + width * height;
860         uint8_t *V = U + width * height / 4;
861
862         register uint8_t *d = yuv;
863
864         for ( i = 0; i < height; i++ )
865         {
866                 register uint8_t *u = U + ( i / 2 ) * ( half );
867                 register uint8_t *v = V + ( i / 2 ) * ( half );
868
869                 for ( j = 0; j < half; j++ )
870                 {
871                         *d ++ = *Y ++;
872                         *d ++ = *u ++;
873                         *d ++ = *Y ++;
874                         *d ++ = *v ++;
875                 }
876         }
877         return ret;
878 }
879
880 uint8_t *mlt_resize_alpha( uint8_t *input, int owidth, int oheight, int iwidth, int iheight, uint8_t alpha_value )
881 {
882         uint8_t *output = NULL;
883
884         if ( input != NULL && ( iwidth != owidth || iheight != oheight ) && ( owidth > 6 && oheight > 6 ) )
885         {
886                 uint8_t *out_line;
887                 int offset_x = ( owidth - iwidth ) / 2;
888                 int offset_y = ( oheight - iheight ) / 2;
889                 int iused = iwidth;
890
891                 output = mlt_pool_alloc( owidth * oheight );
892                 memset( output, alpha_value, owidth * oheight );
893
894                 offset_x -= offset_x % 2;
895
896                 out_line = output + offset_y * owidth;
897                 out_line += offset_x;
898
899                 // Loop for the entirety of our output height.
900                 while ( iheight -- )
901                 {
902                         // We're in the input range for this row.
903                         memcpy( out_line, input, iused );
904
905                         // Move to next input line
906                         input += iwidth;
907
908                 // Move to next output line
909                 out_line += owidth;
910                 }
911         }
912
913         return output;
914 }
915
916 void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
917 {
918         // Calculate strides
919         int istride = iwidth * 2;
920         int ostride = owidth * 2;
921         int offset_x = ( owidth - iwidth );
922         int offset_y = ( oheight - iheight ) / 2;
923         uint8_t *in_line = input;
924         uint8_t *out_line;
925         int size = owidth * oheight;
926         uint8_t *p = output;
927
928         // Optimisation point
929         if ( output == NULL || input == NULL || ( owidth <= 6 || oheight <= 6 || iwidth <= 6 || oheight <= 6 ) )
930         {
931                 return;
932         }
933         else if ( iwidth == owidth && iheight == oheight )
934         {
935                 memcpy( output, input, iheight * istride );
936                 return;
937         }
938
939         while( size -- )
940         {
941                 *p ++ = 16;
942                 *p ++ = 128;
943         }
944
945         offset_x -= offset_x % 4;
946
947         out_line = output + offset_y * ostride;
948         out_line += offset_x;
949
950         // Loop for the entirety of our output height.
951         while ( iheight -- )
952         {
953                 // We're in the input range for this row.
954                 memcpy( out_line, in_line, iwidth * 2 );
955
956                 // Move to next input line
957                 in_line += istride;
958
959                 // Move to next output line
960                 out_line += ostride;
961         }
962 }
963
964 /** A resizing function for yuv422 frames - this does not rescale, but simply
965         resizes. It assumes yuv422 images available on the frame so use with care.
966 */
967
968 uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight )
969 {
970         // Get properties
971         mlt_properties properties = MLT_FRAME_PROPERTIES( this );
972
973         // Get the input image, width and height
974         uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
975         uint8_t *alpha = mlt_frame_get_alpha_mask( this );
976
977         int iwidth = mlt_properties_get_int( properties, "width" );
978         int iheight = mlt_properties_get_int( properties, "height" );
979
980         // If width and height are correct, don't do anything
981         if ( iwidth != owidth || iheight != oheight )
982         {
983                 uint8_t alpha_value = mlt_properties_get_int( properties, "resize_alpha" );
984
985                 // Create the output image
986                 uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
987
988                 // Call the generic resize
989                 mlt_resize_yuv422( output, owidth, oheight, input, iwidth, iheight );
990
991                 // Now update the frame
992                 mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
993                 mlt_properties_set_int( properties, "width", owidth );
994                 mlt_properties_set_int( properties, "height", oheight );
995
996                 // We should resize the alpha too
997                 alpha = mlt_resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value );
998                 if ( alpha != NULL )
999                 {
1000                         mlt_properties_set_data( properties, "alpha", alpha, owidth * oheight, ( mlt_destructor )mlt_pool_release, NULL );
1001                         this->get_alpha_mask = NULL;
1002                 }
1003
1004                 // Return the output
1005                 return output;
1006         }
1007         // No change, return input
1008         return input;
1009 }
1010
1011 /** A rescaling function for yuv422 frames - low quality, and provided for testing
1012         only. It assumes yuv422 images available on the frame so use with care.
1013 */
1014
1015 uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
1016 {
1017         // Get properties
1018         mlt_properties properties = MLT_FRAME_PROPERTIES( this );
1019
1020         // Get the input image, width and height
1021         uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
1022         int iwidth = mlt_properties_get_int( properties, "width" );
1023         int iheight = mlt_properties_get_int( properties, "height" );
1024
1025         // If width and height are correct, don't do anything
1026         if ( iwidth != owidth || iheight != oheight )
1027         {
1028                 // Create the output image
1029                 uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
1030
1031                 // Calculate strides
1032                 int istride = iwidth * 2;
1033                 int ostride = owidth * 2;
1034
1035                 iwidth = iwidth - ( iwidth % 4 );
1036
1037                 // Derived coordinates
1038                 int dy, dx;
1039
1040         // Calculate ranges
1041         int out_x_range = owidth / 2;
1042         int out_y_range = oheight / 2;
1043         int in_x_range = iwidth / 2;
1044         int in_y_range = iheight / 2;
1045
1046         // Output pointers
1047         register uint8_t *out_line = output;
1048         register uint8_t *out_ptr;
1049
1050         // Calculate a middle pointer
1051         uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2;
1052         uint8_t *in_line;
1053
1054                 // Generate the affine transform scaling values
1055                 register int scale_width = ( iwidth << 16 ) / owidth;
1056                 register int scale_height = ( iheight << 16 ) / oheight;
1057                 register int base = 0;
1058
1059                 int outer = out_x_range * scale_width;
1060                 int bottom = out_y_range * scale_height;
1061
1062         // Loop for the entirety of our output height.
1063         for ( dy = - bottom; dy < bottom; dy += scale_height )
1064         {
1065                 // Start at the beginning of the line
1066                 out_ptr = out_line;
1067         
1068                 // Pointer to the middle of the input line
1069                 in_line = in_middle + ( dy >> 16 ) * istride;
1070
1071                 // Loop for the entirety of our output row.
1072                 for ( dx = - outer; dx < outer; dx += scale_width )
1073                 {
1074                                 base = dx >> 15;
1075                                 base &= 0xfffffffe;
1076                                 *out_ptr ++ = *( in_line + base );
1077                                 base &= 0xfffffffc;
1078                                 *out_ptr ++ = *( in_line + base + 1 );
1079                                 dx += scale_width;
1080                                 base = dx >> 15;
1081                                 base &= 0xfffffffe;
1082                                 *out_ptr ++ = *( in_line + base );
1083                                 base &= 0xfffffffc;
1084                                 *out_ptr ++ = *( in_line + base + 3 );
1085                 }
1086
1087                 // Move to next output line
1088                 out_line += ostride;
1089         }
1090
1091                 // Now update the frame
1092                 mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
1093                 mlt_properties_set_int( properties, "width", owidth );
1094                 mlt_properties_set_int( properties, "height", oheight );
1095
1096                 // Return the output
1097                 return output;
1098         }
1099
1100         // No change, return input
1101         return input;
1102 }
1103
1104 int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
1105 {
1106         int ret = 0;
1107         int16_t *src, *dest;
1108         int frequency_src = *frequency, frequency_dest = *frequency;
1109         int channels_src = *channels, channels_dest = *channels;
1110         int samples_src = *samples, samples_dest = *samples;
1111         int i, j;
1112         double d = 0, s = 0;
1113
1114         mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
1115         mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
1116
1117         int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
1118         mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
1119         if ( silent )
1120                 memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
1121
1122         silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
1123         mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
1124         if ( silent )
1125                 memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
1126
1127         if ( channels_src > 6 )
1128                 channels_src = 0;
1129         if ( channels_dest > 6 )
1130                 channels_dest = 0;
1131         if ( samples_src > 4000 )
1132                 samples_src = 0;
1133         if ( samples_dest > 4000 )
1134                 samples_dest = 0;
1135
1136         // determine number of samples to process
1137         *samples = samples_src < samples_dest ? samples_src : samples_dest;
1138         *channels = channels_src < channels_dest ? channels_src : channels_dest;
1139         *buffer = dest;
1140         *frequency = frequency_dest;
1141
1142         // Compute a smooth ramp over start to end
1143         float weight = weight_start;
1144         float weight_step = ( weight_end - weight_start ) / *samples;
1145
1146         if ( src == dest )
1147         {
1148                 *samples = samples_src;
1149                 *channels = channels_src;
1150                 *buffer = src;
1151                 *frequency = frequency_src;
1152                 return ret;
1153         }
1154
1155         // Mixdown
1156         for ( i = 0; i < *samples; i++ )
1157         {
1158                 for ( j = 0; j < *channels; j++ )
1159                 {
1160                         if ( j < channels_dest )
1161                                 d = (double) dest[ i * channels_dest + j ];
1162                         if ( j < channels_src )
1163                                 s = (double) src[ i * channels_src + j ];
1164                         dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
1165                 }
1166                 weight += weight_step;
1167         }
1168
1169         return ret;
1170 }
1171
1172 // Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
1173 // to allow mixing without volume hacking
1174 int mlt_frame_combine_audio( mlt_frame this, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
1175 {
1176         int ret = 0;
1177         int16_t *src, *dest;
1178         int frequency_src = *frequency, frequency_dest = *frequency;
1179         int channels_src = *channels, channels_dest = *channels;
1180         int samples_src = *samples, samples_dest = *samples;
1181         int i, j;
1182         double vp[ 6 ];
1183         double b_weight = 1.0;
1184
1185         if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
1186                 b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
1187
1188         mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
1189         mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
1190
1191         int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
1192         mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
1193         if ( silent )
1194                 memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
1195
1196         silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
1197         mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
1198         if ( silent )
1199                 memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
1200
1201         if ( src == dest )
1202         {
1203                 *samples = samples_src;
1204                 *channels = channels_src;
1205                 *buffer = src;
1206                 *frequency = frequency_src;
1207                 return ret;
1208         }
1209
1210         // determine number of samples to process
1211         *samples = samples_src < samples_dest ? samples_src : samples_dest;
1212         *channels = channels_src < channels_dest ? channels_src : channels_dest;
1213         *buffer = dest;
1214         *frequency = frequency_dest;
1215
1216         for ( j = 0; j < *channels; j++ )
1217                 vp[ j ] = ( double )dest[ j ];
1218
1219         double Fc = 0.5;
1220         double B = exp(-2.0 * M_PI * Fc);
1221         double A = 1.0 - B;
1222         double v;
1223         
1224         for ( i = 0; i < *samples; i++ )
1225         {
1226                 for ( j = 0; j < *channels; j++ )
1227                 {
1228                         v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
1229                         v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
1230                         vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
1231                 }
1232         }
1233
1234         return ret;
1235 }
1236
1237 /* Will this break when mlt_position is converted to double? -Zach */
1238 int mlt_sample_calculator( float fps, int frequency, int64_t position )
1239 {
1240         int samples = 0;
1241
1242         if ( ( int )( fps * 100 ) == 2997 )
1243         {
1244                 samples = frequency / 30;
1245
1246                 switch ( frequency )
1247                 {
1248                         case 48000:
1249                                 if ( position % 5 != 0 )
1250                                         samples += 2;
1251                                 break;
1252                         case 44100:
1253                                 if ( position % 300 == 0 )
1254                                         samples = 1471;
1255                                 else if ( position % 30 == 0 )
1256                                         samples = 1470;
1257                                 else if ( position % 2 == 0 )
1258                                         samples = 1472;
1259                                 else
1260                                         samples = 1471;
1261                                 break;
1262                         case 32000:
1263                                 if ( position % 30 == 0 )
1264                                         samples = 1068;
1265                                 else if ( position % 29 == 0 )
1266                                         samples = 1067;
1267                                 else if ( position % 4 == 2 )
1268                                         samples = 1067;
1269                                 else
1270                                         samples = 1068;
1271                                 break;
1272                         default:
1273                                 samples = 0;
1274                 }
1275         }
1276         else if ( fps != 0 )
1277         {
1278                 samples = frequency / fps;
1279         }
1280
1281         return samples;
1282 }
1283
1284 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t frame )
1285 {
1286         int64_t samples = 0;
1287
1288         // TODO: Correct rules for NTSC and drop the * 100 hack
1289         if ( ( int )( fps * 100 ) == 2997 )
1290         {
1291                 samples = ( ( double )( frame * frequency ) / 30 );
1292                 switch( frequency )
1293                 {
1294                         case 48000:
1295                                 samples += 2 * ( frame / 5 );
1296                                 break;
1297                         case 44100:
1298                                 samples += frame + ( frame / 2 ) - ( frame / 30 ) + ( frame / 300 );
1299                                 break;
1300                         case 32000:
1301                                 samples += ( 2 * frame ) - ( frame / 4 ) - ( frame / 29 );
1302                                 break;
1303                 }
1304         }
1305         else if ( fps != 0 )
1306         {
1307                 samples = ( ( frame * frequency ) / ( int )fps );
1308         }
1309
1310         return samples;
1311 }