system.c

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

C
1,499
字号
        {            input_ClockManageRef( p_input,                                  p_input->stream.p_selected_program,                                  p_mpeg_demux->cur_scr_time );                      if( p_mpeg_demux->i_cur_mux_rate != p_input->stream.i_mux_rate                && p_input->stream.i_mux_rate )            {                msg_Warn( p_input,                          "mux_rate changed prev: %ud, cur: %ud;"                          " expect cosmetic errors" ,                           (unsigned int) p_input->stream.i_mux_rate,                           (unsigned int) p_mpeg_demux->i_cur_mux_rate );            }            p_input->stream.i_mux_rate = p_mpeg_demux->i_cur_mux_rate;        }        vlc_mutex_lock( &p_input->stream.control.control_lock );        if( p_es != NULL && p_es->p_dec != NULL             && (p_es->i_cat != AUDIO_ES || !p_input->stream.control.b_mute) )        {            vlc_mutex_unlock( &p_input->stream.control.control_lock );            p_es->c_packets++;            GatherPES( p_input, p_data, p_es, 1, 0 );        }        else        {            vlc_mutex_unlock( &p_input->stream.control.control_lock );            b_trash = 1;        }    }    /* Trash the packet if it has no payload or if it isn't selected */    if( b_trash )    {        input_DeletePacket( p_input->p_method_data, p_data );        p_input->stream.c_packets_trashed++;    }}/* * TS Demultiplexing *//***************************************************************************** * ReadTS: store a TS 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( i_error < SIZE )                                               \    {                                                                       \        /* EOF */                                                           \        return( 0 );                                                        \    }static ssize_t ReadTS( input_thread_t * p_input, data_packet_t ** pp_data ){    byte_t *            p_peek;    ssize_t             i_error, i_read;    PEEK( 1 );    if( *p_peek != TS_SYNC_CODE )    {        msg_Warn( p_input, "garbage at input (%x)", *p_peek );        if( p_input->i_mtu )        {            while( *p_peek != TS_SYNC_CODE )            {                /* Try to resync on next packet. */                PEEK( TS_PACKET_SIZE );                p_input->p_current_data += TS_PACKET_SIZE;                PEEK( 1 );            }        }        else        {            /* Move forward until we find 0x47 (and hope it's the good             * one... FIXME) */            while( *p_peek != TS_SYNC_CODE )            {                p_input->p_current_data++;                PEEK( 1 );            }        }    }    i_read = input_SplitBuffer( p_input, pp_data, TS_PACKET_SIZE );    if( i_read <= 0 )    {        return( i_read );    }    return( 1 );}/***************************************************************************** * DemuxTS: first step of demultiplexing: the TS header *****************************************************************************/static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data,                     psi_callback_t pf_psi_callback ){    uint16_t            i_pid;    unsigned int        i_dummy;    vlc_bool_t          b_adaptation;         /* Adaptation field is present */    vlc_bool_t          b_payload;                 /* Packet carries payload */    vlc_bool_t          b_unit_start;  /* A PSI or a PES start in the packet */    vlc_bool_t          b_trash = 0;             /* Is the packet unuseful ? */    vlc_bool_t          b_lost = 0;             /* Was there a packet loss ? */    vlc_bool_t          b_psi = 0;                        /* Is this a PSI ? */    vlc_bool_t          b_dvbsub = 0;            /* Is this a dvb subtitle ? */    vlc_bool_t          b_pcr = 0;                   /* Does it have a PCR ? */    vlc_bool_t          b_scrambled;    es_descriptor_t *   p_es = NULL;    es_ts_data_t *      p_es_demux = NULL;    pgrm_ts_data_t *    p_pgrm_demux = NULL;    stream_ts_data_t *  p_stream_demux =                          (stream_ts_data_t *)p_input->stream.p_demux_data;#define p (p_data->p_demux_start)    /* Extract flags values from TS common header. */    i_pid = ((p[1] & 0x1F) << 8) | p[2];    b_unit_start = (p[1] & 0x40);    b_scrambled = (p[3] & 0xc0);    b_adaptation = (p[3] & 0x20);    b_payload = (p[3] & 0x10);    /* Was there a transport error ? */    if ( p[1] & 0x80 )    {        msg_Warn( p_input, "transport_error_indicator set for PID %d counter %x", i_pid, p[3] & 0x0f );    }    /* Find out the elementary stream. */    vlc_mutex_lock( &p_input->stream.stream_lock );    for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number; i_dummy ++ )    {        if( (( pgrm_ts_data_t * ) p_input->stream.pp_programs[i_dummy]->                    p_demux_data)->i_pcr_pid == i_pid )        {            b_pcr = 1;            break;        }    }    p_es = input_FindES( p_input, i_pid );    if( (p_es != NULL) && (p_es->p_demux_data != NULL) )    {        p_es_demux = (es_ts_data_t *)p_es->p_demux_data;        if( p_es_demux->b_psi )        {            b_psi = 1;        }        else if ( p_es_demux->b_dvbsub )        {            b_dvbsub = 1;        }        else        {            p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;        }    }    vlc_mutex_lock( &p_input->stream.control.control_lock );    if( ( p_es == NULL ) || (p_es->i_cat == AUDIO_ES                              && p_input->stream.control.b_mute) )    {        /* Not selected. Just read the adaptation field for a PCR. */        b_trash = 1;    }    else if( p_es->p_dec == NULL && !b_psi && !b_dvbsub )    {        b_trash = 1;    }    else if( b_scrambled )    {        msg_Warn( p_input, "scrambled packet for PID %d counter %x", i_pid, p[3] & 0x0f );        b_trash = 1;    }    vlc_mutex_unlock( &p_input->stream.control.control_lock );    vlc_mutex_unlock( &p_input->stream.stream_lock );    /* Don't change the order of the tests : if b_psi then p_pgrm_demux     * may still be null. Who said it was ugly ?     * I have written worse. --Meuuh */    if( ( p_es ) &&        ((p_es->p_dec != NULL) || b_psi || b_pcr || b_dvbsub) )    {        p_es->c_packets++;        /* Extract adaptation field information if any */        if( !b_adaptation )        {            /* We don't have any adaptation_field, so payload starts             * immediately after the 4 byte TS header */            p_data->p_payload_start += 4;        }        else        {            /* p[4] is adaptation_field_length minus one */            p_data->p_payload_start += 5 + p[4];            /* The adaptation field can be limited to the             * adaptation_field_length byte, so that there is nothing to do:             * skip this possibility */            if( p[4] )            {                /* If the packet has both adaptation_field and payload,                 * adaptation_field cannot be more than 182 bytes long; if                 * there is only an adaptation_field, it must fill the next                 * 183 bytes. */                if( b_payload ? (p[4] > 182) : (p[4] != 183) )                {                    msg_Warn( p_input, "invalid TS adaptation field for PID %d (%2x)",                              i_pid, p[4] );                    p_data->b_discard_payload = 1;                    p_es->c_invalid_packets++;                    /* The length was invalid so we shouldn't have added it to                     * p_payload_start above.  Ensure p_payload_start has a                     * valid value by setting it equal to p_payload_end.  This                     * also stops any data being processed from the packet.                     */                    p_data->p_payload_start = p_data->p_payload_end;                }                /* Now we are sure that the byte containing flags is present:                 * read it */                else                {                    /* discontinuity_indicator */                    if( p[5] & 0x80 )                    {                        msg_Warn( p_input,                            "discontinuity_indicator encountered by TS demux "                            "(PID %d: current %d, packet %d)",                            i_pid,                            ( p_es_demux->i_continuity_counter ) & 0x0f,                            p[3] & 0x0f );                        /* If the PID carries the PCR, there will be a system                         * time-based discontinuity. We let the PCR decoder                         * handle that. */                        p_es->p_pgrm->i_synchro_state = SYNCHRO_REINIT;                        /* Don't resynchronise the counter here - it will                         * be checked later and b_lost will then be set if                         * necessary.                         */                    }                } /* valid TS adaptation field ? */            } /* length > 0 */        } /* has adaptation field */        /* Check the continuity of the stream. */        i_dummy = ((p[3] & 0x0f) - p_es_demux->i_continuity_counter) & 0x0f;        if( b_payload &&                ( i_dummy == 1 || (b_psi && p_stream_demux->b_buggy_psi ) ) )        {            /* Everything is ok, just increase our counter */            (p_es_demux->i_continuity_counter)++;        }        else        {            if( !b_payload && i_dummy == 0 )            {                /* This is a packet without payload, this is allowed by the                 * draft. As there is nothing interesting in this packet                 * (except PCR that have already been handled), we can trash                 * the packet. */                b_trash = 1;            }            else if( !b_payload )            {                /* If there is no payload, the counter should be unchanged */                msg_Warn( p_input, "packet rxd for PID %d with no payload but "                        "wrong counter: current %d, packet %d", i_pid,                        p_es_demux->i_continuity_counter & 0x0f, p[3] & 0x0f );            }            else if( i_dummy <= 0 )            {                /* Duplicate packet: mark it as being to be trashed. */                msg_Warn( p_input,                          "duplicate packet received for PID %d (counter %d)",                          p_es->i_id, p[3] & 0x0f );                b_trash = 1;            }            else if( p_es_demux->i_continuity_counter == 0xFF )            {                /* This means that the packet is the first one we receive for                 * this ES since the continuity counter ranges between 0 and                 * 0x0F excepts when it has been initialized by the input:                 * init the counter to the correct value. */                msg_Warn( p_input, "first packet for PID %d received "                                   "by TS demux", p_es->i_id );                p_es_demux->i_continuity_counter = (p[3] & 0x0f);            }            else            {                /* This can indicate that we missed a packet or that the                 * continuity_counter wrapped and we received a dup packet:                 * as we don't know, do as if we missed a packet to be sure                 * to recover from this situation */                msg_Warn( p_input,                          "packet lost by TS demux for PID %d: current %d, packet %d",                          i_pid,                          p_es_demux->i_continuity_counter & 0x0f,                          p[3] & 0x0f );                b_lost = 1;                p_es_demux->i_continuity_counter = p[3] & 0x0f;            } /* not continuous */        } /* continuity */    } /* if selected or PCR */    /* Handle PCR */    if( b_pcr && b_adaptation && (p[5] & 0x10) && p[4]>=7 )    {        /* Read the PCR. */        mtime_t     pcr_time;        pcr_time = ( (mtime_t)p[6] << 25 ) |                   ( (mtime_t)p[7] << 17 ) |                   ( (mtime_t)p[8] << 9 ) |                   ( (mtime_t)p[9] << 1 ) |                   ( (mtime_t)p[10] >> 7 );        /* Call the pace control. */        for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number;                                i_dummy ++ )        {            if( ( ( pgrm_ts_data_t * ) p_input->stream.pp_programs[i_dummy]->                        p_demux_data )->i_pcr_pid == i_pid )            {                input_ClockManageRef( p_input,                    p_input->stream.pp_programs[i_dummy], pcr_time );            }        }    }    /* Trash the packet if it has no payload or if it isn't selected */    if( b_trash )    {        input_DeletePacket( p_input->p_method_data, p_data );        p_input->stream.c_packets_trashed++;    }    else    {        if( b_psi )        {            /* The payload contains PSI tables */            (* pf_psi_callback) ( p_input, p_data, p_es, b_unit_start );        }        else        {            /* The payload carries a PES stream */            GatherPES( p_input, p_data, p_es, b_unit_start, b_lost );        }    }#undef p}

⌨️ 快捷键说明

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