3 * \brief interface for all frame classes
6 * Copyright (C) 2003-2013 Ushodaya Enterprises Limited
7 * \author Charles Yates <charles.yates@pandora.be>
8 * \author Dan Dennedy <dan@dennedy.org>
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.
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.
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
25 #include "mlt_frame.h"
26 #include "mlt_producer.h"
27 #include "mlt_factory.h"
28 #include "mlt_profile.h"
35 /** Construct a frame object.
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
42 mlt_frame mlt_frame_init( mlt_service service )
45 mlt_frame self = calloc( 1, sizeof( struct mlt_frame_s ) );
49 mlt_profile profile = mlt_service_profile( service );
51 // Initialise the properties
52 mlt_properties properties = &self->parent;
53 mlt_properties_init( properties, self );
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 );
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( );
73 /** Get a frame's properties.
75 * \public \memberof mlt_frame_s
77 * \return the frame's properties or NULL if an invalid frame is supplied
80 mlt_properties mlt_frame_properties( mlt_frame self )
82 return self != NULL ? &self->parent : NULL;
85 /** Determine if the frame will produce a test card image.
87 * \public \memberof mlt_frame_s
89 * \return true (non-zero) if this will produce from a test card
92 int mlt_frame_is_test_card( mlt_frame self )
94 return mlt_deque_count( self->stack_image ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( self ), "test_image" );
97 /** Determine if the frame will produce audio from a test card.
99 * \public \memberof mlt_frame_s
100 * \param self a frame
101 * \return true (non-zero) if this will produce from a test card
104 int mlt_frame_is_test_audio( mlt_frame self )
106 return mlt_deque_count( self->stack_audio ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( self ), "test_audio" );
109 /** Get the sample aspect ratio of the frame.
111 * \public \memberof mlt_frame_s
112 * \param self a frame
113 * \return the aspect ratio
116 double mlt_frame_get_aspect_ratio( mlt_frame self )
118 return mlt_properties_get_double( MLT_FRAME_PROPERTIES( self ), "aspect_ratio" );
121 /** Set the sample aspect ratio of the frame.
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
129 int mlt_frame_set_aspect_ratio( mlt_frame self, double value )
131 return mlt_properties_set_double( MLT_FRAME_PROPERTIES( self ), "aspect_ratio", value );
134 /** Get the time position of this frame.
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.
140 * \public \memberof mlt_frame_s
141 * \param self a frame
142 * \return the position
143 * \see mlt_frame_original_position
146 mlt_position mlt_frame_get_position( mlt_frame self )
148 int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "_position" );
149 return pos < 0 ? 0 : pos;
152 /** Get the original time position of this frame.
154 * This is the position that the original producer set on the frame.
156 * \public \memberof mlt_frame_s
157 * \param self a frame
158 * \return the position
161 mlt_position mlt_frame_original_position( mlt_frame self )
163 int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "original_position" );
164 return pos < 0 ? 0 : pos;
167 /** Set the time position of this frame.
169 * \public \memberof mlt_frame_s
170 * \param self a frame
171 * \param value the position
172 * \return true if error
175 int mlt_frame_set_position( mlt_frame self, mlt_position value )
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 );
183 /** Stack a get_image callback.
185 * \public \memberof mlt_frame_s
186 * \param self a frame
187 * \param get_image the get_image callback
188 * \return true if error
191 int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image )
193 return mlt_deque_push_back( self->stack_image, get_image );
196 /** Pop a get_image callback.
198 * \public \memberof mlt_frame_s
199 * \param self a frame
200 * \return the get_image callback
203 mlt_get_image mlt_frame_pop_get_image( mlt_frame self )
205 return mlt_deque_pop_back( self->stack_image );
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
216 int mlt_frame_push_frame( mlt_frame self, mlt_frame that )
218 return mlt_deque_push_back( self->stack_image, that );
223 * \public \memberof mlt_frame_s
224 * \param self a frame
225 * \return a frame that was previously pushed
228 mlt_frame mlt_frame_pop_frame( mlt_frame self )
230 return mlt_deque_pop_back( self->stack_image );
235 * \public \memberof mlt_frame_s
236 * \param self a frame
237 * \param that an opaque pointer
238 * \return true if error
241 int mlt_frame_push_service( mlt_frame self, void *that )
243 return mlt_deque_push_back( self->stack_image, that );
248 * \public \memberof mlt_frame_s
249 * \param self a frame
250 * \return an opaque pointer to something previously pushed
253 void *mlt_frame_pop_service( mlt_frame self )
255 return mlt_deque_pop_back( self->stack_image );
260 * \public \memberof mlt_frame_s
261 * \param self a frame
262 * \param that an integer
263 * \return true if error
266 int mlt_frame_push_service_int( mlt_frame self, int that )
268 return mlt_deque_push_back_int( self->stack_image, that );
273 * \public \memberof mlt_frame_s
274 * \param self a frame
275 * \return an integer that was previously pushed
278 int mlt_frame_pop_service_int( mlt_frame self )
280 return mlt_deque_pop_back_int( self->stack_image );
283 /** Push an audio item on the stack.
285 * \public \memberof mlt_frame_s
286 * \param self a frame
287 * \param that an opaque pointer
288 * \return true if error
291 int mlt_frame_push_audio( mlt_frame self, void *that )
293 return mlt_deque_push_back( self->stack_audio, that );
296 /** Pop an audio item from the stack
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
303 void *mlt_frame_pop_audio( mlt_frame self )
305 return mlt_deque_pop_back( self->stack_audio );
308 /** Return the service stack
310 * \public \memberof mlt_frame_s
311 * \param self a frame
312 * \return the service stack
315 mlt_deque mlt_frame_service_stack( mlt_frame self )
317 return self->stack_service;
320 /** Set a new image on the frame.
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
330 int mlt_frame_set_image( mlt_frame self, uint8_t *image, int size, mlt_destructor destroy )
332 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, size, destroy, NULL );
335 /** Set a new alpha channel on the frame.
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
345 int mlt_frame_set_alpha( mlt_frame self, uint8_t *alpha, int size, mlt_destructor destroy )
347 self->get_alpha_mask = NULL;
348 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "alpha", alpha, size, destroy, NULL );
351 /** Replace image stack with the information provided.
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).
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.
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
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...
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
377 void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height )
379 // Remove all items from the stack
380 while( mlt_deque_pop_back( self->stack_image ) ) ;
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;
390 /** Get the short name for an image format.
392 * \public \memberof mlt_frame_s
393 * \param format the image format
397 const char * mlt_image_format_name( mlt_image_format format )
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";
413 /** Get the number of bytes needed for an image.
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
422 int mlt_image_format_size( mlt_image_format format, int width, int height, int *bpp )
427 case mlt_image_rgb24:
429 return width * height * 3;
430 case mlt_image_opengl:
431 case mlt_image_rgb24a:
433 return width * height * 4;
434 case mlt_image_yuv422:
436 return width * height * 2;
437 case mlt_image_yuv420p:
438 if ( bpp ) *bpp = 3 / 2;
439 return width * height * 3 / 2;
441 case mlt_image_glsl_texture:
451 static int generate_test_image( mlt_properties properties, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
453 mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
454 mlt_image_format requested_format = *format;
459 mlt_frame test_frame = NULL;
460 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
463 mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
464 mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
465 mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
466 error = mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
467 if ( !error && buffer && *buffer )
469 mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
470 mlt_properties_set_int( properties, "width", *width );
471 mlt_properties_set_int( properties, "height", *height );
472 if ( test_frame->convert_image && requested_format != mlt_image_none )
473 test_frame->convert_image( test_frame, buffer, format, requested_format );
474 mlt_properties_set_int( properties, "format", *format );
479 mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
482 if ( error && buffer && *format != mlt_image_none )
486 *width = *width == 0 ? 720 : *width;
487 *height = *height == 0 ? 576 : *height;
488 size = *width * *height;
490 mlt_properties_set_int( properties, "format", *format );
491 mlt_properties_set_int( properties, "width", *width );
492 mlt_properties_set_int( properties, "height", *height );
493 mlt_properties_set_double( properties, "aspect_ratio", 1.0 );
497 case mlt_image_rgb24:
500 *buffer = mlt_pool_alloc( size );
502 memset( *buffer, 255, size );
504 case mlt_image_rgb24a:
505 case mlt_image_opengl:
508 *buffer = mlt_pool_alloc( size );
510 memset( *buffer, 255, size );
512 case mlt_image_yuv422:
515 *buffer = mlt_pool_alloc( size );
518 register uint8_t *p = *buffer;
519 register uint8_t *q = p + size;
520 while ( p != NULL && p != q )
527 case mlt_image_yuv420p:
528 *buffer = mlt_pool_alloc( size * 3 / 2 );
531 memset( *buffer, 235, size );
532 memset( *buffer + size, 128, size / 2 );
539 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
540 mlt_properties_set_int( properties, "test_image", 1 );
547 /** Get the image associated to the frame.
549 * You should express the desired format, width, and height as inputs. As long
550 * as the loader producer was used to generate this or the imageconvert filter
551 * was attached, then you will get the image back in the format you desire.
552 * However, you do not always get the width and height you request depending
553 * on properties and filters. You do not need to supply a pre-allocated
554 * buffer, but you should always supply the desired image format.
556 * \public \memberof mlt_frame_s
557 * \param self a frame
558 * \param[out] buffer an image buffer
559 * \param[in,out] format the image format
560 * \param[in,out] width the horizontal size in pixels
561 * \param[in,out] height the vertical size in pixels
562 * \param writable whether or not you will need to be able to write to the memory returned in \p buffer
563 * \return true if error
564 * \todo Better describe the width and height as inputs.
567 int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
569 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
570 mlt_get_image get_image = mlt_frame_pop_get_image( self );
571 mlt_image_format requested_format = *format;
576 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
577 error = get_image( self, buffer, format, width, height, writable );
578 if ( !error && buffer && *buffer )
580 mlt_properties_set_int( properties, "width", *width );
581 mlt_properties_set_int( properties, "height", *height );
582 if ( self->convert_image && requested_format != mlt_image_none )
583 self->convert_image( self, buffer, format, requested_format );
584 mlt_properties_set_int( properties, "format", *format );
588 error = generate_test_image( properties, buffer, format, width, height, writable );
591 else if ( mlt_properties_get_data( properties, "image", NULL ) && buffer )
593 *format = mlt_properties_get_int( properties, "format" );
594 *buffer = mlt_properties_get_data( properties, "image", NULL );
595 *width = mlt_properties_get_int( properties, "width" );
596 *height = mlt_properties_get_int( properties, "height" );
597 if ( self->convert_image && *buffer && requested_format != mlt_image_none )
599 self->convert_image( self, buffer, format, requested_format );
600 mlt_properties_set_int( properties, "format", *format );
605 error = generate_test_image( properties, buffer, format, width, height, writable );
611 /** Get the alpha channel associated to the frame.
613 * \public \memberof mlt_frame_s
614 * \param self a frame
615 * \return the alpha channel
618 uint8_t *mlt_frame_get_alpha_mask( mlt_frame self )
620 uint8_t *alpha = NULL;
623 if ( self->get_alpha_mask != NULL )
624 alpha = self->get_alpha_mask( self );
626 alpha = mlt_properties_get_data( &self->parent, "alpha", NULL );
629 int size = mlt_properties_get_int( &self->parent, "width" ) * mlt_properties_get_int( &self->parent, "height" );
630 alpha = mlt_pool_alloc( size );
631 memset( alpha, 255, size );
632 mlt_properties_set_data( &self->parent, "alpha", alpha, size, mlt_pool_release, NULL );
638 /** Get the short name for an audio format.
640 * You do not need to deallocate the returned string.
641 * \public \memberof mlt_frame_s
642 * \param format an audio format enum
643 * \return a string for the name of the image format
646 const char * mlt_audio_format_name( mlt_audio_format format )
650 case mlt_audio_none: return "none";
651 case mlt_audio_s16: return "s16";
652 case mlt_audio_s32: return "s32";
653 case mlt_audio_s32le: return "s32le";
654 case mlt_audio_float: return "float";
655 case mlt_audio_f32le: return "f32le";
656 case mlt_audio_u8: return "u8";
661 /** Get the amount of bytes needed for a block of audio.
663 * \public \memberof mlt_frame_s
664 * \param format an audio format enum
665 * \param samples the number of samples per channel
666 * \param channels the number of channels
667 * \return the number of bytes
670 int mlt_audio_format_size( mlt_audio_format format, int samples, int channels )
674 case mlt_audio_none: return 0;
675 case mlt_audio_s16: return samples * channels * sizeof( int16_t );
676 case mlt_audio_s32le:
677 case mlt_audio_s32: return samples * channels * sizeof( int32_t );
678 case mlt_audio_f32le:
679 case mlt_audio_float: return samples * channels * sizeof( float );
680 case mlt_audio_u8: return samples * channels;
685 /** Get the audio associated to the frame.
687 * You should express the desired format, frequency, channels, and samples as inputs. As long
688 * as the loader producer was used to generate this or the audioconvert filter
689 * was attached, then you will get the audio back in the format you desire.
690 * However, you do not always get the channels and samples you request depending
691 * on properties and filters. You do not need to supply a pre-allocated
692 * buffer, but you should always supply the desired audio format.
693 * The audio is always in interleaved format.
694 * You should use the \p mlt_sample_calculator to determine the number of samples you want.
696 * \public \memberof mlt_frame_s
697 * \param self a frame
698 * \param[out] buffer an audio buffer
699 * \param[in,out] format the audio format
700 * \param[in,out] frequency the sample rate
701 * \param[in,out] channels
702 * \param[in,out] samples the number of samples per frame
703 * \return true if error
706 int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
708 mlt_get_audio get_audio = mlt_frame_pop_audio( self );
709 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
710 int hide = mlt_properties_get_int( properties, "test_audio" );
711 mlt_audio_format requested_format = *format;
713 if ( hide == 0 && get_audio != NULL )
715 get_audio( self, buffer, format, frequency, channels, samples );
716 mlt_properties_set_int( properties, "audio_frequency", *frequency );
717 mlt_properties_set_int( properties, "audio_channels", *channels );
718 mlt_properties_set_int( properties, "audio_samples", *samples );
719 mlt_properties_set_int( properties, "audio_format", *format );
720 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
721 self->convert_audio( self, buffer, format, requested_format );
723 else if ( mlt_properties_get_data( properties, "audio", NULL ) )
725 *buffer = mlt_properties_get_data( properties, "audio", NULL );
726 *format = mlt_properties_get_int( properties, "audio_format" );
727 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
728 *channels = mlt_properties_get_int( properties, "audio_channels" );
729 *samples = mlt_properties_get_int( properties, "audio_samples" );
730 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
731 self->convert_audio( self, buffer, format, requested_format );
736 *samples = *samples <= 0 ? 1920 : *samples;
737 *channels = *channels <= 0 ? 2 : *channels;
738 *frequency = *frequency <= 0 ? 48000 : *frequency;
739 mlt_properties_set_int( properties, "audio_frequency", *frequency );
740 mlt_properties_set_int( properties, "audio_channels", *channels );
741 mlt_properties_set_int( properties, "audio_samples", *samples );
742 mlt_properties_set_int( properties, "audio_format", *format );
751 size = *samples * *channels * sizeof( int16_t );
754 size = *samples * *channels * sizeof( int32_t );
756 case mlt_audio_float:
757 size = *samples * *channels * sizeof( float );
763 *buffer = mlt_pool_alloc( size );
765 memset( *buffer, 0, size );
766 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
767 mlt_properties_set_int( properties, "test_audio", 1 );
770 // TODO: This does not belong here
771 if ( *format == mlt_audio_s16 && mlt_properties_get( properties, "meta.volume" ) )
773 double value = mlt_properties_get_double( properties, "meta.volume" );
777 memset( *buffer, 0, *samples * *channels * 2 );
779 else if ( value != 1.0 )
781 int total = *samples * *channels;
782 int16_t *p = *buffer;
790 mlt_properties_set( properties, "meta.volume", NULL );
796 /** Set the audio on a frame.
798 * \public \memberof mlt_frame_s
799 * \param self a frame
800 * \param buffer an buffer containing audio samples
801 * \param format the format of the audio in the \p buffer
802 * \param size the total size of the buffer (optional)
803 * \param destructor a function that releases or deallocates the \p buffer
804 * \return true if error
807 int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
809 mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "audio_format", format );
810 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "audio", buffer, size, destructor, NULL );
813 /** Get audio on a frame as a waveform image.
815 * This generates an 8-bit grayscale image representation of the audio in a
816 * frame. Currently, this only really works for 2 channels.
817 * This allocates the bitmap using mlt_pool so you should release the return
818 * value with \p mlt_pool_release.
820 * \public \memberof mlt_frame_s
821 * \param self a frame
822 * \param w the width of the image
823 * \param h the height of the image to create
824 * \return a pointer to a new bitmap
827 unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h )
830 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
831 mlt_audio_format format = mlt_audio_s16;
832 int frequency = 16000;
834 mlt_producer producer = mlt_frame_get_original_producer( self );
835 double fps = mlt_producer_get_fps( mlt_producer_cut_parent( producer ) );
836 int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
838 // Increase audio resolution proportional to requested image size
839 while ( samples < w )
842 samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
846 mlt_frame_get_audio( self, (void**)&pcm, &format, &frequency, &channels, &samples );
848 // Make an 8-bit buffer large enough to hold rendering
852 unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
853 if ( bitmap != NULL )
854 memset( bitmap, 0, size );
857 mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
859 // Render vertical lines
860 int16_t *ubound = pcm + samples * channels;
861 int skip = samples / w;
862 skip = !skip ? 1 : skip;
863 unsigned char gray = 0xFF / skip;
866 // Iterate sample stream and along x coordinate
867 for ( i = 0; pcm < ubound; i++ )
869 // pcm data has channels interleaved
870 for ( j = 0; j < channels; j++, pcm++ )
872 // Determine sample's magnitude from 2s complement;
873 int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
874 // The height of a line is the ratio of the magnitude multiplied by
875 // the vertical resolution of a single channel
876 int height = h * pcm_magnitude / channels / 2 / 32768;
877 // Determine the starting y coordinate - left top, right bottom
878 int displacement = h * (j * 2 + 1) / channels / 2 - ( *pcm < 0 ? 0 : height );
879 // Position buffer pointer using y coordinate, stride, and x coordinate
880 unsigned char *p = bitmap + i / skip + displacement * w;
882 // Draw vertical line
883 for ( k = 0; k < height + 1; k++ )
885 p[ w * k ] = ( k == 0 ) ? 0xFF : p[ w * k ] + gray;
887 p[ w * k ] = ( k == height ) ? 0xFF : p[ w * k ] + gray;
894 /** Get the end service that produced self frame.
896 * This fetches the first producer of the frame and not any producers that
899 * \public \memberof mlt_frame_s
900 * \param self a frame
904 mlt_producer mlt_frame_get_original_producer( mlt_frame self )
907 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( self ), "_producer", NULL );
911 /** Destroy the frame.
913 * \public \memberof mlt_frame_s
914 * \param self a frame
917 void mlt_frame_close( mlt_frame self )
919 if ( self != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( self ) ) <= 0 )
921 mlt_deque_close( self->stack_image );
922 mlt_deque_close( self->stack_audio );
923 while( mlt_deque_peek_back( self->stack_service ) )
924 mlt_service_close( mlt_deque_pop_back( self->stack_service ) );
925 mlt_deque_close( self->stack_service );
926 mlt_properties_close( &self->parent );
931 /***** convenience functions *****/
933 /** Determine the number of samples that belong in a frame at a time position.
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
942 int mlt_sample_calculator( float fps, int frequency, int64_t position )
944 /* Compute the cumulative number of samples until the start of this frame and the
945 cumulative number of samples until the start of the next frame. Round each to the
946 nearest integer and take the difference to determine the number of samples in
949 This approach should prevent rounding errors that can accumulate over a large number
950 of frames causing A/V sync problems. */
951 return mlt_sample_calculator_to_now( fps, frequency, position + 1 )
952 - mlt_sample_calculator_to_now( fps, frequency, position );
955 /** Determine the number of samples that belong before a time position.
957 * \public \memberof mlt_frame_s
958 * \param fps the frame rate
959 * \param frequency the sample rate
960 * \param position the time position
961 * \return the number of samples per channel
962 * \bug Will this break when mlt_position is converted to double?
965 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position )
971 samples = (int64_t)( (double) position * (double) frequency / (double) fps +
972 ( position < 0 ? -0.5 : 0.5 ) );
978 void mlt_frame_write_ppm( mlt_frame frame )
982 mlt_image_format format = mlt_image_rgb24;
985 if ( mlt_frame_get_image( frame, &image, &format, &width, &height, 0 ) == 0 )
990 sprintf( filename, "frame-%05d.ppm", (int)mlt_frame_get_position( frame ) );
991 file = fopen( filename, "wb" );
994 fprintf( file, "P6\n%d %d\n255\n", width, height);
995 fwrite( image, width * height * 3, 1, file );
1000 /** Get or create a properties object unique to this service instance.
1002 * Use this function to hold a service's processing parameters for this
1003 * particular frame. Set the parameters in the service's process function.
1004 * Then, get the parameters in the function it pushes to the frame's audio
1005 * or image stack. This makes the service more parallel by reducing race
1006 * conditions and less sensitive to multiple instances (by not setting a
1007 * non-unique property on the frame). Creation and destruction of the
1008 * properties object is handled automatically.
1010 * \public \memberof mlt_frame_s
1011 * \param self a frame
1012 * \param service a service
1013 * \return a properties object
1016 mlt_properties mlt_frame_unique_properties( mlt_frame self, mlt_service service )
1018 mlt_properties frame_props = MLT_FRAME_PROPERTIES( self );
1019 mlt_properties service_props = MLT_SERVICE_PROPERTIES( service );
1020 char *unique = mlt_properties_get( service_props, "_unique_id" );
1021 mlt_properties instance_props = mlt_properties_get_data( frame_props, unique, NULL );
1023 if ( !instance_props )
1025 instance_props = mlt_properties_new();
1026 mlt_properties_set_data( frame_props, unique, instance_props, 0, (mlt_destructor) mlt_properties_close, NULL );
1029 return instance_props;
1032 /** Make a copy of a frame.
1034 * This does not copy the get_image/get_audio processing stacks or any
1035 * data properties other than the audio and image.
1037 * \public \memberof mlt_frame_s
1038 * \param self the frame to clone
1039 * \param is_deep a boolean to indicate whether to make a deep copy of the audio
1040 * and video data chunks or to make a shallow copy by pointing to the supplied frame
1041 * \return a almost-complete copy of the frame
1042 * \todo copy the processing deques
1045 mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
1047 mlt_frame new_frame = mlt_frame_init( NULL );
1048 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
1049 mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
1053 mlt_properties_inherit( new_props, properties );
1055 // Carry over some special data properties for the multi consumer.
1056 mlt_properties_set_data( new_props, "_producer",
1057 mlt_frame_get_original_producer( self ), 0, NULL, NULL );
1058 mlt_properties_set_data( new_props, "movit.convert",
1059 mlt_properties_get_data( properties, "movit.convert", NULL), 0, NULL, NULL );
1063 data = mlt_properties_get_data( properties, "audio", &size );
1067 size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
1068 mlt_properties_get_int( properties, "audio_samples" ),
1069 mlt_properties_get_int( properties, "audio_channels" ) );
1070 copy = mlt_pool_alloc( size );
1071 memcpy( copy, data, size );
1072 mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
1074 data = mlt_properties_get_data( properties, "image", &size );
1077 int width = mlt_properties_get_int( properties, "width" );
1078 int height = mlt_properties_get_int( properties, "height" );
1081 size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
1082 width, height, NULL );
1083 copy = mlt_pool_alloc( size );
1084 memcpy( copy, data, size );
1085 mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );
1087 data = mlt_properties_get_data( properties, "alpha", &size );
1091 size = width * height;
1092 copy = mlt_pool_alloc( size );
1093 memcpy( copy, data, size );
1094 mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
1100 // This frame takes a reference on the original frame since the data is a shallow copy.
1101 mlt_properties_inc_ref( properties );
1102 mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
1103 (mlt_destructor) mlt_frame_close, NULL );
1106 data = mlt_properties_get_data( properties, "audio", &size );
1107 mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
1108 data = mlt_properties_get_data( properties, "image", &size );
1109 mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
1110 data = mlt_properties_get_data( properties, "alpha", &size );
1111 mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );