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

📄 ty.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* register the video stream */    es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );    fmt.i_group = TY_ES_GROUP;    p_sys->p_video = es_out_Add( p_demux->out, &fmt );    /* */    for( i = 0; i < 4; i++ )        p_sys->p_cc[i] = NULL;    cc_Init( &p_sys->cc );    XdsInit( &p_sys->xds );    return VLC_SUCCESS;}/* =========================================================================== *//* Demux: Read & Demux one record from the chunk * * Returns -1 in case of error, 0 in case of EOF, 1 otherwise * * NOTE: I think we can return the number of packets sent instead of just 1. * that means we can demux an entire chunk and shoot it back (may be more efficient) * -- should try that some day :) -- */static int Demux( demux_t *p_demux ){    demux_sys_t  *p_sys = p_demux->p_sys;    ty_rec_hdr_t *p_rec;    block_t      *p_block_in = NULL;    /*msg_Dbg(p_demux, "ty demux processing" );*/       /* did we hit EOF earlier? */    if( p_sys->eof )        return 0;    /*     * what we do (1 record now.. maybe more later):    * - use stream_Read() to read the chunk header & record headers    * - discard entire chunk if it is a PART header chunk    * - parse all the headers into record header array    * - keep a pointer of which record we're on    * - use stream_Block() to fetch each record    * - parse out PTS from PES headers    * - set PTS for data packets    * - pass the data on to the proper codec via es_out_Send()    * if this is the first time or      * if we're at the end of this chunk, start a new one    */    /* parse the next chunk's record headers */    if( p_sys->b_first_chunk || p_sys->i_cur_rec >= p_sys->i_num_recs )    {        if( get_chunk_header(p_demux) == 0 )            return 0;    }    /*======================================================================     * parse & send one record of the chunk     *====================================================================== */    p_rec = &p_sys->rec_hdrs[p_sys->i_cur_rec];    if( !p_rec->b_ext )    {        const long l_rec_size = p_rec->l_rec_size;        /*msg_Dbg(p_demux, "Record Type 0x%x/%02x %ld bytes",                    subrec_type, p_rec->rec_type, l_rec_size );*/          /* some normal records are 0 length, so check for that... */        if( l_rec_size <= 0 )        {            /* no data in payload; we're done */            p_sys->i_cur_rec++;            return 1;        }        /* read in this record's payload */        if( !( p_block_in = stream_Block( p_demux->s, l_rec_size ) ) )            return 0;        /* set these as 'unknown' for now */        p_block_in->i_pts =        p_block_in->i_dts = 0;    }    /*else    {        -- don't read any data from the stream, data was in the record header --        msg_Dbg(p_demux,               "Record Type 0x%02x/%02x, ext data = %02x, %02x", subrec_type,                p_rec->rec_type, p_rec->ex1, p_rec->ex2);    }*/    if( p_rec->rec_type == 0xe0 )    {        /* Video */        DemuxRecVideo( p_demux, p_rec, p_block_in );    }    else if ( p_rec->rec_type == 0xc0 )    {        /* Audio */        DemuxRecAudio( p_demux, p_rec, p_block_in );    }    else if( p_rec->rec_type == 0x01 || p_rec->rec_type == 0x02 )    {        /* Closed Captions/XDS */        DemuxRecCc( p_demux, p_rec, p_block_in );    }    else if ( p_rec->rec_type == 0x03 )    {        /* Tivo data services (e.g. "thumbs-up to record!")  useless for us */        if( p_block_in )            block_Release(p_block_in);    }    else if ( p_rec->rec_type == 0x05 )    {        /* Unknown, but seen regularly */        if( p_block_in )            block_Release(p_block_in);    }    else    {        msg_Dbg(p_demux, "Invalid record type 0x%02x", p_rec->rec_type );        if( p_block_in )            block_Release(p_block_in);    }    /* */    p_sys->i_cur_rec++;    return 1;}/* Control */static int Control(demux_t *p_demux, int i_query, va_list args){    demux_sys_t *p_sys = p_demux->p_sys;    double f, *pf;    int64_t i64, *p_i64;    /*msg_Info(p_demux, "control cmd %d", i_query);*/    switch( i_query )    {    case DEMUX_GET_POSITION:        /* arg is 0.0 - 1.0 percent of overall file position */        if( ( i64 = p_sys->i_stream_size ) > 0 )        {            pf = (double*) va_arg( args, double* );            *pf = (double)stream_Tell( p_demux->s ) / (double) i64;            return VLC_SUCCESS;        }        return VLC_EGENERIC;    case DEMUX_SET_POSITION:        /* arg is 0.0 - 1.0 percent of overall file position */        f = (double) va_arg( args, double );        /* msg_Dbg(p_demux, "Control - set position to %2.3f", f); */        if ((i64 = p_sys->i_stream_size) > 0)            return ty_stream_seek_pct(p_demux, f);        return VLC_EGENERIC;    case DEMUX_GET_TIME:        /* return TiVo timestamp */        p_i64 = (int64_t *) va_arg(args, int64_t *);        //*p_i64 = p_sys->lastAudioPTS - p_sys->firstAudioPTS;        //*p_i64 = (p_sys->l_last_ty_pts / 1000) + (p_sys->lastAudioPTS -        //    p_sys->l_last_ty_pts_sync);        *p_i64 = (p_sys->l_last_ty_pts / 1000);        return VLC_SUCCESS;    case DEMUX_GET_LENGTH:    /* length of program in microseconds, 0 if unk */        /* size / bitrate */        p_i64 = (int64_t *) va_arg(args, int64_t *);        *p_i64 = 0;        return VLC_SUCCESS;    case DEMUX_SET_TIME:      /* arg is time in microsecs */        i64 = (int64_t) va_arg( args, int64_t );        return ty_stream_seek_time(p_demux, i64 * 1000);    case DEMUX_GET_FPS:    default:        return VLC_EGENERIC;    }}/* Close */static void Close( vlc_object_t *p_this ){    demux_t *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys = p_demux->p_sys;    XdsExit( &p_sys->xds );    cc_Exit( &p_sys->cc );    free( p_sys->rec_hdrs );    free( p_sys->seq_table );    free(p_sys);}/* =========================================================================== *//* Compute Presentation Time Stamp (PTS) * Assume buf points to beginning of PTS */static mtime_t get_pts( const uint8_t *buf ){    mtime_t i_pts;    i_pts = ((mtime_t)(buf[0]&0x0e ) << 29)|             (mtime_t)(buf[1] << 22)|            ((mtime_t)(buf[2]&0xfe) << 14)|             (mtime_t)(buf[3] << 7)|             (mtime_t)(buf[4] >> 1);    i_pts *= 100 / 9;   /* convert PTS (90Khz clock) to microseconds */    return i_pts;}/* =========================================================================== */static int find_es_header( const uint8_t *header,                           const uint8_t *buffer, int i_search_len ){    int count;    for( count = 0; count < i_search_len; count++ )    {        if( !memcmp( &buffer[count], header, 4 ) )            return count;    }    return -1;}/* =========================================================================== *//* check if we have a full PES header, if not, then save what we have. * this is called when audio-start packets are encountered. * Returns: *     1 partial PES hdr found, some audio data found (buffer adjusted), *    -1 partial PES hdr found, no audio data found *     0 otherwise (complete PES found, pts extracted, pts set, buffer adjusted) *//* TODO: HD support -- nothing known about those streams */static int check_sync_pes( demux_t *p_demux, block_t *p_block,                           int32_t offset, int32_t rec_len ){    demux_sys_t *p_sys = p_demux->p_sys;    if ( offset < 0 || offset + p_sys->i_Pes_Length > rec_len )    {        /* entire PES header not present */        msg_Dbg( p_demux, "PES header at %d not complete in record. storing.",                 offset );        /* save the partial pes header */        if( offset < 0 )        {            /* no header found, fake some 00's (this works, believe me) */            memset( p_sys->pes_buffer, 4, 0 );            p_sys->i_pes_buf_cnt = 4;            if( rec_len > 4 )                msg_Err( p_demux, "PES header not found in record of %d bytes!",                         rec_len );            return -1;        }        /* copy the partial pes header we found */        memcpy( p_sys->pes_buffer, p_block->p_buffer + offset,                rec_len - offset );        p_sys->i_pes_buf_cnt = rec_len - offset;        if( offset > 0 )        {            /* PES Header was found, but not complete, so trim the end of this record */            p_block->i_buffer -= rec_len - offset;            return 1;        }        return -1;    /* partial PES, no audio data */    }    /* full PES header present, extract PTS */    p_sys->lastAudioPTS = get_pts( &p_block->p_buffer[ offset +            p_sys->i_Pts_Offset ] );    if (p_sys->firstAudioPTS < 0)        p_sys->firstAudioPTS = p_sys->lastAudioPTS;    p_block->i_pts = p_sys->lastAudioPTS;    /*msg_Dbg(p_demux, "Audio PTS %lld", p_sys->lastAudioPTS );*/    /* adjust audio record to remove PES header */    memmove(p_block->p_buffer + offset, p_block->p_buffer + offset +            p_sys->i_Pes_Length, rec_len - p_sys->i_Pes_Length);    p_block->i_buffer -= p_sys->i_Pes_Length;#if 0    msg_Dbg(p_demux, "pes hdr removed; buffer len=%d and has "             "%02x %02x %02x %02x %02x %02x %02x %02x "             "%02x %02x %02x %02x %02x %02x %02x %02x", p_block->i_buffer,             p_block->p_buffer[0], p_block->p_buffer[1],             p_block->p_buffer[2], p_block->p_buffer[3],             p_block->p_buffer[4], p_block->p_buffer[5],             p_block->p_buffer[6], p_block->p_buffer[7],             p_block->p_buffer[8], p_block->p_buffer[9],             p_block->p_buffer[10], p_block->p_buffer[11],             p_block->p_buffer[12], p_block->p_buffer[13],             p_block->p_buffer[14], p_block->p_buffer[15]);#endif    return 0;}static int DemuxRecVideo( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in ){    demux_sys_t *p_sys = p_demux->p_sys;    const int subrec_type = rec_hdr->subrec_type;    const long l_rec_size = rec_hdr->l_rec_size;    // p_block_in->i_buffer might be better    int esOffset1;    int i;    assert( rec_hdr->rec_type == 0xe0 );    if( !p_block_in )        return -1;#if 0    msg_Dbg(p_demux, "packet buffer has "            "%02x %02x %02x %02x %02x %02x %02x %02x "            "%02x %02x %02x %02x %02x %02x %02x %02x",            p_block_in->p_buffer[0], p_block_in->p_buffer[1],            p_block_in->p_buffer[2], p_block_in->p_buffer[3],            p_block_in->p_buffer[4], p_block_in->p_buffer[5],            p_block_in->p_buffer[6], p_block_in->p_buffer[7],            p_block_in->p_buffer[8], p_block_in->p_buffer[9],            p_block_in->p_buffer[10], p_block_in->p_buffer[11],            p_block_in->p_buffer[12], p_block_in->p_buffer[13],            p_block_in->p_buffer[14], p_block_in->p_buffer[15]);#endif    //if( subrec_type == 0x06 || subrec_type == 0x07 )    if( subrec_type != 0x02 && subrec_type != 0x0c &&        subrec_type != 0x08 && l_rec_size > 4 )    {        /* get the PTS from this packet if it has one.         * on S1, only 0x06 has PES.  On S2, however, most all do.         * Do NOT Pass the PES Header to the MPEG2 codec */        esOffset1 = find_es_header( ty_VideoPacket, p_block_in->p_buffer, 5 );        if( esOffset1 != -1 )        {            //msg_Dbg(p_demux, "Video PES hdr in pkt type 0x%02x at offset %d",                //subrec_type, esOffset1);            p_sys->lastVideoPTS = get_pts(                    &p_block_in->p_buffer[ esOffset1 + VIDEO_PTS_OFFSET ] );            /*msg_Dbg(p_demux, "Video rec %d PTS %"PRId64, p_sys->i_cur_rec,                        p_sys->lastVideoPTS );*/            if (subrec_type != 0x06) {                /* if we found a PES, and it's not type 6, then we're S2 */                /* The packet will have video data (& other headers) so we                 * chop out the PES header and send the rest */                if (l_rec_size >= VIDEO_PES_LENGTH) {                    p_block_in->p_buffer += VIDEO_PES_LENGTH + esOffset1;                    p_block_in->i_buffer -= VIDEO_PES_LENGTH + esOffset1;                } else {                    msg_Dbg(p_demux, "video rec type 0x%02x has short PES"                        " (%ld bytes)", subrec_type, l_rec_size);                    /* nuke this block; it's too short, but has PES marker */                    p_block_in->i_buffer = 0;                }            }        }/* else            msg_Dbg(p_demux, "No Video PES hdr in pkt type 0x%02x",                subrec_type); */    }    if(subrec_type == 0x06 )    {        /* type 6 (S1 DTivo) has no data, so we're done */        block_Release(p_block_in);        return 0;    }

⌨️ 快捷键说明

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