/* static */ bool H264::DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest) { MOZ_ASSERT(aSPS); BitReader br(aSPS); int32_t lastScale; int32_t nextScale; int32_t deltaScale; aDest.profile_idc = br.ReadBits(8); aDest.constraint_set0_flag = br.ReadBit(); aDest.constraint_set1_flag = br.ReadBit(); aDest.constraint_set2_flag = br.ReadBit(); aDest.constraint_set3_flag = br.ReadBit(); aDest.constraint_set4_flag = br.ReadBit(); aDest.constraint_set5_flag = br.ReadBit(); br.ReadBits(2); // reserved_zero_2bits aDest.level_idc = br.ReadBits(8); aDest.seq_parameter_set_id = br.ReadUE(); if (aDest.profile_idc == 100 || aDest.profile_idc == 110 || aDest.profile_idc == 122 || aDest.profile_idc == 244 || aDest.profile_idc == 44 || aDest.profile_idc == 83 || aDest.profile_idc == 86 || aDest.profile_idc == 118 || aDest.profile_idc == 128 || aDest.profile_idc == 138 || aDest.profile_idc == 139 || aDest.profile_idc == 134) { if ((aDest.chroma_format_idc = br.ReadUE()) == 3) { aDest.separate_colour_plane_flag = br.ReadBit(); } br.ReadUE(); // bit_depth_luma_minus8 br.ReadUE(); // bit_depth_chroma_minus8 br.ReadBit(); // qpprime_y_zero_transform_bypass_flag if (br.ReadBit()) { // seq_scaling_matrix_present_flag for (int idx = 0; idx < ((aDest.chroma_format_idc != 3) ? 8 : 12); ++idx) { if (br.ReadBit()) { // Scaling list present lastScale = nextScale = 8; int sl_n = (idx < 6) ? 16 : 64; for (int sl_i = 0; sl_i < sl_n; sl_i++) { if (nextScale) { deltaScale = br.ReadSE(); nextScale = (lastScale + deltaScale + 256) % 256; } lastScale = (nextScale == 0) ? lastScale : nextScale; } } } } } else if (aDest.profile_idc == 183) { aDest.chroma_format_idc = 0; } else { // default value if chroma_format_idc isn't set. aDest.chroma_format_idc = 1; } aDest.log2_max_frame_num = br.ReadUE() + 4; aDest.pic_order_cnt_type = br.ReadUE(); if (aDest.pic_order_cnt_type == 0) { aDest.log2_max_pic_order_cnt_lsb = br.ReadUE() + 4; } else if (aDest.pic_order_cnt_type == 1) { aDest.delta_pic_order_always_zero_flag = br.ReadBit(); aDest.offset_for_non_ref_pic = br.ReadSE(); aDest.offset_for_top_to_bottom_field = br.ReadSE(); uint32_t num_ref_frames_in_pic_order_cnt_cycle = br.ReadUE(); for (uint32_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) { br.ReadSE(); // offset_for_ref_frame[i] } } aDest.max_num_ref_frames = br.ReadUE(); aDest.gaps_in_frame_num_allowed_flag = br.ReadBit(); aDest.pic_width_in_mbs = br.ReadUE() + 1; aDest.pic_height_in_map_units = br.ReadUE() + 1; aDest.frame_mbs_only_flag = br.ReadBit(); if (!aDest.frame_mbs_only_flag) { aDest.pic_height_in_map_units *= 2; aDest.mb_adaptive_frame_field_flag = br.ReadBit(); } br.ReadBit(); // direct_8x8_inference_flag aDest.frame_cropping_flag = br.ReadBit(); if (aDest.frame_cropping_flag) { aDest.frame_crop_left_offset = br.ReadUE(); aDest.frame_crop_right_offset = br.ReadUE(); aDest.frame_crop_top_offset = br.ReadUE(); aDest.frame_crop_bottom_offset = br.ReadUE(); } aDest.sample_ratio = 1.0f; aDest.vui_parameters_present_flag = br.ReadBit(); if (aDest.vui_parameters_present_flag) { vui_parameters(br, aDest); } // Calculate common values. uint8_t ChromaArrayType = aDest.separate_colour_plane_flag ? 0 : aDest.chroma_format_idc; // Calculate width. uint32_t CropUnitX = 1; uint32_t SubWidthC = aDest.chroma_format_idc == 3 ? 1 : 2; if (ChromaArrayType != 0) { CropUnitX = SubWidthC; } // Calculate Height uint32_t CropUnitY = 2 - aDest.frame_mbs_only_flag; uint32_t SubHeightC = aDest.chroma_format_idc <= 1 ? 2 : 1; if (ChromaArrayType != 0) { CropUnitY *= SubHeightC; } uint32_t width = aDest.pic_width_in_mbs * 16; uint32_t height = aDest.pic_height_in_map_units * 16; if (aDest.frame_crop_left_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitX && aDest.frame_crop_right_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitX && aDest.frame_crop_top_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitY && aDest.frame_crop_bottom_offset <= std::numeric_limits<int32_t>::max() / 4 / CropUnitY && (aDest.frame_crop_left_offset + aDest.frame_crop_right_offset) * CropUnitX < width && (aDest.frame_crop_top_offset + aDest.frame_crop_bottom_offset) * CropUnitY < height) { aDest.crop_left = aDest.frame_crop_left_offset * CropUnitX; aDest.crop_right = aDest.frame_crop_right_offset * CropUnitX; aDest.crop_top = aDest.frame_crop_top_offset * CropUnitY; aDest.crop_bottom = aDest.frame_crop_bottom_offset * CropUnitY; } else { // Nonsensical value, ignore them. aDest.crop_left = aDest.crop_right = aDest.crop_top = aDest.crop_bottom = 0; } aDest.pic_width = width - aDest.crop_left - aDest.crop_right; aDest.pic_height = height - aDest.crop_top - aDest.crop_bottom; aDest.interlaced = !aDest.frame_mbs_only_flag; // Determine display size. if (aDest.sample_ratio > 1.0) { // Increase the intrinsic width aDest.display_width = ConditionDimension(aDest.pic_width * aDest.sample_ratio); aDest.display_height = aDest.pic_height; } else { // Increase the intrinsic height aDest.display_width = aDest.pic_width; aDest.display_height = ConditionDimension(aDest.pic_height / aDest.sample_ratio); } return true; }
void seq_parameter_set_rbsp(sps_t *sps, rbsp_t *rbsp) { sps->video_parameter_set_id = rbsp->u(4, "video_parameter_set_id"); assert(sps->video_parameter_set_id < MAX_VPS_ID); sps->sps_max_sub_layers_minus1 = rbsp->u(3, "sps_max_sub_layers_minus1"); assert(sps->sps_max_sub_layers_minus1 < MAX_SUB_LAYERS); uint32_t sps_reverved_zero_bit = rbsp->u(1, "sps_reverved_zero_bit"); assert(sps_reverved_zero_bit == 0); profile_tier_level(&sps->ptl, 1, sps->sps_max_sub_layers_minus1, rbsp); sps->seq_parameter_set_id = rbsp->ue("seq_parameter_set_id"); assert(sps->seq_parameter_set_id < MAX_SPS_ID); sps->chroma_format_idc = rbsp->ue("chroma_format_idc"); assert(sps->chroma_format_idc <= CHROMA_FORMAT_IDC_444); sps->separate_colour_plane_flag = 0; if (sps->chroma_format_idc == CHROMA_FORMAT_IDC_444) sps->separate_colour_plane_flag = rbsp->u(1, "separate_colour_plane_flag"); sps->ChromaArrayType = CHROMA_FORMAT_IDC_MONO; if (sps->separate_colour_plane_flag == 0) sps->ChromaArrayType = sps->chroma_format_idc; int SubWidthC [] = {1, 2, 2, 1, 1}; int SubHeightC[] = {1, 2, 1, 1, 1}; sps->SubWidthC = SubWidthC [sps->chroma_format_idc]; sps->SubHeightC = SubHeightC[sps->chroma_format_idc]; sps->pic_width_in_luma_samples = rbsp->ue("pic_width_in_luma_samples"); sps->pic_height_in_luma_samples = rbsp->ue("pic_height_in_luma_samples"); sps->pic_cropping_flag = rbsp->u(1, "pic_cropping_flag"); sps->pic_crop_left_offset = 0; sps->pic_crop_right_offset = 0; sps->pic_crop_top_offset = 0; sps->pic_crop_bottom_offset = 0; if (sps->pic_cropping_flag) { sps->pic_crop_left_offset = rbsp->ue("pic_crop_left_offset"); sps->pic_crop_right_offset = rbsp->ue("pic_crop_right_offset"); sps->pic_crop_top_offset = rbsp->ue("pic_crop_top_offset"); sps->pic_crop_bottom_offset = rbsp->ue("pic_crop_bottom_offset"); int CropUnitX = 1; int CropUnitY = 1; if (sps->ChromaArrayType != CHROMA_FORMAT_IDC_MONO) { CropUnitX = sps->SubWidthC; CropUnitY = sps->SubHeightC; } assert(sps->pic_crop_left_offset + sps->pic_crop_right_offset < sps->pic_width_in_luma_samples / CropUnitX); assert(sps->pic_crop_top_offset + sps->pic_crop_bottom_offset < sps->pic_height_in_luma_samples / CropUnitY); } sps->bit_depth_luma_minus8 = rbsp->ue("bit_depth_luma_minus8"); sps->bit_depth_chroma_minus8 = rbsp->ue("bit_depth_chroma_minus8"); assert(sps->bit_depth_luma_minus8 <= 6); assert(sps->bit_depth_chroma_minus8 <= 6); sps->BitDepthY = 8 + sps->bit_depth_luma_minus8; sps->QpBdOffsetY = 6 * sps->bit_depth_luma_minus8; sps->BitDepthC = 8 + sps->bit_depth_chroma_minus8; sps->QpBdOffsetC = 6 * sps->bit_depth_chroma_minus8; #if 1 sps->pcm_enabled_flag = rbsp->u(1, "pcm_enabled_flag"); sps->pcm_loop_filter_disable_flag = 0; if (sps->pcm_enabled_flag) { sps->pcm_sample_bit_depth_luma_minus1 = rbsp->u(4, "pcm_bit_depth_luma_minus1"); sps->pcm_sample_bit_depth_chroma_minus1 = rbsp->u(4, "pcm_bit_depth_chroma_minus1"); } #endif sps->log2_max_pic_order_cnt_lsb_minus4 = rbsp->ue("log2_max_pic_order_cnt_lsb_minus4"); assert(sps->log2_max_pic_order_cnt_lsb_minus4 <= 12); sps->MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); for (int i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { sps->sps_max_dec_pic_buffering[i] = rbsp->ue("max_dec_pic_buffering"); sps->sps_num_reorder_pics [i] = rbsp->ue("num_reorder_pics"); sps->sps_max_latency_increase [i] = rbsp->ue("max_latency_increase"); assert(sps->sps_max_dec_pic_buffering[i] <= MaxDpbSize); assert(sps->sps_num_reorder_pics [i] <= sps->sps_max_dec_pic_buffering[i]); assert(sps->sps_max_latency_increase [i] <= ((1<<32)-2)); if (i > 0) { assert(sps->sps_max_dec_pic_buffering[i-1] <= sps->sps_max_dec_pic_buffering[i]); assert(sps->sps_num_reorder_pics [i-1] <= sps->sps_num_reorder_pics [i]); } } sps->restricted_ref_pic_lists_flag = rbsp->u(1, "restricted_ref_pic_lists_flag"); sps->lists_modification_present_flag = 0; if (sps->restricted_ref_pic_lists_flag) sps->lists_modification_present_flag = rbsp->u(1, "lists_modification_present_flag"); sps->log2_min_luma_coding_block_size_minus3 = rbsp->ue("log2_min_coding_block_size_minus3"); sps->log2_diff_max_min_luma_coding_block_size = rbsp->ue("log2_diff_max_min_coding_block_size"); sps->Log2MinCbSizeY = sps->log2_min_luma_coding_block_size_minus3 + 3; 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 = (sps->pic_width_in_luma_samples + sps->CtbSizeY) / sps->CtbSizeY; sps->PicHeightInMinCbsY = sps->pic_height_in_luma_samples / sps->MinCbSizeY; sps->PicHeightInCtbsY = (sps->pic_height_in_luma_samples + sps->CtbSizeY) / 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; sps->CtbWidthC = 0; sps->CtbHeightC = 0; if (sps->chroma_format_idc != CHROMA_FORMAT_IDC_MONO && sps->separate_colour_plane_flag == 0) { sps->CtbWidthC = sps->CtbSizeY / sps->SubWidthC; sps->CtbHeightC = sps->CtbSizeY / sps->SubHeightC; } assert(sps->pic_width_in_luma_samples % sps->MinCbSizeY == 0); assert(sps->pic_height_in_luma_samples % sps->MinCbSizeY == 0); sps->log2_min_transform_block_size_minus2 = rbsp->ue("log2_min_transform_block_size_minus2"); sps->log2_diff_max_min_transform_block_size = rbsp->ue("log2_diff_max_min_transform_block_size"); sps->Log2MinTrafoSize = sps->log2_min_transform_block_size_minus2 + 2; sps->Log2MaxTrafoSize = sps->Log2MinTrafoSize + sps->log2_diff_max_min_transform_block_size; assert(sps->Log2MinTrafoSize < sps->Log2MinCbSizeY); assert(sps->Log2MaxTrafoSize <= min(sps->Log2CtbSizeY, 5)); // ScanOrder[log2BlockSize][scanIdx][sPos][sComp] // log2BlockSize ranging from min(2, Log2MinTrafoSize-2) to max(2, Log2MaxTrafoSize-2) for (int log2BlockSize = min(2, sps->Log2MinTrafoSize-2); log2BlockSize <= 3; log2BlockSize++) scan_order(sps->ScanOrder[log2BlockSize], 1 << log2BlockSize); #if 1 if (sps->pcm_enabled_flag) { sps->log2_min_pcm_luma_coding_block_size_minus3 = rbsp->ue("log2_min_pcm_coding_block_size_minus3"); sps->log2_diff_max_min_pcm_luma_coding_block_size = rbsp->ue("log2_diff_max_min_pcm_coding_block_size"); } #endif sps->max_transform_hierarchy_depth_inter = rbsp->ue("max_transform_hierarchy_depth_inter"); sps->max_transform_hierarchy_depth_intra = rbsp->ue("max_transform_hierarchy_depth_intra"); assert(sps->max_transform_hierarchy_depth_inter <= sps->Log2CtbSizeY - sps->Log2MinTrafoSize); assert(sps->max_transform_hierarchy_depth_intra <= sps->Log2CtbSizeY - sps->Log2MinTrafoSize); sps->scaling_list_enable_flag = rbsp->u(1, "scaling_list_enable_flag"); sps->sps_scaling_list_data_present_flag = 0; if (sps->scaling_list_enable_flag) { sps->sps_scaling_list_data_present_flag = rbsp->u(1, "sps_scaling_list_data_present_flag"); if (sps->sps_scaling_list_data_present_flag) scaling_list_data(&sps->sps_scaling_list, rbsp); } sps->amp_enabled_flag = rbsp->u(1, "asymmetric_motion_partitions_enabled_flag"); sps->sample_adaptive_offset_enabled_flag = rbsp->u(1, "sample_adaptive_offset_enabled_flag"); #if 1 sps->pcm_loop_filter_disable_flag = 0; if (sps->pcm_enabled_flag) sps->pcm_loop_filter_disable_flag = rbsp->u(1, "pcm_loop_filter_disable_flag"); #endif #if 0 sps->pcm_enabled_flag = rbsp->u(1, "pcm_enabled_flag"); sps->pcm_loop_filter_disable_flag = 0; if (sps->pcm_enabled_flag) { sps->pcm_sample_bit_depth_luma_minus1 = rbsp->u(4, "pcm_sample_bit_depth_luma_minus1"); sps->pcm_sample_bit_depth_chroma_minus1 = rbsp->u(4, "pcm_sample_bit_depth_chroma_minus1"); sps->PCMBitDepthY = 1 + sps->pcm_sample_bit_depth_luma_minus1; sps->PCMBitDepthC = 1 + sps->pcm_sample_bit_depth_chroma_minus1; assert(sps->PCMBitDepthY <= sps->BitDepthY); assert(sps->PCMBitDepthC <= sps->BitDepthC); sps->log2_min_pcm_luma_coding_block_size_minus3 = rbsp->ue("log2_min_pcm_coding_block_size_minus3"); sps->log2_diff_max_min_pcm_luma_coding_block_size = rbsp->ue("log2_diff_max_min_pcm_coding_block_size"); sps->pcm_loop_filter_disable_flag = rbsp->u(1, "pcm_loop_filter_disable_flag"); sps->Log2MinIpcmCbSizeY = sps->log2_min_pcm_luma_coding_block_size_minus3 + 3; sps->Log2MaxIpcmCbSizeY = sps->Log2MaxIpcmCbSizeY + sps->log2_diff_max_min_pcm_luma_coding_block_size; assert(sps->Log2MinIpcmCbSizeY >= sps->Log2MinCbSizeY); assert(sps->Log2MinIpcmCbSizeY <= min(sps->Log2CtbSizeY, 5)); assert(sps->Log2MaxIpcmCbSizeY <= min(sps->Log2CtbSizeY, 5)); } #endif sps->sps_temporal_id_nesting_flag = rbsp->u(1, "temporal_id_nesting_flag"); assert(sps->sps_temporal_id_nesting_flag == vps->vps_temporal_id_nesting_flag); sps->num_short_term_ref_pic_sets = rbsp->ue("num_short_term_ref_pic_sets"); assert(sps->num_short_term_ref_pic_sets <= MAX_SHORT_TERM_REF_PIC_SETS); for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++) short_term_ref_pic_set(&sps->rps[i], i, rbsp); sps->long_term_ref_pics_present_flag = rbsp->u(1, "long_term_ref_pics_present_flag"); if (sps->long_term_ref_pics_present_flag) { sps->num_long_term_ref_pics_sps = rbsp->ue("num_long_term_ref_pic_sps"); for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) { sps->lt_ref_pic_poc_lsb_sps[i] = rbsp->u(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, "lt_ref_pic_poc_lsb_sps"); sps->used_by_curr_pic_lt_sps_flag[i] = rbsp->u(1, "used_by_curr_pic_lt_sps_flag[i]"); } } sps->sps_temporal_mvp_enable_flag = rbsp->u(1, "sps_temporal_mvp_enable_flag"); #if 0 sps->strong_intra_smoothing_enable_flag = rbsp->u(1, "strong_intra_smoothing_enable_flag"); #endif sps->vui_parameters_present_flag = rbsp->u(1, "vui_parameters_present_flag"); if (sps->vui_parameters_present_flag) vui_parameters(&sps->vui, sps, rbsp); uint32_t sps_extension_flag = rbsp->u(1, "sps_extension_flag"); if (sps_extension_flag) { while (rbsp->more_rbsp_data()) uint32_t sps_extension_data_flag = rbsp->u(1, "sps_extension_data_flag"); } rbsp->rbsp_trailing_bits(); }
/** 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); } }