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

📄 mp4.c

📁 VLC媒体播放程序
💻 C
📖 第 1 页 / 共 4 页
字号:
        p_soun = p_sample->data.p_sample_soun;        if( p_soun->i_qt_version == 0 )        {            switch( p_sample->i_type )            {                case VLC_FOURCC( 'i', 'm', 'a', '4' ):                    p_soun->i_qt_version = 1;                    p_soun->i_sample_per_packet = 64;                    p_soun->i_bytes_per_packet  = 34;                    p_soun->i_bytes_per_frame   = 34 * p_soun->i_channelcount;                    p_soun->i_bytes_per_sample  = 2;                    break;                case VLC_FOURCC( 'M', 'A', 'C', '3' ):                    p_soun->i_qt_version = 1;                    p_soun->i_sample_per_packet = 6;                    p_soun->i_bytes_per_packet  = 2;                    p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;                    p_soun->i_bytes_per_sample  = 2;                    break;                case VLC_FOURCC( 'M', 'A', 'C', '6' ):                    p_soun->i_qt_version = 1;                    p_soun->i_sample_per_packet = 12;                    p_soun->i_bytes_per_packet  = 2;                    p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;                    p_soun->i_bytes_per_sample  = 2;                    break;                default:                    break;            }        }        else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )        {            p_soun->i_qt_version = 0;        }    }    /* It's a little ugly but .. there are special cases */    switch( p_sample->i_type )    {        case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):        case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):            p_track->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );            break;        case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):            p_track->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );            break;        case( VLC_FOURCC( 's', '2', '6', '3' ) ):            p_track->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );            break;        default:            p_track->fmt.i_codec = p_sample->i_type;            break;    }    /* now see if esds is present and if so create a data packet        with decoder_specific_info  */#define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr    if( ( ( p_esds = MP4_BoxGet( p_sample, "esds" ) ) ||          ( p_esds = MP4_BoxGet( p_sample, "wave/esds" ) ) )&&        ( p_esds->data.p_esds )&&        ( p_decconfig ) )    {        /* First update information based on i_objectTypeIndication */        switch( p_decconfig->i_objectTypeIndication )        {            case( 0x20 ): /* MPEG4 VIDEO */                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','v' );                break;            case( 0x40):                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );                break;            case( 0x60):            case( 0x61):            case( 0x62):            case( 0x63):            case( 0x64):            case( 0x65): /* MPEG2 video */                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );                break;            /* Theses are MPEG2-AAC */            case( 0x66): /* main profile */            case( 0x67): /* Low complexity profile */            case( 0x68): /* Scaleable Sampling rate profile */                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );                break;            /* true MPEG 2 audio */            case( 0x69):                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','a' );                break;            case( 0x6a): /* MPEG1 video */                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );                break;            case( 0x6b): /* MPEG1 audio */                p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','a' );                break;            case( 0x6c ): /* jpeg */                p_track->fmt.i_codec = VLC_FOURCC( 'j','p','e','g' );                break;            default:                /* Unknown entry, but don't touch i_fourcc */                msg_Warn( p_input,                          "unknown objectTypeIndication(0x%x) (Track[ID 0x%x])",                          p_decconfig->i_objectTypeIndication,                          p_track->i_track_ID );                break;        }        p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;        if( p_track->fmt.i_extra > 0 )        {            p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );            memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,                    p_track->fmt.i_extra );        }    }    else    {        switch( p_sample->i_type )        {            /* qt decoder, send the complete chunk */            case VLC_FOURCC( 'S', 'V', 'Q', '3' ):            case VLC_FOURCC( 'S', 'V', 'Q', '1' ):            case VLC_FOURCC( 'V', 'P', '3', '1' ):            case VLC_FOURCC( '3', 'I', 'V', '1' ):            case VLC_FOURCC( 'Z', 'y', 'G', 'o' ):                p_track->fmt.i_extra =                    p_sample->data.p_sample_vide->i_qt_image_description;                if( p_track->fmt.i_extra > 0 )                {                    p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );                    memcpy( p_track->fmt.p_extra,                            p_sample->data.p_sample_vide->p_qt_image_description,                            p_track->fmt.i_extra);                }                break;            case VLC_FOURCC( 'Q', 'D', 'M', 'C' ):            case VLC_FOURCC( 'Q', 'D', 'M', '2' ):            case VLC_FOURCC( 'Q', 'c', 'l', 'p' ):            case VLC_FOURCC( 's', 'a', 'm', 'r' ):                p_track->fmt.i_extra =                    p_sample->data.p_sample_soun->i_qt_description;                if( p_track->fmt.i_extra > 0 )                {                    p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );                    memcpy( p_track->fmt.p_extra,                            p_sample->data.p_sample_soun->p_qt_description,                            p_track->fmt.i_extra);                }                break;            default:                break;        }    }#undef p_decconfig    /* some last initialisation */    switch( p_track->fmt.i_cat )    {    case( VIDEO_ES ):        p_track->fmt.video.i_width = p_sample->data.p_sample_vide->i_width;        p_track->fmt.video.i_height = p_sample->data.p_sample_vide->i_height;        /* fall on display size */        if( p_track->fmt.video.i_width <= 0 )            p_track->fmt.video.i_width = p_track->i_width;        if( p_track->fmt.video.i_height <= 0 )            p_track->fmt.video.i_height = p_track->i_height;        /* Find out apect ratio from display size */        if( p_track->i_width > 0 && p_track->i_height > 0 )            p_track->fmt.video.i_aspect =                VOUT_ASPECT_FACTOR * p_track->i_width / p_track->i_height;        break;    case( AUDIO_ES ):        p_track->fmt.audio.i_channels =            p_sample->data.p_sample_soun->i_channelcount;        p_track->fmt.audio.i_rate =            p_sample->data.p_sample_soun->i_sampleratehi;        p_track->fmt.i_bitrate = p_sample->data.p_sample_soun->i_channelcount *            p_sample->data.p_sample_soun->i_sampleratehi *                p_sample->data.p_sample_soun->i_samplesize;        p_track->fmt.audio.i_bitspersample =            p_sample->data.p_sample_soun->i_samplesize;        break;    default:        break;    }    *pp_es = es_out_Add( p_input->p_es_out, &p_track->fmt );    return VLC_SUCCESS;}/* given a time it return sample/chunk * it also update elst field of the track */static int  TrackTimeToSampleChunk( input_thread_t *p_input,                                    mp4_track_t *p_track,                                    int64_t i_start,                                    uint32_t *pi_chunk,                                    uint32_t *pi_sample ){    demux_sys_t *p_sys = p_input->p_demux_data;    MP4_Box_t   *p_stss;    uint64_t     i_dts;    unsigned int i_sample;    unsigned int i_chunk;    int          i_index;    /* FIXME see if it's needed to check p_track->i_chunk_count */    if( !p_track->b_ok || p_track->i_chunk_count == 0 )    {        return( VLC_EGENERIC );    }    /* handle elst (find the correct one) */    MP4_TrackSetELST( p_input, p_track, i_start );    if( p_track->p_elst && p_track->p_elst->data.p_elst->i_entry_count > 0 )    {        MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;        int64_t i_mvt= i_start * p_sys->i_timescale / (int64_t)1000000;        /* now calculate i_start for this elst */        /* offset */        i_start -= p_track->i_elst_time * (int64_t)1000000 / p_sys->i_timescale;        if( i_start < 0 )        {            *pi_chunk = 0;            *pi_sample= 0;            return VLC_SUCCESS;        }        /* to track time scale */        i_start  = i_start * p_track->i_timescale / (int64_t)1000000;        /* add elst offset */        if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||             elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&            elst->i_media_time[p_track->i_elst] > 0 )        {            i_start += elst->i_media_time[p_track->i_elst];        }        msg_Dbg( p_input, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd"ms (track)",                 p_track->i_elst,                 i_mvt * 1000 / p_sys->i_timescale,                 i_start * 1000 / p_track->i_timescale );    }    else    {        /* convert absolute time to in timescale unit */        i_start = i_start * p_track->i_timescale / (int64_t)1000000;    }    /* we start from sample 0/chunk 0, hope it won't take too much time */    /* *** find good chunk *** */    for( i_chunk = 0; ; i_chunk++ )    {        if( i_chunk + 1 >= p_track->i_chunk_count )        {            /* at the end and can't check if i_start in this chunk,               it will be check while searching i_sample */            i_chunk = p_track->i_chunk_count - 1;            break;        }        if( i_start >= p_track->chunk[i_chunk].i_first_dts &&            i_start <  p_track->chunk[i_chunk + 1].i_first_dts )        {            break;        }    }    /* *** find sample in the chunk *** */    i_sample = p_track->chunk[i_chunk].i_sample_first;    i_dts    = p_track->chunk[i_chunk].i_first_dts;    for( i_index = 0; i_sample < p_track->chunk[i_chunk].i_sample_count; )    {        if( i_dts +            p_track->chunk[i_chunk].p_sample_count_dts[i_index] *            p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < i_start )        {            i_dts    +=                p_track->chunk[i_chunk].p_sample_count_dts[i_index] *                p_track->chunk[i_chunk].p_sample_delta_dts[i_index];            i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];            i_index++;        }        else        {            if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )            {                break;            }            i_sample += ( i_start - i_dts ) / p_track->chunk[i_chunk].p_sample_delta_dts[i_index];            break;        }    }    if( i_sample >= p_track->i_sample_count )    {        msg_Warn( p_input,                  "track[Id 0x%x] will be disabled (seeking too far) chunk=%d sample=%d",                  p_track->i_track_ID, i_chunk, i_sample );        return( VLC_EGENERIC );    }    /* *** Try to find nearest sync points *** */    if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )    {        unsigned int i_index;        msg_Dbg( p_input,                    "track[Id 0x%x] using Sync Sample Box (stss)",                    p_track->i_track_ID );        for( i_index = 0; i_index < p_stss->data.p_stss->i_entry_count; i_index++ )        {            if( p_stss->data.p_stss->i_sample_number[i_index] >= i_sample )            {                if( i_index > 0 )                {                    msg_Dbg( p_input, "stts gives %d --> %d (sample number)",                            i_sample,                            p_stss->data.p_stss->i_sample_number[i_index-1] );                    i_sample = p_stss->data.p_stss->i_sample_number[i_index-1];                    /* new i_sample is less than old so i_chunk can only decreased */                    while( i_chunk > 0 &&                            i_sample < p_track->chunk[i_chunk].i_sample_first )                    {                        i_chunk--;                    }                }                else                {                    msg_Dbg( p_input, "stts gives %d --> %d (sample number)",                            i_sample,                            p_stss->data.p_stss->i_sample_number[i_index] );                    i_sample = p_stss->data.p_stss->i_sample_number[i_index];                    /* new i_sample is more than old so i_chunk can only increased */                    while( i_chunk < p_track->i_chunk_count - 1 &&                           i_sample >= p_track->chunk[i_chunk].i_sample_first +                                                p_track->chunk[i_chunk].i_sample_count )                    {                        i_chunk++;                    }                }                break;            }        }    }    else    {        msg_Dbg( p_input,                    "track[Id 0x%x] does not provide Sync Sample Box (stss)",                    p_track->i_track_ID );    }    *pi_chunk  = i_chunk;    *pi_sample = i_sample;    return VLC_SUCCESS;}static int  TrackGotoChunkSample( input_thread_t   *p_input,                                  mp4_track_t *p_track,                                  unsigned int     i_chunk,                                  unsigned int     i_sample ){    vlc_bool_t b_reselect = VLC_FALSE;    /* now see if actual es is ok */    if( p_track->i_chunk < 0 ||        p_track->i_chunk >= p_track->i_chunk_count ||        p_track->chunk[p_track->i_chunk].i_sample_description_index !=            p_track->chunk[i_chunk].i_sample_description_index )    {        msg_Warn( p_input, "recreate ES" );        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, p_track->p_es, &b_reselect );        es_out_Del( p_input->p_es_out, p_track->p_es );        p_track->p_es = NULL;        if( TrackCreateES( p_input,                           p_track, i_chunk,                           &p_track->p_es ) )        {            msg_Err( p_input, "cannot create es for track[Id 0x%x]",                     p_track->i_track_ID );            p_track->b_ok       = VLC_FALSE;            p_track->b_selected = VLC_FALSE;            return VLC_EGENERIC;        }    }    /* select again the new decoder */    if( b_reselect )    {        es_out_Control( p_input->p_es_out, ES_OUT_SET_ES, p_track->p_es );    }    p_track->i_chunk    = i_chunk;    p_track->i_sample   = i_sample;    return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;}/**************************************************************************** * MP4_TrackCreate: **************************************************************************** * Parse track information and create all needed data to run a track * If it succeed b_ok is set to 1 else to 0 ****************************************************************************/static void MP4_TrackCreate( input_thread_t *p_input,                             mp4_track_t *p_track,                             MP4_Box_t  * p_box_trak ){    demux_sys_t *p_sys = p_input->p_demux_data;    MP4_Box_t *p_tkhd = MP4_BoxGet( p_box_trak, "tkhd" );    MP4_Box_t *p_tref = MP4_BoxGet( p_box_trak, "tref" );    MP4_Box_t *p_elst;    MP4_Box_t *p_mdhd;    MP4_Box_t *p_hdlr;    MP4_Box_t *p_vmhd;    MP4_Box_t *p_smhd;    MP4_Box_t *p_drms;    unsigned int i;    char language[4];    /* hint track unsuported */    /* set default value (-> track unusable) */    p_track->b_ok       = VLC_FALSE;    p_track->b_enable   = VLC_FALSE;    p_track->b_selected = VLC_FALSE;    es_format_Init( &p_track->fmt, UNKNOWN_ES, 0 );    if( !p_tkhd )    {        return;    }    /* do we launch this track by default ? */    p_track->b_enable =        ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );    p_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;

⌨️ 快捷键说明

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