Example #1
0
File: hevc.c Project: etix/vlc
static block_t * ParseAUTail(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_nalb)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_ret = NULL;

    block_ChainLastAppend(&p_sys->post.pp_chain_last, p_nalb);

    switch(i_nal_type)
    {
        case HEVC_NAL_EOS:
        case HEVC_NAL_EOB:
            p_ret = OutputQueues(p_sys, true);
            break;

        case HEVC_NAL_SUFF_SEI:
            HxxxParse_AnnexB_SEI( p_nalb->p_buffer, p_nalb->i_buffer,
                                  2 /* nal header */, ParseSEICallback, p_dec );
            break;
    }

    if(!p_ret && p_sys->frame.p_chain == NULL)
        p_ret = OutputQueues(p_sys, false);

    return p_ret;
}
Example #2
0
File: h264.c Project: r1k/vlc
/*****************************************************************************
 * 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_ts_used, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_pic = NULL;
    bool b_new_picture = false;

    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->pp_frame_last = &p_sys->p_frame;
        p_sys->b_frame_sps = false;
        p_sys->b_frame_pps = false;
        p_sys->b_slice = false;
        cc_storage_reset( p_sys->p_ccs );
    }

    if( ( !p_sys->b_sps || !p_sys->b_pps ) &&
        i_nal_type >= H264_NAL_SLICE && i_nal_type <= H264_NAL_SLICE_IDR )
    {
        p_sys->b_slice = true;
        /* Fragment will be discarded later on */
    }
    else if( i_nal_type >= H264_NAL_SLICE && i_nal_type <= H264_NAL_SLICE_IDR )
    {
        slice_t slice;

        if(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 == H264_NAL_SPS )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );
        p_sys->b_frame_sps = true;

        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 == H264_NAL_PPS )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );
        p_sys->b_frame_pps = true;

        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 == H264_NAL_AU_DELIMITER ||
             i_nal_type == H264_NAL_SEI ||
             ( i_nal_type >= H264_NAL_PREFIX && i_nal_type <= H264_NAL_RESERVED_18 ) )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );

        /* Parse SEI for CC support */
        if( i_nal_type == H264_NAL_SEI )
        {
            HxxxParse_AnnexB_SEI( p_frag->p_buffer, p_frag->i_buffer,
                                  1 /* nal header */, ParseSeiCallback, p_dec );
        }
        else if( i_nal_type == H264_NAL_AU_DELIMITER )
        {
            if( p_sys->p_frame && (p_sys->p_frame->i_flags & BLOCK_FLAG_PRIVATE_AUD) )
            {
                block_Release( p_frag );
                p_frag = NULL;
            }
            else
            {
                p_frag->i_flags |= BLOCK_FLAG_PRIVATE_AUD;
            }
        }
    }

    /* Append the block */
    if( p_frag )
        block_ChainLastAppend( &p_sys->pp_frame_last, p_frag );

    *pb_ts_used = false;
    if( p_sys->i_frame_dts <= VLC_TS_INVALID &&
        p_sys->i_frame_pts <= VLC_TS_INVALID && b_new_picture )
    {
        p_sys->i_frame_dts = i_frag_dts;
        p_sys->i_frame_pts = i_frag_pts;
        *pb_ts_used = true;
    }
    return p_pic;
}
Example #3
0
File: hevc.c Project: etix/vlc
static block_t * ParseAUHead(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_nalb)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_ret = NULL;

    if(p_sys->post.p_chain || p_sys->frame.p_chain)
        p_ret = OutputQueues(p_sys, true);

    switch(i_nal_type)
    {
        case HEVC_NAL_AUD:
            if(!p_ret && p_sys->pre.p_chain)
                p_ret = OutputQueues(p_sys, true);
            break;

        case HEVC_NAL_VPS:
        case HEVC_NAL_SPS:
        case HEVC_NAL_PPS:
        {
            uint8_t i_id;
            if( hevc_get_xps_id(p_nalb->p_buffer, p_nalb->i_buffer, &i_id) &&
                InsertXPS(p_dec, i_nal_type, i_id, p_nalb) )
            {
                const hevc_sequence_parameter_set_t *p_sps;
                if( i_nal_type == HEVC_NAL_SPS &&
                   (p_sps = p_dec->p_sys->rgi_p_decsps[i_id]) )
                {
                    if(!p_dec->fmt_out.video.i_frame_rate)
                    {
                        (void) hevc_get_frame_rate( p_sps, p_dec->p_sys->rgi_p_decvps,
                                                    &p_dec->fmt_out.video.i_frame_rate,
                                                    &p_dec->fmt_out.video.i_frame_rate_base );
                    }

                    if(p_dec->fmt_out.video.primaries == COLOR_PRIMARIES_UNDEF)
                    {
                        (void) hevc_get_colorimetry( p_sps,
                                                     &p_dec->fmt_out.video.primaries,
                                                     &p_dec->fmt_out.video.transfer,
                                                     &p_dec->fmt_out.video.space,
                                                     &p_dec->fmt_out.video.b_color_range_full);
                    }

                    unsigned sizes[4];
                    if( hevc_get_picture_size( p_sps, &sizes[0], &sizes[1],
                                                      &sizes[2], &sizes[3] ) )
                    {
                        if( p_dec->fmt_out.video.i_width != sizes[0] ||
                            p_dec->fmt_out.video.i_height != sizes[1] )
                        {
                            p_dec->fmt_out.video.i_width = sizes[0];
                            p_dec->fmt_out.video.i_height = sizes[1];
                        }
                    }

                    if(p_dec->fmt_out.i_profile == -1)
                    {
                        uint8_t i_profile, i_level;
                        if( hevc_get_sps_profile_tier_level( p_sps, &i_profile, &i_level ) )
                        {
                            p_dec->fmt_out.i_profile = i_profile;
                            p_dec->fmt_out.i_level = i_level;
                        }
                    }
                }
            }
            break;
        }

        case HEVC_NAL_PREF_SEI:
            HxxxParse_AnnexB_SEI( p_nalb->p_buffer, p_nalb->i_buffer,
                                  2 /* nal header */, ParseSEICallback, p_dec );
            break;

        default:
            break;
    }

    block_ChainLastAppend(&p_sys->pre.pp_chain_last, p_nalb);

    return p_ret;
}
Example #4
0
File: h264.c Project: IAPark/vlc
/*****************************************************************************
 * 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_ts_used, block_t *p_frag )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_pic = NULL;
    bool b_new_picture = false;

    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->p_active_pps || !p_sys->p_active_sps) )
    {
        msg_Warn( p_dec, "waiting for SPS/PPS" );

        /* Reset context */
        p_sys->slice.type = H264_SLICE_TYPE_UNKNOWN;
        p_sys->b_slice = false;
        DropStoredNAL( p_sys );
        /* From SEI */
        p_sys->i_dpb_output_delay = 0;
        p_sys->i_pic_struct = UINT8_MAX;
        cc_storage_reset( p_sys->p_ccs );
    }

    if( i_nal_type >= H264_NAL_SLICE && i_nal_type <= H264_NAL_SLICE_IDR )
    {
        h264_slice_t newslice;

        if( i_nal_type == H264_NAL_SLICE_IDR )
        {
            p_sys->b_recovered = true;
            p_sys->i_recovery_frame_cnt = UINT_MAX;
            p_sys->i_recoveryfnum = UINT_MAX;
        }

        if( ParseSliceHeader( p_dec, p_frag, &newslice ) )
        {
            /* Only IDR carries the id, to be propagated */
            if( newslice.i_idr_pic_id == -1 )
                newslice.i_idr_pic_id = p_sys->slice.i_idr_pic_id;

            b_new_picture = IsFirstVCLNALUnit( &p_sys->slice, &newslice );
            if( b_new_picture )
            {
                /* Parse SEI for that frame now we should have matched SPS/PPS */
                for( block_t *p_sei = p_sys->p_sei; p_sei; p_sei = p_sei->p_next )
                {
                    HxxxParse_AnnexB_SEI( p_sei->p_buffer, p_sei->i_buffer,
                                          1 /* nal header */, ParseSeiCallback, p_dec );
                }

                if( p_sys->b_slice )
                    p_pic = OutputPicture( p_dec );
            }

            /* */
            p_sys->slice = newslice;
        }
        else
        {
            p_sys->p_active_pps = NULL;
            /* Fragment will be discarded later on */
        }
        p_sys->b_slice = true;
    }
    else if( i_nal_type == H264_NAL_SPS )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );

        PutSPS( p_dec, p_frag );
        p_sys->b_new_sps = true;

        /* Do not append the SPS because we will insert it on keyframes */
        p_frag = NULL;
    }
    else if( i_nal_type == H264_NAL_PPS )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );

        PutPPS( p_dec, p_frag );
        p_sys->b_new_pps = true;

        /* Do not append the PPS because we will insert it on keyframes */
        p_frag = NULL;
    }
    else if( i_nal_type == H264_NAL_SEI )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );

        block_ChainLastAppend( &p_sys->pp_sei_last, p_frag );
        p_frag = NULL;
    }
    else if( i_nal_type == H264_NAL_END_OF_SEQ || i_nal_type == H264_NAL_END_OF_STREAM )
    {
        /* Early end of packetization */
        block_ChainLastAppend( &p_sys->pp_sei_last, p_frag );
        p_frag = NULL;
        /* important for still pictures/menus */
        p_sys->i_next_block_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );
    }
    else if( i_nal_type == H264_NAL_AU_DELIMITER ||
             ( i_nal_type >= H264_NAL_PREFIX && i_nal_type <= H264_NAL_RESERVED_18 ) )
    {
        if( p_sys->b_slice )
            p_pic = OutputPicture( p_dec );

        if( i_nal_type == H264_NAL_AU_DELIMITER )
        {
            if( p_sys->p_frame && (p_sys->p_frame->i_flags & BLOCK_FLAG_PRIVATE_AUD) )
            {
                block_Release( p_frag );
                p_frag = NULL;
            }
            else
            {
                p_frag->i_flags |= BLOCK_FLAG_PRIVATE_AUD;
            }
        }
    }

    /* Append the block */
    if( p_frag )
        block_ChainLastAppend( &p_sys->pp_frame_last, p_frag );

    *pb_ts_used = false;
    if( p_sys->i_frame_dts <= VLC_TS_INVALID &&
        p_sys->i_frame_pts <= VLC_TS_INVALID && b_new_picture )
    {
        p_sys->i_frame_dts = i_frag_dts;
        p_sys->i_frame_pts = i_frag_pts;
        *pb_ts_used = true;
        if( i_frag_dts > VLC_TS_INVALID )
            date_Set( &p_sys->dts, i_frag_dts );
    }

    if( p_pic && (p_pic->i_flags & BLOCK_FLAG_DROP) )
    {
        block_Release( p_pic );
        p_pic = NULL;
    }

    return p_pic;
}