a34579edf83b4585d2c085d4db0509f4ebb34bb1
[melted] / src / framework / mlt_frame.c
1 /*
2 * mlt_frame.c -- interface for all frame classes
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "config.h"
22 #include "mlt_frame.h"
23 #include "mlt_producer.h"
24 #include "mlt_factory.h"
25 #include "mlt_profile.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <math.h>
31
32 /** Constructor for a frame.
33 */
34
35 mlt_frame mlt_frame_init( )
36 {
37 // Allocate a frame
38 mlt_frame this = calloc( sizeof( struct mlt_frame_s ), 1 );
39
40 if ( this != NULL )
41 {
42 // Initialise the properties
43 mlt_properties properties = &this->parent;
44 mlt_properties_init( properties, this );
45
46 // Set default properties on the frame
47 mlt_properties_set_position( properties, "_position", 0.0 );
48 mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
49 mlt_properties_set_int( properties, "width", mlt_profile_get()->width );
50 mlt_properties_set_int( properties, "height", mlt_profile_get()->height );
51 mlt_properties_set_int( properties, "normalised_width", mlt_profile_get()->width );
52 mlt_properties_set_int( properties, "normalised_height", mlt_profile_get()->height );
53 mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( NULL ) );
54 mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
55 mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
56
57 // Construct stacks for frames and methods
58 this->stack_image = mlt_deque_init( );
59 this->stack_audio = mlt_deque_init( );
60 this->stack_service = mlt_deque_init( );
61 }
62
63 return this;
64 }
65
66 /** Fetch the frames properties.
67 */
68
69 mlt_properties mlt_frame_properties( mlt_frame this )
70 {
71 return this != NULL ? &this->parent : NULL;
72 }
73
74 /** Check if we have a way to derive something other than a test card.
75 */
76
77 int mlt_frame_is_test_card( mlt_frame this )
78 {
79 return mlt_deque_count( this->stack_image ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "test_image" );
80 }
81
82 /** Check if we have a way to derive something other than test audio.
83 */
84
85 int mlt_frame_is_test_audio( mlt_frame this )
86 {
87 return mlt_deque_count( this->stack_audio ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "test_audio" );
88 }
89
90 /** Get the aspect ratio of the frame.
91 */
92
93 double mlt_frame_get_aspect_ratio( mlt_frame this )
94 {
95 return mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "aspect_ratio" );
96 }
97
98 /** Set the aspect ratio of the frame.
99 */
100
101 int mlt_frame_set_aspect_ratio( mlt_frame this, double value )
102 {
103 return mlt_properties_set_double( MLT_FRAME_PROPERTIES( this ), "aspect_ratio", value );
104 }
105
106 /** Get the position of this frame.
107 */
108
109 mlt_position mlt_frame_get_position( mlt_frame this )
110 {
111 int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( this ), "_position" );
112 return pos < 0 ? 0 : pos;
113 }
114
115 /** Set the position of this frame.
116 */
117
118 int mlt_frame_set_position( mlt_frame this, mlt_position value )
119 {
120 return mlt_properties_set_position( MLT_FRAME_PROPERTIES( this ), "_position", value );
121 }
122
123 /** Stack a get_image callback.
124 */
125
126 int mlt_frame_push_get_image( mlt_frame this, mlt_get_image get_image )
127 {
128 return mlt_deque_push_back( this->stack_image, get_image );
129 }
130
131 /** Pop a get_image callback.
132 */
133
134 mlt_get_image mlt_frame_pop_get_image( mlt_frame this )
135 {
136 return mlt_deque_pop_back( this->stack_image );
137 }
138
139 /** Push a frame.
140 */
141
142 int mlt_frame_push_frame( mlt_frame this, mlt_frame that )
143 {
144 return mlt_deque_push_back( this->stack_image, that );
145 }
146
147 /** Pop a frame.
148 */
149
150 mlt_frame mlt_frame_pop_frame( mlt_frame this )
151 {
152 return mlt_deque_pop_back( this->stack_image );
153 }
154
155 /** Push a service.
156 */
157
158 int mlt_frame_push_service( mlt_frame this, void *that )
159 {
160 return mlt_deque_push_back( this->stack_image, that );
161 }
162
163 /** Pop a service.
164 */
165
166 void *mlt_frame_pop_service( mlt_frame this )
167 {
168 return mlt_deque_pop_back( this->stack_image );
169 }
170
171 /** Push a service.
172 */
173
174 int mlt_frame_push_service_int( mlt_frame this, int that )
175 {
176 return mlt_deque_push_back_int( this->stack_image, that );
177 }
178
179 /** Pop a service.
180 */
181
182 int mlt_frame_pop_service_int( mlt_frame this )
183 {
184 return mlt_deque_pop_back_int( this->stack_image );
185 }
186
187 /** Push an audio item on the stack.
188 */
189
190 int mlt_frame_push_audio( mlt_frame this, void *that )
191 {
192 return mlt_deque_push_back( this->stack_audio, that );
193 }
194
195 /** Pop an audio item from the stack
196 */
197
198 void *mlt_frame_pop_audio( mlt_frame this )
199 {
200 return mlt_deque_pop_back( this->stack_audio );
201 }
202
203 /** Return the service stack
204 */
205
206 mlt_deque mlt_frame_service_stack( mlt_frame this )
207 {
208 return this->stack_service;
209 }
210
211 /** Replace image stack with the information provided.
212
213 This might prove to be unreliable and restrictive - the idea is that a transition
214 which normally uses two images may decide to only use the b frame (ie: in the case
215 of a composite where the b frame completely obscures the a frame).
216
217 The image must be writable and the destructor for the image itself must be taken
218 care of on another frame and that frame cannot have a replace applied to it...
219 Further it assumes that no alpha mask is in use.
220
221 For these reasons, it can only be used in a specific situation - when you have
222 multiple tracks each with their own transition and these transitions are applied
223 in a strictly reversed order (ie: highest numbered [lowest track] is processed
224 first).
225
226 More reliable approach - the cases should be detected during the process phase
227 and the upper tracks should simply not be invited to stack...
228 */
229
230 void mlt_frame_replace_image( mlt_frame this, uint8_t *image, mlt_image_format format, int width, int height )
231 {
232 // Remove all items from the stack
233 while( mlt_deque_pop_back( this->stack_image ) ) ;
234
235 // Update the information
236 mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", image, 0, NULL, NULL );
237 mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "width", width );
238 mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "height", height );
239 mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "format", format );
240 this->get_alpha_mask = NULL;
241 }
242
243 /** Get the image associated to the frame.
244 */
245
246 int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
247 {
248 mlt_properties properties = MLT_FRAME_PROPERTIES( this );
249 mlt_get_image get_image = mlt_frame_pop_get_image( this );
250 mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
251 int error = 0;
252
253 if ( get_image != NULL )
254 {
255 mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
256 mlt_position position = mlt_frame_get_position( this );
257 error = get_image( this, buffer, format, width, height, writable );
258 mlt_properties_set_int( properties, "width", *width );
259 mlt_properties_set_int( properties, "height", *height );
260 mlt_properties_set_int( properties, "format", *format );
261 mlt_frame_set_position( this, position );
262 }
263 else if ( mlt_properties_get_data( properties, "image", NULL ) != NULL )
264 {
265 *format = mlt_properties_get_int( properties, "format" );
266 *buffer = mlt_properties_get_data( properties, "image", NULL );
267 *width = mlt_properties_get_int( properties, "width" );
268 *height = mlt_properties_get_int( properties, "height" );
269 }
270 else if ( producer != NULL )
271 {
272 mlt_frame test_frame = NULL;
273 mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
274 if ( test_frame != NULL )
275 {
276 mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
277 mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
278 mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
279 mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
280 mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
281 mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
282 mlt_properties_set_int( properties, "width", *width );
283 mlt_properties_set_int( properties, "height", *height );
284 mlt_properties_set_int( properties, "format", *format );
285 mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
286 }
287 else
288 {
289 mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
290 mlt_frame_get_image( this, buffer, format, width, height, writable );
291 }
292 }
293 else
294 {
295 register uint8_t *p;
296 register uint8_t *q;
297 int size = 0;
298
299 *width = *width == 0 ? 720 : *width;
300 *height = *height == 0 ? 576 : *height;
301 size = *width * *height;
302
303 mlt_properties_set_int( properties, "format", *format );
304 mlt_properties_set_int( properties, "width", *width );
305 mlt_properties_set_int( properties, "height", *height );
306 mlt_properties_set_int( properties, "aspect_ratio", 0 );
307
308 switch( *format )
309 {
310 case mlt_image_none:
311 size = 0;
312 *buffer = NULL;
313 break;
314 case mlt_image_rgb24:
315 size *= 3;
316 size += *width * 3;
317 *buffer = mlt_pool_alloc( size );
318 if ( *buffer )
319 memset( *buffer, 255, size );
320 break;
321 case mlt_image_rgb24a:
322 case mlt_image_opengl:
323 size *= 4;
324 size += *width * 4;
325 *buffer = mlt_pool_alloc( size );
326 if ( *buffer )
327 memset( *buffer, 255, size );
328 break;
329 case mlt_image_yuv422:
330 size *= 2;
331 size += *width * 2;
332 *buffer = mlt_pool_alloc( size );
333 p = *buffer;
334 q = p + size;
335 while ( p != NULL && p != q )
336 {
337 *p ++ = 235;
338 *p ++ = 128;
339 }
340 break;
341 case mlt_image_yuv420p:
342 size = size * 3 / 2;
343 *buffer = mlt_pool_alloc( size );
344 if ( *buffer )
345 memset( *buffer, 255, size );
346 break;
347 }
348
349 mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
350 mlt_properties_set_int( properties, "test_image", 1 );
351 }
352
353 mlt_properties_set_int( properties, "scaled_width", *width );
354 mlt_properties_set_int( properties, "scaled_height", *height );
355
356 return error;
357 }
358
359 uint8_t *mlt_frame_get_alpha_mask( mlt_frame this )
360 {
361 uint8_t *alpha = NULL;
362 if ( this != NULL )
363 {
364 if ( this->get_alpha_mask != NULL )
365 alpha = this->get_alpha_mask( this );
366 if ( alpha == NULL )
367 alpha = mlt_properties_get_data( &this->parent, "alpha", NULL );
368 if ( alpha == NULL )
369 {
370 int size = mlt_properties_get_int( &this->parent, "scaled_width" ) * mlt_properties_get_int( &this->parent, "scaled_height" );
371 alpha = mlt_pool_alloc( size );
372 memset( alpha, 255, size );
373 mlt_properties_set_data( &this->parent, "alpha", alpha, size, mlt_pool_release, NULL );
374 }
375 }
376 return alpha;
377 }
378
379 int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
380 {
381 mlt_get_audio get_audio = mlt_frame_pop_audio( this );
382 mlt_properties properties = MLT_FRAME_PROPERTIES( this );
383 int hide = mlt_properties_get_int( properties, "test_audio" );
384
385 if ( hide == 0 && get_audio != NULL )
386 {
387 mlt_position position = mlt_frame_get_position( this );
388 get_audio( this, buffer, format, frequency, channels, samples );
389 mlt_frame_set_position( this, position );
390 }
391 else if ( mlt_properties_get_data( properties, "audio", NULL ) )
392 {
393 *buffer = mlt_properties_get_data( properties, "audio", NULL );
394 *frequency = mlt_properties_get_int( properties, "audio_frequency" );
395 *channels = mlt_properties_get_int( properties, "audio_channels" );
396 *samples = mlt_properties_get_int( properties, "audio_samples" );
397 }
398 else
399 {
400 int size = 0;
401 *samples = *samples <= 0 ? 1920 : *samples;
402 *channels = *channels <= 0 ? 2 : *channels;
403 *frequency = *frequency <= 0 ? 48000 : *frequency;
404 size = *samples * *channels * sizeof( int16_t );
405 *buffer = mlt_pool_alloc( size );
406 if ( *buffer != NULL )
407 memset( *buffer, 0, size );
408 mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
409 mlt_properties_set_int( properties, "test_audio", 1 );
410 }
411
412 mlt_properties_set_int( properties, "audio_frequency", *frequency );
413 mlt_properties_set_int( properties, "audio_channels", *channels );
414 mlt_properties_set_int( properties, "audio_samples", *samples );
415
416 if ( mlt_properties_get( properties, "meta.volume" ) )
417 {
418 double value = mlt_properties_get_double( properties, "meta.volume" );
419
420 if ( value == 0.0 )
421 {
422 memset( *buffer, 0, *samples * *channels * 2 );
423 }
424 else if ( value != 1.0 )
425 {
426 int total = *samples * *channels;
427 int16_t *p = *buffer;
428 while ( total -- )
429 {
430 *p = *p * value;
431 p ++;
432 }
433 }
434
435 mlt_properties_set( properties, "meta.volume", NULL );
436 }
437
438 return 0;
439 }
440
441 unsigned char *mlt_frame_get_waveform( mlt_frame this, int w, int h )
442 {
443 int16_t *pcm = NULL;
444 mlt_properties properties = MLT_FRAME_PROPERTIES( this );
445 mlt_audio_format format = mlt_audio_pcm;
446 int frequency = 32000; // lower frequency available?
447 int channels = 2;
448 double fps = mlt_profile_fps( NULL );
449 int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( this ) );
450
451 // Get the pcm data
452 mlt_frame_get_audio( this, &pcm, &format, &frequency, &channels, &samples );
453
454 // Make an 8-bit buffer large enough to hold rendering
455 int size = w * h;
456 unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
457 if ( bitmap != NULL )
458 memset( bitmap, 0, size );
459 mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
460
461 // Render vertical lines
462 int16_t *ubound = pcm + samples * channels;
463 int skip = samples / w - 1;
464 int i, j, k;
465
466 // Iterate sample stream and along x coordinate
467 for ( i = 0; i < w && pcm < ubound; i++ )
468 {
469 // pcm data has channels interleaved
470 for ( j = 0; j < channels; j++ )
471 {
472 // Determine sample's magnitude from 2s complement;
473 int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
474 // The height of a line is the ratio of the magnitude multiplied by
475 // half the vertical resolution
476 int height = ( int )( ( double )( pcm_magnitude ) / 32768 * h / 2 );
477 // Determine the starting y coordinate - left channel above center,
478 // right channel below - currently assumes 2 channels
479 int displacement = ( h / 2 ) - ( 1 - j ) * height;
480 // Position buffer pointer using y coordinate, stride, and x coordinate
481 unsigned char *p = &bitmap[ i + displacement * w ];
482
483 // Draw vertical line
484 for ( k = 0; k < height; k++ )
485 p[ w * k ] = 0xFF;
486
487 pcm++;
488 }
489 pcm += skip * channels;
490 }
491
492 return bitmap;
493 }
494
495 mlt_producer mlt_frame_get_original_producer( mlt_frame this )
496 {
497 if ( this != NULL )
498 return mlt_properties_get_data( MLT_FRAME_PROPERTIES( this ), "_producer", NULL );
499 return NULL;
500 }
501
502 void mlt_frame_close( mlt_frame this )
503 {
504 if ( this != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( this ) ) <= 0 )
505 {
506 mlt_deque_close( this->stack_image );
507 mlt_deque_close( this->stack_audio );
508 while( mlt_deque_peek_back( this->stack_service ) )
509 mlt_service_close( mlt_deque_pop_back( this->stack_service ) );
510 mlt_deque_close( this->stack_service );
511 mlt_properties_close( &this->parent );
512 free( this );
513 }
514 }
515
516 /***** convenience functions *****/
517
518 int mlt_convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total )
519 {
520 int ret = 0;
521 int yy, uu, vv;
522 int r,g,b;
523 total /= 2;
524 while (total--)
525 {
526 yy = yuv[0];
527 uu = yuv[1];
528 vv = yuv[3];
529 YUV2RGB(yy, uu, vv, r, g, b);
530 rgba[0] = r;
531 rgba[1] = g;
532 rgba[2] = b;
533 rgba[3] = 255;
534 yy = yuv[2];
535 YUV2RGB(yy, uu, vv, r, g, b);
536 rgba[4] = r;
537 rgba[5] = g;
538 rgba[6] = b;
539 rgba[7] = 255;
540 yuv += 4;
541 rgba += 8;
542 }
543 return ret;
544 }
545
546 int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
547 {
548 int ret = 0;
549 register int y0, y1, u0, u1, v0, v1;
550 register int r, g, b;
551 register uint8_t *d = yuv;
552 register int i, j;
553
554 if ( alpha )
555 for ( i = 0; i < height; i++ )
556 {
557 register uint8_t *s = rgba + ( stride * i );
558 for ( j = 0; j < ( width / 2 ); j++ )
559 {
560 r = *s++;
561 g = *s++;
562 b = *s++;
563 *alpha++ = *s++;
564 RGB2YUV (r, g, b, y0, u0 , v0);
565 r = *s++;
566 g = *s++;
567 b = *s++;
568 *alpha++ = *s++;
569 RGB2YUV (r, g, b, y1, u1 , v1);
570 *d++ = y0;
571 *d++ = (u0+u1) >> 1;
572 *d++ = y1;
573 *d++ = (v0+v1) >> 1;
574 }
575 if ( width % 2 )
576 {
577 r = *s++;
578 g = *s++;
579 b = *s++;
580 *alpha++ = *s++;
581 RGB2YUV (r, g, b, y0, u0 , v0);
582 *d++ = y0;
583 *d++ = u0;
584 }
585 }
586 else
587 for ( i = 0; i < height; i++ )
588 {
589 register uint8_t *s = rgba + ( stride * i );
590 for ( j = 0; j < ( width / 2 ); j++ )
591 {
592 r = *s++;
593 g = *s++;
594 b = *s++;
595 s++;
596 RGB2YUV (r, g, b, y0, u0 , v0);
597 r = *s++;
598 g = *s++;
599 b = *s++;
600 s++;
601 RGB2YUV (r, g, b, y1, u1 , v1);
602 *d++ = y0;
603 *d++ = (u0+u1) >> 1;
604 *d++ = y1;
605 *d++ = (v0+v1) >> 1;
606 }
607 if ( width % 2 )
608 {
609 r = *s++;
610 g = *s++;
611 b = *s++;
612 s++;
613 RGB2YUV (r, g, b, y0, u0 , v0);
614 *d++ = y0;
615 *d++ = u0;
616 }
617 }
618
619 return ret;
620 }
621
622 int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
623 {
624 int ret = 0;
625 register int y0, y1, u0, u1, v0, v1;
626 register int r, g, b;
627 register uint8_t *d = yuv;
628 register int i, j;
629
630 for ( i = 0; i < height; i++ )
631 {
632 register uint8_t *s = rgb + ( stride * i );
633 for ( j = 0; j < ( width / 2 ); j++ )
634 {
635 r = *s++;
636 g = *s++;
637 b = *s++;
638 RGB2YUV (r, g, b, y0, u0 , v0);
639 r = *s++;
640 g = *s++;
641 b = *s++;
642 RGB2YUV (r, g, b, y1, u1 , v1);
643 *d++ = y0;
644 *d++ = (u0+u1) >> 1;
645 *d++ = y1;
646 *d++ = (v0+v1) >> 1;
647 }
648 if ( width % 2 )
649 {
650 r = *s++;
651 g = *s++;
652 b = *s++;
653 RGB2YUV (r, g, b, y0, u0 , v0);
654 *d++ = y0;
655 *d++ = u0;
656 }
657 }
658 return ret;
659 }
660
661 int mlt_convert_bgr24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
662 {
663 int ret = 0;
664 register int y0, y1, u0, u1, v0, v1;
665 register int r, g, b;
666 register uint8_t *d = yuv;
667 register int i, j;
668
669 if ( alpha )
670 for ( i = 0; i < height; i++ )
671 {
672 register uint8_t *s = rgba + ( stride * i );
673 for ( j = 0; j < ( width / 2 ); j++ )
674 {
675 b = *s++;
676 g = *s++;
677 r = *s++;
678 *alpha++ = *s++;
679 RGB2YUV (r, g, b, y0, u0 , v0);
680 b = *s++;
681 g = *s++;
682 r = *s++;
683 *alpha++ = *s++;
684 RGB2YUV (r, g, b, y1, u1 , v1);
685 *d++ = y0;
686 *d++ = (u0+u1) >> 1;
687 *d++ = y1;
688 *d++ = (v0+v1) >> 1;
689 }
690 if ( width % 2 )
691 {
692 b = *s++;
693 g = *s++;
694 r = *s++;
695 *alpha++ = *s++;
696 RGB2YUV (r, g, b, y0, u0 , v0);
697 *d++ = y0;
698 *d++ = u0;
699 }
700 }
701 else
702 for ( i = 0; i < height; i++ )
703 {
704 register uint8_t *s = rgba + ( stride * i );
705 for ( j = 0; j < ( width / 2 ); j++ )
706 {
707 b = *s++;
708 g = *s++;
709 r = *s++;
710 s++;
711 RGB2YUV (r, g, b, y0, u0 , v0);
712 b = *s++;
713 g = *s++;
714 r = *s++;
715 s++;
716 RGB2YUV (r, g, b, y1, u1 , v1);
717 *d++ = y0;
718 *d++ = (u0+u1) >> 1;
719 *d++ = y1;
720 *d++ = (v0+v1) >> 1;
721 }
722 if ( width % 2 )
723 {
724 b = *s++;
725 g = *s++;
726 r = *s++;
727 s++;
728 RGB2YUV (r, g, b, y0, u0 , v0);
729 *d++ = y0;
730 *d++ = u0;
731 }
732 }
733 return ret;
734 }
735
736 int mlt_convert_bgr24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
737 {
738 int ret = 0;
739 register int y0, y1, u0, u1, v0, v1;
740 register int r, g, b;
741 register uint8_t *d = yuv;
742 register int i, j;
743
744 for ( i = 0; i < height; i++ )
745 {
746 register uint8_t *s = rgb + ( stride * i );
747 for ( j = 0; j < ( width / 2 ); j++ )
748 {
749 b = *s++;
750 g = *s++;
751 r = *s++;
752 RGB2YUV (r, g, b, y0, u0 , v0);
753 b = *s++;
754 g = *s++;
755 r = *s++;
756 RGB2YUV (r, g, b, y1, u1 , v1);
757 *d++ = y0;
758 *d++ = (u0+u1) >> 1;
759 *d++ = y1;
760 *d++ = (v0+v1) >> 1;
761 }
762 if ( width % 2 )
763 {
764 b = *s++;
765 g = *s++;
766 r = *s++;
767 RGB2YUV (r, g, b, y0, u0 , v0);
768 *d++ = y0;
769 *d++ = u0;
770 }
771 }
772 return ret;
773 }
774
775 int mlt_convert_argb_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
776 {
777 int ret = 0;
778 register int y0, y1, u0, u1, v0, v1;
779 register int r, g, b;
780 register uint8_t *d = yuv;
781 register int i, j;
782
783 if ( alpha )
784 for ( i = 0; i < height; i++ )
785 {
786 register uint8_t *s = rgba + ( stride * i );
787 for ( j = 0; j < ( width / 2 ); j++ )
788 {
789 *alpha++ = *s++;
790 r = *s++;
791 g = *s++;
792 b = *s++;
793 RGB2YUV (r, g, b, y0, u0 , v0);
794 *alpha++ = *s++;
795 r = *s++;
796 g = *s++;
797 b = *s++;
798 RGB2YUV (r, g, b, y1, u1 , v1);
799 *d++ = y0;
800 *d++ = (u0+u1) >> 1;
801 *d++ = y1;
802 *d++ = (v0+v1) >> 1;
803 }
804 if ( width % 2 )
805 {
806 *alpha++ = *s++;
807 r = *s++;
808 g = *s++;
809 b = *s++;
810 RGB2YUV (r, g, b, y0, u0 , v0);
811 *d++ = y0;
812 *d++ = u0;
813 }
814 }
815 else
816 for ( i = 0; i < height; i++ )
817 {
818 register uint8_t *s = rgba + ( stride * i );
819 for ( j = 0; j < ( width / 2 ); j++ )
820 {
821 s++;
822 r = *s++;
823 g = *s++;
824 b = *s++;
825 RGB2YUV (r, g, b, y0, u0 , v0);
826 s++;
827 r = *s++;
828 g = *s++;
829 b = *s++;
830 RGB2YUV (r, g, b, y1, u1 , v1);
831 *d++ = y0;
832 *d++ = (u0+u1) >> 1;
833 *d++ = y1;
834 *d++ = (v0+v1) >> 1;
835 }
836 if ( width % 2 )
837 {
838 s++;
839 r = *s++;
840 g = *s++;
841 b = *s++;
842 RGB2YUV (r, g, b, y0, u0 , v0);
843 *d++ = y0;
844 *d++ = u0;
845 }
846 }
847 return ret;
848 }
849
850 int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv )
851 {
852 int ret = 0;
853 register int i, j;
854
855 int half = width >> 1;
856
857 uint8_t *Y = yuv420p;
858 uint8_t *U = Y + width * height;
859 uint8_t *V = U + width * height / 4;
860
861 register uint8_t *d = yuv;
862
863 for ( i = 0; i < height; i++ )
864 {
865 register uint8_t *u = U + ( i / 2 ) * ( half );
866 register uint8_t *v = V + ( i / 2 ) * ( half );
867
868 for ( j = 0; j < half; j++ )
869 {
870 *d ++ = *Y ++;
871 *d ++ = *u ++;
872 *d ++ = *Y ++;
873 *d ++ = *v ++;
874 }
875 }
876 return ret;
877 }
878
879 uint8_t *mlt_resize_alpha( uint8_t *input, int owidth, int oheight, int iwidth, int iheight, uint8_t alpha_value )
880 {
881 uint8_t *output = NULL;
882
883 if ( input != NULL && ( iwidth != owidth || iheight != oheight ) && ( owidth > 6 && oheight > 6 ) )
884 {
885 uint8_t *out_line;
886 int offset_x = ( owidth - iwidth ) / 2;
887 int offset_y = ( oheight - iheight ) / 2;
888 int iused = iwidth;
889
890 output = mlt_pool_alloc( owidth * oheight );
891 memset( output, alpha_value, owidth * oheight );
892
893 offset_x -= offset_x % 2;
894
895 out_line = output + offset_y * owidth;
896 out_line += offset_x;
897
898 // Loop for the entirety of our output height.
899 while ( iheight -- )
900 {
901 // We're in the input range for this row.
902 memcpy( out_line, input, iused );
903
904 // Move to next input line
905 input += iwidth;
906
907 // Move to next output line
908 out_line += owidth;
909 }
910 }
911
912 return output;
913 }
914
915 void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
916 {
917 // Calculate strides
918 int istride = iwidth * 2;
919 int ostride = owidth * 2;
920 int offset_x = ( owidth - iwidth );
921 int offset_y = ( oheight - iheight ) / 2;
922 uint8_t *in_line = input;
923 uint8_t *out_line;
924 int size = owidth * oheight;
925 uint8_t *p = output;
926
927 // Optimisation point
928 if ( output == NULL || input == NULL || ( owidth <= 6 || oheight <= 6 || iwidth <= 6 || oheight <= 6 ) )
929 {
930 return;
931 }
932 else if ( iwidth == owidth && iheight == oheight )
933 {
934 memcpy( output, input, iheight * istride );
935 return;
936 }
937
938 while( size -- )
939 {
940 *p ++ = 16;
941 *p ++ = 128;
942 }
943
944 offset_x -= offset_x % 4;
945
946 out_line = output + offset_y * ostride;
947 out_line += offset_x;
948
949 // Loop for the entirety of our output height.
950 while ( iheight -- )
951 {
952 // We're in the input range for this row.
953 memcpy( out_line, in_line, iwidth * 2 );
954
955 // Move to next input line
956 in_line += istride;
957
958 // Move to next output line
959 out_line += ostride;
960 }
961 }
962
963 /** A resizing function for yuv422 frames - this does not rescale, but simply
964 resizes. It assumes yuv422 images available on the frame so use with care.
965 */
966
967 uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight )
968 {
969 // Get properties
970 mlt_properties properties = MLT_FRAME_PROPERTIES( this );
971
972 // Get the input image, width and height
973 uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
974 uint8_t *alpha = mlt_frame_get_alpha_mask( this );
975
976 int iwidth = mlt_properties_get_int( properties, "width" );
977 int iheight = mlt_properties_get_int( properties, "height" );
978
979 // If width and height are correct, don't do anything
980 if ( iwidth != owidth || iheight != oheight )
981 {
982 uint8_t alpha_value = mlt_properties_get_int( properties, "resize_alpha" );
983
984 // Create the output image
985 uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
986
987 // Call the generic resize
988 mlt_resize_yuv422( output, owidth, oheight, input, iwidth, iheight );
989
990 // Now update the frame
991 mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
992 mlt_properties_set_int( properties, "width", owidth );
993 mlt_properties_set_int( properties, "height", oheight );
994
995 // We should resize the alpha too
996 alpha = mlt_resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value );
997 if ( alpha != NULL )
998 {
999 mlt_properties_set_data( properties, "alpha", alpha, owidth * oheight, ( mlt_destructor )mlt_pool_release, NULL );
1000 this->get_alpha_mask = NULL;
1001 }
1002
1003 // Return the output
1004 return output;
1005 }
1006 // No change, return input
1007 return input;
1008 }
1009
1010 /** A rescaling function for yuv422 frames - low quality, and provided for testing
1011 only. It assumes yuv422 images available on the frame so use with care.
1012 */
1013
1014 uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
1015 {
1016 // Get properties
1017 mlt_properties properties = MLT_FRAME_PROPERTIES( this );
1018
1019 // Get the input image, width and height
1020 uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
1021 int iwidth = mlt_properties_get_int( properties, "width" );
1022 int iheight = mlt_properties_get_int( properties, "height" );
1023
1024 // If width and height are correct, don't do anything
1025 if ( iwidth != owidth || iheight != oheight )
1026 {
1027 // Create the output image
1028 uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
1029
1030 // Calculate strides
1031 int istride = iwidth * 2;
1032 int ostride = owidth * 2;
1033
1034 iwidth = iwidth - ( iwidth % 4 );
1035
1036 // Derived coordinates
1037 int dy, dx;
1038
1039 // Calculate ranges
1040 int out_x_range = owidth / 2;
1041 int out_y_range = oheight / 2;
1042 int in_x_range = iwidth / 2;
1043 int in_y_range = iheight / 2;
1044
1045 // Output pointers
1046 register uint8_t *out_line = output;
1047 register uint8_t *out_ptr;
1048
1049 // Calculate a middle pointer
1050 uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2;
1051 uint8_t *in_line;
1052
1053 // Generate the affine transform scaling values
1054 register int scale_width = ( iwidth << 16 ) / owidth;
1055 register int scale_height = ( iheight << 16 ) / oheight;
1056 register int base = 0;
1057
1058 int outer = out_x_range * scale_width;
1059 int bottom = out_y_range * scale_height;
1060
1061 // Loop for the entirety of our output height.
1062 for ( dy = - bottom; dy < bottom; dy += scale_height )
1063 {
1064 // Start at the beginning of the line
1065 out_ptr = out_line;
1066
1067 // Pointer to the middle of the input line
1068 in_line = in_middle + ( dy >> 16 ) * istride;
1069
1070 // Loop for the entirety of our output row.
1071 for ( dx = - outer; dx < outer; dx += scale_width )
1072 {
1073 base = dx >> 15;
1074 base &= 0xfffffffe;
1075 *out_ptr ++ = *( in_line + base );
1076 base &= 0xfffffffc;
1077 *out_ptr ++ = *( in_line + base + 1 );
1078 dx += scale_width;
1079 base = dx >> 15;
1080 base &= 0xfffffffe;
1081 *out_ptr ++ = *( in_line + base );
1082 base &= 0xfffffffc;
1083 *out_ptr ++ = *( in_line + base + 3 );
1084 }
1085
1086 // Move to next output line
1087 out_line += ostride;
1088 }
1089
1090 // Now update the frame
1091 mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
1092 mlt_properties_set_int( properties, "width", owidth );
1093 mlt_properties_set_int( properties, "height", oheight );
1094
1095 // Return the output
1096 return output;
1097 }
1098
1099 // No change, return input
1100 return input;
1101 }
1102
1103 int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
1104 {
1105 int ret = 0;
1106 int16_t *src, *dest;
1107 int frequency_src = *frequency, frequency_dest = *frequency;
1108 int channels_src = *channels, channels_dest = *channels;
1109 int samples_src = *samples, samples_dest = *samples;
1110 int i, j;
1111 double d = 0, s = 0;
1112
1113 mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
1114 mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
1115
1116 int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
1117 mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
1118 if ( silent )
1119 memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
1120
1121 silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
1122 mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
1123 if ( silent )
1124 memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
1125
1126 if ( channels_src > 6 )
1127 channels_src = 0;
1128 if ( channels_dest > 6 )
1129 channels_dest = 0;
1130 if ( samples_src > 4000 )
1131 samples_src = 0;
1132 if ( samples_dest > 4000 )
1133 samples_dest = 0;
1134
1135 // determine number of samples to process
1136 *samples = samples_src < samples_dest ? samples_src : samples_dest;
1137 *channels = channels_src < channels_dest ? channels_src : channels_dest;
1138 *buffer = dest;
1139 *frequency = frequency_dest;
1140
1141 // Compute a smooth ramp over start to end
1142 float weight = weight_start;
1143 float weight_step = ( weight_end - weight_start ) / *samples;
1144
1145 if ( src == dest )
1146 {
1147 *samples = samples_src;
1148 *channels = channels_src;
1149 *buffer = src;
1150 *frequency = frequency_src;
1151 return ret;
1152 }
1153
1154 // Mixdown
1155 for ( i = 0; i < *samples; i++ )
1156 {
1157 for ( j = 0; j < *channels; j++ )
1158 {
1159 if ( j < channels_dest )
1160 d = (double) dest[ i * channels_dest + j ];
1161 if ( j < channels_src )
1162 s = (double) src[ i * channels_src + j ];
1163 dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
1164 }
1165 weight += weight_step;
1166 }
1167
1168 return ret;
1169 }
1170
1171 // Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
1172 // to allow mixing without volume hacking
1173 int mlt_frame_combine_audio( mlt_frame this, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
1174 {
1175 int ret = 0;
1176 int16_t *src, *dest;
1177 int frequency_src = *frequency, frequency_dest = *frequency;
1178 int channels_src = *channels, channels_dest = *channels;
1179 int samples_src = *samples, samples_dest = *samples;
1180 int i, j;
1181 double vp[ 6 ];
1182 double b_weight = 1.0;
1183
1184 if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
1185 b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
1186
1187 mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
1188 mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
1189
1190 int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
1191 mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
1192 if ( silent )
1193 memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
1194
1195 silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
1196 mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
1197 if ( silent )
1198 memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
1199
1200 if ( src == dest )
1201 {
1202 *samples = samples_src;
1203 *channels = channels_src;
1204 *buffer = src;
1205 *frequency = frequency_src;
1206 return ret;
1207 }
1208
1209 // determine number of samples to process
1210 *samples = samples_src < samples_dest ? samples_src : samples_dest;
1211 *channels = channels_src < channels_dest ? channels_src : channels_dest;
1212 *buffer = dest;
1213 *frequency = frequency_dest;
1214
1215 for ( j = 0; j < *channels; j++ )
1216 vp[ j ] = ( double )dest[ j ];
1217
1218 double Fc = 0.5;
1219 double B = exp(-2.0 * M_PI * Fc);
1220 double A = 1.0 - B;
1221 double v;
1222
1223 for ( i = 0; i < *samples; i++ )
1224 {
1225 for ( j = 0; j < *channels; j++ )
1226 {
1227 v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
1228 v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
1229 vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
1230 }
1231 }
1232
1233 return ret;
1234 }
1235
1236 /* Will this break when mlt_position is converted to double? -Zach */
1237 int mlt_sample_calculator( float fps, int frequency, int64_t position )
1238 {
1239 int samples = 0;
1240
1241 if ( ( int )( fps * 100 ) == 2997 )
1242 {
1243 samples = frequency / 30;
1244
1245 switch ( frequency )
1246 {
1247 case 48000:
1248 if ( position % 5 != 0 )
1249 samples += 2;
1250 break;
1251 case 44100:
1252 if ( position % 300 == 0 )
1253 samples = 1471;
1254 else if ( position % 30 == 0 )
1255 samples = 1470;
1256 else if ( position % 2 == 0 )
1257 samples = 1472;
1258 else
1259 samples = 1471;
1260 break;
1261 case 32000:
1262 if ( position % 30 == 0 )
1263 samples = 1068;
1264 else if ( position % 29 == 0 )
1265 samples = 1067;
1266 else if ( position % 4 == 2 )
1267 samples = 1067;
1268 else
1269 samples = 1068;
1270 break;
1271 default:
1272 samples = 0;
1273 }
1274 }
1275 else if ( fps != 0 )
1276 {
1277 samples = frequency / fps;
1278 }
1279
1280 return samples;
1281 }
1282
1283 int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t frame )
1284 {
1285 int64_t samples = 0;
1286
1287 // TODO: Correct rules for NTSC and drop the * 100 hack
1288 if ( ( int )( fps * 100 ) == 2997 )
1289 {
1290 samples = ( ( double )( frame * frequency ) / 30 );
1291 switch( frequency )
1292 {
1293 case 48000:
1294 samples += 2 * ( frame / 5 );
1295 break;
1296 case 44100:
1297 samples += frame + ( frame / 2 ) - ( frame / 30 ) + ( frame / 300 );
1298 break;
1299 case 32000:
1300 samples += ( 2 * frame ) - ( frame / 4 ) - ( frame / 29 );
1301 break;
1302 }
1303 }
1304 else if ( fps != 0 )
1305 {
1306 samples = ( ( frame * frequency ) / ( int )fps );
1307 }
1308
1309 return samples;
1310 }