From d602d005542c271a6e38beffe46b82a4eb66884b Mon Sep 17 00:00:00 2001 From: pr-hung Date: Wed, 11 Mar 2026 23:27:25 +0800 Subject: [PATCH] Fix potential vulnerability in cloned code (lib/codec/3rdparty/de265/libde265/slice.cc) --- lib/codec/3rdparty/de265/libde265/slice.cc | 10144 +++++++++---------- 1 file changed, 5072 insertions(+), 5072 deletions(-) diff --git a/lib/codec/3rdparty/de265/libde265/slice.cc b/lib/codec/3rdparty/de265/libde265/slice.cc index ab302841..305094a8 100644 --- a/lib/codec/3rdparty/de265/libde265/slice.cc +++ b/lib/codec/3rdparty/de265/libde265/slice.cc @@ -1,5072 +1,5072 @@ -/* - * H.265 video codec. - * Copyright (c) 2013-2014 struktur AG, Dirk Farin - * - * Authors: struktur AG, Dirk Farin - * Min Chen - * - * This file is part of libde265. - * - * libde265 is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * libde265 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libde265. If not, see . - */ - -#include "slice.h" -#include "motion.h" -#include "util.h" -#include "scan.h" -#include "intrapred.h" -#include "transform.h" -#include "threads.h" -#include "image.h" - -#include -#include -#include - - -#define LOCK de265_mutex_lock(&ctx->thread_pool.mutex) -#define UNLOCK de265_mutex_unlock(&ctx->thread_pool.mutex) - -extern bool read_short_term_ref_pic_set(error_queue* errqueue, - const seq_parameter_set* sps, - bitreader* br, - ref_pic_set* out_set, - int idxRps, // index of the set to be read - const std::vector& sets, - bool sliceRefPicSet); - - -void read_coding_tree_unit(thread_context* tctx); -void read_coding_quadtree(thread_context* tctx, - int xCtb, int yCtb, - int Log2CtbSizeY, - int ctDepth); -/* -void decode_inter_block(decoder_context* ctx,thread_context* tctx, - int xC, int yC, int log2CbSize); -*/ - -void slice_segment_header::set_defaults() -{ - slice_index = 0; - - first_slice_segment_in_pic_flag = 1; - no_output_of_prior_pics_flag = 0; - slice_pic_parameter_set_id = 0; - dependent_slice_segment_flag = 0; - slice_segment_address = 0; - - slice_type = SLICE_TYPE_I; - pic_output_flag = 1; - colour_plane_id = 0; - slice_pic_order_cnt_lsb = 0; - short_term_ref_pic_set_sps_flag = 1; - // ref_pic_set slice_ref_pic_set; - - short_term_ref_pic_set_idx = 0; - num_long_term_sps = 0; - num_long_term_pics = 0; - - //uint8_t lt_idx_sps[MAX_NUM_REF_PICS]; - //int poc_lsb_lt[MAX_NUM_REF_PICS]; - //char used_by_curr_pic_lt_flag[MAX_NUM_REF_PICS]; - - //char delta_poc_msb_present_flag[MAX_NUM_REF_PICS]; - //int delta_poc_msb_cycle_lt[MAX_NUM_REF_PICS]; - - slice_temporal_mvp_enabled_flag = 0; - slice_sao_luma_flag = 0; - slice_sao_chroma_flag = 0; - - num_ref_idx_active_override_flag = 0; - num_ref_idx_l0_active=1; // [1;16] - num_ref_idx_l1_active=1; // [1;16] - - ref_pic_list_modification_flag_l0 = 0; - ref_pic_list_modification_flag_l1 = 0; - //uint8_t list_entry_l0[16]; - //uint8_t list_entry_l1[16]; - - mvd_l1_zero_flag = 0; - cabac_init_flag = 0; - collocated_from_l0_flag = 0; - collocated_ref_idx = 0; - - // --- pred_weight_table --- - - luma_log2_weight_denom=0; // [0;7] - ChromaLog2WeightDenom=0; // [0;7] - - // first index is L0/L1 - /* - uint8_t luma_weight_flag[2][16]; // bool - uint8_t chroma_weight_flag[2][16]; // bool - int16_t LumaWeight[2][16]; - int8_t luma_offset[2][16]; - int16_t ChromaWeight[2][16][2]; - int8_t ChromaOffset[2][16][2]; - */ - - - five_minus_max_num_merge_cand = 0; - slice_qp_delta = 0; - - slice_cb_qp_offset = 0; - slice_cr_qp_offset = 0; - - cu_chroma_qp_offset_enabled_flag = 0; - - deblocking_filter_override_flag = 0; - slice_deblocking_filter_disabled_flag = 0; - slice_beta_offset=0; // = pps->beta_offset if undefined - slice_tc_offset=0; // = pps->tc_offset if undefined - - slice_loop_filter_across_slices_enabled_flag = 0; - - num_entry_point_offsets = 0; - //int offset_len; - //std::vector entry_point_offset; - - slice_segment_header_extension_length = 0; - - SliceAddrRS = slice_segment_address; -} - - -bool read_pred_weight_table(bitreader* br, slice_segment_header* shdr, decoder_context* ctx) -{ - int vlc; - - pic_parameter_set* pps = ctx->get_pps((int)shdr->slice_pic_parameter_set_id); - assert(pps); - seq_parameter_set* sps = ctx->get_sps((int)pps->seq_parameter_set_id); - assert(sps); - - shdr->luma_log2_weight_denom = vlc = get_uvlc(br); - if (vlc<0 || vlc>7) return false; - - if (sps->chroma_format_idc != 0) { - vlc = get_svlc(br); - vlc += shdr->luma_log2_weight_denom; - if (vlc<0 || vlc>7) return false; - shdr->ChromaLog2WeightDenom = vlc; - } - - int sumWeightFlags = 0; - - for (int l=0;l<=1;l++) - if (l==0 || (l==1 && shdr->slice_type == SLICE_TYPE_B)) - { - int num_ref = (l==0 ? shdr->num_ref_idx_l0_active-1 : shdr->num_ref_idx_l1_active-1); - - for (int i=0;i<=num_ref;i++) { - shdr->luma_weight_flag[l][i] = get_bits(br,1); - if (shdr->luma_weight_flag[l][i]) sumWeightFlags++; - } - - if (sps->chroma_format_idc != 0) { - for (int i=0;i<=num_ref;i++) { - shdr->chroma_weight_flag[l][i] = get_bits(br,1); - if (shdr->chroma_weight_flag[l][i]) sumWeightFlags+=2; - } - } - - for (int i=0;i<=num_ref;i++) { - if (shdr->luma_weight_flag[l][i]) { - - // delta_luma_weight - - vlc = get_svlc(br); - if (vlc < -128 || vlc > 127) return false; - - shdr->LumaWeight[l][i] = (1<luma_log2_weight_denom) + vlc; - - // luma_offset - - vlc = get_svlc(br); - if (vlc < -sps->WpOffsetHalfRangeY || vlc > sps->WpOffsetHalfRangeY-1) return false; - shdr->luma_offset[l][i] = vlc; - } - else { - shdr->LumaWeight[l][i] = 1<luma_log2_weight_denom; - shdr->luma_offset[l][i] = 0; - } - - if (shdr->chroma_weight_flag[l][i]) - for (int j=0;j<2;j++) { - // delta_chroma_weight - - vlc = get_svlc(br); - if (vlc < -128 || vlc > 127) return false; - - shdr->ChromaWeight[l][i][j] = (1<ChromaLog2WeightDenom) + vlc; - - // delta_chroma_offset - - vlc = get_svlc(br); - if (vlc < -4*sps->WpOffsetHalfRangeC || - vlc > 4*sps->WpOffsetHalfRangeC-1) return false; - - vlc = Clip3(-sps->WpOffsetHalfRangeC, - sps->WpOffsetHalfRangeC-1, - (sps->WpOffsetHalfRangeC - +vlc - -((sps->WpOffsetHalfRangeC*shdr->ChromaWeight[l][i][j]) - >> shdr->ChromaLog2WeightDenom))); - - shdr->ChromaOffset[l][i][j] = vlc; - } - else { - for (int j=0;j<2;j++) { - shdr->ChromaWeight[l][i][j] = 1<ChromaLog2WeightDenom; - shdr->ChromaOffset[l][i][j] = 0; - } - } - } - } - - // TODO: bitstream conformance requires that 'sumWeightFlags<=24' - - return true; -} - - -void slice_segment_header::reset() -{ - pps = NULL; - - slice_index = 0; - - first_slice_segment_in_pic_flag = 0; - no_output_of_prior_pics_flag = 0; - slice_pic_parameter_set_id = 0; - dependent_slice_segment_flag = 0; - slice_segment_address = 0; - - slice_type = 0; - pic_output_flag = 0; - colour_plane_id = 0; - slice_pic_order_cnt_lsb = 0; - short_term_ref_pic_set_sps_flag = 0; - slice_ref_pic_set.reset(); - - short_term_ref_pic_set_idx = 0; - num_long_term_sps = 0; - num_long_term_pics= 0; - - for (int i=0;iget_RapPicFlag()) { // TODO: is this still correct ? Should we drop RapPicFlag ? - no_output_of_prior_pics_flag = get_bits(br,1); - } - - slice_pic_parameter_set_id = get_uvlc(br); - if (slice_pic_parameter_set_id > DE265_MAX_PPS_SETS || - slice_pic_parameter_set_id == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); - return DE265_OK; - } - - if (!ctx->has_pps(slice_pic_parameter_set_id)) { - ctx->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); - return DE265_OK; - } - - pps = ctx->get_shared_pps(slice_pic_parameter_set_id); - - const seq_parameter_set* sps = pps->sps.get(); - if (!sps->sps_read) { - ctx->add_warning(DE265_WARNING_NONEXISTING_SPS_REFERENCED, false); - *continueDecoding = false; - return DE265_OK; - } - - if (!first_slice_segment_in_pic_flag) { - if (pps->dependent_slice_segments_enabled_flag) { - dependent_slice_segment_flag = get_bits(br,1); - } else { - dependent_slice_segment_flag = 0; - } - - int slice_segment_address = get_bits(br, ceil_log2(sps->PicSizeInCtbsY)); - - if (dependent_slice_segment_flag) { - if (slice_segment_address == 0) { - *continueDecoding = false; - ctx->add_warning(DE265_WARNING_DEPENDENT_SLICE_WITH_ADDRESS_ZERO, false); - return DE265_OK; - } - - if (ctx->previous_slice_header == NULL) { - return DE265_ERROR_NO_INITIAL_SLICE_HEADER; - } - - *this = *ctx->previous_slice_header; - - first_slice_segment_in_pic_flag = 0; - dependent_slice_segment_flag = 1; - } - - this->slice_segment_address = slice_segment_address; - } else { - dependent_slice_segment_flag = 0; - slice_segment_address = 0; - } - - if (slice_segment_address < 0 || - slice_segment_address >= sps->PicSizeInCtbsY) { - ctx->add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - //printf("SLICE %d (%d)\n",slice_segment_address, sps->PicSizeInCtbsY); - - - if (!dependent_slice_segment_flag) { - for (int i=0; inum_extra_slice_header_bits; i++) { - //slice_reserved_undetermined_flag[i] - skip_bits(br,1); - } - - slice_type = get_uvlc(br); - if (slice_type > 2 || - slice_type == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - *continueDecoding = false; - return DE265_OK; - } - - if (pps->output_flag_present_flag) { - pic_output_flag = get_bits(br,1); - } - else { - pic_output_flag = 1; - } - - if (sps->separate_colour_plane_flag == 1) { - colour_plane_id = get_bits(br,2); - } - - - slice_pic_order_cnt_lsb = 0; - short_term_ref_pic_set_sps_flag = 0; - - int NumLtPics = 0; - - if (ctx->get_nal_unit_type() != NAL_UNIT_IDR_W_RADL && - ctx->get_nal_unit_type() != NAL_UNIT_IDR_N_LP) { - slice_pic_order_cnt_lsb = get_bits(br, sps->log2_max_pic_order_cnt_lsb); - short_term_ref_pic_set_sps_flag = get_bits(br,1); - - if (!short_term_ref_pic_set_sps_flag) { - read_short_term_ref_pic_set(ctx, sps, - br, &slice_ref_pic_set, - sps->num_short_term_ref_pic_sets(), - sps->ref_pic_sets, - true); - - CurrRpsIdx = sps->num_short_term_ref_pic_sets(); - CurrRps = slice_ref_pic_set; - } - else { - int nBits = ceil_log2(sps->num_short_term_ref_pic_sets()); - if (nBits>0) short_term_ref_pic_set_idx = get_bits(br,nBits); - else short_term_ref_pic_set_idx = 0; - - if (short_term_ref_pic_set_idx >= sps->num_short_term_ref_pic_sets()) { - ctx->add_warning(DE265_WARNING_SHORT_TERM_REF_PIC_SET_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - CurrRpsIdx = short_term_ref_pic_set_idx; - CurrRps = sps->ref_pic_sets[CurrRpsIdx]; - } - - - // --- long-term MC --- - - if (sps->long_term_ref_pics_present_flag) { - if (sps->num_long_term_ref_pics_sps > 0) { - num_long_term_sps = get_uvlc(br); - if (num_long_term_sps == UVLC_ERROR) { - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - else { - num_long_term_sps = 0; - } - - num_long_term_pics= get_uvlc(br); - if (num_long_term_pics == UVLC_ERROR) { - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - // check maximum number of reference frames - - if (num_long_term_sps + - num_long_term_pics + - CurrRps.NumNegativePics + - CurrRps.NumPositivePics - > sps->sps_max_dec_pic_buffering[sps->sps_max_sub_layers-1]) - { - ctx->add_warning(DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED, false); - *continueDecoding = false; - return DE265_OK; - } - - for (int i=0; inum_long_term_ref_pics_sps); - lt_idx_sps[i] = get_bits(br, nBits); - - // check that the referenced lt-reference really exists - - if (lt_idx_sps[i] >= sps->num_long_term_ref_pics_sps) { - ctx->add_warning(DE265_NON_EXISTING_LT_REFERENCE_CANDIDATE_IN_SLICE_HEADER, false); - *continueDecoding = false; - return DE265_OK; - } - - // delta_poc_msb_present_flag[i] = 0; // TODO ? - - ctx->PocLsbLt[i] = sps->lt_ref_pic_poc_lsb_sps[ lt_idx_sps[i] ]; - ctx->UsedByCurrPicLt[i] = sps->used_by_curr_pic_lt_sps_flag[ lt_idx_sps[i] ]; - } - else { - int nBits = sps->log2_max_pic_order_cnt_lsb; - poc_lsb_lt[i] = get_bits(br, nBits); - used_by_curr_pic_lt_flag[i] = get_bits(br,1); - - ctx->PocLsbLt[i] = poc_lsb_lt[i]; - ctx->UsedByCurrPicLt[i] = used_by_curr_pic_lt_flag[i]; - } - - if (ctx->UsedByCurrPicLt[i]) { - NumLtPics++; - } - - delta_poc_msb_present_flag[i] = get_bits(br,1); - if (delta_poc_msb_present_flag[i]) { - delta_poc_msb_cycle_lt[i] = get_uvlc(br); - if (delta_poc_msb_cycle_lt[i]==UVLC_ERROR) { - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - else { - delta_poc_msb_cycle_lt[i] = 0; - } - - if (i==0 || i==num_long_term_sps) { - ctx->DeltaPocMsbCycleLt[i] = delta_poc_msb_cycle_lt[i]; - } - else { - ctx->DeltaPocMsbCycleLt[i] = (delta_poc_msb_cycle_lt[i] + - ctx->DeltaPocMsbCycleLt[i-1]); - } - } - } - else { - num_long_term_sps = 0; - num_long_term_pics= 0; - } - - if (sps->sps_temporal_mvp_enabled_flag) { - slice_temporal_mvp_enabled_flag = get_bits(br,1); - } - else { - slice_temporal_mvp_enabled_flag = 0; - } - } - else { - slice_pic_order_cnt_lsb = 0; - num_long_term_sps = 0; - num_long_term_pics= 0; - } - - - // --- SAO --- - - if (sps->sample_adaptive_offset_enabled_flag) { - slice_sao_luma_flag = get_bits(br,1); - - if (sps->ChromaArrayType != CHROMA_MONO) { - slice_sao_chroma_flag = get_bits(br,1); - } - else { - slice_sao_chroma_flag = 0; - } - } - else { - slice_sao_luma_flag = 0; - slice_sao_chroma_flag = 0; - } - - num_ref_idx_l0_active = 0; - num_ref_idx_l1_active = 0; - - if (slice_type == SLICE_TYPE_P || - slice_type == SLICE_TYPE_B) { - num_ref_idx_active_override_flag = get_bits(br,1); - if (num_ref_idx_active_override_flag) { - num_ref_idx_l0_active = get_uvlc(br); - if (num_ref_idx_l0_active == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - num_ref_idx_l0_active++;; - - if (slice_type == SLICE_TYPE_B) { - num_ref_idx_l1_active = get_uvlc(br); - if (num_ref_idx_l1_active == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - num_ref_idx_l1_active++; - } - } - else { - num_ref_idx_l0_active = pps->num_ref_idx_l0_default_active; - num_ref_idx_l1_active = pps->num_ref_idx_l1_default_active; - } - - if (num_ref_idx_l0_active > 16) { return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } - if (num_ref_idx_l1_active > 16) { return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } - - NumPocTotalCurr = CurrRps.NumPocTotalCurr_shortterm_only + NumLtPics; - - if (pps->lists_modification_present_flag && NumPocTotalCurr > 1) { - - int nBits = ceil_log2(NumPocTotalCurr); - - ref_pic_list_modification_flag_l0 = get_bits(br,1); - if (ref_pic_list_modification_flag_l0) { - for (int i=0;icabac_init_present_flag) { - cabac_init_flag = get_bits(br,1); - } - else { - cabac_init_flag = 0; - } - - if (slice_temporal_mvp_enabled_flag) { - if (slice_type == SLICE_TYPE_B) - collocated_from_l0_flag = get_bits(br,1); - else - collocated_from_l0_flag = 1; - - if (( collocated_from_l0_flag && num_ref_idx_l0_active > 1) || - (!collocated_from_l0_flag && num_ref_idx_l1_active > 1)) { - collocated_ref_idx = get_uvlc(br); - if (collocated_ref_idx == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - else { - collocated_ref_idx = 0; - } - - // check whether collocated_ref_idx points to a valid index - - if (( collocated_from_l0_flag && collocated_ref_idx >= num_ref_idx_l0_active) || - (!collocated_from_l0_flag && collocated_ref_idx >= num_ref_idx_l1_active)) { - ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - - - if ((pps->weighted_pred_flag && slice_type == SLICE_TYPE_P) || - (pps->weighted_bipred_flag && slice_type == SLICE_TYPE_B)) { - - if (!read_pred_weight_table(br,this,ctx)) - { - ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - - five_minus_max_num_merge_cand = get_uvlc(br); - if (five_minus_max_num_merge_cand == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - MaxNumMergeCand = 5-five_minus_max_num_merge_cand; - } - - slice_qp_delta = get_svlc(br); - if (slice_qp_delta == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - //logtrace(LogSlice,"slice_qp_delta: %d\n",shdr->slice_qp_delta); - - if (pps->pps_slice_chroma_qp_offsets_present_flag) { - slice_cb_qp_offset = get_svlc(br); - if (slice_cb_qp_offset == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - slice_cr_qp_offset = get_svlc(br); - if (slice_cr_qp_offset == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - else { - slice_cb_qp_offset = 0; - slice_cr_qp_offset = 0; - } - - if (pps->range_extension.chroma_qp_offset_list_enabled_flag) { - cu_chroma_qp_offset_enabled_flag = get_bits(br,1); - } - - if (pps->deblocking_filter_override_enabled_flag) { - deblocking_filter_override_flag = get_bits(br,1); - } - else { - deblocking_filter_override_flag = 0; - } - - slice_beta_offset = pps->beta_offset; - slice_tc_offset = pps->tc_offset; - - if (deblocking_filter_override_flag) { - slice_deblocking_filter_disabled_flag = get_bits(br,1); - if (!slice_deblocking_filter_disabled_flag) { - slice_beta_offset = get_svlc(br); - if (slice_beta_offset == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - slice_beta_offset *= 2; - - slice_tc_offset = get_svlc(br); - if (slice_tc_offset == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - slice_tc_offset *= 2; - } - } - else { - slice_deblocking_filter_disabled_flag = pps->pic_disable_deblocking_filter_flag; - } - - if (pps->pps_loop_filter_across_slices_enabled_flag && - (slice_sao_luma_flag || slice_sao_chroma_flag || - !slice_deblocking_filter_disabled_flag )) { - slice_loop_filter_across_slices_enabled_flag = get_bits(br,1); - } - else { - slice_loop_filter_across_slices_enabled_flag = - pps->pps_loop_filter_across_slices_enabled_flag; - } - } - - if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag ) { - num_entry_point_offsets = get_uvlc(br); - if (num_entry_point_offsets == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - if (pps->entropy_coding_sync_enabled_flag) { - // check num_entry_points for valid range - - int firstCTBRow = slice_segment_address / sps->PicWidthInCtbsY; - int lastCTBRow = firstCTBRow + num_entry_point_offsets; - if (lastCTBRow >= sps->PicHeightInCtbsY) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - - if (pps->tiles_enabled_flag) { - if (num_entry_point_offsets > pps->num_tile_columns * pps->num_tile_rows) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - } - - entry_point_offset.resize( num_entry_point_offsets ); - - if (num_entry_point_offsets > 0) { - offset_len = get_uvlc(br); - if (offset_len == UVLC_ERROR) { - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - offset_len++; - - if (offset_len > 32) { - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - for (int i=0; i0) { - entry_point_offset[i] += entry_point_offset[i-1]; - } - } - } - } - else { - num_entry_point_offsets = 0; - } - - if (pps->slice_segment_header_extension_present_flag) { - slice_segment_header_extension_length = get_uvlc(br); - if (slice_segment_header_extension_length == UVLC_ERROR || - slice_segment_header_extension_length > 1000) { // TODO: safety check against too large values - ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - for (int i=0; i DE265_MAX_PPS_SETS) { - errqueue->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); - return DE265_OK; - } - out.write_uvlc(slice_pic_parameter_set_id); - - if (!first_slice_segment_in_pic_flag) { - if (pps->dependent_slice_segments_enabled_flag) { - out.write_bit(dependent_slice_segment_flag); - } - - out.write_bits(slice_segment_address, ceil_log2(sps->PicSizeInCtbsY)); - - if (dependent_slice_segment_flag) { - if (slice_segment_address == 0) { - errqueue->add_warning(DE265_WARNING_DEPENDENT_SLICE_WITH_ADDRESS_ZERO, false); - return DE265_OK; - } - } - } - - if (slice_segment_address < 0 || - slice_segment_address > sps->PicSizeInCtbsY) { - errqueue->add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - - - if (!dependent_slice_segment_flag) { - for (int i=0; inum_extra_slice_header_bits; i++) { - //slice_reserved_undetermined_flag[i] - out.skip_bits(1); - } - - if (slice_type > 2) { - errqueue->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_OK; - } - out.write_uvlc(slice_type); - - if (pps->output_flag_present_flag) { - out.write_bit(pic_output_flag); - } - - if (sps->separate_colour_plane_flag == 1) { - out.write_bits(colour_plane_id,2); - } - - - int NumLtPics = 0; - - if (nal_unit_type != NAL_UNIT_IDR_W_RADL && - nal_unit_type != NAL_UNIT_IDR_N_LP) { - out.write_bits(slice_pic_order_cnt_lsb, sps->log2_max_pic_order_cnt_lsb); - out.write_bit(short_term_ref_pic_set_sps_flag); - - if (!short_term_ref_pic_set_sps_flag) { - /* TODO - read_short_term_ref_pic_set(ctx, sps, - br, &slice_ref_pic_set, - sps->num_short_term_ref_pic_sets, - sps->ref_pic_sets, - true); - */ - //CurrRpsIdx = sps->num_short_term_ref_pic_sets; - //CurrRps = slice_ref_pic_set; - } - else { - int nBits = ceil_log2(sps->num_short_term_ref_pic_sets()); - if (nBits>0) out.write_bits(short_term_ref_pic_set_idx,nBits); - else { assert(short_term_ref_pic_set_idx==0); } - - if (short_term_ref_pic_set_idx > sps->num_short_term_ref_pic_sets()) { - errqueue->add_warning(DE265_WARNING_SHORT_TERM_REF_PIC_SET_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - //CurrRpsIdx = short_term_ref_pic_set_idx; - //CurrRps = sps->ref_pic_sets[CurrRpsIdx]; - } - - - // --- long-term MC --- - - if (sps->long_term_ref_pics_present_flag) { - if (sps->num_long_term_ref_pics_sps > 0) { - out.write_uvlc(num_long_term_sps); - } - else { - assert(num_long_term_sps == 0); - } - - out.write_uvlc(num_long_term_pics); - - - // check maximum number of reference frames - - if (num_long_term_sps + - num_long_term_pics + - CurrRps.NumNegativePics + - CurrRps.NumPositivePics - > sps->sps_max_dec_pic_buffering[sps->sps_max_sub_layers-1]) - { - errqueue->add_warning(DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED, false); - return DE265_OK; - } - - for (int i=0; inum_long_term_ref_pics_sps); - out.write_bits(lt_idx_sps[i], nBits); - - // check that the referenced lt-reference really exists - - if (lt_idx_sps[i] >= sps->num_long_term_ref_pics_sps) { - errqueue->add_warning(DE265_NON_EXISTING_LT_REFERENCE_CANDIDATE_IN_SLICE_HEADER, false); - return DE265_OK; - } - - //ctx->PocLsbLt[i] = sps->lt_ref_pic_poc_lsb_sps[ lt_idx_sps[i] ]; - //ctx->UsedByCurrPicLt[i] = sps->used_by_curr_pic_lt_sps_flag[ lt_idx_sps[i] ]; - } - else { - int nBits = sps->log2_max_pic_order_cnt_lsb; - out.write_bits(poc_lsb_lt[i], nBits); - out.write_bit(used_by_curr_pic_lt_flag[i]); - - //ctx->PocLsbLt[i] = poc_lsb_lt[i]; - //ctx->UsedByCurrPicLt[i] = used_by_curr_pic_lt_flag[i]; - } - - //if (ctx->UsedByCurrPicLt[i]) { - //NumLtPics++; - //} - - out.write_bit(delta_poc_msb_present_flag[i]); - if (delta_poc_msb_present_flag[i]) { - out.write_uvlc(delta_poc_msb_cycle_lt[i]); - } - else { - assert(delta_poc_msb_cycle_lt[i] == 0); - } - - /* - if (i==0 || i==num_long_term_sps) { - ctx->DeltaPocMsbCycleLt[i] = delta_poc_msb_cycle_lt[i]; - } - else { - ctx->DeltaPocMsbCycleLt[i] = (delta_poc_msb_cycle_lt[i] + - ctx->DeltaPocMsbCycleLt[i-1]); - } - */ - } - } - else { - assert(num_long_term_sps == 0); - assert(num_long_term_pics== 0); - } - - if (sps->sps_temporal_mvp_enabled_flag) { - out.write_bit(slice_temporal_mvp_enabled_flag); - } - else { - assert(slice_temporal_mvp_enabled_flag == 0); - } - } - else { - assert(slice_pic_order_cnt_lsb == 0); - assert(num_long_term_sps == 0); - assert(num_long_term_pics== 0); - } - - - // --- SAO --- - - if (sps->sample_adaptive_offset_enabled_flag) { - out.write_bit(slice_sao_luma_flag); - out.write_bit(slice_sao_chroma_flag); - } - else { - assert(slice_sao_luma_flag == 0); - assert(slice_sao_chroma_flag== 0); - } - - if (slice_type == SLICE_TYPE_P || - slice_type == SLICE_TYPE_B) { - out.write_bit(num_ref_idx_active_override_flag); - - if (num_ref_idx_active_override_flag) { - out.write_uvlc(num_ref_idx_l0_active); - num_ref_idx_l0_active++;; - - if (slice_type == SLICE_TYPE_B) { - out.write_uvlc(num_ref_idx_l1_active); - num_ref_idx_l1_active++; - } - } - else { - assert(num_ref_idx_l0_active == pps->num_ref_idx_l0_default_active); - assert(num_ref_idx_l1_active == pps->num_ref_idx_l1_default_active); - } - - NumPocTotalCurr = CurrRps.NumPocTotalCurr_shortterm_only + NumLtPics; - - if (pps->lists_modification_present_flag && NumPocTotalCurr > 1) { - - int nBits = ceil_log2(NumPocTotalCurr); - - out.write_bit(ref_pic_list_modification_flag_l0); - if (ref_pic_list_modification_flag_l0) { - for (int i=0;icabac_init_present_flag) { - out.write_bit(cabac_init_flag); - } - else { - assert(cabac_init_flag == 0); - } - - if (slice_temporal_mvp_enabled_flag) { - if (slice_type == SLICE_TYPE_B) - out.write_bit(collocated_from_l0_flag); - else - { assert(collocated_from_l0_flag == 1); } - - if (( collocated_from_l0_flag && num_ref_idx_l0_active > 1) || - (!collocated_from_l0_flag && num_ref_idx_l1_active > 1)) { - out.write_uvlc(collocated_ref_idx); - } - else { - assert(collocated_ref_idx == 0); - } - } - - if ((pps->weighted_pred_flag && slice_type == SLICE_TYPE_P) || - (pps->weighted_bipred_flag && slice_type == SLICE_TYPE_B)) { - - assert(0); - /* TODO - if (!read_pred_weight_table(br,this,ctx)) - { - ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - */ - } - - out.write_uvlc(five_minus_max_num_merge_cand); - //MaxNumMergeCand = 5-five_minus_max_num_merge_cand; - } - - out.write_svlc(slice_qp_delta); - - if (pps->pps_slice_chroma_qp_offsets_present_flag) { - out.write_svlc(slice_cb_qp_offset); - out.write_svlc(slice_cr_qp_offset); - } - else { - assert(slice_cb_qp_offset == 0); - assert(slice_cr_qp_offset == 0); - } - - if (pps->deblocking_filter_override_enabled_flag) { - out.write_bit(deblocking_filter_override_flag); - } - else { - assert(deblocking_filter_override_flag == 0); - } - - //slice_beta_offset = pps->beta_offset; - //slice_tc_offset = pps->tc_offset; - - if (deblocking_filter_override_flag) { - out.write_bit(slice_deblocking_filter_disabled_flag); - if (!slice_deblocking_filter_disabled_flag) { - out.write_svlc(slice_beta_offset/2); - out.write_svlc(slice_tc_offset /2); - } - } - else { - assert(slice_deblocking_filter_disabled_flag == pps->pic_disable_deblocking_filter_flag); - } - - if (pps->pps_loop_filter_across_slices_enabled_flag && - (slice_sao_luma_flag || slice_sao_chroma_flag || - !slice_deblocking_filter_disabled_flag )) { - out.write_bit(slice_loop_filter_across_slices_enabled_flag); - } - else { - assert(slice_loop_filter_across_slices_enabled_flag == - pps->pps_loop_filter_across_slices_enabled_flag); - } - } - - if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag ) { - out.write_uvlc(num_entry_point_offsets); - - if (num_entry_point_offsets > 0) { - out.write_uvlc(offset_len-1); - - for (int i=0; i0) prev = entry_point_offset[i-1]; - out.write_bits(entry_point_offset[i]-prev-1, offset_len); - } - } - } - } - else { - assert(num_entry_point_offsets == 0); - } - - if (pps->slice_segment_header_extension_present_flag) { - out.write_uvlc(slice_segment_header_extension_length); - if (slice_segment_header_extension_length > 1000) { // TODO: safety check against too large values - errqueue->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); - return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; - } - - for (int i=0; ipic_init_qp + slice_qp_delta; - - switch (slice_type) - { - case SLICE_TYPE_I: initType = 0; break; - case SLICE_TYPE_P: initType = cabac_init_flag + 1; break; - case SLICE_TYPE_B: initType = 2 - cabac_init_flag; break; - } - - MaxNumMergeCand = 5-five_minus_max_num_merge_cand; -} - - -//----------------------------------------------------------------------- - - -void slice_segment_header::dump_slice_segment_header(const decoder_context* ctx, int fd) const -{ - FILE* fh; - if (fd==1) fh=stdout; - else if (fd==2) fh=stderr; - else { return; } - -#define LOG0(t) log2fh(fh, t) -#define LOG1(t,d) log2fh(fh, t,d) -#define LOG2(t,d1,d2) log2fh(fh, t,d1,d2) -#define LOG3(t,d1,d2,d3) log2fh(fh, t,d1,d2,d3) -#define LOG4(t,d1,d2,d3,d4) log2fh(fh, t,d1,d2,d3,d4) - - const pic_parameter_set* pps = ctx->get_pps(slice_pic_parameter_set_id); - assert(pps->pps_read); // TODO: error handling - - const seq_parameter_set* sps = ctx->get_sps((int)pps->seq_parameter_set_id); - assert(sps->sps_read); // TODO: error handling - - - LOG0("----------------- SLICE -----------------\n"); - LOG1("first_slice_segment_in_pic_flag : %d\n", first_slice_segment_in_pic_flag); - if (ctx->get_nal_unit_type() >= NAL_UNIT_BLA_W_LP && - ctx->get_nal_unit_type() <= NAL_UNIT_RESERVED_IRAP_VCL23) { - LOG1("no_output_of_prior_pics_flag : %d\n", no_output_of_prior_pics_flag); - } - - LOG1("slice_pic_parameter_set_id : %d\n", slice_pic_parameter_set_id); - - if (!first_slice_segment_in_pic_flag) { - //if (pps->dependent_slice_segments_enabled_flag) { - LOG1("dependent_slice_segment_flag : %d\n", dependent_slice_segment_flag); - //} - LOG1("slice_segment_address : %d\n", slice_segment_address); - } - - //if (!dependent_slice_segment_flag) - { - //for (int i=0; inum_extra_slice_header_bits; i++) { - //slice_reserved_flag[i] - - LOG1("slice_type : %c\n", - slice_type == 0 ? 'B' : - slice_type == 1 ? 'P' : 'I'); - - if (pps->output_flag_present_flag) { - LOG1("pic_output_flag : %d\n", pic_output_flag); - } - - if (sps->separate_colour_plane_flag == 1) { - LOG1("colour_plane_id : %d\n", colour_plane_id); - } - - LOG1("slice_pic_order_cnt_lsb : %d\n", slice_pic_order_cnt_lsb); - - if (ctx->get_nal_unit_type() != NAL_UNIT_IDR_W_RADL && - ctx->get_nal_unit_type() != NAL_UNIT_IDR_N_LP) { - LOG1("short_term_ref_pic_set_sps_flag : %d\n", short_term_ref_pic_set_sps_flag); - - if (!short_term_ref_pic_set_sps_flag) { - LOG1("ref_pic_set[ %2d ]: ",sps->num_short_term_ref_pic_sets()); - dump_compact_short_term_ref_pic_set(&slice_ref_pic_set, 16, fh); - } - else if (sps->num_short_term_ref_pic_sets() > 1) { - LOG1("short_term_ref_pic_set_idx : %d\n", short_term_ref_pic_set_idx); - dump_compact_short_term_ref_pic_set(&sps->ref_pic_sets[short_term_ref_pic_set_idx], 16, fh); - } - - if (sps->long_term_ref_pics_present_flag) { - if (sps->num_long_term_ref_pics_sps > 0) { - LOG1("num_long_term_sps : %d\n", num_long_term_sps); - } - - LOG1("num_long_term_pics : %d\n", num_long_term_pics); - -#if 0 - for (int i=0; iPocLsbLt[i]); - LOG2("UsedByCurrPicLt[%d] : %d\n", i, ctx->UsedByCurrPicLt[i]); - LOG2("DeltaPocMsbCycleLt[%d] : %d\n", i, ctx->DeltaPocMsbCycleLt[i]); - } -#endif - } - - if (sps->sps_temporal_mvp_enabled_flag) { - LOG1("slice_temporal_mvp_enabled_flag : %d\n", slice_temporal_mvp_enabled_flag); - } - } - - - if (sps->sample_adaptive_offset_enabled_flag) { - LOG1("slice_sao_luma_flag : %d\n", slice_sao_luma_flag); - LOG1("slice_sao_chroma_flag : %d\n", slice_sao_chroma_flag); - } - - - if (slice_type == SLICE_TYPE_P || slice_type == SLICE_TYPE_B) { - LOG1("num_ref_idx_active_override_flag : %d\n", num_ref_idx_active_override_flag); - - LOG2("num_ref_idx_l0_active : %d %s\n", num_ref_idx_l0_active, - num_ref_idx_active_override_flag ? "" : "(from PPS)"); - - if (slice_type == SLICE_TYPE_B) { - LOG2("num_ref_idx_l1_active : %d %s\n", num_ref_idx_l1_active, - num_ref_idx_active_override_flag ? "" : "(from PPS)"); - } - - if (pps->lists_modification_present_flag && NumPocTotalCurr > 1) - { - LOG1("ref_pic_list_modification_flag_l0 : %d\n", ref_pic_list_modification_flag_l0); - if (ref_pic_list_modification_flag_l0) { - for (int i=0;iweighted_pred_flag && slice_type == SLICE_TYPE_P) || - (pps->weighted_bipred_flag && slice_type == SLICE_TYPE_B)) - { - LOG1("luma_log2_weight_denom : %d\n", luma_log2_weight_denom); - if (sps->chroma_format_idc != 0) { - LOG1("ChromaLog2WeightDenom : %d\n", ChromaLog2WeightDenom); - } - - for (int l=0;l<=1;l++) - if (l==0 || (l==1 && slice_type == SLICE_TYPE_B)) - { - int num_ref = (l==0 ? - num_ref_idx_l0_active-1 : - num_ref_idx_l1_active-1); - - if (false) { // do not show these flags - for (int i=0;i<=num_ref;i++) { - LOG3("luma_weight_flag_l%d[%d] : %d\n",l,i,luma_weight_flag[l][i]); - } - - if (sps->chroma_format_idc != 0) { - for (int i=0;i<=num_ref;i++) { - LOG3("chroma_weight_flag_l%d[%d] : %d\n",l,i,chroma_weight_flag[l][i]); - } - } - } - - for (int i=0;i<=num_ref;i++) { - LOG3("LumaWeight_L%d[%d] : %d\n",l,i,LumaWeight[l][i]); - LOG3("luma_offset_l%d[%d] : %d\n",l,i,luma_offset[l][i]); - - for (int j=0;j<2;j++) { - LOG4("ChromaWeight_L%d[%d][%d] : %d\n",l,i,j,ChromaWeight[l][i][j]); - LOG4("ChromaOffset_L%d[%d][%d] : %d\n",l,i,j,ChromaOffset[l][i][j]); - } - } - } - } - - LOG1("five_minus_max_num_merge_cand : %d\n", five_minus_max_num_merge_cand); - } - - - LOG1("slice_qp_delta : %d\n", slice_qp_delta); - if (pps->pps_slice_chroma_qp_offsets_present_flag) { - LOG1("slice_cb_qp_offset : %d\n", slice_cb_qp_offset); - LOG1("slice_cr_qp_offset : %d\n", slice_cr_qp_offset); - } - - if (pps->deblocking_filter_override_enabled_flag) { - LOG1("deblocking_filter_override_flag : %d\n", deblocking_filter_override_flag); - } - - LOG2("slice_deblocking_filter_disabled_flag : %d %s\n", - slice_deblocking_filter_disabled_flag, - (deblocking_filter_override_flag ? "(override)" : "(from pps)")); - - if (deblocking_filter_override_flag) { - - if (!slice_deblocking_filter_disabled_flag) { - LOG1("slice_beta_offset : %d\n", slice_beta_offset); - LOG1("slice_tc_offset : %d\n", slice_tc_offset); - } - } - - if (pps->pps_loop_filter_across_slices_enabled_flag && - (slice_sao_luma_flag || slice_sao_chroma_flag || - !slice_deblocking_filter_disabled_flag)) { - LOG1("slice_loop_filter_across_slices_enabled_flag : %d\n", - slice_loop_filter_across_slices_enabled_flag); - } - } - - if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag) { - LOG1("num_entry_point_offsets : %d\n", num_entry_point_offsets); - - if (num_entry_point_offsets > 0) { - LOG1("offset_len : %d\n", offset_len); - - for (int i=0; ishdr->SliceQPY; - const int initType = tctx->shdr->initType; - assert(initType >= 0 && initType <= 2); - - tctx->ctx_model.init(initType, QPY); - - for (int i=0;i<4;i++) { - tctx->StatCoeff[i] = 0; - } -} - - - -static int decode_transform_skip_flag(thread_context* tctx, int cIdx) -{ - const int context = (cIdx==0) ? 0 : 1; - - logtrace(LogSlice,"# transform_skip_flag (context=%d)\n",context); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_TRANSFORM_SKIP_FLAG+context]); - - logtrace(LogSymbols,"$1 transform_skip_flag=%d\n",bit); - - return bit; -} - - -static int decode_sao_merge_flag(thread_context* tctx) -{ - logtrace(LogSlice,"# sao_merge_left/up_flag\n"); - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_SAO_MERGE_FLAG]); - - logtrace(LogSymbols,"$1 sao_merge_flag=%d\n",bit); - - return bit; -} - - - -static int decode_sao_type_idx(thread_context* tctx) -{ - logtrace(LogSlice,"# sao_type_idx_luma/chroma\n"); - - int bit0 = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_SAO_TYPE_IDX]); - - if (bit0==0) { - logtrace(LogSymbols,"$1 sao_type_idx=%d\n",0); - return 0; - } - else { - int bit1 = decode_CABAC_bypass(&tctx->cabac_decoder); - if (bit1==0) { - logtrace(LogSymbols,"$1 sao_type_idx=%d\n",1); - return 1; - } - else { - logtrace(LogSymbols,"$1 sao_type_idx=%d\n",2); - return 2; - } - } -} - - -static int decode_sao_offset_abs(thread_context* tctx, int bitDepth) -{ - logtrace(LogSlice,"# sao_offset_abs\n"); - int cMax = (1<<(libde265_min(bitDepth,10)-5))-1; - int value = decode_CABAC_TU_bypass(&tctx->cabac_decoder, cMax); - logtrace(LogSymbols,"$1 sao_offset_abs=%d\n",value); - return value; -} - - -static int decode_sao_class(thread_context* tctx) -{ - logtrace(LogSlice,"# sao_class\n"); - int value = decode_CABAC_FL_bypass(&tctx->cabac_decoder, 2); - logtrace(LogSymbols,"$1 sao_class=%d\n",value); - return value; -} - - -static int decode_sao_offset_sign(thread_context* tctx) -{ - logtrace(LogSlice,"# sao_offset_sign\n"); - int value = decode_CABAC_bypass(&tctx->cabac_decoder); - logtrace(LogSymbols,"$1 sao_offset_sign=%d\n",value); - return value; -} - - -static int decode_sao_band_position(thread_context* tctx) -{ - logtrace(LogSlice,"# sao_band_position\n"); - int value = decode_CABAC_FL_bypass(&tctx->cabac_decoder,5); - logtrace(LogSymbols,"$1 sao_band_position=%d\n",value); - return value; -} - - -static int decode_transquant_bypass_flag(thread_context* tctx) -{ - logtrace(LogSlice,"# cu_transquant_bypass_enable_flag\n"); - int value = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_CU_TRANSQUANT_BYPASS_FLAG]); - logtrace(LogSymbols,"$1 transquant_bypass_flag=%d\n",value); - return value; -} - - -#include -#include - -static int decode_split_cu_flag(thread_context* tctx, - int x0, int y0, int ctDepth) -{ - // check if neighbors are available - - int availableL = check_CTB_available(tctx->img, x0,y0, x0-1,y0); - int availableA = check_CTB_available(tctx->img, x0,y0, x0,y0-1); - - int condL = 0; - int condA = 0; - - if (availableL && tctx->img->get_ctDepth(x0-1,y0) > ctDepth) condL=1; - if (availableA && tctx->img->get_ctDepth(x0,y0-1) > ctDepth) condA=1; - - int contextOffset = condL + condA; - int context = contextOffset; - - // decode bit - - logtrace(LogSlice,"# split_cu_flag context=%d R=%x\n", context, tctx->cabac_decoder.range); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_SPLIT_CU_FLAG + context]); - - logtrace(LogSlice,"> split_cu_flag R=%x, ctx=%d, bit=%d\n", tctx->cabac_decoder.range,context,bit); - - logtrace(LogSymbols,"$1 split_cu_flag=%d\n",bit); - - return bit; -} - - -static int decode_cu_skip_flag(thread_context* tctx, - int x0, int y0, int ctDepth) -{ - decoder_context* ctx = tctx->decctx; - - // check if neighbors are available - - int availableL = check_CTB_available(tctx->img, x0,y0, x0-1,y0); - int availableA = check_CTB_available(tctx->img, x0,y0, x0,y0-1); - - int condL = 0; - int condA = 0; - - if (availableL && tctx->img->get_cu_skip_flag(x0-1,y0)) condL=1; - if (availableA && tctx->img->get_cu_skip_flag(x0,y0-1)) condA=1; - - int contextOffset = condL + condA; - int context = contextOffset; - - // decode bit - - logtrace(LogSlice,"# cu_skip_flag context=%d R=%x\n", context, tctx->cabac_decoder.range); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_CU_SKIP_FLAG + context]); - - logtrace(LogSlice,"> cu_skip_flag R=%x, ctx=%d, bit=%d\n", tctx->cabac_decoder.range,context,bit); - - logtrace(LogSymbols,"$1 cu_skip_flag=%d\n",bit); - - return bit; -} - - -static enum PartMode decode_part_mode(thread_context* tctx, - enum PredMode pred_mode, int cLog2CbSize) -{ - de265_image* img = tctx->img; - - if (pred_mode == MODE_INTRA) { - logtrace(LogSlice,"# part_mode (INTRA)\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE]); - - logtrace(LogSlice,"> %s\n",bit ? "2Nx2N" : "NxN"); - - logtrace(LogSymbols,"$1 part_mode=%d\n",bit ? PART_2Nx2N : PART_NxN); - - return bit ? PART_2Nx2N : PART_NxN; - } - else { - const seq_parameter_set& sps = img->get_sps(); - - int bit0 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+0]); - if (bit0) { logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2Nx2N); return PART_2Nx2N; } - - // CHECK_ME: I optimize code and fix bug here, need more VERIFY! - int bit1 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+1]); - if (cLog2CbSize > sps.Log2MinCbSizeY) { - if (!sps.amp_enabled_flag) { - logtrace(LogSymbols,"$1 part_mode=%d\n",bit1 ? PART_2NxN : PART_Nx2N); - return bit1 ? PART_2NxN : PART_Nx2N; - } - else { - int bit3 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+3]); - if (bit3) { - logtrace(LogSymbols,"$1 part_mode=%d\n",bit1 ? PART_2NxN : PART_Nx2N); - return bit1 ? PART_2NxN : PART_Nx2N; - } - - int bit4 = decode_CABAC_bypass(&tctx->cabac_decoder); - if ( bit1 && bit4) { - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2NxnD); - return PART_2NxnD; - } - if ( bit1 && !bit4) { - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2NxnU); - return PART_2NxnU; - } - if (!bit1 && !bit4) { - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_nLx2N); - return PART_nLx2N; - } - if (!bit1 && bit4) { - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_nRx2N); - return PART_nRx2N; - } - } - } - else { - // TODO, we could save one if here when first decoding the next bin and then - // checkcLog2CbSize==3 when it is '0' - - if (bit1) { - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2NxN); - return PART_2NxN; - } - - if (cLog2CbSize==3) { - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_Nx2N); - return PART_Nx2N; - } - else { - int bit2 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+2]); - logtrace(LogSymbols,"$1 part_mode=%d\n",PART_NxN-bit2); - return (enum PartMode)((int)PART_NxN - bit2)/*bit2 ? PART_Nx2N : PART_NxN*/; - } - } - } - - assert(false); // should never be reached - return PART_2Nx2N; -} - - -static inline int decode_prev_intra_luma_pred_flag(thread_context* tctx) -{ - logtrace(LogSlice,"# prev_intra_luma_pred_flag\n"); - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PREV_INTRA_LUMA_PRED_FLAG]); - logtrace(LogSymbols,"$1 prev_intra_luma_pred_flag=%d\n",bit); - return bit; -} - - -static inline int decode_mpm_idx(thread_context* tctx) -{ - logtrace(LogSlice,"# mpm_idx (TU:2)\n"); - int mpm = decode_CABAC_TU_bypass(&tctx->cabac_decoder, 2); - logtrace(LogSlice,"> mpm_idx = %d\n",mpm); - logtrace(LogSymbols,"$1 mpm_idx=%d\n",mpm); - return mpm; -} - - -static inline int decode_rem_intra_luma_pred_mode(thread_context* tctx) -{ - logtrace(LogSlice,"# rem_intra_luma_pred_mode (5 bits)\n"); - int value = decode_CABAC_FL_bypass(&tctx->cabac_decoder, 5); - logtrace(LogSymbols,"$1 rem_intra_luma_pred_mode=%d\n",value); - return value; -} - - -static int decode_intra_chroma_pred_mode(thread_context* tctx) -{ - logtrace(LogSlice,"# intra_chroma_pred_mode\n"); - - int prefix = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_INTRA_CHROMA_PRED_MODE]); - - int mode; - if (prefix==0) { - mode=4; - } - else { - mode = decode_CABAC_FL_bypass(&tctx->cabac_decoder, 2); - } - - logtrace(LogSlice,"> intra_chroma_pred_mode = %d\n",mode); - logtrace(LogSymbols,"$1 intra_chroma_pred_mode=%d\n",mode); - - return mode; -} - - -static int decode_split_transform_flag(thread_context* tctx, - int log2TrafoSize) -{ - logtrace(LogSlice,"# split_transform_flag (log2TrafoSize=%d)\n",log2TrafoSize); - - int context = 5-log2TrafoSize; - assert(context >= 0 && context <= 2); - - logtrace(LogSlice,"# context: %d\n",context); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_SPLIT_TRANSFORM_FLAG + context]); - logtrace(LogSymbols,"$1 split_transform_flag=%d\n",bit); - return bit; -} - - -static int decode_cbf_chroma(thread_context* tctx, - int trafoDepth) -{ - logtrace(LogSlice,"# cbf_chroma\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_CBF_CHROMA + trafoDepth]); - - logtrace(LogSymbols,"$1 cbf_chroma=%d\n",bit); - return bit; -} - - -static int decode_cbf_luma(thread_context* tctx, - int trafoDepth) -{ - logtrace(LogSlice,"# cbf_luma\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_CBF_LUMA + (trafoDepth==0)]); - - logtrace(LogSlice,"> cbf_luma = %d\n",bit); - - logtrace(LogSymbols,"$1 cbf_luma=%d\n",bit); - return bit; -} - - -static inline int decode_coded_sub_block_flag(thread_context* tctx, - int cIdx, - uint8_t coded_sub_block_neighbors) -{ - logtrace(LogSlice,"# coded_sub_block_flag\n"); - - // tricky computation of csbfCtx - int csbfCtx = ((coded_sub_block_neighbors & 1) | // right neighbor set or - (coded_sub_block_neighbors >> 1)); // bottom neighbor set -> csbfCtx=1 - - int ctxIdxInc = csbfCtx; - if (cIdx!=0) { - ctxIdxInc += 2; - } - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_CODED_SUB_BLOCK_FLAG + ctxIdxInc]); - - logtrace(LogSymbols,"$1 coded_sub_block_flag=%d\n",bit); - return bit; -} - - -static int decode_cu_qp_delta_abs(thread_context* tctx) -{ - logtrace(LogSlice,"# cu_qp_delta_abs\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_CU_QP_DELTA_ABS + 0]); - if (bit==0) { - logtrace(LogSymbols,"$1 cu_qp_delta_abs=%d\n",0); - return 0; - } - - int prefix=1; - for (int i=0;i<4;i++) { - bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_CU_QP_DELTA_ABS + 1]); - if (bit==0) { break; } - else { prefix++; } - } - - if (prefix==5) { - int value = decode_CABAC_EGk_bypass(&tctx->cabac_decoder, 0); - logtrace(LogSymbols,"$1 cu_qp_delta_abs=%d\n",value+5); - return value + 5; - } - else { - logtrace(LogSymbols,"$1 cu_qp_delta_abs=%d\n",prefix); - return prefix; - } -} - - -static int decode_last_significant_coeff_prefix(thread_context* tctx, - int log2TrafoSize, - int cIdx, - context_model* model) -{ - logtrace(LogSlice,"# last_significant_coeff_prefix log2TrafoSize:%d cIdx:%d\n",log2TrafoSize,cIdx); - - int cMax = (log2TrafoSize<<1)-1; - - int ctxOffset, ctxShift; - if (cIdx==0) { - ctxOffset = 3*(log2TrafoSize-2) + ((log2TrafoSize-1)>>2); - ctxShift = (log2TrafoSize+1)>>2; - } - else { - ctxOffset = 15; - ctxShift = log2TrafoSize-2; - } - - int binIdx; - int value = cMax; - for (binIdx=0;binIdx> ctxShift); - - logtrace(LogSlice,"context: %d+%d\n",ctxOffset,ctxIdxInc); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, &model[ctxOffset + ctxIdxInc]); - if (bit==0) { - value=binIdx; - break; - } - } - - logtrace(LogSlice,"> last_significant_coeff_prefix: %d\n", value); - - return value; -} - - -static const uint8_t ctxIdxMap[16] = { - 0,1,4,5, - 2,3,4,5, - 6,6,8,8, - 7,7,8,99 -}; - -uint8_t* ctxIdxLookup[4 /* 4-log2-32 */][2 /* !!cIdx */][2 /* !!scanIdx */][4 /* prevCsbf */]; - -bool alloc_and_init_significant_coeff_ctxIdx_lookupTable() -{ - int tableSize = 4*4*(2) + 8*8*(2*2*4) + 16*16*(2*4) + 32*32*(2*4); - - uint8_t* p = (uint8_t*)malloc(tableSize); - if (p==NULL) { - return false; - } - - memset(p,0xFF,tableSize); // just for debugging - - - // --- Set pointers to memory areas. Note that some parameters share the same memory. --- - - // 4x4 - - for (int cIdx=0;cIdx<2;cIdx++) { - for (int scanIdx=0;scanIdx<2;scanIdx++) - for (int prevCsbf=0;prevCsbf<4;prevCsbf++) - ctxIdxLookup[0][cIdx][scanIdx][prevCsbf] = p; - - p += 4*4; - } - - // 8x8 - - for (int cIdx=0;cIdx<2;cIdx++) - for (int scanIdx=0;scanIdx<2;scanIdx++) - for (int prevCsbf=0;prevCsbf<4;prevCsbf++) { - ctxIdxLookup[1][cIdx][scanIdx][prevCsbf] = p; - p += 8*8; - } - - // 16x16 - - for (int cIdx=0;cIdx<2;cIdx++) - for (int prevCsbf=0;prevCsbf<4;prevCsbf++) { - for (int scanIdx=0;scanIdx<2;scanIdx++) { - ctxIdxLookup[2][cIdx][scanIdx][prevCsbf] = p; - } - - p += 16*16; - } - - // 32x32 - - for (int cIdx=0;cIdx<2;cIdx++) - for (int prevCsbf=0;prevCsbf<4;prevCsbf++) { - for (int scanIdx=0;scanIdx<2;scanIdx++) { - ctxIdxLookup[3][cIdx][scanIdx][prevCsbf] = p; - } - - p += 32*32; - } - - - // --- precompute ctxIdx tables --- - - for (int log2w=2; log2w<=5 ; log2w++) - for (int cIdx=0;cIdx<2;cIdx++) - for (int scanIdx=0;scanIdx<2;scanIdx++) - for (int prevCsbf=0;prevCsbf<4;prevCsbf++) - { - for (int yC=0;yC<(1<>2; - - int sigCtx; - - // if log2TrafoSize==2 - if (sbWidth==1) { - sigCtx = ctxIdxMap[(yC<<2) + xC]; - } - else if (xC+yC==0) { - sigCtx = 0; - } - else { - int xS = xC>>2; - int yS = yC>>2; - /* - int prevCsbf = 0; - - if (xS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+1 +yS*sbWidth]; } - if (yS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+(1+yS)*sbWidth]<<1; } - */ - int xP = xC & 3; - int yP = yC & 3; - - //logtrace(LogSlice,"posInSubset: %d,%d\n",xP,yP); - //logtrace(LogSlice,"prevCsbf: %d\n",prevCsbf); - - switch (prevCsbf) { - case 0: - sigCtx = (xP+yP>=3) ? 0 : (xP+yP>0) ? 1 : 2; - break; - case 1: - sigCtx = (yP==0) ? 2 : (yP==1) ? 1 : 0; - break; - case 2: - sigCtx = (xP==0) ? 2 : (xP==1) ? 1 : 0; - break; - default: - sigCtx = 2; - break; - } - - //logtrace(LogSlice,"a) sigCtx=%d\n",sigCtx); - - if (cIdx==0) { - if (xS+yS > 0) sigCtx+=3; - - //logtrace(LogSlice,"b) sigCtx=%d\n",sigCtx); - - // if log2TrafoSize==3 - if (sbWidth==2) { // 8x8 block - sigCtx += (scanIdx==0) ? 9 : 15; - } else { - sigCtx += 21; - } - - //logtrace(LogSlice,"c) sigCtx=%d\n",sigCtx); - } - else { - // if log2TrafoSize==3 - if (sbWidth==2) { // 8x8 block - sigCtx+=9; - } - else { - sigCtx+=12; - } - } - - } - - int ctxIdxInc; - if (cIdx==0) { ctxIdxInc=sigCtx; } - else { ctxIdxInc=27+sigCtx; } - - if (ctxIdxLookup[log2w-2][cIdx][scanIdx][prevCsbf][xC+(yC<>4]; - int x0 = S.x<<2; - int y0 = S.y<<2; - - int subX = ScanOrderPos[s & 0xF].x; - int subY = ScanOrderPos[s & 0xF].y; - int xC = x0 + subX; - int yC = y0 + subY; - - - int w = 1<>2; - - int sigCtx; - - // if log2TrafoSize==2 - if (sbWidth==1) { - sigCtx = ctxIdxMap[(yC<<2) + xC]; - } - else if (xC+yC==0) { - sigCtx = 0; - } - else { - int xS = xC>>2; - int yS = yC>>2; - /* - int prevCsbf = 0; - - if (xS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+1 +yS*sbWidth]; } - if (yS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+(1+yS)*sbWidth]<<1; } - */ - int xP = xC & 3; - int yP = yC & 3; - - logtrace(LogSlice,"posInSubset: %d,%d\n",xP,yP); - logtrace(LogSlice,"prevCsbf: %d\n",prevCsbf); - - //printf("%d | %d %d\n",prevCsbf,xP,yP); - - switch (prevCsbf) { - case 0: - //sigCtx = (xP+yP==0) ? 2 : (xP+yP<3) ? 1 : 0; - sigCtx = (xP+yP>=3) ? 0 : (xP+yP>0) ? 1 : 2; - break; - case 1: - sigCtx = (yP==0) ? 2 : (yP==1) ? 1 : 0; - break; - case 2: - sigCtx = (xP==0) ? 2 : (xP==1) ? 1 : 0; - break; - default: - sigCtx = 2; - break; - } - - logtrace(LogSlice,"a) sigCtx=%d\n",sigCtx); - - if (cIdx==0) { - if (xS+yS > 0) sigCtx+=3; - - logtrace(LogSlice,"b) sigCtx=%d\n",sigCtx); - - // if log2TrafoSize==3 - if (sbWidth==2) { // 8x8 block - sigCtx += (scanIdx==0) ? 9 : 15; - } else { - sigCtx += 21; - } - - logtrace(LogSlice,"c) sigCtx=%d\n",sigCtx); - } - else { - // if log2TrafoSize==3 - if (sbWidth==2) { // 8x8 block - sigCtx+=9; - } - else { - sigCtx+=12; - } - } - } - - int ctxIdxInc; - if (cIdx==0) { ctxIdxInc=sigCtx; } - else { ctxIdxInc=27+sigCtx; } - - - ctxIdxLookup[log2w-2][cIdx][scanIdx][prevCsbf][xC+(yC<>2; - int yS = yC>>2; - int prevCsbf = 0; - if (xS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+1 +yS*sbWidth]; } - if (yS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+(1+yS)*sbWidth]<<1; } - - int xP = xC & 3; - int yP = yC & 3; - - logtrace(LogSlice,"posInSubset: %d,%d\n",xP,yP); - logtrace(LogSlice,"prevCsbf: %d\n",prevCsbf); - - //printf("%d | %d %d\n",prevCsbf,xP,yP); - - switch (prevCsbf) { - case 0: - //sigCtx = (xP+yP==0) ? 2 : (xP+yP<3) ? 1 : 0; - sigCtx = (xP+yP>=3) ? 0 : (xP+yP>0) ? 1 : 2; - break; - case 1: - sigCtx = (yP==0) ? 2 : (yP==1) ? 1 : 0; - break; - case 2: - sigCtx = (xP==0) ? 2 : (xP==1) ? 1 : 0; - break; - default: - sigCtx = 2; - break; - } - - logtrace(LogSlice,"a) sigCtx=%d\n",sigCtx); - - if (cIdx==0) { - if (xS+yS > 0) sigCtx+=3; - - logtrace(LogSlice,"b) sigCtx=%d\n",sigCtx); - - // if log2TrafoSize==3 - if (sbWidth==2) { - sigCtx += (scanIdx==0) ? 9 : 15; - } else { - sigCtx += 21; - } - - logtrace(LogSlice,"c) sigCtx=%d\n",sigCtx); - } - else { - // if log2TrafoSize==3 - if (sbWidth==2) { - sigCtx+=9; - } - else { - sigCtx+=12; - } - } - } - - int ctxIdxInc; - if (cIdx==0) { ctxIdxInc=sigCtx; } - else { ctxIdxInc=27+sigCtx; } - - int context = tctx->shdr->initType*42 + ctxIdxInc; - logtrace(LogSlice,"context: %d\n",context); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG + context]); - return bit; -} -#endif - - - -static inline int decode_significant_coeff_flag_lookup(thread_context* tctx, - uint8_t ctxIdxInc) -{ - logtrace(LogSlice,"# significant_coeff_flag\n"); - logtrace(LogSlice,"context: %d\n",ctxIdxInc); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG + ctxIdxInc]); - - logtrace(LogSymbols,"$1 significant_coeff_flag=%d\n",bit); - - return bit; -} - - - - - -static inline int decode_coeff_abs_level_greater1(thread_context* tctx, - int cIdx, int i, - bool firstCoeffInSubblock, - bool firstSubblock, - int lastSubblock_greater1Ctx, - int* lastInvocation_greater1Ctx, - int* lastInvocation_coeff_abs_level_greater1_flag, - int* lastInvocation_ctxSet, int c1) -{ - logtrace(LogSlice,"# coeff_abs_level_greater1\n"); - - logtrace(LogSlice," cIdx:%d i:%d firstCoeffInSB:%d firstSB:%d lastSB>1:%d last>1Ctx:%d lastLev>1:%d lastCtxSet:%d\n", cIdx,i,firstCoeffInSubblock,firstSubblock,lastSubblock_greater1Ctx, - *lastInvocation_greater1Ctx, - *lastInvocation_coeff_abs_level_greater1_flag, - *lastInvocation_ctxSet); - - int lastGreater1Ctx; - int greater1Ctx; - int ctxSet; - - logtrace(LogSlice,"c1: %d\n",c1); - - if (firstCoeffInSubblock) { - // block with real DC -> ctx 0 - if (i==0 || cIdx>0) { ctxSet=0; } - else { ctxSet=2; } - - if (firstSubblock) { lastGreater1Ctx=1; } - else { lastGreater1Ctx = lastSubblock_greater1Ctx; } - - if (lastGreater1Ctx==0) { ctxSet++; } - - logtrace(LogSlice,"ctxSet: %d\n",ctxSet); - - greater1Ctx=1; - } - else { // !firstCoeffInSubblock - ctxSet = *lastInvocation_ctxSet; - logtrace(LogSlice,"ctxSet (old): %d\n",ctxSet); - - greater1Ctx = *lastInvocation_greater1Ctx; - if (greater1Ctx>0) { - int lastGreater1Flag=*lastInvocation_coeff_abs_level_greater1_flag; - if (lastGreater1Flag==1) greater1Ctx=0; - else { /*if (greater1Ctx>0)*/ greater1Ctx++; } - } - } - - ctxSet = c1; // use HM algo - - int ctxIdxInc = (ctxSet*4) + (greater1Ctx>=3 ? 3 : greater1Ctx); - - if (cIdx>0) { ctxIdxInc+=16; } - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER1_FLAG + ctxIdxInc]); - - *lastInvocation_greater1Ctx = greater1Ctx; - *lastInvocation_coeff_abs_level_greater1_flag = bit; - *lastInvocation_ctxSet = ctxSet; - - //logtrace(LogSymbols,"$1 coeff_abs_level_greater1=%d\n",bit); - - return bit; -} - - -static int decode_coeff_abs_level_greater2(thread_context* tctx, - int cIdx, // int i,int n, - int ctxSet) -{ - logtrace(LogSlice,"# coeff_abs_level_greater2\n"); - - int ctxIdxInc = ctxSet; - - if (cIdx>0) ctxIdxInc+=4; - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER2_FLAG + ctxIdxInc]); - - logtrace(LogSymbols,"$1 coeff_abs_level_greater2=%d\n",bit); - - return bit; -} - - -#define MAX_PREFIX 64 - -static int decode_coeff_abs_level_remaining(thread_context* tctx, - int cRiceParam) -{ - logtrace(LogSlice,"# decode_coeff_abs_level_remaining\n"); - - int prefix=-1; - int codeword=0; - do { - prefix++; - codeword = decode_CABAC_bypass(&tctx->cabac_decoder); - - if (prefix>MAX_PREFIX) { - return 0; // TODO: error - } - } - while (codeword); - - // prefix = nb. 1 bits - - int value; - - if (prefix <= 3) { - // when code only TR part (level < TRMax) - - codeword = decode_CABAC_FL_bypass(&tctx->cabac_decoder, cRiceParam); - value = (prefix<cabac_decoder, prefix-3+cRiceParam); - value = (((1<<(prefix-3))+3-1)<cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_MERGE_FLAG]); - - logtrace(LogSymbols,"$1 merge_flag=%d\n",bit); - - return bit; -} - - -static int decode_merge_idx(thread_context* tctx) -{ - logtrace(LogSlice,"# merge_idx\n"); - - if (tctx->shdr->MaxNumMergeCand <= 1) { - logtrace(LogSymbols,"$1 merge_idx=%d\n",0); - return 0; - } - - // TU coding, first bin is CABAC, remaining are bypass. - // cMax = MaxNumMergeCand-1 - - int idx = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_MERGE_IDX]); - - if (idx==0) { - // nothing - } - else { - idx=1; - - while (idxshdr->MaxNumMergeCand-1) { - if (decode_CABAC_bypass(&tctx->cabac_decoder)) { - idx++; - } - else { - break; - } - } - } - - logtrace(LogSlice,"> merge_idx = %d\n",idx); - logtrace(LogSymbols,"$1 merge_idx=%d\n",idx); - - return idx; -} - - -static int decode_pred_mode_flag(thread_context* tctx) -{ - logtrace(LogSlice,"# pred_mode_flag\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_PRED_MODE_FLAG]); - - logtrace(LogSymbols,"$1 pred_mode=%d\n",bit); - return bit; -} - -static int decode_mvp_lx_flag(thread_context* tctx) -{ - logtrace(LogSlice,"# mvp_lx_flag\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_MVP_LX_FLAG]); - - logtrace(LogSymbols,"$1 mvp_lx_flag=%d\n",bit); - return bit; -} - -static int decode_rqt_root_cbf(thread_context* tctx) -{ - logtrace(LogSlice,"# rqt_root_cbf\n"); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_RQT_ROOT_CBF]); - - logtrace(LogSymbols,"$1 rqt_root_cbf=%d\n",bit); - return bit; -} - -static int decode_ref_idx_lX(thread_context* tctx, int numRefIdxLXActive) -{ - logtrace(LogSlice,"# ref_idx_lX\n"); - - int cMax = numRefIdxLXActive-1; - - if (cMax==0) { - logtrace(LogSlice,"> ref_idx = 0 (cMax==0)\n"); - return 0; - } // do check for single reference frame here - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_REF_IDX_LX + 0]); - - int idx=0; - - while (bit) { - idx++; - if (idx==cMax) { break; } - - if (idx==1) { - bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_REF_IDX_LX + 1]); - } - else { - bit = decode_CABAC_bypass(&tctx->cabac_decoder); - } - } - - logtrace(LogSlice,"> ref_idx = %d\n",idx); - - logtrace(LogSymbols,"$1 ref_idx_lX=%d\n",idx); - return idx; -} - - -static enum InterPredIdc decode_inter_pred_idc(thread_context* tctx, - int x0, int y0, - int nPbW, int nPbH, - int ctDepth) -{ - logtrace(LogSlice,"# inter_pred_idc\n"); - - int value; - - context_model* model = &tctx->ctx_model[CONTEXT_MODEL_INTER_PRED_IDC]; - - if (nPbW+nPbH==12) { - value = decode_CABAC_bit(&tctx->cabac_decoder, - &model[4]); - } - else { - int bit0 = decode_CABAC_bit(&tctx->cabac_decoder, - &model[ctDepth]); - if (bit0==0) { - value = decode_CABAC_bit(&tctx->cabac_decoder, - &model[4]); - } - else { - value = 2; - } - } - - logtrace(LogSlice,"> inter_pred_idc = %d (%s)\n",value, - value==0 ? "L0" : (value==1 ? "L1" : "BI")); - - logtrace(LogSymbols,"$1 decode_inter_pred_idx=%d\n",value+1); - - return (enum InterPredIdc) (value+1); -} - - -static int decode_explicit_rdpcm_flag(thread_context* tctx,int cIdx) -{ - context_model* model = &tctx->ctx_model[CONTEXT_MODEL_RDPCM_FLAG]; - int value = decode_CABAC_bit(&tctx->cabac_decoder, &model[cIdx ? 1 : 0]); - return value; -} - - -static int decode_explicit_rdpcm_dir(thread_context* tctx,int cIdx) -{ - context_model* model = &tctx->ctx_model[CONTEXT_MODEL_RDPCM_DIR]; - int value = decode_CABAC_bit(&tctx->cabac_decoder, &model[cIdx ? 1 : 0]); - return value; -} - - - -/* Take CtbAddrInTS and compute - -> CtbAddrInRS, CtbX, CtbY - */ -bool setCtbAddrFromTS(thread_context* tctx) -{ - const seq_parameter_set& sps = tctx->img->get_sps(); - - if (tctx->CtbAddrInTS < sps.PicSizeInCtbsY) { - tctx->CtbAddrInRS = tctx->img->get_pps().CtbAddrTStoRS[tctx->CtbAddrInTS]; - - tctx->CtbX = tctx->CtbAddrInRS % sps.PicWidthInCtbsY; - tctx->CtbY = tctx->CtbAddrInRS / sps.PicWidthInCtbsY; - return false; - } - else { - tctx->CtbAddrInRS = sps.PicSizeInCtbsY; - - tctx->CtbX = tctx->CtbAddrInRS % sps.PicWidthInCtbsY; - tctx->CtbY = tctx->CtbAddrInRS / sps.PicWidthInCtbsY; - return true; - } -} - -// returns true when we reached the end of the image (ctbAddr==picSizeInCtbsY) -bool advanceCtbAddr(thread_context* tctx) -{ - tctx->CtbAddrInTS++; - - return setCtbAddrFromTS(tctx); -} - - -void read_sao(thread_context* tctx, int xCtb,int yCtb, - int CtbAddrInSliceSeg) -{ - slice_segment_header* shdr = tctx->shdr; - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - const pic_parameter_set& pps = img->get_pps(); - - logtrace(LogSlice,"# read_sao(%d,%d)\n",xCtb,yCtb); - - sao_info saoinfo; - memset(&saoinfo,0,sizeof(sao_info)); - logtrace(LogSlice,"sizeof saoinfo: %d\n",sizeof(sao_info)); - - - char sao_merge_left_flag = 0; - char sao_merge_up_flag = 0; - - if (xCtb>0) { - //char leftCtbInSliceSeg = (CtbAddrInSliceSeg>0); - char leftCtbInSliceSeg = (tctx->CtbAddrInRS > shdr->SliceAddrRS); - char leftCtbInTile = (pps.TileIdRS[xCtb + yCtb * sps.PicWidthInCtbsY] == - pps.TileIdRS[xCtb-1 + yCtb * sps.PicWidthInCtbsY]); - - if (leftCtbInSliceSeg && leftCtbInTile) { - sao_merge_left_flag = decode_sao_merge_flag(tctx); - logtrace(LogSlice,"sao_merge_left_flag: %d\n",sao_merge_left_flag); - } - } - - if (yCtb>0 && sao_merge_left_flag==0) { - logtrace(LogSlice,"CtbAddrInRS:%d PicWidthInCtbsY:%d slice_segment_address:%d\n", - tctx->CtbAddrInRS, - sps.PicWidthInCtbsY, - shdr->slice_segment_address); - char upCtbInSliceSeg = (tctx->CtbAddrInRS - sps.PicWidthInCtbsY) >= shdr->SliceAddrRS; - char upCtbInTile = (pps.TileIdRS[xCtb + yCtb * sps.PicWidthInCtbsY] == - pps.TileIdRS[xCtb + (yCtb-1) * sps.PicWidthInCtbsY]); - - if (upCtbInSliceSeg && upCtbInTile) { - sao_merge_up_flag = decode_sao_merge_flag(tctx); - logtrace(LogSlice,"sao_merge_up_flag: %d\n",sao_merge_up_flag); - } - } - - if (!sao_merge_up_flag && !sao_merge_left_flag) { - int nChroma = 3; - if (sps.ChromaArrayType == CHROMA_MONO) nChroma=1; - - for (int cIdx=0; cIdxslice_sao_luma_flag && cIdx==0) || - (shdr->slice_sao_chroma_flag && cIdx>0)) { - - uint8_t SaoTypeIdx = 0; - - if (cIdx==0) { - char sao_type_idx_luma = decode_sao_type_idx(tctx); - logtrace(LogSlice,"sao_type_idx_luma: %d\n", sao_type_idx_luma); - saoinfo.SaoTypeIdx = SaoTypeIdx = sao_type_idx_luma; - } - else if (cIdx==1) { - char sao_type_idx_chroma = decode_sao_type_idx(tctx); - logtrace(LogSlice,"sao_type_idx_chroma: %d\n", sao_type_idx_chroma); - SaoTypeIdx = sao_type_idx_chroma; - saoinfo.SaoTypeIdx |= SaoTypeIdx<<(2*1); - saoinfo.SaoTypeIdx |= SaoTypeIdx<<(2*2); // set for both chroma components - } - else { - // SaoTypeIdx = 0 - - SaoTypeIdx = (saoinfo.SaoTypeIdx >> (2*cIdx)) & 0x3; - } - - if (SaoTypeIdx != 0) { - for (int i=0;i<4;i++) { - saoinfo.saoOffsetVal[cIdx][i] = decode_sao_offset_abs(tctx, img->get_bit_depth(cIdx)); - logtrace(LogSlice,"saoOffsetVal[%d][%d] = %d\n",cIdx,i, saoinfo.saoOffsetVal[cIdx][i]); - } - - int sign[4]; - if (SaoTypeIdx==1) { - for (int i=0;i<4;i++) { - if (saoinfo.saoOffsetVal[cIdx][i] != 0) { - sign[i] = decode_sao_offset_sign(tctx) ? -1 : 1; - } - else { - sign[i] = 0; // not really required, but compiler warns about uninitialized values - } - } - - saoinfo.sao_band_position[cIdx] = decode_sao_band_position(tctx); - } - else { - uint8_t SaoEoClass = 0; - - sign[0] = sign[1] = 1; - sign[2] = sign[3] = -1; - - if (cIdx==0) { - saoinfo.SaoEoClass = SaoEoClass = decode_sao_class(tctx); - } - else if (cIdx==1) { - SaoEoClass = decode_sao_class(tctx); - saoinfo.SaoEoClass |= SaoEoClass << (2*1); - saoinfo.SaoEoClass |= SaoEoClass << (2*2); - } - - logtrace(LogSlice,"SaoEoClass[%d] = %d\n",cIdx,SaoEoClass); - } - - int log2OffsetScale; - - if (cIdx==0) { - log2OffsetScale = pps.range_extension.log2_sao_offset_scale_luma; - } - else { - log2OffsetScale = pps.range_extension.log2_sao_offset_scale_chroma; - } - - for (int i=0;i<4;i++) { - saoinfo.saoOffsetVal[cIdx][i] = sign[i]*(saoinfo.saoOffsetVal[cIdx][i] << log2OffsetScale); - } - } - } - } - - img->set_sao_info(xCtb,yCtb, &saoinfo); - } - - - if (sao_merge_left_flag) { - img->set_sao_info(xCtb,yCtb, img->get_sao_info(xCtb-1,yCtb)); - } - - if (sao_merge_up_flag) { - img->set_sao_info(xCtb,yCtb, img->get_sao_info(xCtb,yCtb-1)); - } -} - - -void read_coding_tree_unit(thread_context* tctx) -{ - slice_segment_header* shdr = tctx->shdr; - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - - int xCtb = (tctx->CtbAddrInRS % sps.PicWidthInCtbsY); - int yCtb = (tctx->CtbAddrInRS / sps.PicWidthInCtbsY); - int xCtbPixels = xCtb << sps.Log2CtbSizeY; - int yCtbPixels = yCtb << sps.Log2CtbSizeY; - - logtrace(LogSlice,"----- decode CTB %d;%d (%d;%d) POC=%d, SliceAddrRS=%d\n", - xCtbPixels,yCtbPixels, xCtb,yCtb, - tctx->img->PicOrderCntVal, tctx->shdr->SliceAddrRS); - - img->set_SliceAddrRS(xCtb, yCtb, tctx->shdr->SliceAddrRS); - - img->set_SliceHeaderIndex(xCtbPixels,yCtbPixels, shdr->slice_index); - - int CtbAddrInSliceSeg = tctx->CtbAddrInRS - shdr->slice_segment_address; - - if (shdr->slice_sao_luma_flag || shdr->slice_sao_chroma_flag) - { - read_sao(tctx, xCtb,yCtb, CtbAddrInSliceSeg); - } - - read_coding_quadtree(tctx, xCtbPixels, yCtbPixels, sps.Log2CtbSizeY, 0); -} - - -LIBDE265_INLINE static int luma_pos_to_ctbAddrRS(const seq_parameter_set* sps, int x,int y) -{ - int ctbX = x >> sps->Log2CtbSizeY; - int ctbY = y >> sps->Log2CtbSizeY; - - return ctbY * sps->PicWidthInCtbsY + ctbX; -} - - -int check_CTB_available(const de265_image* img, - int xC,int yC, int xN,int yN) -{ - // check whether neighbor is outside of frame - - if (xN < 0 || yN < 0) { return 0; } - if (xN >= img->get_sps().pic_width_in_luma_samples) { return 0; } - if (yN >= img->get_sps().pic_height_in_luma_samples) { return 0; } - - - int current_ctbAddrRS = luma_pos_to_ctbAddrRS(&img->get_sps(), xC,yC); - int neighbor_ctbAddrRS = luma_pos_to_ctbAddrRS(&img->get_sps(), xN,yN); - - // TODO: check if this is correct (6.4.1) - - if (img->get_SliceAddrRS_atCtbRS(current_ctbAddrRS) != - img->get_SliceAddrRS_atCtbRS(neighbor_ctbAddrRS)) { - return 0; - } - - // check if both CTBs are in the same tile. - - if (img->get_pps().TileIdRS[current_ctbAddrRS] != - img->get_pps().TileIdRS[neighbor_ctbAddrRS]) { - return 0; - } - - return 1; -} - - -int residual_coding(thread_context* tctx, - int x0, int y0, // position of TU in frame - int log2TrafoSize, - int cIdx) -{ - logtrace(LogSlice,"- residual_coding x0:%d y0:%d log2TrafoSize:%d cIdx:%d\n",x0,y0,log2TrafoSize,cIdx); - - //slice_segment_header* shdr = tctx->shdr; - - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - const pic_parameter_set& pps = img->get_pps(); - - enum PredMode PredMode = img->get_pred_mode(x0,y0); - - if (cIdx==0) { - img->set_nonzero_coefficient(x0,y0,log2TrafoSize); - } - - - if (pps.transform_skip_enabled_flag && - !tctx->cu_transquant_bypass_flag && - (log2TrafoSize <= pps.Log2MaxTransformSkipSize)) - { - tctx->transform_skip_flag[cIdx] = decode_transform_skip_flag(tctx,cIdx); - } - else - { - tctx->transform_skip_flag[cIdx] = 0; - } - - - tctx->explicit_rdpcm_flag = false; - - if (PredMode == MODE_INTER && sps.range_extension.explicit_rdpcm_enabled_flag && - ( tctx->transform_skip_flag[cIdx] || tctx->cu_transquant_bypass_flag)) - { - tctx->explicit_rdpcm_flag = decode_explicit_rdpcm_flag(tctx,cIdx); - if (tctx->explicit_rdpcm_flag) { - tctx->explicit_rdpcm_dir = decode_explicit_rdpcm_dir(tctx,cIdx); - } - - //printf("EXPLICIT RDPCM %d;%d\n",x0,y0); - } - else - { - tctx->explicit_rdpcm_flag = false; - } - - - - // sbType for persistent_rice_adaptation_enabled_flag - - int sbType = (cIdx==0) ? 2 : 0; - if (tctx->transform_skip_flag[cIdx] || tctx->cu_transquant_bypass_flag) { - sbType++; - } - - - // --- decode position of last coded coefficient --- - - int last_significant_coeff_x_prefix = - decode_last_significant_coeff_prefix(tctx,log2TrafoSize,cIdx, - &tctx->ctx_model[CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_X_PREFIX]); - - int last_significant_coeff_y_prefix = - decode_last_significant_coeff_prefix(tctx,log2TrafoSize,cIdx, - &tctx->ctx_model[CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_Y_PREFIX]); - - - // TODO: we can combine both FL-bypass calls into one, but the gain may be limited... - - int LastSignificantCoeffX; - if (last_significant_coeff_x_prefix > 3) { - int nBits = (last_significant_coeff_x_prefix>>1)-1; - int last_significant_coeff_x_suffix = decode_CABAC_FL_bypass(&tctx->cabac_decoder,nBits); - - LastSignificantCoeffX = - ((2+(last_significant_coeff_x_prefix & 1)) << nBits) + last_significant_coeff_x_suffix; - } - else { - LastSignificantCoeffX = last_significant_coeff_x_prefix; - } - - int LastSignificantCoeffY; - if (last_significant_coeff_y_prefix > 3) { - int nBits = (last_significant_coeff_y_prefix>>1)-1; - int last_significant_coeff_y_suffix = decode_CABAC_FL_bypass(&tctx->cabac_decoder,nBits); - - LastSignificantCoeffY = - ((2+(last_significant_coeff_y_prefix & 1)) << nBits) + last_significant_coeff_y_suffix; - } - else { - LastSignificantCoeffY = last_significant_coeff_y_prefix; - } - - - - // --- determine scanIdx --- - - int scanIdx; - - if (PredMode == MODE_INTRA) { - if (cIdx==0) { - scanIdx = get_intra_scan_idx(log2TrafoSize, img->get_IntraPredMode(x0,y0), cIdx, &sps); - //printf("luma scan idx=%d <- intra mode=%d\n",scanIdx, img->get_IntraPredMode(x0,y0)); - } - else { - scanIdx = get_intra_scan_idx(log2TrafoSize, img->get_IntraPredModeC(x0,y0), cIdx, &sps); - //printf("chroma scan idx=%d <- intra mode=%d chroma:%d trsize:%d\n",scanIdx, - // img->get_IntraPredModeC(x0,y0), sps->chroma_format_idc, 1<nCoeff[cIdx] = 0; - - - // i - subblock index - // n - coefficient index in subblock - - for (int i=lastSubBlock;i>=0;i--) { - position S = ScanOrderSub[i]; - int inferSbDcSigCoeffFlag=0; - - logtrace(LogSlice,"sub block scan idx: %d\n",i); - - - // --- check whether this sub-block is coded --- - - int sub_block_is_coded = 0; - - if ((i0)) { - sub_block_is_coded = decode_coded_sub_block_flag(tctx, cIdx, - coded_sub_block_neighbors[S.x+S.y*sbWidth]); - inferSbDcSigCoeffFlag=1; - } - else if (i==0 || i==lastSubBlock) { - // first (DC) and last sub-block are always coded - // - the first will most probably contain coefficients - // - the last obviously contains the last coded coefficient - - sub_block_is_coded = 1; - } - - if (sub_block_is_coded) { - if (S.x > 0) coded_sub_block_neighbors[S.x-1 + S.y *sbWidth] |= 1; - if (S.y > 0) coded_sub_block_neighbors[S.x + (S.y-1)*sbWidth] |= 2; - } - - - // ----- find significant coefficients in this sub-block ----- - - int16_t coeff_value[16]; - int8_t coeff_scan_pos[16]; - int8_t coeff_sign[16]; - int8_t coeff_has_max_base_level[16]; - int nCoefficients=0; - - - if (sub_block_is_coded) { - int x0 = S.x<<2; - int y0 = S.y<<2; - - int log2w = log2TrafoSize-2; - int prevCsbf = coded_sub_block_neighbors[S.x+S.y*sbWidth]; - uint8_t* ctxIdxMap = ctxIdxLookup[log2w][!!cIdx][!!scanIdx][prevCsbf]; - - logdebug(LogSlice,"log2w:%d cIdx:%d scanIdx:%d prevCsbf:%d\n", - log2w,cIdx,scanIdx,prevCsbf); - - - // set the last coded coefficient in the last subblock - - int last_coeff = (i==lastSubBlock) ? lastScanPos-1 : 15; - - if (i==lastSubBlock) { - coeff_value[nCoefficients] = 1; - coeff_has_max_base_level[nCoefficients] = 1; - coeff_scan_pos[nCoefficients] = lastScanPos; - nCoefficients++; - } - - - // --- decode all coefficients' significant_coeff flags except for the DC coefficient --- - - for (int n= last_coeff ; n>0 ; n--) { - int subX = ScanOrderPos[n].x; - int subY = ScanOrderPos[n].y; - xC = x0 + subX; - yC = y0 + subY; - - - // for all AC coefficients in sub-block, a significant_coeff flag is coded - - int ctxInc; - if (sps.range_extension.transform_skip_context_enabled_flag && - (tctx->cu_transquant_bypass_flag || tctx->transform_skip_flag[cIdx])) { - ctxInc = ( cIdx == 0 ) ? 42 : (16+27); - } - else { - ctxInc = ctxIdxMap[xC+(yC<=0) // last coded coefficient (always set to 1) is not the DC coefficient - { - if (inferSbDcSigCoeffFlag==0) { - // if we cannot infert the DC coefficient, it is coded - - int ctxInc; - if (sps.range_extension.transform_skip_context_enabled_flag && - (tctx->cu_transquant_bypass_flag || tctx->transform_skip_flag[cIdx])) { - ctxInc = ( cIdx == 0 ) ? 42 : (16+27); - } - else { - ctxInc = ctxIdxMap[x0+(y0<0) { ctxSet=0; } - else { ctxSet=2; } - - if (c1==0) { ctxSet++; } - c1=1; - - - // --- decode greater-1 flags --- - - int newLastGreater1ScanPos=-1; - - int lastGreater1Coefficient = libde265_min(8,nCoefficients); - for (int c=0;c0) { - c1++; - } - } - } - - firstSubblock = false; - lastSubblock_greater1Ctx = lastInvocation_greater1Ctx; - - - // --- decode greater-2 flag --- - - if (newLastGreater1ScanPos != -1) { - int flag = decode_coeff_abs_level_greater2(tctx,cIdx, lastInvocation_ctxSet); - coeff_value[newLastGreater1ScanPos] += flag; - coeff_has_max_base_level[newLastGreater1ScanPos] = flag; - } - - - // --- decode coefficient signs --- - - int signHidden; - - - IntraPredMode predModeIntra; - if (cIdx==0) predModeIntra = img->get_IntraPredMode(x0,y0); - else predModeIntra = img->get_IntraPredModeC(x0,y0); - - - if (tctx->cu_transquant_bypass_flag || - (PredMode == MODE_INTRA && - sps.range_extension.implicit_rdpcm_enabled_flag && - tctx->transform_skip_flag[cIdx] && - ( predModeIntra == 10 || predModeIntra == 26 )) || - tctx->explicit_rdpcm_flag) - { - signHidden = 0; - } - else - { - signHidden = (coeff_scan_pos[0]-coeff_scan_pos[nCoefficients-1] > 3); - } - - - for (int n=0;ncabac_decoder); - logtrace(LogSlice,"sign[%d] = %d\n", n, coeff_sign[n]); - } - - // n==nCoefficients-1 - if (!pps.sign_data_hiding_flag || !signHidden) { - coeff_sign[nCoefficients-1] = decode_CABAC_bypass(&tctx->cabac_decoder); - logtrace(LogSlice,"sign[%d] = %d\n", nCoefficients-1, coeff_sign[nCoefficients-1]); - } - else { - coeff_sign[nCoefficients-1] = 0; - } - - - // --- decode coefficient value --- - - int sumAbsLevel=0; - int uiGoRiceParam; - - if (sps.range_extension.persistent_rice_adaptation_enabled_flag==0) { - uiGoRiceParam = 0; - } - else { - uiGoRiceParam = tctx->StatCoeff[sbType]/4; - } - - // printf("initial uiGoRiceParam=%d\n",uiGoRiceParam); - bool firstCoeffWithAbsLevelRemaining = true; - - for (int n=0;n 3*(1<4) uiGoRiceParam=4; - } - } - else { - if (baseLevel + coeff_abs_level_remaining > 3*(1<= (3 << (tctx->StatCoeff[sbType]/4 ))) { - tctx->StatCoeff[sbType]++; - } - else if (2*coeff_abs_level_remaining < (1 << (tctx->StatCoeff[sbType]/4 )) && - tctx->StatCoeff[sbType] > 0) { - tctx->StatCoeff[sbType]--; - } - } - - firstCoeffWithAbsLevelRemaining=false; - } - else { - coeff_abs_level_remaining = 0; - } - - logtrace(LogSlice, "coeff_abs_level_remaining=%d\n",coeff_abs_level_remaining); - - - int16_t currCoeff = baseLevel + coeff_abs_level_remaining; - if (coeff_sign[n]) { - currCoeff = -currCoeff; - } - - if (pps.sign_data_hiding_flag && signHidden) { - sumAbsLevel += baseLevel + coeff_abs_level_remaining; - - if (n==nCoefficients-1 && (sumAbsLevel & 1)) { - currCoeff = -currCoeff; - } - } - - logtrace(LogSlice, "quantized coefficient=%d\n",currCoeff); - -#ifdef DE265_LOG_TRACE - //TransCoeffLevel[yC*CoeffStride + xC] = currCoeff; -#endif - - // put coefficient in list - int p = coeff_scan_pos[n]; - xC = (S.x<<2) + ScanOrderPos[p].x; - yC = (S.y<<2) + ScanOrderPos[p].y; - - tctx->coeffList[cIdx][ tctx->nCoeff[cIdx] ] = currCoeff; - tctx->coeffPos [cIdx][ tctx->nCoeff[cIdx] ] = xC + yC*CoeffStride; - tctx->nCoeff[cIdx]++; - - //printf("%d ",currCoeff); - } // iterate through coefficients in sub-block - - //printf(" (%d;%d)\n",x0,y0); - - } // if nonZero - } // next sub-block - - return DE265_OK; -} - - -static void decode_TU(thread_context* tctx, - int x0,int y0, - int xCUBase,int yCUBase, - int nT, int cIdx, enum PredMode cuPredMode, bool cbf) -{ - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - - int residualDpcm = 0; - - if (cuPredMode == MODE_INTRA) // if intra mode - { - enum IntraPredMode intraPredMode; - - if (cIdx==0) { - intraPredMode = img->get_IntraPredMode(x0,y0); - } - else { - const int SubWidthC = sps.SubWidthC; - const int SubHeightC = sps.SubHeightC; - - intraPredMode = img->get_IntraPredModeC(x0*SubWidthC,y0*SubHeightC); - } - - if (intraPredMode<0 || intraPredMode>=35) { - // TODO: ERROR - intraPredMode = INTRA_DC; - } - - decode_intra_prediction(img, x0,y0, intraPredMode, nT, cIdx); - - - residualDpcm = sps.range_extension.implicit_rdpcm_enabled_flag && - (tctx->cu_transquant_bypass_flag || tctx->transform_skip_flag[cIdx]) && - (intraPredMode == 10 || intraPredMode == 26); - - if (residualDpcm && intraPredMode == 26) - residualDpcm = 2; - } - else // INTER - { - if (tctx->explicit_rdpcm_flag) { - residualDpcm = (tctx->explicit_rdpcm_dir ? 2 : 1); - } - } - - if (cbf) { - scale_coefficients(tctx, x0,y0, xCUBase,yCUBase, nT, cIdx, - tctx->transform_skip_flag[cIdx], cuPredMode==MODE_INTRA, residualDpcm); - } - /* - else if (!cbf && cIdx==0) { - memset(tctx->residual_luma,0,32*32*sizeof(int32_t)); - } - */ - else if (!cbf && cIdx!=0 && tctx->ResScaleVal) { - // --- cross-component-prediction when CBF==0 --- - - tctx->nCoeff[cIdx] = 0; - residualDpcm=0; - - scale_coefficients(tctx, x0,y0, xCUBase,yCUBase, nT, cIdx, - tctx->transform_skip_flag[cIdx], cuPredMode==MODE_INTRA, residualDpcm); - } -} - - -static int decode_log2_res_scale_abs_plus1(thread_context* tctx, int cIdxMinus1) -{ - //const int context = (cIdx==0) ? 0 : 1; - - logtrace(LogSlice,"# log2_res_scale_abs_plus1 (c=%d)\n",cIdxMinus1); - - int value = 0; - int cMax = 4; - for (int binIdx=0;binIdxcabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_LOG2_RES_SCALE_ABS_PLUS1+ctxIdxInc]); - if (!bit) break; - value++; - } - - logtrace(LogSymbols,"$1 log2_res_scale_abs_plus1=%d\n",value); - - return value; -} - - -static int decode_res_scale_sign_flag(thread_context* tctx, int cIdxMinus1) -{ - //const int context = (cIdx==0) ? 0 : 1; - - logtrace(LogSlice,"# res_scale_sign_flag (c=%d)\n",cIdxMinus1); - - int bit = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_RES_SCALE_SIGN_FLAG+cIdxMinus1]); - - logtrace(LogSymbols,"$1 res_scale_sign_flag=%d\n",bit); - - return bit; -} - - -static void read_cross_comp_pred(thread_context* tctx, int cIdxMinus1) -{ - int log2_res_scale_abs_plus1 = decode_log2_res_scale_abs_plus1(tctx,cIdxMinus1); - int ResScaleVal; - - if (log2_res_scale_abs_plus1 != 0) { - int res_scale_sign_flag = decode_res_scale_sign_flag(tctx,cIdxMinus1); - - ResScaleVal = 1 << (log2_res_scale_abs_plus1 - 1); - ResScaleVal *= 1 - 2 * res_scale_sign_flag; - } - else { - ResScaleVal = 0; - } - - tctx->ResScaleVal = ResScaleVal; -} - - -int read_transform_unit(thread_context* tctx, - int x0, int y0, // position of TU in frame - int xBase, int yBase, // position of parent TU in frame - int xCUBase,int yCUBase, // position of CU in frame - int log2TrafoSize, - int trafoDepth, - int blkIdx, - int cbf_luma, int cbf_cb, int cbf_cr) -{ - logtrace(LogSlice,"- read_transform_unit x0:%d y0:%d xBase:%d yBase:%d nT:%d cbf:%d:%d:%d\n", - x0,y0,xBase,yBase, 1<img->get_sps(); - - const int ChromaArrayType = sps.ChromaArrayType; - - int log2TrafoSizeC = (ChromaArrayType==CHROMA_444 ? log2TrafoSize : log2TrafoSize-1); - log2TrafoSizeC = libde265_max(2, log2TrafoSizeC); - - const int cbfLuma = cbf_luma; - const int cbfChroma = cbf_cb | cbf_cr; - - tctx->transform_skip_flag[0]=0; - tctx->transform_skip_flag[1]=0; - tctx->transform_skip_flag[2]=0; - - tctx->explicit_rdpcm_flag = false; - - - enum PredMode cuPredMode = tctx->img->get_pred_mode(x0,y0); - - if (cbfLuma || cbfChroma) - { - bool doDecodeQuantParameters = false; - - if (tctx->img->get_pps().cu_qp_delta_enabled_flag && - !tctx->IsCuQpDeltaCoded) { - - int cu_qp_delta_abs = decode_cu_qp_delta_abs(tctx); - int cu_qp_delta_sign=0; - if (cu_qp_delta_abs) { - cu_qp_delta_sign = decode_CABAC_bypass(&tctx->cabac_decoder); - } - - tctx->IsCuQpDeltaCoded = 1; - tctx->CuQpDelta = cu_qp_delta_abs*(1-2*cu_qp_delta_sign); - - //printf("read cu_qp_delta (%d;%d) = %d\n",x0,y0,tctx->CuQpDelta); - - logtrace(LogSlice,"cu_qp_delta_abs = %d\n",cu_qp_delta_abs); - logtrace(LogSlice,"cu_qp_delta_sign = %d\n",cu_qp_delta_sign); - logtrace(LogSlice,"CuQpDelta = %d\n",tctx->CuQpDelta); - - doDecodeQuantParameters = true; - //decode_quantization_parameters(tctx, x0,y0, xCUBase, yCUBase); - } - - if (tctx->shdr->cu_chroma_qp_offset_enabled_flag && cbfChroma && - !tctx->cu_transquant_bypass_flag && !tctx->IsCuChromaQpOffsetCoded ) { - logtrace(LogSlice,"# cu_chroma_qp_offset_flag\n"); - - int cu_chroma_qp_offset_flag = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_FLAG]); - - - const pic_parameter_set& pps = tctx->img->get_pps(); - - int cu_chroma_qp_offset_idx = 0; - if (cu_chroma_qp_offset_flag && pps.range_extension.chroma_qp_offset_list_len > 1) { - cu_chroma_qp_offset_idx = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_IDX]); - } - - tctx->IsCuChromaQpOffsetCoded = 1; - - if (cu_chroma_qp_offset_flag) { - tctx->CuQpOffsetCb = pps.range_extension.cb_qp_offset_list[ cu_chroma_qp_offset_idx ]; - tctx->CuQpOffsetCr = pps.range_extension.cr_qp_offset_list[ cu_chroma_qp_offset_idx ]; - } - else { - tctx->CuQpOffsetCb = 0; - tctx->CuQpOffsetCr = 0; - } - - doDecodeQuantParameters = true; - //decode_quantization_parameters(tctx, x0,y0, xCUBase, yCUBase); - } - - - if (doDecodeQuantParameters) { - decode_quantization_parameters(tctx, x0,y0, xCUBase, yCUBase); - } - } - - // position of TU in local CU - int xL = x0 - xCUBase; - int yL = y0 - yCUBase; - int nT = 1<ResScaleVal = 0; - - int err; - if (cbf_luma) { - if ((err=residual_coding(tctx,x0,y0, log2TrafoSize,0)) != DE265_OK) return err; - } - - decode_TU(tctx, x0,y0, xCUBase,yCUBase, nT, 0, cuPredMode, cbf_luma); - - - // --- chroma --- - - const int yOffset422 = 1<2 || ChromaArrayType == CHROMA_444) { - // TODO: cross-component prediction - - const bool do_cross_component_prediction = - (tctx->img->get_pps().range_extension.cross_component_prediction_enabled_flag && - cbf_luma && - (cuPredMode == MODE_INTER || tctx->img->is_IntraPredModeC_Mode4(x0,y0))); - - if (do_cross_component_prediction) { - read_cross_comp_pred(tctx, 0); - } - else { - tctx->ResScaleVal = 0; - } - - { - if (cbf_cb & 1) { - if ((err=residual_coding(tctx,x0,y0,log2TrafoSizeC,1)) != DE265_OK) return err; - } - - if (sps.ChromaArrayType != CHROMA_MONO) { - decode_TU(tctx, - x0/SubWidthC,y0/SubHeightC, - xCUBase/SubWidthC,yCUBase/SubHeightC, nTC, 1, cuPredMode, cbf_cb & 1); - } - } - - // 4:2:2 - if (ChromaArrayType == CHROMA_422) { - const int yOffset = 1<ResScaleVal = 0; - } - - { - if (cbf_cr & 1) { - if ((err=residual_coding(tctx,x0,y0,log2TrafoSizeC,2)) != DE265_OK) return err; - } - - if (sps.ChromaArrayType != CHROMA_MONO) { - decode_TU(tctx, - x0/SubWidthC,y0/SubHeightC, - xCUBase/SubWidthC,yCUBase/SubHeightC, - nTC, 2, cuPredMode, cbf_cr & 1); - } - } - - // 4:2:2 - if (ChromaArrayType == CHROMA_422) { - const int yOffset = 1<get_width(0); - int h = img->get_height(0); - - for (int y=0;yget_log2CbSize(x,y)); - } - printf("\n"); - } -} - - -void read_transform_tree(thread_context* tctx, - int x0, int y0, // position of TU in frame - int xBase, int yBase, // position of parent TU in frame - int xCUBase, int yCUBase, // position of CU in frame - int log2TrafoSize, - int trafoDepth, - int blkIdx, - int MaxTrafoDepth, - int IntraSplitFlag, - enum PredMode cuPredMode, - uint8_t parent_cbf_cb,uint8_t parent_cbf_cr) -{ - logtrace(LogSlice,"- read_transform_tree (interleaved) x0:%d y0:%d xBase:%d yBase:%d " - "log2TrafoSize:%d trafoDepth:%d MaxTrafoDepth:%d parent-cbf-cb:%d parent-cbf-cr:%d\n", - x0,y0,xBase,yBase,log2TrafoSize,trafoDepth,MaxTrafoDepth,parent_cbf_cb,parent_cbf_cr); - - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - - int split_transform_flag; - - enum PredMode PredMode = img->get_pred_mode(x0,y0); - assert(PredMode == cuPredMode); - - /* If TrafoSize is larger than maximum size -> split automatically - If TrafoSize is at minimum size -> do not split - If maximum transformation depth is reached -> do not split - If intra-prediction is NxN mode -> split automatically (only at level 0) - Otherwise -> read split flag - */ - if (log2TrafoSize <= sps.Log2MaxTrafoSize && - log2TrafoSize > sps.Log2MinTrafoSize && - trafoDepth < MaxTrafoDepth && - !(IntraSplitFlag && trafoDepth==0)) - { - split_transform_flag = decode_split_transform_flag(tctx, log2TrafoSize); - } - else - { - enum PartMode PartMode = img->get_PartMode(x0,y0); - - int interSplitFlag= (sps.max_transform_hierarchy_depth_inter==0 && - trafoDepth == 0 && - PredMode == MODE_INTER && - PartMode != PART_2Nx2N); - - split_transform_flag = (log2TrafoSize > sps.Log2MaxTrafoSize || - (IntraSplitFlag==1 && trafoDepth==0) || - interSplitFlag==1) ? 1:0; - } - - if (split_transform_flag) { - logtrace(LogSlice,"set_split_transform_flag(%d,%d, %d)\n",x0,y0,trafoDepth); - img->set_split_transform_flag(x0,y0,trafoDepth); - } - - int cbf_cb=-1; - int cbf_cr=-1; - - // CBF_CB/CR flags are encoded like this: - // 4:2:0 and 4:4:4 modes: binary flag in bit 0 - // 4:2:2 mode: bit 0: top block, bit 1: bottom block - - if ((log2TrafoSize>2 && sps.ChromaArrayType != CHROMA_MONO) || - sps.ChromaArrayType == CHROMA_444) { - // we do not have to test for trafoDepth==0, because parent_cbf_cb is 1 at depth 0 - if (/*trafoDepth==0 ||*/ parent_cbf_cb) { - cbf_cb = decode_cbf_chroma(tctx,trafoDepth); - - if (sps.ChromaArrayType == CHROMA_422 && (!split_transform_flag || log2TrafoSize==3)) { - cbf_cb |= (decode_cbf_chroma(tctx,trafoDepth) << 1); - } - } - - // we do not have to test for trafoDepth==0, because parent_cbf_cb is 1 at depth 0 - if (/*trafoDepth==0 ||*/ parent_cbf_cr) { - cbf_cr = decode_cbf_chroma(tctx,trafoDepth); - - if (sps.ChromaArrayType == CHROMA_422 && (!split_transform_flag || log2TrafoSize==3)) { - cbf_cr |= (decode_cbf_chroma(tctx,trafoDepth) << 1); - } - } - } - - //printf("CBF: cb:%d cr:%d\n",cbf_cb,cbf_cr); - - // cbf_cr/cbf_cb not present in bitstream -> induce values - - if (cbf_cb<0) { - assert(!(trafoDepth==0 && log2TrafoSize==2)); - - /* The standard specifies to check trafoDepth>0 AND log2TrafoSize==2. - However, I think that trafoDepth>0 is redundant as a CB is always - at least 8x8 and hence trafoDepth>0. - */ - - if (trafoDepth>0 && log2TrafoSize==2) { - cbf_cb = parent_cbf_cb; - } else { - cbf_cb=0; - } - } - - if (cbf_cr<0) { - if (trafoDepth>0 && log2TrafoSize==2) { - cbf_cr = parent_cbf_cr; - } else { - cbf_cr=0; - } - } - - if (split_transform_flag) { - int x1 = x0 + (1<<(log2TrafoSize-1)); - int y1 = y0 + (1<<(log2TrafoSize-1)); - - logtrace(LogSlice,"transform split.\n"); - - read_transform_tree(tctx, x0,y0, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 0, - MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); - read_transform_tree(tctx, x1,y0, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 1, - MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); - read_transform_tree(tctx, x0,y1, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 2, - MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); - read_transform_tree(tctx, x1,y1, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 3, - MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); - } - else { - int cbf_luma; - - if (PredMode==MODE_INTRA || trafoDepth!=0 || cbf_cb || cbf_cr) { - cbf_luma = decode_cbf_luma(tctx,trafoDepth); - } - else { - /* There cannot be INTER blocks with no residual data. - That case is already handled with rqt_root_cbf. - */ - - cbf_luma = 1; - } - - logtrace(LogSlice,"call read_transform_unit %d/%d\n",x0,y0); - - read_transform_unit(tctx, x0,y0,xBase,yBase, xCUBase,yCUBase, log2TrafoSize,trafoDepth, blkIdx, - cbf_luma, cbf_cb, cbf_cr); - } -} - - -const char* part_mode_name(enum PartMode pm) -{ - switch (pm) { - case PART_2Nx2N: return "2Nx2N"; - case PART_2NxN: return "2NxN"; - case PART_Nx2N: return "Nx2N"; - case PART_NxN: return "NxN"; - case PART_2NxnU: return "2NxnU"; - case PART_2NxnD: return "2NxnD"; - case PART_nLx2N: return "nLx2N"; - case PART_nRx2N: return "nRx2N"; - } - - return "undefined part mode"; -} - - -void read_mvd_coding(thread_context* tctx, - int x0,int y0, int refList) -{ - int abs_mvd_greater0_flag[2]; - abs_mvd_greater0_flag[0] = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+0]); - abs_mvd_greater0_flag[1] = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+0]); - - int abs_mvd_greater1_flag[2]; - if (abs_mvd_greater0_flag[0]) { - abs_mvd_greater1_flag[0] = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+1]); - } - else { - abs_mvd_greater1_flag[0]=0; - } - - if (abs_mvd_greater0_flag[1]) { - abs_mvd_greater1_flag[1] = decode_CABAC_bit(&tctx->cabac_decoder, - &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+1]); - } - else { - abs_mvd_greater1_flag[1]=0; - } - - - int abs_mvd_minus2[2]; - int mvd_sign_flag[2]; - int value[2]; - - for (int c=0;c<2;c++) { - if (abs_mvd_greater0_flag[c]) { - if (abs_mvd_greater1_flag[c]) { - abs_mvd_minus2[c] = decode_CABAC_EGk_bypass(&tctx->cabac_decoder, 1); - } - else { - abs_mvd_minus2[c] = abs_mvd_greater1_flag[c] -1; - } - - mvd_sign_flag[c] = decode_CABAC_bypass(&tctx->cabac_decoder); - - value[c] = abs_mvd_minus2[c]+2; - if (mvd_sign_flag[c]) { value[c] = -value[c]; } - } - else { - value[c] = 0; - } - } - - //set_mvd(tctx->decctx, x0,y0, refList, value[0],value[1]); - tctx->motion.mvd[refList][0] = value[0]; - tctx->motion.mvd[refList][1] = value[1]; - - logtrace(LogSlice, "MVD[%d;%d|%d] = %d;%d\n",x0,y0,refList, value[0],value[1]); -} - - -void read_prediction_unit_SKIP(thread_context* tctx, - int x0, int y0, - int nPbW, int nPbH) -{ - int merge_idx = decode_merge_idx(tctx); - - tctx->motion.merge_idx = merge_idx; - tctx->motion.merge_flag = true; - - logtrace(LogSlice,"prediction skip 2Nx2N, merge_idx: %d\n",merge_idx); -} - - -/* xC/yC : CB position - xB/yB : position offset of the PB - nPbW/nPbH : size of PB - nCS : CB size - */ -void read_prediction_unit(thread_context* tctx, - int xC,int yC, int xB,int yB, - int nPbW, int nPbH, - int ctDepth, int nCS,int partIdx) -{ - logtrace(LogSlice,"read_prediction_unit %d;%d %dx%d\n",xC+xB,yC+xB,nPbW,nPbH); - - int x0 = xC+xB; - int y0 = yC+yB; - - slice_segment_header* shdr = tctx->shdr; - - int merge_flag = decode_merge_flag(tctx); - tctx->motion.merge_flag = merge_flag; - - if (merge_flag) { - int merge_idx = decode_merge_idx(tctx); - - logtrace(LogSlice,"prediction unit %d,%d, merge mode, index: %d\n",x0,y0,merge_idx); - - tctx->motion.merge_idx = merge_idx; - } - else { // no merge flag - enum InterPredIdc inter_pred_idc; - - if (shdr->slice_type == SLICE_TYPE_B) { - inter_pred_idc = decode_inter_pred_idc(tctx,x0,y0,nPbW,nPbH,ctDepth); - } - else { - inter_pred_idc = PRED_L0; - } - - tctx->motion.inter_pred_idc = inter_pred_idc; // set_inter_pred_idc(ctx,x0,y0, inter_pred_idc); - - if (inter_pred_idc != PRED_L1) { - int ref_idx_l0 = decode_ref_idx_lX(tctx, shdr->num_ref_idx_l0_active); - - // NOTE: case for only one reference frame is handles in decode_ref_idx_lX() - tctx->motion.refIdx[0] = ref_idx_l0; - - read_mvd_coding(tctx,x0,y0, 0); - - int mvp_l0_flag = decode_mvp_lx_flag(tctx); // l0 - tctx->motion.mvp_l0_flag = mvp_l0_flag; - - logtrace(LogSlice,"prediction unit %d,%d, L0, refIdx=%d mvp_l0_flag:%d\n", - x0,y0, tctx->motion.refIdx[0], mvp_l0_flag); - } - - if (inter_pred_idc != PRED_L0) { - int ref_idx_l1 = decode_ref_idx_lX(tctx, shdr->num_ref_idx_l1_active); - - // NOTE: case for only one reference frame is handles in decode_ref_idx_lX() - tctx->motion.refIdx[1] = ref_idx_l1; - - if (shdr->mvd_l1_zero_flag && - inter_pred_idc == PRED_BI) { - tctx->motion.mvd[1][0] = 0; - tctx->motion.mvd[1][1] = 0; - } - else { - read_mvd_coding(tctx,x0,y0, 1); - } - - int mvp_l1_flag = decode_mvp_lx_flag(tctx); // l1 - tctx->motion.mvp_l1_flag = mvp_l1_flag; - - logtrace(LogSlice,"prediction unit %d,%d, L1, refIdx=%d mvp_l1_flag:%d\n", - x0,y0, tctx->motion.refIdx[1], mvp_l1_flag); - } - } - - - - decode_prediction_unit(tctx->decctx, tctx->shdr, tctx->img, tctx->motion, - xC,yC,xB,yB, nCS, nPbW,nPbH, partIdx); -} - - - - -template -void read_pcm_samples_internal(thread_context* tctx, int x0, int y0, int log2CbSize, - int cIdx, bitreader& br) -{ - const seq_parameter_set& sps = tctx->img->get_sps(); - - int nPcmBits; - int bitDepth; - - int w = 1<0) { - w /= sps.SubWidthC; - h /= sps.SubHeightC; - - x0 /= sps.SubWidthC; - y0 /= sps.SubHeightC; - - nPcmBits = sps.pcm_sample_bit_depth_chroma; - bitDepth = sps.BitDepth_C; - } - else { - nPcmBits = sps.pcm_sample_bit_depth_luma; - bitDepth = sps.BitDepth_Y; - } - - pixel_t* ptr; - int stride; - ptr = tctx->img->get_image_plane_at_pos_NEW(cIdx,x0,y0); - stride = tctx->img->get_image_stride(cIdx); - - int shift = bitDepth - nPcmBits; - - for (int y=0;ycabac_decoder.bitstream_curr; - br.bytes_remaining = tctx->cabac_decoder.bitstream_end - tctx->cabac_decoder.bitstream_curr; - br.nextbits = 0; - br.nextbits_cnt = 0; - - - if (tctx->img->high_bit_depth(0)) { - read_pcm_samples_internal(tctx,x0,y0,log2CbSize,0,br); - } else { - read_pcm_samples_internal(tctx,x0,y0,log2CbSize,0,br); - } - - if (tctx->img->get_sps().ChromaArrayType != CHROMA_MONO) { - if (tctx->img->high_bit_depth(1)) { - read_pcm_samples_internal(tctx,x0,y0,log2CbSize,1,br); - read_pcm_samples_internal(tctx,x0,y0,log2CbSize,2,br); - } else { - read_pcm_samples_internal(tctx,x0,y0,log2CbSize,1,br); - read_pcm_samples_internal(tctx,x0,y0,log2CbSize,2,br); - } - } - - prepare_for_CABAC(&br); - tctx->cabac_decoder.bitstream_curr = br.data; - init_CABAC_decoder_2(&tctx->cabac_decoder); -} - - -int map_chroma_pred_mode(int intra_chroma_pred_mode, int IntraPredMode) -{ - if (intra_chroma_pred_mode==4) { - return IntraPredMode; - } - else { - static const enum IntraPredMode IntraPredModeCCand[4] = { - INTRA_PLANAR, - INTRA_ANGULAR_26, // vertical - INTRA_ANGULAR_10, // horizontal - INTRA_DC - }; - - int IntraPredModeC = IntraPredModeCCand[intra_chroma_pred_mode]; - if (IntraPredModeC == IntraPredMode) { - return INTRA_ANGULAR_34; - } - else { - return IntraPredModeC; - } - } -} - -// h.265-V2 Table 8-3 -static const uint8_t map_chroma_422[35] = { - 0,1,2, 2, 2, 2, 3, 5, 7, 8,10,12,13,15,17,18,19,20, - 21,22,23,23,24,24,25,25,26,27,27,28,28,29,29,30,31 -}; - -void read_coding_unit(thread_context* tctx, - int x0, int y0, // position of coding unit in frame - int log2CbSize, - int ctDepth) -{ - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - const pic_parameter_set& pps = img->get_pps(); - slice_segment_header* shdr = tctx->shdr; - - logtrace(LogSlice,"- read_coding_unit %d;%d cbsize:%d\n",x0,y0,1<set_log2CbSize(x0,y0, log2CbSize, true); - - /* This is only required on corrupted input streams. - It may happen that there are several slices in the image that overlap. - In this case, flags would accumulate from both slices. - */ - img->clear_split_transform_flags(x0,y0, log2CbSize); - - int nCbS = 1<cu_transquant_bypass_flag = transquant_bypass; - - if (transquant_bypass) { - img->set_cu_transquant_bypass(x0,y0,log2CbSize); - } - } - else { - tctx->cu_transquant_bypass_flag = 0; - } - - uint8_t cu_skip_flag = 0; - if (shdr->slice_type != SLICE_TYPE_I) { - cu_skip_flag = decode_cu_skip_flag(tctx,x0,y0,ctDepth); - } - - int IntraSplitFlag = 0; - - enum PredMode cuPredMode; - - if (cu_skip_flag) { - read_prediction_unit_SKIP(tctx,x0,y0,nCbS,nCbS); - - img->set_PartMode(x0,y0, PART_2Nx2N); // need this for deblocking filter - img->set_pred_mode(x0,y0,log2CbSize, MODE_SKIP); - cuPredMode = MODE_SKIP; - - logtrace(LogSlice,"CU pred mode: SKIP\n"); - - - // DECODE - - int nCS_L = 1<decctx,tctx->shdr,tctx->img,tctx->motion, - x0,y0, 0,0, nCS_L, nCS_L,nCS_L, 0); - } - else /* not skipped */ { - if (shdr->slice_type != SLICE_TYPE_I) { - int pred_mode_flag = decode_pred_mode_flag(tctx); - cuPredMode = pred_mode_flag ? MODE_INTRA : MODE_INTER; - } - else { - cuPredMode = MODE_INTRA; - } - - img->set_pred_mode(x0,y0,log2CbSize, cuPredMode); - - logtrace(LogSlice,"CU pred mode: %s\n", cuPredMode==MODE_INTRA ? "INTRA" : "INTER"); - - - enum PartMode PartMode; - - if (cuPredMode != MODE_INTRA || - log2CbSize == sps.Log2MinCbSizeY) { - PartMode = decode_part_mode(tctx, cuPredMode, log2CbSize); - - if (PartMode==PART_NxN && cuPredMode==MODE_INTRA) { - IntraSplitFlag=1; - } - } else { - PartMode = PART_2Nx2N; - } - - img->set_PartMode(x0,y0, PartMode); // needed for deblocking ? - - logtrace(LogSlice, "PartMode: %s\n", part_mode_name(PartMode)); - - - bool pcm_flag = false; - - if (cuPredMode == MODE_INTRA) { - if (PartMode == PART_2Nx2N && sps.pcm_enabled_flag && - log2CbSize >= sps.Log2MinIpcmCbSizeY && - log2CbSize <= sps.Log2MaxIpcmCbSizeY) { - pcm_flag = decode_CABAC_term_bit(&tctx->cabac_decoder); - } - - if (pcm_flag) { - img->set_pcm_flag(x0,y0,log2CbSize); - - read_pcm_samples(tctx, x0,y0, log2CbSize); - } - else { - int pbOffset = (PartMode == PART_NxN) ? (nCbS/2) : nCbS; - int log2IntraPredSize = (PartMode == PART_NxN) ? (log2CbSize-1) : log2CbSize; - - logtrace(LogSlice,"nCbS:%d pbOffset:%d\n",nCbS,pbOffset); - - int prev_intra_luma_pred_flag[4]; - - int idx=0; - for (int j=0;j0); // left candidate always available for right blk - int availableB = availableB0 || (j>0); // top candidate always available for bottom blk - - - - int PUidx = (x>>sps.Log2MinPUSize) + (y>>sps.Log2MinPUSize)*sps.PicWidthInMinPUs; - - enum IntraPredMode candModeList[3]; - - fillIntraPredModeCandidates(candModeList,x,y,PUidx, - availableA, availableB, img); - - for (int i=0;i<3;i++) - logtrace(LogSlice,"candModeList[%d] = %d\n", i, candModeList[i]); - - if (prev_intra_luma_pred_flag[idx]==1) { - IntraPredMode = candModeList[ mpm_idx[idx] ]; - } - else { - // sort candModeList - - if (candModeList[0] > candModeList[1]) { - std::swap(candModeList[0],candModeList[1]); - } - if (candModeList[0] > candModeList[2]) { - std::swap(candModeList[0],candModeList[2]); - } - if (candModeList[1] > candModeList[2]) { - std::swap(candModeList[1],candModeList[2]); - } - - // skip modes in the list - // (we have 35 modes. skipping the 3 in the list gives us 32, which can be selected by 5 bits) - IntraPredMode = rem_intra_luma_pred_mode[idx]; - for (int n=0;n<=2;n++) { - if (IntraPredMode >= candModeList[n]) { IntraPredMode++; } - } - } - - logtrace(LogSlice,"IntraPredMode[%d][%d] = %d (log2blk:%d)\n",x,y,IntraPredMode, log2IntraPredSize); - - img->set_IntraPredMode(PUidx, log2IntraPredSize, - (enum IntraPredMode)IntraPredMode); - - idx++; - } - - - // set chroma intra prediction mode - - if (sps.ChromaArrayType == CHROMA_444) { - // chroma 4:4:4 - - idx = 0; - for (int j=0;jget_IntraPredMode(x,y); - - int IntraPredModeC = map_chroma_pred_mode(intra_chroma_pred_mode, IntraPredMode); - - logtrace(LogSlice,"IntraPredModeC[%d][%d]: %d (blksize:%d)\n",x,y,IntraPredModeC, - 1<set_IntraPredModeC(x,y, log2IntraPredSize, - (enum IntraPredMode)IntraPredModeC, - intra_chroma_pred_mode == 4); - idx++; - } - } - else if (sps.ChromaArrayType != CHROMA_MONO) { - // chroma 4:2:0 and 4:2:2 - - int intra_chroma_pred_mode = decode_intra_chroma_pred_mode(tctx); - int IntraPredMode = img->get_IntraPredMode(x0,y0); - logtrace(LogSlice,"IntraPredMode: %d\n",IntraPredMode); - int IntraPredModeC = map_chroma_pred_mode(intra_chroma_pred_mode, IntraPredMode); - - if (sps.ChromaArrayType == CHROMA_422) { - IntraPredModeC = map_chroma_422[ IntraPredModeC ]; - } - - img->set_IntraPredModeC(x0,y0, log2CbSize, - (enum IntraPredMode)IntraPredModeC, - intra_chroma_pred_mode == 4); - } - } - } - else { // INTER - int nCS = 1<motion.merge_flag; // !!get_merge_flag(ctx,x0,y0); - - if (cuPredMode != MODE_INTRA && - !(PartMode == PART_2Nx2N && merge_flag)) { - - rqt_root_cbf = !!decode_rqt_root_cbf(tctx); - } - else { - /* rqt_root_cbf=1 is inferred for Inter blocks with 2Nx2N, merge mode. - These must be some residual data, because otherwise, the CB could - also be coded in SKIP mode. - */ - - rqt_root_cbf = true; - } - - //set_rqt_root_cbf(ctx,x0,y0, log2CbSize, rqt_root_cbf); - - if (rqt_root_cbf) { - int MaxTrafoDepth; - - if (cuPredMode==MODE_INTRA) { - MaxTrafoDepth = sps.max_transform_hierarchy_depth_intra + IntraSplitFlag; - } - else { - MaxTrafoDepth = sps.max_transform_hierarchy_depth_inter; - } - - logtrace(LogSlice,"MaxTrafoDepth: %d\n",MaxTrafoDepth); - - uint8_t initial_chroma_cbf = 1; - if (sps.ChromaArrayType == CHROMA_MONO) { - initial_chroma_cbf = 0; - } - - read_transform_tree(tctx, x0,y0, x0,y0, x0,y0, log2CbSize, 0,0, - MaxTrafoDepth, IntraSplitFlag, cuPredMode, - initial_chroma_cbf, initial_chroma_cbf); - } - } // !pcm - } -} - - -// ------------------------------------------------------------------------------------------ - - -void read_coding_quadtree(thread_context* tctx, - int x0, int y0, - int log2CbSize, - int ctDepth) -{ - logtrace(LogSlice,"- read_coding_quadtree %d;%d cbsize:%d depth:%d POC:%d\n",x0,y0,1<img->PicOrderCntVal); - - de265_image* img = tctx->img; - const seq_parameter_set& sps = img->get_sps(); - const pic_parameter_set& pps = img->get_pps(); - - int split_flag; - - // We only send a split flag if CU is larger than minimum size and - // completely contained within the image area. - // If it is partly outside the image area and not at minimum size, - // it is split. If already at minimum size, it is not split further. - if (x0+(1< sps.Log2MinCbSizeY) { - split_flag = decode_split_cu_flag(tctx, x0,y0, ctDepth); - } else { - if (log2CbSize > sps.Log2MinCbSizeY) { split_flag=1; } - else { split_flag=0; } - } - - - if (pps.cu_qp_delta_enabled_flag && - log2CbSize >= pps.Log2MinCuQpDeltaSize) - { - tctx->IsCuQpDeltaCoded = 0; - tctx->CuQpDelta = 0; - } - else - { - // shdr->CuQpDelta = 0; // TODO check: is this the right place to set to default value ? - } - - - if (tctx->shdr->cu_chroma_qp_offset_enabled_flag && - log2CbSize >= pps.Log2MinCuChromaQpOffsetSize) { - tctx->IsCuChromaQpOffsetCoded = 0; - } - - if (split_flag) { - int x1 = x0 + (1<<(log2CbSize-1)); - int y1 = y0 + (1<<(log2CbSize-1)); - - read_coding_quadtree(tctx,x0,y0, log2CbSize-1, ctDepth+1); - - if (x1set_ctDepth(x0,y0, log2CbSize, ctDepth); - - read_coding_unit(tctx, x0,y0, log2CbSize, ctDepth); - } - - logtrace(LogSlice,"-\n"); -} - - -// --------------------------------------------------------------------------- - -enum DecodeResult { - Decode_EndOfSliceSegment, - Decode_EndOfSubstream, - Decode_Error -}; - -/* Decode CTBs until the end of sub-stream, the end-of-slice, or some error occurs. - */ -enum DecodeResult decode_substream(thread_context* tctx, - bool block_wpp, // block on WPP dependencies - bool first_independent_substream) -{ - const pic_parameter_set& pps = tctx->img->get_pps(); - const seq_parameter_set& sps = tctx->img->get_sps(); - - const int ctbW = sps.PicWidthInCtbsY; - - - const int startCtbY = tctx->CtbY; - - //printf("start decoding substream at %d;%d\n",tctx->CtbX,tctx->CtbY); - - // in WPP mode: initialize CABAC model with stored model from row above - - if ((!first_independent_substream || tctx->CtbY != startCtbY) && - pps.entropy_coding_sync_enabled_flag && - tctx->CtbY>=1 && tctx->CtbX==0) - { - if (sps.PicWidthInCtbsY>1) { - if ((tctx->CtbY-1) >= tctx->imgunit->ctx_models.size()) { - return Decode_Error; - } - - //printf("CTX wait on %d/%d\n",1,tctx->CtbY-1); - - // we have to wait until the context model data is there - tctx->img->wait_for_progress(tctx->task, 1,tctx->CtbY-1,CTB_PROGRESS_PREFILTER); - - // copy CABAC model from previous CTB row - tctx->ctx_model = tctx->imgunit->ctx_models[(tctx->CtbY-1)]; - tctx->imgunit->ctx_models[(tctx->CtbY-1)].release(); // not used anymore - } - else { - tctx->img->wait_for_progress(tctx->task, 0,tctx->CtbY-1,CTB_PROGRESS_PREFILTER); - initialize_CABAC_models(tctx); - } - } - - - do { - const int ctbx = tctx->CtbX; - const int ctby = tctx->CtbY; - - if (ctbx+ctby*ctbW >= pps.CtbAddrRStoTS.size()) { - return Decode_Error; - } - - if (ctbx >= sps.PicWidthInCtbsY || - ctby >= sps.PicHeightInCtbsY) { - return Decode_Error; - } - - if (block_wpp && ctby>0 && ctbx < ctbW-1) { - - // TODO: if we are in tiles mode and at the right border, do not wait for x+1,y-1 - - //printf("wait on %d/%d (%d)\n",ctbx+1,ctby-1, ctbx+1+(ctby-1)*sps->PicWidthInCtbsY); - - tctx->img->wait_for_progress(tctx->task, ctbx+1,ctby-1, CTB_PROGRESS_PREFILTER); - } - - //printf("%p: decode %d;%d\n", tctx, tctx->CtbX,tctx->CtbY); - - - // read and decode CTB - - if (tctx->ctx_model.empty() == false) { - return Decode_Error; - } - - read_coding_tree_unit(tctx); - - - // save CABAC-model for WPP (except in last CTB row) - - if (pps.entropy_coding_sync_enabled_flag && - ctbx == 1 && - ctby < sps.PicHeightInCtbsY-1) - { - // no storage for context table has been allocated - if (tctx->imgunit->ctx_models.size() <= ctby) { - return Decode_Error; - } - - tctx->imgunit->ctx_models[ctby] = tctx->ctx_model; - tctx->imgunit->ctx_models[ctby].decouple(); // store an independent copy - } - - - // end of slice segment ? - - int end_of_slice_segment_flag = decode_CABAC_term_bit(&tctx->cabac_decoder); - //printf("end-of-slice flag: %d\n", end_of_slice_segment_flag); - - if (end_of_slice_segment_flag) { - // at the end of the slice segment, we store the CABAC model if we need it - // because a dependent slice may follow - - if (pps.dependent_slice_segments_enabled_flag) { - tctx->shdr->ctx_model_storage = tctx->ctx_model; - tctx->shdr->ctx_model_storage.decouple(); // store an independent copy - - tctx->shdr->ctx_model_storage_defined = true; - } - } - - tctx->img->ctb_progress[ctbx+ctby*ctbW].set_progress(CTB_PROGRESS_PREFILTER); - - //printf("%p: decoded %d|%d\n",tctx, ctby,ctbx); - - - logtrace(LogSlice,"read CTB %d -> end=%d\n", tctx->CtbAddrInRS, end_of_slice_segment_flag); - //printf("read CTB %d -> end=%d\n", tctx->CtbAddrInRS, end_of_slice_segment_flag); - - const int lastCtbY = tctx->CtbY; - - bool endOfPicture = advanceCtbAddr(tctx); // true if we read past the end of the image - - if (endOfPicture && - end_of_slice_segment_flag == false) - { - tctx->decctx->add_warning(DE265_WARNING_CTB_OUTSIDE_IMAGE_AREA, false); - tctx->img->integrity = INTEGRITY_DECODING_ERRORS; - return Decode_Error; - } - - - if (end_of_slice_segment_flag) { - /* corrupted inputs may send the end_of_slice_segment_flag even if not all - CTBs in a row have been coded. Hence, we mark all of them as finished. - */ - - /* - for (int x = ctbx+1 ; xPicWidthInCtbsY; x++) { - printf("mark skipped %d;%d\n",ctbx,ctby); - tctx->img->ctb_progress[ctbx+ctby*ctbW].set_progress(CTB_PROGRESS_PREFILTER); - } - */ - - return Decode_EndOfSliceSegment; - } - - - if (!end_of_slice_segment_flag) { - bool end_of_sub_stream = false; - end_of_sub_stream |= (pps.tiles_enabled_flag && - pps.TileId[tctx->CtbAddrInTS] != pps.TileId[tctx->CtbAddrInTS-1]); - end_of_sub_stream |= (pps.entropy_coding_sync_enabled_flag && - lastCtbY != tctx->CtbY); - - if (end_of_sub_stream) { - int end_of_sub_stream_one_bit = decode_CABAC_term_bit(&tctx->cabac_decoder); - if (!end_of_sub_stream_one_bit) { - tctx->decctx->add_warning(DE265_WARNING_EOSS_BIT_NOT_SET, false); - tctx->img->integrity = INTEGRITY_DECODING_ERRORS; - return Decode_Error; - } - - init_CABAC_decoder_2(&tctx->cabac_decoder); // byte alignment - return Decode_EndOfSubstream; - } - } - - } while (true); -} - - - -bool initialize_CABAC_at_slice_segment_start(thread_context* tctx) -{ - de265_image* img = tctx->img; - const pic_parameter_set& pps = img->get_pps(); - const seq_parameter_set& sps = img->get_sps(); - slice_segment_header* shdr = tctx->shdr; - - if (shdr->dependent_slice_segment_flag) { - int prevCtb = pps.CtbAddrTStoRS[ pps.CtbAddrRStoTS[shdr->slice_segment_address] -1 ]; - - int sliceIdx = img->get_SliceHeaderIndex_atIndex(prevCtb); - if (sliceIdx >= img->slices.size()) { - return false; - } - slice_segment_header* prevCtbHdr = img->slices[ sliceIdx ]; - - if (pps.is_tile_start_CTB(shdr->slice_segment_address % sps.PicWidthInCtbsY, - shdr->slice_segment_address / sps.PicWidthInCtbsY - )) { - initialize_CABAC_models(tctx); - } - else { - // wait for previous slice to finish decoding - - //printf("wait for previous slice to finish decoding\n"); - - - slice_unit* prevSliceSegment = tctx->imgunit->get_prev_slice_segment(tctx->sliceunit); - //assert(prevSliceSegment); - if (prevSliceSegment==NULL) { - return false; - } - - prevSliceSegment->finished_threads.wait_for_progress(prevSliceSegment->nThreads); - - - /* - printf("wait for %d,%d (init)\n", - prevCtb / sps->PicWidthInCtbsY, - prevCtb % sps->PicWidthInCtbsY); - tctx->img->wait_for_progress(tctx->task, prevCtb, CTB_PROGRESS_PREFILTER); - */ - - if (!prevCtbHdr->ctx_model_storage_defined) { - return false; - } - - tctx->ctx_model = prevCtbHdr->ctx_model_storage; - prevCtbHdr->ctx_model_storage.release(); - } - } - else { - initialize_CABAC_models(tctx); - } - - return true; -} - - -std::string thread_task_ctb_row::name() const { - char buf[100]; - sprintf(buf,"ctb-row-%d",debug_startCtbRow); - return buf; -} - - -std::string thread_task_slice_segment::name() const { - char buf[100]; - sprintf(buf,"slice-segment-%d;%d",debug_startCtbX,debug_startCtbY); - return buf; -} - - -void thread_task_slice_segment::work() -{ - thread_task_slice_segment* data = this; - thread_context* tctx = data->tctx; - de265_image* img = tctx->img; - - state = Running; - img->thread_run(this); - - setCtbAddrFromTS(tctx); - - //printf("%p: A start decoding at %d/%d\n", tctx, tctx->CtbX,tctx->CtbY); - - if (data->firstSliceSubstream) { - bool success = initialize_CABAC_at_slice_segment_start(tctx); - if (!success) { - state = Finished; - tctx->sliceunit->finished_threads.increase_progress(1); - img->thread_finishes(this); - return; - } - } - else { - initialize_CABAC_models(tctx); - } - - init_CABAC_decoder_2(&tctx->cabac_decoder); - - /*enum DecodeResult result =*/ decode_substream(tctx, false, data->firstSliceSubstream); - - state = Finished; - tctx->sliceunit->finished_threads.increase_progress(1); - img->thread_finishes(this); - - return; // DE265_OK; -} - - -void thread_task_ctb_row::work() -{ - thread_task_ctb_row* data = this; - thread_context* tctx = data->tctx; - de265_image* img = tctx->img; - - const seq_parameter_set& sps = img->get_sps(); - int ctbW = sps.PicWidthInCtbsY; - - state = Running; - img->thread_run(this); - - setCtbAddrFromTS(tctx); - - int ctby = tctx->CtbAddrInRS / ctbW; - int myCtbRow = ctby; - - //printf("start CTB-row decoding at row %d\n", ctby); - - if (data->firstSliceSubstream) { - bool success = initialize_CABAC_at_slice_segment_start(tctx); - if (!success) { - // could not decode this row, mark whole row as finished - for (int x=0;xctb_progress[myCtbRow*ctbW + x].set_progress(CTB_PROGRESS_PREFILTER); - } - - state = Finished; - tctx->sliceunit->finished_threads.increase_progress(1); - img->thread_finishes(this); - return; - } - //initialize_CABAC(tctx); - } - - init_CABAC_decoder_2(&tctx->cabac_decoder); - - bool firstIndependentSubstream = - data->firstSliceSubstream && !tctx->shdr->dependent_slice_segment_flag; - - /*enum DecodeResult result =*/ - decode_substream(tctx, true, firstIndependentSubstream); - - // mark progress on remaining CTBs in row (in case of decoder error and early termination) - - // TODO: what about slices that end properly in the middle of a CTB row? - - if (tctx->CtbY == myCtbRow) { - int lastCtbX = sps.PicWidthInCtbsY; // assume no tiles when WPP is on - for (int x = tctx->CtbX; xctb_progress[myCtbRow*ctbW + x].set_progress(CTB_PROGRESS_PREFILTER); - } - } - } - - state = Finished; - tctx->sliceunit->finished_threads.increase_progress(1); - img->thread_finishes(this); -} - - -de265_error read_slice_segment_data(thread_context* tctx) -{ - setCtbAddrFromTS(tctx); - - de265_image* img = tctx->img; - const pic_parameter_set& pps = img->get_pps(); - const seq_parameter_set& sps = img->get_sps(); - slice_segment_header* shdr = tctx->shdr; - - bool success = initialize_CABAC_at_slice_segment_start(tctx); - if (!success) { - return DE265_ERROR_UNSPECIFIED_DECODING_ERROR; - } - - init_CABAC_decoder_2(&tctx->cabac_decoder); - - //printf("-----\n"); - - bool first_slice_substream = !shdr->dependent_slice_segment_flag; - - int substream=0; - - enum DecodeResult result; - do { - int ctby = tctx->CtbY; - - - // check whether entry_points[] are correct in the bitstream - - if (substream>0) { - if (substream-1 >= tctx->shdr->entry_point_offset.size() || - tctx->cabac_decoder.bitstream_curr - tctx->cabac_decoder.bitstream_start -2 /* -2 because of CABAC init */ - != tctx->shdr->entry_point_offset[substream-1]) { - tctx->decctx->add_warning(DE265_WARNING_INCORRECT_ENTRY_POINT_OFFSET, true); - } - } - - substream++; - - - result = decode_substream(tctx, false, first_slice_substream); - - - if (result == Decode_EndOfSliceSegment || - result == Decode_Error) { - break; - } - - first_slice_substream = false; - - if (pps.tiles_enabled_flag) { - initialize_CABAC_models(tctx); - } - } while (true); - - return DE265_OK; -} - - -/* TODO: - When a task wants to block, but is the first in the list of pending tasks, - do some error concealment instead of blocking, since it will never be deblocked. - This will only happen in the case of input error. - */ +/* + * H.265 video codec. + * Copyright (c) 2013-2014 struktur AG, Dirk Farin + * + * Authors: struktur AG, Dirk Farin + * Min Chen + * + * This file is part of libde265. + * + * libde265 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libde265 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libde265. If not, see . + */ + +#include "slice.h" +#include "motion.h" +#include "util.h" +#include "scan.h" +#include "intrapred.h" +#include "transform.h" +#include "threads.h" +#include "image.h" + +#include +#include +#include + + +#define LOCK de265_mutex_lock(&ctx->thread_pool.mutex) +#define UNLOCK de265_mutex_unlock(&ctx->thread_pool.mutex) + +extern bool read_short_term_ref_pic_set(error_queue* errqueue, + const seq_parameter_set* sps, + bitreader* br, + ref_pic_set* out_set, + int idxRps, // index of the set to be read + const std::vector& sets, + bool sliceRefPicSet); + + +void read_coding_tree_unit(thread_context* tctx); +void read_coding_quadtree(thread_context* tctx, + int xCtb, int yCtb, + int Log2CtbSizeY, + int ctDepth); +/* +void decode_inter_block(decoder_context* ctx,thread_context* tctx, + int xC, int yC, int log2CbSize); +*/ + +void slice_segment_header::set_defaults() +{ + slice_index = 0; + + first_slice_segment_in_pic_flag = 1; + no_output_of_prior_pics_flag = 0; + slice_pic_parameter_set_id = 0; + dependent_slice_segment_flag = 0; + slice_segment_address = 0; + + slice_type = SLICE_TYPE_I; + pic_output_flag = 1; + colour_plane_id = 0; + slice_pic_order_cnt_lsb = 0; + short_term_ref_pic_set_sps_flag = 1; + // ref_pic_set slice_ref_pic_set; + + short_term_ref_pic_set_idx = 0; + num_long_term_sps = 0; + num_long_term_pics = 0; + + //uint8_t lt_idx_sps[MAX_NUM_REF_PICS]; + //int poc_lsb_lt[MAX_NUM_REF_PICS]; + //char used_by_curr_pic_lt_flag[MAX_NUM_REF_PICS]; + + //char delta_poc_msb_present_flag[MAX_NUM_REF_PICS]; + //int delta_poc_msb_cycle_lt[MAX_NUM_REF_PICS]; + + slice_temporal_mvp_enabled_flag = 0; + slice_sao_luma_flag = 0; + slice_sao_chroma_flag = 0; + + num_ref_idx_active_override_flag = 0; + num_ref_idx_l0_active=1; // [1;16] + num_ref_idx_l1_active=1; // [1;16] + + ref_pic_list_modification_flag_l0 = 0; + ref_pic_list_modification_flag_l1 = 0; + //uint8_t list_entry_l0[16]; + //uint8_t list_entry_l1[16]; + + mvd_l1_zero_flag = 0; + cabac_init_flag = 0; + collocated_from_l0_flag = 0; + collocated_ref_idx = 0; + + // --- pred_weight_table --- + + luma_log2_weight_denom=0; // [0;7] + ChromaLog2WeightDenom=0; // [0;7] + + // first index is L0/L1 + /* + uint8_t luma_weight_flag[2][16]; // bool + uint8_t chroma_weight_flag[2][16]; // bool + int16_t LumaWeight[2][16]; + int8_t luma_offset[2][16]; + int16_t ChromaWeight[2][16][2]; + int8_t ChromaOffset[2][16][2]; + */ + + + five_minus_max_num_merge_cand = 0; + slice_qp_delta = 0; + + slice_cb_qp_offset = 0; + slice_cr_qp_offset = 0; + + cu_chroma_qp_offset_enabled_flag = 0; + + deblocking_filter_override_flag = 0; + slice_deblocking_filter_disabled_flag = 0; + slice_beta_offset=0; // = pps->beta_offset if undefined + slice_tc_offset=0; // = pps->tc_offset if undefined + + slice_loop_filter_across_slices_enabled_flag = 0; + + num_entry_point_offsets = 0; + //int offset_len; + //std::vector entry_point_offset; + + slice_segment_header_extension_length = 0; + + SliceAddrRS = slice_segment_address; +} + + +bool read_pred_weight_table(bitreader* br, slice_segment_header* shdr, decoder_context* ctx) +{ + int vlc; + + pic_parameter_set* pps = ctx->get_pps((int)shdr->slice_pic_parameter_set_id); + assert(pps); + seq_parameter_set* sps = ctx->get_sps((int)pps->seq_parameter_set_id); + assert(sps); + + shdr->luma_log2_weight_denom = vlc = get_uvlc(br); + if (vlc<0 || vlc>7) return false; + + if (sps->chroma_format_idc != 0) { + vlc = get_svlc(br); + vlc += shdr->luma_log2_weight_denom; + if (vlc<0 || vlc>7) return false; + shdr->ChromaLog2WeightDenom = vlc; + } + + int sumWeightFlags = 0; + + for (int l=0;l<=1;l++) + if (l==0 || (l==1 && shdr->slice_type == SLICE_TYPE_B)) + { + int num_ref = (l==0 ? shdr->num_ref_idx_l0_active-1 : shdr->num_ref_idx_l1_active-1); + + for (int i=0;i<=num_ref;i++) { + shdr->luma_weight_flag[l][i] = get_bits(br,1); + if (shdr->luma_weight_flag[l][i]) sumWeightFlags++; + } + + if (sps->chroma_format_idc != 0) { + for (int i=0;i<=num_ref;i++) { + shdr->chroma_weight_flag[l][i] = get_bits(br,1); + if (shdr->chroma_weight_flag[l][i]) sumWeightFlags+=2; + } + } + + for (int i=0;i<=num_ref;i++) { + if (shdr->luma_weight_flag[l][i]) { + + // delta_luma_weight + + vlc = get_svlc(br); + if (vlc < -128 || vlc > 127) return false; + + shdr->LumaWeight[l][i] = (1<luma_log2_weight_denom) + vlc; + + // luma_offset + + vlc = get_svlc(br); + if (vlc < -sps->WpOffsetHalfRangeY || vlc > sps->WpOffsetHalfRangeY-1) return false; + shdr->luma_offset[l][i] = vlc; + } + else { + shdr->LumaWeight[l][i] = 1<luma_log2_weight_denom; + shdr->luma_offset[l][i] = 0; + } + + if (shdr->chroma_weight_flag[l][i]) + for (int j=0;j<2;j++) { + // delta_chroma_weight + + vlc = get_svlc(br); + if (vlc < -128 || vlc > 127) return false; + + shdr->ChromaWeight[l][i][j] = (1<ChromaLog2WeightDenom) + vlc; + + // delta_chroma_offset + + vlc = get_svlc(br); + if (vlc < -4*sps->WpOffsetHalfRangeC || + vlc > 4*sps->WpOffsetHalfRangeC-1) return false; + + vlc = Clip3(-sps->WpOffsetHalfRangeC, + sps->WpOffsetHalfRangeC-1, + (sps->WpOffsetHalfRangeC + +vlc + -((sps->WpOffsetHalfRangeC*shdr->ChromaWeight[l][i][j]) + >> shdr->ChromaLog2WeightDenom))); + + shdr->ChromaOffset[l][i][j] = vlc; + } + else { + for (int j=0;j<2;j++) { + shdr->ChromaWeight[l][i][j] = 1<ChromaLog2WeightDenom; + shdr->ChromaOffset[l][i][j] = 0; + } + } + } + } + + // TODO: bitstream conformance requires that 'sumWeightFlags<=24' + + return true; +} + + +void slice_segment_header::reset() +{ + pps = NULL; + + slice_index = 0; + + first_slice_segment_in_pic_flag = 0; + no_output_of_prior_pics_flag = 0; + slice_pic_parameter_set_id = 0; + dependent_slice_segment_flag = 0; + slice_segment_address = 0; + + slice_type = 0; + pic_output_flag = 0; + colour_plane_id = 0; + slice_pic_order_cnt_lsb = 0; + short_term_ref_pic_set_sps_flag = 0; + slice_ref_pic_set.reset(); + + short_term_ref_pic_set_idx = 0; + num_long_term_sps = 0; + num_long_term_pics= 0; + + for (int i=0;iget_RapPicFlag()) { // TODO: is this still correct ? Should we drop RapPicFlag ? + no_output_of_prior_pics_flag = get_bits(br,1); + } + + slice_pic_parameter_set_id = get_uvlc(br); + if (slice_pic_parameter_set_id >= DE265_MAX_PPS_SETS || + slice_pic_parameter_set_id == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); + return DE265_OK; + } + + if (!ctx->has_pps(slice_pic_parameter_set_id)) { + ctx->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); + return DE265_OK; + } + + pps = ctx->get_shared_pps(slice_pic_parameter_set_id); + + const seq_parameter_set* sps = pps->sps.get(); + if (!sps->sps_read) { + ctx->add_warning(DE265_WARNING_NONEXISTING_SPS_REFERENCED, false); + *continueDecoding = false; + return DE265_OK; + } + + if (!first_slice_segment_in_pic_flag) { + if (pps->dependent_slice_segments_enabled_flag) { + dependent_slice_segment_flag = get_bits(br,1); + } else { + dependent_slice_segment_flag = 0; + } + + int slice_segment_address = get_bits(br, ceil_log2(sps->PicSizeInCtbsY)); + + if (dependent_slice_segment_flag) { + if (slice_segment_address == 0) { + *continueDecoding = false; + ctx->add_warning(DE265_WARNING_DEPENDENT_SLICE_WITH_ADDRESS_ZERO, false); + return DE265_OK; + } + + if (ctx->previous_slice_header == NULL) { + return DE265_ERROR_NO_INITIAL_SLICE_HEADER; + } + + *this = *ctx->previous_slice_header; + + first_slice_segment_in_pic_flag = 0; + dependent_slice_segment_flag = 1; + } + + this->slice_segment_address = slice_segment_address; + } else { + dependent_slice_segment_flag = 0; + slice_segment_address = 0; + } + + if (slice_segment_address < 0 || + slice_segment_address >= sps->PicSizeInCtbsY) { + ctx->add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + //printf("SLICE %d (%d)\n",slice_segment_address, sps->PicSizeInCtbsY); + + + if (!dependent_slice_segment_flag) { + for (int i=0; inum_extra_slice_header_bits; i++) { + //slice_reserved_undetermined_flag[i] + skip_bits(br,1); + } + + slice_type = get_uvlc(br); + if (slice_type > 2 || + slice_type == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + *continueDecoding = false; + return DE265_OK; + } + + if (pps->output_flag_present_flag) { + pic_output_flag = get_bits(br,1); + } + else { + pic_output_flag = 1; + } + + if (sps->separate_colour_plane_flag == 1) { + colour_plane_id = get_bits(br,2); + } + + + slice_pic_order_cnt_lsb = 0; + short_term_ref_pic_set_sps_flag = 0; + + int NumLtPics = 0; + + if (ctx->get_nal_unit_type() != NAL_UNIT_IDR_W_RADL && + ctx->get_nal_unit_type() != NAL_UNIT_IDR_N_LP) { + slice_pic_order_cnt_lsb = get_bits(br, sps->log2_max_pic_order_cnt_lsb); + short_term_ref_pic_set_sps_flag = get_bits(br,1); + + if (!short_term_ref_pic_set_sps_flag) { + read_short_term_ref_pic_set(ctx, sps, + br, &slice_ref_pic_set, + sps->num_short_term_ref_pic_sets(), + sps->ref_pic_sets, + true); + + CurrRpsIdx = sps->num_short_term_ref_pic_sets(); + CurrRps = slice_ref_pic_set; + } + else { + int nBits = ceil_log2(sps->num_short_term_ref_pic_sets()); + if (nBits>0) short_term_ref_pic_set_idx = get_bits(br,nBits); + else short_term_ref_pic_set_idx = 0; + + if (short_term_ref_pic_set_idx >= sps->num_short_term_ref_pic_sets()) { + ctx->add_warning(DE265_WARNING_SHORT_TERM_REF_PIC_SET_OUT_OF_RANGE, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + CurrRpsIdx = short_term_ref_pic_set_idx; + CurrRps = sps->ref_pic_sets[CurrRpsIdx]; + } + + + // --- long-term MC --- + + if (sps->long_term_ref_pics_present_flag) { + if (sps->num_long_term_ref_pics_sps > 0) { + num_long_term_sps = get_uvlc(br); + if (num_long_term_sps == UVLC_ERROR) { + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + else { + num_long_term_sps = 0; + } + + num_long_term_pics= get_uvlc(br); + if (num_long_term_pics == UVLC_ERROR) { + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + // check maximum number of reference frames + + if (num_long_term_sps + + num_long_term_pics + + CurrRps.NumNegativePics + + CurrRps.NumPositivePics + > sps->sps_max_dec_pic_buffering[sps->sps_max_sub_layers-1]) + { + ctx->add_warning(DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED, false); + *continueDecoding = false; + return DE265_OK; + } + + for (int i=0; inum_long_term_ref_pics_sps); + lt_idx_sps[i] = get_bits(br, nBits); + + // check that the referenced lt-reference really exists + + if (lt_idx_sps[i] >= sps->num_long_term_ref_pics_sps) { + ctx->add_warning(DE265_NON_EXISTING_LT_REFERENCE_CANDIDATE_IN_SLICE_HEADER, false); + *continueDecoding = false; + return DE265_OK; + } + + // delta_poc_msb_present_flag[i] = 0; // TODO ? + + ctx->PocLsbLt[i] = sps->lt_ref_pic_poc_lsb_sps[ lt_idx_sps[i] ]; + ctx->UsedByCurrPicLt[i] = sps->used_by_curr_pic_lt_sps_flag[ lt_idx_sps[i] ]; + } + else { + int nBits = sps->log2_max_pic_order_cnt_lsb; + poc_lsb_lt[i] = get_bits(br, nBits); + used_by_curr_pic_lt_flag[i] = get_bits(br,1); + + ctx->PocLsbLt[i] = poc_lsb_lt[i]; + ctx->UsedByCurrPicLt[i] = used_by_curr_pic_lt_flag[i]; + } + + if (ctx->UsedByCurrPicLt[i]) { + NumLtPics++; + } + + delta_poc_msb_present_flag[i] = get_bits(br,1); + if (delta_poc_msb_present_flag[i]) { + delta_poc_msb_cycle_lt[i] = get_uvlc(br); + if (delta_poc_msb_cycle_lt[i]==UVLC_ERROR) { + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + else { + delta_poc_msb_cycle_lt[i] = 0; + } + + if (i==0 || i==num_long_term_sps) { + ctx->DeltaPocMsbCycleLt[i] = delta_poc_msb_cycle_lt[i]; + } + else { + ctx->DeltaPocMsbCycleLt[i] = (delta_poc_msb_cycle_lt[i] + + ctx->DeltaPocMsbCycleLt[i-1]); + } + } + } + else { + num_long_term_sps = 0; + num_long_term_pics= 0; + } + + if (sps->sps_temporal_mvp_enabled_flag) { + slice_temporal_mvp_enabled_flag = get_bits(br,1); + } + else { + slice_temporal_mvp_enabled_flag = 0; + } + } + else { + slice_pic_order_cnt_lsb = 0; + num_long_term_sps = 0; + num_long_term_pics= 0; + } + + + // --- SAO --- + + if (sps->sample_adaptive_offset_enabled_flag) { + slice_sao_luma_flag = get_bits(br,1); + + if (sps->ChromaArrayType != CHROMA_MONO) { + slice_sao_chroma_flag = get_bits(br,1); + } + else { + slice_sao_chroma_flag = 0; + } + } + else { + slice_sao_luma_flag = 0; + slice_sao_chroma_flag = 0; + } + + num_ref_idx_l0_active = 0; + num_ref_idx_l1_active = 0; + + if (slice_type == SLICE_TYPE_P || + slice_type == SLICE_TYPE_B) { + num_ref_idx_active_override_flag = get_bits(br,1); + if (num_ref_idx_active_override_flag) { + num_ref_idx_l0_active = get_uvlc(br); + if (num_ref_idx_l0_active == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + num_ref_idx_l0_active++;; + + if (slice_type == SLICE_TYPE_B) { + num_ref_idx_l1_active = get_uvlc(br); + if (num_ref_idx_l1_active == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + num_ref_idx_l1_active++; + } + } + else { + num_ref_idx_l0_active = pps->num_ref_idx_l0_default_active; + num_ref_idx_l1_active = pps->num_ref_idx_l1_default_active; + } + + if (num_ref_idx_l0_active > 16) { return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } + if (num_ref_idx_l1_active > 16) { return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } + + NumPocTotalCurr = CurrRps.NumPocTotalCurr_shortterm_only + NumLtPics; + + if (pps->lists_modification_present_flag && NumPocTotalCurr > 1) { + + int nBits = ceil_log2(NumPocTotalCurr); + + ref_pic_list_modification_flag_l0 = get_bits(br,1); + if (ref_pic_list_modification_flag_l0) { + for (int i=0;icabac_init_present_flag) { + cabac_init_flag = get_bits(br,1); + } + else { + cabac_init_flag = 0; + } + + if (slice_temporal_mvp_enabled_flag) { + if (slice_type == SLICE_TYPE_B) + collocated_from_l0_flag = get_bits(br,1); + else + collocated_from_l0_flag = 1; + + if (( collocated_from_l0_flag && num_ref_idx_l0_active > 1) || + (!collocated_from_l0_flag && num_ref_idx_l1_active > 1)) { + collocated_ref_idx = get_uvlc(br); + if (collocated_ref_idx == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + else { + collocated_ref_idx = 0; + } + + // check whether collocated_ref_idx points to a valid index + + if (( collocated_from_l0_flag && collocated_ref_idx >= num_ref_idx_l0_active) || + (!collocated_from_l0_flag && collocated_ref_idx >= num_ref_idx_l1_active)) { + ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + + + if ((pps->weighted_pred_flag && slice_type == SLICE_TYPE_P) || + (pps->weighted_bipred_flag && slice_type == SLICE_TYPE_B)) { + + if (!read_pred_weight_table(br,this,ctx)) + { + ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + + five_minus_max_num_merge_cand = get_uvlc(br); + if (five_minus_max_num_merge_cand == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + MaxNumMergeCand = 5-five_minus_max_num_merge_cand; + } + + slice_qp_delta = get_svlc(br); + if (slice_qp_delta == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + //logtrace(LogSlice,"slice_qp_delta: %d\n",shdr->slice_qp_delta); + + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + slice_cb_qp_offset = get_svlc(br); + if (slice_cb_qp_offset == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + slice_cr_qp_offset = get_svlc(br); + if (slice_cr_qp_offset == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + else { + slice_cb_qp_offset = 0; + slice_cr_qp_offset = 0; + } + + if (pps->range_extension.chroma_qp_offset_list_enabled_flag) { + cu_chroma_qp_offset_enabled_flag = get_bits(br,1); + } + + if (pps->deblocking_filter_override_enabled_flag) { + deblocking_filter_override_flag = get_bits(br,1); + } + else { + deblocking_filter_override_flag = 0; + } + + slice_beta_offset = pps->beta_offset; + slice_tc_offset = pps->tc_offset; + + if (deblocking_filter_override_flag) { + slice_deblocking_filter_disabled_flag = get_bits(br,1); + if (!slice_deblocking_filter_disabled_flag) { + slice_beta_offset = get_svlc(br); + if (slice_beta_offset == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + slice_beta_offset *= 2; + + slice_tc_offset = get_svlc(br); + if (slice_tc_offset == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + slice_tc_offset *= 2; + } + } + else { + slice_deblocking_filter_disabled_flag = pps->pic_disable_deblocking_filter_flag; + } + + if (pps->pps_loop_filter_across_slices_enabled_flag && + (slice_sao_luma_flag || slice_sao_chroma_flag || + !slice_deblocking_filter_disabled_flag )) { + slice_loop_filter_across_slices_enabled_flag = get_bits(br,1); + } + else { + slice_loop_filter_across_slices_enabled_flag = + pps->pps_loop_filter_across_slices_enabled_flag; + } + } + + if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag ) { + num_entry_point_offsets = get_uvlc(br); + if (num_entry_point_offsets == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + if (pps->entropy_coding_sync_enabled_flag) { + // check num_entry_points for valid range + + int firstCTBRow = slice_segment_address / sps->PicWidthInCtbsY; + int lastCTBRow = firstCTBRow + num_entry_point_offsets; + if (lastCTBRow >= sps->PicHeightInCtbsY) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + + if (pps->tiles_enabled_flag) { + if (num_entry_point_offsets > pps->num_tile_columns * pps->num_tile_rows) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + } + + entry_point_offset.resize( num_entry_point_offsets ); + + if (num_entry_point_offsets > 0) { + offset_len = get_uvlc(br); + if (offset_len == UVLC_ERROR) { + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + offset_len++; + + if (offset_len > 32) { + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + for (int i=0; i0) { + entry_point_offset[i] += entry_point_offset[i-1]; + } + } + } + } + else { + num_entry_point_offsets = 0; + } + + if (pps->slice_segment_header_extension_present_flag) { + slice_segment_header_extension_length = get_uvlc(br); + if (slice_segment_header_extension_length == UVLC_ERROR || + slice_segment_header_extension_length > 1000) { // TODO: safety check against too large values + ctx->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + for (int i=0; i DE265_MAX_PPS_SETS) { + errqueue->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); + return DE265_OK; + } + out.write_uvlc(slice_pic_parameter_set_id); + + if (!first_slice_segment_in_pic_flag) { + if (pps->dependent_slice_segments_enabled_flag) { + out.write_bit(dependent_slice_segment_flag); + } + + out.write_bits(slice_segment_address, ceil_log2(sps->PicSizeInCtbsY)); + + if (dependent_slice_segment_flag) { + if (slice_segment_address == 0) { + errqueue->add_warning(DE265_WARNING_DEPENDENT_SLICE_WITH_ADDRESS_ZERO, false); + return DE265_OK; + } + } + } + + if (slice_segment_address < 0 || + slice_segment_address > sps->PicSizeInCtbsY) { + errqueue->add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + + + if (!dependent_slice_segment_flag) { + for (int i=0; inum_extra_slice_header_bits; i++) { + //slice_reserved_undetermined_flag[i] + out.skip_bits(1); + } + + if (slice_type > 2) { + errqueue->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_OK; + } + out.write_uvlc(slice_type); + + if (pps->output_flag_present_flag) { + out.write_bit(pic_output_flag); + } + + if (sps->separate_colour_plane_flag == 1) { + out.write_bits(colour_plane_id,2); + } + + + int NumLtPics = 0; + + if (nal_unit_type != NAL_UNIT_IDR_W_RADL && + nal_unit_type != NAL_UNIT_IDR_N_LP) { + out.write_bits(slice_pic_order_cnt_lsb, sps->log2_max_pic_order_cnt_lsb); + out.write_bit(short_term_ref_pic_set_sps_flag); + + if (!short_term_ref_pic_set_sps_flag) { + /* TODO + read_short_term_ref_pic_set(ctx, sps, + br, &slice_ref_pic_set, + sps->num_short_term_ref_pic_sets, + sps->ref_pic_sets, + true); + */ + //CurrRpsIdx = sps->num_short_term_ref_pic_sets; + //CurrRps = slice_ref_pic_set; + } + else { + int nBits = ceil_log2(sps->num_short_term_ref_pic_sets()); + if (nBits>0) out.write_bits(short_term_ref_pic_set_idx,nBits); + else { assert(short_term_ref_pic_set_idx==0); } + + if (short_term_ref_pic_set_idx > sps->num_short_term_ref_pic_sets()) { + errqueue->add_warning(DE265_WARNING_SHORT_TERM_REF_PIC_SET_OUT_OF_RANGE, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + //CurrRpsIdx = short_term_ref_pic_set_idx; + //CurrRps = sps->ref_pic_sets[CurrRpsIdx]; + } + + + // --- long-term MC --- + + if (sps->long_term_ref_pics_present_flag) { + if (sps->num_long_term_ref_pics_sps > 0) { + out.write_uvlc(num_long_term_sps); + } + else { + assert(num_long_term_sps == 0); + } + + out.write_uvlc(num_long_term_pics); + + + // check maximum number of reference frames + + if (num_long_term_sps + + num_long_term_pics + + CurrRps.NumNegativePics + + CurrRps.NumPositivePics + > sps->sps_max_dec_pic_buffering[sps->sps_max_sub_layers-1]) + { + errqueue->add_warning(DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED, false); + return DE265_OK; + } + + for (int i=0; inum_long_term_ref_pics_sps); + out.write_bits(lt_idx_sps[i], nBits); + + // check that the referenced lt-reference really exists + + if (lt_idx_sps[i] >= sps->num_long_term_ref_pics_sps) { + errqueue->add_warning(DE265_NON_EXISTING_LT_REFERENCE_CANDIDATE_IN_SLICE_HEADER, false); + return DE265_OK; + } + + //ctx->PocLsbLt[i] = sps->lt_ref_pic_poc_lsb_sps[ lt_idx_sps[i] ]; + //ctx->UsedByCurrPicLt[i] = sps->used_by_curr_pic_lt_sps_flag[ lt_idx_sps[i] ]; + } + else { + int nBits = sps->log2_max_pic_order_cnt_lsb; + out.write_bits(poc_lsb_lt[i], nBits); + out.write_bit(used_by_curr_pic_lt_flag[i]); + + //ctx->PocLsbLt[i] = poc_lsb_lt[i]; + //ctx->UsedByCurrPicLt[i] = used_by_curr_pic_lt_flag[i]; + } + + //if (ctx->UsedByCurrPicLt[i]) { + //NumLtPics++; + //} + + out.write_bit(delta_poc_msb_present_flag[i]); + if (delta_poc_msb_present_flag[i]) { + out.write_uvlc(delta_poc_msb_cycle_lt[i]); + } + else { + assert(delta_poc_msb_cycle_lt[i] == 0); + } + + /* + if (i==0 || i==num_long_term_sps) { + ctx->DeltaPocMsbCycleLt[i] = delta_poc_msb_cycle_lt[i]; + } + else { + ctx->DeltaPocMsbCycleLt[i] = (delta_poc_msb_cycle_lt[i] + + ctx->DeltaPocMsbCycleLt[i-1]); + } + */ + } + } + else { + assert(num_long_term_sps == 0); + assert(num_long_term_pics== 0); + } + + if (sps->sps_temporal_mvp_enabled_flag) { + out.write_bit(slice_temporal_mvp_enabled_flag); + } + else { + assert(slice_temporal_mvp_enabled_flag == 0); + } + } + else { + assert(slice_pic_order_cnt_lsb == 0); + assert(num_long_term_sps == 0); + assert(num_long_term_pics== 0); + } + + + // --- SAO --- + + if (sps->sample_adaptive_offset_enabled_flag) { + out.write_bit(slice_sao_luma_flag); + out.write_bit(slice_sao_chroma_flag); + } + else { + assert(slice_sao_luma_flag == 0); + assert(slice_sao_chroma_flag== 0); + } + + if (slice_type == SLICE_TYPE_P || + slice_type == SLICE_TYPE_B) { + out.write_bit(num_ref_idx_active_override_flag); + + if (num_ref_idx_active_override_flag) { + out.write_uvlc(num_ref_idx_l0_active); + num_ref_idx_l0_active++;; + + if (slice_type == SLICE_TYPE_B) { + out.write_uvlc(num_ref_idx_l1_active); + num_ref_idx_l1_active++; + } + } + else { + assert(num_ref_idx_l0_active == pps->num_ref_idx_l0_default_active); + assert(num_ref_idx_l1_active == pps->num_ref_idx_l1_default_active); + } + + NumPocTotalCurr = CurrRps.NumPocTotalCurr_shortterm_only + NumLtPics; + + if (pps->lists_modification_present_flag && NumPocTotalCurr > 1) { + + int nBits = ceil_log2(NumPocTotalCurr); + + out.write_bit(ref_pic_list_modification_flag_l0); + if (ref_pic_list_modification_flag_l0) { + for (int i=0;icabac_init_present_flag) { + out.write_bit(cabac_init_flag); + } + else { + assert(cabac_init_flag == 0); + } + + if (slice_temporal_mvp_enabled_flag) { + if (slice_type == SLICE_TYPE_B) + out.write_bit(collocated_from_l0_flag); + else + { assert(collocated_from_l0_flag == 1); } + + if (( collocated_from_l0_flag && num_ref_idx_l0_active > 1) || + (!collocated_from_l0_flag && num_ref_idx_l1_active > 1)) { + out.write_uvlc(collocated_ref_idx); + } + else { + assert(collocated_ref_idx == 0); + } + } + + if ((pps->weighted_pred_flag && slice_type == SLICE_TYPE_P) || + (pps->weighted_bipred_flag && slice_type == SLICE_TYPE_B)) { + + assert(0); + /* TODO + if (!read_pred_weight_table(br,this,ctx)) + { + ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + */ + } + + out.write_uvlc(five_minus_max_num_merge_cand); + //MaxNumMergeCand = 5-five_minus_max_num_merge_cand; + } + + out.write_svlc(slice_qp_delta); + + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + out.write_svlc(slice_cb_qp_offset); + out.write_svlc(slice_cr_qp_offset); + } + else { + assert(slice_cb_qp_offset == 0); + assert(slice_cr_qp_offset == 0); + } + + if (pps->deblocking_filter_override_enabled_flag) { + out.write_bit(deblocking_filter_override_flag); + } + else { + assert(deblocking_filter_override_flag == 0); + } + + //slice_beta_offset = pps->beta_offset; + //slice_tc_offset = pps->tc_offset; + + if (deblocking_filter_override_flag) { + out.write_bit(slice_deblocking_filter_disabled_flag); + if (!slice_deblocking_filter_disabled_flag) { + out.write_svlc(slice_beta_offset/2); + out.write_svlc(slice_tc_offset /2); + } + } + else { + assert(slice_deblocking_filter_disabled_flag == pps->pic_disable_deblocking_filter_flag); + } + + if (pps->pps_loop_filter_across_slices_enabled_flag && + (slice_sao_luma_flag || slice_sao_chroma_flag || + !slice_deblocking_filter_disabled_flag )) { + out.write_bit(slice_loop_filter_across_slices_enabled_flag); + } + else { + assert(slice_loop_filter_across_slices_enabled_flag == + pps->pps_loop_filter_across_slices_enabled_flag); + } + } + + if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag ) { + out.write_uvlc(num_entry_point_offsets); + + if (num_entry_point_offsets > 0) { + out.write_uvlc(offset_len-1); + + for (int i=0; i0) prev = entry_point_offset[i-1]; + out.write_bits(entry_point_offset[i]-prev-1, offset_len); + } + } + } + } + else { + assert(num_entry_point_offsets == 0); + } + + if (pps->slice_segment_header_extension_present_flag) { + out.write_uvlc(slice_segment_header_extension_length); + if (slice_segment_header_extension_length > 1000) { // TODO: safety check against too large values + errqueue->add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); + return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; + } + + for (int i=0; ipic_init_qp + slice_qp_delta; + + switch (slice_type) + { + case SLICE_TYPE_I: initType = 0; break; + case SLICE_TYPE_P: initType = cabac_init_flag + 1; break; + case SLICE_TYPE_B: initType = 2 - cabac_init_flag; break; + } + + MaxNumMergeCand = 5-five_minus_max_num_merge_cand; +} + + +//----------------------------------------------------------------------- + + +void slice_segment_header::dump_slice_segment_header(const decoder_context* ctx, int fd) const +{ + FILE* fh; + if (fd==1) fh=stdout; + else if (fd==2) fh=stderr; + else { return; } + +#define LOG0(t) log2fh(fh, t) +#define LOG1(t,d) log2fh(fh, t,d) +#define LOG2(t,d1,d2) log2fh(fh, t,d1,d2) +#define LOG3(t,d1,d2,d3) log2fh(fh, t,d1,d2,d3) +#define LOG4(t,d1,d2,d3,d4) log2fh(fh, t,d1,d2,d3,d4) + + const pic_parameter_set* pps = ctx->get_pps(slice_pic_parameter_set_id); + assert(pps->pps_read); // TODO: error handling + + const seq_parameter_set* sps = ctx->get_sps((int)pps->seq_parameter_set_id); + assert(sps->sps_read); // TODO: error handling + + + LOG0("----------------- SLICE -----------------\n"); + LOG1("first_slice_segment_in_pic_flag : %d\n", first_slice_segment_in_pic_flag); + if (ctx->get_nal_unit_type() >= NAL_UNIT_BLA_W_LP && + ctx->get_nal_unit_type() <= NAL_UNIT_RESERVED_IRAP_VCL23) { + LOG1("no_output_of_prior_pics_flag : %d\n", no_output_of_prior_pics_flag); + } + + LOG1("slice_pic_parameter_set_id : %d\n", slice_pic_parameter_set_id); + + if (!first_slice_segment_in_pic_flag) { + //if (pps->dependent_slice_segments_enabled_flag) { + LOG1("dependent_slice_segment_flag : %d\n", dependent_slice_segment_flag); + //} + LOG1("slice_segment_address : %d\n", slice_segment_address); + } + + //if (!dependent_slice_segment_flag) + { + //for (int i=0; inum_extra_slice_header_bits; i++) { + //slice_reserved_flag[i] + + LOG1("slice_type : %c\n", + slice_type == 0 ? 'B' : + slice_type == 1 ? 'P' : 'I'); + + if (pps->output_flag_present_flag) { + LOG1("pic_output_flag : %d\n", pic_output_flag); + } + + if (sps->separate_colour_plane_flag == 1) { + LOG1("colour_plane_id : %d\n", colour_plane_id); + } + + LOG1("slice_pic_order_cnt_lsb : %d\n", slice_pic_order_cnt_lsb); + + if (ctx->get_nal_unit_type() != NAL_UNIT_IDR_W_RADL && + ctx->get_nal_unit_type() != NAL_UNIT_IDR_N_LP) { + LOG1("short_term_ref_pic_set_sps_flag : %d\n", short_term_ref_pic_set_sps_flag); + + if (!short_term_ref_pic_set_sps_flag) { + LOG1("ref_pic_set[ %2d ]: ",sps->num_short_term_ref_pic_sets()); + dump_compact_short_term_ref_pic_set(&slice_ref_pic_set, 16, fh); + } + else if (sps->num_short_term_ref_pic_sets() > 1) { + LOG1("short_term_ref_pic_set_idx : %d\n", short_term_ref_pic_set_idx); + dump_compact_short_term_ref_pic_set(&sps->ref_pic_sets[short_term_ref_pic_set_idx], 16, fh); + } + + if (sps->long_term_ref_pics_present_flag) { + if (sps->num_long_term_ref_pics_sps > 0) { + LOG1("num_long_term_sps : %d\n", num_long_term_sps); + } + + LOG1("num_long_term_pics : %d\n", num_long_term_pics); + +#if 0 + for (int i=0; iPocLsbLt[i]); + LOG2("UsedByCurrPicLt[%d] : %d\n", i, ctx->UsedByCurrPicLt[i]); + LOG2("DeltaPocMsbCycleLt[%d] : %d\n", i, ctx->DeltaPocMsbCycleLt[i]); + } +#endif + } + + if (sps->sps_temporal_mvp_enabled_flag) { + LOG1("slice_temporal_mvp_enabled_flag : %d\n", slice_temporal_mvp_enabled_flag); + } + } + + + if (sps->sample_adaptive_offset_enabled_flag) { + LOG1("slice_sao_luma_flag : %d\n", slice_sao_luma_flag); + LOG1("slice_sao_chroma_flag : %d\n", slice_sao_chroma_flag); + } + + + if (slice_type == SLICE_TYPE_P || slice_type == SLICE_TYPE_B) { + LOG1("num_ref_idx_active_override_flag : %d\n", num_ref_idx_active_override_flag); + + LOG2("num_ref_idx_l0_active : %d %s\n", num_ref_idx_l0_active, + num_ref_idx_active_override_flag ? "" : "(from PPS)"); + + if (slice_type == SLICE_TYPE_B) { + LOG2("num_ref_idx_l1_active : %d %s\n", num_ref_idx_l1_active, + num_ref_idx_active_override_flag ? "" : "(from PPS)"); + } + + if (pps->lists_modification_present_flag && NumPocTotalCurr > 1) + { + LOG1("ref_pic_list_modification_flag_l0 : %d\n", ref_pic_list_modification_flag_l0); + if (ref_pic_list_modification_flag_l0) { + for (int i=0;iweighted_pred_flag && slice_type == SLICE_TYPE_P) || + (pps->weighted_bipred_flag && slice_type == SLICE_TYPE_B)) + { + LOG1("luma_log2_weight_denom : %d\n", luma_log2_weight_denom); + if (sps->chroma_format_idc != 0) { + LOG1("ChromaLog2WeightDenom : %d\n", ChromaLog2WeightDenom); + } + + for (int l=0;l<=1;l++) + if (l==0 || (l==1 && slice_type == SLICE_TYPE_B)) + { + int num_ref = (l==0 ? + num_ref_idx_l0_active-1 : + num_ref_idx_l1_active-1); + + if (false) { // do not show these flags + for (int i=0;i<=num_ref;i++) { + LOG3("luma_weight_flag_l%d[%d] : %d\n",l,i,luma_weight_flag[l][i]); + } + + if (sps->chroma_format_idc != 0) { + for (int i=0;i<=num_ref;i++) { + LOG3("chroma_weight_flag_l%d[%d] : %d\n",l,i,chroma_weight_flag[l][i]); + } + } + } + + for (int i=0;i<=num_ref;i++) { + LOG3("LumaWeight_L%d[%d] : %d\n",l,i,LumaWeight[l][i]); + LOG3("luma_offset_l%d[%d] : %d\n",l,i,luma_offset[l][i]); + + for (int j=0;j<2;j++) { + LOG4("ChromaWeight_L%d[%d][%d] : %d\n",l,i,j,ChromaWeight[l][i][j]); + LOG4("ChromaOffset_L%d[%d][%d] : %d\n",l,i,j,ChromaOffset[l][i][j]); + } + } + } + } + + LOG1("five_minus_max_num_merge_cand : %d\n", five_minus_max_num_merge_cand); + } + + + LOG1("slice_qp_delta : %d\n", slice_qp_delta); + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + LOG1("slice_cb_qp_offset : %d\n", slice_cb_qp_offset); + LOG1("slice_cr_qp_offset : %d\n", slice_cr_qp_offset); + } + + if (pps->deblocking_filter_override_enabled_flag) { + LOG1("deblocking_filter_override_flag : %d\n", deblocking_filter_override_flag); + } + + LOG2("slice_deblocking_filter_disabled_flag : %d %s\n", + slice_deblocking_filter_disabled_flag, + (deblocking_filter_override_flag ? "(override)" : "(from pps)")); + + if (deblocking_filter_override_flag) { + + if (!slice_deblocking_filter_disabled_flag) { + LOG1("slice_beta_offset : %d\n", slice_beta_offset); + LOG1("slice_tc_offset : %d\n", slice_tc_offset); + } + } + + if (pps->pps_loop_filter_across_slices_enabled_flag && + (slice_sao_luma_flag || slice_sao_chroma_flag || + !slice_deblocking_filter_disabled_flag)) { + LOG1("slice_loop_filter_across_slices_enabled_flag : %d\n", + slice_loop_filter_across_slices_enabled_flag); + } + } + + if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag) { + LOG1("num_entry_point_offsets : %d\n", num_entry_point_offsets); + + if (num_entry_point_offsets > 0) { + LOG1("offset_len : %d\n", offset_len); + + for (int i=0; ishdr->SliceQPY; + const int initType = tctx->shdr->initType; + assert(initType >= 0 && initType <= 2); + + tctx->ctx_model.init(initType, QPY); + + for (int i=0;i<4;i++) { + tctx->StatCoeff[i] = 0; + } +} + + + +static int decode_transform_skip_flag(thread_context* tctx, int cIdx) +{ + const int context = (cIdx==0) ? 0 : 1; + + logtrace(LogSlice,"# transform_skip_flag (context=%d)\n",context); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_TRANSFORM_SKIP_FLAG+context]); + + logtrace(LogSymbols,"$1 transform_skip_flag=%d\n",bit); + + return bit; +} + + +static int decode_sao_merge_flag(thread_context* tctx) +{ + logtrace(LogSlice,"# sao_merge_left/up_flag\n"); + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_SAO_MERGE_FLAG]); + + logtrace(LogSymbols,"$1 sao_merge_flag=%d\n",bit); + + return bit; +} + + + +static int decode_sao_type_idx(thread_context* tctx) +{ + logtrace(LogSlice,"# sao_type_idx_luma/chroma\n"); + + int bit0 = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_SAO_TYPE_IDX]); + + if (bit0==0) { + logtrace(LogSymbols,"$1 sao_type_idx=%d\n",0); + return 0; + } + else { + int bit1 = decode_CABAC_bypass(&tctx->cabac_decoder); + if (bit1==0) { + logtrace(LogSymbols,"$1 sao_type_idx=%d\n",1); + return 1; + } + else { + logtrace(LogSymbols,"$1 sao_type_idx=%d\n",2); + return 2; + } + } +} + + +static int decode_sao_offset_abs(thread_context* tctx, int bitDepth) +{ + logtrace(LogSlice,"# sao_offset_abs\n"); + int cMax = (1<<(libde265_min(bitDepth,10)-5))-1; + int value = decode_CABAC_TU_bypass(&tctx->cabac_decoder, cMax); + logtrace(LogSymbols,"$1 sao_offset_abs=%d\n",value); + return value; +} + + +static int decode_sao_class(thread_context* tctx) +{ + logtrace(LogSlice,"# sao_class\n"); + int value = decode_CABAC_FL_bypass(&tctx->cabac_decoder, 2); + logtrace(LogSymbols,"$1 sao_class=%d\n",value); + return value; +} + + +static int decode_sao_offset_sign(thread_context* tctx) +{ + logtrace(LogSlice,"# sao_offset_sign\n"); + int value = decode_CABAC_bypass(&tctx->cabac_decoder); + logtrace(LogSymbols,"$1 sao_offset_sign=%d\n",value); + return value; +} + + +static int decode_sao_band_position(thread_context* tctx) +{ + logtrace(LogSlice,"# sao_band_position\n"); + int value = decode_CABAC_FL_bypass(&tctx->cabac_decoder,5); + logtrace(LogSymbols,"$1 sao_band_position=%d\n",value); + return value; +} + + +static int decode_transquant_bypass_flag(thread_context* tctx) +{ + logtrace(LogSlice,"# cu_transquant_bypass_enable_flag\n"); + int value = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_CU_TRANSQUANT_BYPASS_FLAG]); + logtrace(LogSymbols,"$1 transquant_bypass_flag=%d\n",value); + return value; +} + + +#include +#include + +static int decode_split_cu_flag(thread_context* tctx, + int x0, int y0, int ctDepth) +{ + // check if neighbors are available + + int availableL = check_CTB_available(tctx->img, x0,y0, x0-1,y0); + int availableA = check_CTB_available(tctx->img, x0,y0, x0,y0-1); + + int condL = 0; + int condA = 0; + + if (availableL && tctx->img->get_ctDepth(x0-1,y0) > ctDepth) condL=1; + if (availableA && tctx->img->get_ctDepth(x0,y0-1) > ctDepth) condA=1; + + int contextOffset = condL + condA; + int context = contextOffset; + + // decode bit + + logtrace(LogSlice,"# split_cu_flag context=%d R=%x\n", context, tctx->cabac_decoder.range); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_SPLIT_CU_FLAG + context]); + + logtrace(LogSlice,"> split_cu_flag R=%x, ctx=%d, bit=%d\n", tctx->cabac_decoder.range,context,bit); + + logtrace(LogSymbols,"$1 split_cu_flag=%d\n",bit); + + return bit; +} + + +static int decode_cu_skip_flag(thread_context* tctx, + int x0, int y0, int ctDepth) +{ + decoder_context* ctx = tctx->decctx; + + // check if neighbors are available + + int availableL = check_CTB_available(tctx->img, x0,y0, x0-1,y0); + int availableA = check_CTB_available(tctx->img, x0,y0, x0,y0-1); + + int condL = 0; + int condA = 0; + + if (availableL && tctx->img->get_cu_skip_flag(x0-1,y0)) condL=1; + if (availableA && tctx->img->get_cu_skip_flag(x0,y0-1)) condA=1; + + int contextOffset = condL + condA; + int context = contextOffset; + + // decode bit + + logtrace(LogSlice,"# cu_skip_flag context=%d R=%x\n", context, tctx->cabac_decoder.range); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_CU_SKIP_FLAG + context]); + + logtrace(LogSlice,"> cu_skip_flag R=%x, ctx=%d, bit=%d\n", tctx->cabac_decoder.range,context,bit); + + logtrace(LogSymbols,"$1 cu_skip_flag=%d\n",bit); + + return bit; +} + + +static enum PartMode decode_part_mode(thread_context* tctx, + enum PredMode pred_mode, int cLog2CbSize) +{ + de265_image* img = tctx->img; + + if (pred_mode == MODE_INTRA) { + logtrace(LogSlice,"# part_mode (INTRA)\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE]); + + logtrace(LogSlice,"> %s\n",bit ? "2Nx2N" : "NxN"); + + logtrace(LogSymbols,"$1 part_mode=%d\n",bit ? PART_2Nx2N : PART_NxN); + + return bit ? PART_2Nx2N : PART_NxN; + } + else { + const seq_parameter_set& sps = img->get_sps(); + + int bit0 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+0]); + if (bit0) { logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2Nx2N); return PART_2Nx2N; } + + // CHECK_ME: I optimize code and fix bug here, need more VERIFY! + int bit1 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+1]); + if (cLog2CbSize > sps.Log2MinCbSizeY) { + if (!sps.amp_enabled_flag) { + logtrace(LogSymbols,"$1 part_mode=%d\n",bit1 ? PART_2NxN : PART_Nx2N); + return bit1 ? PART_2NxN : PART_Nx2N; + } + else { + int bit3 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+3]); + if (bit3) { + logtrace(LogSymbols,"$1 part_mode=%d\n",bit1 ? PART_2NxN : PART_Nx2N); + return bit1 ? PART_2NxN : PART_Nx2N; + } + + int bit4 = decode_CABAC_bypass(&tctx->cabac_decoder); + if ( bit1 && bit4) { + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2NxnD); + return PART_2NxnD; + } + if ( bit1 && !bit4) { + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2NxnU); + return PART_2NxnU; + } + if (!bit1 && !bit4) { + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_nLx2N); + return PART_nLx2N; + } + if (!bit1 && bit4) { + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_nRx2N); + return PART_nRx2N; + } + } + } + else { + // TODO, we could save one if here when first decoding the next bin and then + // checkcLog2CbSize==3 when it is '0' + + if (bit1) { + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_2NxN); + return PART_2NxN; + } + + if (cLog2CbSize==3) { + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_Nx2N); + return PART_Nx2N; + } + else { + int bit2 = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PART_MODE+2]); + logtrace(LogSymbols,"$1 part_mode=%d\n",PART_NxN-bit2); + return (enum PartMode)((int)PART_NxN - bit2)/*bit2 ? PART_Nx2N : PART_NxN*/; + } + } + } + + assert(false); // should never be reached + return PART_2Nx2N; +} + + +static inline int decode_prev_intra_luma_pred_flag(thread_context* tctx) +{ + logtrace(LogSlice,"# prev_intra_luma_pred_flag\n"); + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_PREV_INTRA_LUMA_PRED_FLAG]); + logtrace(LogSymbols,"$1 prev_intra_luma_pred_flag=%d\n",bit); + return bit; +} + + +static inline int decode_mpm_idx(thread_context* tctx) +{ + logtrace(LogSlice,"# mpm_idx (TU:2)\n"); + int mpm = decode_CABAC_TU_bypass(&tctx->cabac_decoder, 2); + logtrace(LogSlice,"> mpm_idx = %d\n",mpm); + logtrace(LogSymbols,"$1 mpm_idx=%d\n",mpm); + return mpm; +} + + +static inline int decode_rem_intra_luma_pred_mode(thread_context* tctx) +{ + logtrace(LogSlice,"# rem_intra_luma_pred_mode (5 bits)\n"); + int value = decode_CABAC_FL_bypass(&tctx->cabac_decoder, 5); + logtrace(LogSymbols,"$1 rem_intra_luma_pred_mode=%d\n",value); + return value; +} + + +static int decode_intra_chroma_pred_mode(thread_context* tctx) +{ + logtrace(LogSlice,"# intra_chroma_pred_mode\n"); + + int prefix = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_INTRA_CHROMA_PRED_MODE]); + + int mode; + if (prefix==0) { + mode=4; + } + else { + mode = decode_CABAC_FL_bypass(&tctx->cabac_decoder, 2); + } + + logtrace(LogSlice,"> intra_chroma_pred_mode = %d\n",mode); + logtrace(LogSymbols,"$1 intra_chroma_pred_mode=%d\n",mode); + + return mode; +} + + +static int decode_split_transform_flag(thread_context* tctx, + int log2TrafoSize) +{ + logtrace(LogSlice,"# split_transform_flag (log2TrafoSize=%d)\n",log2TrafoSize); + + int context = 5-log2TrafoSize; + assert(context >= 0 && context <= 2); + + logtrace(LogSlice,"# context: %d\n",context); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_SPLIT_TRANSFORM_FLAG + context]); + logtrace(LogSymbols,"$1 split_transform_flag=%d\n",bit); + return bit; +} + + +static int decode_cbf_chroma(thread_context* tctx, + int trafoDepth) +{ + logtrace(LogSlice,"# cbf_chroma\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_CBF_CHROMA + trafoDepth]); + + logtrace(LogSymbols,"$1 cbf_chroma=%d\n",bit); + return bit; +} + + +static int decode_cbf_luma(thread_context* tctx, + int trafoDepth) +{ + logtrace(LogSlice,"# cbf_luma\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &tctx->ctx_model[CONTEXT_MODEL_CBF_LUMA + (trafoDepth==0)]); + + logtrace(LogSlice,"> cbf_luma = %d\n",bit); + + logtrace(LogSymbols,"$1 cbf_luma=%d\n",bit); + return bit; +} + + +static inline int decode_coded_sub_block_flag(thread_context* tctx, + int cIdx, + uint8_t coded_sub_block_neighbors) +{ + logtrace(LogSlice,"# coded_sub_block_flag\n"); + + // tricky computation of csbfCtx + int csbfCtx = ((coded_sub_block_neighbors & 1) | // right neighbor set or + (coded_sub_block_neighbors >> 1)); // bottom neighbor set -> csbfCtx=1 + + int ctxIdxInc = csbfCtx; + if (cIdx!=0) { + ctxIdxInc += 2; + } + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_CODED_SUB_BLOCK_FLAG + ctxIdxInc]); + + logtrace(LogSymbols,"$1 coded_sub_block_flag=%d\n",bit); + return bit; +} + + +static int decode_cu_qp_delta_abs(thread_context* tctx) +{ + logtrace(LogSlice,"# cu_qp_delta_abs\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_CU_QP_DELTA_ABS + 0]); + if (bit==0) { + logtrace(LogSymbols,"$1 cu_qp_delta_abs=%d\n",0); + return 0; + } + + int prefix=1; + for (int i=0;i<4;i++) { + bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_CU_QP_DELTA_ABS + 1]); + if (bit==0) { break; } + else { prefix++; } + } + + if (prefix==5) { + int value = decode_CABAC_EGk_bypass(&tctx->cabac_decoder, 0); + logtrace(LogSymbols,"$1 cu_qp_delta_abs=%d\n",value+5); + return value + 5; + } + else { + logtrace(LogSymbols,"$1 cu_qp_delta_abs=%d\n",prefix); + return prefix; + } +} + + +static int decode_last_significant_coeff_prefix(thread_context* tctx, + int log2TrafoSize, + int cIdx, + context_model* model) +{ + logtrace(LogSlice,"# last_significant_coeff_prefix log2TrafoSize:%d cIdx:%d\n",log2TrafoSize,cIdx); + + int cMax = (log2TrafoSize<<1)-1; + + int ctxOffset, ctxShift; + if (cIdx==0) { + ctxOffset = 3*(log2TrafoSize-2) + ((log2TrafoSize-1)>>2); + ctxShift = (log2TrafoSize+1)>>2; + } + else { + ctxOffset = 15; + ctxShift = log2TrafoSize-2; + } + + int binIdx; + int value = cMax; + for (binIdx=0;binIdx> ctxShift); + + logtrace(LogSlice,"context: %d+%d\n",ctxOffset,ctxIdxInc); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, &model[ctxOffset + ctxIdxInc]); + if (bit==0) { + value=binIdx; + break; + } + } + + logtrace(LogSlice,"> last_significant_coeff_prefix: %d\n", value); + + return value; +} + + +static const uint8_t ctxIdxMap[16] = { + 0,1,4,5, + 2,3,4,5, + 6,6,8,8, + 7,7,8,99 +}; + +uint8_t* ctxIdxLookup[4 /* 4-log2-32 */][2 /* !!cIdx */][2 /* !!scanIdx */][4 /* prevCsbf */]; + +bool alloc_and_init_significant_coeff_ctxIdx_lookupTable() +{ + int tableSize = 4*4*(2) + 8*8*(2*2*4) + 16*16*(2*4) + 32*32*(2*4); + + uint8_t* p = (uint8_t*)malloc(tableSize); + if (p==NULL) { + return false; + } + + memset(p,0xFF,tableSize); // just for debugging + + + // --- Set pointers to memory areas. Note that some parameters share the same memory. --- + + // 4x4 + + for (int cIdx=0;cIdx<2;cIdx++) { + for (int scanIdx=0;scanIdx<2;scanIdx++) + for (int prevCsbf=0;prevCsbf<4;prevCsbf++) + ctxIdxLookup[0][cIdx][scanIdx][prevCsbf] = p; + + p += 4*4; + } + + // 8x8 + + for (int cIdx=0;cIdx<2;cIdx++) + for (int scanIdx=0;scanIdx<2;scanIdx++) + for (int prevCsbf=0;prevCsbf<4;prevCsbf++) { + ctxIdxLookup[1][cIdx][scanIdx][prevCsbf] = p; + p += 8*8; + } + + // 16x16 + + for (int cIdx=0;cIdx<2;cIdx++) + for (int prevCsbf=0;prevCsbf<4;prevCsbf++) { + for (int scanIdx=0;scanIdx<2;scanIdx++) { + ctxIdxLookup[2][cIdx][scanIdx][prevCsbf] = p; + } + + p += 16*16; + } + + // 32x32 + + for (int cIdx=0;cIdx<2;cIdx++) + for (int prevCsbf=0;prevCsbf<4;prevCsbf++) { + for (int scanIdx=0;scanIdx<2;scanIdx++) { + ctxIdxLookup[3][cIdx][scanIdx][prevCsbf] = p; + } + + p += 32*32; + } + + + // --- precompute ctxIdx tables --- + + for (int log2w=2; log2w<=5 ; log2w++) + for (int cIdx=0;cIdx<2;cIdx++) + for (int scanIdx=0;scanIdx<2;scanIdx++) + for (int prevCsbf=0;prevCsbf<4;prevCsbf++) + { + for (int yC=0;yC<(1<>2; + + int sigCtx; + + // if log2TrafoSize==2 + if (sbWidth==1) { + sigCtx = ctxIdxMap[(yC<<2) + xC]; + } + else if (xC+yC==0) { + sigCtx = 0; + } + else { + int xS = xC>>2; + int yS = yC>>2; + /* + int prevCsbf = 0; + + if (xS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+1 +yS*sbWidth]; } + if (yS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+(1+yS)*sbWidth]<<1; } + */ + int xP = xC & 3; + int yP = yC & 3; + + //logtrace(LogSlice,"posInSubset: %d,%d\n",xP,yP); + //logtrace(LogSlice,"prevCsbf: %d\n",prevCsbf); + + switch (prevCsbf) { + case 0: + sigCtx = (xP+yP>=3) ? 0 : (xP+yP>0) ? 1 : 2; + break; + case 1: + sigCtx = (yP==0) ? 2 : (yP==1) ? 1 : 0; + break; + case 2: + sigCtx = (xP==0) ? 2 : (xP==1) ? 1 : 0; + break; + default: + sigCtx = 2; + break; + } + + //logtrace(LogSlice,"a) sigCtx=%d\n",sigCtx); + + if (cIdx==0) { + if (xS+yS > 0) sigCtx+=3; + + //logtrace(LogSlice,"b) sigCtx=%d\n",sigCtx); + + // if log2TrafoSize==3 + if (sbWidth==2) { // 8x8 block + sigCtx += (scanIdx==0) ? 9 : 15; + } else { + sigCtx += 21; + } + + //logtrace(LogSlice,"c) sigCtx=%d\n",sigCtx); + } + else { + // if log2TrafoSize==3 + if (sbWidth==2) { // 8x8 block + sigCtx+=9; + } + else { + sigCtx+=12; + } + } + + } + + int ctxIdxInc; + if (cIdx==0) { ctxIdxInc=sigCtx; } + else { ctxIdxInc=27+sigCtx; } + + if (ctxIdxLookup[log2w-2][cIdx][scanIdx][prevCsbf][xC+(yC<>4]; + int x0 = S.x<<2; + int y0 = S.y<<2; + + int subX = ScanOrderPos[s & 0xF].x; + int subY = ScanOrderPos[s & 0xF].y; + int xC = x0 + subX; + int yC = y0 + subY; + + + int w = 1<>2; + + int sigCtx; + + // if log2TrafoSize==2 + if (sbWidth==1) { + sigCtx = ctxIdxMap[(yC<<2) + xC]; + } + else if (xC+yC==0) { + sigCtx = 0; + } + else { + int xS = xC>>2; + int yS = yC>>2; + /* + int prevCsbf = 0; + + if (xS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+1 +yS*sbWidth]; } + if (yS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+(1+yS)*sbWidth]<<1; } + */ + int xP = xC & 3; + int yP = yC & 3; + + logtrace(LogSlice,"posInSubset: %d,%d\n",xP,yP); + logtrace(LogSlice,"prevCsbf: %d\n",prevCsbf); + + //printf("%d | %d %d\n",prevCsbf,xP,yP); + + switch (prevCsbf) { + case 0: + //sigCtx = (xP+yP==0) ? 2 : (xP+yP<3) ? 1 : 0; + sigCtx = (xP+yP>=3) ? 0 : (xP+yP>0) ? 1 : 2; + break; + case 1: + sigCtx = (yP==0) ? 2 : (yP==1) ? 1 : 0; + break; + case 2: + sigCtx = (xP==0) ? 2 : (xP==1) ? 1 : 0; + break; + default: + sigCtx = 2; + break; + } + + logtrace(LogSlice,"a) sigCtx=%d\n",sigCtx); + + if (cIdx==0) { + if (xS+yS > 0) sigCtx+=3; + + logtrace(LogSlice,"b) sigCtx=%d\n",sigCtx); + + // if log2TrafoSize==3 + if (sbWidth==2) { // 8x8 block + sigCtx += (scanIdx==0) ? 9 : 15; + } else { + sigCtx += 21; + } + + logtrace(LogSlice,"c) sigCtx=%d\n",sigCtx); + } + else { + // if log2TrafoSize==3 + if (sbWidth==2) { // 8x8 block + sigCtx+=9; + } + else { + sigCtx+=12; + } + } + } + + int ctxIdxInc; + if (cIdx==0) { ctxIdxInc=sigCtx; } + else { ctxIdxInc=27+sigCtx; } + + + ctxIdxLookup[log2w-2][cIdx][scanIdx][prevCsbf][xC+(yC<>2; + int yS = yC>>2; + int prevCsbf = 0; + if (xS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+1 +yS*sbWidth]; } + if (yS < sbWidth-1) { prevCsbf += coded_sub_block_flag[xS+(1+yS)*sbWidth]<<1; } + + int xP = xC & 3; + int yP = yC & 3; + + logtrace(LogSlice,"posInSubset: %d,%d\n",xP,yP); + logtrace(LogSlice,"prevCsbf: %d\n",prevCsbf); + + //printf("%d | %d %d\n",prevCsbf,xP,yP); + + switch (prevCsbf) { + case 0: + //sigCtx = (xP+yP==0) ? 2 : (xP+yP<3) ? 1 : 0; + sigCtx = (xP+yP>=3) ? 0 : (xP+yP>0) ? 1 : 2; + break; + case 1: + sigCtx = (yP==0) ? 2 : (yP==1) ? 1 : 0; + break; + case 2: + sigCtx = (xP==0) ? 2 : (xP==1) ? 1 : 0; + break; + default: + sigCtx = 2; + break; + } + + logtrace(LogSlice,"a) sigCtx=%d\n",sigCtx); + + if (cIdx==0) { + if (xS+yS > 0) sigCtx+=3; + + logtrace(LogSlice,"b) sigCtx=%d\n",sigCtx); + + // if log2TrafoSize==3 + if (sbWidth==2) { + sigCtx += (scanIdx==0) ? 9 : 15; + } else { + sigCtx += 21; + } + + logtrace(LogSlice,"c) sigCtx=%d\n",sigCtx); + } + else { + // if log2TrafoSize==3 + if (sbWidth==2) { + sigCtx+=9; + } + else { + sigCtx+=12; + } + } + } + + int ctxIdxInc; + if (cIdx==0) { ctxIdxInc=sigCtx; } + else { ctxIdxInc=27+sigCtx; } + + int context = tctx->shdr->initType*42 + ctxIdxInc; + logtrace(LogSlice,"context: %d\n",context); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG + context]); + return bit; +} +#endif + + + +static inline int decode_significant_coeff_flag_lookup(thread_context* tctx, + uint8_t ctxIdxInc) +{ + logtrace(LogSlice,"# significant_coeff_flag\n"); + logtrace(LogSlice,"context: %d\n",ctxIdxInc); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG + ctxIdxInc]); + + logtrace(LogSymbols,"$1 significant_coeff_flag=%d\n",bit); + + return bit; +} + + + + + +static inline int decode_coeff_abs_level_greater1(thread_context* tctx, + int cIdx, int i, + bool firstCoeffInSubblock, + bool firstSubblock, + int lastSubblock_greater1Ctx, + int* lastInvocation_greater1Ctx, + int* lastInvocation_coeff_abs_level_greater1_flag, + int* lastInvocation_ctxSet, int c1) +{ + logtrace(LogSlice,"# coeff_abs_level_greater1\n"); + + logtrace(LogSlice," cIdx:%d i:%d firstCoeffInSB:%d firstSB:%d lastSB>1:%d last>1Ctx:%d lastLev>1:%d lastCtxSet:%d\n", cIdx,i,firstCoeffInSubblock,firstSubblock,lastSubblock_greater1Ctx, + *lastInvocation_greater1Ctx, + *lastInvocation_coeff_abs_level_greater1_flag, + *lastInvocation_ctxSet); + + int lastGreater1Ctx; + int greater1Ctx; + int ctxSet; + + logtrace(LogSlice,"c1: %d\n",c1); + + if (firstCoeffInSubblock) { + // block with real DC -> ctx 0 + if (i==0 || cIdx>0) { ctxSet=0; } + else { ctxSet=2; } + + if (firstSubblock) { lastGreater1Ctx=1; } + else { lastGreater1Ctx = lastSubblock_greater1Ctx; } + + if (lastGreater1Ctx==0) { ctxSet++; } + + logtrace(LogSlice,"ctxSet: %d\n",ctxSet); + + greater1Ctx=1; + } + else { // !firstCoeffInSubblock + ctxSet = *lastInvocation_ctxSet; + logtrace(LogSlice,"ctxSet (old): %d\n",ctxSet); + + greater1Ctx = *lastInvocation_greater1Ctx; + if (greater1Ctx>0) { + int lastGreater1Flag=*lastInvocation_coeff_abs_level_greater1_flag; + if (lastGreater1Flag==1) greater1Ctx=0; + else { /*if (greater1Ctx>0)*/ greater1Ctx++; } + } + } + + ctxSet = c1; // use HM algo + + int ctxIdxInc = (ctxSet*4) + (greater1Ctx>=3 ? 3 : greater1Ctx); + + if (cIdx>0) { ctxIdxInc+=16; } + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER1_FLAG + ctxIdxInc]); + + *lastInvocation_greater1Ctx = greater1Ctx; + *lastInvocation_coeff_abs_level_greater1_flag = bit; + *lastInvocation_ctxSet = ctxSet; + + //logtrace(LogSymbols,"$1 coeff_abs_level_greater1=%d\n",bit); + + return bit; +} + + +static int decode_coeff_abs_level_greater2(thread_context* tctx, + int cIdx, // int i,int n, + int ctxSet) +{ + logtrace(LogSlice,"# coeff_abs_level_greater2\n"); + + int ctxIdxInc = ctxSet; + + if (cIdx>0) ctxIdxInc+=4; + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER2_FLAG + ctxIdxInc]); + + logtrace(LogSymbols,"$1 coeff_abs_level_greater2=%d\n",bit); + + return bit; +} + + +#define MAX_PREFIX 64 + +static int decode_coeff_abs_level_remaining(thread_context* tctx, + int cRiceParam) +{ + logtrace(LogSlice,"# decode_coeff_abs_level_remaining\n"); + + int prefix=-1; + int codeword=0; + do { + prefix++; + codeword = decode_CABAC_bypass(&tctx->cabac_decoder); + + if (prefix>MAX_PREFIX) { + return 0; // TODO: error + } + } + while (codeword); + + // prefix = nb. 1 bits + + int value; + + if (prefix <= 3) { + // when code only TR part (level < TRMax) + + codeword = decode_CABAC_FL_bypass(&tctx->cabac_decoder, cRiceParam); + value = (prefix<cabac_decoder, prefix-3+cRiceParam); + value = (((1<<(prefix-3))+3-1)<cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_MERGE_FLAG]); + + logtrace(LogSymbols,"$1 merge_flag=%d\n",bit); + + return bit; +} + + +static int decode_merge_idx(thread_context* tctx) +{ + logtrace(LogSlice,"# merge_idx\n"); + + if (tctx->shdr->MaxNumMergeCand <= 1) { + logtrace(LogSymbols,"$1 merge_idx=%d\n",0); + return 0; + } + + // TU coding, first bin is CABAC, remaining are bypass. + // cMax = MaxNumMergeCand-1 + + int idx = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_MERGE_IDX]); + + if (idx==0) { + // nothing + } + else { + idx=1; + + while (idxshdr->MaxNumMergeCand-1) { + if (decode_CABAC_bypass(&tctx->cabac_decoder)) { + idx++; + } + else { + break; + } + } + } + + logtrace(LogSlice,"> merge_idx = %d\n",idx); + logtrace(LogSymbols,"$1 merge_idx=%d\n",idx); + + return idx; +} + + +static int decode_pred_mode_flag(thread_context* tctx) +{ + logtrace(LogSlice,"# pred_mode_flag\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_PRED_MODE_FLAG]); + + logtrace(LogSymbols,"$1 pred_mode=%d\n",bit); + return bit; +} + +static int decode_mvp_lx_flag(thread_context* tctx) +{ + logtrace(LogSlice,"# mvp_lx_flag\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_MVP_LX_FLAG]); + + logtrace(LogSymbols,"$1 mvp_lx_flag=%d\n",bit); + return bit; +} + +static int decode_rqt_root_cbf(thread_context* tctx) +{ + logtrace(LogSlice,"# rqt_root_cbf\n"); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_RQT_ROOT_CBF]); + + logtrace(LogSymbols,"$1 rqt_root_cbf=%d\n",bit); + return bit; +} + +static int decode_ref_idx_lX(thread_context* tctx, int numRefIdxLXActive) +{ + logtrace(LogSlice,"# ref_idx_lX\n"); + + int cMax = numRefIdxLXActive-1; + + if (cMax==0) { + logtrace(LogSlice,"> ref_idx = 0 (cMax==0)\n"); + return 0; + } // do check for single reference frame here + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_REF_IDX_LX + 0]); + + int idx=0; + + while (bit) { + idx++; + if (idx==cMax) { break; } + + if (idx==1) { + bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_REF_IDX_LX + 1]); + } + else { + bit = decode_CABAC_bypass(&tctx->cabac_decoder); + } + } + + logtrace(LogSlice,"> ref_idx = %d\n",idx); + + logtrace(LogSymbols,"$1 ref_idx_lX=%d\n",idx); + return idx; +} + + +static enum InterPredIdc decode_inter_pred_idc(thread_context* tctx, + int x0, int y0, + int nPbW, int nPbH, + int ctDepth) +{ + logtrace(LogSlice,"# inter_pred_idc\n"); + + int value; + + context_model* model = &tctx->ctx_model[CONTEXT_MODEL_INTER_PRED_IDC]; + + if (nPbW+nPbH==12) { + value = decode_CABAC_bit(&tctx->cabac_decoder, + &model[4]); + } + else { + int bit0 = decode_CABAC_bit(&tctx->cabac_decoder, + &model[ctDepth]); + if (bit0==0) { + value = decode_CABAC_bit(&tctx->cabac_decoder, + &model[4]); + } + else { + value = 2; + } + } + + logtrace(LogSlice,"> inter_pred_idc = %d (%s)\n",value, + value==0 ? "L0" : (value==1 ? "L1" : "BI")); + + logtrace(LogSymbols,"$1 decode_inter_pred_idx=%d\n",value+1); + + return (enum InterPredIdc) (value+1); +} + + +static int decode_explicit_rdpcm_flag(thread_context* tctx,int cIdx) +{ + context_model* model = &tctx->ctx_model[CONTEXT_MODEL_RDPCM_FLAG]; + int value = decode_CABAC_bit(&tctx->cabac_decoder, &model[cIdx ? 1 : 0]); + return value; +} + + +static int decode_explicit_rdpcm_dir(thread_context* tctx,int cIdx) +{ + context_model* model = &tctx->ctx_model[CONTEXT_MODEL_RDPCM_DIR]; + int value = decode_CABAC_bit(&tctx->cabac_decoder, &model[cIdx ? 1 : 0]); + return value; +} + + + +/* Take CtbAddrInTS and compute + -> CtbAddrInRS, CtbX, CtbY + */ +bool setCtbAddrFromTS(thread_context* tctx) +{ + const seq_parameter_set& sps = tctx->img->get_sps(); + + if (tctx->CtbAddrInTS < sps.PicSizeInCtbsY) { + tctx->CtbAddrInRS = tctx->img->get_pps().CtbAddrTStoRS[tctx->CtbAddrInTS]; + + tctx->CtbX = tctx->CtbAddrInRS % sps.PicWidthInCtbsY; + tctx->CtbY = tctx->CtbAddrInRS / sps.PicWidthInCtbsY; + return false; + } + else { + tctx->CtbAddrInRS = sps.PicSizeInCtbsY; + + tctx->CtbX = tctx->CtbAddrInRS % sps.PicWidthInCtbsY; + tctx->CtbY = tctx->CtbAddrInRS / sps.PicWidthInCtbsY; + return true; + } +} + +// returns true when we reached the end of the image (ctbAddr==picSizeInCtbsY) +bool advanceCtbAddr(thread_context* tctx) +{ + tctx->CtbAddrInTS++; + + return setCtbAddrFromTS(tctx); +} + + +void read_sao(thread_context* tctx, int xCtb,int yCtb, + int CtbAddrInSliceSeg) +{ + slice_segment_header* shdr = tctx->shdr; + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + const pic_parameter_set& pps = img->get_pps(); + + logtrace(LogSlice,"# read_sao(%d,%d)\n",xCtb,yCtb); + + sao_info saoinfo; + memset(&saoinfo,0,sizeof(sao_info)); + logtrace(LogSlice,"sizeof saoinfo: %d\n",sizeof(sao_info)); + + + char sao_merge_left_flag = 0; + char sao_merge_up_flag = 0; + + if (xCtb>0) { + //char leftCtbInSliceSeg = (CtbAddrInSliceSeg>0); + char leftCtbInSliceSeg = (tctx->CtbAddrInRS > shdr->SliceAddrRS); + char leftCtbInTile = (pps.TileIdRS[xCtb + yCtb * sps.PicWidthInCtbsY] == + pps.TileIdRS[xCtb-1 + yCtb * sps.PicWidthInCtbsY]); + + if (leftCtbInSliceSeg && leftCtbInTile) { + sao_merge_left_flag = decode_sao_merge_flag(tctx); + logtrace(LogSlice,"sao_merge_left_flag: %d\n",sao_merge_left_flag); + } + } + + if (yCtb>0 && sao_merge_left_flag==0) { + logtrace(LogSlice,"CtbAddrInRS:%d PicWidthInCtbsY:%d slice_segment_address:%d\n", + tctx->CtbAddrInRS, + sps.PicWidthInCtbsY, + shdr->slice_segment_address); + char upCtbInSliceSeg = (tctx->CtbAddrInRS - sps.PicWidthInCtbsY) >= shdr->SliceAddrRS; + char upCtbInTile = (pps.TileIdRS[xCtb + yCtb * sps.PicWidthInCtbsY] == + pps.TileIdRS[xCtb + (yCtb-1) * sps.PicWidthInCtbsY]); + + if (upCtbInSliceSeg && upCtbInTile) { + sao_merge_up_flag = decode_sao_merge_flag(tctx); + logtrace(LogSlice,"sao_merge_up_flag: %d\n",sao_merge_up_flag); + } + } + + if (!sao_merge_up_flag && !sao_merge_left_flag) { + int nChroma = 3; + if (sps.ChromaArrayType == CHROMA_MONO) nChroma=1; + + for (int cIdx=0; cIdxslice_sao_luma_flag && cIdx==0) || + (shdr->slice_sao_chroma_flag && cIdx>0)) { + + uint8_t SaoTypeIdx = 0; + + if (cIdx==0) { + char sao_type_idx_luma = decode_sao_type_idx(tctx); + logtrace(LogSlice,"sao_type_idx_luma: %d\n", sao_type_idx_luma); + saoinfo.SaoTypeIdx = SaoTypeIdx = sao_type_idx_luma; + } + else if (cIdx==1) { + char sao_type_idx_chroma = decode_sao_type_idx(tctx); + logtrace(LogSlice,"sao_type_idx_chroma: %d\n", sao_type_idx_chroma); + SaoTypeIdx = sao_type_idx_chroma; + saoinfo.SaoTypeIdx |= SaoTypeIdx<<(2*1); + saoinfo.SaoTypeIdx |= SaoTypeIdx<<(2*2); // set for both chroma components + } + else { + // SaoTypeIdx = 0 + + SaoTypeIdx = (saoinfo.SaoTypeIdx >> (2*cIdx)) & 0x3; + } + + if (SaoTypeIdx != 0) { + for (int i=0;i<4;i++) { + saoinfo.saoOffsetVal[cIdx][i] = decode_sao_offset_abs(tctx, img->get_bit_depth(cIdx)); + logtrace(LogSlice,"saoOffsetVal[%d][%d] = %d\n",cIdx,i, saoinfo.saoOffsetVal[cIdx][i]); + } + + int sign[4]; + if (SaoTypeIdx==1) { + for (int i=0;i<4;i++) { + if (saoinfo.saoOffsetVal[cIdx][i] != 0) { + sign[i] = decode_sao_offset_sign(tctx) ? -1 : 1; + } + else { + sign[i] = 0; // not really required, but compiler warns about uninitialized values + } + } + + saoinfo.sao_band_position[cIdx] = decode_sao_band_position(tctx); + } + else { + uint8_t SaoEoClass = 0; + + sign[0] = sign[1] = 1; + sign[2] = sign[3] = -1; + + if (cIdx==0) { + saoinfo.SaoEoClass = SaoEoClass = decode_sao_class(tctx); + } + else if (cIdx==1) { + SaoEoClass = decode_sao_class(tctx); + saoinfo.SaoEoClass |= SaoEoClass << (2*1); + saoinfo.SaoEoClass |= SaoEoClass << (2*2); + } + + logtrace(LogSlice,"SaoEoClass[%d] = %d\n",cIdx,SaoEoClass); + } + + int log2OffsetScale; + + if (cIdx==0) { + log2OffsetScale = pps.range_extension.log2_sao_offset_scale_luma; + } + else { + log2OffsetScale = pps.range_extension.log2_sao_offset_scale_chroma; + } + + for (int i=0;i<4;i++) { + saoinfo.saoOffsetVal[cIdx][i] = sign[i]*(saoinfo.saoOffsetVal[cIdx][i] << log2OffsetScale); + } + } + } + } + + img->set_sao_info(xCtb,yCtb, &saoinfo); + } + + + if (sao_merge_left_flag) { + img->set_sao_info(xCtb,yCtb, img->get_sao_info(xCtb-1,yCtb)); + } + + if (sao_merge_up_flag) { + img->set_sao_info(xCtb,yCtb, img->get_sao_info(xCtb,yCtb-1)); + } +} + + +void read_coding_tree_unit(thread_context* tctx) +{ + slice_segment_header* shdr = tctx->shdr; + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + + int xCtb = (tctx->CtbAddrInRS % sps.PicWidthInCtbsY); + int yCtb = (tctx->CtbAddrInRS / sps.PicWidthInCtbsY); + int xCtbPixels = xCtb << sps.Log2CtbSizeY; + int yCtbPixels = yCtb << sps.Log2CtbSizeY; + + logtrace(LogSlice,"----- decode CTB %d;%d (%d;%d) POC=%d, SliceAddrRS=%d\n", + xCtbPixels,yCtbPixels, xCtb,yCtb, + tctx->img->PicOrderCntVal, tctx->shdr->SliceAddrRS); + + img->set_SliceAddrRS(xCtb, yCtb, tctx->shdr->SliceAddrRS); + + img->set_SliceHeaderIndex(xCtbPixels,yCtbPixels, shdr->slice_index); + + int CtbAddrInSliceSeg = tctx->CtbAddrInRS - shdr->slice_segment_address; + + if (shdr->slice_sao_luma_flag || shdr->slice_sao_chroma_flag) + { + read_sao(tctx, xCtb,yCtb, CtbAddrInSliceSeg); + } + + read_coding_quadtree(tctx, xCtbPixels, yCtbPixels, sps.Log2CtbSizeY, 0); +} + + +LIBDE265_INLINE static int luma_pos_to_ctbAddrRS(const seq_parameter_set* sps, int x,int y) +{ + int ctbX = x >> sps->Log2CtbSizeY; + int ctbY = y >> sps->Log2CtbSizeY; + + return ctbY * sps->PicWidthInCtbsY + ctbX; +} + + +int check_CTB_available(const de265_image* img, + int xC,int yC, int xN,int yN) +{ + // check whether neighbor is outside of frame + + if (xN < 0 || yN < 0) { return 0; } + if (xN >= img->get_sps().pic_width_in_luma_samples) { return 0; } + if (yN >= img->get_sps().pic_height_in_luma_samples) { return 0; } + + + int current_ctbAddrRS = luma_pos_to_ctbAddrRS(&img->get_sps(), xC,yC); + int neighbor_ctbAddrRS = luma_pos_to_ctbAddrRS(&img->get_sps(), xN,yN); + + // TODO: check if this is correct (6.4.1) + + if (img->get_SliceAddrRS_atCtbRS(current_ctbAddrRS) != + img->get_SliceAddrRS_atCtbRS(neighbor_ctbAddrRS)) { + return 0; + } + + // check if both CTBs are in the same tile. + + if (img->get_pps().TileIdRS[current_ctbAddrRS] != + img->get_pps().TileIdRS[neighbor_ctbAddrRS]) { + return 0; + } + + return 1; +} + + +int residual_coding(thread_context* tctx, + int x0, int y0, // position of TU in frame + int log2TrafoSize, + int cIdx) +{ + logtrace(LogSlice,"- residual_coding x0:%d y0:%d log2TrafoSize:%d cIdx:%d\n",x0,y0,log2TrafoSize,cIdx); + + //slice_segment_header* shdr = tctx->shdr; + + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + const pic_parameter_set& pps = img->get_pps(); + + enum PredMode PredMode = img->get_pred_mode(x0,y0); + + if (cIdx==0) { + img->set_nonzero_coefficient(x0,y0,log2TrafoSize); + } + + + if (pps.transform_skip_enabled_flag && + !tctx->cu_transquant_bypass_flag && + (log2TrafoSize <= pps.Log2MaxTransformSkipSize)) + { + tctx->transform_skip_flag[cIdx] = decode_transform_skip_flag(tctx,cIdx); + } + else + { + tctx->transform_skip_flag[cIdx] = 0; + } + + + tctx->explicit_rdpcm_flag = false; + + if (PredMode == MODE_INTER && sps.range_extension.explicit_rdpcm_enabled_flag && + ( tctx->transform_skip_flag[cIdx] || tctx->cu_transquant_bypass_flag)) + { + tctx->explicit_rdpcm_flag = decode_explicit_rdpcm_flag(tctx,cIdx); + if (tctx->explicit_rdpcm_flag) { + tctx->explicit_rdpcm_dir = decode_explicit_rdpcm_dir(tctx,cIdx); + } + + //printf("EXPLICIT RDPCM %d;%d\n",x0,y0); + } + else + { + tctx->explicit_rdpcm_flag = false; + } + + + + // sbType for persistent_rice_adaptation_enabled_flag + + int sbType = (cIdx==0) ? 2 : 0; + if (tctx->transform_skip_flag[cIdx] || tctx->cu_transquant_bypass_flag) { + sbType++; + } + + + // --- decode position of last coded coefficient --- + + int last_significant_coeff_x_prefix = + decode_last_significant_coeff_prefix(tctx,log2TrafoSize,cIdx, + &tctx->ctx_model[CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_X_PREFIX]); + + int last_significant_coeff_y_prefix = + decode_last_significant_coeff_prefix(tctx,log2TrafoSize,cIdx, + &tctx->ctx_model[CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_Y_PREFIX]); + + + // TODO: we can combine both FL-bypass calls into one, but the gain may be limited... + + int LastSignificantCoeffX; + if (last_significant_coeff_x_prefix > 3) { + int nBits = (last_significant_coeff_x_prefix>>1)-1; + int last_significant_coeff_x_suffix = decode_CABAC_FL_bypass(&tctx->cabac_decoder,nBits); + + LastSignificantCoeffX = + ((2+(last_significant_coeff_x_prefix & 1)) << nBits) + last_significant_coeff_x_suffix; + } + else { + LastSignificantCoeffX = last_significant_coeff_x_prefix; + } + + int LastSignificantCoeffY; + if (last_significant_coeff_y_prefix > 3) { + int nBits = (last_significant_coeff_y_prefix>>1)-1; + int last_significant_coeff_y_suffix = decode_CABAC_FL_bypass(&tctx->cabac_decoder,nBits); + + LastSignificantCoeffY = + ((2+(last_significant_coeff_y_prefix & 1)) << nBits) + last_significant_coeff_y_suffix; + } + else { + LastSignificantCoeffY = last_significant_coeff_y_prefix; + } + + + + // --- determine scanIdx --- + + int scanIdx; + + if (PredMode == MODE_INTRA) { + if (cIdx==0) { + scanIdx = get_intra_scan_idx(log2TrafoSize, img->get_IntraPredMode(x0,y0), cIdx, &sps); + //printf("luma scan idx=%d <- intra mode=%d\n",scanIdx, img->get_IntraPredMode(x0,y0)); + } + else { + scanIdx = get_intra_scan_idx(log2TrafoSize, img->get_IntraPredModeC(x0,y0), cIdx, &sps); + //printf("chroma scan idx=%d <- intra mode=%d chroma:%d trsize:%d\n",scanIdx, + // img->get_IntraPredModeC(x0,y0), sps->chroma_format_idc, 1<nCoeff[cIdx] = 0; + + + // i - subblock index + // n - coefficient index in subblock + + for (int i=lastSubBlock;i>=0;i--) { + position S = ScanOrderSub[i]; + int inferSbDcSigCoeffFlag=0; + + logtrace(LogSlice,"sub block scan idx: %d\n",i); + + + // --- check whether this sub-block is coded --- + + int sub_block_is_coded = 0; + + if ((i0)) { + sub_block_is_coded = decode_coded_sub_block_flag(tctx, cIdx, + coded_sub_block_neighbors[S.x+S.y*sbWidth]); + inferSbDcSigCoeffFlag=1; + } + else if (i==0 || i==lastSubBlock) { + // first (DC) and last sub-block are always coded + // - the first will most probably contain coefficients + // - the last obviously contains the last coded coefficient + + sub_block_is_coded = 1; + } + + if (sub_block_is_coded) { + if (S.x > 0) coded_sub_block_neighbors[S.x-1 + S.y *sbWidth] |= 1; + if (S.y > 0) coded_sub_block_neighbors[S.x + (S.y-1)*sbWidth] |= 2; + } + + + // ----- find significant coefficients in this sub-block ----- + + int16_t coeff_value[16]; + int8_t coeff_scan_pos[16]; + int8_t coeff_sign[16]; + int8_t coeff_has_max_base_level[16]; + int nCoefficients=0; + + + if (sub_block_is_coded) { + int x0 = S.x<<2; + int y0 = S.y<<2; + + int log2w = log2TrafoSize-2; + int prevCsbf = coded_sub_block_neighbors[S.x+S.y*sbWidth]; + uint8_t* ctxIdxMap = ctxIdxLookup[log2w][!!cIdx][!!scanIdx][prevCsbf]; + + logdebug(LogSlice,"log2w:%d cIdx:%d scanIdx:%d prevCsbf:%d\n", + log2w,cIdx,scanIdx,prevCsbf); + + + // set the last coded coefficient in the last subblock + + int last_coeff = (i==lastSubBlock) ? lastScanPos-1 : 15; + + if (i==lastSubBlock) { + coeff_value[nCoefficients] = 1; + coeff_has_max_base_level[nCoefficients] = 1; + coeff_scan_pos[nCoefficients] = lastScanPos; + nCoefficients++; + } + + + // --- decode all coefficients' significant_coeff flags except for the DC coefficient --- + + for (int n= last_coeff ; n>0 ; n--) { + int subX = ScanOrderPos[n].x; + int subY = ScanOrderPos[n].y; + xC = x0 + subX; + yC = y0 + subY; + + + // for all AC coefficients in sub-block, a significant_coeff flag is coded + + int ctxInc; + if (sps.range_extension.transform_skip_context_enabled_flag && + (tctx->cu_transquant_bypass_flag || tctx->transform_skip_flag[cIdx])) { + ctxInc = ( cIdx == 0 ) ? 42 : (16+27); + } + else { + ctxInc = ctxIdxMap[xC+(yC<=0) // last coded coefficient (always set to 1) is not the DC coefficient + { + if (inferSbDcSigCoeffFlag==0) { + // if we cannot infert the DC coefficient, it is coded + + int ctxInc; + if (sps.range_extension.transform_skip_context_enabled_flag && + (tctx->cu_transquant_bypass_flag || tctx->transform_skip_flag[cIdx])) { + ctxInc = ( cIdx == 0 ) ? 42 : (16+27); + } + else { + ctxInc = ctxIdxMap[x0+(y0<0) { ctxSet=0; } + else { ctxSet=2; } + + if (c1==0) { ctxSet++; } + c1=1; + + + // --- decode greater-1 flags --- + + int newLastGreater1ScanPos=-1; + + int lastGreater1Coefficient = libde265_min(8,nCoefficients); + for (int c=0;c0) { + c1++; + } + } + } + + firstSubblock = false; + lastSubblock_greater1Ctx = lastInvocation_greater1Ctx; + + + // --- decode greater-2 flag --- + + if (newLastGreater1ScanPos != -1) { + int flag = decode_coeff_abs_level_greater2(tctx,cIdx, lastInvocation_ctxSet); + coeff_value[newLastGreater1ScanPos] += flag; + coeff_has_max_base_level[newLastGreater1ScanPos] = flag; + } + + + // --- decode coefficient signs --- + + int signHidden; + + + IntraPredMode predModeIntra; + if (cIdx==0) predModeIntra = img->get_IntraPredMode(x0,y0); + else predModeIntra = img->get_IntraPredModeC(x0,y0); + + + if (tctx->cu_transquant_bypass_flag || + (PredMode == MODE_INTRA && + sps.range_extension.implicit_rdpcm_enabled_flag && + tctx->transform_skip_flag[cIdx] && + ( predModeIntra == 10 || predModeIntra == 26 )) || + tctx->explicit_rdpcm_flag) + { + signHidden = 0; + } + else + { + signHidden = (coeff_scan_pos[0]-coeff_scan_pos[nCoefficients-1] > 3); + } + + + for (int n=0;ncabac_decoder); + logtrace(LogSlice,"sign[%d] = %d\n", n, coeff_sign[n]); + } + + // n==nCoefficients-1 + if (!pps.sign_data_hiding_flag || !signHidden) { + coeff_sign[nCoefficients-1] = decode_CABAC_bypass(&tctx->cabac_decoder); + logtrace(LogSlice,"sign[%d] = %d\n", nCoefficients-1, coeff_sign[nCoefficients-1]); + } + else { + coeff_sign[nCoefficients-1] = 0; + } + + + // --- decode coefficient value --- + + int sumAbsLevel=0; + int uiGoRiceParam; + + if (sps.range_extension.persistent_rice_adaptation_enabled_flag==0) { + uiGoRiceParam = 0; + } + else { + uiGoRiceParam = tctx->StatCoeff[sbType]/4; + } + + // printf("initial uiGoRiceParam=%d\n",uiGoRiceParam); + bool firstCoeffWithAbsLevelRemaining = true; + + for (int n=0;n 3*(1<4) uiGoRiceParam=4; + } + } + else { + if (baseLevel + coeff_abs_level_remaining > 3*(1<= (3 << (tctx->StatCoeff[sbType]/4 ))) { + tctx->StatCoeff[sbType]++; + } + else if (2*coeff_abs_level_remaining < (1 << (tctx->StatCoeff[sbType]/4 )) && + tctx->StatCoeff[sbType] > 0) { + tctx->StatCoeff[sbType]--; + } + } + + firstCoeffWithAbsLevelRemaining=false; + } + else { + coeff_abs_level_remaining = 0; + } + + logtrace(LogSlice, "coeff_abs_level_remaining=%d\n",coeff_abs_level_remaining); + + + int16_t currCoeff = baseLevel + coeff_abs_level_remaining; + if (coeff_sign[n]) { + currCoeff = -currCoeff; + } + + if (pps.sign_data_hiding_flag && signHidden) { + sumAbsLevel += baseLevel + coeff_abs_level_remaining; + + if (n==nCoefficients-1 && (sumAbsLevel & 1)) { + currCoeff = -currCoeff; + } + } + + logtrace(LogSlice, "quantized coefficient=%d\n",currCoeff); + +#ifdef DE265_LOG_TRACE + //TransCoeffLevel[yC*CoeffStride + xC] = currCoeff; +#endif + + // put coefficient in list + int p = coeff_scan_pos[n]; + xC = (S.x<<2) + ScanOrderPos[p].x; + yC = (S.y<<2) + ScanOrderPos[p].y; + + tctx->coeffList[cIdx][ tctx->nCoeff[cIdx] ] = currCoeff; + tctx->coeffPos [cIdx][ tctx->nCoeff[cIdx] ] = xC + yC*CoeffStride; + tctx->nCoeff[cIdx]++; + + //printf("%d ",currCoeff); + } // iterate through coefficients in sub-block + + //printf(" (%d;%d)\n",x0,y0); + + } // if nonZero + } // next sub-block + + return DE265_OK; +} + + +static void decode_TU(thread_context* tctx, + int x0,int y0, + int xCUBase,int yCUBase, + int nT, int cIdx, enum PredMode cuPredMode, bool cbf) +{ + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + + int residualDpcm = 0; + + if (cuPredMode == MODE_INTRA) // if intra mode + { + enum IntraPredMode intraPredMode; + + if (cIdx==0) { + intraPredMode = img->get_IntraPredMode(x0,y0); + } + else { + const int SubWidthC = sps.SubWidthC; + const int SubHeightC = sps.SubHeightC; + + intraPredMode = img->get_IntraPredModeC(x0*SubWidthC,y0*SubHeightC); + } + + if (intraPredMode<0 || intraPredMode>=35) { + // TODO: ERROR + intraPredMode = INTRA_DC; + } + + decode_intra_prediction(img, x0,y0, intraPredMode, nT, cIdx); + + + residualDpcm = sps.range_extension.implicit_rdpcm_enabled_flag && + (tctx->cu_transquant_bypass_flag || tctx->transform_skip_flag[cIdx]) && + (intraPredMode == 10 || intraPredMode == 26); + + if (residualDpcm && intraPredMode == 26) + residualDpcm = 2; + } + else // INTER + { + if (tctx->explicit_rdpcm_flag) { + residualDpcm = (tctx->explicit_rdpcm_dir ? 2 : 1); + } + } + + if (cbf) { + scale_coefficients(tctx, x0,y0, xCUBase,yCUBase, nT, cIdx, + tctx->transform_skip_flag[cIdx], cuPredMode==MODE_INTRA, residualDpcm); + } + /* + else if (!cbf && cIdx==0) { + memset(tctx->residual_luma,0,32*32*sizeof(int32_t)); + } + */ + else if (!cbf && cIdx!=0 && tctx->ResScaleVal) { + // --- cross-component-prediction when CBF==0 --- + + tctx->nCoeff[cIdx] = 0; + residualDpcm=0; + + scale_coefficients(tctx, x0,y0, xCUBase,yCUBase, nT, cIdx, + tctx->transform_skip_flag[cIdx], cuPredMode==MODE_INTRA, residualDpcm); + } +} + + +static int decode_log2_res_scale_abs_plus1(thread_context* tctx, int cIdxMinus1) +{ + //const int context = (cIdx==0) ? 0 : 1; + + logtrace(LogSlice,"# log2_res_scale_abs_plus1 (c=%d)\n",cIdxMinus1); + + int value = 0; + int cMax = 4; + for (int binIdx=0;binIdxcabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_LOG2_RES_SCALE_ABS_PLUS1+ctxIdxInc]); + if (!bit) break; + value++; + } + + logtrace(LogSymbols,"$1 log2_res_scale_abs_plus1=%d\n",value); + + return value; +} + + +static int decode_res_scale_sign_flag(thread_context* tctx, int cIdxMinus1) +{ + //const int context = (cIdx==0) ? 0 : 1; + + logtrace(LogSlice,"# res_scale_sign_flag (c=%d)\n",cIdxMinus1); + + int bit = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_RES_SCALE_SIGN_FLAG+cIdxMinus1]); + + logtrace(LogSymbols,"$1 res_scale_sign_flag=%d\n",bit); + + return bit; +} + + +static void read_cross_comp_pred(thread_context* tctx, int cIdxMinus1) +{ + int log2_res_scale_abs_plus1 = decode_log2_res_scale_abs_plus1(tctx,cIdxMinus1); + int ResScaleVal; + + if (log2_res_scale_abs_plus1 != 0) { + int res_scale_sign_flag = decode_res_scale_sign_flag(tctx,cIdxMinus1); + + ResScaleVal = 1 << (log2_res_scale_abs_plus1 - 1); + ResScaleVal *= 1 - 2 * res_scale_sign_flag; + } + else { + ResScaleVal = 0; + } + + tctx->ResScaleVal = ResScaleVal; +} + + +int read_transform_unit(thread_context* tctx, + int x0, int y0, // position of TU in frame + int xBase, int yBase, // position of parent TU in frame + int xCUBase,int yCUBase, // position of CU in frame + int log2TrafoSize, + int trafoDepth, + int blkIdx, + int cbf_luma, int cbf_cb, int cbf_cr) +{ + logtrace(LogSlice,"- read_transform_unit x0:%d y0:%d xBase:%d yBase:%d nT:%d cbf:%d:%d:%d\n", + x0,y0,xBase,yBase, 1<img->get_sps(); + + const int ChromaArrayType = sps.ChromaArrayType; + + int log2TrafoSizeC = (ChromaArrayType==CHROMA_444 ? log2TrafoSize : log2TrafoSize-1); + log2TrafoSizeC = libde265_max(2, log2TrafoSizeC); + + const int cbfLuma = cbf_luma; + const int cbfChroma = cbf_cb | cbf_cr; + + tctx->transform_skip_flag[0]=0; + tctx->transform_skip_flag[1]=0; + tctx->transform_skip_flag[2]=0; + + tctx->explicit_rdpcm_flag = false; + + + enum PredMode cuPredMode = tctx->img->get_pred_mode(x0,y0); + + if (cbfLuma || cbfChroma) + { + bool doDecodeQuantParameters = false; + + if (tctx->img->get_pps().cu_qp_delta_enabled_flag && + !tctx->IsCuQpDeltaCoded) { + + int cu_qp_delta_abs = decode_cu_qp_delta_abs(tctx); + int cu_qp_delta_sign=0; + if (cu_qp_delta_abs) { + cu_qp_delta_sign = decode_CABAC_bypass(&tctx->cabac_decoder); + } + + tctx->IsCuQpDeltaCoded = 1; + tctx->CuQpDelta = cu_qp_delta_abs*(1-2*cu_qp_delta_sign); + + //printf("read cu_qp_delta (%d;%d) = %d\n",x0,y0,tctx->CuQpDelta); + + logtrace(LogSlice,"cu_qp_delta_abs = %d\n",cu_qp_delta_abs); + logtrace(LogSlice,"cu_qp_delta_sign = %d\n",cu_qp_delta_sign); + logtrace(LogSlice,"CuQpDelta = %d\n",tctx->CuQpDelta); + + doDecodeQuantParameters = true; + //decode_quantization_parameters(tctx, x0,y0, xCUBase, yCUBase); + } + + if (tctx->shdr->cu_chroma_qp_offset_enabled_flag && cbfChroma && + !tctx->cu_transquant_bypass_flag && !tctx->IsCuChromaQpOffsetCoded ) { + logtrace(LogSlice,"# cu_chroma_qp_offset_flag\n"); + + int cu_chroma_qp_offset_flag = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_FLAG]); + + + const pic_parameter_set& pps = tctx->img->get_pps(); + + int cu_chroma_qp_offset_idx = 0; + if (cu_chroma_qp_offset_flag && pps.range_extension.chroma_qp_offset_list_len > 1) { + cu_chroma_qp_offset_idx = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_IDX]); + } + + tctx->IsCuChromaQpOffsetCoded = 1; + + if (cu_chroma_qp_offset_flag) { + tctx->CuQpOffsetCb = pps.range_extension.cb_qp_offset_list[ cu_chroma_qp_offset_idx ]; + tctx->CuQpOffsetCr = pps.range_extension.cr_qp_offset_list[ cu_chroma_qp_offset_idx ]; + } + else { + tctx->CuQpOffsetCb = 0; + tctx->CuQpOffsetCr = 0; + } + + doDecodeQuantParameters = true; + //decode_quantization_parameters(tctx, x0,y0, xCUBase, yCUBase); + } + + + if (doDecodeQuantParameters) { + decode_quantization_parameters(tctx, x0,y0, xCUBase, yCUBase); + } + } + + // position of TU in local CU + int xL = x0 - xCUBase; + int yL = y0 - yCUBase; + int nT = 1<ResScaleVal = 0; + + int err; + if (cbf_luma) { + if ((err=residual_coding(tctx,x0,y0, log2TrafoSize,0)) != DE265_OK) return err; + } + + decode_TU(tctx, x0,y0, xCUBase,yCUBase, nT, 0, cuPredMode, cbf_luma); + + + // --- chroma --- + + const int yOffset422 = 1<2 || ChromaArrayType == CHROMA_444) { + // TODO: cross-component prediction + + const bool do_cross_component_prediction = + (tctx->img->get_pps().range_extension.cross_component_prediction_enabled_flag && + cbf_luma && + (cuPredMode == MODE_INTER || tctx->img->is_IntraPredModeC_Mode4(x0,y0))); + + if (do_cross_component_prediction) { + read_cross_comp_pred(tctx, 0); + } + else { + tctx->ResScaleVal = 0; + } + + { + if (cbf_cb & 1) { + if ((err=residual_coding(tctx,x0,y0,log2TrafoSizeC,1)) != DE265_OK) return err; + } + + if (sps.ChromaArrayType != CHROMA_MONO) { + decode_TU(tctx, + x0/SubWidthC,y0/SubHeightC, + xCUBase/SubWidthC,yCUBase/SubHeightC, nTC, 1, cuPredMode, cbf_cb & 1); + } + } + + // 4:2:2 + if (ChromaArrayType == CHROMA_422) { + const int yOffset = 1<ResScaleVal = 0; + } + + { + if (cbf_cr & 1) { + if ((err=residual_coding(tctx,x0,y0,log2TrafoSizeC,2)) != DE265_OK) return err; + } + + if (sps.ChromaArrayType != CHROMA_MONO) { + decode_TU(tctx, + x0/SubWidthC,y0/SubHeightC, + xCUBase/SubWidthC,yCUBase/SubHeightC, + nTC, 2, cuPredMode, cbf_cr & 1); + } + } + + // 4:2:2 + if (ChromaArrayType == CHROMA_422) { + const int yOffset = 1<get_width(0); + int h = img->get_height(0); + + for (int y=0;yget_log2CbSize(x,y)); + } + printf("\n"); + } +} + + +void read_transform_tree(thread_context* tctx, + int x0, int y0, // position of TU in frame + int xBase, int yBase, // position of parent TU in frame + int xCUBase, int yCUBase, // position of CU in frame + int log2TrafoSize, + int trafoDepth, + int blkIdx, + int MaxTrafoDepth, + int IntraSplitFlag, + enum PredMode cuPredMode, + uint8_t parent_cbf_cb,uint8_t parent_cbf_cr) +{ + logtrace(LogSlice,"- read_transform_tree (interleaved) x0:%d y0:%d xBase:%d yBase:%d " + "log2TrafoSize:%d trafoDepth:%d MaxTrafoDepth:%d parent-cbf-cb:%d parent-cbf-cr:%d\n", + x0,y0,xBase,yBase,log2TrafoSize,trafoDepth,MaxTrafoDepth,parent_cbf_cb,parent_cbf_cr); + + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + + int split_transform_flag; + + enum PredMode PredMode = img->get_pred_mode(x0,y0); + assert(PredMode == cuPredMode); + + /* If TrafoSize is larger than maximum size -> split automatically + If TrafoSize is at minimum size -> do not split + If maximum transformation depth is reached -> do not split + If intra-prediction is NxN mode -> split automatically (only at level 0) + Otherwise -> read split flag + */ + if (log2TrafoSize <= sps.Log2MaxTrafoSize && + log2TrafoSize > sps.Log2MinTrafoSize && + trafoDepth < MaxTrafoDepth && + !(IntraSplitFlag && trafoDepth==0)) + { + split_transform_flag = decode_split_transform_flag(tctx, log2TrafoSize); + } + else + { + enum PartMode PartMode = img->get_PartMode(x0,y0); + + int interSplitFlag= (sps.max_transform_hierarchy_depth_inter==0 && + trafoDepth == 0 && + PredMode == MODE_INTER && + PartMode != PART_2Nx2N); + + split_transform_flag = (log2TrafoSize > sps.Log2MaxTrafoSize || + (IntraSplitFlag==1 && trafoDepth==0) || + interSplitFlag==1) ? 1:0; + } + + if (split_transform_flag) { + logtrace(LogSlice,"set_split_transform_flag(%d,%d, %d)\n",x0,y0,trafoDepth); + img->set_split_transform_flag(x0,y0,trafoDepth); + } + + int cbf_cb=-1; + int cbf_cr=-1; + + // CBF_CB/CR flags are encoded like this: + // 4:2:0 and 4:4:4 modes: binary flag in bit 0 + // 4:2:2 mode: bit 0: top block, bit 1: bottom block + + if ((log2TrafoSize>2 && sps.ChromaArrayType != CHROMA_MONO) || + sps.ChromaArrayType == CHROMA_444) { + // we do not have to test for trafoDepth==0, because parent_cbf_cb is 1 at depth 0 + if (/*trafoDepth==0 ||*/ parent_cbf_cb) { + cbf_cb = decode_cbf_chroma(tctx,trafoDepth); + + if (sps.ChromaArrayType == CHROMA_422 && (!split_transform_flag || log2TrafoSize==3)) { + cbf_cb |= (decode_cbf_chroma(tctx,trafoDepth) << 1); + } + } + + // we do not have to test for trafoDepth==0, because parent_cbf_cb is 1 at depth 0 + if (/*trafoDepth==0 ||*/ parent_cbf_cr) { + cbf_cr = decode_cbf_chroma(tctx,trafoDepth); + + if (sps.ChromaArrayType == CHROMA_422 && (!split_transform_flag || log2TrafoSize==3)) { + cbf_cr |= (decode_cbf_chroma(tctx,trafoDepth) << 1); + } + } + } + + //printf("CBF: cb:%d cr:%d\n",cbf_cb,cbf_cr); + + // cbf_cr/cbf_cb not present in bitstream -> induce values + + if (cbf_cb<0) { + assert(!(trafoDepth==0 && log2TrafoSize==2)); + + /* The standard specifies to check trafoDepth>0 AND log2TrafoSize==2. + However, I think that trafoDepth>0 is redundant as a CB is always + at least 8x8 and hence trafoDepth>0. + */ + + if (trafoDepth>0 && log2TrafoSize==2) { + cbf_cb = parent_cbf_cb; + } else { + cbf_cb=0; + } + } + + if (cbf_cr<0) { + if (trafoDepth>0 && log2TrafoSize==2) { + cbf_cr = parent_cbf_cr; + } else { + cbf_cr=0; + } + } + + if (split_transform_flag) { + int x1 = x0 + (1<<(log2TrafoSize-1)); + int y1 = y0 + (1<<(log2TrafoSize-1)); + + logtrace(LogSlice,"transform split.\n"); + + read_transform_tree(tctx, x0,y0, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 0, + MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); + read_transform_tree(tctx, x1,y0, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 1, + MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); + read_transform_tree(tctx, x0,y1, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 2, + MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); + read_transform_tree(tctx, x1,y1, x0,y0, xCUBase,yCUBase, log2TrafoSize-1, trafoDepth+1, 3, + MaxTrafoDepth,IntraSplitFlag, cuPredMode, cbf_cb,cbf_cr); + } + else { + int cbf_luma; + + if (PredMode==MODE_INTRA || trafoDepth!=0 || cbf_cb || cbf_cr) { + cbf_luma = decode_cbf_luma(tctx,trafoDepth); + } + else { + /* There cannot be INTER blocks with no residual data. + That case is already handled with rqt_root_cbf. + */ + + cbf_luma = 1; + } + + logtrace(LogSlice,"call read_transform_unit %d/%d\n",x0,y0); + + read_transform_unit(tctx, x0,y0,xBase,yBase, xCUBase,yCUBase, log2TrafoSize,trafoDepth, blkIdx, + cbf_luma, cbf_cb, cbf_cr); + } +} + + +const char* part_mode_name(enum PartMode pm) +{ + switch (pm) { + case PART_2Nx2N: return "2Nx2N"; + case PART_2NxN: return "2NxN"; + case PART_Nx2N: return "Nx2N"; + case PART_NxN: return "NxN"; + case PART_2NxnU: return "2NxnU"; + case PART_2NxnD: return "2NxnD"; + case PART_nLx2N: return "nLx2N"; + case PART_nRx2N: return "nRx2N"; + } + + return "undefined part mode"; +} + + +void read_mvd_coding(thread_context* tctx, + int x0,int y0, int refList) +{ + int abs_mvd_greater0_flag[2]; + abs_mvd_greater0_flag[0] = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+0]); + abs_mvd_greater0_flag[1] = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+0]); + + int abs_mvd_greater1_flag[2]; + if (abs_mvd_greater0_flag[0]) { + abs_mvd_greater1_flag[0] = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+1]); + } + else { + abs_mvd_greater1_flag[0]=0; + } + + if (abs_mvd_greater0_flag[1]) { + abs_mvd_greater1_flag[1] = decode_CABAC_bit(&tctx->cabac_decoder, + &tctx->ctx_model[CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG+1]); + } + else { + abs_mvd_greater1_flag[1]=0; + } + + + int abs_mvd_minus2[2]; + int mvd_sign_flag[2]; + int value[2]; + + for (int c=0;c<2;c++) { + if (abs_mvd_greater0_flag[c]) { + if (abs_mvd_greater1_flag[c]) { + abs_mvd_minus2[c] = decode_CABAC_EGk_bypass(&tctx->cabac_decoder, 1); + } + else { + abs_mvd_minus2[c] = abs_mvd_greater1_flag[c] -1; + } + + mvd_sign_flag[c] = decode_CABAC_bypass(&tctx->cabac_decoder); + + value[c] = abs_mvd_minus2[c]+2; + if (mvd_sign_flag[c]) { value[c] = -value[c]; } + } + else { + value[c] = 0; + } + } + + //set_mvd(tctx->decctx, x0,y0, refList, value[0],value[1]); + tctx->motion.mvd[refList][0] = value[0]; + tctx->motion.mvd[refList][1] = value[1]; + + logtrace(LogSlice, "MVD[%d;%d|%d] = %d;%d\n",x0,y0,refList, value[0],value[1]); +} + + +void read_prediction_unit_SKIP(thread_context* tctx, + int x0, int y0, + int nPbW, int nPbH) +{ + int merge_idx = decode_merge_idx(tctx); + + tctx->motion.merge_idx = merge_idx; + tctx->motion.merge_flag = true; + + logtrace(LogSlice,"prediction skip 2Nx2N, merge_idx: %d\n",merge_idx); +} + + +/* xC/yC : CB position + xB/yB : position offset of the PB + nPbW/nPbH : size of PB + nCS : CB size + */ +void read_prediction_unit(thread_context* tctx, + int xC,int yC, int xB,int yB, + int nPbW, int nPbH, + int ctDepth, int nCS,int partIdx) +{ + logtrace(LogSlice,"read_prediction_unit %d;%d %dx%d\n",xC+xB,yC+xB,nPbW,nPbH); + + int x0 = xC+xB; + int y0 = yC+yB; + + slice_segment_header* shdr = tctx->shdr; + + int merge_flag = decode_merge_flag(tctx); + tctx->motion.merge_flag = merge_flag; + + if (merge_flag) { + int merge_idx = decode_merge_idx(tctx); + + logtrace(LogSlice,"prediction unit %d,%d, merge mode, index: %d\n",x0,y0,merge_idx); + + tctx->motion.merge_idx = merge_idx; + } + else { // no merge flag + enum InterPredIdc inter_pred_idc; + + if (shdr->slice_type == SLICE_TYPE_B) { + inter_pred_idc = decode_inter_pred_idc(tctx,x0,y0,nPbW,nPbH,ctDepth); + } + else { + inter_pred_idc = PRED_L0; + } + + tctx->motion.inter_pred_idc = inter_pred_idc; // set_inter_pred_idc(ctx,x0,y0, inter_pred_idc); + + if (inter_pred_idc != PRED_L1) { + int ref_idx_l0 = decode_ref_idx_lX(tctx, shdr->num_ref_idx_l0_active); + + // NOTE: case for only one reference frame is handles in decode_ref_idx_lX() + tctx->motion.refIdx[0] = ref_idx_l0; + + read_mvd_coding(tctx,x0,y0, 0); + + int mvp_l0_flag = decode_mvp_lx_flag(tctx); // l0 + tctx->motion.mvp_l0_flag = mvp_l0_flag; + + logtrace(LogSlice,"prediction unit %d,%d, L0, refIdx=%d mvp_l0_flag:%d\n", + x0,y0, tctx->motion.refIdx[0], mvp_l0_flag); + } + + if (inter_pred_idc != PRED_L0) { + int ref_idx_l1 = decode_ref_idx_lX(tctx, shdr->num_ref_idx_l1_active); + + // NOTE: case for only one reference frame is handles in decode_ref_idx_lX() + tctx->motion.refIdx[1] = ref_idx_l1; + + if (shdr->mvd_l1_zero_flag && + inter_pred_idc == PRED_BI) { + tctx->motion.mvd[1][0] = 0; + tctx->motion.mvd[1][1] = 0; + } + else { + read_mvd_coding(tctx,x0,y0, 1); + } + + int mvp_l1_flag = decode_mvp_lx_flag(tctx); // l1 + tctx->motion.mvp_l1_flag = mvp_l1_flag; + + logtrace(LogSlice,"prediction unit %d,%d, L1, refIdx=%d mvp_l1_flag:%d\n", + x0,y0, tctx->motion.refIdx[1], mvp_l1_flag); + } + } + + + + decode_prediction_unit(tctx->decctx, tctx->shdr, tctx->img, tctx->motion, + xC,yC,xB,yB, nCS, nPbW,nPbH, partIdx); +} + + + + +template +void read_pcm_samples_internal(thread_context* tctx, int x0, int y0, int log2CbSize, + int cIdx, bitreader& br) +{ + const seq_parameter_set& sps = tctx->img->get_sps(); + + int nPcmBits; + int bitDepth; + + int w = 1<0) { + w /= sps.SubWidthC; + h /= sps.SubHeightC; + + x0 /= sps.SubWidthC; + y0 /= sps.SubHeightC; + + nPcmBits = sps.pcm_sample_bit_depth_chroma; + bitDepth = sps.BitDepth_C; + } + else { + nPcmBits = sps.pcm_sample_bit_depth_luma; + bitDepth = sps.BitDepth_Y; + } + + pixel_t* ptr; + int stride; + ptr = tctx->img->get_image_plane_at_pos_NEW(cIdx,x0,y0); + stride = tctx->img->get_image_stride(cIdx); + + int shift = bitDepth - nPcmBits; + + for (int y=0;ycabac_decoder.bitstream_curr; + br.bytes_remaining = tctx->cabac_decoder.bitstream_end - tctx->cabac_decoder.bitstream_curr; + br.nextbits = 0; + br.nextbits_cnt = 0; + + + if (tctx->img->high_bit_depth(0)) { + read_pcm_samples_internal(tctx,x0,y0,log2CbSize,0,br); + } else { + read_pcm_samples_internal(tctx,x0,y0,log2CbSize,0,br); + } + + if (tctx->img->get_sps().ChromaArrayType != CHROMA_MONO) { + if (tctx->img->high_bit_depth(1)) { + read_pcm_samples_internal(tctx,x0,y0,log2CbSize,1,br); + read_pcm_samples_internal(tctx,x0,y0,log2CbSize,2,br); + } else { + read_pcm_samples_internal(tctx,x0,y0,log2CbSize,1,br); + read_pcm_samples_internal(tctx,x0,y0,log2CbSize,2,br); + } + } + + prepare_for_CABAC(&br); + tctx->cabac_decoder.bitstream_curr = br.data; + init_CABAC_decoder_2(&tctx->cabac_decoder); +} + + +int map_chroma_pred_mode(int intra_chroma_pred_mode, int IntraPredMode) +{ + if (intra_chroma_pred_mode==4) { + return IntraPredMode; + } + else { + static const enum IntraPredMode IntraPredModeCCand[4] = { + INTRA_PLANAR, + INTRA_ANGULAR_26, // vertical + INTRA_ANGULAR_10, // horizontal + INTRA_DC + }; + + int IntraPredModeC = IntraPredModeCCand[intra_chroma_pred_mode]; + if (IntraPredModeC == IntraPredMode) { + return INTRA_ANGULAR_34; + } + else { + return IntraPredModeC; + } + } +} + +// h.265-V2 Table 8-3 +static const uint8_t map_chroma_422[35] = { + 0,1,2, 2, 2, 2, 3, 5, 7, 8,10,12,13,15,17,18,19,20, + 21,22,23,23,24,24,25,25,26,27,27,28,28,29,29,30,31 +}; + +void read_coding_unit(thread_context* tctx, + int x0, int y0, // position of coding unit in frame + int log2CbSize, + int ctDepth) +{ + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + const pic_parameter_set& pps = img->get_pps(); + slice_segment_header* shdr = tctx->shdr; + + logtrace(LogSlice,"- read_coding_unit %d;%d cbsize:%d\n",x0,y0,1<set_log2CbSize(x0,y0, log2CbSize, true); + + /* This is only required on corrupted input streams. + It may happen that there are several slices in the image that overlap. + In this case, flags would accumulate from both slices. + */ + img->clear_split_transform_flags(x0,y0, log2CbSize); + + int nCbS = 1<cu_transquant_bypass_flag = transquant_bypass; + + if (transquant_bypass) { + img->set_cu_transquant_bypass(x0,y0,log2CbSize); + } + } + else { + tctx->cu_transquant_bypass_flag = 0; + } + + uint8_t cu_skip_flag = 0; + if (shdr->slice_type != SLICE_TYPE_I) { + cu_skip_flag = decode_cu_skip_flag(tctx,x0,y0,ctDepth); + } + + int IntraSplitFlag = 0; + + enum PredMode cuPredMode; + + if (cu_skip_flag) { + read_prediction_unit_SKIP(tctx,x0,y0,nCbS,nCbS); + + img->set_PartMode(x0,y0, PART_2Nx2N); // need this for deblocking filter + img->set_pred_mode(x0,y0,log2CbSize, MODE_SKIP); + cuPredMode = MODE_SKIP; + + logtrace(LogSlice,"CU pred mode: SKIP\n"); + + + // DECODE + + int nCS_L = 1<decctx,tctx->shdr,tctx->img,tctx->motion, + x0,y0, 0,0, nCS_L, nCS_L,nCS_L, 0); + } + else /* not skipped */ { + if (shdr->slice_type != SLICE_TYPE_I) { + int pred_mode_flag = decode_pred_mode_flag(tctx); + cuPredMode = pred_mode_flag ? MODE_INTRA : MODE_INTER; + } + else { + cuPredMode = MODE_INTRA; + } + + img->set_pred_mode(x0,y0,log2CbSize, cuPredMode); + + logtrace(LogSlice,"CU pred mode: %s\n", cuPredMode==MODE_INTRA ? "INTRA" : "INTER"); + + + enum PartMode PartMode; + + if (cuPredMode != MODE_INTRA || + log2CbSize == sps.Log2MinCbSizeY) { + PartMode = decode_part_mode(tctx, cuPredMode, log2CbSize); + + if (PartMode==PART_NxN && cuPredMode==MODE_INTRA) { + IntraSplitFlag=1; + } + } else { + PartMode = PART_2Nx2N; + } + + img->set_PartMode(x0,y0, PartMode); // needed for deblocking ? + + logtrace(LogSlice, "PartMode: %s\n", part_mode_name(PartMode)); + + + bool pcm_flag = false; + + if (cuPredMode == MODE_INTRA) { + if (PartMode == PART_2Nx2N && sps.pcm_enabled_flag && + log2CbSize >= sps.Log2MinIpcmCbSizeY && + log2CbSize <= sps.Log2MaxIpcmCbSizeY) { + pcm_flag = decode_CABAC_term_bit(&tctx->cabac_decoder); + } + + if (pcm_flag) { + img->set_pcm_flag(x0,y0,log2CbSize); + + read_pcm_samples(tctx, x0,y0, log2CbSize); + } + else { + int pbOffset = (PartMode == PART_NxN) ? (nCbS/2) : nCbS; + int log2IntraPredSize = (PartMode == PART_NxN) ? (log2CbSize-1) : log2CbSize; + + logtrace(LogSlice,"nCbS:%d pbOffset:%d\n",nCbS,pbOffset); + + int prev_intra_luma_pred_flag[4]; + + int idx=0; + for (int j=0;j0); // left candidate always available for right blk + int availableB = availableB0 || (j>0); // top candidate always available for bottom blk + + + + int PUidx = (x>>sps.Log2MinPUSize) + (y>>sps.Log2MinPUSize)*sps.PicWidthInMinPUs; + + enum IntraPredMode candModeList[3]; + + fillIntraPredModeCandidates(candModeList,x,y,PUidx, + availableA, availableB, img); + + for (int i=0;i<3;i++) + logtrace(LogSlice,"candModeList[%d] = %d\n", i, candModeList[i]); + + if (prev_intra_luma_pred_flag[idx]==1) { + IntraPredMode = candModeList[ mpm_idx[idx] ]; + } + else { + // sort candModeList + + if (candModeList[0] > candModeList[1]) { + std::swap(candModeList[0],candModeList[1]); + } + if (candModeList[0] > candModeList[2]) { + std::swap(candModeList[0],candModeList[2]); + } + if (candModeList[1] > candModeList[2]) { + std::swap(candModeList[1],candModeList[2]); + } + + // skip modes in the list + // (we have 35 modes. skipping the 3 in the list gives us 32, which can be selected by 5 bits) + IntraPredMode = rem_intra_luma_pred_mode[idx]; + for (int n=0;n<=2;n++) { + if (IntraPredMode >= candModeList[n]) { IntraPredMode++; } + } + } + + logtrace(LogSlice,"IntraPredMode[%d][%d] = %d (log2blk:%d)\n",x,y,IntraPredMode, log2IntraPredSize); + + img->set_IntraPredMode(PUidx, log2IntraPredSize, + (enum IntraPredMode)IntraPredMode); + + idx++; + } + + + // set chroma intra prediction mode + + if (sps.ChromaArrayType == CHROMA_444) { + // chroma 4:4:4 + + idx = 0; + for (int j=0;jget_IntraPredMode(x,y); + + int IntraPredModeC = map_chroma_pred_mode(intra_chroma_pred_mode, IntraPredMode); + + logtrace(LogSlice,"IntraPredModeC[%d][%d]: %d (blksize:%d)\n",x,y,IntraPredModeC, + 1<set_IntraPredModeC(x,y, log2IntraPredSize, + (enum IntraPredMode)IntraPredModeC, + intra_chroma_pred_mode == 4); + idx++; + } + } + else if (sps.ChromaArrayType != CHROMA_MONO) { + // chroma 4:2:0 and 4:2:2 + + int intra_chroma_pred_mode = decode_intra_chroma_pred_mode(tctx); + int IntraPredMode = img->get_IntraPredMode(x0,y0); + logtrace(LogSlice,"IntraPredMode: %d\n",IntraPredMode); + int IntraPredModeC = map_chroma_pred_mode(intra_chroma_pred_mode, IntraPredMode); + + if (sps.ChromaArrayType == CHROMA_422) { + IntraPredModeC = map_chroma_422[ IntraPredModeC ]; + } + + img->set_IntraPredModeC(x0,y0, log2CbSize, + (enum IntraPredMode)IntraPredModeC, + intra_chroma_pred_mode == 4); + } + } + } + else { // INTER + int nCS = 1<motion.merge_flag; // !!get_merge_flag(ctx,x0,y0); + + if (cuPredMode != MODE_INTRA && + !(PartMode == PART_2Nx2N && merge_flag)) { + + rqt_root_cbf = !!decode_rqt_root_cbf(tctx); + } + else { + /* rqt_root_cbf=1 is inferred for Inter blocks with 2Nx2N, merge mode. + These must be some residual data, because otherwise, the CB could + also be coded in SKIP mode. + */ + + rqt_root_cbf = true; + } + + //set_rqt_root_cbf(ctx,x0,y0, log2CbSize, rqt_root_cbf); + + if (rqt_root_cbf) { + int MaxTrafoDepth; + + if (cuPredMode==MODE_INTRA) { + MaxTrafoDepth = sps.max_transform_hierarchy_depth_intra + IntraSplitFlag; + } + else { + MaxTrafoDepth = sps.max_transform_hierarchy_depth_inter; + } + + logtrace(LogSlice,"MaxTrafoDepth: %d\n",MaxTrafoDepth); + + uint8_t initial_chroma_cbf = 1; + if (sps.ChromaArrayType == CHROMA_MONO) { + initial_chroma_cbf = 0; + } + + read_transform_tree(tctx, x0,y0, x0,y0, x0,y0, log2CbSize, 0,0, + MaxTrafoDepth, IntraSplitFlag, cuPredMode, + initial_chroma_cbf, initial_chroma_cbf); + } + } // !pcm + } +} + + +// ------------------------------------------------------------------------------------------ + + +void read_coding_quadtree(thread_context* tctx, + int x0, int y0, + int log2CbSize, + int ctDepth) +{ + logtrace(LogSlice,"- read_coding_quadtree %d;%d cbsize:%d depth:%d POC:%d\n",x0,y0,1<img->PicOrderCntVal); + + de265_image* img = tctx->img; + const seq_parameter_set& sps = img->get_sps(); + const pic_parameter_set& pps = img->get_pps(); + + int split_flag; + + // We only send a split flag if CU is larger than minimum size and + // completely contained within the image area. + // If it is partly outside the image area and not at minimum size, + // it is split. If already at minimum size, it is not split further. + if (x0+(1< sps.Log2MinCbSizeY) { + split_flag = decode_split_cu_flag(tctx, x0,y0, ctDepth); + } else { + if (log2CbSize > sps.Log2MinCbSizeY) { split_flag=1; } + else { split_flag=0; } + } + + + if (pps.cu_qp_delta_enabled_flag && + log2CbSize >= pps.Log2MinCuQpDeltaSize) + { + tctx->IsCuQpDeltaCoded = 0; + tctx->CuQpDelta = 0; + } + else + { + // shdr->CuQpDelta = 0; // TODO check: is this the right place to set to default value ? + } + + + if (tctx->shdr->cu_chroma_qp_offset_enabled_flag && + log2CbSize >= pps.Log2MinCuChromaQpOffsetSize) { + tctx->IsCuChromaQpOffsetCoded = 0; + } + + if (split_flag) { + int x1 = x0 + (1<<(log2CbSize-1)); + int y1 = y0 + (1<<(log2CbSize-1)); + + read_coding_quadtree(tctx,x0,y0, log2CbSize-1, ctDepth+1); + + if (x1set_ctDepth(x0,y0, log2CbSize, ctDepth); + + read_coding_unit(tctx, x0,y0, log2CbSize, ctDepth); + } + + logtrace(LogSlice,"-\n"); +} + + +// --------------------------------------------------------------------------- + +enum DecodeResult { + Decode_EndOfSliceSegment, + Decode_EndOfSubstream, + Decode_Error +}; + +/* Decode CTBs until the end of sub-stream, the end-of-slice, or some error occurs. + */ +enum DecodeResult decode_substream(thread_context* tctx, + bool block_wpp, // block on WPP dependencies + bool first_independent_substream) +{ + const pic_parameter_set& pps = tctx->img->get_pps(); + const seq_parameter_set& sps = tctx->img->get_sps(); + + const int ctbW = sps.PicWidthInCtbsY; + + + const int startCtbY = tctx->CtbY; + + //printf("start decoding substream at %d;%d\n",tctx->CtbX,tctx->CtbY); + + // in WPP mode: initialize CABAC model with stored model from row above + + if ((!first_independent_substream || tctx->CtbY != startCtbY) && + pps.entropy_coding_sync_enabled_flag && + tctx->CtbY>=1 && tctx->CtbX==0) + { + if (sps.PicWidthInCtbsY>1) { + if ((tctx->CtbY-1) >= tctx->imgunit->ctx_models.size()) { + return Decode_Error; + } + + //printf("CTX wait on %d/%d\n",1,tctx->CtbY-1); + + // we have to wait until the context model data is there + tctx->img->wait_for_progress(tctx->task, 1,tctx->CtbY-1,CTB_PROGRESS_PREFILTER); + + // copy CABAC model from previous CTB row + tctx->ctx_model = tctx->imgunit->ctx_models[(tctx->CtbY-1)]; + tctx->imgunit->ctx_models[(tctx->CtbY-1)].release(); // not used anymore + } + else { + tctx->img->wait_for_progress(tctx->task, 0,tctx->CtbY-1,CTB_PROGRESS_PREFILTER); + initialize_CABAC_models(tctx); + } + } + + + do { + const int ctbx = tctx->CtbX; + const int ctby = tctx->CtbY; + + if (ctbx+ctby*ctbW >= pps.CtbAddrRStoTS.size()) { + return Decode_Error; + } + + if (ctbx >= sps.PicWidthInCtbsY || + ctby >= sps.PicHeightInCtbsY) { + return Decode_Error; + } + + if (block_wpp && ctby>0 && ctbx < ctbW-1) { + + // TODO: if we are in tiles mode and at the right border, do not wait for x+1,y-1 + + //printf("wait on %d/%d (%d)\n",ctbx+1,ctby-1, ctbx+1+(ctby-1)*sps->PicWidthInCtbsY); + + tctx->img->wait_for_progress(tctx->task, ctbx+1,ctby-1, CTB_PROGRESS_PREFILTER); + } + + //printf("%p: decode %d;%d\n", tctx, tctx->CtbX,tctx->CtbY); + + + // read and decode CTB + + if (tctx->ctx_model.empty() == false) { + return Decode_Error; + } + + read_coding_tree_unit(tctx); + + + // save CABAC-model for WPP (except in last CTB row) + + if (pps.entropy_coding_sync_enabled_flag && + ctbx == 1 && + ctby < sps.PicHeightInCtbsY-1) + { + // no storage for context table has been allocated + if (tctx->imgunit->ctx_models.size() <= ctby) { + return Decode_Error; + } + + tctx->imgunit->ctx_models[ctby] = tctx->ctx_model; + tctx->imgunit->ctx_models[ctby].decouple(); // store an independent copy + } + + + // end of slice segment ? + + int end_of_slice_segment_flag = decode_CABAC_term_bit(&tctx->cabac_decoder); + //printf("end-of-slice flag: %d\n", end_of_slice_segment_flag); + + if (end_of_slice_segment_flag) { + // at the end of the slice segment, we store the CABAC model if we need it + // because a dependent slice may follow + + if (pps.dependent_slice_segments_enabled_flag) { + tctx->shdr->ctx_model_storage = tctx->ctx_model; + tctx->shdr->ctx_model_storage.decouple(); // store an independent copy + + tctx->shdr->ctx_model_storage_defined = true; + } + } + + tctx->img->ctb_progress[ctbx+ctby*ctbW].set_progress(CTB_PROGRESS_PREFILTER); + + //printf("%p: decoded %d|%d\n",tctx, ctby,ctbx); + + + logtrace(LogSlice,"read CTB %d -> end=%d\n", tctx->CtbAddrInRS, end_of_slice_segment_flag); + //printf("read CTB %d -> end=%d\n", tctx->CtbAddrInRS, end_of_slice_segment_flag); + + const int lastCtbY = tctx->CtbY; + + bool endOfPicture = advanceCtbAddr(tctx); // true if we read past the end of the image + + if (endOfPicture && + end_of_slice_segment_flag == false) + { + tctx->decctx->add_warning(DE265_WARNING_CTB_OUTSIDE_IMAGE_AREA, false); + tctx->img->integrity = INTEGRITY_DECODING_ERRORS; + return Decode_Error; + } + + + if (end_of_slice_segment_flag) { + /* corrupted inputs may send the end_of_slice_segment_flag even if not all + CTBs in a row have been coded. Hence, we mark all of them as finished. + */ + + /* + for (int x = ctbx+1 ; xPicWidthInCtbsY; x++) { + printf("mark skipped %d;%d\n",ctbx,ctby); + tctx->img->ctb_progress[ctbx+ctby*ctbW].set_progress(CTB_PROGRESS_PREFILTER); + } + */ + + return Decode_EndOfSliceSegment; + } + + + if (!end_of_slice_segment_flag) { + bool end_of_sub_stream = false; + end_of_sub_stream |= (pps.tiles_enabled_flag && + pps.TileId[tctx->CtbAddrInTS] != pps.TileId[tctx->CtbAddrInTS-1]); + end_of_sub_stream |= (pps.entropy_coding_sync_enabled_flag && + lastCtbY != tctx->CtbY); + + if (end_of_sub_stream) { + int end_of_sub_stream_one_bit = decode_CABAC_term_bit(&tctx->cabac_decoder); + if (!end_of_sub_stream_one_bit) { + tctx->decctx->add_warning(DE265_WARNING_EOSS_BIT_NOT_SET, false); + tctx->img->integrity = INTEGRITY_DECODING_ERRORS; + return Decode_Error; + } + + init_CABAC_decoder_2(&tctx->cabac_decoder); // byte alignment + return Decode_EndOfSubstream; + } + } + + } while (true); +} + + + +bool initialize_CABAC_at_slice_segment_start(thread_context* tctx) +{ + de265_image* img = tctx->img; + const pic_parameter_set& pps = img->get_pps(); + const seq_parameter_set& sps = img->get_sps(); + slice_segment_header* shdr = tctx->shdr; + + if (shdr->dependent_slice_segment_flag) { + int prevCtb = pps.CtbAddrTStoRS[ pps.CtbAddrRStoTS[shdr->slice_segment_address] -1 ]; + + int sliceIdx = img->get_SliceHeaderIndex_atIndex(prevCtb); + if (sliceIdx >= img->slices.size()) { + return false; + } + slice_segment_header* prevCtbHdr = img->slices[ sliceIdx ]; + + if (pps.is_tile_start_CTB(shdr->slice_segment_address % sps.PicWidthInCtbsY, + shdr->slice_segment_address / sps.PicWidthInCtbsY + )) { + initialize_CABAC_models(tctx); + } + else { + // wait for previous slice to finish decoding + + //printf("wait for previous slice to finish decoding\n"); + + + slice_unit* prevSliceSegment = tctx->imgunit->get_prev_slice_segment(tctx->sliceunit); + //assert(prevSliceSegment); + if (prevSliceSegment==NULL) { + return false; + } + + prevSliceSegment->finished_threads.wait_for_progress(prevSliceSegment->nThreads); + + + /* + printf("wait for %d,%d (init)\n", + prevCtb / sps->PicWidthInCtbsY, + prevCtb % sps->PicWidthInCtbsY); + tctx->img->wait_for_progress(tctx->task, prevCtb, CTB_PROGRESS_PREFILTER); + */ + + if (!prevCtbHdr->ctx_model_storage_defined) { + return false; + } + + tctx->ctx_model = prevCtbHdr->ctx_model_storage; + prevCtbHdr->ctx_model_storage.release(); + } + } + else { + initialize_CABAC_models(tctx); + } + + return true; +} + + +std::string thread_task_ctb_row::name() const { + char buf[100]; + sprintf(buf,"ctb-row-%d",debug_startCtbRow); + return buf; +} + + +std::string thread_task_slice_segment::name() const { + char buf[100]; + sprintf(buf,"slice-segment-%d;%d",debug_startCtbX,debug_startCtbY); + return buf; +} + + +void thread_task_slice_segment::work() +{ + thread_task_slice_segment* data = this; + thread_context* tctx = data->tctx; + de265_image* img = tctx->img; + + state = Running; + img->thread_run(this); + + setCtbAddrFromTS(tctx); + + //printf("%p: A start decoding at %d/%d\n", tctx, tctx->CtbX,tctx->CtbY); + + if (data->firstSliceSubstream) { + bool success = initialize_CABAC_at_slice_segment_start(tctx); + if (!success) { + state = Finished; + tctx->sliceunit->finished_threads.increase_progress(1); + img->thread_finishes(this); + return; + } + } + else { + initialize_CABAC_models(tctx); + } + + init_CABAC_decoder_2(&tctx->cabac_decoder); + + /*enum DecodeResult result =*/ decode_substream(tctx, false, data->firstSliceSubstream); + + state = Finished; + tctx->sliceunit->finished_threads.increase_progress(1); + img->thread_finishes(this); + + return; // DE265_OK; +} + + +void thread_task_ctb_row::work() +{ + thread_task_ctb_row* data = this; + thread_context* tctx = data->tctx; + de265_image* img = tctx->img; + + const seq_parameter_set& sps = img->get_sps(); + int ctbW = sps.PicWidthInCtbsY; + + state = Running; + img->thread_run(this); + + setCtbAddrFromTS(tctx); + + int ctby = tctx->CtbAddrInRS / ctbW; + int myCtbRow = ctby; + + //printf("start CTB-row decoding at row %d\n", ctby); + + if (data->firstSliceSubstream) { + bool success = initialize_CABAC_at_slice_segment_start(tctx); + if (!success) { + // could not decode this row, mark whole row as finished + for (int x=0;xctb_progress[myCtbRow*ctbW + x].set_progress(CTB_PROGRESS_PREFILTER); + } + + state = Finished; + tctx->sliceunit->finished_threads.increase_progress(1); + img->thread_finishes(this); + return; + } + //initialize_CABAC(tctx); + } + + init_CABAC_decoder_2(&tctx->cabac_decoder); + + bool firstIndependentSubstream = + data->firstSliceSubstream && !tctx->shdr->dependent_slice_segment_flag; + + /*enum DecodeResult result =*/ + decode_substream(tctx, true, firstIndependentSubstream); + + // mark progress on remaining CTBs in row (in case of decoder error and early termination) + + // TODO: what about slices that end properly in the middle of a CTB row? + + if (tctx->CtbY == myCtbRow) { + int lastCtbX = sps.PicWidthInCtbsY; // assume no tiles when WPP is on + for (int x = tctx->CtbX; xctb_progress[myCtbRow*ctbW + x].set_progress(CTB_PROGRESS_PREFILTER); + } + } + } + + state = Finished; + tctx->sliceunit->finished_threads.increase_progress(1); + img->thread_finishes(this); +} + + +de265_error read_slice_segment_data(thread_context* tctx) +{ + setCtbAddrFromTS(tctx); + + de265_image* img = tctx->img; + const pic_parameter_set& pps = img->get_pps(); + const seq_parameter_set& sps = img->get_sps(); + slice_segment_header* shdr = tctx->shdr; + + bool success = initialize_CABAC_at_slice_segment_start(tctx); + if (!success) { + return DE265_ERROR_UNSPECIFIED_DECODING_ERROR; + } + + init_CABAC_decoder_2(&tctx->cabac_decoder); + + //printf("-----\n"); + + bool first_slice_substream = !shdr->dependent_slice_segment_flag; + + int substream=0; + + enum DecodeResult result; + do { + int ctby = tctx->CtbY; + + + // check whether entry_points[] are correct in the bitstream + + if (substream>0) { + if (substream-1 >= tctx->shdr->entry_point_offset.size() || + tctx->cabac_decoder.bitstream_curr - tctx->cabac_decoder.bitstream_start -2 /* -2 because of CABAC init */ + != tctx->shdr->entry_point_offset[substream-1]) { + tctx->decctx->add_warning(DE265_WARNING_INCORRECT_ENTRY_POINT_OFFSET, true); + } + } + + substream++; + + + result = decode_substream(tctx, false, first_slice_substream); + + + if (result == Decode_EndOfSliceSegment || + result == Decode_Error) { + break; + } + + first_slice_substream = false; + + if (pps.tiles_enabled_flag) { + initialize_CABAC_models(tctx); + } + } while (true); + + return DE265_OK; +} + + +/* TODO: + When a task wants to block, but is the first in the list of pending tasks, + do some error concealment instead of blocking, since it will never be deblocked. + This will only happen in the case of input error. + */