int get_svlc(bitreader* br) { int v = get_uvlc(br); if (v==0) return v; bool negative = ((v&1)==0); return negative ? -v/2 : (v+1)/2; }
void read_short_term_ref_pic_set(bitreader* br, ref_pic_set* sets, int idxRps, int num_short_term_ref_pic_sets) { char inter_ref_pic_set_prediction_flag=0; if (idxRps != 0) { inter_ref_pic_set_prediction_flag = get_bits(br,1); } if (inter_ref_pic_set_prediction_flag) { int delta_idx; if (idxRps == num_short_term_ref_pic_sets) { delta_idx = get_uvlc(br)+1; } else { delta_idx = 1; } int RIdx = idxRps - delta_idx; assert(RIdx>=0); int delta_rps_sign = get_bits(br,1); int abs_delta_rps = get_uvlc(br)+1; int DeltaRPS = (delta_rps_sign ? -abs_delta_rps : abs_delta_rps); // bits are stored in this order: // - all bits for negative Pocs (forward), // - then all bits for positive Pocs (forward), // - then bits for '0' logtrace(LogHeaders,"predicted from %d with delta %d\n",RIdx,DeltaRPS); int nDeltaPocsRIdx= sets[RIdx].NumDeltaPocs; char *const used_by_curr_pic_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char)); char *const use_delta_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char)); for (int j=0;j<=nDeltaPocsRIdx;j++) { used_by_curr_pic_flag[j] = get_bits(br,1); if (!used_by_curr_pic_flag[j]) { use_delta_flag[j] = get_bits(br,1); } else { use_delta_flag[j] = 1; } } logtrace(LogHeaders,"flags: "); for (int j=0;j<=nDeltaPocsRIdx;j++) { logtrace(LogHeaders,"%d ", use_delta_flag[j]); } logtrace(LogHeaders,"\n"); int nNegativeRIdx = sets[RIdx].NumNegativePics; // --- update list 0 (negative Poc) --- // Iterate through all Pocs in decreasing value order (positive reverse, 0, negative forward). int i=0; for (int j=sets[RIdx].NumPositivePics-1;j>=0;j--) { int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS; if (dPoc<0 && use_delta_flag[nNegativeRIdx+j]) { sets[idxRps].DeltaPocS0[i] = dPoc; sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_flag[nNegativeRIdx+j]; i++; } } if (DeltaRPS<0 && use_delta_flag[nDeltaPocsRIdx]) { sets[idxRps].DeltaPocS0[i] = DeltaRPS; sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_flag[nDeltaPocsRIdx]; i++; } for (int j=0;j<nNegativeRIdx;j++) { int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS; if (dPoc<0 && use_delta_flag[j]) { sets[idxRps].DeltaPocS0[i] = dPoc; sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_flag[j]; i++; } } sets[idxRps].NumNegativePics = i; // --- update list 1 (positive Poc) --- // Iterate through all Pocs in increasing value order (negative reverse, 0, positive forward) i=0; for (int j=sets[RIdx].NumNegativePics-1;j>=0;j--) { int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS; if (dPoc>0 && use_delta_flag[j]) { sets[idxRps].DeltaPocS1[i] = dPoc; sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_flag[j]; i++; } } if (DeltaRPS>0 && use_delta_flag[nDeltaPocsRIdx]) { sets[idxRps].DeltaPocS1[i] = DeltaRPS; sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_flag[nDeltaPocsRIdx]; i++; } for (int j=0;j<sets[RIdx].NumPositivePics;j++) { int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS; if (dPoc>0 && use_delta_flag[nNegativeRIdx+j]) { sets[idxRps].DeltaPocS1[i] = dPoc; sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_flag[nNegativeRIdx+j]; i++; } } sets[idxRps].NumPositivePics = i; sets[idxRps].NumDeltaPocs = sets[idxRps].NumNegativePics + sets[idxRps].NumPositivePics; } else { int num_negative_pics = get_uvlc(br); int num_positive_pics = get_uvlc(br); assert(num_negative_pics + num_positive_pics <= MAX_NUM_REF_PICS); sets[idxRps].NumNegativePics = num_negative_pics; sets[idxRps].NumPositivePics = num_positive_pics; sets[idxRps].NumDeltaPocs = num_positive_pics + num_negative_pics; int lastPocS=0; for (int i=0;i<num_negative_pics;i++) { int delta_poc_s0 = get_uvlc(br)+1; char used_by_curr_pic_s0_flag = get_bits(br,1); logtrace(LogHeaders,"neg: %d %d\n", delta_poc_s0, used_by_curr_pic_s0_flag); sets[idxRps].DeltaPocS0[i] = lastPocS - delta_poc_s0; sets[idxRps].UsedByCurrPicS0[i] = used_by_curr_pic_s0_flag; lastPocS = sets[idxRps].DeltaPocS0[i]; } lastPocS=0; for (int i=0;i<num_positive_pics;i++) { int delta_poc_s1 = get_uvlc(br)+1; char used_by_curr_pic_s1_flag = get_bits(br,1); logtrace(LogHeaders,"pos: %d %d\n", delta_poc_s1, used_by_curr_pic_s1_flag); sets[idxRps].DeltaPocS1[i] = lastPocS + delta_poc_s1; sets[idxRps].UsedByCurrPicS1[i] = used_by_curr_pic_s1_flag; lastPocS = sets[idxRps].DeltaPocS1[i]; } } compute_NumPoc(&sets[idxRps]); }
de265_error read_sps(bitreader* br, seq_parameter_set* sps, ref_pic_set** ref_pic_sets) { sps->video_parameter_set_id = get_bits(br,4); sps->sps_max_sub_layers = get_bits(br,3) +1; if (sps->sps_max_sub_layers>7) { return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } sps->sps_temporal_id_nesting_flag = get_bits(br,1); read_profile_tier_level(br,&sps->profile_tier_level, true, sps->sps_max_sub_layers); sps->seq_parameter_set_id = get_uvlc(br); // --- decode chroma type --- sps->chroma_format_idc = get_uvlc(br); if (sps->chroma_format_idc == 3) { sps->separate_colour_plane_flag = get_bits(br,1); } else { sps->separate_colour_plane_flag = 0; } if (sps->separate_colour_plane_flag) { sps->ChromaArrayType = 0; } else { sps->ChromaArrayType = sps->chroma_format_idc; } sps->SubWidthC = SubWidthC [sps->chroma_format_idc]; sps->SubHeightC = SubHeightC[sps->chroma_format_idc]; // --- picture size --- sps->pic_width_in_luma_samples = get_uvlc(br); sps->pic_height_in_luma_samples = get_uvlc(br); sps->conformance_window_flag = get_bits(br,1); if (sps->conformance_window_flag) { sps->conf_win_left_offset = get_uvlc(br); sps->conf_win_right_offset = get_uvlc(br); sps->conf_win_top_offset = get_uvlc(br); sps->conf_win_bottom_offset= get_uvlc(br); } else { sps->conf_win_left_offset = 0; sps->conf_win_right_offset = 0; sps->conf_win_top_offset = 0; sps->conf_win_bottom_offset= 0; } if (sps->ChromaArrayType==0) { sps->WinUnitX = 1; sps->WinUnitY = 1; } else { sps->WinUnitX = SubWidthC[sps->chroma_format_idc]; sps->WinUnitY = SubHeightC[sps->chroma_format_idc]; } sps->bit_depth_luma = get_uvlc(br) +8; sps->bit_depth_chroma = get_uvlc(br) +8; sps->log2_max_pic_order_cnt_lsb = get_uvlc(br) +4; sps->MaxPicOrderCntLsb = 1<<(sps->log2_max_pic_order_cnt_lsb); // --- sub_layer_ordering_info --- sps->sps_sub_layer_ordering_info_present_flag = get_bits(br,1); int firstLayer = (sps->sps_sub_layer_ordering_info_present_flag ? 0 : sps->sps_max_sub_layers-1 ); for (int i=firstLayer ; i <= sps->sps_max_sub_layers-1; i++ ) { sps->sps_max_dec_pic_buffering[i] = get_uvlc(br); sps->sps_max_num_reorder_pics[i] = get_uvlc(br); sps->sps_max_latency_increase[i] = get_uvlc(br); } // copy info to all layers if only specified once if (sps->sps_sub_layer_ordering_info_present_flag) { int ref = sps->sps_max_sub_layers-1; for (int i=0 ; i < sps->sps_max_sub_layers-1; i++ ) { sps->sps_max_dec_pic_buffering[i] = sps->sps_max_dec_pic_buffering[ref]; sps->sps_max_num_reorder_pics[i] = sps->sps_max_num_reorder_pics[ref]; sps->sps_max_latency_increase[i] = sps->sps_max_latency_increase[ref]; } } sps->log2_min_luma_coding_block_size = get_uvlc(br)+3; sps->log2_diff_max_min_luma_coding_block_size = get_uvlc(br); sps->log2_min_transform_block_size = get_uvlc(br)+2; sps->log2_diff_max_min_transform_block_size = get_uvlc(br); sps->max_transform_hierarchy_depth_inter = get_uvlc(br); sps->max_transform_hierarchy_depth_intra = get_uvlc(br); sps->scaling_list_enable_flag = get_bits(br,1); if (sps->scaling_list_enable_flag) { sps->sps_scaling_list_data_present_flag = get_bits(br,1); if (sps->sps_scaling_list_data_present_flag) { assert(0); //scaling_list_data() } } sps->amp_enabled_flag = get_bits(br,1); sps->sample_adaptive_offset_enabled_flag = get_bits(br,1); sps->pcm_enabled_flag = get_bits(br,1); if (sps->pcm_enabled_flag) { sps->pcm_sample_bit_depth_luma = get_bits(br,4)+1; sps->pcm_sample_bit_depth_chroma = get_bits(br,4)+1; sps->log2_min_pcm_luma_coding_block_size = get_uvlc(br)+3; sps->log2_diff_max_min_pcm_luma_coding_block_size = get_uvlc(br); sps->pcm_loop_filter_disable_flag = get_bits(br,1); } sps->num_short_term_ref_pic_sets = get_uvlc(br); // --- allocate reference pic set --- // allocate one more for the ref-pic-set that may be sent in the slice header *ref_pic_sets = (ref_pic_set *)calloc(sizeof(ref_pic_set), sps->num_short_term_ref_pic_sets + 1); for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++) { //alloc_ref_pic_set(&(*ref_pic_sets)[i], //sps->sps_max_dec_pic_buffering[sps->sps_max_sub_layers-1]); read_short_term_ref_pic_set(br,*ref_pic_sets, i, sps->num_short_term_ref_pic_sets); dump_short_term_ref_pic_set(&(*ref_pic_sets)[i]); } sps->long_term_ref_pics_present_flag = get_bits(br,1); if (sps->long_term_ref_pics_present_flag) { sps->num_long_term_ref_pics_sps = get_uvlc(br); if (sps->num_long_term_ref_pics_sps > 32) { return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; } for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++ ) { sps->lt_ref_pic_poc_lsb_sps[i] = get_bits(br, sps->log2_max_pic_order_cnt_lsb); sps->used_by_curr_pic_lt_sps_flag[i] = get_bits(br,1); } } else { sps->num_long_term_ref_pics_sps = 0; // NOTE: missing definition in standard ! } sps->sps_temporal_mvp_enabled_flag = get_bits(br,1); sps->strong_intra_smoothing_enable_flag = get_bits(br,1); sps->vui_parameters_present_flag = get_bits(br,1); if (sps->vui_parameters_present_flag) { assert(false); /* vui_parameters() sps_extension_flag u(1) if( sps_extension_flag ) while( more_rbsp_data() ) sps_extension_data_flag u(1) rbsp_trailing_bits() */ } sps->sps_extension_flag = get_bits(br,1); if (sps->sps_extension_flag) { assert(false); } check_rbsp_trailing_bits(br); // --- compute derived values --- sps->BitDepth_Y = sps->bit_depth_luma; sps->QpBdOffset_Y = 6*(sps->bit_depth_luma-8); sps->BitDepth_C = sps->bit_depth_chroma; sps->QpBdOffset_C = 6*(sps->bit_depth_chroma-8); sps->Log2MinCbSizeY = sps->log2_min_luma_coding_block_size; sps->Log2CtbSizeY = sps->Log2MinCbSizeY + sps->log2_diff_max_min_luma_coding_block_size; sps->MinCbSizeY = 1 << sps->Log2MinCbSizeY; sps->CtbSizeY = 1 << sps->Log2CtbSizeY; sps->PicWidthInMinCbsY = sps->pic_width_in_luma_samples / sps->MinCbSizeY; sps->PicWidthInCtbsY = ceil_div(sps->pic_width_in_luma_samples, sps->CtbSizeY); sps->PicHeightInMinCbsY = sps->pic_height_in_luma_samples / sps->MinCbSizeY; sps->PicHeightInCtbsY = ceil_div(sps->pic_height_in_luma_samples,sps->CtbSizeY); sps->PicSizeInMinCbsY = sps->PicWidthInMinCbsY * sps->PicHeightInMinCbsY; sps->PicSizeInCtbsY = sps->PicWidthInCtbsY * sps->PicHeightInCtbsY; sps->PicSizeInSamplesY = sps->pic_width_in_luma_samples * sps->pic_height_in_luma_samples; if (sps->chroma_format_idc==0 || sps->separate_colour_plane_flag) { sps->CtbWidthC = 0; sps->CtbHeightC = 0; } else { sps->CtbWidthC = sps->CtbSizeY / sps->SubWidthC; sps->CtbHeightC = sps->CtbSizeY / sps->SubHeightC; } sps->Log2MinTrafoSize = sps->log2_min_transform_block_size; sps->Log2MaxTrafoSize = sps->log2_min_transform_block_size + sps->log2_diff_max_min_transform_block_size; // the following are not in the standard sps->PicWidthInTbsY = sps->PicWidthInCtbsY << (sps->Log2CtbSizeY - sps->Log2MinTrafoSize); sps->PicHeightInTbsY = sps->PicHeightInCtbsY << (sps->Log2CtbSizeY - sps->Log2MinTrafoSize); sps->PicSizeInTbsY = sps->PicWidthInTbsY * sps->PicHeightInTbsY; sps->sps_read = true; return DE265_OK; }
void read_pps(bitreader* br, pic_parameter_set* pps, decoder_context* ctx) { pps->pic_parameter_set_id = get_uvlc(br); pps->seq_parameter_set_id = get_uvlc(br); pps->dependent_slice_segments_enabled_flag = get_bits(br,1); pps->output_flag_present_flag = get_bits(br,1); pps->num_extra_slice_header_bits = get_bits(br,3); pps->sign_data_hiding_flag = get_bits(br,1); pps->cabac_init_present_flag = get_bits(br,1); pps->num_ref_idx_l0_default_active = get_uvlc(br)+1; pps->num_ref_idx_l1_default_active = get_uvlc(br)+1; seq_parameter_set* sps = get_sps(ctx, pps->seq_parameter_set_id); pps->pic_init_qp = get_svlc(br)+26; pps->constrained_intra_pred_flag = get_bits(br,1); pps->transform_skip_enabled_flag = get_bits(br,1); pps->cu_qp_delta_enabled_flag = get_bits(br,1); if (pps->cu_qp_delta_enabled_flag) { pps->diff_cu_qp_delta_depth = get_uvlc(br); } else { pps->diff_cu_qp_delta_depth = 0; } pps->pic_cb_qp_offset = get_svlc(br); pps->pic_cr_qp_offset = get_svlc(br); pps->pps_slice_chroma_qp_offsets_present_flag = get_bits(br,1); pps->weighted_pred_flag = get_bits(br,1); pps->weighted_bipred_flag = get_bits(br,1); pps->transquant_bypass_enable_flag = get_bits(br,1); pps->tiles_enabled_flag = get_bits(br,1); pps->entropy_coding_sync_enabled_flag = get_bits(br,1); // --- tiles --- if (pps->tiles_enabled_flag ) { pps->num_tile_columns = get_uvlc(br)+1; pps->num_tile_rows = get_uvlc(br)+1; pps->uniform_spacing_flag = get_bits(br,1); assert(pps->num_tile_columns <= DE265_MAX_TILE_COLUMNS); assert(pps->num_tile_rows <= DE265_MAX_TILE_ROWS); if (pps->uniform_spacing_flag==false) { int lastColumnWidth = sps->PicWidthInCtbsY; int lastRowHeight = sps->PicHeightInCtbsY; for (int i=0; i<pps->num_tile_columns-1; i++) { pps->colWidth[i] = get_uvlc(br)+1; lastColumnWidth -= pps->colWidth[i]; } pps->colWidth[pps->num_tile_columns-1] = lastColumnWidth; for (int i=0; i<pps->num_tile_rows-1; i++) { pps->rowHeight[i] = get_uvlc(br)+1; lastRowHeight -= pps->rowHeight[i]; } pps->rowHeight[pps->num_tile_rows-1] = lastRowHeight; } pps->loop_filter_across_tiles_enabled_flag = get_bits(br,1); } else { pps->num_tile_columns = 1; pps->num_tile_rows = 1; pps->uniform_spacing_flag = 1; } if (pps->uniform_spacing_flag) { // set columns widths int *const colPos = (int *)alloca((pps->num_tile_columns+1) * sizeof(int)); for (int i=0; i<=pps->num_tile_columns; i++) { colPos[i] = i*sps->PicWidthInCtbsY / pps->num_tile_columns; } for (int i=0; i<pps->num_tile_columns; i++) { pps->colWidth[i] = colPos[i+1] - colPos[i]; } // set row heights int *const rowPos = (int *)alloca((pps->num_tile_rows+1) * sizeof(int)); for (int i=0; i<=pps->num_tile_rows; i++) { rowPos[i] = i*sps->PicHeightInCtbsY / pps->num_tile_rows; } for (int i=0; i<pps->num_tile_rows; i++) { pps->rowHeight[i] = rowPos[i+1] - rowPos[i]; } } // set tile boundaries pps->colBd[0]=0; for (int i=0; i<pps->num_tile_columns; i++) { pps->colBd[i+1] = pps->colBd[i] + pps->colWidth[i]; } pps->rowBd[0]=0; for (int i=0; i<pps->num_tile_rows; i++) { pps->rowBd[i+1] = pps->rowBd[i] + pps->rowHeight[i]; } // alloc raster scan arrays if (pps->CtbAddrRStoTS) { free(pps->CtbAddrRStoTS); } if (pps->CtbAddrTStoRS) { free(pps->CtbAddrTStoRS); } if (pps->TileId) { free(pps->TileId); } if (pps->MinTbAddrZS) { free(pps->MinTbAddrZS); } pps->CtbAddrRStoTS = (int *)malloc( sizeof(int) * sps->PicSizeInCtbsY ); pps->CtbAddrTStoRS = (int *)malloc( sizeof(int) * sps->PicSizeInCtbsY ); pps->TileId = (int *)malloc( sizeof(int) * sps->PicSizeInCtbsY ); pps->MinTbAddrZS = (int *)malloc( sizeof(int) * sps->PicSizeInTbsY ); // raster scan (RS) <-> tile scan (TS) conversion for (int ctbAddrRS=0 ; ctbAddrRS < sps->PicSizeInCtbsY ; ctbAddrRS++) { int tbX = ctbAddrRS % sps->PicWidthInCtbsY; int tbY = ctbAddrRS / sps->PicWidthInCtbsY; int tileX=-1,tileY=-1; for (int i=0; i<pps->num_tile_columns; i++) if (tbX >= pps->colBd[i]) tileX=i; for (int j=0; j<pps->num_tile_rows; j++) if (tbY >= pps->rowBd[j]) tileY=j; pps->CtbAddrRStoTS[ctbAddrRS] = 0; for (int i=0; i<tileX; i++) pps->CtbAddrRStoTS[ctbAddrRS] += pps->rowHeight[tileY]*pps->colWidth[i]; for (int j=0; j<tileY; j++) { //pps->CtbAddrRStoTS[ctbAddrRS] += (tbY - pps->rowBd[tileY])*pps->colWidth[tileX]; //pps->CtbAddrRStoTS[ctbAddrRS] += tbX - pps->colBd[tileX]; pps->CtbAddrRStoTS[ctbAddrRS] += sps->PicWidthInCtbsY * pps->rowHeight[j]; } assert(tileX>=0 && tileY>=0); pps->CtbAddrRStoTS[ctbAddrRS] += (tbY-pps->rowBd[tileY])*pps->colWidth[tileX]; pps->CtbAddrRStoTS[ctbAddrRS] += tbX - pps->colBd[tileX]; // inverse mapping pps->CtbAddrTStoRS[ pps->CtbAddrRStoTS[ctbAddrRS] ] = ctbAddrRS; } logtrace(LogHeaders,"6.5.1 CtbAddrRSToTS\n"); for (int y=0; y<sps->PicHeightInCtbsY; y++) { for (int x=0; x<sps->PicWidthInCtbsY; x++) { logtrace(LogHeaders,"%3d ", pps->CtbAddrRStoTS[x + y*sps->PicWidthInCtbsY]); } logtrace(LogHeaders,"\n"); } // tile id for (int j=0, tIdx=0 ; j<pps->num_tile_rows ; j++) for (int i=0 ; i<pps->num_tile_columns; i++) { for (int y=pps->rowBd[j] ; y<pps->rowBd[j+1] ; y++) for (int x=pps->colBd[j] ; x<pps->colBd[j+1] ; x++) pps->TileId[ pps->CtbAddrRStoTS[y*sps->PicWidthInCtbsY + x] ] = tIdx; tIdx++; } // 6.5.2 Z-scan order array initialization process for (int y=0; y<sps->PicHeightInTbsY; y++) for (int x=0; x<sps->PicWidthInTbsY; x++) { int tbX = (x<<sps->Log2MinTrafoSize)>>sps->Log2CtbSizeY; int tbY = (y<<sps->Log2MinTrafoSize)>>sps->Log2CtbSizeY; int ctbAddrRS = sps->PicWidthInCtbsY*tbY + tbX; pps->MinTbAddrZS[x + y*sps->PicWidthInTbsY] = pps->CtbAddrRStoTS[ctbAddrRS] << ((sps->Log2CtbSizeY-sps->Log2MinTrafoSize)*2); int p=0; for (int i=0 ; i<(sps->Log2CtbSizeY - sps->Log2MinTrafoSize) ; i++) { int m=1<<i; p += (m & x ? m*m : 0) + (m & y ? 2*m*m : 0); } pps->MinTbAddrZS[x + y*sps->PicWidthInTbsY] += p; } // --- debug logging --- /* logtrace(LogHeaders,"6.5.2 Z-scan order array\n"); for (int y=0;y<sps->PicHeightInTbsY;y++) { for (int x=0;x<sps->PicWidthInTbsY;x++) { logtrace(LogHeaders,"%4d ", pps->MinTbAddrZS[x + y*sps->PicWidthInTbsY]); } logtrace(LogHeaders,"\n"); } for (int i=0;i<sps->PicSizeInTbsY;i++) { for (int y=0;y<sps->PicHeightInTbsY;y++) { for (int x=0;x<sps->PicWidthInTbsY;x++) { if (pps->MinTbAddrZS[x + y*sps->PicWidthInTbsY] == i) { logtrace(LogHeaders,"%d %d\n",x,y); } } } } */ // END tiles pps->Log2MinCuQpDeltaSize = sps->Log2CtbSizeY - pps->diff_cu_qp_delta_depth; pps->beta_offset = 0; // default value pps->tc_offset = 0; // default value pps->pps_loop_filter_across_slices_enabled_flag = get_bits(br,1); pps->deblocking_filter_control_present_flag = get_bits(br,1); if (pps->deblocking_filter_control_present_flag) { pps->deblocking_filter_override_enabled_flag = get_bits(br,1); pps->pic_disable_deblocking_filter_flag = get_bits(br,1); if (!pps->pic_disable_deblocking_filter_flag) { pps->beta_offset = get_svlc(br)*2; pps->tc_offset = get_svlc(br)*2; } } else { pps->deblocking_filter_override_enabled_flag = 0; pps->pic_disable_deblocking_filter_flag = 0; } pps->pic_scaling_list_data_present_flag = get_bits(br,1); if (pps->pic_scaling_list_data_present_flag) { assert(false); //scaling_list_data() } pps->lists_modification_present_flag = get_bits(br,1); pps->log2_parallel_merge_level = get_uvlc(br)+2; pps->slice_segment_header_extension_present_flag = get_bits(br,1); pps->pps_extension_flag = get_bits(br,1); if (pps->pps_extension_flag) { assert(false); /* while( more_rbsp_data() ) pps_extension_data_flag u(1) rbsp_trailing_bits() } */ } pps->pps_read = true; }
/* A ref-pic-set is coded either coded - as a list of the relative POC deltas themselves, or - by shifting an existing ref-pic-set by some number of frames When shifting an existing set, the frame 0 is also shifted as an additional reference frame. When coding the ref-pic-sets in the SPS, predicition is always from the previous set. In the slice header, the ref-pic-set can use any previous set as reference. */ bool read_short_term_ref_pic_set(decoder_context* ctx, const seq_parameter_set* sps, bitreader* br, ref_pic_set* out_set, // where to store the read set int idxRps, // index of the set to be read const ref_pic_set* sets, // previously read sets bool sliceRefPicSet) // is this in the slice header? { // --- is this set coded in prediction mode (not possible for the first set) char inter_ref_pic_set_prediction_flag; if (idxRps != 0) { inter_ref_pic_set_prediction_flag = get_bits(br,1); } else { inter_ref_pic_set_prediction_flag = 0; } if (inter_ref_pic_set_prediction_flag) { int vlc; /* Only for the last ref_pic_set (that's the one coded in the slice header), we can specify relative to which reference set we code the set. */ int delta_idx; if (sliceRefPicSet) { // idxRps == num_short_term_ref_pic_sets) { delta_idx = vlc = get_uvlc(br); delta_idx++; } else { delta_idx = 1; } int RIdx = idxRps - delta_idx; // this is our source set, which we will modify assert(RIdx>=0); int delta_rps_sign = get_bits(br,1); int abs_delta_rps = vlc = get_uvlc(br); abs_delta_rps++; int DeltaRPS = (delta_rps_sign ? -abs_delta_rps : abs_delta_rps); // bits are stored in this order: // - all bits for negative Pocs (forward), // - then all bits for positive Pocs (forward), // - then bits for '0', shifting of the current picture // in total, these are 'nDeltaPocsRIdx'+1 bits logtrace(LogHeaders,"predicted from %d with delta %d\n",RIdx,DeltaRPS); int nDeltaPocsRIdx= sets[RIdx].NumDeltaPocs; // size of source set char *const used_by_curr_pic_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char)); char *const use_delta_flag = (char *)alloca((nDeltaPocsRIdx+1) * sizeof(char)); for (int j=0;j<=nDeltaPocsRIdx;j++) { used_by_curr_pic_flag[j] = get_bits(br,1); if (used_by_curr_pic_flag[j]) { use_delta_flag[j] = 1; // if this frame is used, we also have to apply the delta } else { use_delta_flag[j] = get_bits(br,1); // otherwise, it is only optionally included } } logtrace(LogHeaders,"flags: "); for (int j=0;j<=nDeltaPocsRIdx;j++) { logtrace(LogHeaders,"%d ", use_delta_flag[j]); } logtrace(LogHeaders,"\n"); int nNegativeRIdx = sets[RIdx].NumNegativePics; int nPositiveRIdx = sets[RIdx].NumPositivePics; // --- update list 0 (negative Poc) --- // Iterate through all Pocs in decreasing value order (positive reverse, 0, negative forward). int i=0; // target index // positive list for (int j=nPositiveRIdx-1;j>=0;j--) { int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS; // new delta if (dPoc<0 && use_delta_flag[nNegativeRIdx+j]) { out_set->DeltaPocS0[i] = dPoc; out_set->UsedByCurrPicS0[i] = used_by_curr_pic_flag[nNegativeRIdx+j]; i++; } } // frame 0 if (DeltaRPS<0 && use_delta_flag[nDeltaPocsRIdx]) { out_set->DeltaPocS0[i] = DeltaRPS; out_set->UsedByCurrPicS0[i] = used_by_curr_pic_flag[nDeltaPocsRIdx]; i++; } // negative list for (int j=0;j<nNegativeRIdx;j++) { int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS; if (dPoc<0 && use_delta_flag[j]) { out_set->DeltaPocS0[i] = dPoc; out_set->UsedByCurrPicS0[i] = used_by_curr_pic_flag[j]; i++; } } out_set->NumNegativePics = i; // --- update list 1 (positive Poc) --- // Iterate through all Pocs in increasing value order (negative reverse, 0, positive forward) i=0; // target index // negative list for (int j=nNegativeRIdx-1;j>=0;j--) { int dPoc = sets[RIdx].DeltaPocS0[j] + DeltaRPS; if (dPoc>0 && use_delta_flag[j]) { out_set->DeltaPocS1[i] = dPoc; out_set->UsedByCurrPicS1[i] = used_by_curr_pic_flag[j]; i++; } } // frame 0 if (DeltaRPS>0 && use_delta_flag[nDeltaPocsRIdx]) { out_set->DeltaPocS1[i] = DeltaRPS; out_set->UsedByCurrPicS1[i] = used_by_curr_pic_flag[nDeltaPocsRIdx]; i++; } // positive list for (int j=0;j<nPositiveRIdx;j++) { int dPoc = sets[RIdx].DeltaPocS1[j] + DeltaRPS; if (dPoc>0 && use_delta_flag[nNegativeRIdx+j]) { out_set->DeltaPocS1[i] = dPoc; out_set->UsedByCurrPicS1[i] = used_by_curr_pic_flag[nNegativeRIdx+j]; i++; } } out_set->NumPositivePics = i; out_set->NumDeltaPocs = out_set->NumNegativePics + out_set->NumPositivePics; } else { // --- first, read the number of past and future frames in this set --- int num_negative_pics = get_uvlc(br); int num_positive_pics = get_uvlc(br); // total number of reference pictures may not exceed buffer capacity if (num_negative_pics + num_positive_pics > sps->sps_max_dec_pic_buffering[ sps->sps_max_sub_layers-1 ]) { add_warning(ctx, DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED, false); return false; } out_set->NumNegativePics = num_negative_pics; out_set->NumPositivePics = num_positive_pics; out_set->NumDeltaPocs = num_positive_pics + num_negative_pics; // --- now, read the deltas between the reference frames to fill the lists --- // past frames int lastPocS=0; for (int i=0;i<num_negative_pics;i++) { int delta_poc_s0 = get_uvlc(br)+1; char used_by_curr_pic_s0_flag = get_bits(br,1); out_set->DeltaPocS0[i] = lastPocS - delta_poc_s0; out_set->UsedByCurrPicS0[i] = used_by_curr_pic_s0_flag; lastPocS = out_set->DeltaPocS0[i]; } // future frames lastPocS=0; for (int i=0;i<num_positive_pics;i++) { int delta_poc_s1 = get_uvlc(br)+1; char used_by_curr_pic_s1_flag = get_bits(br,1); out_set->DeltaPocS1[i] = lastPocS + delta_poc_s1; out_set->UsedByCurrPicS1[i] = used_by_curr_pic_s1_flag; lastPocS = out_set->DeltaPocS1[i]; } } compute_NumPoc(out_set); return true; }