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

📄 h264.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    return VLC_SUCCESS;}/***************************************************************************** * Close: clean up the packetizer *****************************************************************************/static void Close( vlc_object_t *p_this ){    decoder_t *p_dec = (decoder_t*)p_this;    decoder_sys_t *p_sys = p_dec->p_sys;    int i;    if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );    for( i = 0; i < SPS_MAX; i++ )    {        if( p_sys->pp_sps[i] )            block_Release( p_sys->pp_sps[i] );    }    for( i = 0; i < PPS_MAX; i++ )    {        if( p_sys->pp_pps[i] )            block_Release( p_sys->pp_pps[i] );    }    block_BytestreamRelease( &p_sys->bytestream );    free( p_sys );}/**************************************************************************** * Packetize: the whole thing * Search for the startcodes 3 or more bytes * Feed ParseNALBlock ALWAYS with 4 byte startcode prepended NALs ****************************************************************************/static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    block_t       *p_pic;    if( !pp_block || !*pp_block )        return NULL;    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )    {        if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )        {            p_sys->i_state = STATE_NOSYNC;            block_BytestreamFlush( &p_sys->bytestream );            if( p_sys->p_frame )                block_ChainRelease( p_sys->p_frame );            p_sys->p_frame = NULL;            p_sys->slice.i_frame_type = 0;            p_sys->b_slice = false;        }        block_Release( *pp_block );        return NULL;    }    block_BytestreamPush( &p_sys->bytestream, *pp_block );    for( ;; )    {        bool b_used_ts;        switch( p_sys->i_state )        {            case STATE_NOSYNC:                /* Skip until 3 byte startcode 0 0 1 */                if( block_FindStartcodeFromOffset( &p_sys->bytestream,                      &p_sys->i_offset, p_sys->startcode+1, 3 ) == VLC_SUCCESS)                {                    p_sys->i_state = STATE_NEXT_SYNC;                }                if( p_sys->i_offset )                {                    /* skip the data */                    block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );                    p_sys->i_offset = 0;                    block_BytestreamFlush( &p_sys->bytestream );                }                if( p_sys->i_state != STATE_NEXT_SYNC )                {                    /* Need more data */                    return NULL;                }                p_sys->i_offset = 1; /* To find next startcode */            case STATE_NEXT_SYNC:                /* Find the next 3 byte startcode 0 0 1*/                if( block_FindStartcodeFromOffset( &p_sys->bytestream,                      &p_sys->i_offset, p_sys->startcode+1, 3 ) != VLC_SUCCESS)                {                    /* Need more data */                    return NULL;                }                block_BytestreamFlush( &p_sys->bytestream );                /* Get the new fragment and set the pts/dts */                block_t *p_block_bytestream = p_sys->bytestream.p_block;                p_pic = block_New( p_dec, p_sys->i_offset +1 );                p_pic->i_pts = p_block_bytestream->i_pts;                p_pic->i_dts = p_block_bytestream->i_dts;                /* Force 4 byte startcode 0 0 0 1 */                p_pic->p_buffer[0] = 0;                block_GetBytes( &p_sys->bytestream, &p_pic->p_buffer[1],                                p_pic->i_buffer-1 );                /* Remove trailing 0 bytes */                while( p_pic->i_buffer && (!p_pic->p_buffer[p_pic->i_buffer-1] ) )                    p_pic->i_buffer--;                p_sys->i_offset = 0;                /* Parse the NAL */                p_pic = ParseNALBlock( p_dec, &b_used_ts, p_pic );                if( b_used_ts )                {                    p_block_bytestream->i_dts = -1;                    p_block_bytestream->i_pts = -1;                }                if( !p_pic )                {                    p_sys->i_state = STATE_NOSYNC;                    break;                }#if 0                msg_Dbg( p_dec, "pts=%"PRId64" dts=%"PRId64,                         p_pic->i_pts, p_pic->i_dts );#endif                /* So p_block doesn't get re-added several times */                *pp_block = block_BytestreamPop( &p_sys->bytestream );                p_sys->i_state = STATE_NOSYNC;                return p_pic;        }    }}/**************************************************************************** * PacketizeAVC1: Takes VCL blocks of data and creates annexe B type NAL stream * Will always use 4 byte 0 0 0 1 startcodes * Will prepend a SPS and PPS before each keyframe ****************************************************************************/static block_t *PacketizeAVC1( decoder_t *p_dec, block_t **pp_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    block_t       *p_block;    block_t       *p_ret = NULL;    uint8_t       *p;    if( !pp_block || !*pp_block )        return NULL;    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )    {        block_Release( *pp_block );        return NULL;    }    p_block = *pp_block;    *pp_block = NULL;    for( p = p_block->p_buffer; p < &p_block->p_buffer[p_block->i_buffer]; )    {        block_t *p_pic;        bool b_dummy;        int i_size = 0;        int i;        for( i = 0; i < p_sys->i_avcC_length_size; i++ )        {            i_size = (i_size << 8) | (*p++);        }        if( i_size <= 0 ||            i_size > ( p_block->p_buffer + p_block->i_buffer - p ) )        {            msg_Err( p_dec, "Broken frame : size %d is too big", i_size );            break;        }        block_t *p_part = CreateAnnexbNAL( p_dec, p, i_size );        if( !p_part )            break;        p_part->i_dts = p_block->i_dts;        p_part->i_pts = p_block->i_pts;        /* Parse the NAL */        if( ( p_pic = ParseNALBlock( p_dec, &b_dummy, p_part ) ) )        {            block_ChainAppend( &p_ret, p_pic );        }        p += i_size;    }    block_Release( p_block );    return p_ret;}/**************************************************************************** * Helpers ****************************************************************************/static block_t *CreateAnnexbNAL( decoder_t *p_dec, const uint8_t *p, int i_size ){    block_t *p_nal;    p_nal = block_New( p_dec, 4 + i_size );    if( !p_nal ) return NULL;    /* Add start code */    p_nal->p_buffer[0] = 0x00;    p_nal->p_buffer[1] = 0x00;    p_nal->p_buffer[2] = 0x00;    p_nal->p_buffer[3] = 0x01;    /* Copy nalu */    memcpy( &p_nal->p_buffer[4], p, i_size );    VLC_UNUSED(p_dec);    return p_nal;}static void CreateDecodedNAL( uint8_t **pp_ret, int *pi_ret,                              const uint8_t *src, int i_src ){    const uint8_t *end = &src[i_src];    uint8_t *dst = malloc( i_src );    *pp_ret = dst;    if( dst )    {        while( src < end )        {            if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00 &&                src[2] == 0x03 )            {                *dst++ = 0x00;                *dst++ = 0x00;                src += 3;                continue;            }            *dst++ = *src++;        }    }    *pi_ret = dst - *pp_ret;}static inline int bs_read_ue( bs_t *s ){    int i = 0;    while( bs_read1( s ) == 0 && s->p < s->p_end && i < 32 )    {        i++;    }    return( ( 1 << i) - 1 + bs_read( s, i ) );}static inline int bs_read_se( bs_t *s ){    int val = bs_read_ue( s );    return val&0x01 ? (val+1)/2 : -(val/2);}/***************************************************************************** * ParseNALBlock: parses annexB type NALs * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode *****************************************************************************/static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag ){    decoder_sys_t *p_sys = p_dec->p_sys;    block_t *p_pic = NULL;    const int i_nal_ref_idc = (p_frag->p_buffer[4] >> 5)&0x03;    const int i_nal_type = p_frag->p_buffer[4]&0x1f;    const mtime_t i_frag_dts = p_frag->i_dts;    const mtime_t i_frag_pts = p_frag->i_pts;    if( p_sys->b_slice && ( !p_sys->b_sps || !p_sys->b_pps ) )    {        block_ChainRelease( p_sys->p_frame );        msg_Warn( p_dec, "waiting for SPS/PPS" );        /* Reset context */        p_sys->slice.i_frame_type = 0;        p_sys->p_frame = NULL;        p_sys->b_slice = false;    }    if( ( !p_sys->b_sps || !p_sys->b_pps ) &&        i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR )    {        p_sys->b_slice = true;        /* Fragment will be discarded later on */    }    else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR )    {        slice_t slice;        bool  b_new_picture;        ParseSlice( p_dec, &b_new_picture, &slice, i_nal_ref_idc, i_nal_type, p_frag );        /* */        if( b_new_picture && p_sys->b_slice )            p_pic = OutputPicture( p_dec );        /* */        p_sys->slice = slice;        p_sys->b_slice = true;    }    else if( i_nal_type == NAL_SPS )    {        if( p_sys->b_slice )            p_pic = OutputPicture( p_dec );        PutSPS( p_dec, p_frag );        /* Do not append the SPS because we will insert it on keyframes */        p_frag = NULL;    }    else if( i_nal_type == NAL_PPS )    {        if( p_sys->b_slice )            p_pic = OutputPicture( p_dec );        PutPPS( p_dec, p_frag );        /* Do not append the PPS because we will insert it on keyframes */        p_frag = NULL;    }    else if( i_nal_type == NAL_AU_DELIMITER ||             i_nal_type == NAL_SEI ||             ( i_nal_type >= 13 && i_nal_type <= 18 ) )    {        if( p_sys->b_slice )            p_pic = OutputPicture( p_dec );        /* TODO parse SEI for CC support */    }

⌨️ 快捷键说明

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