[Jahshaka-cvs] openlibraries/src/openmedialib/plugins/gensys gensys_plugin.cpp, 1.8, 1.9 gensys_plu
Status: Beta
Brought to you by:
jahshaka
From: Charles Y. <lil...@us...> - 2006-11-30 13:06:28
|
Update of /cvsroot/openlibraries/openlibraries/src/openmedialib/plugins/gensys In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv23623 Modified Files: gensys_plugin.cpp gensys_plugin.opl Log Message: + Added deinterlace, playlist, temporal and visualise filters Index: gensys_plugin.opl =================================================================== RCS file: /cvsroot/openlibraries/openlibraries/src/openmedialib/plugins/gensys/gensys_plugin.opl,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- gensys_plugin.opl 25 Nov 2006 17:26:13 -0000 1.3 +++ gensys_plugin.opl 30 Nov 2006 13:06:25 -0000 1.4 @@ -3,6 +3,6 @@ <!-- plugins go here --> <openmedialib name="oml" version="0.1.0"> <plugin name="OpenLibraries gensys plugin" type="input" extension='"colour:"' merit="0" filename='"libopenmedialib_gensys.so", "libopenmedialib_gensys.dylib", "openmedialib_gensys-vc71-d-0_3_0.dll", "openmedialib_gensys-vc71-r-0_3_0.dll"'/> - <plugin name="OpenLibraries gensys plugin" type="filter" extension='"chroma", "composite", "correction", "threader"' merit="0" filename='"libopenmedialib_gensys.so", "libopenmedialib_gensys.dylib", "openmedialib_gensys-vc71-d-0_3_0.dll", "openmedialib_gensys-vc71-r-0_3_0.dll"'/> + <plugin name="OpenLibraries gensys plugin" type="filter" extension='"chroma", "composite", "correction", "deinterlace", "playlist", "temporal", "threader", "visualise"' merit="0" filename='"libopenmedialib_gensys.so", "libopenmedialib_gensys.dylib", "openmedialib_gensys-vc71-d-0_3_0.dll", "openmedialib_gensys-vc71-r-0_3_0.dll"'/> </openmedialib> </openlibraries> Index: gensys_plugin.cpp =================================================================== RCS file: /cvsroot/openlibraries/openlibraries/src/openmedialib/plugins/gensys/gensys_plugin.cpp,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- gensys_plugin.cpp 27 Nov 2006 23:26:37 -0000 1.8 +++ gensys_plugin.cpp 30 Nov 2006 13:06:25 -0000 1.9 @@ -16,6 +16,7 @@ #include <iostream> #include <cstdlib> #include <vector> +#include <map> #include <string> #include <cmath> @@ -213,6 +214,8 @@ properties( ).append( prop_v_ = 128 ); } + virtual const opl::wstring get_uri( ) const { return L"chroma"; } + virtual frame_type_ptr fetch( ) { acquire_values( ); @@ -301,6 +304,8 @@ // TODO: Audio cross fades/mixing. // // TODO: Vertical and horizontal alignment. +// +// DONE: Correction of pixel default struct geometry { int x, y, w, h; }; @@ -322,7 +327,7 @@ , prop_mix_( pcos::key::from_string( "mix" ) ) { properties( ).append( prop_mode_ = opl::wstring( L"fill" ) ); - properties( ).append( prop_pixel_ = 1 ); + properties( ).append( prop_pixel_ = 0 ); properties( ).append( prop_px_ = 0 ); properties( ).append( prop_py_ = 0 ); properties( ).append( prop_pw_ = 720 ); @@ -334,6 +339,8 @@ properties( ).append( prop_mix_ = 1.0 ); } + virtual const opl::wstring get_uri( ) const { return L"composite"; } + virtual const size_t inputs( ) const { return 2; } virtual frame_type_ptr fetch( ) @@ -608,6 +615,8 @@ properties( ).append( prop_saturation_ = 1.0 ); } + virtual const opl::wstring get_uri( ) const { return L"correction"; } + virtual frame_type_ptr fetch( ) { acquire_values( ); @@ -776,22 +785,27 @@ prop_active_.set( 0 ); } + virtual const opl::wstring get_uri( ) const { return L"threader"; } + void update_active( ) { - if ( prop_active_.value< int >( ) == 1 && !running_ ) - { - running_ = true; - reader_ = new boost::thread( start_ ); - } - else if ( prop_active_.value< int >( ) == 0 && running_ ) + if ( is_thread_safe( ) ) { - running_ = false; + if ( prop_active_.value< int >( ) == 1 && !running_ ) { - scoped_lock lock( mutex_ ); - cond_.notify_all( ); + running_ = true; + reader_ = new boost::thread( start_ ); + } + else if ( prop_active_.value< int >( ) == 0 && running_ ) + { + running_ = false; + { + scoped_lock lock( mutex_ ); + cond_.notify_all( ); + } + reader_->join( ); + delete reader_; } - reader_->join( ); - delete reader_; } } @@ -871,6 +885,12 @@ return result; } + virtual void on_slot_change( input_type_ptr input, int ) + { + if ( !input ) + prop_active_.set( 0 ); + } + private: reader_thread start_; boost::shared_ptr< pcos::observer > obs_active_; @@ -884,6 +904,402 @@ boost::thread *reader_; }; +// Temporal Interpolating filter +// +// A basic drop and dupe frame rate interpolating filter. +// +// Takes a single connected input. +// +// Properties: +// +// enable_audio = 0 or 1 [default: inheritied from connected input] +// +// enable_video = 0 or 1 [default: inheritied from connected input] +// +// in = 0 to n [default: 0] +// The first frame expressed in the source frame rate. +// +// out = 0 to n [default: inherited from connected input] +// The last frame expressed in the source frame rate. +// +// width, height = w, h [default: inherited from connected input] +// The width/height of each frame. +// +// sar_num, sar_den = n, d [default: inhertited from connected input] +// The sample aspect ratio +// +// fps_num, fps_den = n, d [default: inhertited from connected input] +// The target frame rate +// +// Caveat: All properties should be set prior to the first fetch. +// +// TODO: honour the fps requested + +class ML_PLUGIN_DECLSPEC temporal_filter : public filter_type +{ + public: + temporal_filter( ) + : filter_type( ) + , position_( -1 ) + , last_position_( -1 ) + , prop_enable_audio_( pcos::key::from_string( "enable_audio" ) ) + , prop_enable_video_( pcos::key::from_string( "enable_video" ) ) + , prop_in_( pcos::key::from_string( "in" ) ) + , prop_out_( pcos::key::from_string( "out" ) ) + , prop_width_( pcos::key::from_string( "width" ) ) + , prop_height_( pcos::key::from_string( "height" ) ) + , prop_sar_num_( pcos::key::from_string( "sar_num" ) ) + , prop_sar_den_( pcos::key::from_string( "sar_den" ) ) + , prop_fps_num_( pcos::key::from_string( "fps_num" ) ) + , prop_fps_den_( pcos::key::from_string( "fps_den" ) ) + { + properties( ).append( prop_enable_audio_ = 0 ); + properties( ).append( prop_enable_video_ = 0 ); + properties( ).append( prop_in_ = 0 ); + properties( ).append( prop_out_ = 0 ); + properties( ).append( prop_width_ = 0 ); + properties( ).append( prop_height_ = 0 ); + properties( ).append( prop_sar_num_ = 0 ); + properties( ).append( prop_sar_den_ = 0 ); + properties( ).append( prop_fps_num_ = 0 ); + properties( ).append( prop_fps_den_ = 0 ); + reseater_ = create_audio_reseat( ); + } + + virtual int get_frames( ) const + { + return map_source_to_dest( prop_out_.value< int >( ) - prop_in_.value< int >( ) ); + } + + virtual const opl::wstring get_uri( ) const { return L"temporal"; } + + virtual void seek( int position, bool relative = false ) + { + if( relative ) + position_ += position; + else + position_ = position; + } + + virtual int get_position( ) const + { + return position_; + } + + virtual frame_type_ptr fetch( ) + { + acquire_values( ); + + frame_type_ptr result; + input_type_ptr input = fetch_slot( ); + + if ( input ) + { + if ( prop_enable_audio_.value< int >( ) == 0 ) + { + input->set_process_flags( process_image ); + input->seek( prop_in_.value< int >( ) + map_dest_to_source( get_position( ) ) ); + result = input->fetch( ); + resample( result ); + } + else /* if ( prop_fps_num_.value< int >( ) == prop_src_num_ && prop_fps_den_.value< int >( ) == prop_src_den_ ) */ + { + input->seek( prop_in_.value< int >( ) + map_dest_to_source( get_position( ) ) ); + result = input->fetch( ); + resample( result ); + } + } + + return result; + } + + virtual void on_slot_change( input_type_ptr input, int ) + { + if ( input ) + { + prop_in_ = 0; + prop_out_ = input->get_frames( ); + + frame_type_ptr frame = input->fetch( ); + + if ( frame ) + { + prop_fps_num_ = frame->get_fps_num( ); + prop_fps_den_ = frame->get_fps_den( ); + prop_src_num_ = frame->get_fps_num( ); + prop_src_den_ = frame->get_fps_den( ); + + if ( frame->get_image( ) ) + { + prop_enable_video_ = 1; + prop_width_ = frame->get_image( )->width( ); + prop_height_ = frame->get_image( )->height( ); + prop_sar_num_ = frame->get_sar_num( ); + prop_sar_den_ = frame->get_sar_den( ); + } + else + { + prop_enable_video_ = 0; + } + + if ( frame->get_audio( ) ) + { + prop_enable_audio_ = 1; + prop_src_frequency_ = frame->get_audio( )->frequency( ); + } + else + { + prop_enable_audio_ = 0; + } + } + else + { + prop_enable_video_ = 0; + prop_enable_video_ = 0; + } + } + } + + private: + inline int map_source_to_dest( int position ) const + { + return int( ( double( position ) * double( prop_fps_num_.value< int >( ) * prop_src_den_ ) ) / ( double( prop_fps_den_.value< int >( ) * prop_src_num_ ) ) ); + } + + inline int map_dest_to_source( int position ) const + { + return int( double( position ) * double( prop_src_num_ * prop_fps_den_.value< int >( ) ) / double( prop_src_den_ * prop_fps_num_.value< int >( ) ) + 0.5 ); + } + + inline int get_in( ) const + { + return map_source_to_dest( prop_in_.value< int >( ) ); + } + + inline int get_out( ) const + { + return map_source_to_dest( prop_out_.value< int >( ) ); + } + + void resample( frame_type_ptr ) + { + } + + int position_; + int last_position_; + pcos::property prop_enable_audio_; + pcos::property prop_enable_video_; + pcos::property prop_in_; + pcos::property prop_out_; + pcos::property prop_width_; + pcos::property prop_height_; + pcos::property prop_sar_num_; + pcos::property prop_sar_den_; + int prop_src_num_; + int prop_src_den_; + pcos::property prop_fps_num_; + pcos::property prop_fps_den_; + int prop_src_frequency_; + audio_reseat_ptr reseater_; + std::map< int, frame_type_ptr > frame_store; +}; + +// Deinterlace +// +// Deinterlaces an image on demand. + +class ML_PLUGIN_DECLSPEC deinterlace_filter : public filter_type +{ + public: + deinterlace_filter( ) + : filter_type( ) + { + } + + virtual const opl::wstring get_uri( ) const { return L"deinterlace"; } + + virtual frame_type_ptr fetch( ) + { + acquire_values( ); + + frame_type_ptr result; + input_type_ptr input = fetch_slot( ); + + if ( input ) + { + input->seek( get_position( ) ); + result = input->fetch( ); + if ( result && result->get_image( ) ) + result->set_image( il::deinterlace( result->get_image( ) ) ); + } + + return result; + } +}; + +// Wave Visualisation +// +// Provides a wave visualisation of the audio. +// +// Expects a single input. + +class ML_PLUGIN_DECLSPEC visualise_filter : public filter_type +{ + public: + visualise_filter( ) + : filter_type( ) + { + } + + virtual const opl::wstring get_uri( ) const { return L"visualise"; } + + virtual frame_type_ptr fetch( ) + { + acquire_values( ); + + frame_type_ptr result; + input_type_ptr input = fetch_slot( ); + + if ( input ) + { + input->seek( get_position( ) ); + result = input->fetch( ); + if ( result ) + visualise( result ); + } + + return result; + } + + private: + void visualise( frame_type_ptr frame ) + { + if ( frame->get_audio( ) != 0 ) + { + audio_type_ptr audio = frame->get_audio( ); + image_type_ptr image = il::allocate( L"r8g8b8", 640, 480 ); + memset( image->data( ), 0, image->size( ) ); + + short *buff = ( short * )audio->data( ); + int samples = audio->samples( ); + int channels = audio->channels( ); + + double sample_offset = 640.0 / samples; + int pitch = image->pitch( ); + unsigned char *middle = image->data( ) + pitch * image->height( ) / 2; + + short sample; + unsigned char *p; + int i, j; + int offset; + + for ( i = 0; i < 640; i ++ ) + { + offset = i * 3; + for ( j = 0; j < channels; j ++ ) + { + sample = ( buff + 2 * int( sample_offset * i * channels ) )[ j ] / 140; + p = middle - sample * pitch + offset; + *p ++ = j == 0 ? 255 : 0; + *p ++ = j == 0 ? 0 : 255; + *p ++ = 0; + } + } + + frame->set_image( image ); + } + } +}; + +// Playlist filter +// +// Experimental n-ary filter - the number of possibly connected inputs is +// defined by the 'inputs' property. The number of frames reported by the filter +// is defined as the sum of the frames in all the connected inputs. The frame +// rate/image information reported reflects the values of the input associated +// to slot 0 (and hence, if nothing is connected to slot 0, those values are +// null'd - behaviour in such a case is considered undefined). +// +// It is not this filters responsibility to ensure that all connected inputs +// have the same frame rate/sample information - that is left as an exercise +// for the filter graph builder to deal with. +// +// Properties: +// +// inputs = n (default: 2) +// The maximum number of connected inputs + +class ML_PLUGIN_DECLSPEC playlist_filter : public filter_type +{ + public: + playlist_filter( ) + : filter_type( ) + , prop_inputs_( pcos::key::from_string( "inputs" ) ) + { + properties( ).append( prop_inputs_ = 2 ); + } + + virtual const size_t inputs( ) const { return size_t( prop_inputs_.value< int >( ) ); } + + virtual const opl::wstring get_uri( ) const { return L"playlist"; } + + virtual int get_frames( ) const + { + int result = 0; + for ( size_t i = 0; i < inputs( ); i ++ ) + if ( fetch_slot( i ) ) + result += fetch_slot( i )->get_frames( ); + return result; + } + + virtual frame_type_ptr fetch( ) + { + acquire_values( ); + + frame_type_ptr result; + size_t slot = slot_for_position( get_position( ) ); + input_type_ptr input = fetch_slot( slot ); + + if ( input ) + { + input->seek( get_position( ) - slot_offset( slot ) ); + result = input->fetch( ); + } + + return result; + } + + private: + size_t slot_for_position( int position ) + { + size_t result = 0; + for ( size_t i = 0; i < inputs( ); i ++ ) + { + if ( fetch_slot( i ) ) + { + result = i; + if ( position < fetch_slot( i )->get_frames( ) ) + break; + position -= fetch_slot( i )->get_frames( ); + } + } + return result; + } + + int slot_offset( size_t slot ) + { + int result = 0; + for ( size_t i = 0; i < slot; i ++ ) + { + if ( fetch_slot( i ) ) + result += fetch_slot( i )->get_frames( ); + } + return result; + } + + pcos::property prop_inputs_; +}; + // // Plugin object // @@ -900,12 +1316,20 @@ { if ( request == L"chroma" ) return filter_type_ptr( new chroma_filter( ) ); - if ( request == L"composite" ) + else if ( request == L"composite" ) return filter_type_ptr( new composite_filter( ) ); - if ( request == L"correction" ) + else if ( request == L"correction" ) return filter_type_ptr( new correction_filter( ) ); - if ( request == L"threader" ) + else if ( request == L"deinterlace" ) + return filter_type_ptr( new deinterlace_filter( ) ); + else if ( request == L"playlist" ) + return filter_type_ptr( new playlist_filter( ) ); + else if ( request == L"temporal" ) + return filter_type_ptr( new temporal_filter( ) ); + else if ( request == L"threader" ) return filter_type_ptr( new threader_filter( ) ); + else if ( request == L"visualise" ) + return filter_type_ptr( new visualise_filter( ) ); return filter_type_ptr( ); } }; @@ -943,3 +1367,4 @@ #ifdef _MSC_VER # pragma warning ( pop ) #endif + |