]> git.sesse.net Git - mlt/blob - src/framework/mlt_frame.c
make mlt_position type double
[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                 case mlt_image_glsl:    return "glsl";
407                 case mlt_image_glsl_texture: return "glsl_texture";
408         }
409         return "invalid";
410 }
411
412 /** Get the number of bytes needed for an image.
413   *
414   * \public \memberof mlt_frame_s
415   * \param format the image format
416   * \param width width of the image in pixels
417   * \param height height of the image in pixels
418   * \param[out] bpp the number of bytes per pixel (optional)
419   * \return the number of bytes
420   */
421 int mlt_image_format_size( mlt_image_format format, int width, int height, int *bpp )
422 {
423         height += 1;
424         switch ( format )
425         {
426                 case mlt_image_rgb24:
427                         if ( bpp ) *bpp = 3;
428                         return width * height * 3;
429                 case mlt_image_opengl:
430                 case mlt_image_rgb24a:
431                         if ( bpp ) *bpp = 4;
432                         return width * height * 4;
433                 case mlt_image_yuv422:
434                         if ( bpp ) *bpp = 2;
435                         return width * height * 2;
436                 case mlt_image_yuv420p:
437                         if ( bpp ) *bpp = 3 / 2;
438                         return width * height * 3 / 2;
439                 default:
440                         if ( bpp ) *bpp = 0;
441                         return 0;
442         }
443         return 0;
444 }
445
446 static int generate_test_image( mlt_properties properties, uint8_t **buffer,  mlt_image_format *format, int *width, int *height, int writable )
447 {
448         mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
449         mlt_image_format requested_format = *format;
450         int error = 1;
451
452         if ( producer )
453         {
454                 mlt_frame test_frame = NULL;
455                 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
456                 if ( test_frame )
457                 {
458                         mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
459                         mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
460                         mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
461                         error = mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
462                         if ( !error && buffer && *buffer )
463                         {
464                                 mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
465                                 mlt_properties_set_int( properties, "width", *width );
466                                 mlt_properties_set_int( properties, "height", *height );
467                                 if ( test_frame->convert_image && requested_format != mlt_image_none )
468                                         test_frame->convert_image( test_frame, buffer, format, requested_format );
469                                 mlt_properties_set_int( properties, "format", *format );
470                         }
471                 }
472                 else
473                 {
474                         mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
475                 }
476         }
477         if ( error && buffer && *format != mlt_image_none )
478         {
479                 int size = 0;
480
481                 *width = *width == 0 ? 720 : *width;
482                 *height = *height == 0 ? 576 : *height;
483                 size = *width * *height;
484
485                 mlt_properties_set_int( properties, "format", *format );
486                 mlt_properties_set_int( properties, "width", *width );
487                 mlt_properties_set_int( properties, "height", *height );
488                 mlt_properties_set_double( properties, "aspect_ratio", 1.0 );
489
490                 switch( *format )
491                 {
492                         case mlt_image_rgb24:
493                                 size *= 3;
494                                 size += *width * 3;
495                                 *buffer = mlt_pool_alloc( size );
496                                 if ( *buffer )
497                                         memset( *buffer, 255, size );
498                                 break;
499                         case mlt_image_rgb24a:
500                         case mlt_image_opengl:
501                                 size *= 4;
502                                 size += *width * 4;
503                                 *buffer = mlt_pool_alloc( size );
504                                 if ( *buffer )
505                                         memset( *buffer, 255, size );
506                                 break;
507                         case mlt_image_yuv422:
508                                 size *= 2;
509                                 size += *width * 2;
510                                 *buffer = mlt_pool_alloc( size );
511                                 if ( *buffer )
512                                 {
513                                         register uint8_t *p = *buffer;
514                                         register uint8_t *q = p + size;
515                                         while ( p != NULL && p != q )
516                                         {
517                                                 *p ++ = 235;
518                                                 *p ++ = 128;
519                                         }
520                                 }
521                                 break;
522                         case mlt_image_yuv420p:
523                                 *buffer = mlt_pool_alloc( size * 3 / 2 );
524                                 if ( *buffer )
525                                 {
526                                         memset( *buffer, 235, size );
527                                         memset( *buffer + size, 128, size / 2 );
528                                 }
529                                 break;
530                         default:
531                                 size = 0;
532                                 break;
533                 }
534                 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
535                 mlt_properties_set_int( properties, "test_image", 1 );
536                 error = 0;
537         }
538         return error;
539 }
540
541
542 /** Get the image associated to the frame.
543  *
544  * You should express the desired format, width, and height as inputs. As long
545  * as the loader producer was used to generate this or the imageconvert filter
546  * was attached, then you will get the image back in the format you desire.
547  * However, you do not always get the width and height you request depending
548  * on properties and filters. You do not need to supply a pre-allocated
549  * buffer, but you should always supply the desired image format.
550  *
551  * \public \memberof mlt_frame_s
552  * \param self a frame
553  * \param[out] buffer an image buffer
554  * \param[in,out] format the image format
555  * \param[in,out] width the horizontal size in pixels
556  * \param[in,out] height the vertical size in pixels
557  * \param writable whether or not you will need to be able to write to the memory returned in \p buffer
558  * \return true if error
559  * \todo Better describe the width and height as inputs.
560  */
561
562 int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
563 {
564         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
565         mlt_get_image get_image = mlt_frame_pop_get_image( self );
566         mlt_image_format requested_format = *format;
567         int error = 0;
568
569         if ( get_image )
570         {
571                 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
572                 error = get_image( self, buffer, format, width, height, writable );
573                 if ( !error && buffer && *buffer )
574                 {
575                         mlt_properties_set_int( properties, "width", *width );
576                         mlt_properties_set_int( properties, "height", *height );
577                         if ( self->convert_image && requested_format != mlt_image_none )
578                                 self->convert_image( self, buffer, format, requested_format );
579                         mlt_properties_set_int( properties, "format", *format );
580                 }
581                 else
582                 {
583                         error = generate_test_image( properties, buffer, format, width, height, writable );
584                 }
585         }
586         else if ( mlt_properties_get_data( properties, "image", NULL ) && buffer )
587         {
588                 *format = mlt_properties_get_int( properties, "format" );
589                 *buffer = mlt_properties_get_data( properties, "image", NULL );
590                 *width = mlt_properties_get_int( properties, "width" );
591                 *height = mlt_properties_get_int( properties, "height" );
592                 if ( self->convert_image && *buffer && requested_format != mlt_image_none )
593                 {
594                         self->convert_image( self, buffer, format, requested_format );
595                         mlt_properties_set_int( properties, "format", *format );
596                 }
597         }
598         else
599         {
600                 error = generate_test_image( properties, buffer, format, width, height, writable );
601         }
602
603         return error;
604 }
605
606 /** Get the alpha channel associated to the frame.
607  *
608  * \public \memberof mlt_frame_s
609  * \param self a frame
610  * \return the alpha channel
611  */
612
613 uint8_t *mlt_frame_get_alpha_mask( mlt_frame self )
614 {
615         uint8_t *alpha = NULL;
616         if ( self != NULL )
617         {
618                 if ( self->get_alpha_mask != NULL )
619                         alpha = self->get_alpha_mask( self );
620                 if ( alpha == NULL )
621                         alpha = mlt_properties_get_data( &self->parent, "alpha", NULL );
622                 if ( alpha == NULL )
623                 {
624                         int size = mlt_properties_get_int( &self->parent, "width" ) * mlt_properties_get_int( &self->parent, "height" );
625                         alpha = mlt_pool_alloc( size );
626                         memset( alpha, 255, size );
627                         mlt_properties_set_data( &self->parent, "alpha", alpha, size, mlt_pool_release, NULL );
628                 }
629         }
630         return alpha;
631 }
632
633 /** Get the short name for an audio format.
634  *
635  * You do not need to deallocate the returned string.
636  * \public \memberof mlt_frame_s
637  * \param format an audio format enum
638  * \return a string for the name of the image format
639  */
640
641 const char * mlt_audio_format_name( mlt_audio_format format )
642 {
643         switch ( format )
644         {
645                 case mlt_audio_none:   return "none";
646                 case mlt_audio_s16:    return "s16";
647                 case mlt_audio_s32:    return "s32";
648                 case mlt_audio_s32le:  return "s32le";
649                 case mlt_audio_float:  return "float";
650                 case mlt_audio_f32le:  return "f32le";
651                 case mlt_audio_u8:     return "u8";
652         }
653         return "invalid";
654 }
655
656 /** Get the amount of bytes needed for a block of audio.
657   *
658   * \public \memberof mlt_frame_s
659   * \param format an audio format enum
660   * \param samples the number of samples per channel
661   * \param channels the number of channels
662   * \return the number of bytes
663   */
664
665 int mlt_audio_format_size( mlt_audio_format format, int samples, int channels )
666 {
667         switch ( format )
668         {
669                 case mlt_audio_none:   return 0;
670                 case mlt_audio_s16:    return samples * channels * sizeof( int16_t );
671                 case mlt_audio_s32le:
672                 case mlt_audio_s32:    return samples * channels * sizeof( int32_t );
673                 case mlt_audio_f32le:
674                 case mlt_audio_float:  return samples * channels * sizeof( float );
675                 case mlt_audio_u8:     return samples * channels;
676         }
677         return 0;
678 }
679
680 /** Get the audio associated to the frame.
681  *
682  * You should express the desired format, frequency, channels, and samples as inputs. As long
683  * as the loader producer was used to generate this or the audioconvert filter
684  * was attached, then you will get the audio back in the format you desire.
685  * However, you do not always get the channels and samples you request depending
686  * on properties and filters. You do not need to supply a pre-allocated
687  * buffer, but you should always supply the desired audio format.
688  * The audio is always in interleaved format.
689  * You should use the \p mlt_sample_calculator to determine the number of samples you want.
690  *
691  * \public \memberof mlt_frame_s
692  * \param self a frame
693  * \param[out] buffer an audio buffer
694  * \param[in,out] format the audio format
695  * \param[in,out] frequency the sample rate
696  * \param[in,out] channels
697  * \param[in,out] samples the number of samples per frame
698  * \return true if error
699  */
700
701 int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
702 {
703         mlt_get_audio get_audio = mlt_frame_pop_audio( self );
704         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
705         int hide = mlt_properties_get_int( properties, "test_audio" );
706         mlt_audio_format requested_format = *format;
707
708         if ( hide == 0 && get_audio != NULL )
709         {
710                 get_audio( self, buffer, format, frequency, channels, samples );
711                 mlt_properties_set_int( properties, "audio_frequency", *frequency );
712                 mlt_properties_set_int( properties, "audio_channels", *channels );
713                 mlt_properties_set_int( properties, "audio_samples", *samples );
714                 mlt_properties_set_int( properties, "audio_format", *format );
715                 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
716                         self->convert_audio( self, buffer, format, requested_format );
717         }
718         else if ( mlt_properties_get_data( properties, "audio", NULL ) )
719         {
720                 *buffer = mlt_properties_get_data( properties, "audio", NULL );
721                 *format = mlt_properties_get_int( properties, "audio_format" );
722                 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
723                 *channels = mlt_properties_get_int( properties, "audio_channels" );
724                 *samples = mlt_properties_get_int( properties, "audio_samples" );
725                 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
726                         self->convert_audio( self, buffer, format, requested_format );
727         }
728         else
729         {
730                 int size = 0;
731                 *samples = *samples <= 0 ? 1920 : *samples;
732                 *channels = *channels <= 0 ? 2 : *channels;
733                 *frequency = *frequency <= 0 ? 48000 : *frequency;
734                 mlt_properties_set_int( properties, "audio_frequency", *frequency );
735                 mlt_properties_set_int( properties, "audio_channels", *channels );
736                 mlt_properties_set_int( properties, "audio_samples", *samples );
737                 mlt_properties_set_int( properties, "audio_format", *format );
738
739                 switch( *format )
740                 {
741                         case mlt_image_none:
742                                 size = 0;
743                                 *buffer = NULL;
744                                 break;
745                         case mlt_audio_s16:
746                                 size = *samples * *channels * sizeof( int16_t );
747                                 break;
748                         case mlt_audio_s32:
749                                 size = *samples * *channels * sizeof( int32_t );
750                                 break;
751                         case mlt_audio_float:
752                                 size = *samples * *channels * sizeof( float );
753                                 break;
754                         default:
755                                 break;
756                 }
757                 if ( size )
758                         *buffer = mlt_pool_alloc( size );
759                 if ( *buffer )
760                         memset( *buffer, 0, size );
761                 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
762                 mlt_properties_set_int( properties, "test_audio", 1 );
763         }
764
765         // TODO: This does not belong here
766         if ( *format == mlt_audio_s16 && mlt_properties_get( properties, "meta.volume" ) )
767         {
768                 double value = mlt_properties_get_double( properties, "meta.volume" );
769
770                 if ( value == 0.0 )
771                 {
772                         memset( *buffer, 0, *samples * *channels * 2 );
773                 }
774                 else if ( value != 1.0 )
775                 {
776                         int total = *samples * *channels;
777                         int16_t *p = *buffer;
778                         while ( total -- )
779                         {
780                                 *p = *p * value;
781                                 p ++;
782                         }
783                 }
784
785                 mlt_properties_set( properties, "meta.volume", NULL );
786         }
787
788         return 0;
789 }
790
791 /** Set the audio on a frame.
792  *
793  * \public \memberof mlt_frame_s
794  * \param self a frame
795  * \param buffer an buffer containing audio samples
796  * \param format the format of the audio in the \p buffer
797  * \param size the total size of the buffer (optional)
798  * \param destructor a function that releases or deallocates the \p buffer
799  * \return true if error
800  */
801
802 int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
803 {
804         mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "audio_format", format );
805         return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "audio", buffer, size, destructor, NULL );
806 }
807
808 /** Get audio on a frame as a waveform image.
809  *
810  * This generates an 8-bit grayscale image representation of the audio in a
811  * frame. Currently, this only really works for 2 channels.
812  * This allocates the bitmap using mlt_pool so you should release the return
813  * value with \p mlt_pool_release.
814  *
815  * \public \memberof mlt_frame_s
816  * \param self a frame
817  * \param w the width of the image
818  * \param h the height of the image to create
819  * \return a pointer to a new bitmap
820  */
821
822 unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h )
823 {
824         int16_t *pcm = NULL;
825         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
826         mlt_audio_format format = mlt_audio_s16;
827         int frequency = 16000;
828         int channels = 2;
829         mlt_producer producer = mlt_frame_get_original_producer( self );
830         double fps = mlt_producer_get_fps( mlt_producer_cut_parent( producer ) );
831         int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
832
833         // Increase audio resolution proportional to requested image size
834         while ( samples < w )
835         {
836                 frequency += 16000;
837                 samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
838         }
839
840         // Get the pcm data
841         mlt_frame_get_audio( self, (void**)&pcm, &format, &frequency, &channels, &samples );
842
843         // Make an 8-bit buffer large enough to hold rendering
844         int size = w * h;
845         if ( size <= 0 )
846                 return NULL;
847         unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
848         if ( bitmap != NULL )
849                 memset( bitmap, 0, size );
850         else
851                 return NULL;
852         mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
853
854         // Render vertical lines
855         int16_t *ubound = pcm + samples * channels;
856         int skip = samples / w;
857         skip = !skip ? 1 : skip;
858         unsigned char gray = 0xFF / skip;
859         int i, j, k;
860
861         // Iterate sample stream and along x coordinate
862         for ( i = 0; pcm < ubound; i++ )
863         {
864                 // pcm data has channels interleaved
865                 for ( j = 0; j < channels; j++, pcm++ )
866                 {
867                         // Determine sample's magnitude from 2s complement;
868                         int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
869                         // The height of a line is the ratio of the magnitude multiplied by
870                         // the vertical resolution of a single channel
871                                 int height = h * pcm_magnitude / channels / 2 / 32768;
872                         // Determine the starting y coordinate - left top, right bottom
873                         int displacement = h * (j * 2 + 1) / channels / 2 - ( *pcm < 0 ? 0 : height );
874                         // Position buffer pointer using y coordinate, stride, and x coordinate
875                         unsigned char *p = bitmap + i / skip + displacement * w;
876
877                         // Draw vertical line
878                         for ( k = 0; k < height + 1; k++ )
879                                 if ( *pcm < 0 )
880                                         p[ w * k ] = ( k == 0 ) ? 0xFF : p[ w * k ] + gray;
881                                 else
882                                         p[ w * k ] = ( k == height ) ? 0xFF : p[ w * k ] + gray;
883                 }
884         }
885
886         return bitmap;
887 }
888
889 /** Get the end service that produced self frame.
890  *
891  * This fetches the first producer of the frame and not any producers that
892  * encapsulate it.
893  *
894  * \public \memberof mlt_frame_s
895  * \param self a frame
896  * \return a producer
897  */
898
899 mlt_producer mlt_frame_get_original_producer( mlt_frame self )
900 {
901         if ( self != NULL )
902                 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( self ), "_producer", NULL );
903         return NULL;
904 }
905
906 /** Destroy the frame.
907  *
908  * \public \memberof mlt_frame_s
909  * \param self a frame
910  */
911
912 void mlt_frame_close( mlt_frame self )
913 {
914         if ( self != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( self ) ) <= 0 )
915         {
916                 mlt_deque_close( self->stack_image );
917                 mlt_deque_close( self->stack_audio );
918                 while( mlt_deque_peek_back( self->stack_service ) )
919                         mlt_service_close( mlt_deque_pop_back( self->stack_service ) );
920                 mlt_deque_close( self->stack_service );
921                 mlt_properties_close( &self->parent );
922                 free( self );
923         }
924 }
925
926 /***** convenience functions *****/
927
928 /** Determine the number of samples that belong in a frame at a time position.
929  *
930  * \public \memberof mlt_frame_s
931  * \param fps the frame rate
932  * \param frequency the sample rate
933  * \param position the time position
934  * \return the number of samples per channel
935  */
936
937 int mlt_sample_calculator( float fps, int frequency, int64_t position )
938 {
939         /* Compute the cumulative number of samples until the start of this frame and the
940         cumulative number of samples until the start of the next frame. Round each to the
941         nearest integer and take the difference to determine the number of samples in
942         this frame.
943
944         This approach should prevent rounding errors that can accumulate over a large number
945         of frames causing A/V sync problems. */
946         return mlt_sample_calculator_to_now( fps, frequency, position + 1 )
947                  - mlt_sample_calculator_to_now( fps, frequency, position );
948 }
949
950 /** Determine the number of samples that belong before a time position.
951  *
952  * \public \memberof mlt_frame_s
953  * \param fps the frame rate
954  * \param frequency the sample rate
955  * \param position the time position
956  * \return the number of samples per channel
957  * \bug Will this break when mlt_position is converted to double?
958  */
959
960 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position )
961 {
962         int64_t samples = 0;
963
964         if ( fps )
965         {
966                 samples = (int64_t)( (double) position * (double) frequency / (double) fps +
967                         ( position < 0 ? -0.5 : 0.5 ) );
968         }
969
970         return samples;
971 }
972
973 void mlt_frame_write_ppm( mlt_frame frame )
974 {
975         int width = 0;
976         int height = 0;
977         mlt_image_format format = mlt_image_rgb24;
978         uint8_t *image;
979         
980         if ( mlt_frame_get_image( frame, &image, &format, &width, &height, 0 ) == 0 )
981         {
982                 FILE *file;
983                 char filename[16];
984                 
985                 sprintf( filename, "frame-%05d.ppm", (int)mlt_frame_get_position( frame ) );
986                 file = fopen( filename, "wb" );
987                 if ( !file )
988                         return;
989                 fprintf( file, "P6\n%d %d\n255\n", width, height);
990                 fwrite( image, width * height * 3, 1, file );
991                 fclose( file );
992         }
993 }
994
995 /** Get or create a properties object unique to this service instance.
996  *
997  * Use this function to hold a service's processing parameters for this
998  * particular frame. Set the parameters in the service's process function.
999  * Then, get the parameters in the function it pushes to the frame's audio
1000  * or image stack. This makes the service more parallel by reducing race
1001  * conditions and less sensitive to multiple instances (by not setting a
1002  * non-unique property on the frame). Creation and destruction of the
1003  * properties object is handled automatically.
1004  *
1005  * \public \memberof mlt_frame_s
1006  * \param self a frame
1007  * \param service a service
1008  * \return a properties object
1009  */
1010
1011 mlt_properties mlt_frame_unique_properties( mlt_frame self, mlt_service service )
1012 {
1013         mlt_properties frame_props = MLT_FRAME_PROPERTIES( self );
1014         mlt_properties service_props = MLT_SERVICE_PROPERTIES( service );
1015         char *unique = mlt_properties_get( service_props, "_unique_id" );
1016         mlt_properties instance_props = mlt_properties_get_data( frame_props, unique, NULL );
1017         
1018         if ( !instance_props )
1019         {
1020                 instance_props = mlt_properties_new();
1021                 mlt_properties_set_data( frame_props, unique, instance_props, 0, (mlt_destructor) mlt_properties_close, NULL );
1022         }
1023
1024         return instance_props;
1025 }
1026
1027 /** Make a copy of a frame.
1028  *
1029  * This does not copy the get_image/get_audio processing stacks or any
1030  * data properties other than the audio and image.
1031  *
1032  * \public \memberof mlt_frame_s
1033  * \param self the frame to clone
1034  * \param is_deep a boolean to indicate whether to make a deep copy of the audio
1035  * and video data chunks or to make a shallow copy by pointing to the supplied frame
1036  * \return a almost-complete copy of the frame
1037  * \todo copy the processing deques
1038  */
1039
1040 mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
1041 {
1042         mlt_frame new_frame = mlt_frame_init( NULL );
1043         mlt_properties properties = MLT_FRAME_PROPERTIES( self );
1044         mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
1045         void *data, *copy;
1046         int size;
1047
1048         mlt_properties_inherit( new_props, properties );
1049
1050         // Carry over some special data properties for the multi consumer.
1051         mlt_properties_set_data( new_props, "_producer",
1052                 mlt_frame_get_original_producer( self ), 0, NULL, NULL );
1053         mlt_properties_set_data( new_props, "movit.convert",
1054                 mlt_properties_get_data( properties, "movit.convert", NULL), 0, NULL, NULL );
1055
1056         if ( is_deep )
1057         {
1058                 data = mlt_properties_get_data( properties, "audio", &size );
1059                 if ( data )
1060                 {
1061                         if ( !size )
1062                                 size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
1063                                         mlt_properties_get_int( properties, "audio_samples" ),
1064                                         mlt_properties_get_int( properties, "audio_channels" ) );
1065                         copy = mlt_pool_alloc( size );
1066                         memcpy( copy, data, size );
1067                         mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
1068                 }
1069                 data = mlt_properties_get_data( properties, "image", &size );
1070                 if ( data )
1071                 {
1072                         if ( ! size )
1073                                 size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
1074                                         mlt_properties_get_int( properties, "width" ),
1075                                         mlt_properties_get_int( properties, "height" ), NULL );
1076                         copy = mlt_pool_alloc( size );
1077                         memcpy( copy, data, size );
1078                         mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );
1079
1080                         data = mlt_properties_get_data( properties, "alpha", &size );
1081                         if ( data )
1082                         {
1083                                 if ( ! size )
1084                                         size = mlt_properties_get_int( properties, "width" ) *
1085                                                 mlt_properties_get_int( properties, "height" );
1086                                 copy = mlt_pool_alloc( size );
1087                                 memcpy( copy, data, size );
1088                                 mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
1089                         };
1090                 }
1091         }
1092         else
1093         {
1094                 // This frame takes a reference on the original frame since the data is a shallow copy.
1095                 mlt_properties_inc_ref( properties );
1096                 mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
1097                         (mlt_destructor) mlt_frame_close, NULL );
1098
1099                 // Copy properties
1100                 data = mlt_properties_get_data( properties, "audio", &size );
1101                 mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
1102                 data = mlt_properties_get_data( properties, "image", &size );
1103                 mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
1104                 data = mlt_properties_get_data( properties, "alpha", &size );
1105                 mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );
1106         }
1107
1108         return new_frame;
1109 }