system.c

来自「VLC媒体播放程序」· C语言 代码 · 共 1,499 行 · 第 1/4 页

C
1,499
字号
        {            /* stream_private_id */            i_pes_header_size += 1;        }        /* Now we've parsed the header, we just have to indicate in some         * specific data packets where the PES payload begins (renumber         * p_payload_start), so that the decoders can find the beginning         * of their data right out of the box. */        p_data = p_pes->p_first;        i_payload_size = p_data->p_payload_end                                 - p_data->p_payload_start;        while( i_pes_header_size > i_payload_size )        {            /* These packets are entirely filled by the PES header. */            i_pes_header_size -= i_payload_size;            p_data->p_payload_start = p_data->p_payload_end;            /* Go to the next data packet. */            if( (p_data = p_data->p_next) == NULL )            {                msg_Warn( p_input, "PES header bigger than payload" );                input_DeletePES( p_input->p_method_data, p_pes );                p_pes = NULL;                return;            }            i_payload_size = p_data->p_payload_end                                 - p_data->p_payload_start;        }        /* This last packet is partly header, partly payload. */        if( i_payload_size < i_pes_header_size )        {            msg_Warn( p_input, "PES header bigger than payload" );            input_DeletePES( p_input->p_method_data, p_pes );            p_pes = NULL;            return;        }        p_data->p_payload_start += i_pes_header_size;        /* Now we can eventually put the PES packet in the decoder's         * PES fifo */        if( p_es->p_dec != NULL )        {            input_DecodePES( p_es->p_dec, p_pes );        }        else if ( p_es->p_dec == NULL &&                   ((es_ts_data_t*)p_es->p_demux_data)->b_dvbsub)        {            es_descriptor_t* p_dvbsub;            uint8_t          i_count;            uint8_t         i;            i_count = ((es_ts_data_t*)p_es->p_demux_data)->i_dvbsub_es_count;            // If a language is selected, we send the packet to the decoder            for(i = 0; i < i_count; i++)            {                p_dvbsub = ((es_ts_data_t*)p_es->p_demux_data)->p_dvbsub_es[i];                if(p_dvbsub->p_dec !=NULL)                {                    input_DecodePES ( p_dvbsub->p_dec, p_pes );                    break;                }            }            if(i == i_count)            {                input_DeletePES( p_input->p_method_data, p_pes );            }        }        else        {            msg_Err( p_input, "no fifo to receive PES %p "                              "(who wrote this damn code ?)", p_pes );            input_DeletePES( p_input->p_method_data, p_pes );        }        p_pes = NULL;    }#undef p_pes}/***************************************************************************** * GatherPES: ***************************************************************************** * Gather a PES packet. *****************************************************************************/static void GatherPES( input_thread_t * p_input, data_packet_t * p_data,                       es_descriptor_t * p_es,                       vlc_bool_t b_unit_start, vlc_bool_t b_packet_lost ){#define p_pes (p_es->p_pes)    if( b_packet_lost && p_pes != NULL )    {        p_pes->b_discontinuity = 1;    }    if( b_unit_start && p_pes != NULL )    {        /* If the data packet contains the begining of a new PES packet, and         * if we were reassembling a PES packet, then the PES should be         * complete now, so parse its header and give it to the decoders. */        ParsePES( p_input, p_es );    }    if( !b_unit_start && p_pes == NULL )    {        /* Random access... */        input_DeletePacket( p_input->p_method_data, p_data );    }    else    {        if( b_unit_start )        {            /* If we are at the beginning of a new PES packet, we must fetch             * a new PES buffer to begin with the reassembly of this PES             * packet. This is also here that we can synchronize with the             * stream if we lost packets or if the decoder has just             * started. */            if( (p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )            {                msg_Err( p_input, "out of memory" );                p_input->b_error = 1;                return;            }            p_pes->i_rate = p_input->stream.control.i_rate;            p_pes->p_first = p_data;            /* If the PES header fits in the first data packet, we can             * already set p_gather->i_pes_real_size. */            if( p_data->p_payload_end - p_data->p_payload_start                    >= PES_HEADER_SIZE )            {                p_es->i_pes_real_size = ((uint16_t)p_data->p_payload_start[4] << 8)                                         + p_data->p_payload_start[5];                if ( p_es->i_pes_real_size )                {                    p_es->i_pes_real_size += 6;                }            }            else            {                p_es->i_pes_real_size = 0;            }        }        else        {            /* Update the relations between the data packets */            p_pes->p_last->p_next = p_data;        }        p_pes->p_last = p_data;        p_pes->i_nb_data++;        /* Size of the payload carried in the data packet */        p_pes->i_pes_size += (p_data->p_payload_end                                 - p_data->p_payload_start);        /* We can check if the packet is finished */        if( p_es->i_pes_real_size  && p_pes->i_pes_size >= p_es->i_pes_real_size )        {            if( p_pes->i_pes_size > p_es->i_pes_real_size )            {                msg_Warn( p_input,                          "Oversized PES packet for PID %d: expected %d, actual %d",                          p_es->i_id, p_es->i_pes_real_size, p_pes->i_pes_size );            }            /* The packet is finished, parse it */            ParsePES( p_input, p_es );        }    }#undef p_pes}/* * PS Demultiplexing *//***************************************************************************** * GetID: Get the ID of a stream *****************************************************************************/static uint16_t GetID( input_thread_t *p_input, data_packet_t * p_data ){    uint16_t i_id;    i_id = p_data->p_demux_start[3];                            /* stream_id */    if( i_id == 0xBD )    {        mpeg_demux_t *p_mpeg_demux = (mpeg_demux_t *)p_input->p_private;        /* FIXME : this is not valid if the header is split in multiple         * packets */        /* stream_private_id */        i_id |= p_data->p_demux_start[ 9 + p_data->p_demux_start[8] ] << 8;        /* FIXME: See note about cur_scr_time above. */        p_mpeg_demux->cur_scr_time = -1;    }    return( i_id );}/***************************************************************************** * DecodePSM: Decode the Program Stream Map information ***************************************************************************** * FIXME : loads are not aligned in this function *****************************************************************************/static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ){    stream_ps_data_t *  p_demux =                 (stream_ps_data_t *)p_input->stream.p_demux_data;    byte_t *            p_byte;    byte_t *            p_end;    unsigned int        i;    unsigned int        i_new_es_number = 0;    if( p_data->p_demux_start + 10 > p_data->p_payload_end )    {        msg_Err( p_input, "PSM too short, packet corrupt" );        return;    }    if( p_demux->b_has_PSM        && p_demux->i_PSM_version == (p_data->p_demux_start[6] & 0x1F) )    {        /* Already got that one. */        return;    }    p_demux->b_has_PSM = 1;    p_demux->i_PSM_version = p_data->p_demux_start[6] & 0x1F;    /* Go to elementary_stream_map_length, jumping over     * program_stream_info. */    p_byte = p_data->p_demux_start + 10              + U16_AT(&p_data->p_demux_start[8]);    if( p_byte > p_data->p_payload_end )    {        msg_Err( p_input, "PSM too short, packet corrupt" );        return;    }    /* This is the full size of the elementary_stream_map.     * 2 == elementary_stream_map_length     * Please note that CRC_32 is not included in the length. */    p_end = p_byte + 2 + U16_AT(p_byte);    p_byte += 2;    if( p_end > p_data->p_payload_end )    {        msg_Err( p_input, "PSM too short, packet corrupt" );        return;    }    vlc_mutex_lock( &p_input->stream.stream_lock );    /* 4 == minimum useful size of a section */    while( p_byte + 4 <= p_end )    {        es_descriptor_t *   p_es = NULL;        uint8_t             i_stream_id = p_byte[1];        /* FIXME: there will be a problem with private streams... (same         * stream_id) */        /* Look for the ES in the ES table */        for( i = i_new_es_number;             i < p_input->stream.pp_programs[0]->i_es_number;             i++ )        {            if( p_input->stream.pp_programs[0]->pp_es[i]->i_stream_id                    == i_stream_id )            {                p_es = p_input->stream.pp_programs[0]->pp_es[i];                /* FIXME: do something below */#if 0                if( p_es->i_type != p_byte[0] )                {                    input_DelES( p_input, p_es );                    p_es = NULL;                }                else#endif                {                    /* Move the ES to the beginning. */                    p_input->stream.pp_programs[0]->pp_es[i]                        = p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ];                    p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ]                        = p_es;                    i_new_es_number++;                }                break;            }        }        /* The goal is to have all the ES we have just read in the         * beginning of the pp_es table, and all the others at the end,         * so that we can close them more easily at the end. */        if( p_es == NULL )        {            int i_fourcc, i_cat;            switch( p_byte[0] )            {            case MPEG1_VIDEO_ES:            case MPEG2_VIDEO_ES:            case MPEG2_MOTO_VIDEO_ES:                i_fourcc = VLC_FOURCC('m','p','g','v');                i_cat = VIDEO_ES;                break;            case DVD_SPU_ES:                i_fourcc = VLC_FOURCC('s','p','u','b');                i_cat = SPU_ES;                break;            case MPEG1_AUDIO_ES:            case MPEG2_AUDIO_ES:                i_fourcc = VLC_FOURCC('m','p','g','a');                i_cat = AUDIO_ES;                break;            case A52_AUDIO_ES:                i_fourcc = VLC_FOURCC('a','5','2','b');                i_cat = AUDIO_ES;                break;            case LPCM_AUDIO_ES:                i_fourcc = VLC_FOURCC('l','p','c','b');                i_cat = AUDIO_ES;                break;            default:                i_cat = UNKNOWN_ES;                i_fourcc = 0;                break;            }            p_es = input_AddES( p_input, p_input->stream.pp_programs[0],                                i_stream_id, i_cat, NULL, 0 );            p_es->i_fourcc = i_fourcc;            /* input_AddES has inserted the new element at the end. */            p_input->stream.pp_programs[0]->pp_es[                p_input->stream.pp_programs[0]->i_es_number ]                = p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ];            p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ] = p_es;            i_new_es_number++;        }        p_byte += 4 + U16_AT(&p_byte[2]);    }    /* Un-select the streams that are no longer parts of the program. */    while( i_new_es_number < p_input->stream.pp_programs[0]->i_es_number )    {        /* We remove pp_es[i_new_es_member] and not pp_es[i] because the         * list will be emptied starting from the end */        input_DelES( p_input,                     p_input->stream.pp_programs[0]->pp_es[i_new_es_number] );    }    msg_Dbg( p_input, "the stream map after the PSM is now:" );    input_DumpStream( p_input );    vlc_mutex_unlock( &p_input->stream.stream_lock );}/***************************************************************************** * ReadPS: store a PS packet into a data_buffer_t *****************************************************************************/#define PEEK( SIZE )                                                        \    i_error = input_Peek( p_input, &p_peek, SIZE );                         \    if( i_error == -1 )                                                     \    {                                                                       \        return( -1 );                                                       \    }                                                                       \    else if( (size_t)i_error < SIZE )                                       \    {                                                                       \        /* EOF */                                                           \        return( 0 );                                                        \    }static ssize_t ReadPS( input_thread_t * p_input, data_packet_t ** pp_data ){

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?