/* * * Copyright 2015 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @file h265d_parser.c * @brief * @author csy(csy@rock-chips.com) * @version 1.0.0 * @history * 2015.7.15 : Create */ #define MODULE_TAG "H265D_PARSER" #include "mpp_env.h" #include "mpp_mem.h" #include "mpp_bitread.h" #include "mpp_packet_impl.h" #include "h265d_parser.h" #include "h265d_syntax.h" #include "h265d_api.h" #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes RK_U32 h265d_debug; #ifdef dump FILE *fp = NULL; #endif //static RK_U32 start_write = 0, value = 0; /** * Find the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or END_NOT_FOUND */ static RK_S32 hevc_find_frame_end(SplitContext_t *sc, const RK_U8 *buf, int buf_size) { RK_S32 i; for (i = 0; i < buf_size; i++) { int nut, layer_id; sc->state64 = (sc->state64 << 8) | buf[i]; if (((sc->state64 >> 3 * 8) & 0xFFFFFF) != START_CODE) continue; nut = (sc->state64 >> (2 * 8 + 1)) & 0x3F; layer_id = (((sc->state64 >> 2 * 8) & 0x01) << 5) + (((sc->state64 >> 1 * 8) & 0xF8) >> 3); //mpp_log("nut = %d layer_id = %d\n",nut,layer_id); // Beginning of access unit if ((nut >= NAL_VPS && nut <= NAL_AUD) || nut == NAL_SEI_PREFIX || (nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) { if (sc->frame_start_found && !layer_id) { sc->frame_start_found = 0; return i - 5; } } else if (nut <= NAL_RASL_R || (nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT)) { int first_slice_segment_in_pic_flag = buf[i] >> 7; //mpp_log("nut = %d first_slice_segment_in_pic_flag %d layer_id = %d \n",nut, // first_slice_segment_in_pic_flag, // layer_id); if (first_slice_segment_in_pic_flag && !layer_id) { if (!sc->frame_start_found) { sc->frame_start_found = 1; } else { // First slice of next frame found sc->frame_start_found = 0; return i - 5; } } } } return END_NOT_FOUND; } static RK_S32 mpp_combine_frame(SplitContext_t *sc, RK_S32 next, const RK_U8 **buf, RK_S32 *buf_size) { if (sc->overread) { mpp_log("overread %d, state:%X next:%d index:%d o_index:%d\n", sc->overread, sc->state, next, sc->index, sc->overread_index); mpp_log("%X %X %X %X\n", (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); } /* Copy overread bytes from last frame into buffer. */ for (; sc->overread > 0; sc->overread--) { sc->buffer[sc->index++] = sc->buffer[sc->overread_index++]; } /* flush remaining if EOF */ if (!*buf_size && next == END_NOT_FOUND) { next = 0; } sc->last_index = sc->index; /* copy into buffer end return */ if (next == END_NOT_FOUND) { RK_U32 min_size = (*buf_size) + sc->index + MPP_INPUT_BUFFER_PADDING_SIZE; void* new_buffer; if (min_size > sc->buffer_size) { min_size = MPP_MAX(17 * min_size / 16 + 32, min_size); new_buffer = mpp_realloc(sc->buffer, RK_U8, min_size); if (!new_buffer) { sc->buffer_size = 0; return MPP_ERR_NOMEM; } sc->buffer_size = min_size; sc->buffer = new_buffer; } memcpy(&sc->buffer[sc->index], *buf, *buf_size); sc->index += *buf_size; return -1; } *buf_size = sc->overread_index = sc->index + next; /* append to buffer */ if (sc->index) { RK_U32 min_size = next + sc->index + MPP_INPUT_BUFFER_PADDING_SIZE; void* new_buffer; if (min_size > sc->buffer_size) { min_size = MPP_MAX(17 * min_size / 16 + 32, min_size); new_buffer = mpp_realloc(sc->buffer, RK_U8, min_size); if (!new_buffer) { sc->buffer_size = 0; return MPP_ERR_NOMEM; } sc->buffer_size = min_size; sc->buffer = new_buffer; } if (next > -MPP_INPUT_BUFFER_PADDING_SIZE) memcpy(&sc->buffer[sc->index], *buf, next + MPP_INPUT_BUFFER_PADDING_SIZE); sc->index = 0; *buf = sc->buffer; } /* store overread bytes */ for (; next < 0; next++) { sc->state = (sc->state << 8) | sc->buffer[sc->last_index + next]; sc->state64 = (sc->state64 << 8) | sc->buffer[sc->last_index + next]; sc->overread++; } if (sc->overread) { mpp_log("overread %d, state:%X next:%d index:%d o_index:%d\n", sc->overread, sc->state, next, sc->index, sc->overread_index); mpp_log("%X %X %X %X\n", (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); } return 0; } static RK_S32 h265d_split_init(void **sc) { SplitContext_t *s = NULL; if (s == NULL) { s = mpp_calloc(SplitContext_t, 1); if (s != NULL) { *sc = s; } else { mpp_err("split alloc context fail"); return MPP_ERR_NOMEM; } } s->buffer = mpp_malloc(RK_U8, MAX_FRAME_SIZE); s->buffer_size = MAX_FRAME_SIZE; s->fetch_timestamp = 1; return MPP_OK; } static void mpp_fetch_timestamp(SplitContext_t *s, RK_S32 off) { RK_S32 i; s->dts = s->pts = -1; s->offset = 0; for (i = 0; i < MPP_PARSER_PTS_NB; i++) { h265d_dbg(H265D_DBG_TIME, "s->cur_offset %lld s->cur_frame_offset[%d] %lld s->frame_offset %lld s->next_frame_offset %lld", s->cur_offset, i, s->cur_frame_offset[i], s->frame_offset, s->next_frame_offset); if ( s->cur_offset + off >= s->cur_frame_offset[i] && (s->frame_offset < s->cur_frame_offset[i] || (!s->frame_offset && !s->next_frame_offset)) // first field/frame // check disabled since MPEG-TS does not send complete PES packets && /*s->next_frame_offset + off <*/ s->cur_frame_end[i]) { s->dts = s->cur_frame_dts[i]; s->pts = s->cur_frame_pts[i]; s->offset = s->next_frame_offset - s->cur_frame_offset[i]; if (s->cur_offset + off < s->cur_frame_end[i]) break; } } } static RK_S32 h265d_split_frame(void *sc, const RK_U8 **poutbuf, RK_S32 *poutbuf_size, const RK_U8 *buf, RK_S32 buf_size, RK_S64 pts, RK_S64 dts) { RK_S32 next, i; SplitContext_t *s = (SplitContext_t*)sc; if (s->cur_offset + buf_size != s->cur_frame_end[s->cur_frame_start_index]) { /* skip remainder packets */ /* add a new packet descriptor */ i = (s->cur_frame_start_index + 1) & (MPP_PARSER_PTS_NB - 1); s->cur_frame_start_index = i; s->cur_frame_offset[i] = s->cur_offset; s->cur_frame_end[i] = s->cur_offset + buf_size; s->cur_frame_pts[i] = pts; s->cur_frame_dts[i] = dts; h265d_dbg(H265D_DBG_TIME, "s->cur_frame_start_index = %d,cur_frame_offset = %lld,s->cur_frame_end = %lld pts = %lld", s->cur_frame_start_index, s->cur_frame_offset[i], s->cur_frame_end[i], pts); } if (s->fetch_timestamp) { s->fetch_timestamp = 0; s->last_pts = s->pts; s->last_dts = s->dts; mpp_fetch_timestamp(s, 0); } if (s->eos && !buf_size) { *poutbuf = s->buffer; *poutbuf_size = s->index; return 0; } next = hevc_find_frame_end(s, buf, buf_size); if (s->eos && buf_size && next == END_NOT_FOUND) { next = buf_size; } if (mpp_combine_frame(s, next, &buf, &buf_size) < 0) { *poutbuf = NULL; *poutbuf_size = 0; s->cur_offset += buf_size; return buf_size; } *poutbuf = buf; *poutbuf_size = buf_size; if (next < 0) next = 0; if (*poutbuf_size) { /* fill the data for the current frame */ s->frame_offset = s->next_frame_offset; /* offset of the next frame */ s->next_frame_offset = s->cur_offset + next; s->fetch_timestamp = 1; } s->cur_offset += next; return next; } static RK_S32 h265d_split_reset(void *sc) { RK_U8 *buf = NULL; RK_U32 size = 0; SplitContext_t *s = (SplitContext_t*)sc; if (sc == NULL) { return MPP_OK; } buf = s->buffer; size = s->buffer_size; memset(s, 0, sizeof(SplitContext_t)); s->fetch_timestamp = 1; s->buffer = buf; s->buffer_size = size; s->eos = 0; return MPP_OK; } static RK_S32 h265d_split_deinit(void *sc) { SplitContext_t *s = (SplitContext_t *)sc; if (s->buffer) { mpp_free(s->buffer); s->buffer = NULL; } if (s) { mpp_free(s); s = NULL; } return MPP_OK; } static RK_S32 pred_weight_table(HEVCContext *s, BitReadCtx_t *gb) { RK_U32 i = 0; RK_U32 j = 0; RK_U8 luma_weight_l0_flag[16]; RK_U8 chroma_weight_l0_flag[16]; RK_U8 luma_weight_l1_flag[16]; RK_U8 chroma_weight_l1_flag[16]; READ_UE(gb, &s->sh.luma_log2_weight_denom); if (s->sps->chroma_format_idc != 0) { RK_S32 delta = 0; READ_SE(gb, &delta); s->sh.chroma_log2_weight_denom = mpp_clip(s->sh.luma_log2_weight_denom + delta, 0, 7); } for (i = 0; i < s->sh.nb_refs[L0]; i++) { READ_ONEBIT(gb, &luma_weight_l0_flag[i]); if (!luma_weight_l0_flag[i]) { s->sh.luma_weight_l0[i] = 1 << s->sh.luma_log2_weight_denom; s->sh.luma_offset_l0[i] = 0; } } if (s->sps->chroma_format_idc != 0) { // FIXME: invert "if" and "for" for (i = 0; i < s->sh.nb_refs[L0]; i++) { READ_ONEBIT(gb, &chroma_weight_l0_flag[i]); } } else { for (i = 0; i < s->sh.nb_refs[L0]; i++) chroma_weight_l0_flag[i] = 0; } for (i = 0; i < s->sh.nb_refs[L0]; i++) { if (luma_weight_l0_flag[i]) { RK_S32 delta_luma_weight_l0 = 0; READ_SE(gb, &delta_luma_weight_l0); s->sh.luma_weight_l0[i] = (1 << s->sh.luma_log2_weight_denom) + delta_luma_weight_l0; READ_SE(gb, &s->sh.luma_offset_l0[i]); } if (chroma_weight_l0_flag[i]) { for (j = 0; j < 2; j++) { RK_S32 delta_chroma_weight_l0 = 0; RK_S32 delta_chroma_offset_l0 = 0; READ_SE(gb, &delta_chroma_weight_l0); READ_SE(gb, &delta_chroma_offset_l0); s->sh.chroma_weight_l0[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l0; s->sh.chroma_offset_l0[i][j] = mpp_clip((delta_chroma_offset_l0 - ((128 * s->sh.chroma_weight_l0[i][j]) >> s->sh.chroma_log2_weight_denom) + 128), -128, 127); } } else { s->sh.chroma_weight_l0[i][0] = 1 << s->sh.chroma_log2_weight_denom; s->sh.chroma_offset_l0[i][0] = 0; s->sh.chroma_weight_l0[i][1] = 1 << s->sh.chroma_log2_weight_denom; s->sh.chroma_offset_l0[i][1] = 0; } } if (s->sh.slice_type == B_SLICE) { for (i = 0; i < s->sh.nb_refs[L1]; i++) { READ_ONEBIT(gb, &luma_weight_l1_flag[i]); if (!luma_weight_l1_flag[i]) { s->sh.luma_weight_l1[i] = 1 << s->sh.luma_log2_weight_denom; s->sh.luma_offset_l1[i] = 0; } } if (s->sps->chroma_format_idc != 0) { for (i = 0; i < s->sh.nb_refs[L1]; i++) READ_ONEBIT(gb, &chroma_weight_l1_flag[i]); } else { for (i = 0; i < s->sh.nb_refs[L1]; i++) chroma_weight_l1_flag[i] = 0; } for (i = 0; i < s->sh.nb_refs[L1]; i++) { if (luma_weight_l1_flag[i]) { RK_S32 delta_luma_weight_l1 = 0; READ_UE(gb, &delta_luma_weight_l1); s->sh.luma_weight_l1[i] = (1 << s->sh.luma_log2_weight_denom) + delta_luma_weight_l1; READ_SE(gb, &s->sh.luma_offset_l1[i]); } if (chroma_weight_l1_flag[i]) { for (j = 0; j < 2; j++) { RK_S32 delta_chroma_weight_l1 = 0; RK_S32 delta_chroma_offset_l1 = 0; READ_SE(gb, &delta_chroma_weight_l1); READ_SE(gb, &delta_chroma_offset_l1); s->sh.chroma_weight_l1[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l1; s->sh.chroma_offset_l1[i][j] = mpp_clip((delta_chroma_offset_l1 - ((128 * s->sh.chroma_weight_l1[i][j]) >> s->sh.chroma_log2_weight_denom) + 128), -128, 127); } } else { s->sh.chroma_weight_l1[i][0] = 1 << s->sh.chroma_log2_weight_denom; s->sh.chroma_offset_l1[i][0] = 0; s->sh.chroma_weight_l1[i][1] = 1 << s->sh.chroma_log2_weight_denom; s->sh.chroma_offset_l1[i][1] = 0; } } } return 0; __BITREAD_ERR: return MPP_ERR_STREAM; } static RK_S32 decode_lt_rps(HEVCContext *s, LongTermRPS *rps, BitReadCtx_t *gb) { const HEVCSPS *sps = s->sps; RK_S32 max_poc_lsb = 1 << sps->log2_max_poc_lsb; RK_S32 prev_delta_msb = 0; RK_U32 nb_sps = 0, nb_sh; RK_S32 i; RK_S32 bit_begin = gb->used_bits; s->rps_bit_offset[s->slice_idx] = s->rps_bit_offset_st[s->slice_idx]; rps->nb_refs = 0; if (!sps->long_term_ref_pics_present_flag) return 0; if (sps->num_long_term_ref_pics_sps > 0) READ_UE(gb, &nb_sps); READ_UE(gb, &nb_sh); if (nb_sh + nb_sps > MPP_ARRAY_ELEMS(rps->poc)) return MPP_ERR_STREAM; rps->nb_refs = nb_sh + nb_sps; for (i = 0; i < rps->nb_refs; i++) { RK_U8 delta_poc_msb_present; if ((RK_U32)i < nb_sps) { RK_U8 lt_idx_sps = 0; if (sps->num_long_term_ref_pics_sps > 1) READ_BITS(gb, mpp_ceil_log2(sps->num_long_term_ref_pics_sps), <_idx_sps); rps->poc[i] = sps->lt_ref_pic_poc_lsb_sps[lt_idx_sps]; rps->used[i] = sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps]; } else { READ_BITS(gb, sps->log2_max_poc_lsb, &rps->poc[i]); READ_ONEBIT(gb, &rps->used[i]); } READ_ONEBIT(gb, &delta_poc_msb_present); if (delta_poc_msb_present) { RK_S32 delta = 0; READ_UE(gb, &delta); if (i && (RK_U32)i != nb_sps) delta += prev_delta_msb; rps->poc[i] += s->poc - delta * max_poc_lsb - s->sh.pic_order_cnt_lsb; prev_delta_msb = delta; } } s->rps_bit_offset[s->slice_idx] += (gb->used_bits - bit_begin); return 0; __BITREAD_ERR: return MPP_ERR_STREAM; } static RK_S32 set_sps(HEVCContext *s, const HEVCSPS *sps) { RK_U32 num = 0, den = 0; MppFrameFormat fmt = s->h265dctx->cfg->base.out_fmt & (~MPP_FRAME_FMT_MASK); s->h265dctx->coded_width = sps->width; s->h265dctx->coded_height = sps->height; s->h265dctx->width = sps->output_width; s->h265dctx->height = sps->output_height; s->h265dctx->pix_fmt = fmt | sps->pix_fmt; s->h265dctx->nBitDepth = sps->bit_depth; s->h265dctx->sample_aspect_ratio = sps->vui.sar; if (sps->vui.video_signal_type_present_flag) s->h265dctx->color_range = sps->vui.video_full_range_flag ? MPP_FRAME_RANGE_JPEG : MPP_FRAME_RANGE_MPEG; else s->h265dctx->color_range = MPP_FRAME_RANGE_MPEG; if (sps->vui.colour_description_present_flag) { s->h265dctx->colorspace = sps->vui.matrix_coeffs; } else { s->h265dctx->colorspace = MPP_FRAME_SPC_UNSPECIFIED; } s->sps = sps; s->vps = (HEVCVPS*) s->vps_list[s->sps->vps_id]; if (s->vps->vps_timing_info_present_flag) { num = s->vps->vps_num_units_in_tick; den = s->vps->vps_time_scale; } else if (sps->vui.vui_timing_info_present_flag) { num = sps->vui.vui_num_units_in_tick; den = sps->vui.vui_time_scale; } if (num != 0 && den != 0) { // s->h265dctx->time_base.num = num; // s->h265dctx->time_base.den = den; // av_reduce(&s->h265dctx->time_base.num, &s->h265dctx->time_base.den, // num, den, 1 << 30); } return 0; } static RK_S32 compare_sliceheader(SliceHeader *openhevc_sh, SliceHeader *sh) { if (openhevc_sh->pps_id != sh->pps_id) { mpp_log(" pps_id diff \n"); return -1; } if (openhevc_sh->slice_type != sh->slice_type) { mpp_log(" slice_type diff \n"); return -1; } if (openhevc_sh->pic_order_cnt_lsb != sh->pic_order_cnt_lsb) { mpp_log(" pic_order_cnt_lsb diff \n"); return -1; } if (openhevc_sh->first_slice_in_pic_flag != sh->first_slice_in_pic_flag) { mpp_log(" first_slice_in_pic_flag diff \n"); return -1; } if (openhevc_sh->dependent_slice_segment_flag != sh->dependent_slice_segment_flag) { mpp_log(" dependent_slice_segment_flag diff \n"); return -1; } if (openhevc_sh->pic_output_flag != sh->pic_output_flag) { mpp_log(" pic_output_flag diff \n"); return -1; } if (openhevc_sh->colour_plane_id != sh->colour_plane_id) { mpp_log(" colour_plane_id diff \n"); return -1; } if (openhevc_sh->rpl_modification_flag[0] != sh->rpl_modification_flag[0]) { mpp_log(" rpl_modification_flag[0] diff \n"); return -1; } if (openhevc_sh->rpl_modification_flag[1] != sh->rpl_modification_flag[1]) { mpp_log(" rpl_modification_flag[1] diff \n"); return -1; } if (openhevc_sh->no_output_of_prior_pics_flag != sh->no_output_of_prior_pics_flag) { mpp_log(" no_output_of_prior_pics_flag diff \n"); return -1; } if (openhevc_sh->slice_temporal_mvp_enabled_flag != sh->slice_temporal_mvp_enabled_flag) { mpp_log(" slice_temporal_mvp_enabled_flag diff \n"); return -1; } if (openhevc_sh->nb_refs[0] != sh->nb_refs[0]) { mpp_log(" nb_refs[0] diff \n"); return -1; } if (openhevc_sh->nb_refs[1] != sh->nb_refs[1]) { mpp_log(" nb_refs[1] diff \n"); return -1; } if (openhevc_sh->slice_sample_adaptive_offset_flag[0] != sh->slice_sample_adaptive_offset_flag[0]) { mpp_log(" slice_sample_adaptive_offset_flag[0] diff \n"); return -1; } if (openhevc_sh->slice_sample_adaptive_offset_flag[1] != sh->slice_sample_adaptive_offset_flag[1]) { mpp_log(" slice_sample_adaptive_offset_flag[1] diff \n"); return -1; } if (openhevc_sh->slice_sample_adaptive_offset_flag[2] != sh->slice_sample_adaptive_offset_flag[2]) { mpp_log(" slice_sample_adaptive_offset_flag[2] diff \n"); return -1; } if (openhevc_sh->mvd_l1_zero_flag != sh->mvd_l1_zero_flag) { mpp_log(" mvd_l1_zero_flag diff \n"); return -1; } if (openhevc_sh->cabac_init_flag != sh->cabac_init_flag) { mpp_log(" cabac_init_flag diff \n"); return -1; } if (openhevc_sh->disable_deblocking_filter_flag != sh->disable_deblocking_filter_flag) { mpp_log(" disable_deblocking_filter_flag diff \n"); return -1; } if (openhevc_sh->slice_loop_filter_across_slices_enabled_flag != sh->slice_loop_filter_across_slices_enabled_flag) { mpp_log(" slice_loop_filter_across_slices_enable diff \n"); return -1; } if (openhevc_sh->collocated_list != sh->collocated_list) { mpp_log(" collocated_list diff \n"); return -1; } if (openhevc_sh->collocated_ref_idx != sh->collocated_ref_idx) { mpp_log(" collocated_ref_idx diff \n"); return -1; } if (openhevc_sh->slice_qp_delta != sh->slice_qp_delta) { mpp_log(" slice_qp_delta diff \n"); return -1; } if (openhevc_sh->slice_cb_qp_offset != sh->slice_cb_qp_offset) { mpp_log(" slice_cb_qp_offset diff \n"); return -1; } if (openhevc_sh->slice_cr_qp_offset != sh->slice_cr_qp_offset) { mpp_log(" slice_cr_qp_offset diff \n"); return -1; } if (openhevc_sh->beta_offset != sh->beta_offset) { mpp_log(" beta_offset diff \n"); return -1; } if (openhevc_sh->tc_offset != sh->tc_offset) { mpp_log(" tc_offset diff \n"); return -1; } if (openhevc_sh->max_num_merge_cand != sh->max_num_merge_cand) { mpp_log(" max_num_merge_cand diff \n"); return -1; } if (openhevc_sh->num_entry_point_offsets != sh->num_entry_point_offsets) { mpp_log(" num_entry_point_offsets diff \n"); return -1; } if (openhevc_sh->slice_qp != sh->slice_qp) { mpp_log(" slice_qp diff \n"); return -1; } if (openhevc_sh->luma_log2_weight_denom != sh->luma_log2_weight_denom) { mpp_log(" luma_log2_weight_denom diff \n"); return -1; } if (openhevc_sh->chroma_log2_weight_denom != sh->chroma_log2_weight_denom) { mpp_log(" chroma_log2_weight_denom diff \n"); return -1; } /* if (openhevc_sh->slice_ctb_addr_rs != sh->slice_ctb_addr_rs) { mpp_log(" slice_ctb_addr_rs diff \n"); return -1; }*/ return 0; } static RK_S32 hls_slice_header(HEVCContext *s) { BitReadCtx_t *gb = &s->HEVClc->gb; SliceHeader *sh = &s->sh; RK_S32 i, ret; RK_S32 value, pps_id; RK_S32 bit_begin; #ifdef JCTVC_M0458_INTERLAYER_RPS_SIG int NumILRRefIdx; #endif // Coded parameters READ_ONEBIT(gb, &sh->first_slice_in_pic_flag); if ((IS_IDR(s) || IS_BLA(s)) && sh->first_slice_in_pic_flag) { s->seq_decode = (s->seq_decode + 1) & 0xff; s->max_ra = INT_MAX; if (IS_IDR(s)) mpp_hevc_clear_refs(s); } if (s->nal_unit_type >= 16 && s->nal_unit_type <= 23) READ_ONEBIT(gb, &sh->no_output_of_prior_pics_flag); if (IS_IRAP(s) && s->miss_ref_flag && sh->first_slice_in_pic_flag) { // mpp_err("s->nal_unit_type = %d s->poc %d",s->nal_unit_type,s->poc); s->max_ra = INT_MAX; s->miss_ref_flag = 0; } READ_UE(gb, &pps_id); if (pps_id >= MAX_PPS_COUNT || !s->pps_list[pps_id]) { mpp_err( "PPS id out of range: %d\n", pps_id); return MPP_ERR_STREAM; } else { sh->pps_id = pps_id; if (pps_id != s->pre_pps_id) { s->ps_need_upate = 1; s->pre_pps_id = pps_id; } } if (!sh->first_slice_in_pic_flag && s->pps != (HEVCPPS*)s->pps_list[sh->pps_id]) { mpp_err( "PPS changed between slices.\n"); return MPP_ERR_STREAM; } s->pps = (HEVCPPS*)s->pps_list[sh->pps_id]; if (s->sps != (HEVCSPS*)s->sps_list[s->pps->sps_id]) { s->sps = (HEVCSPS*)s->sps_list[s->pps->sps_id]; mpp_hevc_clear_refs(s); s->ps_need_upate = 1; ret = set_sps(s, s->sps); if (ret < 0) return ret; s->seq_decode = (s->seq_decode + 1) & 0xff; s->max_ra = INT_MAX; } // s->h265dctx->profile = s->sps->ptl.general_ptl.profile_idc; // s->h265dctx->level = s->sps->ptl.general_ptl.level_idc; sh->dependent_slice_segment_flag = 0; if (!sh->first_slice_in_pic_flag) { RK_S32 slice_address_length; if (s->pps->dependent_slice_segments_enabled_flag) READ_ONEBIT(gb, &sh->dependent_slice_segment_flag); slice_address_length = mpp_ceil_log2(s->sps->ctb_width * s->sps->ctb_height); READ_BITS(gb, slice_address_length, &sh->slice_segment_addr); if (sh->slice_segment_addr >= (RK_U32)(s->sps->ctb_width * s->sps->ctb_height)) { mpp_err( "Invalid slice segment address: %u.\n", sh->slice_segment_addr); return MPP_ERR_STREAM; } if (!sh->dependent_slice_segment_flag) { sh->slice_addr = sh->slice_segment_addr; s->slice_idx++; } } else { sh->slice_segment_addr = sh->slice_addr = 0; s->slice_idx = 0; s->slice_initialized = 0; } if (!sh->dependent_slice_segment_flag) { s->slice_initialized = 0; for (i = 0; i < s->pps->num_extra_slice_header_bits; i++) SKIP_BITS(gb, 1); // slice_reserved_undetermined_flag[] READ_UE(gb, &sh->slice_type); if (!(sh->slice_type == I_SLICE || sh->slice_type == P_SLICE || sh->slice_type == B_SLICE)) { mpp_err( "Unknown slice type: %d.\n", sh->slice_type); return MPP_ERR_STREAM; } if (!s->decoder_id && IS_IRAP(s) && sh->slice_type != I_SLICE) { mpp_err( "Inter slices in an IRAP frame.\n"); return MPP_ERR_STREAM; } if (s->pps->output_flag_present_flag) READ_ONEBIT(gb, &sh->pic_output_flag); if (s->sps->separate_colour_plane_flag) READ_BITS(gb, 2, &sh->colour_plane_id ); if (!IS_IDR(s)) { int poc; READ_BITS(gb, s->sps->log2_max_poc_lsb, &sh->pic_order_cnt_lsb); poc = mpp_hevc_compute_poc(s, sh->pic_order_cnt_lsb); if (!sh->first_slice_in_pic_flag && poc != s->poc) { mpp_log("Ignoring POC change between slices: %d -> %d\n", s->poc, poc); #if 0 if (s->h265dctx->err_recognition & AV_EF_EXPLODE) return MPP_ERR_STREAM; #endif poc = s->poc; } s->poc = poc; READ_ONEBIT(gb, &sh->short_term_ref_pic_set_sps_flag); bit_begin = gb->used_bits; if (!sh->short_term_ref_pic_set_sps_flag) { ret = mpp_hevc_decode_short_term_rps(s, &sh->slice_rps, s->sps, 1); if (ret < 0) return ret; sh->short_term_rps = &sh->slice_rps; } else { RK_S32 numbits, rps_idx; if (!s->sps->nb_st_rps) { mpp_err( "No ref lists in the SPS.\n"); return MPP_ERR_STREAM; } numbits = mpp_ceil_log2(s->sps->nb_st_rps); rps_idx = 0; if (numbits > 0) READ_BITS(gb, numbits, &rps_idx); sh->short_term_rps = &s->sps->st_rps[rps_idx]; } s->rps_bit_offset_st[s->slice_idx] = gb->used_bits - bit_begin; sh->short_term_ref_pic_set_size = s->rps_bit_offset_st[s->slice_idx]; ret = decode_lt_rps(s, &sh->long_term_rps, gb); if (ret < 0) { mpp_log("Invalid long term RPS.\n"); // if (s->h265dctx->err_recognition & AV_EF_EXPLODE) // return MPP_ERR_STREAM; } if (s->sps->sps_temporal_mvp_enabled_flag) READ_ONEBIT(gb, &sh->slice_temporal_mvp_enabled_flag); else sh->slice_temporal_mvp_enabled_flag = 0; } else { s->sh.short_term_rps = NULL; s->poc = 0; } /* 8.3.1 */ if (s->temporal_id == 0 && s->nal_unit_type != NAL_TRAIL_N && s->nal_unit_type != NAL_TSA_N && s->nal_unit_type != NAL_STSA_N && s->nal_unit_type != NAL_RADL_N && s->nal_unit_type != NAL_RADL_R && s->nal_unit_type != NAL_RASL_N && s->nal_unit_type != NAL_RASL_R) s->pocTid0 = s->poc; if (s->sps->sao_enabled) { READ_ONEBIT(gb, &sh->slice_sample_adaptive_offset_flag[0]); READ_ONEBIT(gb, &sh->slice_sample_adaptive_offset_flag[1]); sh->slice_sample_adaptive_offset_flag[2] = sh->slice_sample_adaptive_offset_flag[1]; } else { sh->slice_sample_adaptive_offset_flag[0] = 0; sh->slice_sample_adaptive_offset_flag[1] = 0; sh->slice_sample_adaptive_offset_flag[2] = 0; } sh->nb_refs[L0] = sh->nb_refs[L1] = 0; if (sh->slice_type == P_SLICE || sh->slice_type == B_SLICE) { int nb_refs; sh->nb_refs[L0] = s->pps->num_ref_idx_l0_default_active; if (sh->slice_type == B_SLICE) sh->nb_refs[L1] = s->pps->num_ref_idx_l1_default_active; READ_ONEBIT(gb, &value); if (value) { // num_ref_idx_active_override_flag READ_UE(gb, &sh->nb_refs[L0]); sh->nb_refs[L0] += 1; if (sh->slice_type == B_SLICE) { READ_UE(gb, &sh->nb_refs[L1]); sh->nb_refs[L1] += 1; } } if (sh->nb_refs[L0] > MAX_REFS || sh->nb_refs[L1] > MAX_REFS) { mpp_err( "Too many refs: %d/%d.\n", sh->nb_refs[L0], sh->nb_refs[L1]); return MPP_ERR_STREAM; } sh->rpl_modification_flag[0] = 0; sh->rpl_modification_flag[1] = 0; nb_refs = mpp_hevc_frame_nb_refs(s); if (!nb_refs) { mpp_err( "Zero refs for a frame with P or B slices.\n"); return MPP_ERR_STREAM; } if (s->pps->lists_modification_present_flag && nb_refs > 1) { READ_ONEBIT(gb, &sh->rpl_modification_flag[0]); if (sh->rpl_modification_flag[0]) { for (i = 0; (RK_U32)i < sh->nb_refs[L0]; i++) READ_BITS(gb, mpp_ceil_log2(nb_refs), &sh->list_entry_lx[0][i]); } if (sh->slice_type == B_SLICE) { READ_ONEBIT(gb, &sh->rpl_modification_flag[1]); if (sh->rpl_modification_flag[1] == 1) for (i = 0; (RK_U32)i < sh->nb_refs[L1]; i++) READ_BITS(gb, mpp_ceil_log2(nb_refs), &sh->list_entry_lx[1][i]); } } if (sh->slice_type == B_SLICE) READ_ONEBIT(gb, &sh->mvd_l1_zero_flag); if (s->pps->cabac_init_present_flag) READ_ONEBIT(gb, &sh->cabac_init_flag); else sh->cabac_init_flag = 0; sh->collocated_ref_idx = 0; if (sh->slice_temporal_mvp_enabled_flag) { sh->collocated_list = L0; if (sh->slice_type == B_SLICE) { READ_ONEBIT(gb, &value); sh->collocated_list = !value; } if (sh->nb_refs[sh->collocated_list] > 1) { READ_UE(gb, &sh->collocated_ref_idx); if (sh->collocated_ref_idx >= sh->nb_refs[sh->collocated_list]) { mpp_err( "Invalid collocated_ref_idx: %d.\n", sh->collocated_ref_idx); return MPP_ERR_STREAM; } } } if ((s->pps->weighted_pred_flag && sh->slice_type == P_SLICE) || (s->pps->weighted_bipred_flag && sh->slice_type == B_SLICE)) { pred_weight_table(s, gb); } READ_UE(gb, &value); sh->max_num_merge_cand = 5 - value; if (sh->max_num_merge_cand < 1 || sh->max_num_merge_cand > 5) { mpp_err( "Invalid number of merging MVP candidates: %d.\n", sh->max_num_merge_cand); return MPP_ERR_STREAM; } } READ_SE(gb, &sh->slice_qp_delta ); if (s->pps->pic_slice_level_chroma_qp_offsets_present_flag) { READ_SE(gb, &sh->slice_cb_qp_offset); READ_SE(gb, &sh->slice_cr_qp_offset); } else { sh->slice_cb_qp_offset = 0; sh->slice_cr_qp_offset = 0; } if (s->pps->deblocking_filter_control_present_flag) { int deblocking_filter_override_flag = 0; if (s->pps->deblocking_filter_override_enabled_flag) READ_ONEBIT(gb, & deblocking_filter_override_flag); if (deblocking_filter_override_flag) { READ_ONEBIT(gb, &sh->disable_deblocking_filter_flag); if (!sh->disable_deblocking_filter_flag) { READ_SE(gb, &sh->beta_offset); sh->beta_offset = sh->beta_offset * 2; READ_SE(gb, &sh->tc_offset); sh->tc_offset = sh->tc_offset * 2; } } else { sh->disable_deblocking_filter_flag = s->pps->disable_dbf; sh->beta_offset = s->pps->beta_offset; sh->tc_offset = s->pps->tc_offset; } } else { sh->disable_deblocking_filter_flag = 0; sh->beta_offset = 0; sh->tc_offset = 0; } if (s->pps->seq_loop_filter_across_slices_enabled_flag && (sh->slice_sample_adaptive_offset_flag[0] || sh->slice_sample_adaptive_offset_flag[1] || !sh->disable_deblocking_filter_flag)) { READ_ONEBIT(gb, &sh->slice_loop_filter_across_slices_enabled_flag); } else { sh->slice_loop_filter_across_slices_enabled_flag = s->pps->seq_loop_filter_across_slices_enabled_flag; } } else if (!s->slice_initialized) { mpp_err( "Independent slice segment missing.\n"); return MPP_ERR_STREAM; } sh->num_entry_point_offsets = 0; if (s->pps->tiles_enabled_flag || s->pps->entropy_coding_sync_enabled_flag) { READ_UE(gb, &sh->num_entry_point_offsets); if (s->pps->entropy_coding_sync_enabled_flag) { if (sh->num_entry_point_offsets > s->sps->ctb_height || sh->num_entry_point_offsets < 0) { mpp_err("The number of entries %d is higher than the number of CTB rows %d \n", sh->num_entry_point_offsets, s->sps->ctb_height); return MPP_ERR_STREAM; } } else { if (sh->num_entry_point_offsets > s->sps->ctb_height * s->sps->ctb_width || sh->num_entry_point_offsets < 0) { mpp_err("The number of entries %d is higher than the number of CTBs %d \n", sh->num_entry_point_offsets, s->sps->ctb_height * s->sps->ctb_width); return MPP_ERR_STREAM; } } } if (s->pps->slice_header_extension_present_flag) { //if slice_header_extension_present_flag is 1, we should cut the extension data. RK_U32 length = 0; s->start_bit = gb->used_bits; READ_UE(gb, &length); for (i = 0; (RK_U32)i < length; i++) { SKIP_BITS(gb, 8); // slice_header_extension_data_byte } s->end_bit = gb->used_bits; } // Inferred parameters sh->slice_qp = 26U + s->pps->pic_init_qp_minus26 + sh->slice_qp_delta; if (sh->slice_qp > 51 || sh->slice_qp < -s->sps->qp_bd_offset) { mpp_err("The slice_qp %d is outside the valid range " "[%d, 51].\n", sh->slice_qp, -s->sps->qp_bd_offset); return MPP_ERR_STREAM; } if (s->h265dctx->compare_info != NULL && sh->first_slice_in_pic_flag) { CurrentFameInf_t *info = (CurrentFameInf_t *)s->h265dctx->compare_info; SliceHeader *openhevc_sh = (SliceHeader *)&info->sh; h265d_dbg(H265D_DBG_FUNCTION, "compare_sliceheader in"); if (compare_sliceheader(openhevc_sh, &s->sh) < 0) { mpp_log("compare sliceHeader with openhevc diff\n"); mpp_assert(0); } h265d_dbg(H265D_DBG_FUNCTION, "compare_sliceheader ok"); } sh->slice_ctb_addr_rs = sh->slice_segment_addr; if (!s->sh.slice_ctb_addr_rs && s->sh.dependent_slice_segment_flag) { mpp_err("Impossible slice segment.\n"); return MPP_ERR_STREAM; } s->slice_initialized = 1; return 0; __BITREAD_ERR: return MPP_ERR_STREAM; } /** * @return AV MPP_ERR_STREAM if the packet is not a valid NAL unit, * 0 if the unit should be skipped, 1 otherwise */ static RK_S32 hls_nal_unit(HEVCContext *s) { BitReadCtx_t*gb = &s->HEVClc->gb; RK_S32 value = 0; READ_ONEBIT(gb, &value); /*this bit should be zero*/ READ_BITS(gb, 6, &s->nal_unit_type); READ_BITS(gb, 6, &s->nuh_layer_id); READ_BITS(gb, 3, &s->temporal_id); s->temporal_id = s->temporal_id - 1; h265d_dbg(H265D_DBG_GLOBAL, "nal_unit_type: %d, nuh_layer_id: %d temporal_id: %d\n", s->nal_unit_type, s->nuh_layer_id, s->temporal_id); if (s->temporal_id < 0) return MPP_ERR_STREAM; return (s->nuh_layer_id); __BITREAD_ERR: return MPP_ERR_STREAM; } static RK_S32 mpp_hevc_output_frame(void *ctx, int flush) { H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = (HEVCContext *)h265dctx->priv_data; do { RK_S32 nb_output = 0; RK_S32 min_poc = INT_MAX; RK_S32 min_idx = 0; RK_U32 i; for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) { HEVCFrame *frame = &s->DPB[i]; if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) && frame->sequence == s->seq_output) { nb_output++; if (frame->poc < min_poc) { min_poc = frame->poc; min_idx = i; } } } /* wait for more frames before output */ if (!flush && s->seq_output == s->seq_decode && s->sps && nb_output <= s->sps->temporal_layer[s->sps->max_sub_layers - 1].num_reorder_pics) return 0; if (nb_output) { HEVCFrame *frame = &s->DPB[min_idx]; frame->flags &= ~(HEVC_FRAME_FLAG_OUTPUT); s->output_frame_idx = min_idx; mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_QUEUE_USE); mpp_buf_slot_enqueue(s->slots, frame->slot_index, QUEUE_DISPLAY); h265d_dbg(H265D_DBG_REF, "Output frame with POC %d frame->slot_index = %d\n", frame->poc, frame->slot_index); return 1; } if (s->seq_output != s->seq_decode) s->seq_output = (s->seq_output + 1) & 0xff; else break; } while (1); return 0; } static RK_S32 hevc_frame_start(HEVCContext *s) { int ret; if (s->ref) { mpp_log_f("found two frame in one packet do nothing!\n"); return 0; } s->is_decoded = 0; s->first_nal_type = s->nal_unit_type; s->miss_ref_flag = 0; ret = mpp_hevc_frame_rps(s); if (ret < 0) { mpp_err("Error constructing the frame RPS.\n"); goto fail; } ret = mpp_hevc_set_new_ref(s, &s->frame, s->poc); if (ret < 0) goto fail; if (!s->h265dctx->cfg->base.disable_error && s->miss_ref_flag) { if (!IS_IRAP(s)) { mpp_frame_set_errinfo(s->frame, MPP_FRAME_ERR_UNKNOW); s->ref->error_flag = 1; } else { /*when found current I frame have miss refer may be stream have error so first set current frame no output and flush other frame output from dpb then set current frame can as output */ HEVCFrame *frame = NULL; RK_U32 i = 0; for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) { frame = &s->DPB[i]; if (frame->poc == s->poc ) { frame->flags &= ~(HEVC_FRAME_FLAG_OUTPUT); break; } else { frame = NULL; } } do { ret = mpp_hevc_output_frame(s->h265dctx, 1); } while (ret); if (frame) { frame->flags |= HEVC_FRAME_FLAG_OUTPUT; } } } mpp_buf_slot_set_prop(s->slots, s->ref->slot_index, SLOT_FRAME, s->ref->frame); return 0; fail: s->ref = NULL; return ret; } static RK_S32 parser_nal_unit(HEVCContext *s, const RK_U8 *nal, int length) { HEVCLocalContext *lc = s->HEVClc; BitReadCtx_t *gb = &lc->gb; RK_S32 ret; mpp_set_bitread_ctx(gb, (RK_U8*)nal, length); mpp_set_pre_detection(gb); ret = hls_nal_unit(s); if (ret < 0) { mpp_err("Invalid NAL unit %d, skipping.\n", s->nal_unit_type); goto fail; } else if (ret != (s->decoder_id) && s->nal_unit_type != NAL_VPS) return 0; if (s->temporal_id > s->temporal_layer_id) return 0; s->nuh_layer_id = ret; h265d_dbg(H265D_DBG_GLOBAL, "s->nal_unit_type = %d,len = %d \n", s->nal_unit_type, length); switch (s->nal_unit_type) { case NAL_VPS: ret = mpp_hevc_decode_nal_vps(s); if (ret < 0 && !s->is_decoded) { mpp_err("mpp_hevc_decode_nal_vps error ret = %d", ret); goto fail; } break; case NAL_SPS: ret = mpp_hevc_decode_nal_sps(s); if (ret < 0 && !s->is_decoded) { mpp_err("mpp_hevc_decode_nal_sps error ret = %d", ret); goto fail; } break; case NAL_PPS: if (s->pre_pps_data == NULL) { s->pre_pps_data = mpp_calloc(RK_U8, length + 128); memcpy(s->pre_pps_data, nal, length); s->pps_len = length; s->pps_buf_size = length + 128; s->ps_need_upate = 1; } else if (s->pps_len == length) { if (memcmp(s->pre_pps_data, nal, length)) { s->ps_need_upate = 1; memcpy(s->pre_pps_data, nal, length); } } else { if (s->pps_buf_size < length) { MPP_FREE(s->pre_pps_data); s->pre_pps_data = mpp_calloc(RK_U8, length + 128); memcpy(s->pre_pps_data, nal, length); s->pps_buf_size = length + 128; s->pps_len = length; } s->ps_need_upate = 1; } ret = mpp_hevc_decode_nal_pps(s); if (ret < 0 && !s->is_decoded) { mpp_err("mpp_hevc_decode_nal_pps error ret = %d", ret); goto fail; } break; case NAL_SEI_PREFIX: case NAL_SEI_SUFFIX: ret = mpp_hevc_decode_nal_sei(s); if (ret < 0) { mpp_err("mpp_hevc_decode_nal_sei error ret = %d", ret); //goto fail; } break; case NAL_TRAIL_R: case NAL_TRAIL_N: case NAL_TSA_N: case NAL_TSA_R: case NAL_STSA_N: case NAL_STSA_R: case NAL_BLA_W_LP: case NAL_BLA_W_RADL: case NAL_BLA_N_LP: case NAL_IDR_W_RADL: case NAL_IDR_N_LP: case NAL_CRA_NUT: case NAL_RADL_N: case NAL_RADL_R: case NAL_RASL_N: case NAL_RASL_R: if (s->task == NULL) { s->extra_has_frame = 1; break; } h265d_dbg(H265D_DBG_FUNCTION, "hls_slice_header in"); ret = hls_slice_header(s); h265d_dbg(H265D_DBG_FUNCTION, "hls_slice_header out"); if (ret < 0) { mpp_err("hls_slice_header error ret = %d", ret); if (s->first_nal_type != s->nal_unit_type) return 0; return ret; } if (s->max_ra == INT_MAX) { if (s->nal_unit_type == NAL_CRA_NUT || IS_BLA(s)) { s->max_ra = s->poc; } else { if (IS_IDR(s)) s->max_ra = INT_MIN; } } if ((s->nal_unit_type == NAL_RASL_R || s->nal_unit_type == NAL_RASL_N) && s->poc <= s->max_ra) { s->is_decoded = 0; break; } else if (!s->h265dctx->cfg->base.disable_error && (s->poc < s->max_ra) && !IS_IRAP(s)) { //when seek to I slice skip the stream small then I slic poc s->is_decoded = 0; break; } else { if (s->nal_unit_type == NAL_RASL_R && s->poc > s->max_ra) s->max_ra = INT_MIN; } if (s->sh.first_slice_in_pic_flag) { ret = hevc_frame_start(s); if (ret < 0) { mpp_err("hevc_frame_start = %d", ret); return ret; } } else if (!s->ref) { mpp_err("First slice in a frame missing.\n"); goto fail; } if (s->nal_unit_type != s->first_nal_type) { mpp_err("Non-matching NAL types of the VCL NALUs: %d %d\n", s->first_nal_type, s->nal_unit_type); goto fail; } if (!s->sh.dependent_slice_segment_flag && s->sh.slice_type != I_SLICE) { // ret = mpp_hevc_slice_rpl(s); if (ret < 0) { mpp_err("Error constructing the reference lists for the current slice.\n"); goto fail; } // rk_get_ref_info(s); } s->is_decoded = 1; break; case NAL_EOS_NUT: case NAL_EOB_NUT: s->seq_decode = (s->seq_decode + 1) & 0xff; s->max_ra = INT_MAX; break; case NAL_AUD: case NAL_FD_NUT: break; default: mpp_log("Skipping NAL unit %d\n", s->nal_unit_type); } return 0; fail: return ret; } typedef union { RK_U32 u32; RK_U16 u16[2]; RK_U8 u8 [4]; float f32; } mpp_alias32; #define MPP_FAST_UNALIGNED 1 #ifndef MPP_RN32A #define MPP_RN32A(p) (((const mpp_alias32*)(p))->u32) #endif RK_S32 mpp_hevc_extract_rbsp(HEVCContext *s, const RK_U8 *src, int length, HEVCNAL *nal) { RK_S32 i; s->skipped_bytes = 0; #define STARTCODE_TEST \ if (i + 2 < length && src[i + 1] == 0 && src[i + 2] < 2) { \ /* startcode, so we must be past the end */ \ length = i; \ break; \ } #if MPP_FAST_UNALIGNED #define FIND_FIRST_ZERO \ if (i > 0 && !src[i]) \ i--; \ while (src[i]) \ i++ for (i = 0; i + 1 < length; i += 5) { if (!((~MPP_RN32A(src + i) & (MPP_RN32A(src + i) - 0x01000101U)) & 0x80008080U)) continue; FIND_FIRST_ZERO; STARTCODE_TEST; i -= 3; } #else for (i = 0; i + 1 < length; i += 2) { if (src[i]) continue; if (i > 0 && src[i - 1] == 0) i--; STARTCODE_TEST; } #endif if (length + MPP_INPUT_BUFFER_PADDING_SIZE > nal->rbsp_buffer_size) { RK_S32 min_size = length + MPP_INPUT_BUFFER_PADDING_SIZE; mpp_free(nal->rbsp_buffer); nal->rbsp_buffer = NULL; min_size = MPP_MAX(17 * min_size / 16 + 32, min_size); nal->rbsp_buffer = mpp_malloc(RK_U8, min_size); if (nal->rbsp_buffer == NULL) { min_size = 0; } nal->rbsp_buffer_size = min_size; } memcpy(nal->rbsp_buffer, src, length); nal->data = nal->rbsp_buffer; nal->size = length; memset(nal->rbsp_buffer + length, 0, MPP_INPUT_BUFFER_PADDING_SIZE); return length; } static RK_S32 split_nal_units(HEVCContext *s, RK_U8 *buf, RK_U32 length) { RK_S32 i, consumed; MPP_RET ret = MPP_OK; s->nb_nals = 0; while (length >= 4) { HEVCNAL *nal; RK_S32 extract_length = 0; if (s->is_nalff) { for (i = 0; i < s->nal_length_size; i++) extract_length = (extract_length << 8) | buf[i]; buf += s->nal_length_size; length -= s->nal_length_size; if ((RK_U32)extract_length > length) { mpp_err( "Invalid NAL unit size.\n"); ret = MPP_ERR_STREAM; goto fail; } } else { /* search start code */ if (buf[2] == 0) { length--; buf++; continue; } if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { RK_U32 state = (RK_U32) - 1; int has_nal = 0; for (i = 0; i < (RK_S32)length; i++) { state = (state << 8) | buf[i]; if (((state >> 8) & 0xFFFFFF) == START_CODE) { has_nal = 1; i = i - 3; break; } } if (has_nal) { length -= i; buf += i; continue; } if (s->nb_nals) { return MPP_OK; } else { mpp_err( "No start code is found.\n"); ret = MPP_ERR_STREAM; goto fail; } } buf += 3; length -= 3; } if (!s->is_nalff) extract_length = length; if (!extract_length) { return MPP_OK; } if (s->nals_allocated < 1) { RK_S32 new_size = s->nals_allocated + 10; HEVCNAL *tmp = mpp_malloc(HEVCNAL, new_size); memset((void*)tmp, 0, new_size * sizeof(HEVCNAL)); s->nals_allocated = new_size; s->nals = tmp; } if (s->nals_allocated < s->nb_nals + 1) { int new_size = s->nals_allocated + 10; HEVCNAL *tmp = mpp_malloc(HEVCNAL, new_size); memset((void*)tmp, 0, new_size * sizeof(HEVCNAL)); if (!tmp) { mpp_err("return enomm new_size %d", new_size); ret = MPP_ERR_NOMEM; goto fail; } memcpy((void*)tmp, (void*)s->nals, (new_size - 10)*sizeof(HEVCNAL)); mpp_free(s->nals); s->nals = NULL; s->nals = tmp; memset(s->nals + s->nals_allocated, 0, (new_size - s->nals_allocated) * sizeof(*tmp)); s->nals_allocated = new_size; } nal = &s->nals[s->nb_nals]; consumed = mpp_hevc_extract_rbsp(s, buf, extract_length, nal); if (consumed <= 0) { ret = MPP_ERR_STREAM; goto fail; } s->nb_nals++; mpp_set_bitread_ctx(&s->HEVClc->gb, (RK_U8 *)nal->data, nal->size); mpp_set_pre_detection(&s->HEVClc->gb); if (hls_nal_unit(s) < 0) s->nb_nals--; if (s->nal_unit_type < NAL_VPS) { if (nal->size != consumed) h265d_dbg(H265D_DBG_GLOBAL, "tag_stream: nal.size=%d, consumed=%d\n", nal->size, consumed); } /* if (s->nal_unit_type == NAL_EOB_NUT || s->nal_unit_type == NAL_EOS_NUT) s->eos = 1;*/ buf += consumed; length -= consumed; } fail: return (s->nb_nals) ? MPP_OK : ret; } static RK_S32 parser_nal_units(HEVCContext *s) { /* parse the NAL units */ RK_S32 i, ret = 0, slice_cnt = 0; for (i = 0; i < s->nb_nals; i++) { ret = parser_nal_unit(s, s->nals[i].data, s->nals[i].size); if (ret < 0) { mpp_err("Error parsing NAL unit #%d,error ret = 0xd.\n", i, ret); goto fail; } /* update slice data if slice_header_extension_present_flag is 1*/ if (s->nal_unit_type < 32) { switch (s->nal_unit_type) { case NAL_TRAIL_R: case NAL_TRAIL_N: case NAL_TSA_N: case NAL_TSA_R: case NAL_STSA_N: case NAL_STSA_R: case NAL_BLA_W_LP: case NAL_BLA_W_RADL: case NAL_BLA_N_LP: case NAL_IDR_W_RADL: case NAL_IDR_N_LP: case NAL_CRA_NUT: case NAL_RADL_N: case NAL_RADL_R: case NAL_RASL_N: case NAL_RASL_R: if (s->pps && s->pps->slice_header_extension_present_flag) { h265d_dxva2_picture_context_t *temp = (h265d_dxva2_picture_context_t *)s->hal_pic_private; temp->slice_cut_param[slice_cnt].start_bit = s->start_bit; temp->slice_cut_param[slice_cnt].end_bit = s->end_bit; temp->slice_cut_param[slice_cnt].is_enable = 1; break; } default: break; } slice_cnt++; } } fail: return ret; } static RK_U16 U16_AT(const RK_U8 *ptr) { return ptr[0] << 8 | ptr[1]; } static RK_S32 hevc_parser_extradata(HEVCContext *s) { H265dContext_t *h265dctx = s->h265dctx; RK_S32 ret = MPP_SUCCESS; if (h265dctx->extradata_size > 3 && (h265dctx->extradata[0] || h265dctx->extradata[1] || h265dctx->extradata[2] > 1)) { /* It seems the extradata is encoded as hvcC format. * Temporarily, we support configurationVersion==0 until 14496-15 3rd * is finalized. When finalized, configurationVersion will be 1 and we * can recognize hvcC by checking if h265dctx->extradata[0]==1 or not. */ const RK_U8 *ptr = (const RK_U8 *)h265dctx->extradata; RK_U32 size = h265dctx->extradata_size; RK_U32 numofArrays = 0, numofNals = 0; RK_U32 j = 0, i = 0; if (size < 7) { return MPP_NOK; } mpp_log("extradata is encoded as hvcC format"); s->is_nalff = 1; s->nal_length_size = 1 + (ptr[14 + 7] & 3); ptr += 22; size -= 22; numofArrays = (char)ptr[0]; ptr += 1; size -= 1; for (i = 0; i < numofArrays; i++) { ptr += 1; size -= 1; // Num of nals numofNals = U16_AT(ptr); ptr += 2; size -= 2; for (j = 0; j < numofNals; j++) { RK_U32 length = 0; if (size < 2) { return MPP_NOK; } length = U16_AT(ptr); ptr += 2; size -= 2; if (size < length) { return MPP_NOK; } parser_nal_unit(s, ptr, length); ptr += length; size -= length; } } } else { s->is_nalff = 0; ret = split_nal_units(s, h265dctx->extradata, h265dctx->extradata_size); if (ret < 0) return ret; ret = parser_nal_units(s); if (ret < 0) return ret; } return ret; } MPP_RET h265d_prepare(void *ctx, MppPacket pkt, HalDecTask *task) { MPP_RET ret = MPP_OK; H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = (HEVCContext *)h265dctx->priv_data; SplitContext_t *sc = (SplitContext_t*)h265dctx->split_cxt; RK_S64 pts = -1, dts = -1; RK_U8 *buf = NULL; void *pos = NULL; RK_S32 length = 0; task->valid = 0; s->eos = mpp_packet_get_eos(pkt); if (sc != NULL) { sc->eos = s->eos; } else if (h265dctx->cfg->base.split_parse) { h265d_split_init((void**)&sc); if (sc == NULL) { mpp_err("split contxt malloc fail"); return MPP_ERR_NOMEM; } h265dctx->split_cxt = sc; } buf = (RK_U8 *)mpp_packet_get_pos(pkt); pts = mpp_packet_get_pts(pkt); dts = mpp_packet_get_dts(pkt); h265d_dbg(H265D_DBG_TIME, "prepare get pts %lld", pts); length = (RK_S32)mpp_packet_get_length(pkt); if (mpp_packet_get_flag(pkt)& MPP_PACKET_FLAG_EXTRA_DATA) { h265dctx->extradata_size = length; h265dctx->extradata = buf; s->extra_has_frame = 0; s->task = NULL; hevc_parser_extradata(s); if (!s->extra_has_frame) { pos = buf + length; mpp_packet_set_pos(pkt, pos); return MPP_OK; } } if (h265dctx->cfg->base.split_parse && !s->is_nalff) { RK_S32 consume = 0; RK_U8 *split_out_buf = NULL; RK_S32 split_size = 0; consume = h265d_split_frame(h265dctx->split_cxt, (const RK_U8**)&split_out_buf, &split_size, (const RK_U8*)buf, length, pts, dts); pos = buf + consume; mpp_packet_set_pos(pkt, pos); if (split_size) { buf = split_out_buf; length = split_size; s->checksum_buf = buf; //check with openhevc s->checksum_buf_size = split_size; h265d_dbg(H265D_DBG_TIME, "split frame get pts %lld", sc->pts); s->pts = sc->pts; s->eos = (s->eos && (mpp_packet_get_length(pkt) < 4)) ? 1 : 0; } else { return MPP_FAIL_SPLIT_FRAME; } } else { pos = buf + length; s->pts = pts; mpp_packet_set_pos(pkt, pos); if (s->eos && !length) { task->valid = 0; task->flags.eos = 1; h265d_flush(ctx); return ret; } } #ifdef dump if (s->nb_frame < 10 && fp != NULL) { fwrite(buf, 1, length, fp); } #endif ret = (MPP_RET)split_nal_units(s, buf, length); if (MPP_OK == ret) { if (MPP_OK == h265d_syntax_fill_slice(s->h265dctx, task->input)) { task->valid = 1; task->input_packet = s->input_packet; } } return ret; } MPP_RET h265d_get_stream(void *ctx, RK_U8 **buf, RK_S32 *size) { MPP_RET ret = MPP_OK; H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = h265dctx->priv_data; *buf = s->checksum_buf; *size = s->checksum_buf_size; return ret; } MPP_RET h265d_set_compare_info(void *ctx, void *info) { MPP_RET ret = MPP_OK; H265dContext_t *h265dctx = (H265dContext_t *)ctx; h265dctx->compare_info = info; return ret; } MPP_RET h265d_parse(void *ctx, HalDecTask *task) { MPP_RET ret; H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = h265dctx->priv_data; task->valid = 0; s->got_frame = 0; s->task = task; s->ref = NULL; ret = parser_nal_units(s); if (ret < 0) { if (ret == MPP_ERR_STREAM) { mpp_log("current stream is no right skip it %p\n", s->ref); ret = 0; } // return ret; task->flags.parse_err = 1; } h265d_dbg(H265D_DBG_GLOBAL, "decode poc = %d", s->poc); if (s->ref) { h265d_parser2_syntax(h265dctx); s->task->syntax.data = s->hal_pic_private; s->task->syntax.number = 1; s->task->valid = 1; } if (s->eos) { h265d_flush(ctx); s->task->flags.eos = 1; } s->nb_frame++; if (s->is_decoded) { h265d_dbg(H265D_DBG_GLOBAL, "Decoded frame with POC %d.\n", s->poc); s->is_decoded = 0; } mpp_hevc_output_frame(ctx, 0); return MPP_OK; } MPP_RET h265d_deinit(void *ctx) { H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = h265dctx->priv_data; SplitContext_t *sc = h265dctx->split_cxt; RK_U8 *buf = NULL; int i; for (i = 0; i < MAX_DPB_SIZE; i++) { mpp_hevc_unref_frame(s, &s->DPB[i], ~0); mpp_frame_deinit(&s->DPB[i].frame); } for (i = 0; i < MAX_VPS_COUNT; i++) mpp_free(s->vps_list[i]); for (i = 0; i < MAX_SPS_COUNT; i++) { if (s->sps_list[i]) mpp_mem_pool_put(s->sps_pool, s->sps_list[i]); } for (i = 0; i < MAX_PPS_COUNT; i++) mpp_hevc_pps_free(s->pps_list[i]); mpp_free(s->HEVClc); s->HEVClc = NULL; for (i = 0; i < s->nals_allocated; i++) mpp_free(s->nals[i].rbsp_buffer); if (s->nals) { mpp_free(s->nals); } MPP_FREE(s->pre_pps_data); s->nals_allocated = 0; if (s->hal_pic_private) { mpp_free(s->hal_pic_private); } if (s->input_packet) { buf = mpp_packet_get_data(s->input_packet); mpp_free(buf); mpp_packet_deinit(&s->input_packet); } if (s->sps_pool) mpp_mem_pool_deinit(s->sps_pool); if (s) { mpp_free(s); } if (sc) { h265d_split_deinit(sc); } return 0; } static RK_S32 hevc_init_context(H265dContext_t *h265dctx) { HEVCContext *s = h265dctx->priv_data; RK_U32 i; s->h265dctx = h265dctx; s->HEVClc = (HEVCLocalContext*)mpp_calloc(HEVCLocalContext, 1); if (!s->HEVClc) goto fail; for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) { s->DPB[i].slot_index = 0xff; s->DPB[i].poc = INT_MAX; s->DPB[i].error_flag = 0; mpp_frame_init(&s->DPB[i].frame); if (!s->DPB[i].frame) goto fail; } s->max_ra = INT_MAX; s->temporal_layer_id = 8; s->context_initialized = 1; return 0; fail: h265d_deinit(h265dctx); return MPP_ERR_NOMEM; } MPP_RET h265d_init(void *ctx, ParserCfg *parser_cfg) { H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = (HEVCContext *)h265dctx->priv_data; SplitContext_t *sc = (SplitContext_t*)h265dctx->split_cxt; RK_S32 ret; RK_U8 *buf = NULL; RK_S32 size = SZ_512K; if (s == NULL) { s = (HEVCContext*)mpp_calloc(HEVCContext, 1); if (s == NULL) { mpp_err("hevc contxt malloc fail"); return MPP_ERR_NOMEM; } h265dctx->priv_data = s; } h265dctx->cfg = parser_cfg->cfg; if (sc == NULL && h265dctx->cfg->base.split_parse) { h265d_split_init((void**)&sc); if (sc == NULL) { mpp_err("split contxt malloc fail"); return MPP_ERR_NOMEM; } h265dctx->split_cxt = sc; } // mpp_env_set_u32("h265d_debug", H265D_DBG_REF); mpp_env_get_u32("h265d_debug", &h265d_debug, 0); ret = hevc_init_context(h265dctx); s->hal_pic_private = mpp_calloc_size(void, sizeof(h265d_dxva2_picture_context_t)); if (ret < 0) return ret; s->picture_struct = 0; s->slots = parser_cfg->frame_slots; s->packet_slots = parser_cfg->packet_slots; if (h265dctx->extradata_size > 0 && h265dctx->extradata) { ret = hevc_parser_extradata(s); if (ret < 0) { h265d_deinit(h265dctx); return ret; } } buf = mpp_malloc(RK_U8, size); if (buf == NULL) { return MPP_ERR_NOMEM; } if (MPP_OK != mpp_packet_init(&s->input_packet, (void*)buf, size)) { return MPP_ERR_NOMEM; } mpp_buf_slot_setup(s->slots, 25); s->h265dctx->hw_info = parser_cfg->hw_info; s->pre_pps_id = -1; s->sps_pool = mpp_mem_pool_init(sizeof(HEVCSPS)); #ifdef dump fp = fopen("/data/dump1.bin", "wb+"); #endif return 0; } MPP_RET h265d_flush(void *ctx) { RK_S32 ret = 0; do { ret = mpp_hevc_output_frame(ctx, 1); } while (ret); return MPP_OK; } MPP_RET h265d_reset(void *ctx) { H265dContext_t *h265dctx = (H265dContext_t *)ctx; HEVCContext *s = (HEVCContext *)h265dctx->priv_data; RK_S32 ret = 0; do { ret = mpp_hevc_output_frame(ctx, 1); } while (ret); mpp_hevc_flush_dpb(s); h265d_split_reset(h265dctx->split_cxt); s->max_ra = INT_MAX; s->eos = 0; return MPP_OK; } MPP_RET h265d_control(void *ctx, MpiCmd cmd, void *param) { (void) ctx; (void) cmd; (void) param; return MPP_OK; } MPP_RET h265d_callback(void *ctx, void *err_info) { H265dContext_t *h265dctx = (H265dContext_t *)ctx; HalDecTask *task_dec = (HalDecTask *)err_info; HEVCContext *s = (HEVCContext *)h265dctx->priv_data; if (!h265dctx->cfg->base.disable_error) { MppFrame frame = NULL; RK_U32 i = 0; if (s->first_nal_type >= 16 && s->first_nal_type <= 23) { mpp_log("IS_IRAP frame found error"); s->max_ra = INT_MAX; } // s->miss_ref_flag = 1; mpp_buf_slot_get_prop(s->slots, task_dec->output, SLOT_FRAME_PTR, &frame); mpp_frame_set_errinfo(frame, MPP_FRAME_ERR_UNKNOW); for (i = 0; i < MPP_ARRAY_ELEMS(s->DPB); i++) { if (s->DPB[i].slot_index == task_dec->output) { s->DPB[i].error_flag = 1; } } } if (!task_dec->flags.parse_err) s->ps_need_upate = 0; (void) err_info; return MPP_OK; } const ParserApi api_h265d_parser = { .name = "h265d_parse", .coding = MPP_VIDEO_CodingHEVC, .ctx_size = sizeof(H265dContext_t), .flag = 0, .init = h265d_init, .deinit = h265d_deinit, .prepare = h265d_prepare, .parse = h265d_parse, .reset = h265d_reset, .flush = h265d_flush, .control = h265d_control, .callback = h265d_callback, };