From 8bf137cd71aafb9c8f6a42c78ddb6bd0a8fe99db Mon Sep 17 00:00:00 2001 From: ddennedy Date: Thu, 8 Jan 2004 04:30:28 +0000 Subject: [PATCH] move audio sample calculator to mlt_frame and use from ffmpeg and mcmpeg, add mlt_frame_audio_mix, add audio_crossfade to transition_luma, add to docs git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@40 d19143bc-622f-0410-bfdd-b5b2a6649095 --- docs/services.txt | 192 ++++++++++++++++++++++++++++-- mlt/docs/services.txt | 192 ++++++++++++++++++++++++++++-- mlt/src/framework/mlt_frame.c | 75 ++++++++++++ mlt/src/framework/mlt_frame.h | 2 + mlt/src/modules/core/transition_luma.c | 40 ++++++- mlt/src/modules/dv/producer_libdv.c | 14 ++- mlt/src/modules/ffmpeg/producer_ffmpeg.c | 50 +-------- mlt/src/modules/sdl/consumer_sdl.c | 2 +- mlt/src/tests/dan.c | 8 +- src/framework/mlt_frame.c | 75 ++++++++++++ src/framework/mlt_frame.h | 2 + src/modules/core/transition_luma.c | 40 ++++++- src/modules/dv/producer_libdv.c | 14 ++- src/modules/ffmpeg/producer_ffmpeg.c | 50 +-------- src/modules/sdl/consumer_sdl.c | 2 +- src/tests/dan.c | 8 +- 16 files changed, 628 insertions(+), 138 deletions(-) diff --git a/docs/services.txt b/docs/services.txt index 8118894..cc79a24 100644 --- a/docs/services.txt +++ b/docs/services.txt @@ -3,11 +3,11 @@ Producers ffmpeg - Description: + Description Test case pipe based producer for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file v4l - produce a/v from video4linux and dsp device @@ -46,11 +46,11 @@ Producers libdv - Description: + Description libdv based decoder for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file @@ -63,7 +63,8 @@ Producers string resource - file location double fps - output frames per second - double aspect_ratio - aspect ratio of video + double aspect_ratio - aspect ratio of video] + timecode length - duration of resource (in seconds) Dependencies @@ -75,11 +76,11 @@ Producers mcdv - Description: + Description Mainconcept based dv decoder for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file @@ -93,6 +94,7 @@ Producers string resource - file location double fps - output frames per second double aspect_ratio - aspect ratio of video + timecode length - duration of resource (in seconds) Dependencies @@ -100,15 +102,15 @@ Producers Known Bugs - Can be problematic with source NTSC DV files? + Can be problematic with source NTSC DV files? really? mcmpeg - Description: + Description Mainconcept based mpeg decoder for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file @@ -132,28 +134,196 @@ Producers None. pango + + Description + + A title generator that uses the Pango international text layout + and Freetype2 font renderer. + + Constructor Argument + + 'markup' - a string containing Pango markup see: + http://developer.gnome.org/doc/API/2.0/pango/PangoMarkupFormat.html + - requires xml-like encoding special chars: <, > ( and '&' and '"' ?) + + Initialisation Properties + + timecode in - in point + timecode out - out point + int video_standard - enum mlt_video_standard from mlt_frame.h + PAL = 0, NTSC = 1 + this determines proper pixel aspect ratio + + int fgcolor - an rgba color specification of the text (i.e. 0xrrggbbaa) + int bgcolor - an rgba color of the background rectangle + int align - paragraph alignment: 0 = left, 1 = center, 2 = right + int pad - the number of pixels to pad the background rectangle beyond edges of text + default 0 + string markup - see constructor argument + string text - non-markup text (can contain markup chars un-encoded) + string font - the default typeface to use when not using markup + default "Sans 48" + int x - the horizontal position of the title on the frame + default 0 + int y - the vertical position of the title on the frame + default 0 + double mix - the overall opacity control of the generated title + default 1.0 + + Read Only Properties + + string resource - "pango" + + Dependencies + + libpango-1.0, libpangoft2-1.0, libfreetype, libgdk_pixbuf-2.0, libglib-2.0, + libgobject-2.0, libgmodule-2.0, libfontconfig + + Known Bugs + + no frame-alignment functionality + pixbuf + + Description + + A graphics overlay generator using gdk-pixbuf + + Constructor Argument + + 'file' - The name of a graphics file loadable by + a gdk-pixbuf loader. see /usr/lib/gdk-pixbuf/loaders + definitely png, jpeg, tiff, pnm, and xpm + - If "%" in filename, the filename is used with sprintf + generate a filename from a counter for multi-file/flipbook animation. + The file sequence ends when numeric discontinuity >100. + - If filename contains "/.all.", suffix with an extension to load + all pictures with matching extension from a directory + + Initialisation Properties + + timecode in - in point + timecode out - out point + int video_standard - enum mlt_video_standard from mlt_frame.h + PAL = 0, NTSC = 1 + this determines proper pixel aspect ratio + double ttl - how long (seconds) to repeat each picture in file sequences + + Read Only Properties + + string resource - file location + + Dependencies + + libgdk_pixbuf-2.0, libglib-2.0, libgobject-2.0, libgmodule-2.0 + + Known Bugs + + none + ppm + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs Filters ------- deinterlace + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + ffmpeg_dub + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + gamma + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + greyscale + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + resize + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs Transitions ----------- composite + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + + luma + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs Consumers --------- bluefish + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + ffmpeg - sdl + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + sdl + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs diff --git a/mlt/docs/services.txt b/mlt/docs/services.txt index 8118894..cc79a24 100644 --- a/mlt/docs/services.txt +++ b/mlt/docs/services.txt @@ -3,11 +3,11 @@ Producers ffmpeg - Description: + Description Test case pipe based producer for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file v4l - produce a/v from video4linux and dsp device @@ -46,11 +46,11 @@ Producers libdv - Description: + Description libdv based decoder for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file @@ -63,7 +63,8 @@ Producers string resource - file location double fps - output frames per second - double aspect_ratio - aspect ratio of video + double aspect_ratio - aspect ratio of video] + timecode length - duration of resource (in seconds) Dependencies @@ -75,11 +76,11 @@ Producers mcdv - Description: + Description Mainconcept based dv decoder for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file @@ -93,6 +94,7 @@ Producers string resource - file location double fps - output frames per second double aspect_ratio - aspect ratio of video + timecode length - duration of resource (in seconds) Dependencies @@ -100,15 +102,15 @@ Producers Known Bugs - Can be problematic with source NTSC DV files? + Can be problematic with source NTSC DV files? really? mcmpeg - Description: + Description Mainconcept based mpeg decoder for video and audio. - Constructor argument: + Constructor Argument 'file' - produce a/v from file @@ -132,28 +134,196 @@ Producers None. pango + + Description + + A title generator that uses the Pango international text layout + and Freetype2 font renderer. + + Constructor Argument + + 'markup' - a string containing Pango markup see: + http://developer.gnome.org/doc/API/2.0/pango/PangoMarkupFormat.html + - requires xml-like encoding special chars: <, > ( and '&' and '"' ?) + + Initialisation Properties + + timecode in - in point + timecode out - out point + int video_standard - enum mlt_video_standard from mlt_frame.h + PAL = 0, NTSC = 1 + this determines proper pixel aspect ratio + + int fgcolor - an rgba color specification of the text (i.e. 0xrrggbbaa) + int bgcolor - an rgba color of the background rectangle + int align - paragraph alignment: 0 = left, 1 = center, 2 = right + int pad - the number of pixels to pad the background rectangle beyond edges of text + default 0 + string markup - see constructor argument + string text - non-markup text (can contain markup chars un-encoded) + string font - the default typeface to use when not using markup + default "Sans 48" + int x - the horizontal position of the title on the frame + default 0 + int y - the vertical position of the title on the frame + default 0 + double mix - the overall opacity control of the generated title + default 1.0 + + Read Only Properties + + string resource - "pango" + + Dependencies + + libpango-1.0, libpangoft2-1.0, libfreetype, libgdk_pixbuf-2.0, libglib-2.0, + libgobject-2.0, libgmodule-2.0, libfontconfig + + Known Bugs + + no frame-alignment functionality + pixbuf + + Description + + A graphics overlay generator using gdk-pixbuf + + Constructor Argument + + 'file' - The name of a graphics file loadable by + a gdk-pixbuf loader. see /usr/lib/gdk-pixbuf/loaders + definitely png, jpeg, tiff, pnm, and xpm + - If "%" in filename, the filename is used with sprintf + generate a filename from a counter for multi-file/flipbook animation. + The file sequence ends when numeric discontinuity >100. + - If filename contains "/.all.", suffix with an extension to load + all pictures with matching extension from a directory + + Initialisation Properties + + timecode in - in point + timecode out - out point + int video_standard - enum mlt_video_standard from mlt_frame.h + PAL = 0, NTSC = 1 + this determines proper pixel aspect ratio + double ttl - how long (seconds) to repeat each picture in file sequences + + Read Only Properties + + string resource - file location + + Dependencies + + libgdk_pixbuf-2.0, libglib-2.0, libgobject-2.0, libgmodule-2.0 + + Known Bugs + + none + ppm + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs Filters ------- deinterlace + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + ffmpeg_dub + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + gamma + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + greyscale + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + resize + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs Transitions ----------- composite + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + + luma + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs Consumers --------- bluefish + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + ffmpeg - sdl + + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs + sdl + Description + Constructor Argument + Initialisation Properties + Read Only Properties + Dependencies + Known Bugs diff --git a/mlt/src/framework/mlt_frame.c b/mlt/src/framework/mlt_frame.c index dd17983..5a5701a 100644 --- a/mlt/src/framework/mlt_frame.c +++ b/mlt/src/framework/mlt_frame.c @@ -688,3 +688,78 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight ) return input; } +int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + int ret = 0; + int16_t *p_src, *p_dest; + int frequency_src, frequency_dest; + int channels_src, channels_dest; + int samples_src, samples_dest; + int i, j; + + mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest ); + mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src ); + + *samples = samples_src < samples_dest ? samples_src : samples_dest; + *channels = channels_src < channels_dest ? channels_src : channels_dest; + *buffer = p_dest; + + for ( i = 0; i < *samples; i++ ) + { + for ( j = 0; j < *channels; j++ ) + { + double dest = (double) p_dest[ i * channels_dest + j ]; + double src = (double) p_src[ i * channels_src + j ]; + p_dest[ i * channels_dest + j ] = src * weight + dest * ( 1.0 - weight ); + } + } + + return ret; +} + +int mlt_sample_calculator( float fps, int frequency, int64_t position ) +{ + int samples = 0; + + if ( fps > 29 && fps <= 30 ) + { + samples = frequency / 30; + + switch ( frequency ) + { + case 48000: + if ( position % 5 != 0 ) + samples += 2; + break; + case 44100: + if ( position % 300 == 0 ) + samples = 1471; + else if ( position % 30 == 0 ) + samples = 1470; + else if ( position % 2 == 0 ) + samples = 1472; + else + samples = 1471; + break; + case 32000: + if ( position % 30 == 0 ) + samples = 1068; + else if ( position % 29 == 0 ) + samples = 1067; + else if ( position % 4 == 2 ) + samples = 1067; + else + samples = 1068; + break; + default: + samples = 0; + } + } + else if ( fps != 0 ) + { + samples = frequency / fps; + } + + return samples; +} + diff --git a/mlt/src/framework/mlt_frame.h b/mlt/src/framework/mlt_frame.h index 94508ec..175df0a 100644 --- a/mlt/src/framework/mlt_frame.h +++ b/mlt/src/framework/mlt_frame.h @@ -91,6 +91,8 @@ extern int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y extern uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight ); extern uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight ); extern void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight ); +extern int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ); +extern int mlt_sample_calculator( float fps, int frequency, int64_t position ); #endif diff --git a/mlt/src/modules/core/transition_luma.c b/mlt/src/modules/core/transition_luma.c index 7ab770f..fa6d7c3 100644 --- a/mlt/src/modules/core/transition_luma.c +++ b/mlt/src/modules/core/transition_luma.c @@ -184,6 +184,31 @@ static int transition_get_image( mlt_frame this, uint8_t **image, mlt_image_form return 0; } +static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + // Get the properties of the a frame + mlt_properties a_props = mlt_frame_properties( frame ); + + // Get the b frame from the stack + mlt_frame b_frame = mlt_frame_pop_frame( frame ); + + // Get the properties of the b frame + mlt_properties b_props = mlt_frame_properties( b_frame ); + + // Restore the original get_audio + frame->get_audio = mlt_properties_get_data( a_props, "get_audio", NULL ); + + double mix = 0; + if ( mlt_properties_get( b_props, "mix" ) != NULL ) + mix = mlt_properties_get_double( b_props, "mix" ); + mlt_frame_mix_audio( frame, b_frame, mix, buffer, format, frequency, channels, samples ); + + // Push the b_frame back on for get_image + mlt_frame_push_frame( frame, b_frame ); + + return 0; +} + /** Load the luma map from PGM stream. */ @@ -293,17 +318,18 @@ static mlt_frame transition_process( mlt_transition transition, mlt_frame a_fram int width = mlt_properties_get_int( b_props, "width" ); int height = mlt_properties_get_int( b_props, "height" ); char command[ 512 ]; - char *ext = strrchr( luma_file, '.' ); FILE *pipe; command[ 511 ] = '\0'; this->filename = luma_file; snprintf( command, 511, "anytopnm %s | pnmscale -width %d -height %d", luma_file, width, height ); - pipe = popen( command, "r" ); + //pipe = popen( command, "r" ); + pipe = fopen( luma_file, "r" ); if ( pipe != NULL ) { luma_read_pgm( pipe, &this->bitmap, &this->width, &this->height ); - pclose( pipe ); + //pclose( pipe ); + fclose( pipe ); } } @@ -324,6 +350,14 @@ static mlt_frame transition_process( mlt_transition transition, mlt_frame a_fram mlt_frame_push_get_image( a_frame, transition_get_image ); mlt_frame_push_frame( a_frame, b_frame ); + +/************************ AUDIO ***************************/ + // Backup the original get_audio (it's still needed) + mlt_properties_set_data( mlt_frame_properties( a_frame ), "get_audio", a_frame->get_audio, 0, NULL, NULL ); + + // Override the get_audio method + a_frame->get_audio = transition_get_audio; + return a_frame; } diff --git a/mlt/src/modules/dv/producer_libdv.c b/mlt/src/modules/dv/producer_libdv.c index c2921e3..f3d63a6 100644 --- a/mlt/src/modules/dv/producer_libdv.c +++ b/mlt/src/modules/dv/producer_libdv.c @@ -129,13 +129,17 @@ static int producer_collect_info( producer_libdv this ) this->frames_in_file = this->file_size / this->frame_size; // Calculate default in/out points - double fps = this->is_pal ? 25 : 30000 / 1001; + double fps = this->is_pal ? 25 : 30000.0 / 1001.0; mlt_timecode length = ( mlt_timecode )( this->frames_in_file ) / fps; mlt_properties_set_double( properties, "fps", fps ); mlt_properties_set_timecode( properties, "length", length ); mlt_properties_set_timecode( properties, "in", 0.0 ); mlt_properties_set_timecode( properties, "out", length ); + // Parse the header for meta info + dv_parse_header( this->dv_decoder, data ); + mlt_properties_set_double( properties, "aspect_ratio", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 ); + // Set the speed to normal mlt_properties_set_double( properties, "speed", 1 ); } @@ -160,6 +164,9 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma // Get the dv data uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL ); + // Parse the header for meta info + dv_parse_header( this->dv_decoder, data ); + // Assign width and height from properties *width = mlt_properties_get_int( properties, "width" ); *height = mlt_properties_get_int( properties, "height" ); @@ -216,6 +223,9 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma // Get the dv data uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL ); + // Parse the header for meta info + dv_parse_header( this->dv_decoder, data ); + // Obtain required values *frequency = decoder->audio->frequency; *samples = decoder->audio->samples_this_frame; @@ -283,7 +293,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Parse the header for meta info dv_parse_header( this->dv_decoder, data ); mlt_properties_set_int( properties, "progressive", dv_is_progressive( this->dv_decoder ) ); - mlt_properties_set_double( properties, "display_aspect", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 ); + mlt_properties_set_double( properties, "aspect_ratio", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 ); // Hmm - register audio callback ( *frame )->get_audio = producer_get_audio; diff --git a/mlt/src/modules/ffmpeg/producer_ffmpeg.c b/mlt/src/modules/ffmpeg/producer_ffmpeg.c index 2af9de3..662b1e4 100644 --- a/mlt/src/modules/ffmpeg/producer_ffmpeg.c +++ b/mlt/src/modules/ffmpeg/producer_ffmpeg.c @@ -343,52 +343,6 @@ static void producer_ffmpeg_position( producer_ffmpeg this, uint64_t requested, this->open = 1; } -static int sample_calculator( float fps, int frequency, int64_t position ) -{ - int samples = 0; - - if ( fps > 29 && fps <= 30 ) - { - samples = frequency / 30; - - switch ( frequency ) - { - case 48000: - if ( position % 5 != 0 ) - samples += 2; - break; - case 44100: - if ( position % 300 == 0 ) - samples = 1471; - else if ( position % 30 == 0 ) - samples = 1470; - else if ( position % 2 == 0 ) - samples = 1472; - else - samples = 1471; - break; - case 32000: - if ( position % 30 == 0 ) - samples = 1068; - else if ( position % 29 == 0 ) - samples = 1067; - else if ( position % 4 == 2 ) - samples = 1067; - else - samples = 1068; - break; - default: - samples = 0; - } - } - else if ( fps != 0 ) - { - samples = frequency / fps; - } - - return samples; -} - static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { // Get the frames properties @@ -415,7 +369,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma { do { - *samples = sample_calculator( fps, *frequency, target - skip ); + *samples = mlt_sample_calculator( fps, *frequency, target - skip ); if ( fread( *buffer, *samples * *channels * 2, 1, producer->audio ) != 1 ) { rwpipe_close( producer->audio_pipe ); @@ -427,7 +381,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma } else { - *samples = sample_calculator( fps, *frequency, target ); + *samples = mlt_sample_calculator( fps, *frequency, target ); memset( *buffer, 0, size ); } diff --git a/mlt/src/modules/sdl/consumer_sdl.c b/mlt/src/modules/sdl/consumer_sdl.c index 85852d5..2725d1d 100644 --- a/mlt/src/modules/sdl/consumer_sdl.c +++ b/mlt/src/modules/sdl/consumer_sdl.c @@ -199,7 +199,7 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud // Get the properties of this consumer mlt_properties properties = this->properties; mlt_audio_format afmt = mlt_audio_pcm; - int channels; + int channels = 0; int samples; int frequency; int16_t *pcm; diff --git a/mlt/src/tests/dan.c b/mlt/src/tests/dan.c index 99469a8..a896b14 100644 --- a/mlt/src/tests/dan.c +++ b/mlt/src/tests/dan.c @@ -23,14 +23,14 @@ int main( int argc, char **argv ) // Create the producer(s) mlt_producer dv1 = mlt_factory_producer( "mcdv", file1 ); - mlt_producer_set_in_and_out( dv1, 0.0, 2.0 ); + mlt_producer_set_in_and_out( dv1, 300.0, 303.0 ); mlt_producer dv2 = mlt_factory_producer( "mcmpeg", file2 ); //mlt_producer_set_in_and_out( dv2, 10.0, 30.0 ); #if 0 // Connect the consumer to the producer - mlt_consumer_connect( consumer, mlt_producer_service( dv1 ) ); + mlt_consumer_connect( consumer, mlt_producer_service( dv2 ) ); // Do stuff until we're told otherwise... fprintf( stderr, "Press return to continue\n" ); @@ -74,8 +74,8 @@ int main( int argc, char **argv ) // Define a transition mlt_transition transition = mlt_factory_transition( "luma", NULL ); mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 ); - mlt_transition_set_in_and_out( transition, 1.0, 2.0 ); - mlt_properties_set( mlt_transition_properties( transition ), "filename", "clock.pgm" ); + mlt_transition_set_in_and_out( transition, 1.0, 3.0 ); + //mlt_properties_set( mlt_transition_properties( transition ), "filename", "clock.pgm" ); mlt_properties_set_double( mlt_transition_properties( transition ), "softness", 0.1 ); // Buy a tractor and connect it to the filter diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index dd17983..5a5701a 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -688,3 +688,78 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight ) return input; } +int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + int ret = 0; + int16_t *p_src, *p_dest; + int frequency_src, frequency_dest; + int channels_src, channels_dest; + int samples_src, samples_dest; + int i, j; + + mlt_frame_get_audio( this, &p_dest, format, &frequency_dest, &channels_dest, &samples_dest ); + mlt_frame_get_audio( that, &p_src, format, &frequency_src, &channels_src, &samples_src ); + + *samples = samples_src < samples_dest ? samples_src : samples_dest; + *channels = channels_src < channels_dest ? channels_src : channels_dest; + *buffer = p_dest; + + for ( i = 0; i < *samples; i++ ) + { + for ( j = 0; j < *channels; j++ ) + { + double dest = (double) p_dest[ i * channels_dest + j ]; + double src = (double) p_src[ i * channels_src + j ]; + p_dest[ i * channels_dest + j ] = src * weight + dest * ( 1.0 - weight ); + } + } + + return ret; +} + +int mlt_sample_calculator( float fps, int frequency, int64_t position ) +{ + int samples = 0; + + if ( fps > 29 && fps <= 30 ) + { + samples = frequency / 30; + + switch ( frequency ) + { + case 48000: + if ( position % 5 != 0 ) + samples += 2; + break; + case 44100: + if ( position % 300 == 0 ) + samples = 1471; + else if ( position % 30 == 0 ) + samples = 1470; + else if ( position % 2 == 0 ) + samples = 1472; + else + samples = 1471; + break; + case 32000: + if ( position % 30 == 0 ) + samples = 1068; + else if ( position % 29 == 0 ) + samples = 1067; + else if ( position % 4 == 2 ) + samples = 1067; + else + samples = 1068; + break; + default: + samples = 0; + } + } + else if ( fps != 0 ) + { + samples = frequency / fps; + } + + return samples; +} + diff --git a/src/framework/mlt_frame.h b/src/framework/mlt_frame.h index 94508ec..175df0a 100644 --- a/src/framework/mlt_frame.h +++ b/src/framework/mlt_frame.h @@ -91,6 +91,8 @@ extern int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y extern uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight ); extern uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight ); extern void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight ); +extern int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ); +extern int mlt_sample_calculator( float fps, int frequency, int64_t position ); #endif diff --git a/src/modules/core/transition_luma.c b/src/modules/core/transition_luma.c index 7ab770f..fa6d7c3 100644 --- a/src/modules/core/transition_luma.c +++ b/src/modules/core/transition_luma.c @@ -184,6 +184,31 @@ static int transition_get_image( mlt_frame this, uint8_t **image, mlt_image_form return 0; } +static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + // Get the properties of the a frame + mlt_properties a_props = mlt_frame_properties( frame ); + + // Get the b frame from the stack + mlt_frame b_frame = mlt_frame_pop_frame( frame ); + + // Get the properties of the b frame + mlt_properties b_props = mlt_frame_properties( b_frame ); + + // Restore the original get_audio + frame->get_audio = mlt_properties_get_data( a_props, "get_audio", NULL ); + + double mix = 0; + if ( mlt_properties_get( b_props, "mix" ) != NULL ) + mix = mlt_properties_get_double( b_props, "mix" ); + mlt_frame_mix_audio( frame, b_frame, mix, buffer, format, frequency, channels, samples ); + + // Push the b_frame back on for get_image + mlt_frame_push_frame( frame, b_frame ); + + return 0; +} + /** Load the luma map from PGM stream. */ @@ -293,17 +318,18 @@ static mlt_frame transition_process( mlt_transition transition, mlt_frame a_fram int width = mlt_properties_get_int( b_props, "width" ); int height = mlt_properties_get_int( b_props, "height" ); char command[ 512 ]; - char *ext = strrchr( luma_file, '.' ); FILE *pipe; command[ 511 ] = '\0'; this->filename = luma_file; snprintf( command, 511, "anytopnm %s | pnmscale -width %d -height %d", luma_file, width, height ); - pipe = popen( command, "r" ); + //pipe = popen( command, "r" ); + pipe = fopen( luma_file, "r" ); if ( pipe != NULL ) { luma_read_pgm( pipe, &this->bitmap, &this->width, &this->height ); - pclose( pipe ); + //pclose( pipe ); + fclose( pipe ); } } @@ -324,6 +350,14 @@ static mlt_frame transition_process( mlt_transition transition, mlt_frame a_fram mlt_frame_push_get_image( a_frame, transition_get_image ); mlt_frame_push_frame( a_frame, b_frame ); + +/************************ AUDIO ***************************/ + // Backup the original get_audio (it's still needed) + mlt_properties_set_data( mlt_frame_properties( a_frame ), "get_audio", a_frame->get_audio, 0, NULL, NULL ); + + // Override the get_audio method + a_frame->get_audio = transition_get_audio; + return a_frame; } diff --git a/src/modules/dv/producer_libdv.c b/src/modules/dv/producer_libdv.c index c2921e3..f3d63a6 100644 --- a/src/modules/dv/producer_libdv.c +++ b/src/modules/dv/producer_libdv.c @@ -129,13 +129,17 @@ static int producer_collect_info( producer_libdv this ) this->frames_in_file = this->file_size / this->frame_size; // Calculate default in/out points - double fps = this->is_pal ? 25 : 30000 / 1001; + double fps = this->is_pal ? 25 : 30000.0 / 1001.0; mlt_timecode length = ( mlt_timecode )( this->frames_in_file ) / fps; mlt_properties_set_double( properties, "fps", fps ); mlt_properties_set_timecode( properties, "length", length ); mlt_properties_set_timecode( properties, "in", 0.0 ); mlt_properties_set_timecode( properties, "out", length ); + // Parse the header for meta info + dv_parse_header( this->dv_decoder, data ); + mlt_properties_set_double( properties, "aspect_ratio", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 ); + // Set the speed to normal mlt_properties_set_double( properties, "speed", 1 ); } @@ -160,6 +164,9 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma // Get the dv data uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL ); + // Parse the header for meta info + dv_parse_header( this->dv_decoder, data ); + // Assign width and height from properties *width = mlt_properties_get_int( properties, "width" ); *height = mlt_properties_get_int( properties, "height" ); @@ -216,6 +223,9 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma // Get the dv data uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL ); + // Parse the header for meta info + dv_parse_header( this->dv_decoder, data ); + // Obtain required values *frequency = decoder->audio->frequency; *samples = decoder->audio->samples_this_frame; @@ -283,7 +293,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i // Parse the header for meta info dv_parse_header( this->dv_decoder, data ); mlt_properties_set_int( properties, "progressive", dv_is_progressive( this->dv_decoder ) ); - mlt_properties_set_double( properties, "display_aspect", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 ); + mlt_properties_set_double( properties, "aspect_ratio", dv_format_wide( this->dv_decoder ) ? 16.0/9.0 : 4.0/3.0 ); // Hmm - register audio callback ( *frame )->get_audio = producer_get_audio; diff --git a/src/modules/ffmpeg/producer_ffmpeg.c b/src/modules/ffmpeg/producer_ffmpeg.c index 2af9de3..662b1e4 100644 --- a/src/modules/ffmpeg/producer_ffmpeg.c +++ b/src/modules/ffmpeg/producer_ffmpeg.c @@ -343,52 +343,6 @@ static void producer_ffmpeg_position( producer_ffmpeg this, uint64_t requested, this->open = 1; } -static int sample_calculator( float fps, int frequency, int64_t position ) -{ - int samples = 0; - - if ( fps > 29 && fps <= 30 ) - { - samples = frequency / 30; - - switch ( frequency ) - { - case 48000: - if ( position % 5 != 0 ) - samples += 2; - break; - case 44100: - if ( position % 300 == 0 ) - samples = 1471; - else if ( position % 30 == 0 ) - samples = 1470; - else if ( position % 2 == 0 ) - samples = 1472; - else - samples = 1471; - break; - case 32000: - if ( position % 30 == 0 ) - samples = 1068; - else if ( position % 29 == 0 ) - samples = 1067; - else if ( position % 4 == 2 ) - samples = 1067; - else - samples = 1068; - break; - default: - samples = 0; - } - } - else if ( fps != 0 ) - { - samples = frequency / fps; - } - - return samples; -} - static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { // Get the frames properties @@ -415,7 +369,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma { do { - *samples = sample_calculator( fps, *frequency, target - skip ); + *samples = mlt_sample_calculator( fps, *frequency, target - skip ); if ( fread( *buffer, *samples * *channels * 2, 1, producer->audio ) != 1 ) { rwpipe_close( producer->audio_pipe ); @@ -427,7 +381,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma } else { - *samples = sample_calculator( fps, *frequency, target ); + *samples = mlt_sample_calculator( fps, *frequency, target ); memset( *buffer, 0, size ); } diff --git a/src/modules/sdl/consumer_sdl.c b/src/modules/sdl/consumer_sdl.c index 85852d5..2725d1d 100644 --- a/src/modules/sdl/consumer_sdl.c +++ b/src/modules/sdl/consumer_sdl.c @@ -199,7 +199,7 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud // Get the properties of this consumer mlt_properties properties = this->properties; mlt_audio_format afmt = mlt_audio_pcm; - int channels; + int channels = 0; int samples; int frequency; int16_t *pcm; diff --git a/src/tests/dan.c b/src/tests/dan.c index 99469a8..a896b14 100644 --- a/src/tests/dan.c +++ b/src/tests/dan.c @@ -23,14 +23,14 @@ int main( int argc, char **argv ) // Create the producer(s) mlt_producer dv1 = mlt_factory_producer( "mcdv", file1 ); - mlt_producer_set_in_and_out( dv1, 0.0, 2.0 ); + mlt_producer_set_in_and_out( dv1, 300.0, 303.0 ); mlt_producer dv2 = mlt_factory_producer( "mcmpeg", file2 ); //mlt_producer_set_in_and_out( dv2, 10.0, 30.0 ); #if 0 // Connect the consumer to the producer - mlt_consumer_connect( consumer, mlt_producer_service( dv1 ) ); + mlt_consumer_connect( consumer, mlt_producer_service( dv2 ) ); // Do stuff until we're told otherwise... fprintf( stderr, "Press return to continue\n" ); @@ -74,8 +74,8 @@ int main( int argc, char **argv ) // Define a transition mlt_transition transition = mlt_factory_transition( "luma", NULL ); mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 ); - mlt_transition_set_in_and_out( transition, 1.0, 2.0 ); - mlt_properties_set( mlt_transition_properties( transition ), "filename", "clock.pgm" ); + mlt_transition_set_in_and_out( transition, 1.0, 3.0 ); + //mlt_properties_set( mlt_transition_properties( transition ), "filename", "clock.pgm" ); mlt_properties_set_double( mlt_transition_properties( transition ), "softness", 0.1 ); // Buy a tractor and connect it to the filter -- 1.7.4.4