]> git.sesse.net Git - mlt/blob - src/framework/mlt_frame.c
2fef7c080de63e6ac2ef088aeddba86f6c77f62f
[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 program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #include "mlt_frame.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 /** Constructor for a frame.
28 */
29
30 mlt_frame mlt_frame_init( )
31 {
32         // Allocate a frame
33         mlt_frame this = calloc( sizeof( struct mlt_frame_s ), 1 );
34
35         if ( this != NULL )
36         {
37                 // Initialise the properties
38                 mlt_properties properties = &this->parent;
39                 mlt_properties_init( properties, this );
40
41                 // Set default properties on the frame
42                 mlt_properties_set_position( properties, "_position", 0.0 );
43                 mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
44                 mlt_properties_set_int( properties, "width", 720 );
45                 mlt_properties_set_int( properties, "height", 576 );
46                 mlt_properties_set_double( properties, "aspect_ratio", 4.0 / 3.0 );
47                 mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
48                 mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
49         }
50         return this;
51 }
52
53 /** Fetch the frames properties.
54 */
55
56 mlt_properties mlt_frame_properties( mlt_frame this )
57 {
58         return &this->parent;
59 }
60
61 /** Check if we have a way to derive something other than a test card.
62 */
63
64 int mlt_frame_is_test_card( mlt_frame this )
65 {
66         return mlt_properties_get_int( mlt_frame_properties( this ), "test_image" );
67 }
68
69 /** Check if we have a way to derive something than test audio.
70 */
71
72 int mlt_frame_is_test_audio( mlt_frame this )
73 {
74         return this->get_audio == NULL || mlt_properties_get_int( mlt_frame_properties( this ), "test_audio" );
75 }
76
77 /** Get the aspect ratio of the frame.
78 */
79
80 double mlt_frame_get_aspect_ratio( mlt_frame this )
81 {
82         return mlt_properties_get_double( mlt_frame_properties( this ), "aspect_ratio" );
83 }
84
85 /** Set the aspect ratio of the frame.
86 */
87
88 int mlt_frame_set_aspect_ratio( mlt_frame this, double value )
89 {
90         return mlt_properties_set_double( mlt_frame_properties( this ), "aspect_ratio", value );
91 }
92
93 /** Get the position of this frame.
94 */
95
96 mlt_position mlt_frame_get_position( mlt_frame this )
97 {
98         return mlt_properties_get_position( mlt_frame_properties( this ), "_position" );
99 }
100
101 /** Set the position of this frame.
102 */
103
104 int mlt_frame_set_position( mlt_frame this, mlt_position value )
105 {
106         return mlt_properties_set_position( mlt_frame_properties( this ), "_position", value );
107 }
108
109 /** Stack a get_image callback.
110 */
111
112 int mlt_frame_push_get_image( mlt_frame this, mlt_get_image get_image )
113 {
114         int ret = this->stack_get_image_size >= 10;
115         if ( ret == 0 )
116                 this->stack_get_image[ this->stack_get_image_size ++ ] = get_image;
117         return ret;
118 }
119
120 /** Pop a get_image callback.
121 */
122
123 mlt_get_image mlt_frame_pop_get_image( mlt_frame this )
124 {
125         mlt_get_image result = NULL;
126         if ( this->stack_get_image_size > 0 )
127                 result = this->stack_get_image[ -- this->stack_get_image_size ];
128         return result;
129 }
130
131 /** Push a frame.
132 */
133
134 int mlt_frame_push_frame( mlt_frame this, mlt_frame that )
135 {
136         int ret = this->stack_frame_size >= 10;
137         if ( ret == 0 )
138                 this->stack_frame[ this->stack_frame_size ++ ] = that;
139         return ret;
140 }
141
142 /** Pop a frame.
143 */
144
145 mlt_frame mlt_frame_pop_frame( mlt_frame this )
146 {
147         mlt_frame result = NULL;
148         if ( this->stack_frame_size > 0 )
149                 result = this->stack_frame[ -- this->stack_frame_size ];
150         return result;
151 }
152
153 int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
154 {
155         mlt_properties properties = mlt_frame_properties( this );
156         mlt_get_image get_image = mlt_frame_pop_get_image( this );
157         
158         if ( get_image != NULL )
159         {
160                 return get_image( this, buffer, format, width, height, writable );
161         }
162         else if ( mlt_properties_get_data( properties, "image", NULL ) != NULL )
163         {
164                 *format = mlt_image_yuv422;
165                 *buffer = mlt_properties_get_data( properties, "image", NULL );
166                 *width = mlt_properties_get_int( properties, "width" );
167                 *height = mlt_properties_get_int( properties, "height" );
168         }
169         else
170         {
171                 uint8_t *p;
172                 uint8_t *q;
173                 int size = 0;
174
175                 *width = *width == 0 ? 720 : *width;
176                 *height = *height == 0 ? 576 : *height;
177                 size = *width * *height;
178
179                 mlt_properties_set_int( properties, "width", *width );
180                 mlt_properties_set_int( properties, "height", *height );
181
182                 switch( *format )
183                 {
184                         case mlt_image_none:
185                                 size = 0;
186                                 *buffer = NULL;
187                                 break;
188                         case mlt_image_rgb24:
189                                 size *= 3;
190                                 *buffer = malloc( size );
191                                 if ( *buffer )
192                                         memset( *buffer, 255, size );
193                                 break;
194                         case mlt_image_rgb24a:
195                                 size *= 4;
196                                 *buffer = malloc( size );
197                                 if ( *buffer )
198                                         memset( *buffer, 255, size );
199                                 break;
200                         case mlt_image_yuv422:
201                                 size *= 2;
202                                 *buffer = malloc( size );
203                                 p = *buffer;
204                                 q = p + size;
205                                 while ( p != NULL && p != q )
206                                 {
207                                         *p ++ = 255;
208                                         *p ++ = 128;
209                                 }
210                                 break;
211                         case mlt_image_yuv420p:
212                                 size = size * 3 / 2;
213                                 *buffer = malloc( size );
214                                 if ( *buffer )
215                                         memset( *buffer, 255, size );
216                                 break;
217                 }
218
219                 mlt_properties_set_data( properties, "image", *buffer, size, free, NULL );
220                 mlt_properties_set_int( properties, "test_image", 1 );
221         }
222
223         return 0;
224 }
225
226 uint8_t *mlt_frame_get_alpha_mask( mlt_frame this )
227 {
228         if ( this->get_alpha_mask != NULL )
229                 return this->get_alpha_mask( this );
230         return NULL;
231 }
232
233 int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
234 {
235         mlt_properties properties = mlt_frame_properties( this );
236
237         if ( this->get_audio != NULL )
238         {
239                 return this->get_audio( this, buffer, format, frequency, channels, samples );
240         }
241         else
242         {
243                 int size = 0;
244                 *samples = *samples <= 0 ? 1920 : *samples;
245                 *channels = *channels <= 0 ? 2 : *channels;
246                 *frequency = *frequency <= 0 ? 48000 : *frequency;
247                 size = *samples * *channels * sizeof( int16_t );
248                 *buffer = malloc( size );
249                 if ( *buffer != NULL )
250                         memset( *buffer, 0, size );
251                 mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL );
252                 mlt_properties_set_int( properties, "test_audio", 1 );
253         }
254         return 0;
255 }
256
257 void mlt_frame_close( mlt_frame this )
258 {
259         mlt_properties_close( &this->parent );
260         free( this );
261 }
262
263 /***** convenience functions *****/
264 #define RGB2YUV(r, g, b, y, u, v)\
265   y = (306*r + 601*g + 117*b)  >> 10;\
266   u = ((-172*r - 340*g + 512*b) >> 10)  + 128;\
267   v = ((512*r - 429*g - 83*b) >> 10) + 128;\
268   y = y < 0 ? 0 : y;\
269   u = u < 0 ? 0 : u;\
270   v = v < 0 ? 0 : v;\
271   y = y > 255 ? 255 : y;\
272   u = u > 255 ? 255 : u;\
273   v = v > 255 ? 255 : v
274
275 int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
276 {
277         int ret = 0;
278         register int y0, y1, u0, u1, v0, v1;
279         register int r, g, b;
280         register uint8_t *d = yuv;
281         register int i, j;
282
283         for ( i = 0; i < height; i++ )
284         {
285                 register uint8_t *s = rgba + ( stride * i );
286                 for ( j = 0; j < ( width / 2 ); j++ )
287                 {
288                         r = *s++;
289                         g = *s++;
290                         b = *s++;
291                         *alpha++ = *s++;
292                         RGB2YUV (r, g, b, y0, u0 , v0);
293                         r = *s++;
294                         g = *s++;
295                         b = *s++;
296                         *alpha++ = *s++;
297                         RGB2YUV (r, g, b, y1, u1 , v1);
298                         *d++ = y0;
299                         *d++ = (u0+u1) >> 1;
300                         *d++ = y1;
301                         *d++ = (v0+v1) >> 1;
302                 }
303                 if ( width % 2 )
304                 {
305                         r = *s++;
306                         g = *s++;
307                         b = *s++;
308                         *alpha++ = *s++;
309                         RGB2YUV (r, g, b, y0, u0 , v0);
310                         *d++ = y0;
311                         *d++ = u0;
312                 }
313         }
314         return ret;
315 }
316
317 int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
318 {
319         int ret = 0;
320         register int y0, y1, u0, u1, v0, v1;
321         register int r, g, b;
322         register uint8_t *d = yuv;
323         register int i, j;
324
325         for ( i = 0; i < height; i++ )
326         {
327                 register uint8_t *s = rgb + ( stride * i );
328                 for ( j = 0; j < ( width / 2 ); j++ )
329                 {
330                         r = *s++;
331                         g = *s++;
332                         b = *s++;
333                         RGB2YUV (r, g, b, y0, u0 , v0);
334                         r = *s++;
335                         g = *s++;
336                         b = *s++;
337                         RGB2YUV (r, g, b, y1, u1 , v1);
338                         *d++ = y0;
339                         *d++ = (u0+u1) >> 1;
340                         *d++ = y1;
341                         *d++ = (v0+v1) >> 1;
342                 }
343                 if ( width % 2 )
344                 {
345                         r = *s++;
346                         g = *s++;
347                         b = *s++;
348                         RGB2YUV (r, g, b, y0, u0 , v0);
349                         *d++ = y0;
350                         *d++ = u0;
351                 }
352         }
353         return ret;
354 }
355
356 int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv )
357 {
358         int ret = 0;
359         register int i, j;
360
361         int half = width >> 1;
362
363         uint8_t *Y = yuv420p;
364         uint8_t *U = Y + width * height;
365         uint8_t *V = U + width * height / 4;
366
367         register uint8_t *d = yuv;
368
369         for ( i = 0; i < height; i++ )
370         {
371                 register uint8_t *u = U + ( i / 2 ) * ( half );
372                 register uint8_t *v = V + ( i / 2 ) * ( half );
373
374                 for ( j = 0; j < half; j++ )
375                 {
376                         *d ++ = *Y ++;
377                         *d ++ = *u ++;
378                         *d ++ = *Y ++;
379                         *d ++ = *v ++;
380                 }
381         }
382         return ret;
383 }
384
385 void *memfill( void *dst, void *src, int l, int elements )
386 {
387         int i = 0;
388         if ( l == 2 )
389         {
390                 uint8_t *p = dst;
391                 uint8_t *src1 = src;
392                 uint8_t *src2 = src + 1;
393                 for ( i = 0; i < elements; i ++ )
394                 {
395                         *p ++ = *src1;
396                         *p ++ = *src2;
397                 }
398                 dst = p;
399         }
400         else
401         {
402                 for ( i = 0; i < elements; i ++ )
403                         dst = memcpy( dst, src, l ) + l;
404         }
405         return dst;
406 }
407
408 void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
409 {
410         // Calculate strides
411         int istride = iwidth * 2;
412         int ostride = owidth * 2;
413
414         iwidth = iwidth - ( iwidth % 4 );
415         owidth = owidth - ( owidth % 4 );
416         iheight = iheight - ( iheight % 2 );
417         oheight = oheight - ( oheight % 2 );
418
419         // Optimisation point
420         if ( iwidth == owidth && iheight == oheight )
421                 memcpy( output, input, iheight * istride );
422
423         // Coordinates (0,0 is middle of output)
424         int y;
425
426         // Calculate ranges
427         int out_x_range = owidth / 2;
428         int out_y_range = oheight / 2;
429         int in_x_range = iwidth / 2 < out_x_range ? iwidth / 2 : out_x_range;
430         int in_y_range = iheight / 2 < out_y_range ? iheight / 2 : out_y_range;
431
432         // Output pointers
433         uint8_t *out_line = output;
434         uint8_t *out_ptr = out_line;
435
436         // Calculate a middle and possibly invalid pointer in the input
437         uint8_t *in_middle = input + istride * ( iheight / 2 ) + ( iwidth / 2 ) * 2;
438         int in_line = - in_y_range * istride - in_x_range * 2;
439
440         uint8_t black[ 2 ] = { 16, 128 };
441
442         // Loop for the entirety of our output height.
443         for ( y = - out_y_range; y < out_y_range ; y ++ )
444         {
445         // Start at the beginning of the line
446         out_ptr = out_line;
447
448                 if ( abs( y ) < iheight / 2 )
449                 {
450                         // Fill the outer part with black
451                         out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
452
453                 // We're in the input range for this row.
454                         memcpy( out_ptr, in_middle + in_line, 2 * iwidth );
455                         out_ptr += 2 * iwidth;
456
457                         // Fill the outer part with black
458                         out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
459
460                 // Move to next input line
461                 in_line += istride;
462                 }
463                 else
464                 {
465                         // Fill whole line with black
466                         out_ptr = memfill( out_ptr, black, 2, owidth );
467                 }
468
469         // Move to next output line
470         out_line += ostride;
471         }
472 }
473
474 /** A resizing function for yuv422 frames - this does not rescale, but simply
475         resizes. It assumes yuv422 images available on the frame so use with care.
476 */
477
478 uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight )
479 {
480         // Get properties
481         mlt_properties properties = mlt_frame_properties( this );
482
483         // Get the input image, width and height
484         uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
485         int iwidth = mlt_properties_get_int( properties, "width" );
486         int iheight = mlt_properties_get_int( properties, "height" );
487
488         // If width and height are correct, don't do anything
489         if ( iwidth != owidth || iheight != oheight )
490         {
491                 // Create the output image
492                 uint8_t *output = malloc( owidth * oheight * 2 );
493
494                 // Call the generic resize
495                 mlt_resize_yuv422( output, owidth, oheight, input, iwidth, iheight );
496
497                 // Now update the frame
498                 mlt_properties_set_data( properties, "image", output, owidth * oheight * 2, free, NULL );
499                 mlt_properties_set_int( properties, "width", owidth );
500                 mlt_properties_set_int( properties, "height", oheight );
501                 mlt_frame_set_aspect_ratio( this, 4.0/3.0/*( float )owidth / oheight*/ );
502
503                 // Return the output
504                 return output;
505         }
506
507         // No change, return input
508         return input;
509 }
510
511 /** A rescaling function for yuv422 frames - low quality, and provided for testing
512         only. It assumes yuv422 images available on the frame so use with care.
513 */
514
515 uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
516 {
517         // Get properties
518         mlt_properties properties = mlt_frame_properties( this );
519
520         // Get the input image, width and height
521         uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
522         int iwidth = mlt_properties_get_int( properties, "width" );
523         int iheight = mlt_properties_get_int( properties, "height" );
524
525         // If width and height are correct, don't do anything
526         if ( iwidth != owidth || iheight != oheight )
527         {
528                 // Create the output image
529                 uint8_t *output = malloc( owidth * oheight * 2 );
530
531                 // Calculate strides
532                 int istride = iwidth * 2;
533                 int ostride = owidth * 2;
534
535                 iwidth = iwidth - ( iwidth % 4 );
536
537         // Coordinates (0,0 is middle of output)
538         int y, x;
539
540                 // Derived coordinates
541                 int dy, dx;
542
543         // Calculate ranges
544         int out_x_range = owidth / 2;
545         int out_y_range = oheight / 2;
546         int in_x_range = iwidth / 2;
547         int in_y_range = iheight / 2;
548
549         // Output pointers
550         uint8_t *out_line = output;
551         uint8_t *out_ptr;
552
553         // Calculate a middle pointer
554         uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2;
555         uint8_t *in_line;
556                 uint8_t *in_ptr;
557
558                 // Generate the affine transform scaling values
559                 int scale_width = ( iwidth << 16 ) / owidth;
560                 int scale_height = ( iheight << 16 ) / oheight;
561
562         // Loop for the entirety of our output height.
563         for ( y = - out_y_range; y < out_y_range ; y ++ )
564         {
565                         // Calculate the derived y value
566                         dy = ( scale_height * y ) >> 16;
567
568                 // Start at the beginning of the line
569                 out_ptr = out_line;
570         
571                 // Pointer to the middle of the input line
572                 in_line = in_middle + dy * istride;
573         
574                 // Loop for the entirety of our output row.
575                 for ( x = - out_x_range; x < out_x_range; x += 1 )
576                 {
577                                 // Calculated the derived x
578                                 dx = ( scale_width * x ) >> 16;
579
580                 // We're in the input range for this row.
581                                 in_ptr = in_line + ( dx << 1 );
582                 *out_ptr ++ = *in_ptr ++;
583                                 in_ptr = in_line + ( ( dx >> 1 ) << 2 ) + ( ( x & 1 ) << 1 ) + 1;
584                 *out_ptr ++ = *in_ptr;
585                 }
586
587                 // Move to next output line
588                 out_line += ostride;
589         }
590
591                 // Now update the frame
592                 mlt_properties_set_data( properties, "image", output, owidth * oheight * 2, free, NULL );
593                 mlt_properties_set_int( properties, "width", owidth );
594                 mlt_properties_set_int( properties, "height", oheight );
595
596                 // Return the output
597                 return output;
598         }
599
600         // No change, return input
601         return input;
602 }
603
604 int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
605 {
606         int ret = 0;
607         int16_t *p_src, *p_dest;
608         int16_t *src, *dest;
609         //static int16_t *extra_src = NULL, *extra_dest = NULL;
610         static int extra_src_samples = 0, extra_dest_samples = 0;
611         int frequency_src = *frequency, frequency_dest = *frequency;
612         int channels_src = *channels, channels_dest = *channels;
613         int samples_src = *samples, samples_dest = *samples;
614         int i, j;
615         double d = 0, s = 0;
616
617         mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest );
618         //fprintf( stderr, "mix: frame dest samples %d channels %d position %lld\n", samples_dest, channels_dest, mlt_properties_get_position( mlt_frame_properties( this ), "_position" ) );
619         mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src );
620         //fprintf( stderr, "mix: frame src  samples %d channels %d\n", samples_src, channels_src );
621         src = p_src;
622         dest = p_dest;
623         if ( channels_src > 6 )
624                 channels_src = 0;
625         if ( channels_dest > 6 )
626                 channels_dest = 0;
627         if ( samples_src > 4000 )
628                 samples_src = 0;
629         if ( samples_dest > 4000 )
630                 samples_dest = 0;
631
632 #if 0
633         // Append new samples to leftovers
634         if ( extra_dest_samples > 0 )
635         {
636                 fprintf( stderr, "prepending %d samples to dest\n", extra_dest_samples );
637                 dest = realloc( extra_dest, ( samples_dest + extra_dest_samples ) * 2 * channels_dest );
638                 memcpy( &extra_dest[ extra_dest_samples * channels_dest ], p_dest, samples_dest * 2 * channels_dest );
639         }
640         else
641                 dest = p_dest;
642         if ( extra_src_samples > 0 )
643         {
644                 fprintf( stderr, "prepending %d samples to src\n", extra_src_samples );
645                 src = realloc( extra_src, ( samples_src + extra_src_samples ) * 2 * channels_src );
646                 memcpy( &extra_src[ extra_src_samples * channels_src ], p_src, samples_src * 2 * channels_src );
647         }
648         else
649                 src = p_src;
650 #endif
651
652         // determine number of samples to process       
653         if ( samples_src + extra_src_samples < samples_dest + extra_dest_samples )
654                 *samples = samples_src + extra_src_samples;
655         else if ( samples_dest + extra_dest_samples < samples_src + extra_src_samples )
656                 *samples = samples_dest + extra_dest_samples;
657         
658         *channels = channels_src < channels_dest ? channels_src : channels_dest;
659         *buffer = p_dest;
660         *frequency = frequency_dest;
661
662         // Mixdown
663         for ( i = 0; i < *samples; i++ )
664         {
665                 for ( j = 0; j < *channels; j++ )
666                 {
667                         if ( j < channels_dest )
668                                 d = (double) dest[ i * channels_dest + j ];
669                         if ( j < channels_src )
670                                 s = (double) src[ i * channels_src + j ];
671                         dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
672                 }
673         }
674
675         // We have to copy --sigh
676         if ( dest != p_dest )
677                 memcpy( p_dest, dest, *samples * 2 * *channels );
678
679 #if 0
680         // Store the leftovers
681         if ( samples_src + extra_src_samples < samples_dest + extra_dest_samples )
682         {
683                 extra_dest_samples = ( samples_dest + extra_dest_samples ) - ( samples_src + extra_src_samples );
684                 size_t size = extra_dest_samples * 2 * channels_dest;
685                 fprintf( stderr, "storing %d samples from dest\n", extra_dest_samples );
686                 if ( extra_dest )
687                         free( extra_dest );
688                 extra_dest = malloc( size );
689                 if ( extra_dest )
690                         memcpy( extra_dest, &p_dest[ ( samples_dest - extra_dest_samples - 1 ) * channels_dest ], size );
691                 else
692                         extra_dest_samples = 0;
693         }
694         else if ( samples_dest + extra_dest_samples < samples_src + extra_src_samples )
695         {
696                 extra_src_samples = ( samples_src + extra_src_samples ) - ( samples_dest + extra_dest_samples );
697                 size_t size = extra_src_samples * 2 * channels_src;
698                 fprintf( stderr, "storing %d samples from src\n", extra_dest_samples );
699                 if ( extra_src )
700                         free( extra_src );
701                 extra_src = malloc( size );
702                 if ( extra_src )
703                         memcpy( extra_src, &p_src[ ( samples_src - extra_src_samples - 1 ) * channels_src ], size );
704                 else
705                         extra_src_samples = 0;
706         }
707 #endif
708         
709         return ret;
710 }
711
712 int mlt_sample_calculator( float fps, int frequency, int64_t position )
713 {
714         int samples = 0;
715
716         if ( fps > 29 && fps <= 30 )
717         {
718                 samples = frequency / 30;
719
720                 switch ( frequency )
721                 {
722                         case 48000:
723                                 if ( position % 5 != 0 )
724                                         samples += 2;
725                                 break;
726                         case 44100:
727                                 if ( position % 300 == 0 )
728                                         samples = 1471;
729                                 else if ( position % 30 == 0 )
730                                         samples = 1470;
731                                 else if ( position % 2 == 0 )
732                                         samples = 1472;
733                                 else
734                                         samples = 1471;
735                                 break;
736                         case 32000:
737                                 if ( position % 30 == 0 )
738                                         samples = 1068;
739                                 else if ( position % 29 == 0 )
740                                         samples = 1067;
741                                 else if ( position % 4 == 2 )
742                                         samples = 1067;
743                                 else
744                                         samples = 1068;
745                                 break;
746                         default:
747                                 samples = 0;
748                 }
749         }
750         else if ( fps != 0 )
751         {
752                 samples = frequency / fps;
753         }
754
755         return samples;
756 }
757