Files
mpp/mpp/codec/dec/h265/h265d_parser.c
xueman.ruan ec1f93f181 [h265d_parser]: avoid segment fault
Signed-off-by: xueman.ruan <xueman.ruan@rock-chips.com>
Change-Id: I6d1e6b4407c56e96657beb731b8a3432e881142c
2022-06-15 09:37:50 +08:00

2145 lines
65 KiB
C

/*
*
* 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), &lt_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,
};