3 * \brief interface for all frame classes
6 * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
7 * \author Charles Yates <charles.yates@pandora.be>
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.
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.
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
24 #include "mlt_frame.h"
25 #include "mlt_producer.h"
26 #include "mlt_factory.h"
27 #include "mlt_profile.h"
34 /** Construct a frame object.
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
41 mlt_frame mlt_frame_init( mlt_service service )
44 mlt_frame self = calloc( 1, sizeof( struct mlt_frame_s ) );
48 mlt_profile profile = mlt_service_profile( service );
50 // Initialise the properties
51 mlt_properties properties = &self->parent;
52 mlt_properties_init( properties, self );
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 );
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( );
72 /** Get a frame's properties.
74 * \public \memberof mlt_frame_s
76 * \return the frame's properties or NULL if an invalid frame is supplied
79 mlt_properties mlt_frame_properties( mlt_frame self )
81 return self != NULL ? &self->parent : NULL;
84 /** Determine if the frame will produce a test card image.
86 * \public \memberof mlt_frame_s
88 * \return true (non-zero) if this will produce from a test card
91 int mlt_frame_is_test_card( mlt_frame self )
93 return mlt_deque_count( self->stack_image ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( self ), "test_image" );
96 /** Determine if the frame will produce audio from a test card.
98 * \public \memberof mlt_frame_s
100 * \return true (non-zero) if this will produce from a test card
103 int mlt_frame_is_test_audio( mlt_frame self )
105 return mlt_deque_count( self->stack_audio ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( self ), "test_audio" );
108 /** Get the sample aspect ratio of the frame.
110 * \public \memberof mlt_frame_s
111 * \param self a frame
112 * \return the aspect ratio
115 double mlt_frame_get_aspect_ratio( mlt_frame self )
117 return mlt_properties_get_double( MLT_FRAME_PROPERTIES( self ), "aspect_ratio" );
120 /** Set the sample aspect ratio of the frame.
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
128 int mlt_frame_set_aspect_ratio( mlt_frame self, double value )
130 return mlt_properties_set_double( MLT_FRAME_PROPERTIES( self ), "aspect_ratio", value );
133 /** Get the time position of this frame.
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.
139 * \public \memberof mlt_frame_s
140 * \param self a frame
141 * \return the position
142 * \see mlt_frame_original_position
145 mlt_position mlt_frame_get_position( mlt_frame self )
147 int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "_position" );
148 return pos < 0 ? 0 : pos;
151 /** Get the original time position of this frame.
153 * This is the position that the original producer set on the frame.
155 * \public \memberof mlt_frame_s
156 * \param self a frame
157 * \return the position
160 mlt_position mlt_frame_original_position( mlt_frame self )
162 int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "original_position" );
163 return pos < 0 ? 0 : pos;
166 /** Set the time position of this frame.
168 * \public \memberof mlt_frame_s
169 * \param self a frame
170 * \param value the position
171 * \return true if error
174 int mlt_frame_set_position( mlt_frame self, mlt_position value )
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 );
182 /** Stack a get_image callback.
184 * \public \memberof mlt_frame_s
185 * \param self a frame
186 * \param the get_image callback
187 * \return true if error
190 int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image )
192 return mlt_deque_push_back( self->stack_image, get_image );
195 /** Pop a get_image callback.
197 * \public \memberof mlt_frame_s
198 * \param self a frame
199 * \return the get_image callback
202 mlt_get_image mlt_frame_pop_get_image( mlt_frame self )
204 return mlt_deque_pop_back( self->stack_image );
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
215 int mlt_frame_push_frame( mlt_frame self, mlt_frame that )
217 return mlt_deque_push_back( self->stack_image, that );
222 * \public \memberof mlt_frame_s
223 * \param self a frame
224 * \return a frame that was previously pushed
227 mlt_frame mlt_frame_pop_frame( mlt_frame self )
229 return mlt_deque_pop_back( self->stack_image );
234 * \public \memberof mlt_frame_s
235 * \param self a frame
236 * \param that an opaque pointer
237 * \return true if error
240 int mlt_frame_push_service( mlt_frame self, void *that )
242 return mlt_deque_push_back( self->stack_image, that );
247 * \public \memberof mlt_frame_s
248 * \param self a frame
249 * \return an opaque pointer to something previously pushed
252 void *mlt_frame_pop_service( mlt_frame self )
254 return mlt_deque_pop_back( self->stack_image );
259 * \public \memberof mlt_frame_s
260 * \param self a frame
261 * \param that an integer
262 * \return true if error
265 int mlt_frame_push_service_int( mlt_frame self, int that )
267 return mlt_deque_push_back_int( self->stack_image, that );
272 * \public \memberof mlt_frame_s
273 * \param self a frame
274 * \return an integer that was previously pushed
277 int mlt_frame_pop_service_int( mlt_frame self )
279 return mlt_deque_pop_back_int( self->stack_image );
282 /** Push an audio item on the stack.
284 * \public \memberof mlt_frame_s
285 * \param self a frame
286 * \param that an opaque pointer
287 * \return true if error
290 int mlt_frame_push_audio( mlt_frame self, void *that )
292 return mlt_deque_push_back( self->stack_audio, that );
295 /** Pop an audio item from the stack
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
302 void *mlt_frame_pop_audio( mlt_frame self )
304 return mlt_deque_pop_back( self->stack_audio );
307 /** Return the service stack
309 * \public \memberof mlt_frame_s
310 * \param self a frame
311 * \return the service stack
314 mlt_deque mlt_frame_service_stack( mlt_frame self )
316 return self->stack_service;
319 /** Set a new image on the frame.
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
329 int mlt_frame_set_image( mlt_frame self, uint8_t *image, int size, mlt_destructor destroy )
331 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, size, destroy, NULL );
334 /** Set a new alpha channel on the frame.
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
344 int mlt_frame_set_alpha( mlt_frame self, uint8_t *alpha, int size, mlt_destructor destroy )
346 self->get_alpha_mask = NULL;
347 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "alpha", alpha, size, destroy, NULL );
350 /** Replace image stack with the information provided.
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).
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.
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
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...
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
376 void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height )
378 // Remove all items from the stack
379 while( mlt_deque_pop_back( self->stack_image ) ) ;
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;
389 /** Get the short name for an image format.
391 * \public \memberof mlt_frame_s
392 * \param format the image format
396 const char * mlt_image_format_name( mlt_image_format format )
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";
412 /** Get the number of bytes needed for an image.
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
421 int mlt_image_format_size( mlt_image_format format, int width, int height, int *bpp )
426 case mlt_image_rgb24:
428 return width * height * 3;
429 case mlt_image_opengl:
430 case mlt_image_rgb24a:
432 return width * height * 4;
433 case mlt_image_yuv422:
435 return width * height * 2;
436 case mlt_image_yuv420p:
437 if ( bpp ) *bpp = 3 / 2;
438 return width * height * 3 / 2;
446 static int generate_test_image( mlt_properties properties, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
448 mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
449 mlt_image_format requested_format = *format;
454 mlt_frame test_frame = NULL;
455 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
458 mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
459 mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
460 mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
461 error = mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
462 if ( !error && buffer && *buffer )
464 mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
465 mlt_properties_set_int( properties, "width", *width );
466 mlt_properties_set_int( properties, "height", *height );
467 if ( test_frame->convert_image && requested_format != mlt_image_none )
468 test_frame->convert_image( test_frame, buffer, format, requested_format );
469 mlt_properties_set_int( properties, "format", *format );
474 mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
477 if ( error && buffer && *format != mlt_image_none )
481 *width = *width == 0 ? 720 : *width;
482 *height = *height == 0 ? 576 : *height;
483 size = *width * *height;
485 mlt_properties_set_int( properties, "format", *format );
486 mlt_properties_set_int( properties, "width", *width );
487 mlt_properties_set_int( properties, "height", *height );
488 mlt_properties_set_double( properties, "aspect_ratio", 1.0 );
492 case mlt_image_rgb24:
495 *buffer = mlt_pool_alloc( size );
497 memset( *buffer, 255, size );
499 case mlt_image_rgb24a:
500 case mlt_image_opengl:
503 *buffer = mlt_pool_alloc( size );
505 memset( *buffer, 255, size );
507 case mlt_image_yuv422:
510 *buffer = mlt_pool_alloc( size );
513 register uint8_t *p = *buffer;
514 register uint8_t *q = p + size;
515 while ( p != NULL && p != q )
522 case mlt_image_yuv420p:
523 *buffer = mlt_pool_alloc( size * 3 / 2 );
526 memset( *buffer, 235, size );
527 memset( *buffer + size, 128, size / 2 );
534 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
535 mlt_properties_set_int( properties, "test_image", 1 );
542 /** Get the image associated to the frame.
544 * You should express the desired format, width, and height as inputs. As long
545 * as the loader producer was used to generate this or the imageconvert filter
546 * was attached, then you will get the image back in the format you desire.
547 * However, you do not always get the width and height you request depending
548 * on properties and filters. You do not need to supply a pre-allocated
549 * buffer, but you should always supply the desired image format.
551 * \public \memberof mlt_frame_s
552 * \param self a frame
553 * \param[out] buffer an image buffer
554 * \param[in,out] format the image format
555 * \param[in,out] width the horizontal size in pixels
556 * \param[in,out] height the vertical size in pixels
557 * \param writable whether or not you will need to be able to write to the memory returned in \p buffer
558 * \return true if error
559 * \todo Better describe the width and height as inputs.
562 int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
564 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
565 mlt_get_image get_image = mlt_frame_pop_get_image( self );
566 mlt_image_format requested_format = *format;
571 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
572 error = get_image( self, buffer, format, width, height, writable );
573 if ( !error && buffer && *buffer )
575 mlt_properties_set_int( properties, "width", *width );
576 mlt_properties_set_int( properties, "height", *height );
577 if ( self->convert_image && requested_format != mlt_image_none )
578 self->convert_image( self, buffer, format, requested_format );
579 mlt_properties_set_int( properties, "format", *format );
583 error = generate_test_image( properties, buffer, format, width, height, writable );
586 else if ( mlt_properties_get_data( properties, "image", NULL ) && buffer )
588 *format = mlt_properties_get_int( properties, "format" );
589 *buffer = mlt_properties_get_data( properties, "image", NULL );
590 *width = mlt_properties_get_int( properties, "width" );
591 *height = mlt_properties_get_int( properties, "height" );
592 if ( self->convert_image && *buffer && requested_format != mlt_image_none )
594 self->convert_image( self, buffer, format, requested_format );
595 mlt_properties_set_int( properties, "format", *format );
600 error = generate_test_image( properties, buffer, format, width, height, writable );
606 /** Get the alpha channel associated to the frame.
608 * \public \memberof mlt_frame_s
609 * \param self a frame
610 * \return the alpha channel
613 uint8_t *mlt_frame_get_alpha_mask( mlt_frame self )
615 uint8_t *alpha = NULL;
618 if ( self->get_alpha_mask != NULL )
619 alpha = self->get_alpha_mask( self );
621 alpha = mlt_properties_get_data( &self->parent, "alpha", NULL );
624 int size = mlt_properties_get_int( &self->parent, "width" ) * mlt_properties_get_int( &self->parent, "height" );
625 alpha = mlt_pool_alloc( size );
626 memset( alpha, 255, size );
627 mlt_properties_set_data( &self->parent, "alpha", alpha, size, mlt_pool_release, NULL );
633 /** Get the short name for an audio format.
635 * You do not need to deallocate the returned string.
636 * \public \memberof mlt_frame_s
637 * \param format an audio format enum
638 * \return a string for the name of the image format
641 const char * mlt_audio_format_name( mlt_audio_format format )
645 case mlt_audio_none: return "none";
646 case mlt_audio_s16: return "s16";
647 case mlt_audio_s32: return "s32";
648 case mlt_audio_s32le: return "s32le";
649 case mlt_audio_float: return "float";
650 case mlt_audio_f32le: return "f32le";
651 case mlt_audio_u8: return "u8";
656 /** Get the amount of bytes needed for a block of audio.
658 * \public \memberof mlt_frame_s
659 * \param format an audio format enum
660 * \param samples the number of samples per channel
661 * \param channels the number of channels
662 * \return the number of bytes
665 int mlt_audio_format_size( mlt_audio_format format, int samples, int channels )
669 case mlt_audio_none: return 0;
670 case mlt_audio_s16: return samples * channels * sizeof( int16_t );
671 case mlt_audio_s32le:
672 case mlt_audio_s32: return samples * channels * sizeof( int32_t );
673 case mlt_audio_f32le:
674 case mlt_audio_float: return samples * channels * sizeof( float );
675 case mlt_audio_u8: return samples * channels;
680 /** Get the audio associated to the frame.
682 * You should express the desired format, frequency, channels, and samples as inputs. As long
683 * as the loader producer was used to generate this or the audioconvert filter
684 * was attached, then you will get the audio back in the format you desire.
685 * However, you do not always get the channels and samples you request depending
686 * on properties and filters. You do not need to supply a pre-allocated
687 * buffer, but you should always supply the desired audio format.
688 * The audio is always in interleaved format.
689 * You should use the \p mlt_sample_calculator to determine the number of samples you want.
691 * \public \memberof mlt_frame_s
692 * \param self a frame
693 * \param[out] buffer an audio buffer
694 * \param[in,out] format the audio format
695 * \param[in,out] frequency the sample rate
696 * \param[in,out] channels
697 * \param[in,out] samples the number of samples per frame
698 * \return true if error
701 int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
703 mlt_get_audio get_audio = mlt_frame_pop_audio( self );
704 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
705 int hide = mlt_properties_get_int( properties, "test_audio" );
706 mlt_audio_format requested_format = *format;
708 if ( hide == 0 && get_audio != NULL )
710 get_audio( self, buffer, format, frequency, channels, samples );
711 mlt_properties_set_int( properties, "audio_frequency", *frequency );
712 mlt_properties_set_int( properties, "audio_channels", *channels );
713 mlt_properties_set_int( properties, "audio_samples", *samples );
714 mlt_properties_set_int( properties, "audio_format", *format );
715 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
716 self->convert_audio( self, buffer, format, requested_format );
718 else if ( mlt_properties_get_data( properties, "audio", NULL ) )
720 *buffer = mlt_properties_get_data( properties, "audio", NULL );
721 *format = mlt_properties_get_int( properties, "audio_format" );
722 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
723 *channels = mlt_properties_get_int( properties, "audio_channels" );
724 *samples = mlt_properties_get_int( properties, "audio_samples" );
725 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
726 self->convert_audio( self, buffer, format, requested_format );
731 *samples = *samples <= 0 ? 1920 : *samples;
732 *channels = *channels <= 0 ? 2 : *channels;
733 *frequency = *frequency <= 0 ? 48000 : *frequency;
734 mlt_properties_set_int( properties, "audio_frequency", *frequency );
735 mlt_properties_set_int( properties, "audio_channels", *channels );
736 mlt_properties_set_int( properties, "audio_samples", *samples );
737 mlt_properties_set_int( properties, "audio_format", *format );
746 size = *samples * *channels * sizeof( int16_t );
749 size = *samples * *channels * sizeof( int32_t );
751 case mlt_audio_float:
752 size = *samples * *channels * sizeof( float );
758 *buffer = mlt_pool_alloc( size );
760 memset( *buffer, 0, size );
761 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
762 mlt_properties_set_int( properties, "test_audio", 1 );
765 // TODO: This does not belong here
766 if ( *format == mlt_audio_s16 && mlt_properties_get( properties, "meta.volume" ) )
768 double value = mlt_properties_get_double( properties, "meta.volume" );
772 memset( *buffer, 0, *samples * *channels * 2 );
774 else if ( value != 1.0 )
776 int total = *samples * *channels;
777 int16_t *p = *buffer;
785 mlt_properties_set( properties, "meta.volume", NULL );
791 /** Set the audio on a frame.
793 * \public \memberof mlt_frame_s
794 * \param self a frame
795 * \param buffer an buffer containing audio samples
796 * \param format the format of the audio in the \p buffer
797 * \param size the total size of the buffer (optional)
798 * \param destructor a function that releases or deallocates the \p buffer
799 * \return true if error
802 int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
804 mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "audio_format", format );
805 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "audio", buffer, size, destructor, NULL );
808 /** Get audio on a frame as a waveform image.
810 * This generates an 8-bit grayscale image representation of the audio in a
811 * frame. Currently, this only really works for 2 channels.
812 * This allocates the bitmap using mlt_pool so you should release the return
813 * value with \p mlt_pool_release.
815 * \public \memberof mlt_frame_s
816 * \param self a frame
817 * \param w the width of the image
818 * \param h the height of the image to create
819 * \return a pointer to a new bitmap
822 unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h )
825 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
826 mlt_audio_format format = mlt_audio_s16;
827 int frequency = 16000;
829 mlt_producer producer = mlt_frame_get_original_producer( self );
830 double fps = mlt_producer_get_fps( mlt_producer_cut_parent( producer ) );
831 int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
833 // Increase audio resolution proportional to requested image size
834 while ( samples < w )
837 samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
841 mlt_frame_get_audio( self, (void**)&pcm, &format, &frequency, &channels, &samples );
843 // Make an 8-bit buffer large enough to hold rendering
847 unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
848 if ( bitmap != NULL )
849 memset( bitmap, 0, size );
852 mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
854 // Render vertical lines
855 int16_t *ubound = pcm + samples * channels;
856 int skip = samples / w;
857 skip = !skip ? 1 : skip;
858 unsigned char gray = 0xFF / skip;
861 // Iterate sample stream and along x coordinate
862 for ( i = 0; pcm < ubound; i++ )
864 // pcm data has channels interleaved
865 for ( j = 0; j < channels; j++, pcm++ )
867 // Determine sample's magnitude from 2s complement;
868 int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
869 // The height of a line is the ratio of the magnitude multiplied by
870 // the vertical resolution of a single channel
871 int height = h * pcm_magnitude / channels / 2 / 32768;
872 // Determine the starting y coordinate - left top, right bottom
873 int displacement = h * (j * 2 + 1) / channels / 2 - ( *pcm < 0 ? 0 : height );
874 // Position buffer pointer using y coordinate, stride, and x coordinate
875 unsigned char *p = bitmap + i / skip + displacement * w;
877 // Draw vertical line
878 for ( k = 0; k < height + 1; k++ )
880 p[ w * k ] = ( k == 0 ) ? 0xFF : p[ w * k ] + gray;
882 p[ w * k ] = ( k == height ) ? 0xFF : p[ w * k ] + gray;
889 /** Get the end service that produced self frame.
891 * This fetches the first producer of the frame and not any producers that
894 * \public \memberof mlt_frame_s
895 * \param self a frame
899 mlt_producer mlt_frame_get_original_producer( mlt_frame self )
902 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( self ), "_producer", NULL );
906 /** Destroy the frame.
908 * \public \memberof mlt_frame_s
909 * \param self a frame
912 void mlt_frame_close( mlt_frame self )
914 if ( self != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( self ) ) <= 0 )
916 mlt_deque_close( self->stack_image );
917 mlt_deque_close( self->stack_audio );
918 while( mlt_deque_peek_back( self->stack_service ) )
919 mlt_service_close( mlt_deque_pop_back( self->stack_service ) );
920 mlt_deque_close( self->stack_service );
921 mlt_properties_close( &self->parent );
926 /***** convenience functions *****/
928 /** Determine the number of samples that belong in a frame at a time position.
930 * \public \memberof mlt_frame_s
931 * \param fps the frame rate
932 * \param frequency the sample rate
933 * \param position the time position
934 * \return the number of samples per channel
937 int mlt_sample_calculator( float fps, int frequency, int64_t position )
939 /* Compute the cumulative number of samples until the start of this frame and the
940 cumulative number of samples until the start of the next frame. Round each to the
941 nearest integer and take the difference to determine the number of samples in
944 This approach should prevent rounding errors that can accumulate over a large number
945 of frames causing A/V sync problems. */
946 return mlt_sample_calculator_to_now( fps, frequency, position + 1 )
947 - mlt_sample_calculator_to_now( fps, frequency, position );
950 /** Determine the number of samples that belong before a time position.
952 * \public \memberof mlt_frame_s
953 * \param fps the frame rate
954 * \param frequency the sample rate
955 * \param position the time position
956 * \return the number of samples per channel
957 * \bug Will this break when mlt_position is converted to double?
960 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position )
966 samples = (int64_t)( (double) position * (double) frequency / (double) fps +
967 ( position < 0 ? -0.5 : 0.5 ) );
973 void mlt_frame_write_ppm( mlt_frame frame )
977 mlt_image_format format = mlt_image_rgb24;
980 if ( mlt_frame_get_image( frame, &image, &format, &width, &height, 0 ) == 0 )
985 sprintf( filename, "frame-%05d.ppm", (int)mlt_frame_get_position( frame ) );
986 file = fopen( filename, "wb" );
989 fprintf( file, "P6\n%d %d\n255\n", width, height);
990 fwrite( image, width * height * 3, 1, file );
995 /** Get or create a properties object unique to this service instance.
997 * Use this function to hold a service's processing parameters for this
998 * particular frame. Set the parameters in the service's process function.
999 * Then, get the parameters in the function it pushes to the frame's audio
1000 * or image stack. This makes the service more parallel by reducing race
1001 * conditions and less sensitive to multiple instances (by not setting a
1002 * non-unique property on the frame). Creation and destruction of the
1003 * properties object is handled automatically.
1005 * \public \memberof mlt_frame_s
1006 * \param self a frame
1007 * \param service a service
1008 * \return a properties object
1011 mlt_properties mlt_frame_unique_properties( mlt_frame self, mlt_service service )
1013 mlt_properties frame_props = MLT_FRAME_PROPERTIES( self );
1014 mlt_properties service_props = MLT_SERVICE_PROPERTIES( service );
1015 char *unique = mlt_properties_get( service_props, "_unique_id" );
1016 mlt_properties instance_props = mlt_properties_get_data( frame_props, unique, NULL );
1018 if ( !instance_props )
1020 instance_props = mlt_properties_new();
1021 mlt_properties_set_data( frame_props, unique, instance_props, 0, (mlt_destructor) mlt_properties_close, NULL );
1024 return instance_props;
1027 /** Make a copy of a frame.
1029 * This does not copy the get_image/get_audio processing stacks or any
1030 * data properties other than the audio and image.
1032 * \public \memberof mlt_frame_s
1033 * \param self the frame to clone
1034 * \param is_deep a boolean to indicate whether to make a deep copy of the audio
1035 * and video data chunks or to make a shallow copy by pointing to the supplied frame
1036 * \return a almost-complete copy of the frame
1037 * \todo copy the processing deques
1040 mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
1042 mlt_frame new_frame = mlt_frame_init( NULL );
1043 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
1044 mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
1048 mlt_properties_inherit( new_props, properties );
1050 // Carry over some special data properties for the multi consumer.
1051 mlt_properties_set_data( new_props, "_producer",
1052 mlt_frame_get_original_producer( self ), 0, NULL, NULL );
1053 mlt_properties_set_data( new_props, "movit.convert",
1054 mlt_properties_get_data( properties, "movit.convert", NULL), 0, NULL, NULL );
1058 data = mlt_properties_get_data( properties, "audio", &size );
1062 size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
1063 mlt_properties_get_int( properties, "audio_samples" ),
1064 mlt_properties_get_int( properties, "audio_channels" ) );
1065 copy = mlt_pool_alloc( size );
1066 memcpy( copy, data, size );
1067 mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
1069 data = mlt_properties_get_data( properties, "image", &size );
1073 size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
1074 mlt_properties_get_int( properties, "width" ),
1075 mlt_properties_get_int( properties, "height" ), NULL );
1076 copy = mlt_pool_alloc( size );
1077 memcpy( copy, data, size );
1078 mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );
1080 data = mlt_properties_get_data( properties, "alpha", &size );
1084 size = mlt_properties_get_int( properties, "width" ) *
1085 mlt_properties_get_int( properties, "height" );
1086 copy = mlt_pool_alloc( size );
1087 memcpy( copy, data, size );
1088 mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
1094 // This frame takes a reference on the original frame since the data is a shallow copy.
1095 mlt_properties_inc_ref( properties );
1096 mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
1097 (mlt_destructor) mlt_frame_close, NULL );
1100 data = mlt_properties_get_data( properties, "audio", &size );
1101 mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
1102 data = mlt_properties_get_data( properties, "image", &size );
1103 mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
1104 data = mlt_properties_get_data( properties, "alpha", &size );
1105 mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );