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