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