system.c

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

C
1,499
字号
    byte_t *            p_peek;    size_t              i_packet_size;    ssize_t             i_error, i_read;    /* Read what we believe to be a packet header. */    PEEK( 4 );    if( p_peek[0] || p_peek[1] || p_peek[2] != 1 || p_peek[3] < 0xB9 )    {        if( p_peek[0] || p_peek[1] || p_peek[2] )        {            /* It is common for MPEG-1 streams to pad with zeros             * (although it is forbidden by the recommendation), so             * don't bother everybody in this case. */            msg_Warn( p_input, "garbage (0x%.2x%.2x%.2x%.2x)",                      p_peek[0], p_peek[1], p_peek[2], p_peek[3] );        }        /* This is not the startcode of a packet. Read the stream         * until we find one. */        while( p_peek[0] || p_peek[1] || p_peek[2] != 1 || p_peek[3] < 0xB9 )        {            p_input->p_current_data++;            PEEK( 4 );            if( p_input->b_die ) return( -1 );        }        /* Packet found. */    }    /* 0x1B9 == SYSTEM_END_CODE, it is only 4 bytes long. */    if( p_peek[3] != 0xB9 )    {        /* The packet is at least 6 bytes long. */        PEEK( 6 );        if( p_peek[3] != 0xBA )        {            /* That's the case for all packets, except pack header. */            i_packet_size = (p_peek[4] << 8) | p_peek[5];        }        else        {            /* Pack header. */            if( (p_peek[4] & 0xC0) == 0x40 )            {                /* MPEG-2 */                i_packet_size = 8;            }            else if( (p_peek[4] & 0xF0) == 0x20 )            {                /* MPEG-1 */                i_packet_size = 6;            }            else            {                msg_Err( p_input, "unable to determine stream type" );                p_input->p_current_data++;                return( -1 );            }        }    }    else    {        /* System End Code */        i_packet_size = -2;    }    /* Fetch a packet of the appropriate size. */    i_read = input_SplitBuffer( p_input, pp_data, i_packet_size + 6 );    if( i_read <= 0 )    {        return( i_read );    }    /* In MPEG-2 pack headers we still have to read stuffing bytes. */    if( ((*pp_data)->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )    {        size_t i_stuffing = ((*pp_data)->p_demux_start[13] & 0x7);        /* Force refill of the input buffer - though we don't care         * about p_peek. Please note that this is unoptimized. */        PEEK( i_stuffing );        p_input->p_current_data += i_stuffing;    }    return( 1 );}#undef PEEK/***************************************************************************** * ParsePS: read the PS header *****************************************************************************/static es_descriptor_t * ParsePS( input_thread_t * p_input,                                  data_packet_t * p_data ){    uint32_t            i_code;    es_descriptor_t *   p_es = NULL;    i_code = p_data->p_demux_start[3];    if( i_code > 0xBC ) /* ES start code */    {        uint16_t            i_id;        unsigned int        i_dummy;        /* This is a PES packet. Find out if we want it or not. */        i_id = GetID( p_input, p_data );        vlc_mutex_lock( &p_input->stream.stream_lock );        if( p_input->stream.pp_programs[0]->b_is_ok )        {            /* Look only at the selected ES. */            for( i_dummy = 0; i_dummy < p_input->stream.i_selected_es_number;                 i_dummy++ )            {                if( p_input->stream.pp_selected_es[i_dummy] != NULL                    && p_input->stream.pp_selected_es[i_dummy]->i_id == i_id )                {                    p_es = p_input->stream.pp_selected_es[i_dummy];                    break;                }            }        }        else        {            vlc_bool_t b_auto_spawn = VLC_FALSE;            stream_ps_data_t * p_demux =              (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;            /* Search all ES ; if not found -> AddES */            p_es = input_FindES( p_input, i_id );            if( p_es == NULL && !p_demux->b_has_PSM )            {                int i_fourcc, i_cat;                /* Set stream type and auto-spawn. */                if( (i_id & 0xF0) == 0xE0 )                {                    /* MPEG video */                    i_fourcc = VLC_FOURCC('m','p','g','v');                    i_cat = VIDEO_ES;#ifdef AUTO_SPAWN                    if( !p_input->stream.b_seekable ) b_auto_spawn = VLC_TRUE;#endif                }                else if( (i_id & 0xE0) == 0xC0 )                {                    /* MPEG audio */                    i_fourcc = VLC_FOURCC('m','p','g','a');                    i_cat = AUDIO_ES;#ifdef AUTO_SPAWN                    if( !p_input->stream.b_seekable )                    if( config_GetInt( p_input, "audio-channel" )                            == (i_id & 0x1F) ||                        ( config_GetInt( p_input, "audio-channel" ) < 0                          && !(i_id & 0x1F) ) )                    switch( config_GetInt( p_input, "audio-type" ) )                    {                    case -1:                    case REQUESTED_MPEG:                        b_auto_spawn = VLC_TRUE;                    }#endif                }                else if( (i_id & 0xF8FF) == 0x88BD )                {                    i_fourcc = VLC_FOURCC('d','t','s','b');                    i_cat = AUDIO_ES;#ifdef AUTO_SPAWN                    if( !p_input->stream.b_seekable )                    if( config_GetInt( p_input, "audio-channel" )                            == ((i_id & 0x700) >> 8) ||                        ( config_GetInt( p_input, "audio-channel" ) < 0                          && !((i_id & 0x700) >> 8)) )                    switch( config_GetInt( p_input, "audio-type" ) )                    {                    case -1:                    case REQUESTED_DTS:                        b_auto_spawn = VLC_TRUE;                    }#endif                }                else if( (i_id & 0xF0FF) == 0x80BD )                {                    /* A52 audio (0x80->0x8F) */                    i_fourcc = VLC_FOURCC('a','5','2','b');                    i_cat = AUDIO_ES;#ifdef AUTO_SPAWN                    if( !p_input->stream.b_seekable )                    if( config_GetInt( p_input, "audio-channel" )                            == ((i_id & 0xF00) >> 8) ||                        ( config_GetInt( p_input, "audio-channel" ) < 0                          && !((i_id & 0xF00) >> 8)) )                    switch( config_GetInt( p_input, "audio-type" ) )                    {                    case -1:                    case REQUESTED_A52:                        b_auto_spawn = VLC_TRUE;                    }#endif                }                else if( (i_id & 0xE0FF) == 0x20BD )                {                    /* Subtitles video (0x20->0x3F) */                    i_fourcc = VLC_FOURCC('s','p','u','b');                    i_cat = SPU_ES;#ifdef AUTO_SPAWN                    if( !p_input->stream.b_seekable )                    if( config_GetInt( p_input, "spu-channel" )                           == ((i_id & 0x1F00) >> 8) )                    {                        b_auto_spawn = VLC_TRUE;                    }#endif                }                else if( (i_id & 0xF0FF) == 0xA0BD )                {                    /* LPCM audio (0xA0->0xAF) */                    i_fourcc = VLC_FOURCC('l','p','c','b');                    i_cat = AUDIO_ES;                }                else if( (i_id & 0xFFFF) == 0x70BD )                {                    /* SVCD OGT subtitles in stream 0x070 */                    i_fourcc = VLC_FOURCC('o','g','t', ' ');                    i_cat = SPU_ES;                    b_auto_spawn = VLC_TRUE;                }                else if( ((i_id >> 8) & 0xFF) <= 0x03 &&                         (i_id & 0x00FF) == 0x00BD )                {                    /* CVD subtitles (0x00->0x03) */                    i_fourcc = VLC_FOURCC('c','v','d', ' ');                    i_cat = SPU_ES;                    b_auto_spawn = VLC_TRUE;                }                else                {                    i_cat = UNKNOWN_ES;                    i_fourcc = 0;                }                p_es = input_AddES( p_input, p_input->stream.pp_programs[0],                                    i_id, i_cat, NULL, 0 );                p_es->i_stream_id = p_data->p_demux_start[3];                p_es->i_fourcc = i_fourcc;                if( b_auto_spawn ) input_SelectES( p_input, p_es );                /* Tell the interface the stream has changed */                p_input->stream.b_changed = 1;            }        } /* stream.b_is_ok */        vlc_mutex_unlock( &p_input->stream.stream_lock );    } /* i_code > 0xBC */    return( p_es );}/***************************************************************************** * DemuxPS: first step of demultiplexing: the PS header *****************************************************************************/static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data ){    uint32_t i_code;    vlc_bool_t b_trash = 0;    es_descriptor_t * p_es = NULL;    mpeg_demux_t *p_mpeg_demux = (mpeg_demux_t *)p_input->p_private;    i_code = ((uint32_t)p_data->p_demux_start[0] << 24)                | ((uint32_t)p_data->p_demux_start[1] << 16)                | ((uint32_t)p_data->p_demux_start[2] << 8)                | p_data->p_demux_start[3];    if( i_code <= 0x1BC )    {        switch( i_code )        {        case 0x1BA: /* PACK_START_CODE */            {                /* Read the SCR. */                mtime_t scr_time;                uint32_t i_mux_rate;                if( (p_data->p_demux_start[4] & 0xC0) == 0x40 )                {                    /* MPEG-2 */                    byte_t      p_header[14];                    byte_t *    p_byte;                    p_byte = p_data->p_demux_start;                    if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 )                    {                        msg_Warn( p_input,                                  "packet too short to have a header" );                        b_trash = 1;                        break;                    }                    scr_time =                         ((mtime_t)(p_header[4] & 0x38) << 27) |                         ((mtime_t)(U32_AT(p_header + 4) & 0x03FFF800)                                        << 4) |                         ((( ((mtime_t)U16_AT(p_header + 6) << 16)                            | (mtime_t)U16_AT(p_header + 8) ) & 0x03FFF800)                                        >> 11);                    /* mux_rate */                    i_mux_rate = ((uint32_t)U16_AT(p_header + 10) << 6)                                   | (p_header[12] >> 2);                    /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME                     * This is the biggest kludge ever !                     * I don't know what's wrong with mux_rate calculation                     * but this heuristic works well : */                    i_mux_rate <<= 1;                    i_mux_rate /= 3;                }                else                {                    /* MPEG-1 SCR is like PTS. */                    byte_t      p_header[12];                    byte_t *    p_byte;                    p_byte = p_data->p_demux_start;                    if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 )                    {                        msg_Warn( p_input,                                  "packet too short to have a header" );                        b_trash = 1;                        break;                    }                    scr_time =                         ((mtime_t)(p_header[4] & 0x0E) << 29) |                         (((mtime_t)U32_AT(p_header + 4) & 0xFFFE00) << 6) |                         ((mtime_t)p_header[7] << 7) |                         ((mtime_t)p_header[8] >> 1);                    /* mux_rate */                    i_mux_rate = (U32_AT(p_header + 8) & 0x7FFFFE) >> 1;                }                p_mpeg_demux->cur_scr_time   = scr_time;                p_mpeg_demux->i_cur_mux_rate = i_mux_rate;                b_trash = 1;            }            break;        case 0x1BB: /* SYSTEM_START_CODE */            b_trash = 1;                              /* Nothing interesting */            break;        case 0x1BC: /* PROGRAM_STREAM_MAP_CODE */            DecodePSM( p_input, p_data );            b_trash = 1;            break;        case 0x1B9: /* PROGRAM_END_CODE */            b_trash = 1;            break;        default:            /* This should not happen */            b_trash = 1;            msg_Warn( p_input, "unwanted packet received "                               "with startcode 0x%.8x", i_code );        }    }    else    {        p_es = ParsePS( p_input, p_data );        /* Call the pace control.          * FIXME: see hack note about cur_scr_time in system.h.          */        if( p_mpeg_demux->cur_scr_time != -1 )

⌨️ 快捷键说明

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