From: lilo_booter Date: Wed, 31 Dec 2003 12:08:59 +0000 (+0000) Subject: ffmpeg audio dub X-Git-Url: http://research.m1stereo.tv/gitweb?a=commitdiff_plain;h=35aa3217c6ad838d1612875e3efdb0c99e4fd639;p=melted ffmpeg audio dub git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@32 d19143bc-622f-0410-bfdd-b5b2a6649095 --- diff --git a/mlt/src/modules/ffmpeg/Makefile b/mlt/src/modules/ffmpeg/Makefile index 7e6b4d0..a2fede0 100644 --- a/mlt/src/modules/ffmpeg/Makefile +++ b/mlt/src/modules/ffmpeg/Makefile @@ -2,7 +2,8 @@ TARGET = ../libmltffmpeg.so OBJS = factory.o \ - producer_ffmpeg.o + producer_ffmpeg.o \ + filter_ffmpeg_dub.o CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread diff --git a/mlt/src/modules/ffmpeg/configure b/mlt/src/modules/ffmpeg/configure index e4e7f8d..9219312 100755 --- a/mlt/src/modules/ffmpeg/configure +++ b/mlt/src/modules/ffmpeg/configure @@ -7,5 +7,9 @@ cat << EOF >> ../producers.dat ffmpeg libmltffmpeg.so EOF +cat << EOF >> ../filters.dat +ffmpeg_dub libmltffmpeg.so +EOF + fi diff --git a/mlt/src/modules/ffmpeg/factory.c b/mlt/src/modules/ffmpeg/factory.c index 5498e55..ab82406 100644 --- a/mlt/src/modules/ffmpeg/factory.c +++ b/mlt/src/modules/ffmpeg/factory.c @@ -21,6 +21,7 @@ #include #include "producer_ffmpeg.h" +#include "filter_ffmpeg_dub.h" void *mlt_create_producer( char *id, void *arg ) { @@ -31,6 +32,8 @@ void *mlt_create_producer( char *id, void *arg ) void *mlt_create_filter( char *id, void *arg ) { + if ( !strcmp( id, "ffmpeg_dub" ) ) + return filter_ffmpeg_dub_init( arg ); return NULL; } diff --git a/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c b/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c new file mode 100644 index 0000000..3ba9932 --- /dev/null +++ b/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.c @@ -0,0 +1,131 @@ +/* + * filter_ffmpeg_dub.c -- simple ffmpeg dub test case + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "filter_ffmpeg_dub.h" +#include +#include +#include + +/** Do it. +*/ + +static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + // Obtain the frame properties + mlt_properties frame_properties = mlt_frame_properties( frame ); + + // Get the producer used. + mlt_producer producer = mlt_properties_get_data( frame_properties, "producer", NULL ); + + // Get the producer properties + mlt_properties producer_properties = mlt_producer_properties( producer ); + + // Get the original get_audio + int ( *get_audio )( mlt_frame, int16_t **, mlt_audio_format *, int *, int *, int * ) = mlt_properties_get_data( frame_properties, "get_audio", NULL ); + + // Call the original get_audio + get_audio( frame, buffer, format, frequency, channels, samples ); + + // Now if our producer is still producing, override the audio + if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) ) + { + // Get the position + double position = mlt_properties_get_double( producer_properties, "dub_position" ); + + // We need a frame from the producer + mlt_frame producer_frame; + + // Seek to the position + mlt_producer_seek_frame( producer, ( int64_t )position ); + + // Get the next frame + producer->get_frame( producer, &producer_frame, 0 ); + + if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) ) + { + // Now get the audio from this frame + producer_frame->get_audio( producer_frame, buffer, format, frequency, channels, samples ); + + // This producer frame will be destroyed automatically when frame is destroyed + mlt_properties_set_data( frame_properties, "ffmpeg_dub_frame", producer_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); + + // Incrment the position + mlt_properties_set_double( producer_properties, "dub_position", position + 1 ); + } + } + + return 0; +} + +/** Filter processing. +*/ + +static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) +{ + // Obtain the filter properties + mlt_properties filter_properties = mlt_filter_properties( this ); + + // Get the producer used. + mlt_producer producer = mlt_properties_get_data( filter_properties, "producer", NULL ); + + // Obtain the frame properties + mlt_properties frame_properties = mlt_frame_properties( frame ); + + // Backup the original get_audio (it's still needed) + mlt_properties_set_data( frame_properties, "get_audio", frame->get_audio, 0, NULL, NULL ); + + // Pass the producer on the frame + mlt_properties_set_data( frame_properties, "producer", producer, 0, NULL, NULL ); + + // Override the get_audio method + frame->get_audio = filter_get_audio; + + return frame; +} + +/** Constructor for the filter. +*/ + +mlt_filter filter_ffmpeg_dub_init( char *file ) +{ + // Create the filter object + mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); + + // Initialise it + mlt_filter_init( this, NULL ); + + // Overide the filter process method + this->process = filter_process; + + // Obtain the properties + mlt_properties properties = mlt_filter_properties( this ); + + // Create an ffmpeg producer + mlt_producer producer = mlt_factory_producer( "ffmpeg", file ); + + // Pass the producer + mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); + + // Initialise the audio frame position + mlt_properties_set_double( properties, "dub_position", 0 ); + + return this; +} + diff --git a/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.h b/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.h new file mode 100644 index 0000000..688d01b --- /dev/null +++ b/mlt/src/modules/ffmpeg/filter_ffmpeg_dub.h @@ -0,0 +1,28 @@ +/* + * filter_ffmpeg_dub.h -- simple ffmpeg dub test case + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FILTER_FFMPEG_DUB_H_ +#define _FILTER_FFMPEG_DUB_H_ + +#include + +extern mlt_filter filter_ffmpeg_dub_init( char *file ); + +#endif diff --git a/mlt/src/modules/ffmpeg/producer_ffmpeg.c b/mlt/src/modules/ffmpeg/producer_ffmpeg.c index 4506ff8..45c702b 100644 --- a/mlt/src/modules/ffmpeg/producer_ffmpeg.c +++ b/mlt/src/modules/ffmpeg/producer_ffmpeg.c @@ -219,6 +219,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma mlt_properties properties = mlt_frame_properties( this ); producer_ffmpeg producer = mlt_properties_get_data( properties, "producer_ffmpeg", NULL ); + mlt_properties producer_properties = mlt_producer_properties( &producer->parent ); int skip = mlt_properties_get_int( properties, "skip" ); @@ -244,7 +245,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma producer->end_of_audio = 1; } } - while( skip -- ); + while( producer->audio != NULL && skip -- ); } else { @@ -254,6 +255,9 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma // Pass the data on the frame properties mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL ); + // Set the producer properties + mlt_properties_set_int( producer_properties, "end_of_clip", producer->end_of_video && producer->end_of_audio ); + return 0; } diff --git a/mlt/src/modules/gtk2/producer_pixbuf.c b/mlt/src/modules/gtk2/producer_pixbuf.c index b8a792d..06b32c6 100644 --- a/mlt/src/modules/gtk2/producer_pixbuf.c +++ b/mlt/src/modules/gtk2/producer_pixbuf.c @@ -89,6 +89,8 @@ mlt_producer producer_pixbuf_init( const char *filename ) gap ++; } } + mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_timecode( properties, "playtime", this->count ); } else if ( strstr( filename, "/.all." ) != NULL ) { @@ -115,6 +117,8 @@ mlt_producer producer_pixbuf_init( const char *filename ) free( de[ i ] ); } + mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_timecode( properties, "playtime", this->count ); free( de ); free( dir_name ); } @@ -122,6 +126,8 @@ mlt_producer producer_pixbuf_init( const char *filename ) { this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); this->filenames[ this->count ++ ] = strdup( filename ); + mlt_properties_set_timecode( properties, "out", 1 ); + mlt_properties_set_timecode( properties, "playtime", 1 ); } // Initialise gobject types diff --git a/src/modules/ffmpeg/Makefile b/src/modules/ffmpeg/Makefile index 7e6b4d0..a2fede0 100644 --- a/src/modules/ffmpeg/Makefile +++ b/src/modules/ffmpeg/Makefile @@ -2,7 +2,8 @@ TARGET = ../libmltffmpeg.so OBJS = factory.o \ - producer_ffmpeg.o + producer_ffmpeg.o \ + filter_ffmpeg_dub.o CFLAGS = -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread diff --git a/src/modules/ffmpeg/configure b/src/modules/ffmpeg/configure index e4e7f8d..9219312 100755 --- a/src/modules/ffmpeg/configure +++ b/src/modules/ffmpeg/configure @@ -7,5 +7,9 @@ cat << EOF >> ../producers.dat ffmpeg libmltffmpeg.so EOF +cat << EOF >> ../filters.dat +ffmpeg_dub libmltffmpeg.so +EOF + fi diff --git a/src/modules/ffmpeg/factory.c b/src/modules/ffmpeg/factory.c index 5498e55..ab82406 100644 --- a/src/modules/ffmpeg/factory.c +++ b/src/modules/ffmpeg/factory.c @@ -21,6 +21,7 @@ #include #include "producer_ffmpeg.h" +#include "filter_ffmpeg_dub.h" void *mlt_create_producer( char *id, void *arg ) { @@ -31,6 +32,8 @@ void *mlt_create_producer( char *id, void *arg ) void *mlt_create_filter( char *id, void *arg ) { + if ( !strcmp( id, "ffmpeg_dub" ) ) + return filter_ffmpeg_dub_init( arg ); return NULL; } diff --git a/src/modules/ffmpeg/filter_ffmpeg_dub.c b/src/modules/ffmpeg/filter_ffmpeg_dub.c new file mode 100644 index 0000000..3ba9932 --- /dev/null +++ b/src/modules/ffmpeg/filter_ffmpeg_dub.c @@ -0,0 +1,131 @@ +/* + * filter_ffmpeg_dub.c -- simple ffmpeg dub test case + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "filter_ffmpeg_dub.h" +#include +#include +#include + +/** Do it. +*/ + +static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) +{ + // Obtain the frame properties + mlt_properties frame_properties = mlt_frame_properties( frame ); + + // Get the producer used. + mlt_producer producer = mlt_properties_get_data( frame_properties, "producer", NULL ); + + // Get the producer properties + mlt_properties producer_properties = mlt_producer_properties( producer ); + + // Get the original get_audio + int ( *get_audio )( mlt_frame, int16_t **, mlt_audio_format *, int *, int *, int * ) = mlt_properties_get_data( frame_properties, "get_audio", NULL ); + + // Call the original get_audio + get_audio( frame, buffer, format, frequency, channels, samples ); + + // Now if our producer is still producing, override the audio + if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) ) + { + // Get the position + double position = mlt_properties_get_double( producer_properties, "dub_position" ); + + // We need a frame from the producer + mlt_frame producer_frame; + + // Seek to the position + mlt_producer_seek_frame( producer, ( int64_t )position ); + + // Get the next frame + producer->get_frame( producer, &producer_frame, 0 ); + + if ( !mlt_properties_get_int( producer_properties, "end_of_clip" ) ) + { + // Now get the audio from this frame + producer_frame->get_audio( producer_frame, buffer, format, frequency, channels, samples ); + + // This producer frame will be destroyed automatically when frame is destroyed + mlt_properties_set_data( frame_properties, "ffmpeg_dub_frame", producer_frame, 0, ( mlt_destructor )mlt_frame_close, NULL ); + + // Incrment the position + mlt_properties_set_double( producer_properties, "dub_position", position + 1 ); + } + } + + return 0; +} + +/** Filter processing. +*/ + +static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) +{ + // Obtain the filter properties + mlt_properties filter_properties = mlt_filter_properties( this ); + + // Get the producer used. + mlt_producer producer = mlt_properties_get_data( filter_properties, "producer", NULL ); + + // Obtain the frame properties + mlt_properties frame_properties = mlt_frame_properties( frame ); + + // Backup the original get_audio (it's still needed) + mlt_properties_set_data( frame_properties, "get_audio", frame->get_audio, 0, NULL, NULL ); + + // Pass the producer on the frame + mlt_properties_set_data( frame_properties, "producer", producer, 0, NULL, NULL ); + + // Override the get_audio method + frame->get_audio = filter_get_audio; + + return frame; +} + +/** Constructor for the filter. +*/ + +mlt_filter filter_ffmpeg_dub_init( char *file ) +{ + // Create the filter object + mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); + + // Initialise it + mlt_filter_init( this, NULL ); + + // Overide the filter process method + this->process = filter_process; + + // Obtain the properties + mlt_properties properties = mlt_filter_properties( this ); + + // Create an ffmpeg producer + mlt_producer producer = mlt_factory_producer( "ffmpeg", file ); + + // Pass the producer + mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL ); + + // Initialise the audio frame position + mlt_properties_set_double( properties, "dub_position", 0 ); + + return this; +} + diff --git a/src/modules/ffmpeg/filter_ffmpeg_dub.h b/src/modules/ffmpeg/filter_ffmpeg_dub.h new file mode 100644 index 0000000..688d01b --- /dev/null +++ b/src/modules/ffmpeg/filter_ffmpeg_dub.h @@ -0,0 +1,28 @@ +/* + * filter_ffmpeg_dub.h -- simple ffmpeg dub test case + * Copyright (C) 2003-2004 Ushodaya Enterprises Limited + * Author: Charles Yates + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _FILTER_FFMPEG_DUB_H_ +#define _FILTER_FFMPEG_DUB_H_ + +#include + +extern mlt_filter filter_ffmpeg_dub_init( char *file ); + +#endif diff --git a/src/modules/ffmpeg/producer_ffmpeg.c b/src/modules/ffmpeg/producer_ffmpeg.c index 4506ff8..45c702b 100644 --- a/src/modules/ffmpeg/producer_ffmpeg.c +++ b/src/modules/ffmpeg/producer_ffmpeg.c @@ -219,6 +219,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma mlt_properties properties = mlt_frame_properties( this ); producer_ffmpeg producer = mlt_properties_get_data( properties, "producer_ffmpeg", NULL ); + mlt_properties producer_properties = mlt_producer_properties( &producer->parent ); int skip = mlt_properties_get_int( properties, "skip" ); @@ -244,7 +245,7 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma producer->end_of_audio = 1; } } - while( skip -- ); + while( producer->audio != NULL && skip -- ); } else { @@ -254,6 +255,9 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma // Pass the data on the frame properties mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL ); + // Set the producer properties + mlt_properties_set_int( producer_properties, "end_of_clip", producer->end_of_video && producer->end_of_audio ); + return 0; } diff --git a/src/modules/gtk2/producer_pixbuf.c b/src/modules/gtk2/producer_pixbuf.c index b8a792d..06b32c6 100644 --- a/src/modules/gtk2/producer_pixbuf.c +++ b/src/modules/gtk2/producer_pixbuf.c @@ -89,6 +89,8 @@ mlt_producer producer_pixbuf_init( const char *filename ) gap ++; } } + mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_timecode( properties, "playtime", this->count ); } else if ( strstr( filename, "/.all." ) != NULL ) { @@ -115,6 +117,8 @@ mlt_producer producer_pixbuf_init( const char *filename ) free( de[ i ] ); } + mlt_properties_set_timecode( properties, "out", this->count ); + mlt_properties_set_timecode( properties, "playtime", this->count ); free( de ); free( dir_name ); } @@ -122,6 +126,8 @@ mlt_producer producer_pixbuf_init( const char *filename ) { this->filenames = realloc( this->filenames, sizeof( char * ) * ( this->count + 1 ) ); this->filenames[ this->count ++ ] = strdup( filename ); + mlt_properties_set_timecode( properties, "out", 1 ); + mlt_properties_set_timecode( properties, "playtime", 1 ); } // Initialise gobject types