private void writeOffsetWeight(SliceHeader sliceHeader, BitWriter writer, int list) { SeqParameterSet sps = sliceHeader.sps; int defaultLW = 1 << sliceHeader.pred_weight_table.luma_log2_weight_denom; int defaultCW = 1 << sliceHeader.pred_weight_table.chroma_log2_weight_denom; for (int i = 0; i < sliceHeader.pred_weight_table.luma_weight[list].Length; i++) { bool flagLuma = sliceHeader.pred_weight_table.luma_weight[list][i] != defaultLW || sliceHeader.pred_weight_table.luma_offset[list][i] != 0; CAVLCWriter.writeBool(writer, flagLuma, "SH: luma_weight_l0_flag"); if (flagLuma) { CAVLCWriter.writeSE(writer, sliceHeader.pred_weight_table.luma_weight[list][i], "SH: luma_weight_l" + list); CAVLCWriter.writeSE(writer, sliceHeader.pred_weight_table.luma_offset[list][i], "SH: luma_offset_l" + list); } if (sps.chroma_format_idc != ColorSpace.MONO) { bool flagChroma = sliceHeader.pred_weight_table.chroma_weight[list][0][i] != defaultCW || sliceHeader.pred_weight_table.chroma_offset[list][0][i] != 0 || sliceHeader.pred_weight_table.chroma_weight[list][1][i] != defaultCW || sliceHeader.pred_weight_table.chroma_offset[list][1][i] != 0; CAVLCWriter.writeBool(writer, flagChroma, "SH: chroma_weight_l0_flag"); if (flagChroma) { for (int j = 0; j < 2; j++) { CAVLCWriter.writeSE(writer, sliceHeader.pred_weight_table.chroma_weight[list][j][i], "SH: chroma_weight_l" + list); CAVLCWriter.writeSE(writer, sliceHeader.pred_weight_table.chroma_offset[list][j][i], "SH: chroma_offset_l" + list); } } } } }
public SliceHeader run(System.IO.MemoryStream iss, System.IO.MemoryStream os, NALUnit nu, SeqParameterSet sps, PictureParameterSet pps) { System.IO.MemoryStream nal = os.duplicate(); Utility.unescapeNAL(iss); BitReader reader = new BitReader(iss); SliceHeader sh = shr.readPart1(reader); return(part2(iss, os, nu, sps, pps, nal, reader, sh)); }
private void writeDecRefPicMarking(SliceHeader sliceHeader, bool idrSlice, BitWriter writer) { if (idrSlice) { RefPicMarkingIDR drpmidr = sliceHeader.refPicMarkingIDR; CAVLCWriter.writeBool(writer, drpmidr.isDiscardDecodedPics(), "SH: no_output_of_prior_pics_flag"); CAVLCWriter.writeBool(writer, drpmidr.isUseForlongTerm(), "SH: long_term_reference_flag"); } else { CAVLCWriter.writeBool(writer, sliceHeader.refPicMarkingNonIDR != null, "SH: adaptive_ref_pic_marking_mode_flag"); if (sliceHeader.refPicMarkingNonIDR != null) { RefPicMarking drpmidr = sliceHeader.refPicMarkingNonIDR; foreach (var mmop in drpmidr.getInstructions()) { switch (mmop.getType()) { case RefPicMarking.InstrType.REMOVE_SHORT: CAVLCWriter.writeUE(writer, 1, "SH: memory_management_control_operation"); CAVLCWriter.writeUE(writer, mmop.getArg1() - 1, "SH: difference_of_pic_nums_minus1"); break; case RefPicMarking.InstrType.REMOVE_LONG: CAVLCWriter.writeUE(writer, 2, "SH: memory_management_control_operation"); CAVLCWriter.writeUE(writer, mmop.getArg1(), "SH: long_term_pic_num"); break; case RefPicMarking.InstrType.CONVERT_INTO_LONG: CAVLCWriter.writeUE(writer, 3, "SH: memory_management_control_operation"); CAVLCWriter.writeUE(writer, mmop.getArg1() - 1, "SH: difference_of_pic_nums_minus1"); CAVLCWriter.writeUE(writer, mmop.getArg2(), "SH: long_term_frame_idx"); break; case RefPicMarking.InstrType.TRUNK_LONG: CAVLCWriter.writeUE(writer, 4, "SH: memory_management_control_operation"); CAVLCWriter.writeUE(writer, mmop.getArg1() + 1, "SH: max_long_term_frame_idx_plus1"); break; case RefPicMarking.InstrType.CLEAR: CAVLCWriter.writeUE(writer, 5, "SH: memory_management_control_operation"); break; case RefPicMarking.InstrType.MARK_LONG: CAVLCWriter.writeUE(writer, 6, "SH: memory_management_control_operation"); CAVLCWriter.writeUE(writer, mmop.getArg1(), "SH: long_term_frame_idx"); break; } } CAVLCWriter.writeUE(writer, 0, "SH: memory_management_control_operation"); } } }
public SliceHeader run(System.IO.MemoryStream iss, System.IO.MemoryStream os, NALUnit nu) { System.IO.MemoryStream nal = os.duplicate(); Utility.unescapeNAL(iss); BitReader reader = new BitReader(iss); SliceHeader sh = shr.readPart1(reader); PictureParameterSet pp = findPPS(pps, sh.pic_parameter_set_id); return(part2(iss, os, nu, findSPS(sps, pp.pic_parameter_set_id), pp, nal, reader, sh)); }
private void writeRefPicListReordering(SliceHeader sliceHeader, BitWriter writer) { if (sliceHeader.slice_type.isInter()) { CAVLCWriter.writeBool(writer, sliceHeader.refPicReordering[0] != null, "SH: ref_pic_list_reordering_flag_l0"); writeReorderingList(sliceHeader.refPicReordering[0], writer); } if (sliceHeader.slice_type == SliceType.B) { CAVLCWriter.writeBool(writer, sliceHeader.refPicReordering[1] != null, "SH: ref_pic_list_reordering_flag_l1"); writeReorderingList(sliceHeader.refPicReordering[1], writer); } }
private void fillHorizontalEdge(Picture pic, int comp, int mbAddr, int[][] bs) { SliceHeader sh = shs[mbAddr]; int mbWidth = sh.sps.pic_width_in_mbs_minus1 + 1; int alpha = sh.slice_alpha_c0_offset_div2 << 1; int beta = sh.slice_beta_offset_div2 << 1; int mbX = mbAddr % mbWidth; int mbY = mbAddr / mbWidth; bool topAvailable = mbY > 0 && (sh.disable_deblocking_filter_idc != 2 || shs[mbAddr - mbWidth] == sh); int curQp = mbQps[comp][mbAddr]; int cW = 2 - pic.getColor().compWidth[comp]; int cH = 2 - pic.getColor().compHeight[comp]; if (topAvailable) { int topQp = mbQps[comp][mbAddr - mbWidth]; int avgQp = (topQp + curQp + 1) >> 1; for (int blkX = 0; blkX < 4; blkX++) { int thisBlkX = (mbX << 2) + blkX; int thisBlkY = (mbY << 2); filterBlockEdgeHoris(pic, comp, thisBlkX << cW, thisBlkY << cH, getIdxAlpha(alpha, avgQp), getIdxBeta(beta, avgQp), bs[0][blkX], 1 << cW); } } bool skip4x4 = comp == 0 && tr8x8Used[mbAddr] || cH == 1; for (int blkY = 1; blkY < 4; blkY++) { if (skip4x4 && (blkY & 1) == 1) { continue; } for (int blkX = 0; blkX < 4; blkX++) { int thisBlkX = (mbX << 2) + blkX; int thisBlkY = (mbY << 2) + blkY; filterBlockEdgeHoris(pic, comp, thisBlkX << cW, thisBlkY << cH, getIdxAlpha(alpha, curQp), getIdxBeta(beta, curQp), bs[blkY][blkX], 1 << cW); } } }
public SliceHeader readPart1(BitReader inb) { SliceHeader sh = new SliceHeader(); sh.first_mb_in_slice = CAVLCReader.readUE(inb, "SH: first_mb_inb_slice"); int sh_type = CAVLCReader.readUE(inb, "SH: slice_type"); sh.slice_type = (SliceType)(sh_type % 5); sh.slice_type_restr = (sh_type / 5) > 0; sh.pic_parameter_set_id = CAVLCReader.readUE(inb, "SH: pic_parameter_set_id"); return(sh); }
private bool hasMMCO5(SliceHeader firstSliceHeader, NALUnit firstNu) { if (firstNu.type != NALUnitType.IDR_SLICE && firstSliceHeader.refPicMarkingNonIDR != null) { nVideo.Codecs.H264.RefPicMarking.Instruction[] instructions = firstSliceHeader.refPicMarkingNonIDR.getInstructions(); foreach (var instruction in instructions) { if (instruction.getType() == nVideo.Codecs.H264.RefPicMarking.InstrType.CLEAR) { return(true); } } } return(false); }
private void writePredWeightTable(SliceHeader sliceHeader, BitWriter writer) { SeqParameterSet sps = sliceHeader.sps; CAVLCWriter.writeUE(writer, sliceHeader.pred_weight_table.luma_log2_weight_denom, "SH: luma_log2_weight_denom"); if (sps.chroma_format_idc != ColorSpace.MONO) { CAVLCWriter.writeUE(writer, sliceHeader.pred_weight_table.chroma_log2_weight_denom, "SH: chroma_log2_weight_denom"); } writeOffsetWeight(sliceHeader, writer, 0); if (sliceHeader.slice_type == SliceType.B) { writeOffsetWeight(sliceHeader, writer, 1); } }
public int calcPOC(SliceHeader firstSliceHeader, NALUnit firstNu) { switch (firstSliceHeader.sps.pic_order_cnt_type) { case 0: return(calcPOC0(firstSliceHeader, firstNu)); case 1: return(calcPOC1(firstSliceHeader, firstNu)); case 2: return(calcPOC2(firstSliceHeader, firstNu)); default: throw new Exception("POC no!!!"); } }
private int calcPOC0(SliceHeader firstSliceHeader, NALUnit firstNu) { if (firstNu.type == NALUnitType.IDR_SLICE) { prevPOCMsb = prevPOCLsb = 0; } int maxPOCLsbDiv2 = 1 << (firstSliceHeader.sps.log2_max_pic_order_cnt_lsb_minus4 + 3), maxPOCLsb = maxPOCLsbDiv2 << 1; int POCLsb = firstSliceHeader.pic_order_cnt_lsb; int POCMsb, POC; if ((POCLsb < prevPOCLsb) && ((prevPOCLsb - POCLsb) >= maxPOCLsbDiv2)) { POCMsb = prevPOCMsb + maxPOCLsb; } else if ((POCLsb > prevPOCLsb) && ((POCLsb - prevPOCLsb) > maxPOCLsbDiv2)) { POCMsb = prevPOCMsb - maxPOCLsb; } else { POCMsb = prevPOCMsb; } POC = POCMsb + POCLsb; if (firstNu.nal_ref_idc > 0) { if (hasMMCO5(firstSliceHeader, firstNu)) { prevPOCMsb = 0; prevPOCLsb = POC; } else { prevPOCMsb = POCMsb; prevPOCLsb = POCLsb; } } return(POC); }
private Frame init(int[][] buffer, MemoryStream segment, NALUnit marker) { firstNu = marker; shr = new SliceHeaderReader(); BitReader br = new BitReader(segment.duplicate()); firstSliceHeader = shr.readPart1(br); activePps = vdecoder.pps[firstSliceHeader.pic_parameter_set_id]; activeSps = vdecoder.sps[activePps.seq_parameter_set_id]; shr.readPart2(firstSliceHeader, marker, activeSps, activePps, br); int picWidthInMbs = activeSps.pic_width_in_mbs_minus1 + 1; int picHeightInMbs = Utility.getPicHeightInMbs(activeSps); int[][] nCoeff = (int[][])Array.CreateInstance(typeof(int), new int[] { picHeightInMbs << 2, picWidthInMbs << 2 }); //new int[picHeightInMbs << 2][picWidthInMbs << 2]; mvs = (int[][][][])Array.CreateInstance(typeof(int), new int[] { 2, picHeightInMbs << 2, picWidthInMbs << 2, 3 }); //new int[2][picHeightInMbs << 2][picWidthInMbs << 2][3]; MBType[] mbTypes = new MBType[picHeightInMbs * picWidthInMbs]; bool[] tr8x8Used = new bool[picHeightInMbs * picWidthInMbs]; int[][] mbQps = (int[][])Array.CreateInstance(typeof(int), new int[] { 3, picHeightInMbs * picWidthInMbs });//new int[3][picHeightInMbs * picWidthInMbs]; SliceHeader[] shs = new SliceHeader[picHeightInMbs * picWidthInMbs]; Frame[][][] refsUsed = new Frame[picHeightInMbs * picWidthInMbs][][]; if (vdecoder.sRefs == null) { vdecoder.sRefs = new Frame[1 << (firstSliceHeader.sps.log2_max_frame_num_minus4 + 4)]; vdecoder.lRefs = new Dictionary <int, Frame>(); } Frame result = createFrame(activeSps, buffer, firstSliceHeader.frame_num, mvs, refsUsed, vdecoder.poc.calcPOC(firstSliceHeader, firstNu)); decoder = new SliceDecoder(activeSps, activePps, nCoeff, mvs, mbTypes, mbQps, shs, tr8x8Used, refsUsed, result, vdecoder.sRefs, vdecoder.lRefs); decoder.setDebug(vdecoder.debug); filter = new DeblockingFilter(picWidthInMbs, activeSps.bit_depth_chroma_minus8 + 8, nCoeff, mvs, mbTypes, mbQps, shs, tr8x8Used, refsUsed); return(result); }
private static void readRefPicListReorderinbg(SliceHeader sh, BitReader inb) { sh.refPicReordering = new int[2][][]; // System.out.println(i++); if (sh.slice_type.isInter()) { bool ref_pic_list_reorderinbg_flag_l0 = CAVLCReader.readBool(inb, "SH: ref_pic_list_reorderinbg_flag_l0"); if (ref_pic_list_reorderinbg_flag_l0) { sh.refPicReordering[0] = readReorderinbgEntries(inb); } } if (sh.slice_type == SliceType.B) { bool ref_pic_list_reorderinbg_flag_l1 = CAVLCReader.readBool(inb, "SH: ref_pic_list_reorderinbg_flag_l1"); if (ref_pic_list_reorderinbg_flag_l1) { sh.refPicReordering[1] = readReorderinbgEntries(inb); } } }
private void calcBsH(Picture pic, int mbAddr, int[][] bs) { SliceHeader sh = shs[mbAddr]; int mbWidth = sh.sps.pic_width_in_mbs_minus1 + 1; int mbX = mbAddr % mbWidth; int mbY = mbAddr / mbWidth; bool topAvailable = mbY > 0 && (sh.disable_deblocking_filter_idc != 2 || shs[mbAddr - mbWidth] == sh); bool thisIntra = mbTypes[mbAddr] != null && mbTypes[mbAddr].isIntra(); if (topAvailable) { bool topIntra = mbTypes[mbAddr - mbWidth] != null && mbTypes[mbAddr - mbWidth].isIntra(); for (int blkX = 0; blkX < 4; blkX++) { int thisBlkX = (mbX << 2) + blkX; int thisBlkY = (mbY << 2); bs[0][blkX] = calcBoundaryStrenth(true, topIntra, thisIntra, nCoeff[thisBlkY][thisBlkX], nCoeff[thisBlkY - 1][thisBlkX], mvs[0][thisBlkY][thisBlkX], mvs[0][thisBlkY - 1][thisBlkX], mvs[1][thisBlkY][thisBlkX], mvs[1][thisBlkY - 1][thisBlkX], mbAddr, mbAddr - mbWidth); } } for (int blkY = 1; blkY < 4; blkY++) { for (int blkX = 0; blkX < 4; blkX++) { int thisBlkX = (mbX << 2) + blkX; int thisBlkY = (mbY << 2) + blkY; bs[blkY][blkX] = calcBoundaryStrenth(false, thisIntra, thisIntra, nCoeff[thisBlkY][thisBlkX], nCoeff[thisBlkY - 1][thisBlkX], mvs[0][thisBlkY][thisBlkX], mvs[0][thisBlkY - 1][thisBlkX], mvs[1][thisBlkY][thisBlkX], mvs[1][thisBlkY - 1][thisBlkX], mbAddr, mbAddr); } } }
private bool validSh(SliceHeader sh) { return(sh.first_mb_in_slice == 0 && sh.pic_parameter_set_id < 2); }
public Prediction(SliceHeader sh) { this.sh = sh; }
private static void readPredWeightTable(SeqParameterSet sps, PictureParameterSet pps, SliceHeader sh, BitReader inb) { sh.pred_weight_table = new PredictionWeightTable(); int[] numRefsminus1 = sh.num_ref_idx_active_override_flag ? sh.num_ref_idx_active_minus1 : pps.num_ref_idx_active_minus1; int[] nr = new int[] { numRefsminus1[0] + 1, numRefsminus1[1] + 1 }; sh.pred_weight_table.luma_log2_weight_denom = CAVLCReader.readUE(inb, "SH: luma_log2_weight_denom"); if (sps.chroma_format_idc != ColorSpace.MONO) { sh.pred_weight_table.chroma_log2_weight_denom = CAVLCReader.readUE(inb, "SH: chroma_log2_weight_denom"); } int defaultLW = 1 << sh.pred_weight_table.luma_log2_weight_denom; int defaultCW = 1 << sh.pred_weight_table.chroma_log2_weight_denom; for (int list = 0; list < 2; list++) { sh.pred_weight_table.luma_weight[list] = new int[nr[list]]; sh.pred_weight_table.luma_offset[list] = new int[nr[list]]; sh.pred_weight_table.chroma_weight[list] = (int[][])System.Array.CreateInstance(typeof(int), new int[] { 2, nr[list] }); sh.pred_weight_table.chroma_offset[list] = (int[][])System.Array.CreateInstance(typeof(int), new int[] { 2, nr[list] }); for (int i = 0; i < nr[list]; i++) { sh.pred_weight_table.luma_weight[list][i] = defaultLW; sh.pred_weight_table.luma_offset[list][i] = 0; sh.pred_weight_table.chroma_weight[list][0][i] = defaultCW; sh.pred_weight_table.chroma_offset[list][0][i] = 0; sh.pred_weight_table.chroma_weight[list][1][i] = defaultCW; sh.pred_weight_table.chroma_offset[list][1][i] = 0; } } readWeightOffset(sps, pps, sh, inb, nr, 0); if (sh.slice_type == SliceType.B) { readWeightOffset(sps, pps, sh, inb, nr, 1); } }
private int calcPOC1(SliceHeader firstSliceHeader, NALUnit firstNu) { return(firstSliceHeader.frame_num << 1); }
private static void readWeightOffset(SeqParameterSet sps, PictureParameterSet pps, SliceHeader sh, BitReader inb, int[] numRefs, int list) { for (int i = 0; i < numRefs[list]; i++) { bool luma_weight_l0_flag = CAVLCReader.readBool(inb, "SH: luma_weight_l0_flag"); if (luma_weight_l0_flag) { sh.pred_weight_table.luma_weight[list][i] = CAVLCReader.readSE(inb, "SH: weight"); sh.pred_weight_table.luma_offset[list][i] = CAVLCReader.readSE(inb, "SH: offset"); } if (sps.chroma_format_idc != ColorSpace.MONO) { bool chroma_weight_l0_flag = CAVLCReader.readBool(inb, "SH: chroma_weight_l0_flag"); if (chroma_weight_l0_flag) { sh.pred_weight_table.chroma_weight[list][0][i] = CAVLCReader.readSE(inb, "SH: weight"); sh.pred_weight_table.chroma_offset[list][0][i] = CAVLCReader.readSE(inb, "SH: offset"); sh.pred_weight_table.chroma_weight[list][1][i] = CAVLCReader.readSE(inb, "SH: weight"); sh.pred_weight_table.chroma_offset[list][1][i] = CAVLCReader.readSE(inb, "SH: offset"); } } } }
public SliceHeader readPart2(SliceHeader sh, NALUnit nalUnit, SeqParameterSet sps, PictureParameterSet pps, BitReader inb) { sh.pps = pps; sh.sps = sps; sh.frame_num = CAVLCReader.readU(inb, sps.log2_max_frame_num_minus4 + 4, "SH: frame_num"); if (!sps.frame_mbs_only_flag) { sh.field_pic_flag = CAVLCReader.readBool(inb, "SH: field_pic_flag"); if (sh.field_pic_flag) { sh.bottom_field_flag = CAVLCReader.readBool(inb, "SH: bottom_field_flag"); } } if (nalUnit.type == NALUnitType.IDR_SLICE) { sh.idr_pic_id = CAVLCReader.readUE(inb, "SH: idr_pic_id"); } if (sps.pic_order_cnt_type == 0) { sh.pic_order_cnt_lsb = CAVLCReader.readU(inb, sps.log2_max_pic_order_cnt_lsb_minus4 + 4, "SH: pic_order_cnt_lsb"); if (pps.pic_order_present_flag && !sps.field_pic_flag) { sh.delta_pic_order_cnt_bottom = CAVLCReader.readSE(inb, "SH: delta_pic_order_cnt_bottom"); } } sh.delta_pic_order_cnt = new int[2]; if (sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero_flag) { sh.delta_pic_order_cnt[0] = CAVLCReader.readSE(inb, "SH: delta_pic_order_cnt[0]"); if (pps.pic_order_present_flag && !sps.field_pic_flag) { sh.delta_pic_order_cnt[1] = CAVLCReader.readSE(inb, "SH: delta_pic_order_cnt[1]"); } } if (pps.redundant_pic_cnt_present_flag) { sh.redundant_pic_cnt = CAVLCReader.readUE(inb, "SH: redundant_pic_cnt"); } if (sh.slice_type == SliceType.B) { sh.direct_spatial_mv_pred_flag = CAVLCReader.readBool(inb, "SH: direct_spatial_mv_pred_flag"); } if (sh.slice_type == SliceType.P || sh.slice_type == SliceType.SP || sh.slice_type == SliceType.B) { sh.num_ref_idx_active_override_flag = CAVLCReader.readBool(inb, "SH: num_ref_idx_active_override_flag"); if (sh.num_ref_idx_active_override_flag) { sh.num_ref_idx_active_minus1[0] = CAVLCReader.readUE(inb, "SH: num_ref_idx_l0_active_minus1"); if (sh.slice_type == SliceType.B) { sh.num_ref_idx_active_minus1[1] = CAVLCReader.readUE(inb, "SH: num_ref_idx_l1_active_minus1"); } } } readRefPicListReorderinbg(sh, inb); if ((pps.weighted_pred_flag && (sh.slice_type == SliceType.P || sh.slice_type == SliceType.SP)) || (pps.weighted_bipred_idc == 1 && sh.slice_type == SliceType.B)) { readPredWeightTable(sps, pps, sh, inb); } if (nalUnit.nal_ref_idc != 0) { readDecoderPicMarkinbg(nalUnit, sh, inb); } if (pps.entropy_coding_mode_flag && sh.slice_type.isInter()) { sh.cabac_init_idc = CAVLCReader.readUE(inb, "SH: cabac_inbit_idc"); } sh.slice_qp_delta = CAVLCReader.readSE(inb, "SH: slice_qp_delta"); if (sh.slice_type == SliceType.SP || sh.slice_type == SliceType.SI) { if (sh.slice_type == SliceType.SP) { sh.sp_for_switch_flag = CAVLCReader.readBool(inb, "SH: sp_for_switch_flag"); } sh.slice_qs_delta = CAVLCReader.readSE(inb, "SH: slice_qs_delta"); } if (pps.deblocking_filter_control_present_flag) { sh.disable_deblocking_filter_idc = CAVLCReader.readUE(inb, "SH: disable_deblockinbg_filter_idc"); if (sh.disable_deblocking_filter_idc != 1) { sh.slice_alpha_c0_offset_div2 = CAVLCReader.readSE(inb, "SH: slice_alpha_c0_offset_div2"); sh.slice_beta_offset_div2 = CAVLCReader.readSE(inb, "SH: slice_beta_offset_div2"); } } if (pps.num_slice_groups_minus1 > 0 && pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5) { int len = Utility.getPicHeightInMbs(sps) * (sps.pic_width_in_mbs_minus1 + 1) / (pps.slice_group_change_rate_minus1 + 1); if ((Utility.getPicHeightInMbs(sps) * (sps.pic_width_in_mbs_minus1 + 1)) % (pps.slice_group_change_rate_minus1 + 1) > 0) { len += 1; } len = CeilLog2(len + 1); sh.slice_group_change_cycle = CAVLCReader.readU(inb, len, "SH: slice_group_change_cycle"); } return(sh); }
// static int i = 0; private static void readDecoderPicMarkinbg(NALUnit nalUnit, SliceHeader sh, BitReader inb) { if (nalUnit.type == NALUnitType.IDR_SLICE) { bool no_output_of_prior_pics_flag = CAVLCReader.readBool(inb, "SH: no_output_of_prior_pics_flag"); bool long_term_reference_flag = CAVLCReader.readBool(inb, "SH: long_term_reference_flag"); sh.refPicMarkingIDR = new nVideo.Codecs.H264.RefPicMarkingIDR(no_output_of_prior_pics_flag, long_term_reference_flag); } else { bool adaptive_ref_pic_markinbg_mode_flag = CAVLCReader.readBool(inb, "SH: adaptive_ref_pic_markinbg_mode_flag"); if (adaptive_ref_pic_markinbg_mode_flag) { List <nVideo.Codecs.H264.RefPicMarking.Instruction> mmops = new List <nVideo.Codecs.H264.RefPicMarking.Instruction>(); int memory_management_control_operation; do { memory_management_control_operation = CAVLCReader.readUE(inb, "SH: memory_management_control_operation"); nVideo.Codecs.H264.RefPicMarking.Instruction inbstr = null; switch (memory_management_control_operation) { case 1: inbstr = new nVideo.Codecs.H264.RefPicMarking.Instruction(nVideo.Codecs.H264.RefPicMarking.InstrType.REMOVE_SHORT, CAVLCReader.readUE(inb, "SH: difference_of_pic_nums_minus1") + 1, 0); break; case 2: inbstr = new nVideo.Codecs.H264.RefPicMarking.Instruction(nVideo.Codecs.H264.RefPicMarking.InstrType.REMOVE_LONG, CAVLCReader.readUE(inb, "SH: long_term_pic_num"), 0); break; case 3: inbstr = new nVideo.Codecs.H264.RefPicMarking.Instruction(nVideo.Codecs.H264.RefPicMarking.InstrType.CONVERT_INTO_LONG, CAVLCReader.readUE(inb, "SH: difference_of_pic_nums_minus1") + 1, CAVLCReader.readUE(inb, "SH: long_term_frame_idx")); break; case 4: inbstr = new nVideo.Codecs.H264.RefPicMarking.Instruction(nVideo.Codecs.H264.RefPicMarking.InstrType.TRUNK_LONG, CAVLCReader.readUE(inb, "SH: max_long_term_frame_idx_plus1") - 1, 0); break; case 5: inbstr = new nVideo.Codecs.H264.RefPicMarking.Instruction(nVideo.Codecs.H264.RefPicMarking.InstrType.CLEAR, 0, 0); break; case 6: inbstr = new nVideo.Codecs.H264.RefPicMarking.Instruction(nVideo.Codecs.H264.RefPicMarking.InstrType.MARK_LONG, CAVLCReader.readUE(inb, "SH: long_term_frame_idx"), 0); break; } if (inbstr != null) { mmops.Add(inbstr); } } while (memory_management_control_operation != 0); sh.refPicMarkingNonIDR = new RefPicMarking(mmops.ToArray()); } } }
protected abstract void tweak(SliceHeader sh);
public void write(SliceHeader sliceHeader, bool idrSlice, int nalRefIdc, BitWriter writer) { SeqParameterSet sps = sliceHeader.sps; PictureParameterSet pps = sliceHeader.pps; CAVLCWriter.writeUE(writer, sliceHeader.first_mb_in_slice, "SH: first_mb_in_slice"); CAVLCWriter.writeUE(writer, (int)sliceHeader.slice_type + (sliceHeader.slice_type_restr ? 5 : 0), "SH: slice_type"); CAVLCWriter.writeUE(writer, sliceHeader.pic_parameter_set_id, "SH: pic_parameter_set_id"); CAVLCWriter.writeU(writer, sliceHeader.frame_num, sps.log2_max_frame_num_minus4 + 4, "SH: frame_num"); if (!sps.frame_mbs_only_flag) { CAVLCWriter.writeBool(writer, sliceHeader.field_pic_flag, "SH: field_pic_flag"); if (sliceHeader.field_pic_flag) { CAVLCWriter.writeBool(writer, sliceHeader.bottom_field_flag, "SH: bottom_field_flag"); } } if (idrSlice) { CAVLCWriter.writeUE(writer, sliceHeader.idr_pic_id, "SH: idr_pic_id"); } if (sps.pic_order_cnt_type == 0) { CAVLCWriter.writeU(writer, sliceHeader.pic_order_cnt_lsb, sps.log2_max_pic_order_cnt_lsb_minus4 + 4); if (pps.pic_order_present_flag && !sps.field_pic_flag) { CAVLCWriter.writeSE(writer, sliceHeader.delta_pic_order_cnt_bottom, "SH: delta_pic_order_cnt_bottom"); } } if (sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero_flag) { CAVLCWriter.writeSE(writer, sliceHeader.delta_pic_order_cnt[0], "SH: delta_pic_order_cnt"); if (pps.pic_order_present_flag && !sps.field_pic_flag) { CAVLCWriter.writeSE(writer, sliceHeader.delta_pic_order_cnt[1], "SH: delta_pic_order_cnt"); } } if (pps.redundant_pic_cnt_present_flag) { CAVLCWriter.writeUE(writer, sliceHeader.redundant_pic_cnt, "SH: redundant_pic_cnt"); } if (sliceHeader.slice_type == SliceType.B) { CAVLCWriter.writeBool(writer, sliceHeader.direct_spatial_mv_pred_flag, "SH: direct_spatial_mv_pred_flag"); } if (sliceHeader.slice_type == SliceType.P || sliceHeader.slice_type == SliceType.SP || sliceHeader.slice_type == SliceType.B) { CAVLCWriter.writeBool(writer, sliceHeader.num_ref_idx_active_override_flag, "SH: num_ref_idx_active_override_flag"); if (sliceHeader.num_ref_idx_active_override_flag) { CAVLCWriter.writeUE(writer, sliceHeader.num_ref_idx_active_minus1[0], "SH: num_ref_idx_l0_active_minus1"); if (sliceHeader.slice_type == SliceType.B) { CAVLCWriter.writeUE(writer, sliceHeader.num_ref_idx_active_minus1[1], "SH: num_ref_idx_l1_active_minus1"); } } } writeRefPicListReordering(sliceHeader, writer); if ((pps.weighted_pred_flag && (sliceHeader.slice_type == SliceType.P || sliceHeader.slice_type == SliceType.SP)) || (pps.weighted_bipred_idc == 1 && sliceHeader.slice_type == SliceType.B)) { writePredWeightTable(sliceHeader, writer); } if (nalRefIdc != 0) { writeDecRefPicMarking(sliceHeader, idrSlice, writer); } if (pps.entropy_coding_mode_flag && sliceHeader.slice_type.isInter()) { CAVLCWriter.writeUE(writer, sliceHeader.cabac_init_idc, "SH: cabac_init_idc"); } CAVLCWriter.writeSE(writer, sliceHeader.slice_qp_delta, "SH: slice_qp_delta"); if (sliceHeader.slice_type == SliceType.SP || sliceHeader.slice_type == SliceType.SI) { if (sliceHeader.slice_type == SliceType.SP) { CAVLCWriter.writeBool(writer, sliceHeader.sp_for_switch_flag, "SH: sp_for_switch_flag"); } CAVLCWriter.writeSE(writer, sliceHeader.slice_qs_delta, "SH: slice_qs_delta"); } if (pps.deblocking_filter_control_present_flag) { CAVLCWriter.writeUE(writer, sliceHeader.disable_deblocking_filter_idc, "SH: disable_deblocking_filter_idc"); if (sliceHeader.disable_deblocking_filter_idc != 1) { CAVLCWriter.writeSE(writer, sliceHeader.slice_alpha_c0_offset_div2, "SH: slice_alpha_c0_offset_div2"); CAVLCWriter.writeSE(writer, sliceHeader.slice_beta_offset_div2, "SH: slice_beta_offset_div2"); } } if (pps.num_slice_groups_minus1 > 0 && pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5) { int len = (sps.pic_height_in_map_units_minus1 + 1) * (sps.pic_width_in_mbs_minus1 + 1) / (pps.slice_group_change_rate_minus1 + 1); if (((sps.pic_height_in_map_units_minus1 + 1) * (sps.pic_width_in_mbs_minus1 + 1)) % (pps.slice_group_change_rate_minus1 + 1) > 0) { len += 1; } len = CeilLog2(len + 1); CAVLCWriter.writeU(writer, sliceHeader.slice_group_change_cycle, len); } }
private SliceHeader part2(System.IO.MemoryStream iss, System.IO.MemoryStream os, NALUnit nu, SeqParameterSet sps, PictureParameterSet pps, System.IO.MemoryStream nal, BitReader reader, SliceHeader sh) { BitWriter writer = new BitWriter(os); shr.readPart2(sh, nu, sps, pps, reader); tweak(sh); shw.write(sh, nu.type == NALUnitType.IDR_SLICE, nu.nal_ref_idc, writer); if (pps.entropy_coding_mode_flag) { copyDataCABAC(iss, os, reader, writer); } else { copyDataCAVLC(iss, os, reader, writer); } nal.limit(os.Position); Utility.escapeNAL(nal); os.position(nal.limit()); return(sh); }