/** Parses first data of pps. */ void PpsSliceGroupHeader(unsigned char *data, int *Position, PPS *pt_pps, unsigned char *SliceGroupId) { int i; int iGroup; if ( pt_pps -> num_slice_groups_minus1 > 0 ) { pt_pps -> slice_group_map_type = (unsigned char) read_ue(data, Position); if ( pt_pps -> slice_group_map_type == 0 ) for ( iGroup = 0 ; iGroup <= pt_pps -> num_slice_groups_minus1 ; iGroup++ ) pt_pps -> run_length_minus1 [iGroup] = (short) read_ue(data, Position); else if ( pt_pps -> slice_group_map_type == 2 ) for ( iGroup = 0 ; iGroup < pt_pps -> num_slice_groups_minus1 ; iGroup++ ) { pt_pps -> top_left_tab [iGroup] = (short) read_ue(data, Position);// pt_pps -> bottom_right_tab [iGroup] = (short) read_ue(data, Position);// } else if ( pt_pps -> slice_group_map_type == 3 || pt_pps -> slice_group_map_type == 4 || pt_pps -> slice_group_map_type == 5 ) { pt_pps -> slice_group_change_direction_flag = (unsigned char) getNbits(data, Position, 1); pt_pps -> slice_group_change_rate_minus1 = (short) read_ue(data, Position) + 1; } else if ( pt_pps -> slice_group_map_type == 6 ) { short log2_num_slice_groups_minus1 = (short) log_base2(pt_pps -> num_slice_groups_minus1 + 1); short pic_size_in_map_units_minus1 = (short) read_ue(data, Position); for ( i = 0 ; i <= pic_size_in_map_units_minus1 ; i++ ) { SliceGroupId [i] = (unsigned char) getNbits(data, Position, log2_num_slice_groups_minus1); } } } }
/*! * \param *dc The current DecodingContext. * \param *slice structure. * \return *rplm_t initialized data structure. */ static rplm_t *decodeRPLM(DecodingContext_t *dc, slice_t *slice) { TRACE_INFO(SLICE, " > " BLD_GREEN "decodeRPLM()\n" CLR_RESET); // RPLM allocation //////////////////////////////////////////////////////////////////////////// rplm_t *rplm = (rplm_t*)calloc(1, sizeof(rplm_t)); if (rplm == NULL) { TRACE_ERROR(SLICE, "Unable to alloc new RPLM!\n"); } else { // RPLM decoding //////////////////////////////////////////////////////////////////////// if (slice->slice_type % 5 != 2 && slice->slice_type % 5 != 4) { rplm->ref_pic_list_modification_flag_l0 = read_bit(dc->bitstr); if (rplm->ref_pic_list_modification_flag_l0) { do { rplm->modification_of_pic_nums_idc = read_ue(dc->bitstr); if (rplm->modification_of_pic_nums_idc == 0 || rplm->modification_of_pic_nums_idc == 1) { rplm->abs_diff_pic_num_minus1 = read_ue(dc->bitstr); } else if (rplm->modification_of_pic_nums_idc == 2) { rplm->long_term_pic_num = read_ue(dc->bitstr); } } while (rplm->modification_of_pic_nums_idc != 3); } } if (slice->slice_type % 5 == 1) { rplm->ref_pic_list_modification_flag_l1 = read_bit(dc->bitstr); if (rplm->ref_pic_list_modification_flag_l1) { do { rplm->modification_of_pic_nums_idc = read_ue(dc->bitstr); if (rplm->modification_of_pic_nums_idc == 0 || rplm->modification_of_pic_nums_idc == 1) { rplm->abs_diff_pic_num_minus1 = read_ue(dc->bitstr); } else if (rplm->modification_of_pic_nums_idc == 2) { rplm->long_term_pic_num = read_ue(dc->bitstr); } } while (rplm->modification_of_pic_nums_idc != 3); } } } return rplm; }
/*! * \param *dc The current DecodingContext. * \param mbAddr The current macroblock address. * \return 0 if macroblock decoding fail, 1 otherwise. * * This function extract one macroblock from the bitstream, handle intra/inter * prediction for its blocks. */ int macroblock_layer(DecodingContext_t *dc, const int mbAddr) { TRACE_INFO(MB, "<> " BLD_GREEN "macroblock_layer(" CLR_RESET "%i" BLD_GREEN ")\n" CLR_RESET, mbAddr); int retcode = FAILURE; // Macroblock allocation //////////////////////////////////////////////////////////////////////////// dc->mb_array[mbAddr] = (Macroblock_t*)calloc(1, sizeof(Macroblock_t)); if (dc->mb_array[mbAddr] == NULL) { TRACE_ERROR(MB, "Unable to alloc new macroblock!\n"); } else { // Set macroblock address dc->mb_array[mbAddr]->mbAddr = mbAddr; // Shortcuts pps_t *pps = dc->pps_array[dc->active_slice->pic_parameter_set_id]; sps_t *sps = dc->sps_array[pps->seq_parameter_set_id]; slice_t *slice = dc->active_slice; Macroblock_t *mb = dc->mb_array[mbAddr]; // Macroblock decoding //////////////////////////////////////////////////////////////////////// #if ENABLE_DEBUG mb->mbFileAddrStart = bitstream_get_absolute_bit_offset(dc->bitstr); #endif // ENABLE_DEBUG deriv_macroblockneighbours_availability(dc, mbAddr); MbPosition(mb, sps); if (pps->entropy_coding_mode_flag) mb->mb_type = read_ae(dc, SE_mb_type); else mb->mb_type = read_ue(dc->bitstr); mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0); mb->NumMbPart = NumMbPart(slice->slice_type, mb->mb_type); if (mb->mb_type == I_PCM) { #if ENABLE_IPCM TRACE_3(MB, "---- macroblock_layer - I PCM macroblock\n"); while (bitstream_check_alignment(dc->bitstr) == false) { if (read_bit(dc->bitstr) != 0) // pcm_alignment_zero_bit { TRACE_ERROR(MB, " Error while reading pcm_alignment_zero_bit: must be 0!\n"); return FAILURE; } } // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2 initCabacDecodingEngine(dc); int i = 0; for (i = 0; i < 256; i++) { mb->pcm_sample_luma[i] = (uint8_t)read_bits(dc->bitstr, sps->BitDepthY); } // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2 initCabacDecodingEngine(dc); for (i = 0; i < 2 * sps->MbWidthC * sps->MbHeightC; i++) { mb->pcm_sample_chroma[i] = (uint8_t)read_bits(dc->bitstr, sps->BitDepthC); } // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2 initCabacDecodingEngine(dc); #else // ENABLE_IPCM TRACE_ERROR(MB, "I_PCM decoding is currently disabled!\n"); return UNSUPPORTED; #endif // ENABLE_IPCM } else { #if ENABLE_INTER_PRED bool noSubMbPartSizeLessThan8x8Flag = true; if (mb->mb_type != I_NxN && mb->MbPartPredMode[0] != Intra_16x16 && mb->NumMbPart == 4) { TRACE_3(MB, "---- macroblock_layer - mb partition & related\n"); int mbPartIdx = 0; for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if (mb->sub_mb_type[mbPartIdx] != B_Direct_8x8) { if (NumSubMbPart(slice->slice_type, mb->sub_mb_type[mbPartIdx]) > 1) { noSubMbPartSizeLessThan8x8Flag = false; } } else if (sps->direct_8x8_inference_flag == false) { noSubMbPartSizeLessThan8x8Flag = false; } } // Read sub macroblock prediction mode sub_mb_pred(dc, mb->mb_type, mb->sub_mb_type); } else #endif // ENABLE_INTER_PRED { TRACE_3(MB, "---- macroblock_layer - transform_size_8x8_flag & prediction modes\n"); if (pps->transform_8x8_mode_flag == true && mb->mb_type == I_NxN) { if (pps->entropy_coding_mode_flag) mb->transform_size_8x8_flag = read_ae(dc, SE_transform_size_8x8_flag); else mb->transform_size_8x8_flag = read_bit(dc->bitstr); // Need to update MbPartPredMode in order to detect I_8x8 prediction mode mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0); } // Read macroblock prediction mode mb_pred(dc, mb); } if (mb->MbPartPredMode[0] != Intra_16x16) { TRACE_3(MB, "---- macroblock_layer - coded block pattern & transform_size_8x8_flag\n"); if (pps->entropy_coding_mode_flag) mb->coded_block_pattern = read_ae(dc, SE_coded_block_pattern); else mb->coded_block_pattern = read_me(dc->bitstr, sps->ChromaArrayType, dc->IdrPicFlag); mb->CodedBlockPatternLuma = mb->coded_block_pattern % 16; mb->CodedBlockPatternChroma = mb->coded_block_pattern / 16; #if ENABLE_INTER_PRED if (mb->CodedBlockPatternLuma > 0 && pps->transform_8x8_mode_flag == true && mb->mb_type != I_NxN && noSubMbPartSizeLessThan8x8Flag == true && (mb->mb_type != B_Direct_16x16 || sps->direct_8x8_inference_flag == true)) { if (pps->entropy_coding_mode_flag) mb->transform_size_8x8_flag = read_ae(dc, SE_transform_size_8x8_flag); else mb->transform_size_8x8_flag = read_bit(dc->bitstr); // Need to update MbPartPredMode in order to account for I_8x8 prediction mode if (transform_size_8x8_flag) mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0); } #endif // ENABLE_INTER_PRED } if (mb->CodedBlockPatternLuma > 0 || mb->CodedBlockPatternChroma > 0 || mb->MbPartPredMode[0] == Intra_16x16) { TRACE_3(MB, "---- macroblock_layer - quantization parameter & residual datas\n"); // Read QP delta if (pps->entropy_coding_mode_flag) mb->mb_qp_delta = read_ae(dc, SE_mb_qp_delta); else mb->mb_qp_delta = read_se(dc->bitstr); // Parse the residual coefficients //////////////////////////////////////////////////////////////// // Luma levels residual_luma(dc, 0, 15); // Chroma levels residual_chroma(dc, 0, 15); } else { TRACE_3(MB, "---- macroblock_layer - No residual datas to decode in this macroblock\n"); } // Compute luma Quantization Parameters if (mb->mb_qp_delta) mb->QPY = ((slice->QPYprev + mb->mb_qp_delta + 52 + sps->QpBdOffsetY*2) % (52 + sps->QpBdOffsetY)) - sps->QpBdOffsetY; else mb->QPY = slice->QPYprev; mb->QPprimeY = mb->QPY + sps->QpBdOffsetY; slice->QPYprev = mb->QPY; // Set Transform Bypass Mode if (sps->qpprime_y_zero_transform_bypass_flag == true && mb->QPprimeY == 0) mb->TransformBypassModeFlag = true; // Prediction process (include quantization and transformation stages) //////////////////////////////////////////////////////////////// if (dc->IdrPicFlag) { retcode = intra_prediction_process(dc, mb); } else { retcode = inter_prediction_process(dc, mb); } // Print macroblock(s) header and block data ? //////////////////////////////////////////////////////////////// #if ENABLE_DEBUG mb->mbFileAddrStop = bitstream_get_absolute_bit_offset(dc->bitstr) - 1; int frame_debug_range[2] = {-1, -1}; // Range of (idr) frame(s) to debug/analyse int mb_debug_range[2] = {-1, -1}; // Range of macroblock(s) to debug/analyse if (dc->idrCounter >= frame_debug_range[0] && dc->idrCounter <= frame_debug_range[1]) { if (mb->mbAddr >= mb_debug_range[0] && mb->mbAddr <= mb_debug_range[1]) { print_macroblock_layer(dc, mb); print_macroblock_pixel_residual(mb); print_macroblock_pixel_predicted(mb); print_macroblock_pixel_final(mb); } } #endif // ENABLE_DEBUG } TRACE_3(MB, "---- macroblock_layer - the end\n\n"); } return retcode; }
/*! * \param *dc The current DecodingContext. * \param mb_type The macroblock prediction type. * \param *sub_mb_type The sub macroblock prediction type. * * Find the sub macroblock prediction type (intra prediction mode or motion vectors exctraction). */ static void sub_mb_pred(DecodingContext_t *dc, const unsigned int mb_type, unsigned int *sub_mb_type) { TRACE_INFO(MB, " > " BLD_GREEN "sub_mb_pred()\n" CLR_RESET); // Shortcut Macroblock_t *mb = dc->mb_array[dc->CurrMbAddr]; slice_t *slice = dc->active_slice; // Read sub_mb_type int mbPartIdx = 0; for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if (dc->entropy_coding_mode_flag) sub_mb_type[mbPartIdx] = read_ae(dc, SE_sub_mb_type); else sub_mb_type[mbPartIdx] = read_ue(dc->bitstr); } // ref_idx_l0 for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if ((slice->num_ref_idx_l0_active_minus1 > 0 || slice->mb_field_decoding_flag != slice->field_pic_flag) && mb_type != P_8x8ref0 && sub_mb_type[mbPartIdx] != B_Direct_8x8 && SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L1) { if (dc->entropy_coding_mode_flag) mb->ref_idx_l0[mbPartIdx] = read_ae(dc, SE_ref_idx_lx); else mb->ref_idx_l0[mbPartIdx] = read_te(dc->bitstr, 0); } } // ref_idx_l1 for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if ((slice->num_ref_idx_l1_active_minus1 > 0 || slice->mb_field_decoding_flag != slice->field_pic_flag) && sub_mb_type[mbPartIdx] != B_Direct_8x8 && SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L0) { if (dc->entropy_coding_mode_flag) mb->ref_idx_l1[mbPartIdx] = read_ae(dc, SE_ref_idx_lx); else mb->ref_idx_l1[mbPartIdx] = read_te(dc->bitstr, 0); } } // mvd_l0 for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if (sub_mb_type[mbPartIdx] != B_Direct_8x8 && SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L1) { int subMbPartIdx = 0; for (subMbPartIdx = 0; subMbPartIdx < NumSubMbPart(slice->slice_type, sub_mb_type[mbPartIdx]); subMbPartIdx++) { if (dc->entropy_coding_mode_flag) { mb->mvd_l0[mbPartIdx][subMbPartIdx][0] = read_ae(dc, SE_mvd_lx0); mb->mvd_l0[mbPartIdx][subMbPartIdx][1] = read_ae(dc, SE_mvd_lx1); } else { mb->mvd_l0[mbPartIdx][subMbPartIdx][0] = read_se(dc->bitstr); mb->mvd_l0[mbPartIdx][subMbPartIdx][1] = read_se(dc->bitstr); } } } } // mvd_l1 for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if (sub_mb_type[mbPartIdx] != B_Direct_8x8 && SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L0) { int subMbPartIdx = 0; for (subMbPartIdx = 0; subMbPartIdx < NumSubMbPart(slice->slice_type, sub_mb_type[mbPartIdx]); subMbPartIdx++) { if (dc->entropy_coding_mode_flag) { mb->mvd_l1[mbPartIdx][subMbPartIdx][0] = read_ae(dc, SE_mvd_lx0); mb->mvd_l1[mbPartIdx][subMbPartIdx][1] = read_ae(dc, SE_mvd_lx1); } else { mb->mvd_l1[mbPartIdx][subMbPartIdx][0] = read_se(dc->bitstr); mb->mvd_l1[mbPartIdx][subMbPartIdx][1] = read_se(dc->bitstr); } } } } }
/*! * \brief Read prediction informations for current macroblock. * \param *dc The current DecodingContext. * \param *mb The current macroblock. * * Intra prediction infos are a table containing prediction mode for each blocks. * Inter prediction infos are motion vectors. */ static void mb_pred(DecodingContext_t *dc, Macroblock_t *mb) { TRACE_INFO(MB, " > " BLD_GREEN "mb_pred()\n" CLR_RESET); if (mb->MbPartPredMode[0] == Intra_4x4 || mb->MbPartPredMode[0] == Intra_8x8 || mb->MbPartPredMode[0] == Intra_16x16) { if (mb->MbPartPredMode[0] == Intra_4x4) { // Read intra prediction mode for all 16 4x4 luma blocks unsigned int luma4x4BlkIdx = 0; for (luma4x4BlkIdx = 0; luma4x4BlkIdx < 16; luma4x4BlkIdx++) { if (dc->entropy_coding_mode_flag) mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = read_ae(dc, SE_prev_intraxxx_pred_mode_flag); else mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = read_bit(dc->bitstr); if (mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] == false) { if (dc->entropy_coding_mode_flag) mb->rem_intra4x4_pred_mode[luma4x4BlkIdx] = read_ae(dc, SE_rem_intraxxx_pred_mode); else mb->rem_intra4x4_pred_mode[luma4x4BlkIdx] = read_bits(dc->bitstr, 3); } } } else if (mb->MbPartPredMode[0] == Intra_8x8) { // Read intra prediction mode for all 4 8x8 luma blocks unsigned int luma8x8BlkIdx = 0; for (luma8x8BlkIdx = 0; luma8x8BlkIdx < 4; luma8x8BlkIdx++) { if (dc->entropy_coding_mode_flag) mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] = read_ae(dc, SE_prev_intraxxx_pred_mode_flag); else mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] = read_bit(dc->bitstr); if (mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] == false) { if (dc->entropy_coding_mode_flag) mb->rem_intra8x8_pred_mode[luma8x8BlkIdx] = read_ae(dc, SE_rem_intraxxx_pred_mode); else mb->rem_intra8x8_pred_mode[luma8x8BlkIdx] = read_bits(dc->bitstr, 3); } } } // Read intra prediction mode for chroma blocks if (dc->ChromaArrayType == 1 || dc->ChromaArrayType == 2) { if (dc->entropy_coding_mode_flag) mb->IntraChromaPredMode = read_ae(dc, SE_intra_chroma_pred_mode); else mb->IntraChromaPredMode = read_ue(dc->bitstr); } } else if (mb->MbPartPredMode[0] != Direct) { // ref_idx_l0 unsigned int mbPartIdx = 0; for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if ((dc->active_slice->num_ref_idx_l0_active_minus1 > 0 || dc->active_slice->mb_field_decoding_flag != dc->active_slice->field_pic_flag) && MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L1) { if (dc->entropy_coding_mode_flag) mb->ref_idx_l0[mbPartIdx] = read_ae(dc, SE_ref_idx_lx); else mb->ref_idx_l0[mbPartIdx] = read_te(dc->bitstr, 0); } } // ref_idx_l1 for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if ((dc->active_slice->num_ref_idx_l1_active_minus1 > 0 || dc->active_slice->mb_field_decoding_flag != dc->active_slice->field_pic_flag) && MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L0) { if (dc->entropy_coding_mode_flag) mb->ref_idx_l1[mbPartIdx] = read_ae(dc, SE_ref_idx_lx); else mb->ref_idx_l1[mbPartIdx] = read_te(dc->bitstr, 0); } } // mvd_l0 for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if (MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L1) { if (dc->entropy_coding_mode_flag) { mb->mvd_l0[mbPartIdx][0][0] = read_ae(dc, SE_mvd_lx0); mb->mvd_l0[mbPartIdx][0][1] = read_ae(dc, SE_mvd_lx1); } else { mb->mvd_l0[mbPartIdx][0][0] = read_te(dc->bitstr, 0); mb->mvd_l0[mbPartIdx][0][1] = read_te(dc->bitstr, 0); } } } // mvd_l1 for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if (MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L0) { if (dc->entropy_coding_mode_flag) { mb->mvd_l1[mbPartIdx][0][0] = read_ae(dc, SE_mvd_lx0); mb->mvd_l1[mbPartIdx][0][1] = read_ae(dc, SE_mvd_lx1); } else { mb->mvd_l1[mbPartIdx][0][0] = read_te(dc->bitstr, 0); mb->mvd_l1[mbPartIdx][0][1] = read_te(dc->bitstr, 0); } } } } }
/** Parses first data of pps. */ void PpsFirstHeader(unsigned char *data, int *Position, PPS *pt_pps) { pt_pps -> entropy_coding_mode_flag = (unsigned char) getNbits(data, Position, 1); pt_pps -> pic_order_present_flag = (unsigned char) getNbits(data, Position, 1); pt_pps -> num_slice_groups_minus1 = (unsigned char) read_ue(data, Position); }
/*! * \param *dc The current DecodingContext. * \param *slice structre. * \return *drpm_t initialized data structure. */ static drpm_t *decodeDRPM(DecodingContext_t *dc, slice_t *slice) { TRACE_INFO(SLICE, " > " BLD_GREEN "decodeDRPM()\n" CLR_RESET); // DRPM allocation //////////////////////////////////////////////////////////////////////////// drpm_t *drpm = (drpm_t*)calloc(1, sizeof(drpm_t)); if (drpm == NULL) { TRACE_ERROR(SLICE, "Unable to alloc new DRPM!\n"); } else { // DRPM decoding //////////////////////////////////////////////////////////////////////// if (dc->IdrPicFlag) { drpm->no_output_of_prior_pics_flag = read_bit(dc->bitstr); drpm->long_term_reference_flag = read_bit(dc->bitstr); } else { drpm->adaptive_ref_pic_marking_mode_flag = read_bit(dc->bitstr); if (drpm->adaptive_ref_pic_marking_mode_flag) { do { drpm->memory_management_control_operation = read_ue(dc->bitstr); if (drpm->memory_management_control_operation == 1 || drpm->memory_management_control_operation == 3) { drpm->difference_of_pic_nums_minus1 = read_ue(dc->bitstr); } else if (drpm->memory_management_control_operation == 2) { drpm->long_term_pic_num = read_ue(dc->bitstr); } else if (drpm->memory_management_control_operation == 3 || drpm->memory_management_control_operation == 6) { drpm->long_term_frame_idx = read_ue(dc->bitstr); } else if (drpm->memory_management_control_operation == 4) { drpm->max_long_term_frame_idx_plus1 = read_ue(dc->bitstr); if (drpm->max_long_term_frame_idx_plus1 > 0) { drpm->MaxLongTermFrameIdx = drpm->max_long_term_frame_idx_plus1 - 1; } else { //FIXME 8.2.5.4.4 Decoding process for MaxLongTermFrameIdx } } } while (drpm->memory_management_control_operation != 0); } } } return drpm; }
/*! * \param *dc The current DecodingContext. * \param *slice The current Slice. */ static int decodeSliceHeader(DecodingContext_t *dc, slice_t *slice) { TRACE_INFO(SLICE, "> " BLD_GREEN "decodeSliceHeader()\n" CLR_RESET); // Slice header decoding //////////////////////////////////////////////////////////////////////////// slice->first_mb_in_slice = read_ue(dc->bitstr); slice->slice_type = read_ue(dc->bitstr); slice->pic_parameter_set_id = read_ue(dc->bitstr); // Shortcuts pps_t *pps = dc->pps_array[slice->pic_parameter_set_id]; sps_t *sps = dc->sps_array[pps->seq_parameter_set_id]; if (sps->separate_colour_plane_flag) { slice->colour_plane_id = read_bits(dc->bitstr, 2); } slice->frame_num = read_bits(dc->bitstr, sps->log2_max_frame_num_minus4 + 4); if (sps->frame_mbs_only_flag == false) { slice->field_pic_flag = read_bit(dc->bitstr); if (slice->field_pic_flag) { slice->bottom_field_flag = read_bit(dc->bitstr); slice->MaxPicNum = sps->MaxFrameNum*2; slice->CurrPicNum = slice->frame_num*2 + 1; } else { slice->MaxPicNum = sps->MaxFrameNum; slice->CurrPicNum = slice->frame_num; } } slice->MbaffFrameFlag = sps->mb_adaptive_frame_field_flag && !slice->field_pic_flag; slice->PicHeightInMbs = sps->FrameHeightInMbs / (1 + slice->field_pic_flag); slice->PicHeightInSamplesL = slice->PicHeightInMbs * 16; slice->PicHeightInSamplesC = slice->PicHeightInMbs * sps->MbHeightC; slice->PicSizeInMbs = sps->PicWidthInMbs * slice->PicHeightInMbs; if (dc->IdrPicFlag) { slice->PrevRefFrameNum = 0; slice->idr_pic_id = read_ue(dc->bitstr); } if (sps->pic_order_cnt_type == 0) { slice->pic_order_cnt_lsb = read_bits(dc->bitstr, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); if (pps->bottom_field_pic_order_in_frame_present_flag && slice->field_pic_flag == false) { slice->delta_pic_order_cnt_bottom = read_se(dc->bitstr); } } else if (sps->pic_order_cnt_type == 1 && sps->delta_pic_order_always_zero_flag == false) { slice->delta_pic_order_cnt[0] = read_se(dc->bitstr); if (pps->bottom_field_pic_order_in_frame_present_flag && slice->field_pic_flag == false) { slice->delta_pic_order_cnt[1] = read_se(dc->bitstr); } } if (pps->redundant_pic_cnt_present_flag) { slice->redundant_pic_cnt = read_ue(dc->bitstr); } if (slice->slice_type == 1 || slice->slice_type == 6) // B frame { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (B frame)\n"); return UNSUPPORTED; slice->direct_spatial_mv_pred_flag = read_bit(dc->bitstr); } if (slice->slice_type == 0 || slice->slice_type == 5 || slice->slice_type == 3 || slice->slice_type == 8 || slice->slice_type == 1 || slice->slice_type == 6) // P, SP, B frame { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (P, SP, B frame)\n"); return UNSUPPORTED; /* slice->num_ref_idx_active_override_flag = read_bit(dc->bitstr); if (slice->num_ref_idx_active_override_flag) { slice->num_ref_idx_l0_active_minus1 = read_ue(dc->bitstr); if (slice->slice_type == 1 || slice->slice_type == 6) // B frame { slice->num_ref_idx_l1_active_minus1 = read_ue(dc->bitstr); } } */ } if (dc->active_nalu->nal_unit_type == 20) { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (unit_type == 20: MVC extension)\n"); return UNSUPPORTED; } else { // RPLM slice->rplm = decodeRPLM(dc, slice); } if ((pps->weighted_pred_flag == true && (slice->slice_type == 0 || slice->slice_type == 5 || slice->slice_type == 3 || slice->slice_type == 8)) || (pps->weighted_bipred_idc == 1 && (slice->slice_type == 1 || slice->slice_type == 6))) // P, SP, B frame { // PWT slice->pwt = decodePWT(dc, slice); } if (dc->active_nalu->nal_ref_idc != 0) { // DRPM slice->drpm = decodeDRPM(dc, slice); } if (pps->entropy_coding_mode_flag == true && ((slice->slice_type != 2 && slice->slice_type != 7) && (slice->slice_type != 4 && slice->slice_type != 9))) // Not I or SI frame { slice->cabac_init_idc = read_ue(dc->bitstr); } slice->slice_qp_delta = read_se(dc->bitstr); slice->SliceQPY = 26 + pps->pic_init_qp_minus26 + slice->slice_qp_delta; slice->QPYprev = slice->SliceQPY; // Set QPYprev value to use it in the first macroblock if (slice->slice_type == 3 || slice->slice_type == 8 || slice->slice_type == 4 || slice->slice_type == 9) // SP, SI frame { #if ENABLE_SWITCHING_SLICE if (slice->slice_type == 4 || slice->slice_type == 9) { slice->sp_for_switch_flag = read_bit(dc->bitstr); } slice->slice_qs_delta = read_se(dc->bitstr); slice->SliceQSY = 26 + pps->pic_init_qs_minus26 + slice->slice_qs_delta; #else /* ENABLE_SWITCHING_SLICE */ TRACE_ERROR(SLICE, ">>> UNSUPPORTED (slice_type == SP || slice_type == SI)\n"); return UNSUPPORTED; #endif /* ENABLE_SWITCHING_SLICE */ } if (pps->deblocking_filter_control_present_flag) { slice->disable_deblocking_filter_idc = read_ue(dc->bitstr); if (slice->disable_deblocking_filter_idc != 1) { slice->slice_alpha_c0_offset_div2 = read_se(dc->bitstr); slice->slice_beta_offset_div2 = read_se(dc->bitstr); slice->FilterOffsetA = slice->slice_alpha_c0_offset_div2 << 1; slice->FilterOffsetB = slice->slice_beta_offset_div2 << 1; } } if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (FMO)\n"); return UNSUPPORTED; } // Check content return checkSliceHeader(dc); }
/*! * \param *dc The current DecodingContext. * \param *slice The current Slice. * \return 0 if an error occurred while decoding slice datas, 1 otherwise. */ static int decodeSliceData(DecodingContext_t *dc, slice_t *slice) { TRACE_INFO(SLICE, "> " BLD_GREEN "decodeSliceData()\n" CLR_RESET); // Initialization int retcode = SUCCESS; dc->CurrMbAddr = 0; slice->moreDataFlag = true; slice->prevMbSkipped = false; // Shortcut pps_t *pps = dc->pps_array[slice->pic_parameter_set_id]; // Slice data decoding //////////////////////////////////////////////////////////////////////////// if (pps->entropy_coding_mode_flag) { // CABAC alignment while (bitstream_check_alignment(dc->bitstr) == false) { if (read_bit(dc->bitstr) == 0) // cabac_alignment_one_bit { TRACE_ERROR(SLICE, "cabac_alignment_one_bit must be 1\n"); return FAILURE; } } // CABAC initialization process initCabacContextVariables(dc); initCabacDecodingEngine(dc); } while ((retcode == SUCCESS) && (slice->moreDataFlag == true) && (dc->CurrMbAddr < dc->PicSizeInMbs)) { #if ENABLE_INTER_PRED // Only I frames are supported anyway if (slice->slice_type != 2 && slice->slice_type != 7 && slice->slice_type != 4 && slice->slice_type != 9) // Not I or SI slice { if (pps->entropy_coding_mode_flag) { slice->mb_skip_flag = read_ae(dc, SE_mb_skip_flag); slice->moreDataFlag = !slice->mb_skip_flag; } else { int i = 0; slice->mb_skip_run = read_ue(dc->bitstr); slice->prevMbSkipped = (slice->mb_skip_run > 0); for (i = 0; i < slice->mb_skip_run; i++) { dc->CurrMbAddr = NextMbAddress(dc, dc->CurrMbAddr); } if (slice->mb_skip_run > 0) { slice->moreDataFlag = h264_more_rbsp_data(dc->bitstr); } } } // If there is still some data in the slice if (slice->moreDataFlag) { #if ENABLE_MBAFF if (slice->MbaffFrameFlag == true && (dc->CurrMbAddr % 2 == 0 || (dc->CurrMbAddr % 2 == 1 && slice->prevMbSkipped == true))) { if (pps->entropy_coding_mode_flag) slice->mb_field_decoding_flag = read_ae(dc, SE_mb_field_decoding_flag); else slice->mb_field_decoding_flag = read_bit(dc->bitstr); TRACE_ERROR(DSLICE, ">>> UNSUPPORTED (interlaced mode)\n"); return UNSUPPORTED; } #endif /* ENABLE_MBAFF */ // Macroblock decoding retcode = macroblock_layer(dc, dc->CurrMbAddr); } #endif /* ENABLE_INTER_PRED */ // Macroblock decoding retcode = macroblock_layer(dc, dc->CurrMbAddr); // Check for end of slice if (pps->entropy_coding_mode_flag) { #if ENABLE_INTER_PRED // Only I frames are supported anyway if (slice->slice_type != 2 && slice->slice_type != 7 && slice->slice_type != 4 && slice->slice_type != 9) // Not I or SI slice { slice->prevMbSkipped = slice->mb_skip_flag; } #if ENABLE_MBAFF // MbaffFrameFlag is unsupported, so always "false" if (slice->MbaffFrameFlag == true && dc->CurrMbAddr % 2 == 0) { slice->moreDataFlag = true; } else #endif /* ENABLE_MBAFF */ #endif /* ENABLE_INTER_PRED */ { slice->end_of_slice_flag = read_ae(dc, SE_end_of_slice_flag); if (slice->end_of_slice_flag) { TRACE_INFO(SLICE, "end_of_slice_flag detected!\n"); slice->moreDataFlag = false; } } } else { slice->moreDataFlag = h264_more_rbsp_data(dc->bitstr); } // Get next macroblock address dc->CurrMbAddr = NextMbAddress(dc, dc->CurrMbAddr); } return retcode; }
//for init access unit int slice_header_svc_cut(unsigned char *data, SPS *sps, PPS *pps, int *position, SLICE *Slice, NAL *Nal) { PPS *pt_pps_id ; SPS *pt_sps_id ; int PicParameterId; int SeqParameterId; //Read header data Slice -> first_mb_in_slice = read_ue(data, position); Slice -> slice_type = read_ue(data, position); if ( Slice -> slice_type > 4 ) { Slice -> slice_type -= 5 ; } PicParameterId = read_ue(data, position); Nal -> pic_parameter_id[Nal -> LayerId] = PicParameterId = CLIP3(0, PPS_BUF_SIZE - 1, PicParameterId); pt_pps_id = &pps[PicParameterId]; //Should be in slice header //Sometimes Subset SPS are after PPS (rtsp) if(pt_pps_id -> seq_parameter_set_id > sps[0] . MaxSpsId){ pt_pps_id -> seq_parameter_set_id = sps[0] . MaxSpsId; } SeqParameterId = pt_pps_id -> seq_parameter_set_id + (Nal -> LayerId ? 16: 0); pt_sps_id = &sps[SeqParameterId]; Slice -> frame_num = getNbits(data, position, pt_sps_id -> log2_max_frame_num ); //Read Frame parameter if ( !pt_sps_id -> frame_mbs_only_flag ) { Slice -> field_pic_flag = getNbits(data, position, 1); if ( Slice -> field_pic_flag ) { Slice->bottom_field_flag = getNbits(data, position, 1); } } else { Slice->field_pic_flag = 0; } if ( 1 == Nal -> IdrFlag) { Slice->idr_pic_id = read_ue(data, position);//idr_pic_id = } if ( pt_sps_id -> pic_order_cnt_type == 0 ) { Slice -> pic_order_cnt_lsb = getNbits(data, position, pt_sps_id -> log2_max_pic_order_cnt_lsb ); if ( pt_pps_id -> pic_order_present_flag && !Slice -> field_pic_flag ) Slice -> delta_pic_order_cnt_bottom = read_se(data, position); } if ( pt_sps_id -> pic_order_cnt_type == 1 && !pt_sps_id -> delta_pic_order_always_zero_flag ) { Slice -> delta_pic_order_cnt [0] = read_se(data, position); if ( pt_pps_id -> pic_order_present_flag && !Slice -> field_pic_flag ) Slice -> delta_pic_order_cnt [1] = read_se(data, position); } if ( pt_pps_id -> redundant_pic_cnt_present_flag ) { read_ue(data, position);//redundant_pic_cnt = } return 0; }
int macroblock_layer_in_scalable_extension(const NAL *Nal, const PPS *Pps, RESIDU *Current_residu, RESIDU *BaseResidu, const unsigned char *ai_pcData, int *position, const SLICE *ai_pstSlice, DATA Tab_Block[], const VLC_TABLES *vlc, unsigned char aio_tiNon_zero_count_cache [ ], unsigned char aio_tiSlice_table [ ], const short iMb_x, const short iMb_y, int direct_8x8_inference_flag, int *last_QP) { int noSubMbPartSizeLessThan8x8; int BaseModeFlag = 0; const int iCurrMbAddr = iMb_x + iMb_y * (short)(ai_pstSlice -> mb_stride); short intra4x4_pred_mode_cache[40]; DATA * aio_pstBlock = &Tab_Block[iCurrMbAddr]; //TODO if( ai_pstSlice -> AdaptiveBaseModeFlag && Current_residu -> InCropWindow) { Current_residu -> BaseModeFlag = BaseModeFlag = getNbits(ai_pcData, position, 1); //u(1) }else if (ai_pstSlice -> DefaultBaseModeFlag){ Current_residu -> BaseModeFlag = BaseModeFlag = 1; } if(!BaseModeFlag){ int mb_type = read_ue(ai_pcData, position); //According to the slice type and the macroblock type //the parameters are adjusted switch ( ai_pstSlice -> slice_type ) { case EI : #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckMbType(mb_type, I_BL)){ return 1; } #endif aio_pstBlock -> MbPartPredMode [0] = i_mb_type_info[mb_type] . type; Current_residu -> MbType = i_mb_type_info[mb_type] . type; Current_residu -> Cbp = i_mb_type_info[mb_type] . Cbp; Current_residu -> Intra16x16PredMode = i_mb_type_info[mb_type] . pred_mode; break ; case EP : if (mb_type < 5){ #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckMbType(mb_type, P_BL)){ return 1; } #endif aio_pstBlock -> NumMbPart = p_mb_type_info[mb_type] . partcount; aio_pstBlock -> MbPartPredMode [0] = p_mb_type_info[mb_type] . type_0; aio_pstBlock -> MbPartPredMode [1] = p_mb_type_info[mb_type] . type_1; Current_residu -> MbType = p_mb_type_info[mb_type] . name; Current_residu -> Mode = p_mb_type_info[mb_type] . Mode; } else { mb_type -= 5; #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckMbType(mb_type, I_BL)){ return 1; } #endif aio_pstBlock -> MbPartPredMode [0] = i_mb_type_info[mb_type] . type; Current_residu -> MbType = i_mb_type_info[mb_type] . type; Current_residu -> Cbp = i_mb_type_info[mb_type] . Cbp; Current_residu -> Intra16x16PredMode = i_mb_type_info[mb_type] . pred_mode; } break ; case EB : if (mb_type < 23) { #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckMbType(mb_type, B_BL)){ return 1; } #endif aio_pstBlock -> NumMbPart = b_mb_type_info[mb_type] . partcount; aio_pstBlock -> MbPartPredMode [0] = b_mb_type_info[mb_type] . type_0; aio_pstBlock -> MbPartPredMode [1] = b_mb_type_info[mb_type] . type_1; Current_residu -> MbType = b_mb_type_info[mb_type] . name; Current_residu -> Mode = b_mb_type_info[mb_type] . Mode; } else { mb_type -= 23; #ifdef ERROR_DETECTION //Error detection if(ErrorsCheckMbType(mb_type, I_BL)){ return 1; } #endif aio_pstBlock -> MbPartPredMode [0] = i_mb_type_info[mb_type] . type; Current_residu -> MbType = i_mb_type_info[mb_type] . type; Current_residu -> Cbp = i_mb_type_info[mb_type] . Cbp; Current_residu -> Intra16x16PredMode = i_mb_type_info[mb_type] . pred_mode; } break; } //Initialize base macroblock address GetBaseMbAddr(Nal, aio_pstBlock, iMb_x << 4, iMb_y << 4); } else{ aio_pstBlock -> MbPartPredMode [0] = Current_residu -> MbType = GetBaseType(Nal, BaseResidu, aio_pstBlock, iMb_x, iMb_y); } //Updating the slice table in order to save in which slice each macroblock belong to Current_residu -> SliceNum = aio_tiSlice_table [iCurrMbAddr] = ai_pstSlice -> slice_num ; if ( !BaseModeFlag && Current_residu -> MbType == INTRA_PCM ) { while ( !bytes_aligned(*position) ) { getNbits(ai_pcData, position, 1);//pcm_alignment_zero_bit = } ParseIPCM(ai_pcData, position, Current_residu, aio_tiNon_zero_count_cache); } else { //Updating the parameter in order to decode the VLC fill_caches_svc( ai_pstSlice, Current_residu, BaseResidu, 0, aio_tiNon_zero_count_cache, aio_tiSlice_table, aio_pstBlock, intra4x4_pred_mode_cache, iMb_x, iMb_y, Pps -> constrained_intra_pred_flag, Nal -> TCoeffPrediction); if (!BaseModeFlag){ //Recovery of the motion vectors for the sub_macroblock if ( !IS_I(Current_residu -> MbType) && (aio_pstBlock -> NumMbPart == 4)) { int mbPartIdx; if(sub_mb_pred_svc(ai_pcData, position, ai_pstSlice, aio_pstBlock, Current_residu)){ return 1; } noSubMbPartSizeLessThan8x8 = 0; if ( direct_8x8_inference_flag ){ noSubMbPartSizeLessThan8x8 = 1; } for ( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx ++){ if ( sub_mb_type_name[ai_pstSlice -> slice_type][Current_residu -> SubMbType[mbPartIdx]] != B_direct){ if ( sub_num_part[ai_pstSlice -> slice_type][Current_residu -> SubMbType[mbPartIdx]] > 1 ) noSubMbPartSizeLessThan8x8 = 0; } } } else { noSubMbPartSizeLessThan8x8 = 1; if ( Pps -> transform_8x8_mode_flag && Current_residu -> MbType == INTRA_4x4 && getNbits(ai_pcData, position, 1)){ Current_residu -> MbType = Current_residu -> Transform8x8 = aio_pstBlock -> Transform8x8 = aio_pstBlock -> MbPartPredMode[0] = INTRA_8x8; } //Recovery of the prediction mode and the motion vectors for the macroblock if(mb_pred_svc(ai_pcData, position, ai_pstSlice, aio_pstBlock, Current_residu, intra4x4_pred_mode_cache)){ return 1; } } } //Decoding process of the VLC if( ai_pstSlice -> AdaptiveResidualPredictionFlag && ai_pstSlice -> slice_type != EI && (BaseModeFlag || ( !IS_I( Current_residu -> MbType) && Current_residu -> InCropWindow ))){ Current_residu -> ResidualPredictionFlag = getNbits(ai_pcData, position, 1); }else{ Current_residu -> ResidualPredictionFlag = ai_pstSlice -> DefaultResidualPredictionFlag; } if ( BaseModeFlag || aio_pstBlock -> MbPartPredMode[0] != INTRA_16x16 ){ Current_residu -> Cbp = read_me_svc(ai_pcData, position, aio_pstBlock -> MbPartPredMode[0],Current_residu, iCurrMbAddr, ai_pstSlice, iMb_x); if ( (Current_residu -> Cbp & 15) && Pps -> transform_8x8_mode_flag && (BaseModeFlag || (!IS_I(Current_residu -> MbType) && noSubMbPartSizeLessThan8x8 && ( Current_residu -> MbType == B_direct || direct_8x8_inference_flag))) && getNbits(ai_pcData, position, 1)){ Current_residu -> Transform8x8 = aio_pstBlock -> Transform8x8 = INTRA_8x8; } } if ( Current_residu -> Cbp > 0 || (Current_residu -> MbType == INTRA_16x16)) { int mb_qp_delta = read_se(ai_pcData, position); residual(ai_pcData, position, Current_residu, vlc, aio_tiNon_zero_count_cache); //In case of cbp is equal to zéro, we check if there is a DC level if (Current_residu -> Cbp == 0 && aio_tiNon_zero_count_cache[0] != 0){ Current_residu -> Cbp = 15; } if ( Current_residu -> MbType == INTRA_16x16 && !(Current_residu -> Cbp & 15) && (Current_residu -> Cbp & 0x30) && aio_tiNon_zero_count_cache[0]){ Current_residu -> Cbp += 15; } #ifdef TI_OPTIM *last_QP = Current_residu -> Qp = divide(*last_QP + mb_qp_delta + 52, 52) >> 8 ; #else *last_QP = Current_residu -> Qp = (*last_QP + mb_qp_delta + 52) % 52; #endif }else {
/** This function permits to decode from the bitstream the Sequence Parameter Set NAL unit. All the parameters decoded will be stored in the sps structure. @param data The NAL unit. @param position The current position in the NAL. @param NalBytesInNalunit The sizes of the NAL unit in bytes. @param sps The sps structure which contains all parameters decoded in this NAL. */ void seq_parameter_set_data ( unsigned char *data, int *position, SPS *pt_sps){ int i = 0 ; if( pt_sps -> profile_idc == 100 || pt_sps -> profile_idc == 110 || pt_sps -> profile_idc == 122 || pt_sps -> profile_idc == 244 || pt_sps -> profile_idc == 44 || pt_sps -> profile_idc == 83 || pt_sps -> profile_idc == 86 ) { pt_sps -> chroma_format_idc = read_ue(data, position); if( pt_sps -> chroma_format_idc == 3 ){ getNbits(data, position, 1);//separate_colour_plane_flag } pt_sps -> bit_depth_luma = read_ue(data, position) + 8; pt_sps -> bit_depth_chroma = read_ue(data, position) + 8; getNbits(data, position, 1);//qpprime_y_zero_transform_bypass_flag decode_scaling_matrices(data, position, pt_sps,1, pt_sps -> scaling_matrix4 , pt_sps -> scaling_matrix8); } pt_sps -> log2_max_frame_num = read_ue(data, position) + 4; pt_sps -> pic_order_cnt_type = read_ue(data, position); if ( pt_sps -> pic_order_cnt_type == 0 ) { pt_sps -> log2_max_pic_order_cnt_lsb = read_ue(data, position) + 4; } else if ( pt_sps -> pic_order_cnt_type == 1 ) { pt_sps -> delta_pic_order_always_zero_flag = getNbits(data, position, 1); pt_sps -> offset_for_non_ref_pic = read_se(data, position); pt_sps -> offset_for_top_to_bottom_field = read_se(data, position); pt_sps -> num_ref_frames_in_pic_order_cnt_cycle = read_ue(data, position); for (; i < pt_sps -> num_ref_frames_in_pic_order_cnt_cycle ; i++ ) { pt_sps -> offset_for_ref_frame [i] = read_se(data, position); } } pt_sps -> num_ref_frames = read_ue(data, position);// getNbits(data, position, 1);//gaps_in_frame_num_value_allowed_flag = pt_sps -> pic_width_in_mbs = read_ue(data, position) + 1; pt_sps -> pic_height_in_map_units = read_ue(data, position) + 1; pt_sps -> frame_mbs_only_flag = getNbits(data, position, 1); pt_sps -> PicSizeInMbs = pt_sps -> pic_width_in_mbs * pt_sps -> pic_height_in_map_units; if ( !pt_sps -> frame_mbs_only_flag ) { pt_sps -> MbAdaptiveFrameFieldFlag = getNbits(data, position, 1); } //To initialize the number of decoded frame before displaying. get_max_dpb(pt_sps); pt_sps -> direct_8x8_inference_flag = getNbits(data, position, 1); if ( getNbits(data, position, 1)) {//frame_cropping_flag pt_sps -> CropLeft = (read_ue(data, position)) << 1;//frame_crop_left_offset = pt_sps -> CropRight = (read_ue(data, position)) << 1;//frame_crop_right_offset = pt_sps -> CropTop = (read_ue(data, position)) << 1;//frame_crop_top_offset = pt_sps -> CropBottom = (read_ue(data, position)) << 1;//frame_crop_bottom_offset = } if ( getNbits(data, position, 1) ) { vui_parameters(data, position, pt_sps); } }
/** This function permits to get from the NAL unit additional parameters. VUI parameters are not required for constructing the luma and chroma samples by teh decoding process. @param data The NAL unit. @param position The current position in the NAL. */ void vui_parameters ( unsigned char *data, int *position, SPS *sps ) { int overscan_info_present_flag ; int video_signal_type_present_flag ; int bitstream_restriction_flag ; int aspect_ratio_info_present_flag = getNbits(data, position, 1); if ( aspect_ratio_info_present_flag ) { int aspect_ratio_idc = getNbits(data, position, 8); if ( aspect_ratio_idc == Extended_SAR ) { getNbits(data, position, 16);//sar_width = getNbits(data, position, 16);// sar_height = } } //scanner dans ffmpeg mais pas pris en compte overscan_info_present_flag = getNbits(data, position, 1); if ( overscan_info_present_flag ) getNbits(data, position, 1);// overscan_appropriate_flag = video_signal_type_present_flag = getNbits(data, position, 1); if ( video_signal_type_present_flag ) { getNbits(data, position, 3);//video_format = getNbits(data, position, 1);// video_full_range_flag = if (getNbits(data, position, 1)) { getNbits(data, position, 8);// colour_primaries = getNbits(data, position, 8);// transfer_characteristics = getNbits(data, position, 8);// matrix_coefficients = } } if (getNbits(data, position, 1)) { read_ue(data, position);//chroma_sample_loc_type_top_field = read_ue(data, position);// chroma_sample_loc_type_bottom_field = } //****************************************** if (getNbits(data, position, 1)) { get32bits(data, position);// num_units_in_tick = get32bits(data, position);//time_scale = getNbits(data, position, 1);// fixed_frame_rate_flag = } sps -> nal_hrd_parameters_present_flag = getNbits(data, position, 1); if ( sps -> nal_hrd_parameters_present_flag ) hrd_parameters(data, position,sps); sps -> vlc_hrd_parameters_present_flag = getNbits(data, position, 1); if ( sps -> vlc_hrd_parameters_present_flag ) hrd_parameters(data, position,sps); //scanner dans ffmpeg mais pas pris en compte if ( sps -> nal_hrd_parameters_present_flag || sps -> vlc_hrd_parameters_present_flag ) getNbits(data, position, 1);//low_delay_hrd_flag = //******************************************** sps -> pic_present_flag = getNbits(data, position, 1);// = bitstream_restriction_flag = getNbits(data, position, 1); if ( bitstream_restriction_flag ) { //scanner dans ffmpeg mais pas pris en compte getNbits(data, position, 1);// motion_vectors_over_pic_boundaries_flag = read_ue(data, position);//max_bytes_per_pic_denom = read_ue(data, position);//max_bits_per_mb_denom = read_ue(data, position);//log2_max_mv_length_horizontal = read_ue(data, position);//log2_max_mv_length_vertical = //****************************************** read_ue(data, position);//num_reorder_frames = read_ue(data, position);//max_dec_frame_buffering = } }