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