//7.3.2.3 Supplemental enhancement information RBSP syntax void structure(sei_rbsp)(h264_stream_t* h, bs_t* b) { if( is_reading ) { for( int i = 0; i < h->num_seis; i++ ) { sei_free(h->seis[i]); } h->num_seis = 0; do { h->num_seis++; h->seis = (sei_t**)realloc(h->seis, h->num_seis * sizeof(sei_t*)); h->seis[h->num_seis - 1] = sei_new(); h->sei = h->seis[h->num_seis - 1]; structure(sei_message)(h, b); } while( more_rbsp_data(h, b) ); } if( is_writing ) { for (int i = 0; i < h->num_seis; i++) { h->sei = h->seis[i]; structure(sei_message)(h, b); } h->sei = NULL; } structure(rbsp_trailing_bits)(h, b); }
int ff_hevc_decode_nal_sei(HEVCContext *s) { do { decode_nal_sei_message(s); } while (more_rbsp_data(&s->HEVClc.gb)); return 0; }
/** Same as previous but without SliceIgroup table. */ void PPSCut (unsigned char *data, PPS *pps, SPS *sps, int NalBytesInNalunit ) { int Position = 8; unsigned char Pps_id = (unsigned char) read_ue(data, &Position); unsigned char Sps_id = (unsigned char) read_ue(data, &Position); unsigned char pic_parameter_set_id = CLIP3(0, PPS_BUF_SIZE - 1, Pps_id); unsigned char seq_parameter_set_id = CLIP3(0, SPS_BUF_SIZE - 1, Sps_id); PPS *pt_pps = &pps[pic_parameter_set_id]; pt_pps -> seq_parameter_set_id = seq_parameter_set_id; //Initialization of the maximun number of pps if(pic_parameter_set_id > pps[0] . MaxPpsId){ pps[0] . MaxPpsId = pic_parameter_set_id; } PpsFirstHeader(data, &Position, pt_pps); PpsSliceGroupHeaderCut(data, &Position, pt_pps); PpsEndOfHeader(data, &Position, pt_pps); if( more_rbsp_data(data, &Position, &NalBytesInNalunit) ) { // Position < NalBytesInNalunit << 3 SPS *pt_sps = &sps[seq_parameter_set_id]; PpsHighProfile(data, &Position, pt_pps, pt_sps); } rbsp_trailing_bits(&Position); }
/*! ************************************************************************ * \brief * Check if there are symbols for the next MB ************************************************************************ */ int uvlc_startcode_follows(struct img_par *img, struct inp_par *inp, int dummy) { int dp_Nr = assignSE2partition[img->currentSlice->dp_mode][SE_MBTYPE]; DataPartition *dP = &(img->currentSlice->partArr[dp_Nr]); Bitstream *currStream = dP->bitstream; byte *buf = currStream->streamBuffer; //KS: new function test for End of Buffer return (!(more_rbsp_data(buf, currStream->frame_bitoffset,currStream->bitstream_length))); }
int ff_hevc_decode_nal_sei(HEVCContext *s) { int ret; do { ret = decode_nal_sei_message(s); if (ret < 0) return(AVERROR(ENOMEM)); } while (more_rbsp_data(&s->HEVClc->gb)); return 1; }
int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, const HEVCParamSets *ps, int type) { int ret; do { ret = decode_nal_sei_message(gb, logctx, s, ps, type); if (ret < 0) return ret; } while (more_rbsp_data(gb)); return 1; }
/* decode_one_slice() */ AVCDec_Status DecodeSlice(AVCDecObject *decvid) { AVCDec_Status status; AVCCommonObj *video = decvid->common; AVCSliceHeader *sliceHdr = video->sliceHdr; AVCMacroblock *currMB ; AVCDecBitstream *stream = decvid->bitstream; uint slice_group_id; uint CurrMbAddr, moreDataFlag; /* set the first mb in slice */ CurrMbAddr = sliceHdr->first_mb_in_slice; slice_group_id = video->MbToSliceGroupMap[CurrMbAddr]; if ((CurrMbAddr && (CurrMbAddr != (uint)(video->mbNum + 1))) && video->currSeqParams->constrained_set1_flag == 1) { ConcealSlice(decvid, video->mbNum, CurrMbAddr); } moreDataFlag = 1; video->mb_skip_run = -1; /* while loop , see subclause 7.3.4 */ do { if (CurrMbAddr >= video->PicSizeInMbs) { return AVCDEC_FAIL; } currMB = video->currMB = &(video->mblock[CurrMbAddr]); video->mbNum = CurrMbAddr; currMB->slice_id = video->slice_id; // slice /* we can remove this check if we don't support Mbaff. */ /* we can wrap below into an initMB() function which will also do necessary reset of macroblock related parameters. */ video->mb_x = CurrMbAddr % video->PicWidthInMbs; video->mb_y = CurrMbAddr / video->PicWidthInMbs; /* check the availability of neighboring macroblocks */ InitNeighborAvailability(video, CurrMbAddr); /* read_macroblock and decode_one_macroblock() */ status = DecodeMB(decvid); if (status != AVCDEC_SUCCESS) { return status; } #ifdef MB_BASED_DEBLOCK if (video->currPicParams->num_slice_groups_minus1 == 0) { MBInLoopDeblock(video); /* MB-based deblocking */ } else /* this mode cannot be used if the number of slice group is not one. */ { return AVCDEC_FAIL; } #endif video->numMBs--; moreDataFlag = more_rbsp_data(stream); /* go to next MB */ while (++CurrMbAddr < video->PicSizeInMbs && video->MbToSliceGroupMap[CurrMbAddr] != (int)slice_group_id) { } } while ((moreDataFlag && video->numMBs > 0) || video->mb_skip_run > 0); /* even if no more data, but last few MBs are skipped */ if (video->numMBs == 0) { video->newPic = TRUE; video->mbNum = 0; // _Conceal return AVCDEC_PICTURE_READY; } return AVCDEC_SUCCESS; }
//7.3.2.2 Picture parameter set RBSP syntax void structure(pic_parameter_set_rbsp)(h264_stream_t* h, bs_t* b) { pps_t* pps = h->pps; if( is_reading ) { memset(pps, 0, sizeof(pps_t)); } value( pps->pic_parameter_set_id, ue); value( pps->seq_parameter_set_id, ue ); value( pps->entropy_coding_mode_flag, u1 ); value( pps->pic_order_present_flag, u1 ); value( pps->num_slice_groups_minus1, ue ); if( pps->num_slice_groups_minus1 > 0 ) { value( pps->slice_group_map_type, ue ); if( pps->slice_group_map_type == 0 ) { for( int i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++ ) { value( pps->run_length_minus1[ i_group ], ue ); } } else if( pps->slice_group_map_type == 2 ) { for( int i_group = 0; i_group < pps->num_slice_groups_minus1; i_group++ ) { value( pps->top_left[ i_group ], ue ); value( pps->bottom_right[ i_group ], ue ); } } else if( pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4 || pps->slice_group_map_type == 5 ) { value( pps->slice_group_change_direction_flag, u1 ); value( pps->slice_group_change_rate_minus1, ue ); } else if( pps->slice_group_map_type == 6 ) { value( pps->pic_size_in_map_units_minus1, ue ); for( int i = 0; i <= pps->pic_size_in_map_units_minus1; i++ ) { int v = intlog2( pps->num_slice_groups_minus1 + 1 ); value( pps->slice_group_id[ i ], u(v) ); } } } value( pps->num_ref_idx_l0_active_minus1, ue ); value( pps->num_ref_idx_l1_active_minus1, ue ); value( pps->weighted_pred_flag, u1 ); value( pps->weighted_bipred_idc, u(2) ); value( pps->pic_init_qp_minus26, se ); value( pps->pic_init_qs_minus26, se ); value( pps->chroma_qp_index_offset, se ); value( pps->deblocking_filter_control_present_flag, u1 ); value( pps->constrained_intra_pred_flag, u1 ); value( pps->redundant_pic_cnt_present_flag, u1 ); int have_more_data = 0; if( is_reading ) { have_more_data = more_rbsp_data(h, b); } if( is_writing ) { have_more_data = pps->transform_8x8_mode_flag | pps->pic_scaling_matrix_present_flag | pps->second_chroma_qp_index_offset != 0; } if( have_more_data ) { value( pps->transform_8x8_mode_flag, u1 ); value( pps->pic_scaling_matrix_present_flag, u1 ); if( pps->pic_scaling_matrix_present_flag ) { for( int i = 0; i < 6 + 2* pps->transform_8x8_mode_flag; i++ ) { value( pps->pic_scaling_list_present_flag[ i ], u1 ); if( pps->pic_scaling_list_present_flag[ i ] ) { if( i < 6 ) { structure(scaling_list)( b, pps->ScalingList4x4[ i ], 16, &( pps->UseDefaultScalingMatrix4x4Flag[ i ] ) ); } else { structure(scaling_list)( b, pps->ScalingList8x8[ i - 6 ], 64, &( pps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ) ); } } } } value( pps->second_chroma_qp_index_offset, se ); } structure(rbsp_trailing_bits)(h, b); if( is_reading ) { memcpy(h->pps, h->pps_table[pps->pic_parameter_set_id], sizeof(pps_t)); } }
void RBSP_decode(NALunit nal_unit) { static int nalBrojac=0; static int idr_frame_number=0; printf("Entering RBPS_decode #%d\n",nalBrojac++); initRawReader(nal_unit.rbsp_byte, nal_unit.NumBytesInRBSP); //TYPE 7 = Sequence parameter set TODO: Provjera postoji li veæ SPS //READ SPS if (nal_unit.nal_unit_type==NAL_UNIT_TYPE_SEI) { printf("RBSP_decode -> Not supported NAL unit type: SEI (type 6)\n"); } else if (nal_unit.nal_unit_type==NAL_UNIT_TYPE_SPS) { fill_sps(&nal_unit); init_h264_structures(); AllocateMemory(); } //TYPE 8 = Picture parameter set TODO: Provjera postoji li veæ PPS i SPS else if (nal_unit.nal_unit_type==NAL_UNIT_TYPE_PPS) { fill_pps(&nal_unit); } //IDR or NOT IDR slice data //////////////////////////////////////////////////////////////////// //Actual picture decoding takes place here //The main loop works macroblock by macroblock until the end of the slice //Macroblock skipping is implemented else if ((nal_unit.nal_unit_type==NAL_UNIT_TYPE_IDR) || (nal_unit.nal_unit_type==NAL_UNIT_TYPE_NOT_IDR)) { frameCount++; //Read slice header fill_shd(&nal_unit); printf("Working on frame #%d...\n", frameCount); int MbCount=shd.PicSizeInMbs; //Norm: firstMbAddr=first_mb_in_slice * ( 1 + MbaffFrameFlag ); int firstMbAddr = 0; CurrMbAddr = firstMbAddr; //Norm: moreDataFlag = 1 bool moreDataFlag = true; //Norm: prevMbSkipped = 0 int prevMbSkipped = 0; //Used later on int mb_skip_run; // Prediction samples formed by either intra or inter prediction. int predL[16][16], predCb[8][8], predCr[8][8]; QPy = shd.SliceQPy; while (moreDataFlag && CurrMbAddr<MbCount) { /*for (int i = 0; i < 4; i++) ChromaDCLevel[0][i] = ChromaDCLevel[1][i] = 0; for (int i = 0; i < 16; i++) LumaDCLevel[i] = 0;*/ if ((shd.slice_type%5)!=I_SLICE && (shd.slice_type%5)!=SI_SLICE) { //First decode various data at the beggining of each slice/frame //Norm: if( !entropy_coding_mode_flag ) ... this "if clause" is skipped. mb_skip_run=expGolomb_UD(); prevMbSkipped = (mb_skip_run > 0); for(int i=0; i<mb_skip_run; i++ ) { if (CurrMbAddr >= MbCount) { break; } mb_type = P_Skip; mb_type_array[CurrMbAddr]=P_Skip; // Inter prediction: DeriveMVs(); Decode(predL, predCr, predCb); // Norm: QpBdOffsetY == 0 in baseline QPy = (QPy + mb_qp_delta + 52) % 52; // Inverse transformation and decoded sample construction: transformDecodingP_Skip(predL, predCb, predCr, QPy); //Norm: CurrMbAddr = NextMbAddress( CurrMbAddr ) CurrMbAddr++; } if ((CurrMbAddr != firstMbAddr) || (mb_skip_run > 0)) { moreDataFlag = more_rbsp_data(); } } if(moreDataFlag) { // Norm: start macroblock_layer() mb_pos_array[CurrMbAddr]=(RBSP_current_bit+1)&7; mb_type = expGolomb_UD(); mb_type_array[CurrMbAddr]=mb_type; if ((mb_type > 31) || ((shd.slice_type == I_SLICE) && (mb_type > 24))) { printf("Fatal error: Unexpected mb_type value (%d)\n", mb_type); printf("Slice type: %d\n", shd.slice_type); printf("Frame #%d, CurrMbAddr = %d\n", frameCount, CurrMbAddr); system("pause"); writeToPPM("errorFrame"); // dump the current frame exit(1); } //Norm: if( mb_type != I_NxN && MbPartPredMode( mb_type, 0 ) != Intra_16x16 && NumMbPart( mb_type ) == 4 ) // I_NxN is an alias for Intra_4x4 and Intra_8x8 MbPartPredMode (mb_type in both cases equal to 0) // mb_type (positive integer value) is equal to "Name of mb_type" (i.e. I_NxN). These are often interchanged in the norm // Everything as described in norm page 119. table 7-11. //Specific inter prediction? // Norm: if (mb_type != I_NxN && MbPartPredMode(mb_type,0) != Intra_16x16 && NumMbPart(mb_type) == 4) if(MbPartPredMode(mb_type,0) != Intra_4x4 && MbPartPredMode( mb_type, 0 )!=Intra_16x16 && NumMbPart( mb_type )==4 ) { // Norm: start sub_mb_pred(mb_type) int mbPartIdx; for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { sub_mb_type[mbPartIdx]=expGolomb_UD(); } for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if ((shd.num_ref_idx_active_override_flag > 0) && (mb_type != P_8x8ref0) && (SubMbPredMode(sub_mb_type[mbPartIdx]) != Pred_L1)) { ref_idx_l0_array[CurrMbAddr][mbPartIdx] = expGolomb_TD(); } } // Norm: there are no B-frames in baseline, so the stream // does not contain ref_idx_l1 or mvd_l1 for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { for (int subMbPartIdx = 0; subMbPartIdx < NumSubMbPart(sub_mb_type[mbPartIdx]); subMbPartIdx++) { mvd_l0[mbPartIdx][subMbPartIdx][0] = expGolomb_SD(); mvd_l0[mbPartIdx][subMbPartIdx][1] = expGolomb_SD(); } } // Norm: end sub_mb_pred(mb_type) } else { //Norm: This is section "mb_pred( mb_type )" if(MbPartPredMode(mb_type, 0) == Intra_4x4 /*|| MbPartPredMode(mb_type, 0) == Intra_8x8*/ || MbPartPredMode(mb_type, 0) == Intra_16x16 ) { if(MbPartPredMode(mb_type, 0) == Intra_4x4) { for(int luma4x4BlkIdx=0; luma4x4BlkIdx<16; luma4x4BlkIdx++) { prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = (bool)getRawBit(); if(prev_intra4x4_pred_mode_flag[luma4x4BlkIdx]==false) { rem_intra4x4_pred_mode[luma4x4BlkIdx]=getRawBits(3); } } } //Norm: //if( MbPartPredMode( mb_type, 0 ) = = Intra_8x8 ) //This if clause has been skipped, because "intra_8x8" is not supported in baseline. //Norm: //if( ChromaArrayType == 1 || ChromaArrayType == 2 ) //baseline defines "ChromaArrayType==1", so the if clause is skipped intra_chroma_pred_mode=expGolomb_UD(); if (intra_chroma_pred_mode > 3) { printf("Fatal error: Unexpected intra_chroma_pred_mode value (%d)\n", intra_chroma_pred_mode); printf("Frame #%d, CurrMbAddr = %d\n", frameCount, CurrMbAddr); system("pause"); writeToPPM("errorFrame"); // dump the current frame exit(1); } } else { int mbPartIdx; for (mbPartIdx = 0; mbPartIdx < NumMbPart(mb_type); mbPartIdx++) { if ((shd.num_ref_idx_l0_active_minus1 > 0) && (MbPartPredMode(mb_type, mbPartIdx) != Pred_L1)) { ref_idx_l0_array[CurrMbAddr][mbPartIdx] = expGolomb_TD(); } } // Norm: there are no B-frames in baseline, so the stream // does not contain ref_idx_l1 or mvd_l1 for (mbPartIdx = 0; mbPartIdx < NumMbPart(mb_type); ++mbPartIdx) { if (MbPartPredMode(mb_type, mbPartIdx) != Pred_L1) { mvd_l0[mbPartIdx][0][0] = expGolomb_SD(); mvd_l0[mbPartIdx][0][1] = expGolomb_SD(); } } } // Norm: end mb_pred(mb_type) } //If the next if clause does not execute, this is the final value of coded block patterns for this macroblock CodedBlockPatternLuma=-1; CodedBlockPatternChroma=-1; if(MbPartPredMode(mb_type,0)!=Intra_16x16) { int coded_block_pattern=expGolomb_UD(); if (coded_block_pattern > 47) { printf("Fatal error: Unexpected coded_block_pattern value (%d)\n", coded_block_pattern); printf("Frame #%d, CurrMbAddr = %d\n", frameCount, CurrMbAddr); system("pause"); writeToPPM("errorFrame"); // dump the current frame exit(1); } //This is not real coded_block_pattern, it's the coded "codeNum" value which is now being decoded: if(MbPartPredMode(mb_type,0)==Intra_4x4 /*|| MbPartPredMode(mb_type,0)==Intra_8x8*/ ) { coded_block_pattern=codeNum_to_coded_block_pattern_intra[coded_block_pattern]; } //Inter prediction else { coded_block_pattern=codeNum_to_coded_block_pattern_inter[coded_block_pattern]; } CodedBlockPatternLuma=coded_block_pattern & 15; CodedBlockPatternChroma=coded_block_pattern >> 4; //Norm: /* if( CodedBlockPatternLuma > 0 && transform_8x8_mode_flag && mb_type != I_NxN && noSubMbPartSizeLessThan8x8Flag && ( mb_type != B_Direct_16x16 || direct_8x8_inference_flag)) */ //This if clause is not implemented since transform_8x8_mode_flag is not supported } //DOES NOT EXIST IN THE NORM! else { if (shd.slice_type % 5 == I_SLICE) { CodedBlockPatternChroma=I_Macroblock_Modes[mb_type][5]; CodedBlockPatternLuma=I_Macroblock_Modes[mb_type][6]; } else { CodedBlockPatternChroma=P_and_SP_macroblock_modes[mb_type][5]; CodedBlockPatternLuma=P_and_SP_macroblock_modes[mb_type][6]; } } CodedBlockPatternLumaArray[CurrMbAddr] = CodedBlockPatternLuma; CodedBlockPatternChromaArray[CurrMbAddr] = CodedBlockPatternChroma; if(CodedBlockPatternLuma>0 || CodedBlockPatternChroma>0 || MbPartPredMode(mb_type,0)==Intra_16x16) { mb_qp_delta=expGolomb_SD(); if ((mb_qp_delta < -26) || (mb_qp_delta > 25)) { printf("Fatal error: Unexpected mb_qp_delta value (%d)\n", mb_qp_delta); printf("Frame #%d, CurrMbAddr = %d\n", frameCount, CurrMbAddr); system("pause"); writeToPPM("errorFrame"); // dump the current frame exit(1); } //Norm: decode residual data. //residual_block_cavlc( coeffLevel, startIdx, endIdx, maxNumCoeff ) residual(0, 15); } else { clear_residual_structures(); } // Norm: end macroblock_layer() //Data ready for rendering // Norm: QpBdOffsetY == 0 in baseline QPy = (QPy + mb_qp_delta + 52) % 52; if ((MbPartPredMode(mb_type , 0) == Intra_4x4) || (MbPartPredMode(mb_type , 0) == Intra_16x16)) { intraPrediction(predL, predCr, predCb); } else { DeriveMVs(); Decode(predL, predCr, predCb); } if (MbPartPredMode(mb_type, 0) == Intra_16x16) { transformDecodingIntra_16x16Luma(Intra16x16DCLevel, Intra16x16ACLevel, predL, QPy); } else if (MbPartPredMode(mb_type, 0) != Intra_4x4) // Intra { for(int luma4x4BlkIdx = 0; luma4x4BlkIdx < 16; luma4x4BlkIdx++) { transformDecoding4x4LumaResidual(LumaLevel, predL, luma4x4BlkIdx, QPy); } } transformDecodingChroma(ChromaDCLevel[0], ChromaACLevel[0], predCb, QPy, true); transformDecodingChroma(ChromaDCLevel[1], ChromaACLevel[1], predCr, QPy, false); moreDataFlag=more_rbsp_data(); ++CurrMbAddr; }