X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Finput_programs.c;h=ddff45529212f1da49f3388715d566a54c82c4db;hb=647cca0ebb2e897a570018ba80483bb81a7d90c6;hp=d99287c22a5dc38677c99d9130734d201306401c;hpb=67bc00c9b61ba1b8235345b316711568b737f387;p=vlc diff --git a/src/input/input_programs.c b/src/input/input_programs.c index d99287c22a..ddff455292 100644 --- a/src/input/input_programs.c +++ b/src/input/input_programs.c @@ -2,6 +2,7 @@ * input_programs.c: es_descriptor_t, pgrm_descriptor_t management ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN + * $Id: input_programs.c,v 1.26 2001/01/18 05:13:22 sam Exp $ * * Authors: * @@ -40,6 +41,8 @@ #include "input_ext-dec.h" #include "input.h" +#include "main.h" /* --noaudio --novideo */ + /* * NOTICE : all of these functions expect you to have taken the lock on * p_input->stream.lock @@ -50,16 +53,59 @@ *****************************************************************************/ void input_InitStream( input_thread_t * p_input, size_t i_data_len ) { - p_input->stream.i_pgrm_number = 0; + p_input->stream.i_stream_id = 0; + p_input->stream.pp_es = NULL; + p_input->stream.pp_selected_es = NULL; p_input->stream.pp_programs = NULL; if( i_data_len ) { - p_input->stream.p_demux_data = malloc( i_data_len ); + if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL ) + { + intf_ErrMsg( "Unable to allocate memory in input_InitStream"); + /* FIXME : find a way to tell if failed */ + return; + } memset( p_input->stream.p_demux_data, 0, i_data_len ); } } +/***************************************************************************** + * input_EndStream: free all stream descriptors + *****************************************************************************/ +void input_EndStream( input_thread_t * p_input ) +{ + /* Free all programs and associated ES, and associated decoders. */ + while( p_input->stream.i_pgrm_number ) + { + input_DelProgram( p_input, p_input->stream.pp_programs[0] ); + } + + /* Free standalone ES */ + while( p_input->stream.i_es_number ) + { + input_DelES( p_input, p_input->stream.pp_es[0] ); + } +} + +/***************************************************************************** + * input_FindProgram: returns a pointer to a program described by its ID + *****************************************************************************/ +pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id ) +{ + int i; + + for( i = 0; i < p_input->stream.i_pgrm_number; i++ ) + { + if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id ) + { + return p_input->stream.pp_programs[i]; + } + } + + return( NULL ); +} + /***************************************************************************** * input_AddProgram: add and init a program descriptor ***************************************************************************** @@ -78,14 +124,25 @@ pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input, p_input->stream.pp_programs = realloc( p_input->stream.pp_programs, p_input->stream.i_pgrm_number * sizeof(pgrm_descriptor_t *) ); - + if( p_input->stream.pp_programs == NULL ) + { + intf_ErrMsg( "Unable to realloc memory in input_AddProgram" ); + return( NULL ); + } + /* Allocate the structure to store this description */ p_input->stream.pp_programs[i_pgrm_index] = malloc( sizeof(pgrm_descriptor_t) ); - + if( p_input->stream.pp_programs[i_pgrm_index] == NULL ) + { + intf_ErrMsg( "Unable to allocate memory in input_AddProgram" ); + return( NULL ); + } + /* Init this entry */ p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id; p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0; + p_input->stream.pp_programs[i_pgrm_index]->i_version = 0; p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0; p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL; @@ -107,6 +164,11 @@ pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input, { p_input->stream.pp_programs[i_pgrm_index]->p_demux_data = malloc( i_data_len ); + if( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data == NULL ) + { + intf_ErrMsg( "Unable to allocate memory in input_AddProgram" ); + return( NULL ); + } memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0, i_data_len ); } @@ -119,53 +181,69 @@ pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input, ***************************************************************************** * All ES descriptions referenced in the descriptor will be deleted. *****************************************************************************/ -void input_DelProgram( input_thread_t * p_input, u16 i_pgrm_id ) +void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm ) { - int i_index, i_pgrm_index = -1; - pgrm_descriptor_t * p_pgrm = NULL; + int i_pgrm_index; - intf_DbgMsg("Deleting description for pgrm %d", i_pgrm_id); + ASSERT( p_pgrm ); - /* Find where this program is described */ - for( i_index = 0; i_index < p_input->stream.i_pgrm_number; i_index++ ) - { - if( p_input->stream.pp_programs[i_index]->i_number == i_pgrm_id ) - { - i_pgrm_index = i_index; - p_pgrm = p_input->stream.pp_programs[ i_pgrm_index ]; - break; - } - } - - /* Make sure that the pgrm exists */ - ASSERT(i_pgrm_index >= 0); - ASSERT(p_pgrm); + intf_DbgMsg("Deleting description for pgrm %d", p_pgrm->i_number); /* Free the structures that describe the es that belongs to that program */ - for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ ) + while( p_pgrm->i_es_number ) { - input_DelES( p_input, p_pgrm->pp_es[i_index]->i_id ); + input_DelES( p_input, p_pgrm->pp_es[0] ); } - /* Free the table of es descriptors */ - free( p_pgrm->pp_es ); - /* Free the demux data */ if( p_pgrm->p_demux_data != NULL ) { free( p_pgrm->p_demux_data ); } - /* Free the description of this stream */ - free( p_pgrm ); + /* Find the program in the programs table */ + for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number; + i_pgrm_index++ ) + { + if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm ) + break; + } /* Remove this program from the stream's list of programs */ p_input->stream.i_pgrm_number--; + p_input->stream.pp_programs[i_pgrm_index] = p_input->stream.pp_programs[p_input->stream.i_pgrm_number]; p_input->stream.pp_programs = realloc( p_input->stream.pp_programs, p_input->stream.i_pgrm_number * sizeof(pgrm_descriptor_t *) ); + + if( p_input->stream.i_pgrm_number && p_input->stream.pp_programs == NULL) + { + intf_ErrMsg( "input error: unable to realloc program list" + " in input_DelProgram" ); + } + + /* Free the description of this program */ + free( p_pgrm ); +} + +/***************************************************************************** + * input_FindES: returns a pointer to an ES described by its ID + *****************************************************************************/ +es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id ) +{ + int i; + + for( i = 0; i < p_input->stream.i_es_number; i++ ) + { + if( p_input->stream.pp_es[i]->i_id == i_es_id ) + { + return p_input->stream.pp_es[i]; + } + } + + return( NULL ); } /***************************************************************************** @@ -179,53 +257,66 @@ es_descriptor_t * input_AddES( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm, u16 i_es_id, size_t i_data_len ) { - int i_index; - es_descriptor_t * p_es = NULL; + es_descriptor_t * p_es; - intf_DbgMsg("Adding description for ES %d", i_es_id); + intf_DbgMsg("Adding description for ES 0x%x", i_es_id); - /* Find an empty slot to store the description of that es */ - for( i_index = 0; i_index < INPUT_MAX_ES && - p_input->p_es[i_index].i_id != EMPTY_ID; i_index++ ); - - if( i_index >= INPUT_MAX_ES ) + p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) ); + if( p_es == NULL ) { - /* No slot is empty */ - intf_ErrMsg("Stream carries too many ES for our decoder"); + intf_ErrMsg( "Unable to allocate memory in input_AddES" ); + return( NULL); } - else + p_input->stream.i_es_number++; + p_input->stream.pp_es = realloc( p_input->stream.pp_es, + p_input->stream.i_es_number + * sizeof(es_descriptor_t *) ); + if( p_input->stream.pp_es == NULL ) { - /* Reserve the slot for that ES */ - p_es = &p_input->p_es[i_index]; - p_es->i_id = i_es_id; - intf_DbgMsg("Slot %d in p_es table assigned to ES %d", - i_index, i_es_pid); + intf_ErrMsg( "Unable to realloc memory in input_AddES" ); + return( NULL ); + } + p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es; + p_es->i_id = i_es_id; - /* Init its values */ - p_es->b_discontinuity = 0; - p_es->p_pes = NULL; - p_es->p_decoder_fifo = NULL; + /* Init its values */ + p_es->b_discontinuity = 0; + p_es->p_pes = NULL; + p_es->p_decoder_fifo = NULL; - if( i_data_len ) + if( i_data_len ) + { + p_es->p_demux_data = malloc( i_data_len ); + if( p_es->p_demux_data == NULL ) { - p_es->p_demux_data = malloc( i_data_len ); - memset( p_es->p_demux_data, 0, i_data_len ); + intf_ErrMsg( "Unable to allocate memory in input_AddES" ); + return( NULL ); } + memset( p_es->p_demux_data, 0, i_data_len ); + } + else + { + p_es->p_demux_data = NULL; + } - /* Add this ES to the program definition if one is given */ - if( p_pgrm ) - { - p_pgrm->i_es_number++; - p_pgrm->pp_es = realloc( p_pgrm->pp_es, - p_pgrm->i_es_number - * sizeof(es_descriptor_t *) ); - p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es; - p_es->p_pgrm = p_pgrm; - } - else + /* Add this ES to the program definition if one is given */ + if( p_pgrm ) + { + p_pgrm->i_es_number++; + p_pgrm->pp_es = realloc( p_pgrm->pp_es, + p_pgrm->i_es_number + * sizeof(es_descriptor_t *) ); + if( p_pgrm->pp_es == NULL ) { - p_es->p_pgrm = NULL; + intf_ErrMsg( "Unable to realloc memory in input_AddES" ); + return( NULL ); } + p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es; + p_es->p_pgrm = p_pgrm; + } + else + { + p_es->p_pgrm = NULL; } return p_es; @@ -234,53 +325,108 @@ es_descriptor_t * input_AddES( input_thread_t * p_input, /***************************************************************************** * input_DelES: *****************************************************************************/ -void input_DelES( input_thread_t * p_input, u16 i_id ) +void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es ) { - int i_index; - pgrm_descriptor_t * p_pgrm = NULL; - es_descriptor_t * p_es = NULL; + int i_index, i_es_index; + pgrm_descriptor_t * p_pgrm; - /* Look for the description of the ES */ - for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ ) + ASSERT( p_es ); + p_pgrm = p_es->p_pgrm; + + /* Kill associated decoder, if any. */ + if( p_es->p_decoder_fifo != NULL ) { - if( p_input->p_es[i_index].i_id == i_id ) - { - p_es = &p_input->p_es[i_index]; - p_pgrm = p_input->p_es[i_index].p_pgrm; - break; - } + input_EndDecoder( p_input, p_es ); } - ASSERT( p_es ); - /* Remove this ES from the description of the program if it is associated to * one */ if( p_pgrm ) { - for( i_index = 0; ; i_index++ ) + for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ ) { - if( p_pgrm->pp_es[i_index]->i_id == i_id ) + if( p_pgrm->pp_es[i_index] == p_es ) { p_pgrm->i_es_number--; p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number]; p_pgrm->pp_es = realloc( p_pgrm->pp_es, p_pgrm->i_es_number * sizeof(es_descriptor_t *)); + if( p_pgrm->i_es_number && p_pgrm->pp_es == NULL ) + { + intf_ErrMsg( "Unable to realloc memory in input_DelES" ); + } break; } } } - /* The table of stream descriptors is static, so don't free memory - * but just mark the slot as unused */ - p_es->i_id = EMPTY_ID; - /* Free the demux data */ if( p_es->p_demux_data != NULL ) { free( p_es->p_demux_data ); } + + /* Find the ES in the ES table */ + for( i_es_index = 0; i_es_index < p_input->stream.i_es_number; + i_es_index++ ) + { + if( p_input->stream.pp_es[i_es_index] == p_es ) + break; + } + + /* Free the ES */ + free( p_es ); + p_input->stream.i_es_number--; + p_input->stream.pp_es[i_es_index] = + p_input->stream.pp_es[p_input->stream.i_es_number]; + p_input->stream.pp_es = realloc( p_input->stream.pp_es, + p_input->stream.i_es_number + * sizeof(es_descriptor_t *)); + if( p_input->stream.i_es_number && p_input->stream.pp_es == NULL ) + { + intf_ErrMsg( "Unable to realloc memory in input_DelES" ); + } + +} + +#ifdef STATS +/***************************************************************************** + * input_DumpStream: dumps the contents of a stream descriptor + *****************************************************************************/ +void input_DumpStream( input_thread_t * p_input ) +{ + int i, j; +#define S p_input->stream + intf_Msg( "input info: Dumping stream ID 0x%x", S.i_stream_id ); + if( S.b_seekable ) + intf_Msg( "input info: seekable stream, position: %d/%d", + S.i_tell, S.i_size ); + else + intf_Msg( "input info: %s", S.b_pace_control ? "pace controlled" : + "pace un-controlled" ); +#undef S + for( i = 0; i < p_input->stream.i_pgrm_number; i++ ) + { +#define P p_input->stream.pp_programs[i] + intf_Msg( "input info: Dumping program 0x%x, version %d (%s)", + P->i_number, P->i_version, + P->b_is_ok ? "complete" : "partial" ); + if( P->i_synchro_state == SYNCHRO_OK ) + intf_Msg( "input info: synchro absolute delta : %lld (jitter : %lld)", + P->delta_absolute, P->delta_cr ); +#undef P + for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ ) + { +#define ES p_input->stream.pp_programs[i]->pp_es[j] + intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s", + ES->i_id, ES->i_stream_id, ES->i_type, + ES->p_decoder_fifo != NULL ? "selected" : "not selected"); +#undef ES + } + } } +#endif /***************************************************************************** * InitDecConfig: initializes a decoder_config_t @@ -288,7 +434,7 @@ void input_DelES( input_thread_t * p_input, u16 i_id ) static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es, decoder_config_t * p_config ) { - p_config->i_stream_id = p_es->i_stream_id; + p_config->i_id = p_es->i_id; p_config->i_type = p_es->i_type; p_config->p_stream_ctrl = &p_input->stream.control; @@ -304,7 +450,7 @@ static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es, vlc_mutex_init(&p_config->p_decoder_fifo->data_lock); vlc_cond_init(&p_config->p_decoder_fifo->data_wait); p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0; - p_config->p_decoder_fifo->b_die = 0; + p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0; p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data; p_config->p_decoder_fifo->pf_delete_pes = p_input->p_plugin->pf_delete_pes; @@ -324,11 +470,16 @@ static vdec_config_t * GetVdecConfig( input_thread_t * p_input, vdec_config_t * p_config; p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) ); + if( p_config == NULL ) + { + intf_ErrMsg( "Unable to allocate memory in GetVdecConfig" ); + return( NULL ); + } p_config->p_vout = p_input->p_default_vout; if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 ) { free( p_config ); - return NULL; + return( NULL ); } return( p_config ); @@ -342,12 +493,17 @@ static adec_config_t * GetAdecConfig( input_thread_t * p_input, { adec_config_t * p_config; - p_config = (adec_config_t *)malloc( sizeof(adec_config_t) ); + p_config = (adec_config_t *)malloc( sizeof(adec_config_t)); + if( p_config == NULL ) + { + intf_ErrMsg( "Unable to allocate memory in GetAdecConfig" ); + return( NULL ); + } p_config->p_aout = p_input->p_default_aout; if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 ) { free( p_config ); - return NULL; + return( NULL ); } return( p_config ); @@ -356,13 +512,19 @@ static adec_config_t * GetAdecConfig( input_thread_t * p_input, /***************************************************************************** * input_SelectES: selects an ES and spawns the associated decoder *****************************************************************************/ +/* FIXME */ +vlc_thread_t adec_CreateThread( void * ); +vlc_thread_t ac3dec_CreateThread( void * ); +vlc_thread_t vpar_CreateThread( void * ); +vlc_thread_t spudec_CreateThread( void * ); + int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) { - int i; - es_descriptor_t ** p_spot = NULL; + /* FIXME ! */ + decoder_capabilities_t decoder; #ifdef DEBUG_INPUT - intf_DbgMsg( "Selecting ES %d", p_es->i_id ); + intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id ); #endif if( p_es->p_decoder_fifo != NULL ) @@ -371,37 +533,44 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) return( -1 ); } - /* Find a free spot in pp_selected_es. */ - for( i = 0; i < INPUT_MAX_SELECTED_ES; i++ ) - { - if( p_input->pp_selected_es[i] == NULL ) - { - p_spot = &p_input->pp_selected_es[i]; - break; - } - } - - if( p_spot == NULL ) - { - intf_ErrMsg( "Too many ES selected" ); - return( -1 ); - } - switch( p_es->i_type ) { - /* FIXME ! */ - case AC3_AUDIO_ES: - p_es->thread_id = ac3dec_CreateThread( GetAdecConfig( p_input, p_es ) ); - break; - case MPEG1_AUDIO_ES: case MPEG2_AUDIO_ES: - p_es->thread_id = adec_CreateThread( GetAdecConfig( p_input, p_es ) ); + if( p_main->b_audio ) + { + decoder.pf_create_thread = adec_CreateThread; + p_es->thread_id = input_RunDecoder( &decoder, + (void *)GetAdecConfig( p_input, p_es ) ); + } break; case MPEG1_VIDEO_ES: case MPEG2_VIDEO_ES: - p_es->thread_id = vpar_CreateThread( GetVdecConfig( p_input, p_es ) ); + if( p_main->b_video ) + { + decoder.pf_create_thread = vpar_CreateThread; + p_es->thread_id = input_RunDecoder( &decoder, + (void *)GetVdecConfig( p_input, p_es ) ); + } + break; + + case AC3_AUDIO_ES: + if( p_main->b_audio ) + { + decoder.pf_create_thread = ac3dec_CreateThread; + p_es->thread_id = input_RunDecoder( &decoder, + (void *)GetAdecConfig( p_input, p_es ) ); + } + break; + + case DVD_SPU_ES: + if( p_main->b_video ) + { + decoder.pf_create_thread = spudec_CreateThread; + p_es->thread_id = input_RunDecoder( &decoder, + (void *)GetVdecConfig( p_input, p_es ) ); + } break; default: @@ -410,6 +579,25 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) break; } - *p_spot = p_es; + if( p_es->thread_id == 0 ) + { + return( -1 ); + } + + if( p_es->p_decoder_fifo != NULL ) + { + p_input->stream.i_selected_es_number++; + p_input->stream.pp_selected_es = realloc( + p_input->stream.pp_selected_es, + p_input->stream.i_selected_es_number + * sizeof(es_descriptor_t *) ); + if( p_input->stream.pp_selected_es == NULL ) + { + intf_ErrMsg( "Unable to realloc memory in input_SelectES" ); + return(-1); + } + p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1] + = p_es; + } return( 0 ); }