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