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