⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 vlc stand 0.1.99 ist sehr einfach
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** * input_ParsePES ***************************************************************************** * Parse a finished PES packet and analyze its header. *****************************************************************************/static __inline__ void input_ParsePES( input_thread_t *p_input,                                       es_descriptor_t *p_es_descriptor ){    decoder_fifo_t *            p_fifo;    u8                          i_pes_header_size;    ts_packet_t *               p_ts;    int                         i_ts_payload_size;#define p_pes (p_es_descriptor->p_pes_packet)    //intf_DbgMsg("End of PES packet %p\n", p_pes);    /* First read the 6 header bytes common to all PES packets:       use them to test the PES validity */    if( (p_pes->p_pes_header[0] || p_pes->p_pes_header[1] ||        (p_pes->p_pes_header[2] != 1)) ||                                 /* packet_start_code_prefix != 0x000001 */        ((p_pes->i_pes_real_size) &&         (p_pes->i_pes_real_size != p_pes->i_pes_size)) )               /* PES_packet_length is set and != total received payload */    {      /* Trash the packet and set p_pes to NULL to be sure the next PES         packet will have its b_data_lost flag set */      intf_DbgMsg("Corrupted PES packet received: trashed\n");      input_NetlistFreePES( p_input, p_pes );      p_pes = NULL;      /* Stats XXX?? */    }    else    {        /* The PES packet is valid. Check its type to test if it may           carry additional informations in a header extension */        p_pes->i_stream_id =  p_pes->p_pes_header[3];        switch( p_pes->i_stream_id )        {        case 0xBE:  /* Padding */        case 0xBC:  /* Program stream map */        case 0xBF:  /* Private stream 2 */        case 0xB0:  /* ECM */        case 0xB1:  /* EMM */        case 0xFF:  /* Program stream directory */        case 0xF2:  /* DSMCC stream */        case 0xF8:  /* ITU-T H.222.1 type E stream */            /* The payload begins immediatly after the 6 bytes header, so               we have finished with the parsing */            i_pes_header_size = 6;            break;        default:            /* The PES header contains at least 3 more bytes: parse them */            p_pes->b_data_alignment = p_pes->p_pes_header[6] & 0x04;            p_pes->b_has_pts = p_pes->p_pes_header[7] & 0x80;            i_pes_header_size = p_pes->p_pes_header[8] + 9;            /* Now parse the optional header extensions (in the limit of               the 14 bytes */            if( p_pes->b_has_pts )            {                pcr_descriptor_t * p_pcr;                p_pcr = p_input->p_pcr;                p_pes->i_pts =                    ( ((mtime_t)(p_pes->p_pes_header[9] & 0x0E) << 29) |                      (((mtime_t)U16_AT(p_pes->p_pes_header + 10) << 14) - (1 << 14)) |                      ((mtime_t)U16_AT(p_pes->p_pes_header + 12) >> 1) ) * 300;                p_pes->i_pts /= 27;                if( p_pcr->i_synchro_state )                {                    switch( p_pcr->i_synchro_state )                    {                        case SYNCHRO_NOT_STARTED:                            p_pes->b_has_pts = 0;                            break;                        case SYNCHRO_START:                            p_pes->i_pts += p_pcr->delta_pcr;                            p_pcr->delta_absolute = mdate() - p_pes->i_pts + INPUT_PTS_DELAY;                            p_pes->i_pts += p_pcr->delta_absolute;                            p_pcr->i_synchro_state = 0;                            break;                        case SYNCHRO_REINIT: /* We skip a PES */                            p_pes->b_has_pts = 0;                            p_pcr->i_synchro_state = SYNCHRO_START;                            break;                    }                }                else                {                    p_pes->i_pts += p_pcr->delta_pcr + p_pcr->delta_absolute;                }            }            break;        }        /* Now we've parsed the header, we just have to indicate in some           specific TS packets where the PES payload begins (renumber           i_payload_start), so that the decoders can find the beginning           of their data right out of the box. */        p_ts = p_pes->p_first_ts;        i_ts_payload_size = p_ts->i_payload_end - p_ts->i_payload_start;        while( i_pes_header_size > i_ts_payload_size )        {            /* These packets are entirely filled by the PES header. */            i_pes_header_size -= i_ts_payload_size;            p_ts->i_payload_start = p_ts->i_payload_end;            /* Go to the next TS packet: here we won't have to test it is               not NULL because we trash the PES packets when packet lost               occurs */            p_ts = p_ts->p_next_ts;            i_ts_payload_size = p_ts->i_payload_end - p_ts->i_payload_start;        }        /* This last packet is partly header, partly payload. */        p_ts->i_payload_start += i_pes_header_size;        /* Now we can eventually put the PES packet in the decoder's           PES fifo */        switch( p_es_descriptor->i_type )        {            case MPEG1_VIDEO_ES:            case MPEG2_VIDEO_ES:#ifdef OLD_DECODER                p_fifo = &(((vdec_thread_t*)(p_es_descriptor->p_dec))->fifo);#else                p_fifo = &(((vpar_thread_t*)(p_es_descriptor->p_dec))->fifo);#endif                break;            case MPEG1_AUDIO_ES:            case MPEG2_AUDIO_ES:                p_fifo = &(((adec_thread_t*)(p_es_descriptor->p_dec))->fifo);                break;            case AC3_AUDIO_ES:                /* we skip 4 bytes at the beginning of the AC3 payload */                //p_ts->i_payload_start += 4;                p_fifo = &(((ac3dec_thread_t *)(p_es_descriptor->p_dec))->fifo);                break;	    case LPCM_AUDIO_ES:                p_fifo = &(((lpcmdec_thread_t *)(p_es_descriptor->p_dec))->fifo);                break;            case DVD_SPU_ES:                /* we skip the first byte at the beginning of the                 * subpicture payload, it only contains the SPU ID. */                p_ts->i_payload_start++;                p_fifo = &(((spudec_thread_t *)(p_es_descriptor->p_dec))->fifo);                break;            default:                /* This should never happen */                intf_DbgMsg("Unknown stream type (%d, %d): PES trashed\n",                    p_es_descriptor->i_id, p_es_descriptor->i_type);                p_fifo = NULL;                break;        }        if( p_fifo != NULL )        {            vlc_mutex_lock( &p_fifo->data_lock );            if( DECODER_FIFO_ISFULL( *p_fifo ) )            {                /* The FIFO is full !!! This should not happen. */#ifdef STATS                p_input->c_packets_trashed += p_pes->i_ts_packets;                p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;#endif                input_NetlistFreePES( p_input, p_pes );                intf_DbgMsg("PES trashed - fifo full ! (%d, %d)\n",                           p_es_descriptor->i_id, p_es_descriptor->i_type);            }        else            {                //intf_DbgMsg("Putting %p into fifo %p/%d\n",                //            p_pes, p_fifo, p_fifo->i_end);                p_fifo->buffer[p_fifo->i_end] = p_pes;                DECODER_FIFO_INCEND( *p_fifo );                /* Warn the decoder that it's got work to do. */                vlc_cond_signal( &p_fifo->data_wait );            }            vlc_mutex_unlock( &p_fifo->data_lock );        }        else        {            intf_DbgMsg("No fifo to receive PES %p: trash\n", p_pes);#ifdef STATS            p_input->c_packets_trashed += p_pes->i_ts_packets;            p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;#endif            input_NetlistFreePES( p_input, p_pes );        }    }#undef p_pes}/***************************************************************************** * input_DemuxPSI: ***************************************************************************** * Notice that current ES state has been locked by input_SortPacket. (No more true, * changed by benny - FIXME: See if it's ok, and definitely change the code ?? ) *****************************************************************************/static __inline__ void input_DemuxPSI( input_thread_t *p_input,                                       ts_packet_t *p_ts_packet,                                       es_descriptor_t *p_es_descriptor,                                       boolean_t b_unit_start, boolean_t b_packet_lost ){    int i_data_offset;    /* Offset of the interesting data in the TS packet */    u16 i_data_length;                               /* Length of those data */    //boolean_t b_first_section; /* Was there another section in the TS packet ? */    ASSERT(p_input);    ASSERT(p_ts_packet);    ASSERT(p_es_descriptor);#define p_psi (p_es_descriptor->p_psi_section)    //intf_DbgMsg( "input debug: PSI demultiplexing %p (%p)\n", p_ts_packet, p_input);    //intf_DbgMsg( "Packet: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x (unit start: %d)\n", p_ts_packet->buffer[p_ts_packet->i_payload_start], p_ts_packet->buffer[p_ts_packet->i_payload_start+1], p_ts_packet->buffer[p_ts_packet->i_payload_start+2], p_ts_packet->buffer[p_ts_packet->i_payload_start+3], p_ts_packet->buffer[p_ts_packet->i_payload_start+4], p_ts_packet->buffer[p_ts_packet->i_payload_start+5], p_ts_packet->buffer[p_ts_packet->i_payload_start+6], p_ts_packet->buffer[p_ts_packet->i_payload_start+7], p_ts_packet->buffer[p_ts_packet->i_payload_start+8], p_ts_packet->buffer[p_ts_packet->i_payload_start+9], p_ts_packet->buffer[p_ts_packet->i_payload_start+10], p_ts_packet->buffer[p_ts_packet->i_payload_start+11], p_ts_packet->buffer[p_ts_packet->i_payload_start+12], p_ts_packet->buffer[p_ts_packet->i_payload_start+13], p_ts_packet->buffer[p_ts_packet->i_payload_start+14], p_ts_packet->buffer[p_ts_packet->i_payload_start+15], p_ts_packet->buffer[p_ts_packet->i_payload_start+16], p_ts_packet->buffer[p_ts_packet->i_payload_start+17], p_ts_packet->buffer[p_ts_packet->i_payload_start+18], p_ts_packet->buffer[p_ts_packet->i_payload_start+19], p_ts_packet->buffer[p_ts_packet->i_payload_start+20], b_unit_start);    /* Try to find the beginning of the payload in the packet to initialise       the do-while loop that follows -> Compute the i_data_offset variable:       by default, the value is set so that we won't enter in the while loop.       It will be set to a correct value if the data are not corrupted */    i_data_offset = TS_PACKET_SIZE;    /* Has the reassembly of a section already began in a previous packet ? */    if( p_psi->b_running_section )    {        /* Was data lost since the last TS packet ? */        if( b_packet_lost )        {            /* Discard the packet and wait for the begining of a new one to resynch */            p_psi->b_running_section = 0;            p_psi->i_current_position = 0;            intf_DbgMsg( "PSI section(s) discarded due to packet loss\n" );        }        else        {            /* The data that complete a previously began section are always at               the beginning of the TS payload... */            i_data_offset = p_ts_packet->i_payload_start;            /* ...Unless there is a pointer field, that we have to bypass */            if( b_unit_start )                i_data_offset++;            //intf_DbgMsg( "New part of the section received at offset %d\n", i_data_offset );        }    }    /* We are looking for the beginning of a new section */    else    {        if( b_unit_start )        {            /* Get the offset at which the data for that section can be found               The offset is stored in the pointer_field since we are interested in               the first section of the TS packet. Note that the +1 is to bypass               the pointer field */            i_data_offset = p_ts_packet->i_payload_start +                            p_ts_packet->buffer[p_ts_packet->i_payload_start] + 1;            //intf_DbgMsg( "New section beginning at offset %d in TS packet\n", i_data_offset );        }        else        {            /* This may either mean that the TS is bad or that the packet contains               the end of a section that had been discarded in a previous loop:               trash the TS packet since we cannot do anything with those data: */            p_psi->b_running_section = 0;            p_psi->i_current_position = 0;            intf_DbgMsg( "PSI packet discarded due to lack of synchronisation\n" );        }    }    /* The section we will deal with during the first iteration of the following       loop is the first one contained in the TS packet */    //    b_first_section = 1;    /* Reassemble the pieces of sections contained in the TS packet and decode       the sections that could have been completed.       Stop when we reach the end of the packet or stuffing bytes */    while( i_data_offset < TS_PACKET_SIZE && p_ts_packet->buffer[i_data_offset] != 0xFF )    {        /* If the current section is a new one, reinit the data fields of the p_psi           struct to start its decoding */        if( !p_psi->b_running_section )        {            /* Read the length of the new section */            p_psi->i_length = (U16_AT(&p_ts_packet->buffer[i_data_offset+1]) & 0xFFF) + 3;            //intf_DbgMsg( "Section length %d\n", p_psi->i_length );            if( p_psi->i_length > PSI_SECTION_SIZE )            {                /* The TS packet is corrupted, stop here to avoid possible a seg fault */                intf_DbgMsg( "PSI Section size is too big, aborting its reception\n" );                break;            }            /* Init the reassembly of that section */            p_psi->b_running_section = 1;            p_psi->i_current_position = 0;        }      /* Compute the length of data related to the section in this TS packet */        if( p_psi->i_length - p_psi->i_current_position > TS_PACKET_SIZE - i_data_offset)            i_data_length = TS_PACKET_SIZE - i_data_offset;        else          i_data_length = p_psi->i_length - p_psi->i_current_position;        /* Copy those data in the section buffer */        memcpy( &p_psi->buffer[p_psi->i_current_position], &p_ts_packet->buffer[i_data_offset],                i_data_length );        /* Interesting data are now after the ones we copied, since no gap is           allowed between 2 sections in a TS packets */        i_data_offset += i_data_length;        /* Decode the packet if it is now complete */        if (p_psi->i_length == p_psi->i_current_position + i_data_length)        {            /* Packet is complete, decode it */            //intf_DbgMsg( "SECTION COMPLETE: starting decoding of its data\n" );            input_PsiDecode( p_input, p_psi );            /* Prepare the buffer to receive a new section */            p_psi->i_current_position = 0;            p_psi->b_running_section = 0;            /* The new section won't be the first anymore */            //b_first_section = 0;        }        else        {            /* Prepare the buffer to receive the next part of the section */          p_psi->i_current_position += i_data_length;          //intf_DbgMsg( "Section not complete, waiting for the end\n" );        }        //intf_DbgMsg( "Must loop ? Next data offset: %d, stuffing: %d\n",        //             i_data_offset, p_ts_packet->buffer[i_data_offset] );    }    /* Relase the TS packet, we don't need it anymore */    input_NetlistFreeTS( p_input, p_ts_packet );#undef p_psi}

⌨️ 快捷键说明

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