/***************************************************************************** * CloseEncoder: ffmpeg encoder destruction *****************************************************************************/ void E_(CloseEncoder)( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys = p_enc->p_sys; #if LIBAVCODEC_BUILD >= 4702 if ( p_sys->b_inited && p_enc->i_threads >= 1 ) { int i; struct thread_context_t ** pp_contexts = (struct thread_context_t **)p_sys->p_context->thread_opaque; for ( i = 0; i < p_enc->i_threads; i++ ) { pp_contexts[i]->b_die = 1; vlc_cond_signal( &pp_contexts[i]->cond ); vlc_thread_join( pp_contexts[i] ); vlc_mutex_destroy( &pp_contexts[i]->lock ); vlc_cond_destroy( &pp_contexts[i]->cond ); vlc_object_destroy( pp_contexts[i] ); } free( pp_contexts ); } #endif avcodec_close( p_sys->p_context ); av_free( p_sys->p_context ); if( p_sys->p_buffer ) free( p_sys->p_buffer ); if( p_sys->p_buffer_out ) free( p_sys->p_buffer_out ); free( p_sys ); }
/***************************************************************************** * Close: destroy interface window *****************************************************************************/ static void Close( vlc_object_t *p_this ) { vlc_value_t lockval; var_Get( p_this->p_libvlc, "gtk", &lockval ); vlc_mutex_lock( lockval.p_address ); i_refcount--; if( i_refcount > 0 ) { vlc_mutex_unlock( lockval.p_address ); var_Destroy( p_this->p_libvlc, "gtk" ); return; } gtk_main_quit(); vlc_thread_join( p_gtk_main ); vlc_object_destroy( p_gtk_main ); p_gtk_main = NULL; vlc_mutex_unlock( lockval.p_address ); var_Destroy( p_this->p_libvlc, "gtk" ); }
/***************************************************************************** * End: terminate logo video thread output method *****************************************************************************/ static void End( vout_thread_t *p_vout ) { vout_sys_t *p_sys = p_vout->p_sys; int i_index; /* Free the fake output buffers we allocated */ for( i_index = I_OUTPUTPICTURES ; i_index ; ) { i_index--; free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); } var_DelCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout); var_DelCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout); if( p_sys->p_vout ) { DEL_CALLBACKS( p_sys->p_vout, SendEvents ); vlc_object_detach( p_sys->p_vout ); vout_Destroy( p_sys->p_vout ); } if( p_sys->p_blend->p_module ) module_Unneed( p_sys->p_blend, p_sys->p_blend->p_module ); vlc_object_detach( p_sys->p_blend ); vlc_object_destroy( p_sys->p_blend ); }
/***************************************************************************** * Close: close the audio device *****************************************************************************/ static void Close( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; aout_sys_t *p_sys = p_aout->output.p_sys; /* Before calling waveOutClose we must reset the device */ p_aout->b_die = VLC_TRUE; waveOutReset( p_sys->h_waveout ); /* wake up the audio thread */ SetEvent( p_sys->event ); vlc_thread_join( p_sys->p_notif ); vlc_object_destroy( p_sys->p_notif ); CloseHandle( p_sys->event ); /* Close the device */ if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR ) { msg_Err( p_aout, "waveOutClose failed" ); } free( p_sys->p_silence_buffer ); free( p_sys ); }
/** * Destroy the playlist. * * Delete all items in the playlist and free the playlist structure. * \param p_playlist the playlist structure to destroy */ void playlist_Destroy( playlist_t * p_playlist ) { p_playlist->b_die = 1; vlc_thread_join( p_playlist ); var_Destroy( p_playlist, "intf-change" ); var_Destroy( p_playlist, "item-change" ); var_Destroy( p_playlist, "playlist-current" ); var_Destroy( p_playlist, "intf-popmenu" ); var_Destroy( p_playlist, "intf-show" ); var_Destroy( p_playlist, "prevent-skip" ); var_Destroy( p_playlist, "play-and-stop" ); var_Destroy( p_playlist, "random" ); var_Destroy( p_playlist, "repeat" ); var_Destroy( p_playlist, "loop" ); while( p_playlist->i_groups > 0 ) { playlist_DeleteGroup( p_playlist, p_playlist->pp_groups[0]->i_id ); } while( p_playlist->i_size > 0 ) { playlist_Delete( p_playlist, 0 ); } vlc_object_destroy( p_playlist ); }
/***************************************************************************** * FindFilter: find an audio filter for a specific transformation *****************************************************************************/ static aout_filter_t * FindFilter( aout_instance_t * p_aout, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ) { aout_filter_t * p_filter = vlc_object_create( p_aout, sizeof(aout_filter_t) ); if ( p_filter == NULL ) return NULL; vlc_object_attach( p_filter, p_aout ); memcpy( &p_filter->input, p_input_format, sizeof(audio_sample_format_t) ); memcpy( &p_filter->output, p_output_format, sizeof(audio_sample_format_t) ); p_filter->p_module = module_Need( p_filter, "audio filter", NULL, 0 ); if ( p_filter->p_module == NULL ) { vlc_object_detach( p_filter ); vlc_object_destroy( p_filter ); return NULL; } p_filter->b_continuity = VLC_FALSE; return p_filter; }
/***************************************************************************** * Open: open a scope effect plugin *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys; galaktos_thread_t *p_thread; if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { msg_Warn( p_filter, "bad input or output format" ); return VLC_EGENERIC; } if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { msg_Warn( p_filter, "input and output formats are not similar" ); return VLC_EGENERIC; } p_filter->pf_do_work = DoWork; p_filter->b_in_place = 1; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) ); /* Create galaktos thread */ p_sys->p_thread = p_thread = vlc_object_create( p_filter, sizeof( galaktos_thread_t ) ); vlc_object_attach( p_thread, p_this ); /* var_Create( p_thread, "galaktos-width", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "galaktos-width", &width ); var_Create( p_thread, "galaktos-height", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "galaktos-height", &height ); */ p_thread->i_cur_sample = 0; bzero( p_thread->p_data, 2*2*512 ); p_thread->i_width = 600; p_thread->i_height = 600; p_thread->b_fullscreen = 0; galaktos_init( p_thread ); p_thread->i_channels = aout_FormatNbChannels( &p_filter->input ); p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) ); if( vlc_thread_create( p_thread, "galaktos update thread", Thread, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) { msg_Err( p_filter, "cannot lauch galaktos thread" ); if( p_thread->psz_title ) free( p_thread->psz_title ); vlc_object_detach( p_thread ); vlc_object_destroy( p_thread ); free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * Close: close the plugin *****************************************************************************/ static void Close( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys = p_filter->p_sys; /* Stop Goom Thread */ p_sys->p_thread->b_die = VLC_TRUE; vlc_mutex_lock( &p_sys->p_thread->lock ); vlc_cond_signal( &p_sys->p_thread->wait ); vlc_mutex_unlock( &p_sys->p_thread->lock ); vlc_thread_join( p_sys->p_thread ); /* Free data */ vout_Request( p_filter, p_sys->p_thread->p_vout, 0, 0, 0, 0 ); vlc_mutex_destroy( &p_sys->p_thread->lock ); vlc_cond_destroy( &p_sys->p_thread->wait ); vlc_object_detach( p_sys->p_thread ); while( p_sys->p_thread->i_blocks-- ) { block_Release( p_sys->p_thread->pp_blocks[p_sys->p_thread->i_blocks] ); } vlc_object_destroy( p_sys->p_thread ); free( p_sys ); }
/***************************************************************************** * Decrement an object refcount * And destroy the object if its refcount reach zero. *****************************************************************************/ void vlc_object_release( vlc_object_t *p_this ) { vlc_object_internals_t *internals = vlc_internals( p_this ); vlc_object_t *parent = NULL; bool b_should_destroy; vlc_spin_lock( &internals->ref_spin ); assert( internals->i_refcount > 0 ); if( internals->i_refcount > 1 ) { /* Fast path */ /* There are still other references to the object */ internals->i_refcount--; vlc_spin_unlock( &internals->ref_spin ); return; } vlc_spin_unlock( &internals->ref_spin ); /* Slow path */ /* Remember that we cannot hold the spin while waiting on the mutex */ libvlc_lock (p_this->p_libvlc); /* Take the spin again. Note that another thread may have held the * object in the (very short) mean time. */ vlc_spin_lock( &internals->ref_spin ); b_should_destroy = --internals->i_refcount == 0; vlc_spin_unlock( &internals->ref_spin ); if( b_should_destroy ) { /* Detach from parent to protect against FIND_CHILDREN */ parent = p_this->p_parent; if (likely(parent)) { /* Unlink */ if (internals->prev != NULL) internals->prev->next = internals->next; else vlc_internals(parent)->first = internals->next; if (internals->next != NULL) internals->next->prev = internals->prev; } /* We have no children */ assert (internals->first == NULL); } libvlc_unlock (p_this->p_libvlc); if( b_should_destroy ) { int canc; canc = vlc_savecancel (); vlc_object_destroy( p_this ); vlc_restorecancel (canc); if (parent) vlc_object_release (parent); } }
/***************************************************************************** * Open: initializes demux structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; uint8_t *p_peek; vlc_value_t val; if( stream_Peek( p_demux->s, &p_peek, 5 ) < 5 ) return VLC_EGENERIC; if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x00 || p_peek[3] != 0x01 || (p_peek[4]&0x1F) != 7 ) /* SPS */ { if( !p_demux->b_force ) { msg_Warn( p_demux, "h264 module discarded (no startcode)" ); return VLC_EGENERIC; } msg_Err( p_demux, "this doesn't look like a H264 ES stream, " "continuing anyway" ); } p_demux->pf_demux = Demux; p_demux->pf_control= Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->p_es = NULL; p_sys->i_dts = 1; var_Create( p_demux, "h264-fps", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT ); var_Get( p_demux, "h264-fps", &val ); p_sys->f_fps = val.f_float; if( val.f_float < 0.001 ) p_sys->f_fps = 0.001; msg_Dbg( p_demux, "using %.2f fps", p_sys->f_fps ); /* * Load the mpegvideo packetizer */ p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_PACKETIZER ); p_sys->p_packetizer->pf_decode_audio = NULL; p_sys->p_packetizer->pf_decode_video = NULL; p_sys->p_packetizer->pf_decode_sub = NULL; p_sys->p_packetizer->pf_packetize = NULL; es_format_Init( &p_sys->p_packetizer->fmt_in, VIDEO_ES, VLC_FOURCC( 'h', '2', '6', '4' ) ); es_format_Init( &p_sys->p_packetizer->fmt_out, UNKNOWN_ES, 0 ); p_sys->p_packetizer->p_module = module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 ); if( p_sys->p_packetizer->p_module == NULL) { vlc_object_destroy( p_sys->p_packetizer ); msg_Err( p_demux, "cannot find mp4v packetizer" ); free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * Close: frees unused data *****************************************************************************/ static void Close( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module ); vlc_object_destroy( p_sys->p_packetizer ); free( p_sys ); }
/***************************************************************************** * aout_Delete: destroy aout structure *****************************************************************************/ void aout_Delete( aout_instance_t * p_aout ) { var_Destroy( p_aout, "intf-change" ); vlc_mutex_destroy( &p_aout->input_fifos_lock ); vlc_mutex_destroy( &p_aout->mixer_lock ); vlc_mutex_destroy( &p_aout->output_fifo_lock ); /* Free structure. */ vlc_object_destroy( p_aout ); }
/***************************************************************************** * aout_FiltersDestroyPipeline: deallocate a filters pipeline *****************************************************************************/ void aout_FiltersDestroyPipeline( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters ) { int i; for ( i = 0; i < i_nb_filters; i++ ) { module_Unneed( pp_filters[i], pp_filters[i]->p_module ); vlc_object_detach( pp_filters[i] ); vlc_object_destroy( pp_filters[i] ); } }
/***************************************************************************** * Close: frees unused data *****************************************************************************/ static void Close( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; /* Unneed module */ module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module ); /* Delete the decoder */ vlc_object_destroy( p_sys->p_packetizer ); free( p_sys ); }
/** * Destroy a announce handler object * * \param p_announce the announce handler to destroy * \return VLC_SUCCESS or an error */ int announce_HandlerDestroy( announce_handler_t *p_announce ) { if( p_announce->p_sap ) { p_announce->p_sap->b_die = VLC_TRUE; /* Wait for the SAP thread to exit */ vlc_thread_join( p_announce->p_sap ); announce_SAPHandlerDestroy( p_announce->p_sap ); } /* Free the structure */ vlc_object_destroy( p_announce ); return VLC_SUCCESS; }
/***************************************************************************** * Close: close the plugin *****************************************************************************/ static void Close( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys = p_filter->p_sys; /* Stop galaktos Thread */ p_sys->p_thread->b_die = VLC_TRUE; galaktos_done( p_sys->p_thread ); vlc_thread_join( p_sys->p_thread ); /* Free data */ vlc_object_detach( p_sys->p_thread ); vlc_object_destroy( p_sys->p_thread ); free( p_sys ); }
/***************************************************************************** * Open: initialize and create window *****************************************************************************/ static int Open( vlc_object_t *p_this ) { vlc_value_t lockval; /* FIXME: put this in the module (de)initialization ASAP */ var_Create( p_this->p_libvlc, "gtk", VLC_VAR_MUTEX ); var_Get( p_this->p_libvlc, "gtk", &lockval ); vlc_mutex_lock( lockval.p_address ); if( i_refcount > 0 ) { i_refcount++; vlc_mutex_unlock( lockval.p_address ); return VLC_SUCCESS; } p_gtk_main = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); /* Only initialize gthreads if it's the first time we do it */ if( !g_thread_supported() ) { g_thread_init( NULL ); } /* Launch the gtk_main() thread. It will not return until it has * called gdk_threads_enter(), which ensures us thread safety. */ if( vlc_thread_create( p_gtk_main, "gtk_main", GtkMain, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) { vlc_object_destroy( p_gtk_main ); i_refcount--; vlc_mutex_unlock( lockval.p_address ); var_Destroy( p_this->p_libvlc, "gtk" ); return VLC_ETHREAD; } i_refcount++; vlc_mutex_unlock( lockval.p_address ); return VLC_SUCCESS; }
/** * Destroy the SAP handler * \param p_this the SAP Handler to destroy * \return nothing */ void announce_SAPHandlerDestroy( sap_handler_t *p_sap ) { int i; vlc_mutex_destroy( &p_sap->object_lock ); /* Free the remaining sessions */ for( i = 0 ; i< p_sap->i_sessions ; i++) { sap_session_t *p_session = p_sap->pp_sessions[i]; FREE( p_session->psz_sdp ); FREE( p_session->psz_data ); REMOVE_ELEM( p_sap->pp_sessions, p_sap->i_sessions , i ); FREE( p_session ); } /* Free the remaining addresses */ for( i = 0 ; i< p_sap->i_addresses ; i++) { sap_address_t *p_address = p_sap->pp_addresses[i]; FREE( p_address->psz_address ); if( p_address->i_rfd > -1 ) { net_Close( p_address->i_rfd ); } if( p_address->i_wfd > -1 && p_sap->b_control ) { net_Close( p_address->i_wfd ); } REMOVE_ELEM( p_sap->pp_addresses, p_sap->i_addresses, i ); FREE( p_address ); } /* Free the structure */ vlc_object_destroy( p_sap ); }
/***************************************************************************** * Dummy: used by stress-test, creates objects and then do nothing. *****************************************************************************/ static void * Dummy( vlc_object_t *p_this ) { int i; vlc_object_t *pp_objects[MAXOBJ/MAXTH]; for( i = 0; i < MAXOBJ/MAXTH; i++ ) { pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); } vlc_thread_ready( p_this ); while( !p_this->b_die ) { msleep( 10000 ); } for( i = MAXOBJ/MAXTH; i--; ) { vlc_object_destroy( pp_objects[i] ); } return NULL; }
/***************************************************************************** * Callback: test callback functions *****************************************************************************/ static int Callback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { int i; char psz_var[20]; vlc_object_t *pp_objects[10]; vlc_value_t val; /* Allocate a few variables */ for( i = 0; i < 1000; i++ ) { sprintf( psz_var, "blork-%i", i ); var_Create( p_this, psz_var, VLC_VAR_INTEGER ); var_AddCallback( p_this, psz_var, MyCallback, NULL ); } /* * Test #1: callback loop detection */ printf( "Test #1: callback loop detection\n" ); printf( " - without boundary check (vlc should print an error)\n" ); val.i_int = 1234567; var_Set( p_this, "blork-12", val ); printf( " - with boundary check\n" ); val.i_int = 12; var_Set( p_this, "blork-12", val ); /* * Test #2: concurrent access */ printf( "Test #2: concurrent access\n" ); printf( " - launch worker threads\n" ); for( i = 0; i < 10; i++ ) { pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); vlc_object_attach( pp_objects[i], p_this ); vlc_thread_create( pp_objects[i], "foo", MyThread, 0, VLC_TRUE ); } msleep( 3000000 ); printf( " - kill worker threads\n" ); for( i = 0; i < 10; i++ ) { pp_objects[i]->b_die = VLC_TRUE; vlc_thread_join( pp_objects[i] ); vlc_object_detach( pp_objects[i] ); vlc_object_destroy( pp_objects[i] ); } /* Clean our mess */ for( i = 0; i < 1000; i++ ) { sprintf( psz_var, "blork-%i", i ); var_DelCallback( p_this, psz_var, MyCallback, NULL ); var_Destroy( p_this, psz_var ); } return VLC_SUCCESS; }
/***************************************************************************** * aout_InputNew : allocate a new input and rework the filter pipeline *****************************************************************************/ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) { audio_sample_format_t chain_input_format; audio_sample_format_t chain_output_format; vlc_value_t val, text; char * psz_filters, *psz_visual; int i_visual; aout_FormatPrint( p_aout, "input", &p_input->input ); p_input->i_nb_filters = 0; /* Prepare FIFO. */ aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate ); p_input->p_first_byte_to_mix = NULL; /* Prepare format structure */ memcpy( &chain_input_format, &p_input->input, sizeof(audio_sample_format_t) ); memcpy( &chain_output_format, &p_aout->mixer.mixer, sizeof(audio_sample_format_t) ); chain_output_format.i_rate = p_input->input.i_rate; aout_FormatPrepare( &chain_output_format ); /* Now add user filters */ if( var_Type( p_aout, "visual" ) == 0 ) { module_t *p_module; var_Create( p_aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE ); text.psz_string = _("Visualizations"); var_Change( p_aout, "visual", VLC_VAR_SETTEXT, &text, NULL ); val.psz_string = ""; text.psz_string = _("Disable"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = "spectrometer"; text.psz_string = _("Spectrometer"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = "scope"; text.psz_string = _("Scope"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = "spectrum"; text.psz_string = _("Spectrum"); var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); /* Look for goom plugin */ p_module = config_FindModule( VLC_OBJECT(p_aout), "goom" ); if( p_module ) { val.psz_string = "goom"; text.psz_string = "Goom"; var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); } /* Look for galaktos plugin */ p_module = config_FindModule( VLC_OBJECT(p_aout), "galaktos" ); if( p_module ) { val.psz_string = "galaktos"; text.psz_string = "GaLaktos"; var_Change( p_aout, "visual", VLC_VAR_ADDCHOICE, &val, &text ); } if( var_Get( p_aout, "effect-list", &val ) == VLC_SUCCESS ) { var_Set( p_aout, "visual", val ); if( val.psz_string ) free( val.psz_string ); } var_AddCallback( p_aout, "visual", VisualizationCallback, NULL ); } if( var_Type( p_aout, "equalizer" ) == 0 ) { module_config_t *p_config; int i; p_config = config_FindConfig( VLC_OBJECT(p_aout), "equalizer-preset" ); if( p_config && p_config->i_list ) { var_Create( p_aout, "equalizer", VLC_VAR_STRING | VLC_VAR_HASCHOICE ); text.psz_string = _("Equalizer"); var_Change( p_aout, "equalizer", VLC_VAR_SETTEXT, &text, NULL ); val.psz_string = ""; text.psz_string = _("Disable"); var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text ); for( i = 0; i < p_config->i_list; i++ ) { val.psz_string = p_config->ppsz_list[i]; text.psz_string = p_config->ppsz_list_text[i]; var_Change( p_aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text ); } var_AddCallback( p_aout, "equalizer", EqualizerCallback, NULL ); } } if( var_Type( p_aout, "audio-filter" ) == 0 ) { var_Create( p_aout, "audio-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); text.psz_string = _("Audio filters"); var_Change( p_aout, "audio-filter", VLC_VAR_SETTEXT, &text, NULL ); } if( var_Type( p_aout, "audio-visual" ) == 0 ) { var_Create( p_aout, "audio-visual", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); text.psz_string = _("Audio visualizations"); var_Change( p_aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL ); } var_Get( p_aout, "audio-filter", &val ); psz_filters = val.psz_string; var_Get( p_aout, "audio-visual", &val ); psz_visual = val.psz_string; /* parse user filter lists */ for( i_visual = 0; i_visual < 2; i_visual++ ) { char *psz_next = NULL; char *psz_parser = i_visual ? psz_visual : psz_filters; if( psz_parser == NULL || !*psz_parser ) continue; while( psz_parser && *psz_parser ) { aout_filter_t * p_filter = NULL; if( p_input->i_nb_filters >= AOUT_MAX_FILTERS ) { msg_Dbg( p_aout, "max filters reached (%d)", AOUT_MAX_FILTERS ); break; } while( *psz_parser == ' ' && *psz_parser == ':' ) { psz_parser++; } if( ( psz_next = strchr( psz_parser , ':' ) ) ) { *psz_next++ = '\0'; } if( *psz_parser =='\0' ) { break; } /* Create a VLC object */ p_filter = vlc_object_create( p_aout, sizeof(aout_filter_t) ); if( p_filter == NULL ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", psz_parser ); psz_parser = psz_next; continue; } vlc_object_attach( p_filter , p_aout ); /* try to find the requested filter */ if( i_visual == 1 ) /* this can only be a visualization module */ { /* request format */ memcpy( &p_filter->input, &chain_output_format, sizeof(audio_sample_format_t) ); memcpy( &p_filter->output, &chain_output_format, sizeof(audio_sample_format_t) ); p_filter->p_module = module_Need( p_filter, "visualization", psz_parser, VLC_TRUE ); } else /* this can be a audio filter module as well as a visualization module */ { /* request format */ memcpy( &p_filter->input, &chain_input_format, sizeof(audio_sample_format_t) ); memcpy( &p_filter->output, &chain_output_format, sizeof(audio_sample_format_t) ); p_filter->p_module = module_Need( p_filter, "audio filter", psz_parser, VLC_TRUE ); if ( p_filter->p_module == NULL ) { /* if the filter requested a special format, retry */ if ( !( AOUT_FMTS_IDENTICAL( &p_filter->input, &chain_input_format ) && AOUT_FMTS_IDENTICAL( &p_filter->output, &chain_output_format ) ) ) { aout_FormatPrepare( &p_filter->input ); aout_FormatPrepare( &p_filter->output ); p_filter->p_module = module_Need( p_filter, "audio filter", psz_parser, VLC_TRUE ); } /* try visual filters */ else { memcpy( &p_filter->input, &chain_output_format, sizeof(audio_sample_format_t) ); memcpy( &p_filter->output, &chain_output_format, sizeof(audio_sample_format_t) ); p_filter->p_module = module_Need( p_filter, "visualization", psz_parser, VLC_TRUE ); } } } /* failure */ if ( p_filter->p_module == NULL ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", psz_parser ); vlc_object_detach( p_filter ); vlc_object_destroy( p_filter ); psz_parser = psz_next; continue; } /* complete the filter chain if necessary */ if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &p_filter->input ) ) { if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, &p_input->i_nb_filters, &chain_input_format, &p_filter->input ) < 0 ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", psz_parser ); module_Unneed( p_filter, p_filter->p_module ); vlc_object_detach( p_filter ); vlc_object_destroy( p_filter ); psz_parser = psz_next; continue; } } /* success */ p_filter->b_continuity = VLC_FALSE; p_input->pp_filters[p_input->i_nb_filters++] = p_filter; memcpy( &chain_input_format, &p_filter->output, sizeof( audio_sample_format_t ) ); /* next filter if any */ psz_parser = psz_next; } } if( psz_filters ) free( psz_filters ); if( psz_visual ) free( psz_visual ); /* complete the filter chain if necessary */ if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &chain_output_format ) ) { if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, &p_input->i_nb_filters, &chain_input_format, &chain_output_format ) < 0 ) { inputFailure( p_aout, p_input, "couldn't set an input pipeline" ); return -1; } } /* Prepare hints for the buffer allocator. */ p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; p_input->input_alloc.i_bytes_per_sec = -1; /* Create resamplers. */ if ( AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) ) { p_input->i_nb_resamplers = 0; } else { chain_output_format.i_rate = (__MAX(p_input->input.i_rate, p_aout->mixer.mixer.i_rate) * (100 + AOUT_MAX_RESAMPLING)) / 100; if ( chain_output_format.i_rate == p_aout->mixer.mixer.i_rate ) { /* Just in case... */ chain_output_format.i_rate++; } p_input->i_nb_resamplers = 0; if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers, &p_input->i_nb_resamplers, &chain_output_format, &p_aout->mixer.mixer ) < 0 ) { inputFailure( p_aout, p_input, "couldn't set a resampler pipeline"); return -1; } aout_FiltersHintBuffers( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers, &p_input->input_alloc ); p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; /* Setup the initial rate of the resampler */ p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; } p_input->i_resampling_type = AOUT_RESAMPLING_NONE; aout_FiltersHintBuffers( p_aout, p_input->pp_filters, p_input->i_nb_filters, &p_input->input_alloc ); p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; /* i_bytes_per_sec is still == -1 if no filters */ p_input->input_alloc.i_bytes_per_sec = __MAX( p_input->input_alloc.i_bytes_per_sec, (int)(p_input->input.i_bytes_per_frame * p_input->input.i_rate / p_input->input.i_frame_length) ); /* Success */ p_input->b_error = VLC_FALSE; p_input->b_restart = VLC_FALSE; return 0; }
/***************************************************************************** * aout_FiltersCreatePipeline: create a filters pipeline to transform a sample * format to another ***************************************************************************** * TODO : allow the user to add/remove specific filters *****************************************************************************/ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ) { audio_sample_format_t temp_format; int i_nb_conversions; if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) ) { msg_Dbg( p_aout, "no need for any filter" ); *pi_nb_filters = 0; return 0; } aout_FormatsPrint( p_aout, "filter(s)", p_input_format, p_output_format ); /* Try to find a filter to do the whole conversion. */ pp_filters[0] = FindFilter( p_aout, p_input_format, p_output_format ); if ( pp_filters[0] != NULL ) { msg_Dbg( p_aout, "found a filter for the whole conversion" ); *pi_nb_filters = 1; return 0; } /* We'll have to split the conversion. We always do the downmixing * before the resampling, because the audio decoder can probably do it * for us. */ i_nb_conversions = SplitConversion( p_input_format, p_output_format, &temp_format ); if ( !i_nb_conversions ) { /* There was only one conversion to do, and we already failed. */ msg_Err( p_aout, "couldn't find a filter for the conversion" ); return -1; } pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format ); if ( pp_filters[0] == NULL && i_nb_conversions == 2 ) { /* Try with only one conversion. */ SplitConversion( p_input_format, &temp_format, &temp_format ); pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format ); } if ( pp_filters[0] == NULL ) { msg_Err( p_aout, "couldn't find a filter for the first part of the conversion" ); return -1; } /* We have the first stage of the conversion. Find a filter for * the rest. */ pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, p_output_format ); if ( pp_filters[1] == NULL ) { /* Try to split the conversion. */ i_nb_conversions = SplitConversion( &pp_filters[0]->output, p_output_format, &temp_format ); if ( !i_nb_conversions ) { vlc_object_detach( pp_filters[0] ); vlc_object_destroy( pp_filters[0] ); msg_Err( p_aout, "couldn't find a filter for the second part of the conversion" ); } pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, &temp_format ); pp_filters[2] = FindFilter( p_aout, &temp_format, p_output_format ); if ( pp_filters[1] == NULL || pp_filters[2] == NULL ) { vlc_object_detach( pp_filters[0] ); vlc_object_destroy( pp_filters[0] ); if ( pp_filters[1] != NULL ) { vlc_object_detach( pp_filters[1] ); vlc_object_destroy( pp_filters[1] ); } if ( pp_filters[2] != NULL ) { vlc_object_detach( pp_filters[2] ); vlc_object_destroy( pp_filters[2] ); } msg_Err( p_aout, "couldn't find filters for the second part of the conversion" ); } *pi_nb_filters = 3; } else { *pi_nb_filters = 2; } /* We have enough filters. */ msg_Dbg( p_aout, "found %d filters for the whole conversion", *pi_nb_filters ); return 0; }
/***************************************************************************** * Open: initializes demux structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; uint8_t *p_peek; module_t *p_id3; int b_forced = VLC_FALSE; if( p_demux->psz_path ) { int i_len = strlen( p_demux->psz_path ); if( i_len > 4 && !strcasecmp( &p_demux->psz_path[i_len - 4], ".aac" ) ) { b_forced = VLC_TRUE; } } if( !p_demux->b_force && !b_forced ) { return VLC_EGENERIC; } /* skip possible id3 header */ if( ( p_id3 = module_Need( p_demux, "id3", NULL, 0 ) ) ) { module_Unneed( p_demux, p_id3 ); } /* peek the begining (10 is for adts header) */ if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) { msg_Err( p_demux, "cannot peek" ); return VLC_EGENERIC; } if( !strncmp( p_peek, "ADIF", 4 ) ) { msg_Err( p_demux, "ADIF file. Not yet supported. (Please report)" ); return VLC_EGENERIC; } p_demux->pf_demux = Demux; p_demux->pf_control= Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->p_es = NULL; p_sys->b_start = VLC_TRUE; /* * Load the mpeg 4 audio packetizer */ p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_PACKETIZER ); p_sys->p_packetizer->pf_decode_audio = NULL; p_sys->p_packetizer->pf_decode_video = NULL; p_sys->p_packetizer->pf_decode_sub = NULL; p_sys->p_packetizer->pf_packetize = NULL; es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES, VLC_FOURCC( 'm', 'p', '4', 'a' ) ); es_format_Init( &p_sys->p_packetizer->fmt_out, UNKNOWN_ES, 0 ); p_sys->p_packetizer->p_module = module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 ); if( p_sys->p_packetizer->p_module == NULL) { vlc_object_destroy( p_sys->p_packetizer ); msg_Err( p_demux, "cannot find mp4a packetizer" ); free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * Stress: perform various stress tests *****************************************************************************/ static int Stress( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { vlc_object_t **pp_objects; mtime_t start; char ** ppsz_name; char * psz_blob; int i, i_level; if( *newval.psz_string ) { i_level = atoi( newval.psz_string ); if( i_level <= 0 ) { i_level = 1; } else if( i_level > 200 ) { /* It becomes quite dangerous above 150 */ i_level = 200; } } else { i_level = 10; } /* Allocate required data */ ppsz_name = malloc( MAXVAR * i_level * sizeof(char*) ); psz_blob = malloc( 20 * MAXVAR * i_level * sizeof(char) ); for( i = 0; i < MAXVAR * i_level; i++ ) { ppsz_name[i] = psz_blob + 20 * i; } pp_objects = malloc( MAXOBJ * i_level * sizeof(void*) ); /* * Test #1: objects */ printf( "Test #1: objects\n" ); printf( " - creating %i objects\n", MAXOBJ * i_level ); start = mdate(); for( i = 0; i < MAXOBJ * i_level; i++ ) { pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); } printf( " - randomly looking up %i objects\n", MAXLOOK * i_level ); for( i = MAXLOOK * i_level; i--; ) { int id = (int) (MAXOBJ * i_level * 1.0 * rand() / (RAND_MAX)); vlc_object_get( p_this, pp_objects[id]->i_object_id ); vlc_object_release( p_this ); } printf( " - destroying the objects (LIFO)\n" ); for( i = MAXOBJ * i_level; i--; ) { vlc_object_destroy( pp_objects[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* * Test #2: integer variables */ printf( "Test #2: integer variables\n" ); printf( " - creating %i integer variables\n", MAXVAR * i_level ); start = mdate(); for( i = 0; i < MAXVAR * i_level; i++ ) { sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 ); var_Create( p_this, ppsz_name[i], VLC_VAR_INTEGER ); } printf( " - randomly assigning %i values\n", MAXSET * i_level ); for( i = 0; i < MAXSET * i_level; i++ ) { int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX)); var_Set( p_this, ppsz_name[v], (vlc_value_t)i ); } printf( " - destroying the variables\n" ); for( i = 0; i < MAXVAR * i_level; i++ ) { var_Destroy( p_this, ppsz_name[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* * Test #3: string variables */ printf( "Test #3: string variables\n" ); printf( " - creating %i string variables\n", MAXVAR * i_level ); start = mdate(); for( i = 0; i < MAXVAR * i_level; i++ ) { sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 ); var_Create( p_this, ppsz_name[i], VLC_VAR_STRING ); } printf( " - randomly assigning %i values\n", MAXSET * i_level ); for( i = 0; i < MAXSET * i_level; i++ ) { int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX)); var_Set( p_this, ppsz_name[v], (vlc_value_t)ppsz_name[v] ); } printf( " - destroying the variables\n" ); for( i = 0; i < MAXVAR * i_level; i++ ) { var_Destroy( p_this, ppsz_name[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* * Test #4: threads */ printf( "Test #4: threads\n" ); start = mdate(); printf( " - spawning %i threads that will each create %i objects\n", MAXTH * i_level, MAXOBJ/MAXTH ); for( i = 0; i < MAXTH * i_level; i++ ) { pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); vlc_thread_create( pp_objects[i], "foo", Dummy, 0, VLC_TRUE ); } printf( " - killing the threads (LIFO)\n" ); for( i = MAXTH * i_level; i--; ) { pp_objects[i]->b_die = VLC_TRUE; vlc_thread_join( pp_objects[i] ); vlc_object_destroy( pp_objects[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* Free required data */ free( pp_objects ); free( psz_blob ); free( ppsz_name ); return VLC_SUCCESS; }
/** * Create playlist * * Create a playlist structure. * \param p_parent the vlc object that is to be the parent of this playlist * \return a pointer to the created playlist, or NULL on error */ playlist_t * __playlist_Create ( vlc_object_t *p_parent ) { playlist_t *p_playlist; vlc_value_t val; /* Allocate structure */ p_playlist = vlc_object_create( p_parent, VLC_OBJECT_PLAYLIST ); if( !p_playlist ) { msg_Err( p_parent, "out of memory" ); return NULL; } var_Create( p_playlist, "intf-change", VLC_VAR_BOOL ); val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-change", val ); var_Create( p_playlist, "item-change", VLC_VAR_INTEGER ); val.i_int = -1; var_Set( p_playlist, "item-change", val ); var_Create( p_playlist, "playlist-current", VLC_VAR_INTEGER ); val.i_int = -1; var_Set( p_playlist, "playlist-current", val ); var_Create( p_playlist, "intf-popupmenu", VLC_VAR_BOOL ); var_Create( p_playlist, "intf-show", VLC_VAR_BOOL ); val.b_bool = VLC_TRUE; var_Set( p_playlist, "intf-show", val ); var_Create( p_playlist, "prevent-skip", VLC_VAR_BOOL ); val.b_bool = VLC_FALSE; var_Set( p_playlist, "prevent-skip", val ); var_Create( p_playlist, "play-and-stop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_playlist, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_playlist, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_playlist, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); p_playlist->p_input = NULL; p_playlist->i_status = PLAYLIST_STOPPED; p_playlist->i_index = -1; p_playlist->i_size = 0; p_playlist->pp_items = NULL; p_playlist->i_groups = 0; p_playlist->pp_groups = NULL; p_playlist->i_last_group = 0; p_playlist->i_last_id = 0; p_playlist->i_sort = SORT_ID; p_playlist->i_order = ORDER_NORMAL; playlist_CreateGroup( p_playlist, _("Normal") ); if( vlc_thread_create( p_playlist, "playlist", RunThread, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) { msg_Err( p_playlist, "cannot spawn playlist thread" ); vlc_object_destroy( p_playlist ); return NULL; } /* The object has been initialized, now attach it */ vlc_object_attach( p_playlist, p_parent ); return p_playlist; }
/***************************************************************************** * RunThread: main playlist thread *****************************************************************************/ static void RunThread ( playlist_t *p_playlist ) { vlc_object_t *p_obj; vlc_value_t val; mtime_t i_vout_destroyed_date = 0; mtime_t i_sout_destroyed_date = 0; playlist_item_t *p_autodelete_item = 0; /* Tell above that we're ready */ vlc_thread_ready( p_playlist ); while( !p_playlist->b_die ) { vlc_mutex_lock( &p_playlist->object_lock ); /* If there is an input, check that it doesn't need to die. */ if( p_playlist->p_input ) { /* This input is dead. Remove it ! */ if( p_playlist->p_input->b_dead ) { input_thread_t *p_input; p_input = p_playlist->p_input; p_playlist->p_input = NULL; /* Release the playlist lock, because we may get stuck * in input_DestroyThread() for some time. */ vlc_mutex_unlock( &p_playlist->object_lock ); /* Destroy input */ input_DestroyThread( p_input ); /* Unlink current input * (_after_ input_DestroyThread for vout garbage collector) */ vlc_object_detach( p_input ); /* Destroy object */ vlc_object_destroy( p_input ); i_vout_destroyed_date = 0; i_sout_destroyed_date = 0; /* Check for autodeletion */ if( p_autodelete_item ) { playlist_ItemDelete( p_autodelete_item ); p_autodelete_item = 0; } continue; } /* This input is dying, let him do */ else if( p_playlist->p_input->b_die ) { ; } /* This input has finished, ask him to die ! */ else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof ) { input_StopThread( p_playlist->p_input ); if( p_playlist->pp_items[p_playlist->i_index]->b_autodeletion ) { /* This ain't pretty but hey it works */ p_autodelete_item = p_playlist->pp_items[p_playlist->i_index]; p_playlist->pp_items[p_playlist->i_index] = playlist_ItemNew( p_playlist, p_autodelete_item->input.psz_uri, 0); vlc_mutex_unlock( &p_playlist->object_lock ); p_playlist->i_status = PLAYLIST_STOPPED; playlist_Delete( p_playlist, p_playlist->i_index ); p_playlist->i_status = PLAYLIST_RUNNING; vlc_mutex_lock( &p_playlist->object_lock ); } SkipItem( p_playlist, 1 ); vlc_mutex_unlock( &p_playlist->object_lock ); continue; } else if( p_playlist->p_input->i_state != INIT_S ) { vlc_mutex_unlock( &p_playlist->object_lock ); i_vout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, i_vout_destroyed_date ); i_sout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, i_sout_destroyed_date ); vlc_mutex_lock( &p_playlist->object_lock ); } } else if( p_playlist->i_status != PLAYLIST_STOPPED ) { /* Start another input. Let's check if that item has * been forced. In that case, we override random (by not skipping) * and play-and-stop */ vlc_bool_t b_forced; var_Get( p_playlist, "prevent-skip", &val ); b_forced = val.b_bool; if( val.b_bool == VLC_FALSE ) { SkipItem( p_playlist, 0 ); } /* Reset forced status */ val.b_bool = VLC_FALSE; var_Set( p_playlist, "prevent-skip", val ); /* Check for play-and-stop */ var_Get( p_playlist, "play-and-stop", &val ); if( val.b_bool == VLC_FALSE || b_forced == VLC_TRUE ) { PlayItem( p_playlist ); } } else if( p_playlist->i_status == PLAYLIST_STOPPED ) { vlc_mutex_unlock( &p_playlist->object_lock ); i_sout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, mdate() ); i_vout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, mdate() ); vlc_mutex_lock( &p_playlist->object_lock ); } vlc_mutex_unlock( &p_playlist->object_lock ); msleep( INTF_IDLE_SLEEP ); } /* If there is an input, kill it */ while( 1 ) { vlc_mutex_lock( &p_playlist->object_lock ); if( p_playlist->p_input == NULL ) { vlc_mutex_unlock( &p_playlist->object_lock ); break; } if( p_playlist->p_input->b_dead ) { input_thread_t *p_input; /* Unlink current input */ p_input = p_playlist->p_input; p_playlist->p_input = NULL; vlc_mutex_unlock( &p_playlist->object_lock ); /* Destroy input */ input_DestroyThread( p_input ); /* Unlink current input (_after_ input_DestroyThread for vout * garbage collector)*/ vlc_object_detach( p_input ); /* Destroy object */ vlc_object_destroy( p_input ); continue; } else if( p_playlist->p_input->b_die ) { /* This input is dying, leave him alone */ ; } else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof ) { input_StopThread( p_playlist->p_input ); vlc_mutex_unlock( &p_playlist->object_lock ); continue; } else { p_playlist->p_input->b_eof = 1; } vlc_mutex_unlock( &p_playlist->object_lock ); msleep( INTF_IDLE_SLEEP ); } /* close all remaining sout */ while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD ) ) ) { vlc_object_release( p_obj ); sout_DeleteInstance( (sout_instance_t*)p_obj ); } /* close all remaining vout */ while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_VOUT, FIND_CHILD ) ) ) { vlc_object_detach( p_obj ); vlc_object_release( p_obj ); vout_Destroy( (vout_thread_t *)p_obj ); } }
static void ReleaseFilter( aout_filter_t * p_filter ) { module_Unneed( p_filter, p_filter->p_module ); vlc_object_detach( p_filter ); vlc_object_destroy( p_filter ); }
/***************************************************************************** * Init: initialize logo video thread output method *****************************************************************************/ static int Init( vout_thread_t *p_vout ) { vout_sys_t *p_sys = p_vout->p_sys; picture_t *p_pic; int i_index; I_OUTPUTPICTURES = 0; /* Initialize the output structure */ p_vout->output.i_chroma = p_vout->render.i_chroma; p_vout->output.i_width = p_vout->render.i_width; p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; /* Load the video blending filter */ p_sys->p_blend = vlc_object_create( p_vout, sizeof(filter_t) ); vlc_object_attach( p_sys->p_blend, p_vout ); p_sys->p_blend->fmt_out.video.i_x_offset = p_sys->p_blend->fmt_out.video.i_y_offset = 0; p_sys->p_blend->fmt_in.video.i_x_offset = p_sys->p_blend->fmt_in.video.i_y_offset = 0; p_sys->p_blend->fmt_out.video.i_aspect = p_vout->render.i_aspect; p_sys->p_blend->fmt_out.video.i_chroma = p_vout->output.i_chroma; p_sys->p_blend->fmt_in.video.i_chroma = VLC_FOURCC('Y','U','V','A'); p_sys->p_blend->fmt_in.video.i_aspect = VOUT_ASPECT_FACTOR; p_sys->p_blend->fmt_in.video.i_width = p_sys->p_blend->fmt_in.video.i_visible_width = p_sys->p_pic->p[Y_PLANE].i_visible_pitch; p_sys->p_blend->fmt_in.video.i_height = p_sys->p_blend->fmt_in.video.i_visible_height = p_sys->p_pic->p[Y_PLANE].i_visible_lines; p_sys->p_blend->fmt_out.video.i_width = p_sys->p_blend->fmt_out.video.i_visible_width = p_vout->output.i_width; p_sys->p_blend->fmt_out.video.i_height = p_sys->p_blend->fmt_out.video.i_visible_height = p_vout->output.i_height; p_sys->p_blend->p_module = module_Need( p_sys->p_blend, "video blending", 0, 0 ); if( !p_sys->p_blend->p_module ) { msg_Err( p_vout, "can't open blending filter, aborting" ); vlc_object_detach( p_sys->p_blend ); vlc_object_destroy( p_sys->p_blend ); return VLC_EGENERIC; } if( p_sys->posx < 0 || p_sys->posy < 0 ) { p_sys->posx = 0; p_sys->posy = 0; if( p_sys->pos & SUBPICTURE_ALIGN_BOTTOM ) { p_sys->posy = p_vout->render.i_height - p_sys->i_height; } else if ( !(p_sys->pos & SUBPICTURE_ALIGN_TOP) ) { p_sys->posy = p_vout->render.i_height / 2 - p_sys->i_height / 2; } if( p_sys->pos & SUBPICTURE_ALIGN_RIGHT ) { p_sys->posx = p_vout->render.i_width - p_sys->i_width; } else if ( !(p_sys->pos & SUBPICTURE_ALIGN_LEFT) ) { p_sys->posx = p_vout->render.i_width / 2 - p_sys->i_width / 2; } } /* Try to open the real video output */ msg_Dbg( p_vout, "spawning the real video output" ); p_sys->p_vout = vout_Create( p_vout, p_vout->render.i_width, p_vout->render.i_height, p_vout->render.i_chroma, p_vout->render.i_aspect ); /* Everything failed */ if( p_sys->p_vout == NULL ) { msg_Err( p_vout, "can't open vout, aborting" ); return VLC_EGENERIC; } var_AddCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout); var_AddCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout); ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES ); ADD_CALLBACKS( p_sys->p_vout, SendEvents ); ADD_PARENT_CALLBACKS( SendEventsToChild ); return VLC_SUCCESS; }
/***************************************************************************** * Open: initializes demux structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; vlc_bool_t b_forced = VLC_FALSE; uint8_t *p_peek; es_format_t fmt; if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) { msg_Err( p_demux, "cannot peek" ); return VLC_EGENERIC; } if( !strncmp( p_demux->psz_demux, "mpgv", 4 ) ) { b_forced = VLC_TRUE; } if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 ) { if( !b_forced ) { msg_Warn( p_demux, "ES module discarded (no startcode)" ); return VLC_EGENERIC; } msg_Err( p_demux, "this doesn't look like an MPEG ES stream, continuing" ); } if( p_peek[3] > 0xb9 ) { if( !b_forced ) { msg_Warn( p_demux, "ES module discarded (system startcode)" ); return VLC_EGENERIC; } msg_Err( p_demux, "this seems to be a system stream (PS plug-in ?), but continuing" ); } p_demux->pf_demux = Demux; p_demux->pf_control= Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->b_start = VLC_TRUE; p_sys->p_es = NULL; /* * Load the mpegvideo packetizer */ p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_PACKETIZER ); p_sys->p_packetizer->pf_decode_audio = NULL; p_sys->p_packetizer->pf_decode_video = NULL; p_sys->p_packetizer->pf_decode_sub = NULL; p_sys->p_packetizer->pf_packetize = NULL; es_format_Init( &p_sys->p_packetizer->fmt_in, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) ); es_format_Init( &p_sys->p_packetizer->fmt_out, UNKNOWN_ES, 0 ); p_sys->p_packetizer->p_module = module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 ); if( p_sys->p_packetizer->p_module == NULL) { vlc_object_destroy( p_sys->p_packetizer ); msg_Err( p_demux, "cannot find mpgv packetizer" ); free( p_sys ); return VLC_EGENERIC; } /* * create the output */ es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) ); p_sys->p_es = es_out_Add( p_demux->out, &fmt ); return VLC_SUCCESS; }
/***************************************************************************** * Thread: *****************************************************************************/ static void Thread( vlc_object_t *p_this ) { galaktos_thread_t *p_thread = (galaktos_thread_t*)p_this; int count=0; double realfps=0,fpsstart=0; int timed=0; int timestart=0; int mspf=0; /* Get on OpenGL provider */ p_thread->p_opengl = (vout_thread_t *)vlc_object_create( p_this, VLC_OBJECT_OPENGL ); if( p_thread->p_opengl == NULL ) { msg_Err( p_thread, "out of memory" ); return; } vlc_object_attach( p_thread->p_opengl, p_this ); /* Initialize vout parameters */ vout_InitFormat( &p_thread->p_opengl->fmt_in, VLC_FOURCC('R','V','3','2'), p_thread->i_width, p_thread->i_height, 1 ); p_thread->p_opengl->i_window_width = p_thread->i_width; p_thread->p_opengl->i_window_height = p_thread->i_height; p_thread->p_opengl->render.i_width = p_thread->i_width; p_thread->p_opengl->render.i_height = p_thread->i_width; p_thread->p_opengl->render.i_aspect = VOUT_ASPECT_FACTOR; p_thread->p_opengl->b_scale = VLC_TRUE; p_thread->p_opengl->b_fullscreen = VLC_FALSE; p_thread->p_opengl->i_alignment = 0; p_thread->p_opengl->fmt_in.i_sar_num = 1; p_thread->p_opengl->fmt_in.i_sar_den = 1; p_thread->p_opengl->fmt_render = p_thread->p_opengl->fmt_in; p_thread->p_module = module_Need( p_thread->p_opengl, "opengl provider", NULL, 0 ); if( p_thread->p_module == NULL ) { msg_Err( p_thread, "unable to initialize OpenGL" ); vlc_object_detach( p_thread->p_opengl ); vlc_object_destroy( p_thread->p_opengl ); return; } p_thread->p_opengl->pf_init( p_thread->p_opengl ); setup_opengl( p_thread->i_width, p_thread->i_height ); CreateRenderTarget(512, &RenderTargetTextureID, NULL); timestart=mdate()/1000; while( !p_thread->b_die ) { mspf = 1000 / 60; if( galaktos_update( p_thread ) == 1 ) { p_thread->b_die = 1; } if( p_thread->psz_title ) { free( p_thread->psz_title ); p_thread->psz_title = NULL; } if (++count%100==0) { realfps=100/((mdate()/1000-fpsstart)/1000); // printf("%f\n",realfps); fpsstart=mdate()/1000; } //framerate limiter timed=mspf-(mdate()/1000-timestart); // printf("%d,%d\n",time,mspf); if (timed>0) msleep(1000*timed); // printf("Limiter %d\n",(mdate()/1000-timestart)); timestart=mdate()/1000; } /* Free the openGL provider */ module_Unneed( p_thread->p_opengl, p_thread->p_module ); vlc_object_detach( p_thread->p_opengl ); vlc_object_destroy( p_thread->p_opengl ); }