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( sizeof( struct mlt_frame_s ), 1 );
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 * \public \memberof mlt_frame_s
136 * \param self a frame
137 * \return the position
140 mlt_position mlt_frame_get_position( mlt_frame self )
142 int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "_position" );
143 return pos < 0 ? 0 : pos;
146 /** Set the time position of this frame.
148 * \public \memberof mlt_frame_s
149 * \param self a frame
150 * \param value the position
151 * \return true if error
154 int mlt_frame_set_position( mlt_frame self, mlt_position value )
156 return mlt_properties_set_position( MLT_FRAME_PROPERTIES( self ), "_position", value );
159 /** Stack a get_image callback.
161 * \public \memberof mlt_frame_s
162 * \param self a frame
163 * \param the get_image callback
164 * \return true if error
167 int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image )
169 return mlt_deque_push_back( self->stack_image, get_image );
172 /** Pop a get_image callback.
174 * \public \memberof mlt_frame_s
175 * \param self a frame
176 * \return the get_image callback
179 mlt_get_image mlt_frame_pop_get_image( mlt_frame self )
181 return mlt_deque_pop_back( self->stack_image );
186 * \public \memberof mlt_frame_s
187 * \param self a frame
188 * \param that the frame to push onto \p self
189 * \return true if error
192 int mlt_frame_push_frame( mlt_frame self, mlt_frame that )
194 return mlt_deque_push_back( self->stack_image, that );
199 * \public \memberof mlt_frame_s
200 * \param self a frame
201 * \return a frame that was previously pushed
204 mlt_frame mlt_frame_pop_frame( mlt_frame self )
206 return mlt_deque_pop_back( self->stack_image );
211 * \public \memberof mlt_frame_s
212 * \param self a frame
213 * \param that an opaque pointer
214 * \return true if error
217 int mlt_frame_push_service( mlt_frame self, void *that )
219 return mlt_deque_push_back( self->stack_image, that );
224 * \public \memberof mlt_frame_s
225 * \param self a frame
226 * \return an opaque pointer to something previously pushed
229 void *mlt_frame_pop_service( mlt_frame self )
231 return mlt_deque_pop_back( self->stack_image );
236 * \public \memberof mlt_frame_s
237 * \param self a frame
238 * \param that an integer
239 * \return true if error
242 int mlt_frame_push_service_int( mlt_frame self, int that )
244 return mlt_deque_push_back_int( self->stack_image, that );
249 * \public \memberof mlt_frame_s
250 * \param self a frame
251 * \return an integer that was previously pushed
254 int mlt_frame_pop_service_int( mlt_frame self )
256 return mlt_deque_pop_back_int( self->stack_image );
259 /** Push an audio item on the stack.
261 * \public \memberof mlt_frame_s
262 * \param self a frame
263 * \param that an opaque pointer
264 * \return true if error
267 int mlt_frame_push_audio( mlt_frame self, void *that )
269 return mlt_deque_push_back( self->stack_audio, that );
272 /** Pop an audio item from the stack
274 * \public \memberof mlt_frame_s
275 * \param self a frame
276 * \return an opaque pointer to something that was pushed onto the frame's audio stack
279 void *mlt_frame_pop_audio( mlt_frame self )
281 return mlt_deque_pop_back( self->stack_audio );
284 /** Return the service stack
286 * \public \memberof mlt_frame_s
287 * \param self a frame
288 * \return the service stack
291 mlt_deque mlt_frame_service_stack( mlt_frame self )
293 return self->stack_service;
296 /** Set a new image on the frame.
298 * \public \memberof mlt_frame_s
299 * \param self a frame
300 * \param image a pointer to the raw image data
301 * \param size the size of the image data in bytes (optional)
302 * \param destroy a function to deallocate \p image when the frame is closed (optional)
303 * \return true if error
306 int mlt_frame_set_image( mlt_frame self, uint8_t *image, int size, mlt_destructor destroy )
308 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, size, destroy, NULL );
311 /** Set a new alpha channel on the frame.
313 * \public \memberof mlt_frame_s
314 * \param self a frame
315 * \param alpha a pointer to the alpha channel
316 * \param size the size of the alpha channel in bytes (optional)
317 * \param destroy a function to deallocate \p alpha when the frame is closed (optional)
318 * \return true if error
321 int mlt_frame_set_alpha( mlt_frame self, uint8_t *alpha, int size, mlt_destructor destroy )
323 self->get_alpha_mask = NULL;
324 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "alpha", alpha, size, destroy, NULL );
327 /** Replace image stack with the information provided.
329 * This might prove to be unreliable and restrictive - the idea is that a transition
330 * which normally uses two images may decide to only use the b frame (ie: in the case
331 * of a composite where the b frame completely obscures the a frame).
333 * The image must be writable and the destructor for the image itself must be taken
334 * care of on another frame and that frame cannot have a replace applied to it...
335 * Further it assumes that no alpha mask is in use.
337 * For these reasons, it can only be used in a specific situation - when you have
338 * multiple tracks each with their own transition and these transitions are applied
339 * in a strictly reversed order (ie: highest numbered [lowest track] is processed
342 * More reliable approach - the cases should be detected during the process phase
343 * and the upper tracks should simply not be invited to stack...
345 * \public \memberof mlt_frame_s
346 * \param self a frame
347 * \param image a new image
348 * \param format the image format
349 * \param width the width of the new image
350 * \param height the height of the new image
353 void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height )
355 // Remove all items from the stack
356 while( mlt_deque_pop_back( self->stack_image ) ) ;
358 // Update the information
359 mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "image", image, 0, NULL, NULL );
360 mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "width", width );
361 mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "height", height );
362 mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "format", format );
363 self->get_alpha_mask = NULL;
366 /** Get the short name for an image format.
368 * \public \memberof mlt_frame_s
369 * \param format the image format
373 const char * mlt_image_format_name( mlt_image_format format )
377 case mlt_image_none: return "none";
378 case mlt_image_rgb24: return "rgb24";
379 case mlt_image_rgb24a: return "rgb24a";
380 case mlt_image_yuv422: return "yuv422";
381 case mlt_image_yuv420p: return "yuv420p";
382 case mlt_image_opengl: return "opengl";
387 /** Get the number of bytes needed for an image.
389 * \public \memberof mlt_frame_s
390 * \param format the image format
391 * \param width width of the image in pixels
392 * \param height height of the image in pixels
393 * \param[out] bpp the number of bytes per pixel (optional)
394 * \return the number of bytes
396 int mlt_image_format_size( mlt_image_format format, int width, int height, int *bpp )
404 case mlt_image_rgb24:
406 return width * height * 3;
407 case mlt_image_opengl:
408 case mlt_image_rgb24a:
410 return width * height * 4;
411 case mlt_image_yuv422:
413 return width * height * 2;
414 case mlt_image_yuv420p:
415 if ( bpp ) *bpp = 3 / 2;
416 return width * height * 3 / 2;
421 /** Get the image associated to the frame.
423 * You should express the desired format, width, and height as inputs. As long
424 * as the loader producer was used to generate this or the imageconvert filter
425 * was attached, then you will get the image back in the format you desire.
426 * However, you do not always get the width and height you request depending
427 * on properties and filters. You do not need to supply a pre-allocated
428 * buffer, but you should always supply the desired image format.
430 * \public \memberof mlt_frame_s
431 * \param self a frame
432 * \param[out] buffer an image buffer
433 * \param[in,out] format the image format
434 * \param[in,out] width the horizontal size in pixels
435 * \param[in,out] height the vertical size in pixels
436 * \param writable whether or not you will need to be able to write to the memory returned in \p buffer
437 * \return true if error
438 * \todo Better describe the width and height as inputs.
441 int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
443 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
444 mlt_get_image get_image = mlt_frame_pop_get_image( self );
445 mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
446 mlt_image_format requested_format = *format;
451 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
452 error = get_image( self, buffer, format, width, height, writable );
453 if ( !error && *buffer )
455 mlt_properties_set_int( properties, "width", *width );
456 mlt_properties_set_int( properties, "height", *height );
457 if ( self->convert_image && *buffer && requested_format != mlt_image_none )
458 self->convert_image( self, buffer, format, requested_format );
459 mlt_properties_set_int( properties, "format", *format );
463 // Cause the image to be loaded from test card or fallback (white) below.
464 mlt_frame_get_image( self, buffer, format, width, height, writable );
467 else if ( mlt_properties_get_data( properties, "image", NULL ) )
469 *format = mlt_properties_get_int( properties, "format" );
470 *buffer = mlt_properties_get_data( properties, "image", NULL );
471 *width = mlt_properties_get_int( properties, "width" );
472 *height = mlt_properties_get_int( properties, "height" );
473 if ( self->convert_image && *buffer && requested_format != mlt_image_none )
475 self->convert_image( self, buffer, format, requested_format );
476 mlt_properties_set_int( properties, "format", *format );
481 mlt_frame test_frame = NULL;
482 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
485 mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
486 mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
487 mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
488 mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
489 mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
490 mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
491 // mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
492 // mlt_properties_set_int( properties, "width", *width );
493 // mlt_properties_set_int( properties, "height", *height );
494 // mlt_properties_set_int( properties, "format", *format );
498 mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
499 mlt_frame_get_image( self, buffer, format, width, height, writable );
508 *width = *width == 0 ? 720 : *width;
509 *height = *height == 0 ? 576 : *height;
510 size = *width * *height;
512 mlt_properties_set_int( properties, "format", *format );
513 mlt_properties_set_int( properties, "width", *width );
514 mlt_properties_set_int( properties, "height", *height );
515 mlt_properties_set_int( properties, "aspect_ratio", 0 );
523 case mlt_image_rgb24:
526 *buffer = mlt_pool_alloc( size );
528 memset( *buffer, 255, size );
530 case mlt_image_rgb24a:
531 case mlt_image_opengl:
534 *buffer = mlt_pool_alloc( size );
536 memset( *buffer, 255, size );
538 case mlt_image_yuv422:
541 *buffer = mlt_pool_alloc( size );
544 while ( p != NULL && p != q )
550 case mlt_image_yuv420p:
552 *buffer = mlt_pool_alloc( size );
554 memset( *buffer, 255, size );
558 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
559 mlt_properties_set_int( properties, "test_image", 1 );
565 /** Get the alpha channel associated to the frame.
567 * \public \memberof mlt_frame_s
568 * \param self a frame
569 * \return the alpha channel
572 uint8_t *mlt_frame_get_alpha_mask( mlt_frame self )
574 uint8_t *alpha = NULL;
577 if ( self->get_alpha_mask != NULL )
578 alpha = self->get_alpha_mask( self );
580 alpha = mlt_properties_get_data( &self->parent, "alpha", NULL );
583 int size = mlt_properties_get_int( &self->parent, "width" ) * mlt_properties_get_int( &self->parent, "height" );
584 alpha = mlt_pool_alloc( size );
585 memset( alpha, 255, size );
586 mlt_properties_set_data( &self->parent, "alpha", alpha, size, mlt_pool_release, NULL );
592 /** Get the short name for an audio format.
594 * You do not need to deallocate the returned string.
595 * \public \memberof mlt_frame_s
596 * \param format an audio format enum
597 * \return a string for the name of the image format
600 const char * mlt_audio_format_name( mlt_audio_format format )
604 case mlt_audio_none: return "none";
605 case mlt_audio_s16: return "s16";
606 case mlt_audio_s32: return "s32";
607 case mlt_audio_s32le: return "s32le";
608 case mlt_audio_float: return "float";
609 case mlt_audio_f32le: return "f32le";
614 /** Get the amount of bytes needed for a block of audio.
616 * \public \memberof mlt_frame_s
617 * \param format an audio format enum
618 * \param samples the number of samples per channel
619 * \param channels the number of channels
620 * \return the number of bytes
623 int mlt_audio_format_size( mlt_audio_format format, int samples, int channels )
627 case mlt_audio_none: return 0;
628 case mlt_audio_s16: return samples * channels * sizeof( int16_t );
629 case mlt_audio_s32le:
630 case mlt_audio_s32: return samples * channels * sizeof( int32_t );
631 case mlt_audio_f32le:
632 case mlt_audio_float: return samples * channels * sizeof( float );
637 /** Get the audio associated to the frame.
639 * You should express the desired format, frequency, channels, and samples as inputs. As long
640 * as the loader producer was used to generate this or the audioconvert filter
641 * was attached, then you will get the audio back in the format you desire.
642 * However, you do not always get the channels and samples you request depending
643 * on properties and filters. You do not need to supply a pre-allocated
644 * buffer, but you should always supply the desired audio format.
645 * The audio is always in interleaved format.
646 * You should use the \p mlt_sample_calculator to determine the number of samples you want.
648 * \public \memberof mlt_frame_s
649 * \param self a frame
650 * \param[out] buffer an audio buffer
651 * \param[in,out] format the audio format
652 * \param[in,out] frequency the sample rate
653 * \param[in,out] channels
654 * \param[in,out] samples the number of samples per frame
655 * \return true if error
658 int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
660 mlt_get_audio get_audio = mlt_frame_pop_audio( self );
661 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
662 int hide = mlt_properties_get_int( properties, "test_audio" );
663 mlt_audio_format requested_format = *format;
665 if ( hide == 0 && get_audio != NULL )
667 get_audio( self, buffer, format, frequency, channels, samples );
668 mlt_properties_set_int( properties, "audio_frequency", *frequency );
669 mlt_properties_set_int( properties, "audio_channels", *channels );
670 mlt_properties_set_int( properties, "audio_samples", *samples );
671 mlt_properties_set_int( properties, "audio_format", *format );
672 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
673 self->convert_audio( self, buffer, format, requested_format );
675 else if ( mlt_properties_get_data( properties, "audio", NULL ) )
677 *buffer = mlt_properties_get_data( properties, "audio", NULL );
678 *format = mlt_properties_get_int( properties, "audio_format" );
679 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
680 *channels = mlt_properties_get_int( properties, "audio_channels" );
681 *samples = mlt_properties_get_int( properties, "audio_samples" );
682 if ( self->convert_audio && *buffer && requested_format != mlt_audio_none )
683 self->convert_audio( self, buffer, format, requested_format );
688 *samples = *samples <= 0 ? 1920 : *samples;
689 *channels = *channels <= 0 ? 2 : *channels;
690 *frequency = *frequency <= 0 ? 48000 : *frequency;
691 mlt_properties_set_int( properties, "audio_frequency", *frequency );
692 mlt_properties_set_int( properties, "audio_channels", *channels );
693 mlt_properties_set_int( properties, "audio_samples", *samples );
694 mlt_properties_set_int( properties, "audio_format", *format );
703 size = *samples * *channels * sizeof( int16_t );
706 size = *samples * *channels * sizeof( int32_t );
708 case mlt_audio_float:
709 size = *samples * *channels * sizeof( float );
715 *buffer = mlt_pool_alloc( size );
717 memset( *buffer, 0, size );
718 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
719 mlt_properties_set_int( properties, "test_audio", 1 );
722 // TODO: This does not belong here
723 if ( *format == mlt_audio_s16 && mlt_properties_get( properties, "meta.volume" ) )
725 double value = mlt_properties_get_double( properties, "meta.volume" );
729 memset( *buffer, 0, *samples * *channels * 2 );
731 else if ( value != 1.0 )
733 int total = *samples * *channels;
734 int16_t *p = *buffer;
742 mlt_properties_set( properties, "meta.volume", NULL );
748 /** Set the audio on a frame.
750 * \public \memberof mlt_frame_s
751 * \param self a frame
752 * \param buffer an buffer containing audio samples
753 * \param format the format of the audio in the \p buffer
754 * \param size the total size of the buffer (optional)
755 * \param destructor a function that releases or deallocates the \p buffer
756 * \return true if error
759 int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
761 mlt_properties_set_int( MLT_FRAME_PROPERTIES( self ), "audio_format", format );
762 return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "audio", buffer, size, destructor, NULL );
765 /** Get audio on a frame as a waveform image.
767 * This generates an 8-bit grayscale image representation of the audio in a
768 * frame. Currently, this only really works for 2 channels.
769 * This allocates the bitmap using mlt_pool so you should release the return
770 * value with \p mlt_pool_release.
772 * \public \memberof mlt_frame_s
773 * \param self a frame
774 * \param w the width of the image
775 * \param h the height of the image to create
776 * \return a pointer to a new bitmap
779 unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h )
782 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
783 mlt_audio_format format = mlt_audio_s16;
784 int frequency = 16000;
786 mlt_producer producer = mlt_frame_get_original_producer( self );
787 double fps = mlt_producer_get_fps( mlt_producer_cut_parent( producer ) );
788 int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
790 // Increase audio resolution proportional to requested image size
791 while ( samples < w )
794 samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( self ) );
798 mlt_frame_get_audio( self, (void**)&pcm, &format, &frequency, &channels, &samples );
800 // Make an 8-bit buffer large enough to hold rendering
802 unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
803 if ( bitmap != NULL )
804 memset( bitmap, 0, size );
805 mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
807 // Render vertical lines
808 int16_t *ubound = pcm + samples * channels;
809 int skip = samples / w;
810 skip = !skip ? 1 : skip;
811 unsigned char gray = 0xFF / skip;
814 // Iterate sample stream and along x coordinate
815 for ( i = 0; pcm < ubound; i++ )
817 // pcm data has channels interleaved
818 for ( j = 0; j < channels; j++, pcm++ )
820 // Determine sample's magnitude from 2s complement;
821 int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
822 // The height of a line is the ratio of the magnitude multiplied by
823 // the vertical resolution of a single channel
824 int height = h * pcm_magnitude / channels / 2 / 32768;
825 // Determine the starting y coordinate - left top, right bottom
826 int displacement = h * (j * 2 + 1) / channels / 2 - ( *pcm < 0 ? 0 : height );
827 // Position buffer pointer using y coordinate, stride, and x coordinate
828 unsigned char *p = bitmap + i / skip + displacement * w;
830 // Draw vertical line
831 for ( k = 0; k < height + 1; k++ )
833 p[ w * k ] = ( k == 0 ) ? 0xFF : p[ w * k ] + gray;
835 p[ w * k ] = ( k == height ) ? 0xFF : p[ w * k ] + gray;
842 /** Get the end service that produced self frame.
844 * This fetches the first producer of the frame and not any producers that
847 * \public \memberof mlt_frame_s
848 * \param self a frame
852 mlt_producer mlt_frame_get_original_producer( mlt_frame self )
855 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( self ), "_producer", NULL );
859 /** Destroy the frame.
861 * \public \memberof mlt_frame_s
862 * \param self a frame
865 void mlt_frame_close( mlt_frame self )
867 if ( self != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( self ) ) <= 0 )
869 mlt_deque_close( self->stack_image );
870 mlt_deque_close( self->stack_audio );
871 while( mlt_deque_peek_back( self->stack_service ) )
872 mlt_service_close( mlt_deque_pop_back( self->stack_service ) );
873 mlt_deque_close( self->stack_service );
874 mlt_properties_close( &self->parent );
879 /***** convenience functions *****/
881 /** Determine the number of samples that belong in a frame at a time position.
883 * \public \memberof mlt_frame_s
884 * \param fps the frame rate
885 * \param frequency the sample rate
886 * \param position the time position
887 * \return the number of samples per channel
890 int mlt_sample_calculator( float fps, int frequency, int64_t position )
892 /* Compute the cumulative number of samples until the start of this frame and the
893 cumulative number of samples until the start of the next frame. Round each to the
894 nearest integer and take the difference to determine the number of samples in
897 This approach should prevent rounding errors that can accumulate over a large number
898 of frames causing A/V sync problems. */
899 return mlt_sample_calculator_to_now( fps, frequency, position + 1 )
900 - mlt_sample_calculator_to_now( fps, frequency, position );
903 /** Determine the number of samples that belong before a time position.
905 * \public \memberof mlt_frame_s
906 * \param fps the frame rate
907 * \param frequency the sample rate
908 * \param position the time position
909 * \return the number of samples per channel
910 * \bug Will this break when mlt_position is converted to double?
913 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position )
919 samples = (int64_t)( (double) position * (double) frequency / (double) fps +
920 ( position < 0 ? -0.5 : 0.5 ) );
926 void mlt_frame_write_ppm( mlt_frame frame )
930 mlt_image_format format = mlt_image_rgb24;
933 if ( mlt_frame_get_image( frame, &image, &format, &width, &height, 0 ) == 0 )
938 sprintf( filename, "frame-%05d.ppm", mlt_frame_get_position( frame ) );
939 file = fopen( filename, "wb" );
942 fprintf( file, "P6\n%d %d\n255\n", width, height);
943 fwrite( image, width * height * 3, 1, file );
948 /** Get or create a properties object unique to this service instance.
950 * Use this function to hold a service's processing parameters for this
951 * particular frame. Set the parameters in the service's process function.
952 * Then, get the parameters in the function it pushes to the frame's audio
953 * or image stack. This makes the service more parallel by reducing race
954 * conditions and less sensitive to multiple instances (by not setting a
955 * non-unique property on the frame). Creation and destruction of the
956 * properties object is handled automatically.
958 * \public \memberof mlt_frame_s
959 * \param self a frame
960 * \param service a service
961 * \return a properties object
964 mlt_properties mlt_frame_unique_properties( mlt_frame self, mlt_service service )
966 mlt_properties frame_props = MLT_FRAME_PROPERTIES( self );
967 mlt_properties service_props = MLT_SERVICE_PROPERTIES( service );
968 char *unique = mlt_properties_get( service_props, "_unique_id" );
969 mlt_properties instance_props = mlt_properties_get_data( frame_props, unique, NULL );
971 if ( !instance_props )
973 instance_props = mlt_properties_new();
974 mlt_properties_set_data( frame_props, unique, instance_props, 0, (mlt_destructor) mlt_properties_close, NULL );
977 return instance_props;
980 /** Make a copy of a frame.
982 * This does not copy the get_image/get_audio processing stacks or any
983 * data properties other than the audio and image.
985 * \public \memberof mlt_frame_s
986 * \param self the frame to clone
987 * \param is_deep a boolean to indicate whether to make a deep copy of the audio
988 * and video data chunks or to make a shallow copy by pointing to the supplied frame
989 * \return a almost-complete copy of the frame
990 * \todo copy the processing deques
993 mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
995 mlt_frame new_frame = mlt_frame_init( NULL );
996 mlt_properties properties = MLT_FRAME_PROPERTIES( self );
997 mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
1001 mlt_properties_inherit( new_props, properties );
1004 data = mlt_properties_get_data( properties, "audio", &size );
1008 size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
1009 mlt_properties_get_int( properties, "audio_samples" ),
1010 mlt_properties_get_int( properties, "audio_channels" ) );
1011 copy = mlt_pool_alloc( size );
1012 memcpy( copy, data, size );
1013 mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
1015 data = mlt_properties_get_data( properties, "image", &size );
1019 size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
1020 mlt_properties_get_int( properties, "width" ),
1021 mlt_properties_get_int( properties, "height" ), NULL );
1022 copy = mlt_pool_alloc( size );
1023 memcpy( copy, data, size );
1024 mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );
1026 data = mlt_properties_get_data( properties, "alpha", &size );
1030 size = mlt_properties_get_int( properties, "width" ) *
1031 mlt_properties_get_int( properties, "height" );
1032 copy = mlt_pool_alloc( size );
1033 memcpy( copy, data, size );
1034 mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
1040 // This frame takes a reference on the original frame since the data is a shallow copy.
1041 mlt_properties_inc_ref( properties );
1042 mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
1043 (mlt_destructor) mlt_frame_close, NULL );
1046 data = mlt_properties_get_data( properties, "audio", &size );
1047 mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
1048 data = mlt_properties_get_data( properties, "image", &size );
1049 mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
1050 data = mlt_properties_get_data( properties, "alpha", &size );
1051 mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );