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