]> git.sesse.net Git - mlt/blob - src/framework/mlt_frame.c
fix possible crash in mlt_frame_get_waveform
[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 #include "mlt_log.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 /** Construct a frame object.
35  *
36  * \public \memberof mlt_frame_s
37  * \param service the pointer to any service that can provide access to the profile
38  * \return a frame object on success or NULL if there was an allocation error
39  */
40
41 mlt_frame mlt_frame_init( mlt_service service )
42 {
43         // Allocate a frame
44         mlt_frame self = calloc( 1, sizeof( struct mlt_frame_s ) );
45
46         if ( self != NULL )
47         {
48                 mlt_profile profile = mlt_service_profile( service );
49
50                 // Initialise the properties
51                 mlt_properties properties = &self->parent;
52                 mlt_properties_init( properties, self );
53
54                 // Set default properties on the frame
55                 mlt_properties_set_position( properties, "_position", 0.0 );
56                 mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
57                 mlt_properties_set_int( properties, "width", profile? profile->width : 720 );
58                 mlt_properties_set_int( properties, "height", profile? profile->height : 576 );
59                 mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( NULL ) );
60                 mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
61                 mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
62
63                 // Construct stacks for frames and methods
64                 self->stack_image = mlt_deque_init( );
65                 self->stack_audio = mlt_deque_init( );
66                 self->stack_service = mlt_deque_init( );
67         }
68
69         return self;
70 }
71
72 /** Get a frame's properties.
73  *
74  * \public \memberof mlt_frame_s
75  * \param self a frame
76  * \return the frame's properties or NULL if an invalid frame is supplied
77  */
78
79 mlt_properties mlt_frame_properties( mlt_frame self )
80 {
81         return self != NULL ? &self->parent : NULL;
82 }
83
84 /** Determine if the frame will produce a test card image.
85  *
86  * \public \memberof mlt_frame_s
87  * \param self a frame
88  * \return true (non-zero) if this will produce from a test card
89  */
90
91 int mlt_frame_is_test_card( mlt_frame self )
92 {
93         return mlt_deque_count( self->stack_image ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( self ), "test_image" );
94 }
95
96 /** Determine if the frame will produce audio from a test card.
97  *
98  * \public \memberof mlt_frame_s
99  * \param self a frame
100  * \return true (non-zero) if this will produce from a test card
101  */
102
103 int mlt_frame_is_test_audio( mlt_frame self )
104 {
105         return mlt_deque_count( self->stack_audio ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( self ), "test_audio" );
106 }
107
108 /** Get the sample aspect ratio of the frame.
109  *
110  * \public \memberof  mlt_frame_s
111  * \param self a frame
112  * \return the aspect ratio
113  */
114
115 double mlt_frame_get_aspect_ratio( mlt_frame self )
116 {
117         return mlt_properties_get_double( MLT_FRAME_PROPERTIES( self ), "aspect_ratio" );
118 }
119
120 /** Set the sample aspect ratio of the frame.
121  *
122  * \public \memberof mlt_frame_s
123  * \param self a frame
124  * \param value the new image sample aspect ratio
125  * \return true if error
126  */
127
128 int mlt_frame_set_aspect_ratio( mlt_frame self, double value )
129 {
130         return mlt_properties_set_double( MLT_FRAME_PROPERTIES( self ), "aspect_ratio", value );
131 }
132
133 /** Get the time position of this frame.
134  *
135  * This position is not necessarily the position as the original
136  * producer knows it. It could be the position that the playlist,
137  * multitrack, or tractor producer set.
138  *
139  * \public \memberof mlt_frame_s
140  * \param self a frame
141  * \return the position
142  * \see mlt_frame_original_position
143  */
144
145 mlt_position mlt_frame_get_position( mlt_frame self )
146 {
147         int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "_position" );
148         return pos < 0 ? 0 : pos;
149 }
150
151 /** Get the original time position of this frame.
152  *
153  * This is the position that the original producer set on the frame.
154  *
155  * \public \memberof mlt_frame_s
156  * \param self a frame
157  * \return the position
158  */
159
160 mlt_position mlt_frame_original_position( mlt_frame self )
161 {
162         int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "original_position" );
163         return pos < 0 ? 0 : pos;
164 }
165
166 /** Set the time position of this frame.
167  *
168  * \public \memberof mlt_frame_s
169  * \param self a frame
170  * \param value the position
171  * \return true if error
172  */
173
174 int mlt_frame_set_position( mlt_frame self, mlt_position value )
175 {
176         // Only set the original_position the first time.
177         if ( ! mlt_properties_get( MLT_FRAME_PROPERTIES( self ), "original_position" ) )
178                 mlt_properties_set_position( MLT_FRAME_PROPERTIES( self ), "original_position", value );
179         return mlt_properties_set_position( MLT_FRAME_PROPERTIES( self ), "_position", value );
180 }
181
182 /** Stack a get_image callback.
183  *
184  * \public \memberof mlt_frame_s
185  * \param self a frame
186  * \param the get_image callback
187  * \return true if error
188  */
189
190 int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image )
191 {
192         return mlt_deque_push_back( self->stack_image, get_image );
193 }
194
195 /** Pop a get_image callback.
196  *
197  * \public \memberof mlt_frame_s
198  * \param self a frame
199  * \return the get_image callback
200  */
201
202 mlt_get_image mlt_frame_pop_get_image( mlt_frame self )
203 {
204         return mlt_deque_pop_back( self->stack_image );
205 }
206
207 /** Push a frame.
208  *
209  * \public \memberof mlt_frame_s
210  * \param self a frame
211  * \param that the frame to push onto \p self
212  * \return true if error
213  */
214
215 int mlt_frame_push_frame( mlt_frame self, mlt_frame that )
216 {
217         return mlt_deque_push_back( self->stack_image, that );
218 }
219
220 /** Pop a frame.
221  *
222  * \public \memberof mlt_frame_s
223  * \param self a frame
224  * \return a frame that was previously pushed
225  */
226
227 mlt_frame mlt_frame_pop_frame( mlt_frame self )
228 {
229         return mlt_deque_pop_back( self->stack_image );
230 }
231
232 /** Push a service.
233  *
234  * \public \memberof mlt_frame_s
235  * \param self a frame
236  * \param that an opaque pointer
237  * \return true if error
238  */
239
240 int mlt_frame_push_service( mlt_frame self, void *that )
241 {
242         return mlt_deque_push_back( self->stack_image, that );
243 }
244
245 /** Pop a service.
246  *
247  * \public \memberof mlt_frame_s
248  * \param self a frame
249  * \return an opaque pointer to something previously pushed
250  */
251
252 void *mlt_frame_pop_service( mlt_frame self )
253 {
254         return mlt_deque_pop_back( self->stack_image );
255 }
256
257 /** Push a number.
258  *
259  * \public \memberof mlt_frame_s
260  * \param self a frame
261  * \param that an integer
262  * \return true if error
263  */
264
265 int mlt_frame_push_service_int( mlt_frame self, int that )
266 {
267         return mlt_deque_push_back_int( self->stack_image, that );
268 }
269
270 /** Pop a number.
271  *
272  * \public \memberof mlt_frame_s
273  * \param self a frame
274  * \return an integer that was previously pushed
275  */
276
277 int mlt_frame_pop_service_int( mlt_frame self )
278 {
279         return mlt_deque_pop_back_int( self->stack_image );
280 }
281
282 /** Push an audio item on the stack.
283  *
284  * \public \memberof mlt_frame_s
285  * \param self a frame
286  * \param that an opaque pointer
287  * \return true if error
288  */
289
290 int mlt_frame_push_audio( mlt_frame self, void *that )
291 {
292         return mlt_deque_push_back( self->stack_audio, that );
293 }
294
295 /** Pop an audio item from the stack
296  *
297  * \public \memberof mlt_frame_s
298  * \param self a frame
299  * \return an opaque pointer to something that was pushed onto the frame's audio stack
300  */
301
302 void *mlt_frame_pop_audio( mlt_frame self )
303 {
304         return mlt_deque_pop_back( self->stack_audio );
305 }
306
307 /** Return the service stack
308  *
309  * \public \memberof mlt_frame_s
310  * \param self a frame
311  * \return the service stack
312  */
313
314 mlt_deque mlt_frame_service_stack( mlt_frame self )
315 {
316         return self->stack_service;
317 }
318
319 /** Set a new image on the frame.
320   *
321   * \public \memberof mlt_frame_s
322   * \param self a frame
323   * \param image a pointer to the raw image data
324   * \param size the size of the image data in bytes (optional)
325   * \param destroy a function to deallocate \p image when the frame is closed (optional)
326   * \return true if error
327   */
328
329 int mlt_frame_set_image( mlt_frame self, uint8_t *image, int size, mlt_destructor destroy )
330 {
331         return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, size, destroy, NULL );
332 }
333
334 /** Set a new alpha channel on the frame.
335   *
336   * \public \memberof mlt_frame_s
337   * \param self a frame
338   * \param alpha a pointer to the alpha channel
339   * \param size the size of the alpha channel in bytes (optional)
340   * \param destroy a function to deallocate \p alpha when the frame is closed (optional)
341   * \return true if error
342   */
343
344 int mlt_frame_set_alpha( mlt_frame self, uint8_t *alpha, int size, mlt_destructor destroy )
345 {
346         self->get_alpha_mask = NULL;
347         return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "alpha", alpha, size, destroy, NULL );
348 }
349
350 /** Replace image stack with the information provided.
351  *
352  * This might prove to be unreliable and restrictive - the idea is that a transition
353  * which normally uses two images may decide to only use the b frame (ie: in the case
354  * of a composite where the b frame completely obscures the a frame).
355  *
356  * The image must be writable and the destructor for the image itself must be taken
357  * care of on another frame and that frame cannot have a replace applied to it...
358  * Further it assumes that no alpha mask is in use.
359  *
360  * For these reasons, it can only be used in a specific situation - when you have
361  * multiple tracks each with their own transition and these transitions are applied
362  * in a strictly reversed order (ie: highest numbered [lowest track] is processed
363  * first).
364  *
365  * More reliable approach - the cases should be detected during the process phase
366  * and the upper tracks should simply not be invited to stack...
367  *
368  * \public \memberof mlt_frame_s
369  * \param self a frame
370  * \param image a new image
371  * \param format the image format
372  * \param width the width of the new image
373  * \param height the height of the new image
374  */
375
376 void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height )
377 {
378         // Remove all items from the stack
379         while( mlt_deque_pop_back( self->stack_image ) ) ;
380
381         // Update the information
382         mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, 0, NULL, NULL );
383         mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "width", width );
384         mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "height", height );
385         mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "format", format );
386         self->get_alpha_mask = NULL;
387 }
388
389 /** Get the short name for an image format.
390  *
391  * \public \memberof mlt_frame_s
392  * \param format the image format
393  * \return a string
394  */
395
396 const char * mlt_image_format_name( mlt_image_format format )
397 {
398         switch ( format )
399         {
400                 case mlt_image_none:    return "none";
401                 case mlt_image_rgb24:   return "rgb24";
402                 case mlt_image_rgb24a:  return "rgb24a";
403                 case mlt_image_yuv422:  return "yuv422";
404                 case mlt_image_yuv420p: return "yuv420p";
405                 case mlt_image_opengl:  return "opengl";
406         }
407         return "invalid";
408 }
409
410 /** Get the number of bytes needed for an image.
411   *
412   * \public \memberof mlt_frame_s
413   * \param format the image format
414   * \param width width of the image in pixels
415   * \param height height of the image in pixels
416   * \param[out] bpp the number of bytes per pixel (optional)
417   * \return the number of bytes
418   */
419 int mlt_image_format_size( mlt_image_format format, int width, int height, int *bpp )
420 {
421         height += 1;
422         switch ( format )
423         {
424                 case mlt_image_none:
425                         if ( bpp ) *bpp = 0;
426                         return 0;
427                 case mlt_image_rgb24:
428                         if ( bpp ) *bpp = 3;
429                         return width * height * 3;
430                 case mlt_image_opengl:
431                 case mlt_image_rgb24a:
432                         if ( bpp ) *bpp = 4;
433                         return width * height * 4;
434                 case mlt_image_yuv422:
435                         if ( bpp ) *bpp = 2;
436                         return width * height * 2;
437                 case mlt_image_yuv420p:
438                         if ( bpp ) *bpp = 3 / 2;
439                         return width * height * 3 / 2;
440         }
441         return 0;
442 }
443
444 /** Get the image associated to the frame.
445  *
446  * You should express the desired format, width, and height as inputs. As long
447  * as the loader producer was used to generate this or the imageconvert filter
448  * was attached, then you will get the image back in the format you desire.
449  * However, you do not always get the width and height you request depending
450  * on properties and filters. You do not need to supply a pre-allocated
451  * buffer, but you should always supply the desired image format.
452  *
453  * \public \memberof mlt_frame_s
454  * \param self a frame
455  * \param[out] buffer an image buffer
456  * \param[in,out] format the image format
457  * \param[in,out] width the horizontal size in pixels
458  * \param[in,out] height the vertical size in pixels
459  * \param writable whether or not you will need to be able to write to the memory returned in \p buffer
460  * \return true if error
461  * \todo Better describe the width and height as inputs.
462  */
463
464 int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
465 {
466         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
467         mlt_get_image get_image = mlt_frame_pop_get_image( self );
468         mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
469         mlt_image_format requested_format = *format;
470         int error = 0;
471
472         if ( get_image )
473         {
474                 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
475                 error = get_image( self, buffer, format, width, height, writable );
476                 if ( !error && *buffer )
477                 {
478                         mlt_properties_set_int( properties, "width", *width );
479                         mlt_properties_set_int( properties, "height", *height );
480                         if ( self->convert_image && *buffer && requested_format != mlt_image_none )
481                                 self->convert_image( self, buffer, format, requested_format );
482                         mlt_properties_set_int( properties, "format", *format );
483                 }
484                 else
485                 {
486                         // Cause the image to be loaded from test card or fallback (white) below.
487                         mlt_frame_get_image( self, buffer, format, width, height, writable );
488                 }
489         }
490         else if ( mlt_properties_get_data( properties, "image", NULL ) )
491         {
492                 *format = mlt_properties_get_int( properties, "format" );
493                 *buffer = mlt_properties_get_data( properties, "image", NULL );
494                 *width = mlt_properties_get_int( properties, "width" );
495                 *height = mlt_properties_get_int( properties, "height" );
496                 if ( self->convert_image && *buffer && requested_format != mlt_image_none )
497                 {
498                         self->convert_image( self, buffer, format, requested_format );
499                         mlt_properties_set_int( properties, "format", *format );
500                 }
501         }
502         else if ( producer )
503         {
504                 mlt_frame test_frame = NULL;
505                 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
506                 if ( test_frame )
507                 {
508                         mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
509                         mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
510                         mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
511                         mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
512                         mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
513 //                      mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
514 //                      mlt_properties_set_int( properties, "width", *width );
515 //                      mlt_properties_set_int( properties, "height", *height );
516 //                      mlt_properties_set_int( properties, "format", *format );
517                 }
518                 else
519                 {
520                         mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
521                         mlt_frame_get_image( self, buffer, format, width, height, writable );
522                 }
523         }
524         else
525         {
526                 register uint8_t *p;
527                 register uint8_t *q;
528                 int size = 0;
529
530                 *width = *width == 0 ? 720 : *width;
531                 *height = *height == 0 ? 576 : *height;
532                 size = *width * *height;
533
534                 mlt_properties_set_int( properties, "format", *format );
535                 mlt_properties_set_int( properties, "width", *width );
536                 mlt_properties_set_int( properties, "height", *height );
537                 mlt_properties_set_int( properties, "aspect_ratio", 0 );
538
539                 switch( *format )
540                 {
541                         case mlt_image_none:
542                                 size = 0;
543                                 *buffer = NULL;
544                                 break;
545                         case mlt_image_rgb24:
546                                 size *= 3;
547                                 size += *width * 3;
548                                 *buffer = mlt_pool_alloc( size );
549                                 if ( *buffer )
550                                         memset( *buffer, 255, size );
551                                 break;
552                         case mlt_image_rgb24a:
553                         case mlt_image_opengl:
554                                 size *= 4;
555                                 size += *width * 4;
556                                 *buffer = mlt_pool_alloc( size );
557                                 if ( *buffer )
558                                         memset( *buffer, 255, size );
559                                 break;
560                         case mlt_image_yuv422:
561                                 size *= 2;
562                                 size += *width * 2;
563                                 *buffer = mlt_pool_alloc( size );
564                                 p = *buffer;
565                                 q = p + size;
566                                 while ( p != NULL && p != q )
567                                 {
568                                         *p ++ = 235;
569                                         *p ++ = 128;
570                                 }
571                                 break;
572                         case mlt_image_yuv420p:
573                                 size = size * 3 / 2;
574                                 *buffer = mlt_pool_alloc( size );
575                                 if ( *buffer )
576                                         memset( *buffer, 255, size );
577                                 break;
578                 }
579
580                 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
581                 mlt_properties_set_int( properties, "test_image", 1 );
582         }
583
584         return error;
585 }
586
587 /** Get the alpha channel associated to the frame.
588  *
589  * \public \memberof mlt_frame_s
590  * \param self a frame
591  * \return the alpha channel
592  */
593
594 uint8_t *mlt_frame_get_alpha_mask( mlt_frame self )
595 {
596         uint8_t *alpha = NULL;
597         if ( self != NULL )
598         {
599                 if ( self->get_alpha_mask != NULL )
600                         alpha = self->get_alpha_mask( self );
601                 if ( alpha == NULL )
602                         alpha = mlt_properties_get_data( &self->parent, "alpha", NULL );
603                 if ( alpha == NULL )
604                 {
605                         int size = mlt_properties_get_int( &self->parent, "width" ) * mlt_properties_get_int( &self->parent, "height" );
606                         alpha = mlt_pool_alloc( size );
607                         memset( alpha, 255, size );
608                         mlt_properties_set_data( &self->parent, "alpha", alpha, size, mlt_pool_release, NULL );
609                 }
610         }
611         return alpha;
612 }
613
614 /** Get the short name for an audio format.
615  *
616  * You do not need to deallocate the returned string.
617  * \public \memberof mlt_frame_s
618  * \param format an audio format enum
619  * \return a string for the name of the image format
620  */
621
622 const char * mlt_audio_format_name( mlt_audio_format format )
623 {
624         switch ( format )
625         {
626                 case mlt_audio_none:   return "none";
627                 case mlt_audio_s16:    return "s16";
628                 case mlt_audio_s32:    return "s32";
629                 case mlt_audio_s32le:  return "s32le";
630                 case mlt_audio_float:  return "float";
631                 case mlt_audio_f32le:  return "f32le";
632         }
633         return "invalid";
634 }
635
636 /** Get the amount of bytes needed for a block of audio.
637   *
638   * \public \memberof mlt_frame_s
639   * \param format an audio format enum
640   * \param samples the number of samples per channel
641   * \param channels the number of channels
642   * \return the number of bytes
643   */
644
645 int mlt_audio_format_size( mlt_audio_format format, int samples, int channels )
646 {
647         switch ( format )
648         {
649                 case mlt_audio_none:   return 0;
650                 case mlt_audio_s16:    return samples * channels * sizeof( int16_t );
651                 case mlt_audio_s32le:
652                 case mlt_audio_s32:    return samples * channels * sizeof( int32_t );
653                 case mlt_audio_f32le:
654                 case mlt_audio_float:  return samples * channels * sizeof( float );
655         }
656         return 0;
657 }
658
659 /** Get the audio associated to the frame.
660  *
661  * You should express the desired format, frequency, channels, and samples as inputs. As long
662  * as the loader producer was used to generate this or the audioconvert filter
663  * was attached, then you will get the audio back in the format you desire.
664  * However, you do not always get the channels and samples you request depending
665  * on properties and filters. You do not need to supply a pre-allocated
666  * buffer, but you should always supply the desired audio format.
667  * The audio is always in interleaved format.
668  * You should use the \p mlt_sample_calculator to determine the number of samples you want.
669  *
670  * \public \memberof mlt_frame_s
671  * \param self a frame
672  * \param[out] buffer an audio buffer
673  * \param[in,out] format the audio format
674  * \param[in,out] frequency the sample rate
675  * \param[in,out] channels
676  * \param[in,out] samples the number of samples per frame
677  * \return true if error
678  */
679
680 int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
681 {
682         mlt_get_audio get_audio = mlt_frame_pop_audio( self );
683         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
684         int hide = mlt_properties_get_int( properties, "test_audio" );
685         mlt_audio_format requested_format = *format;
686
687         if ( hide == 0 && get_audio != NULL )
688         {
689                 get_audio( self, buffer, format, frequency, channels, samples );
690                 mlt_properties_set_int( properties, "audio_frequency", *frequency );
691                 mlt_properties_set_int( properties, "audio_channels", *channels );
692                 mlt_properties_set_int( properties, "audio_samples", *samples );
693                 mlt_properties_set_int( properties, "audio_format", *format );
694                 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
695                         self->convert_audio( self, buffer, format, requested_format );
696         }
697         else if ( mlt_properties_get_data( properties, "audio", NULL ) )
698         {
699                 *buffer = mlt_properties_get_data( properties, "audio", NULL );
700                 *format = mlt_properties_get_int( properties, "audio_format" );
701                 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
702                 *channels = mlt_properties_get_int( properties, "audio_channels" );
703                 *samples = mlt_properties_get_int( properties, "audio_samples" );
704                 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
705                         self->convert_audio( self, buffer, format, requested_format );
706         }
707         else
708         {
709                 int size = 0;
710                 *samples = *samples <= 0 ? 1920 : *samples;
711                 *channels = *channels <= 0 ? 2 : *channels;
712                 *frequency = *frequency <= 0 ? 48000 : *frequency;
713                 mlt_properties_set_int( properties, "audio_frequency", *frequency );
714                 mlt_properties_set_int( properties, "audio_channels", *channels );
715                 mlt_properties_set_int( properties, "audio_samples", *samples );
716                 mlt_properties_set_int( properties, "audio_format", *format );
717
718                 switch( *format )
719                 {
720                         case mlt_image_none:
721                                 size = 0;
722                                 *buffer = NULL;
723                                 break;
724                         case mlt_audio_s16:
725                                 size = *samples * *channels * sizeof( int16_t );
726                                 break;
727                         case mlt_audio_s32:
728                                 size = *samples * *channels * sizeof( int32_t );
729                                 break;
730                         case mlt_audio_float:
731                                 size = *samples * *channels * sizeof( float );
732                                 break;
733                         default:
734                                 break;
735                 }
736                 if ( size )
737                         *buffer = mlt_pool_alloc( size );
738                 if ( *buffer )
739                         memset( *buffer, 0, size );
740                 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
741                 mlt_properties_set_int( properties, "test_audio", 1 );
742         }
743
744         // TODO: This does not belong here
745         if ( *format == mlt_audio_s16 && mlt_properties_get( properties, "meta.volume" ) )
746         {
747                 double value = mlt_properties_get_double( properties, "meta.volume" );
748
749                 if ( value == 0.0 )
750                 {
751                         memset( *buffer, 0, *samples * *channels * 2 );
752                 }
753                 else if ( value != 1.0 )
754                 {
755                         int total = *samples * *channels;
756                         int16_t *p = *buffer;
757                         while ( total -- )
758                         {
759                                 *p = *p * value;
760                                 p ++;
761                         }
762                 }
763
764                 mlt_properties_set( properties, "meta.volume", NULL );
765         }
766
767         return 0;
768 }
769
770 /** Set the audio on a frame.
771  *
772  * \public \memberof mlt_frame_s
773  * \param self a frame
774  * \param buffer an buffer containing audio samples
775  * \param format the format of the audio in the \p buffer
776  * \param size the total size of the buffer (optional)
777  * \param destructor a function that releases or deallocates the \p buffer
778  * \return true if error
779  */
780
781 int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
782 {
783         mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "audio_format", format );
784         return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "audio", buffer, size, destructor, NULL );
785 }
786
787 /** Get audio on a frame as a waveform image.
788  *
789  * This generates an 8-bit grayscale image representation of the audio in a
790  * frame. Currently, this only really works for 2 channels.
791  * This allocates the bitmap using mlt_pool so you should release the return
792  * value with \p mlt_pool_release.
793  *
794  * \public \memberof mlt_frame_s
795  * \param self a frame
796  * \param w the width of the image
797  * \param h the height of the image to create
798  * \return a pointer to a new bitmap
799  */
800
801 unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h )
802 {
803         int16_t *pcm = NULL;
804         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
805         mlt_audio_format format = mlt_audio_s16;
806         int frequency = 16000;
807         int channels = 2;
808         mlt_producer producer = mlt_frame_get_original_producer( self );
809         double fps = mlt_producer_get_fps( mlt_producer_cut_parent( producer ) );
810         int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
811
812         // Increase audio resolution proportional to requested image size
813         while ( samples < w )
814         {
815                 frequency += 16000;
816                 samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
817         }
818
819         // Get the pcm data
820         mlt_frame_get_audio( self, (void**)&pcm, &format, &frequency, &channels, &samples );
821
822         // Make an 8-bit buffer large enough to hold rendering
823         int size = w * h;
824         if ( size <= 0 )
825                 return NULL;
826         unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
827         if ( bitmap != NULL )
828                 memset( bitmap, 0, size );
829         else
830                 return NULL;
831         mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
832
833         // Render vertical lines
834         int16_t *ubound = pcm + samples * channels;
835         int skip = samples / w;
836         skip = !skip ? 1 : skip;
837         unsigned char gray = 0xFF / skip;
838         int i, j, k;
839
840         // Iterate sample stream and along x coordinate
841         for ( i = 0; pcm < ubound; i++ )
842         {
843                 // pcm data has channels interleaved
844                 for ( j = 0; j < channels; j++, pcm++ )
845                 {
846                         // Determine sample's magnitude from 2s complement;
847                         int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
848                         // The height of a line is the ratio of the magnitude multiplied by
849                         // the vertical resolution of a single channel
850                                 int height = h * pcm_magnitude / channels / 2 / 32768;
851                         // Determine the starting y coordinate - left top, right bottom
852                         int displacement = h * (j * 2 + 1) / channels / 2 - ( *pcm < 0 ? 0 : height );
853                         // Position buffer pointer using y coordinate, stride, and x coordinate
854                         unsigned char *p = bitmap + i / skip + displacement * w;
855
856                         // Draw vertical line
857                         for ( k = 0; k < height + 1; k++ )
858                                 if ( *pcm < 0 )
859                                         p[ w * k ] = ( k == 0 ) ? 0xFF : p[ w * k ] + gray;
860                                 else
861                                         p[ w * k ] = ( k == height ) ? 0xFF : p[ w * k ] + gray;
862                 }
863         }
864
865         return bitmap;
866 }
867
868 /** Get the end service that produced self frame.
869  *
870  * This fetches the first producer of the frame and not any producers that
871  * encapsulate it.
872  *
873  * \public \memberof mlt_frame_s
874  * \param self a frame
875  * \return a producer
876  */
877
878 mlt_producer mlt_frame_get_original_producer( mlt_frame self )
879 {
880         if ( self != NULL )
881                 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( self ), "_producer", NULL );
882         return NULL;
883 }
884
885 /** Destroy the frame.
886  *
887  * \public \memberof mlt_frame_s
888  * \param self a frame
889  */
890
891 void mlt_frame_close( mlt_frame self )
892 {
893         if ( self != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( self ) ) <= 0 )
894         {
895                 mlt_deque_close( self->stack_image );
896                 mlt_deque_close( self->stack_audio );
897                 while( mlt_deque_peek_back( self->stack_service ) )
898                         mlt_service_close( mlt_deque_pop_back( self->stack_service ) );
899                 mlt_deque_close( self->stack_service );
900                 mlt_properties_close( &self->parent );
901                 free( self );
902         }
903 }
904
905 /***** convenience functions *****/
906
907 /** Determine the number of samples that belong in a frame at a time position.
908  *
909  * \public \memberof mlt_frame_s
910  * \param fps the frame rate
911  * \param frequency the sample rate
912  * \param position the time position
913  * \return the number of samples per channel
914  */
915
916 int mlt_sample_calculator( float fps, int frequency, int64_t position )
917 {
918         /* Compute the cumulative number of samples until the start of this frame and the
919         cumulative number of samples until the start of the next frame. Round each to the
920         nearest integer and take the difference to determine the number of samples in
921         this frame.
922
923         This approach should prevent rounding errors that can accumulate over a large number
924         of frames causing A/V sync problems. */
925         return mlt_sample_calculator_to_now( fps, frequency, position + 1 )
926                  - mlt_sample_calculator_to_now( fps, frequency, position );
927 }
928
929 /** Determine the number of samples that belong before a time position.
930  *
931  * \public \memberof mlt_frame_s
932  * \param fps the frame rate
933  * \param frequency the sample rate
934  * \param position the time position
935  * \return the number of samples per channel
936  * \bug Will this break when mlt_position is converted to double?
937  */
938
939 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position )
940 {
941         int64_t samples = 0;
942
943         if ( fps )
944         {
945                 samples = (int64_t)( (double) position * (double) frequency / (double) fps +
946                         ( position < 0 ? -0.5 : 0.5 ) );
947         }
948
949         return samples;
950 }
951
952 void mlt_frame_write_ppm( mlt_frame frame )
953 {
954         int width = 0;
955         int height = 0;
956         mlt_image_format format = mlt_image_rgb24;
957         uint8_t *image;
958         
959         if ( mlt_frame_get_image( frame, &image, &format, &width, &height, 0 ) == 0 )
960         {
961                 FILE *file;
962                 char filename[16];
963                 
964                 sprintf( filename, "frame-%05d.ppm", mlt_frame_get_position( frame ) );
965                 file = fopen( filename, "wb" );
966                 if ( !file )
967                         return;
968                 fprintf( file, "P6\n%d %d\n255\n", width, height);
969                 fwrite( image, width * height * 3, 1, file );
970                 fclose( file );
971         }
972 }
973
974 /** Get or create a properties object unique to this service instance.
975  *
976  * Use this function to hold a service's processing parameters for this
977  * particular frame. Set the parameters in the service's process function.
978  * Then, get the parameters in the function it pushes to the frame's audio
979  * or image stack. This makes the service more parallel by reducing race
980  * conditions and less sensitive to multiple instances (by not setting a
981  * non-unique property on the frame). Creation and destruction of the
982  * properties object is handled automatically.
983  *
984  * \public \memberof mlt_frame_s
985  * \param self a frame
986  * \param service a service
987  * \return a properties object
988  */
989
990 mlt_properties mlt_frame_unique_properties( mlt_frame self, mlt_service service )
991 {
992         mlt_properties frame_props = MLT_FRAME_PROPERTIES( self );
993         mlt_properties service_props = MLT_SERVICE_PROPERTIES( service );
994         char *unique = mlt_properties_get( service_props, "_unique_id" );
995         mlt_properties instance_props = mlt_properties_get_data( frame_props, unique, NULL );
996         
997         if ( !instance_props )
998         {
999                 instance_props = mlt_properties_new();
1000                 mlt_properties_set_data( frame_props, unique, instance_props, 0, (mlt_destructor) mlt_properties_close, NULL );
1001         }
1002
1003         return instance_props;
1004 }
1005
1006 /** Make a copy of a frame.
1007  *
1008  * This does not copy the get_image/get_audio processing stacks or any
1009  * data properties other than the audio and image.
1010  *
1011  * \public \memberof mlt_frame_s
1012  * \param self the frame to clone
1013  * \param is_deep a boolean to indicate whether to make a deep copy of the audio
1014  * and video data chunks or to make a shallow copy by pointing to the supplied frame
1015  * \return a almost-complete copy of the frame
1016  * \todo copy the processing deques
1017  */
1018
1019 mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
1020 {
1021         mlt_frame new_frame = mlt_frame_init( NULL );
1022         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
1023         mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
1024         void *data, *copy;
1025         int size;
1026
1027         mlt_properties_inherit( new_props, properties );
1028         if ( is_deep )
1029         {
1030                 data = mlt_properties_get_data( properties, "audio", &size );
1031                 if ( data )
1032                 {
1033                         if ( !size )
1034                                 size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
1035                                         mlt_properties_get_int( properties, "audio_samples" ),
1036                                         mlt_properties_get_int( properties, "audio_channels" ) );
1037                         copy = mlt_pool_alloc( size );
1038                         memcpy( copy, data, size );
1039                         mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
1040                 }
1041                 data = mlt_properties_get_data( properties, "image", &size );
1042                 if ( data )
1043                 {
1044                         if ( ! size )
1045                                 size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
1046                                         mlt_properties_get_int( properties, "width" ),
1047                                         mlt_properties_get_int( properties, "height" ), NULL );
1048                         copy = mlt_pool_alloc( size );
1049                         memcpy( copy, data, size );
1050                         mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );
1051
1052                         data = mlt_properties_get_data( properties, "alpha", &size );
1053                         if ( data )
1054                         {
1055                                 if ( ! size )
1056                                         size = mlt_properties_get_int( properties, "width" ) *
1057                                                 mlt_properties_get_int( properties, "height" );
1058                                 copy = mlt_pool_alloc( size );
1059                                 memcpy( copy, data, size );
1060                                 mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
1061                         };
1062                 }
1063         }
1064         else
1065         {
1066                 // This frame takes a reference on the original frame since the data is a shallow copy.
1067                 mlt_properties_inc_ref( properties );
1068                 mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
1069                         (mlt_destructor) mlt_frame_close, NULL );
1070
1071                 // Copy properties
1072                 data = mlt_properties_get_data( properties, "audio", &size );
1073                 mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
1074                 data = mlt_properties_get_data( properties, "image", &size );
1075                 mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
1076                 data = mlt_properties_get_data( properties, "alpha", &size );
1077                 mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );
1078         }
1079
1080         return new_frame;
1081 }