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

📄 mkv.cpp

📁 VLC Player Source Code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
error:    delete p_sys;    return VLC_EGENERIC;}/***************************************************************************** * Close: frees unused data *****************************************************************************/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;    delete p_sys;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){    demux_sys_t        *p_sys = p_demux->p_sys;    int64_t     *pi64;    double      *pf, f;    int         i_skp;    size_t      i_idx;    vlc_meta_t *p_meta;    input_attachment_t ***ppp_attach;    int *pi_int;    int i;    switch( i_query )    {        case DEMUX_GET_ATTACHMENTS:            ppp_attach = (input_attachment_t***)va_arg( args, input_attachment_t*** );            pi_int = (int*)va_arg( args, int * );            if( p_sys->stored_attachments.size() <= 0 )                return VLC_EGENERIC;            *pi_int = p_sys->stored_attachments.size();            *ppp_attach = (input_attachment_t**)malloc( sizeof(input_attachment_t**) *                                                        p_sys->stored_attachments.size() );            if( !(*ppp_attach) )                return VLC_ENOMEM;            for( i = 0; i < p_sys->stored_attachments.size(); i++ )            {                attachment_c *a = p_sys->stored_attachments[i];                (*ppp_attach)[i] = vlc_input_attachment_New( a->psz_file_name.c_str(), a->psz_mime_type.c_str(), NULL,                                                             a->p_data, a->i_size );            }            return VLC_SUCCESS;        case DEMUX_GET_META:            p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );            vlc_meta_Merge( p_meta, p_sys->meta );            return VLC_SUCCESS;        case DEMUX_GET_LENGTH:            pi64 = (int64_t*)va_arg( args, int64_t * );            if( p_sys->f_duration > 0.0 )            {                *pi64 = (int64_t)(p_sys->f_duration * 1000);                return VLC_SUCCESS;            }            return VLC_EGENERIC;        case DEMUX_GET_POSITION:            pf = (double*)va_arg( args, double * );            if ( p_sys->f_duration > 0.0 )                *pf = (double)(p_sys->i_pts >= p_sys->i_start_pts ? p_sys->i_pts : p_sys->i_start_pts ) / (1000.0 * p_sys->f_duration);            return VLC_SUCCESS;        case DEMUX_SET_POSITION:            f = (double)va_arg( args, double );            Seek( p_demux, -1, f, NULL );            return VLC_SUCCESS;        case DEMUX_GET_TIME:            pi64 = (int64_t*)va_arg( args, int64_t * );            *pi64 = p_sys->i_pts;            return VLC_SUCCESS;        case DEMUX_GET_TITLE_INFO:            if( p_sys->titles.size() > 1 || ( p_sys->titles.size() == 1 && p_sys->titles[0]->i_seekpoint > 0 ) )            {                input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );                int *pi_int    = (int*)va_arg( args, int* );                *pi_int = p_sys->titles.size();                *ppp_title = (input_title_t**)malloc( sizeof( input_title_t**) * p_sys->titles.size() );                for( size_t i = 0; i < p_sys->titles.size(); i++ )                {                    (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->titles[i] );                }                return VLC_SUCCESS;            }            return VLC_EGENERIC;        case DEMUX_SET_TITLE:            /* TODO handle editions as titles */            i_idx = (int)va_arg( args, int );            if( i_idx < p_sys->used_segments.size() )            {                p_sys->JumpTo( *p_sys->used_segments[i_idx], NULL );                return VLC_SUCCESS;            }            return VLC_EGENERIC;        case DEMUX_SET_SEEKPOINT:            i_skp = (int)va_arg( args, int );            // TODO change the way it works with the << & >> buttons on the UI (+1/-1 instead of a number)            if( p_sys->titles.size() && i_skp < p_sys->titles[p_sys->i_current_title]->i_seekpoint)            {                Seek( p_demux, (int64_t)p_sys->titles[p_sys->i_current_title]->seekpoint[i_skp]->i_time_offset, -1, NULL);                p_demux->info.i_seekpoint |= INPUT_UPDATE_SEEKPOINT;                p_demux->info.i_seekpoint = i_skp;                return VLC_SUCCESS;            }            return VLC_EGENERIC;        case DEMUX_GET_FPS:            pf = (double *)va_arg( args, double * );            *pf = 0.0;            if( p_sys->p_current_segment && p_sys->p_current_segment->Segment() )            {                const matroska_segment_c *p_segment = p_sys->p_current_segment->Segment();                for( size_t i = 0; i < p_segment->tracks.size(); i++ )                {                    mkv_track_t *tk = p_segment->tracks[i];                    if( tk->fmt.i_cat == VIDEO_ES && tk->fmt.video.i_frame_rate_base > 0 )                    {                        *pf = (double)tk->fmt.video.i_frame_rate / tk->fmt.video.i_frame_rate_base;                        break;                    }                }            }            return VLC_SUCCESS;        case DEMUX_SET_TIME:        default:            return VLC_EGENERIC;    }}int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration ){    pp_simpleblock = NULL;    pp_block = NULL;    *pi_ref1  = 0;    *pi_ref2  = 0;    for( ;; )    {        EbmlElement *el = NULL;        int         i_level;        if ( ep == NULL )            return VLC_EGENERIC;        if( pp_simpleblock != NULL || ((el = ep->Get()) == NULL && pp_block != NULL) )        {            /* Check blocks validity to protect againts broken files */            if( BlockFindTrackIndex( NULL, pp_block , pp_simpleblock ) )            {                delete pp_block;                pp_simpleblock = NULL;                pp_block = NULL;                continue;            }            /* update the index */#define idx p_indexes[i_index - 1]            if( i_index > 0 && idx.i_time == -1 )            {                if ( pp_simpleblock != NULL )                    idx.i_time        = pp_simpleblock->GlobalTimecode() / (mtime_t)1000;                else                    idx.i_time        = (*pp_block).GlobalTimecode() / (mtime_t)1000;                idx.b_key         = *pi_ref1 == 0 ? true : false;            }#undef idx            return VLC_SUCCESS;        }        i_level = ep->GetLevel();        if( el == NULL )        {            if( i_level > 1 )            {                ep->Up();                continue;            }            msg_Warn( &sys.demuxer, "EOF" );            return VLC_EGENERIC;        }        /* Verify that we are still inside our cluster         * It can happens whith broken files and when seeking         * without index */        if( i_level > 1 )        {            if( cluster && !ep->IsTopPresent( cluster ) )            {                msg_Warn( &sys.demuxer, "Unexpected escape from current cluster" );                cluster = NULL;            }            if( !cluster )                continue;        }        /* do parsing */        switch ( i_level )        {        case 1:            if( MKV_IS_ID( el, KaxCluster ) )            {                cluster = (KaxCluster*)el;                i_cluster_pos = cluster->GetElementPosition();                /* add it to the index */                if( i_index == 0 ||                    ( i_index > 0 && p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) )                {                    IndexAppendCluster( cluster );                }                // reset silent tracks                for (size_t i=0; i<tracks.size(); i++)                {                    tracks[i]->b_silent = false;                }                ep->Down();            }            else if( MKV_IS_ID( el, KaxCues ) )            {                msg_Warn( &sys.demuxer, "find KaxCues FIXME" );                return VLC_EGENERIC;            }            else            {                msg_Dbg( &sys.demuxer, "unknown (%s)", typeid( el ).name() );            }            break;        case 2:            if( MKV_IS_ID( el, KaxClusterTimecode ) )            {                KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el;                ctc.ReadData( es.I_O(), SCOPE_ALL_DATA );                cluster->InitTimecode( uint64( ctc ), i_timescale );            }            else if( MKV_IS_ID( el, KaxClusterSilentTracks ) )            {                ep->Down();            }            else if( MKV_IS_ID( el, KaxBlockGroup ) )            {                i_block_pos = el->GetElementPosition();                ep->Down();            }            else if( MKV_IS_ID( el, KaxSimpleBlock ) )            {                pp_simpleblock = (KaxSimpleBlock*)el;                pp_simpleblock->ReadData( es.I_O() );                pp_simpleblock->SetParent( *cluster );            }            break;        case 3:            if( MKV_IS_ID( el, KaxBlock ) )            {                pp_block = (KaxBlock*)el;                pp_block->ReadData( es.I_O() );                pp_block->SetParent( *cluster );                ep->Keep();            }            else if( MKV_IS_ID( el, KaxBlockDuration ) )            {                KaxBlockDuration &dur = *(KaxBlockDuration*)el;                dur.ReadData( es.I_O() );                *pi_duration = uint64( dur );            }            else if( MKV_IS_ID( el, KaxReferenceBlock ) )            {                KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;                ref.ReadData( es.I_O() );                if( *pi_ref1 == 0 )                {                    *pi_ref1 = int64( ref ) * cluster->GlobalTimecodeScale();                }                else if( *pi_ref2 == 0 )                {                    *pi_ref2 = int64( ref ) * cluster->GlobalTimecodeScale();                }            }            else if( MKV_IS_ID( el, KaxClusterSilentTrackNumber ) )            {                KaxClusterSilentTrackNumber &track_num = *(KaxClusterSilentTrackNumber*)el;                track_num.ReadData( es.I_O() );                // find the track                for (size_t i=0; i<tracks.size(); i++)                {                    if ( tracks[i]->i_number == uint32(track_num))                    {                        tracks[i]->b_silent = true;                        break;                    }                }            }            break;        default:            msg_Err( &sys.demuxer, "invalid level = %d", i_level );            return VLC_EGENERIC;        }    }}static block_t *MemToBlock( demux_t *p_demux, uint8_t *p_mem, int i_mem, size_t offset){    block_t *p_block;    if( !(p_block = block_New( p_demux, i_mem + offset ) ) ) return NULL;    memcpy( p_block->p_buffer + offset, p_mem, i_mem );    //p_block->i_rate = p_input->stream.control.i_rate;    return p_block;}static void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock,                         mtime_t i_pts, mtime_t i_duration, bool f_mandatory ){    demux_sys_t        *p_sys = p_demux->p_sys;    matroska_segment_c *p_segment = p_sys->p_current_segment->Segment();    size_t          i_track;    unsigned int    i;    bool            b;    if( p_segment->BlockFindTrackIndex( &i_track, block, simpleblock ) )    {        msg_Err( p_demux, "invalid track number" );        return;    }    mkv_track_t *tk = p_segment->tracks[i_track];    if( tk->fmt.i_cat != NAV_ES && tk->p_es == NULL )    {        msg_Err( p_demux, "unknown track number" );        return;    }    if( i_pts + i_duration < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES )    {        return; /* discard audio packets that shouldn't be rendered */    }    if ( tk->fmt.i_cat != NAV_ES )    {        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );        if( !b )        {            tk->b_inited = false;            return;        }    }    /* First send init data */    if( !tk->b_inited && tk->i_data_init > 0 )    {        block_t *p_init;        msg_Dbg( p_demux, "sending header (%d bytes)", tk->i_data_init );        p_init = MemToBlock( p_demux, tk->p_data_init, tk->i_data_init, 0 );        if( p_init ) es_out_Send( p_demux->out, tk->p_es, p_init );    }    tk->b_inited = true;    for( i = 0;         (block != NULL && i < block->NumberFrames()) || (simpleblock != NULL && i < simpleblock->NumberFrames());         i++ )    {        block_t *p_block;        DataBuffer *data;        if( simpleblock != NULL )        {            data = &simpleblock->GetBuffer(i);            // condition when the DTS is correct (keyframe or B frame == NOT P frame)            f_mandatory = simpleblock->IsDiscarda

⌨️ 快捷键说明

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