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