1 /*
2 * Copyright (c) 2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "encode_hevc_header_packer.h"
24 #include "encode_utils.h"
25
HevcHeaderPacker()26 HevcHeaderPacker::HevcHeaderPacker()
27 {
28 for (auto it = m_rbsp.begin(); it != m_rbsp.end(); ++it)
29 {
30 *it = 0;
31 }
32 }
33
GetNaluParams(uint8_t nal_unit_type_in,unsigned short layer_id_in,unsigned short temporal_id,mfxU16 long_start_code)34 MOS_STATUS HevcHeaderPacker::GetNaluParams(uint8_t nal_unit_type_in, unsigned short layer_id_in, unsigned short temporal_id, mfxU16 long_start_code)
35 {
36 m_naluParams.long_start_code = long_start_code;
37 m_naluParams.nal_unit_type = static_cast<mfxU16>(nal_unit_type_in);
38 m_naluParams.nuh_layer_id = layer_id_in;
39 m_naluParams.nuh_temporal_id_plus1 = temporal_id + 1;
40 return MOS_STATUS_SUCCESS;
41 }
42
GetSPSParams(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams)43 MOS_STATUS HevcHeaderPacker::GetSPSParams(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams)
44 {
45 m_spsParams.log2_min_luma_coding_block_size_minus3 = hevcSeqParams->log2_min_coding_block_size_minus3;
46 m_spsParams.log2_diff_max_min_luma_coding_block_size = hevcSeqParams->log2_max_coding_block_size_minus3 - hevcSeqParams->log2_min_coding_block_size_minus3;
47 m_spsParams.pic_width_in_luma_samples = (hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) * (1 << (hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
48 m_spsParams.pic_height_in_luma_samples = (hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) * (1 << (hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
49 m_spsParams.separate_colour_plane_flag = hevcSeqParams->separate_colour_plane_flag;
50 m_spsParams.num_short_term_ref_pic_sets = 0; //NA
51 m_spsParams.num_long_term_ref_pics_sps = 0; //NA
52 m_spsParams.log2_max_pic_order_cnt_lsb_minus4 = 0; //Related to CurrPicOrderCnt?
53 m_spsParams.long_term_ref_pics_present_flag = 0; //NA, default in msdk
54 m_spsParams.temporal_mvp_enabled_flag = hevcSeqParams->sps_temporal_mvp_enable_flag;
55 m_spsParams.sample_adaptive_offset_enabled_flag = hevcSeqParams->SAO_enabled_flag;
56 for (int i = 0; i < 65; i++) //NA
57 {
58 m_spsParams.strps[i] = {};
59 } //NA
60 m_spsParams.chroma_format_idc = hevcSeqParams->chroma_format_idc; //NA
61 m_spsParams.high_precision_offsets_enabled_flag = 0; //NA
62 m_spsParams.bit_depth_chroma_minus8 = hevcSeqParams->bit_depth_chroma_minus8; //NA
63 m_bDssEnabled = hevcSeqParams->SliceSizeControl;
64 return MOS_STATUS_SUCCESS;
65 }
66
GetPPSParams(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)67 MOS_STATUS HevcHeaderPacker::GetPPSParams(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)
68 {
69 m_ppsParams.dependent_slice_segments_enabled_flag = hevcPicParams->dependent_slice_segments_enabled_flag;
70 m_ppsParams.num_extra_slice_header_bits = 0;
71 m_ppsParams.output_flag_present_flag = 0;
72 m_ppsParams.lists_modification_present_flag = 0; //NA
73 m_ppsParams.cabac_init_present_flag = 1; //NA
74 m_ppsParams.weighted_pred_flag = hevcPicParams->weighted_pred_flag; //NA
75 m_ppsParams.weighted_bipred_flag = hevcPicParams->weighted_bipred_flag; //NA
76 m_ppsParams.slice_chroma_qp_offsets_present_flag = 1;
77 m_ppsParams.deblocking_filter_override_enabled_flag = 0; //hevcPicParams->deblocking_filter_override_enabled_flag; exist but not transfered from msdk
78 m_ppsParams.loop_filter_across_slices_enabled_flag = hevcPicParams->loop_filter_across_slices_flag; //>=CNL,else =0
79 m_ppsParams.tiles_enabled_flag = hevcPicParams->tiles_enabled_flag;
80 m_ppsParams.entropy_coding_sync_enabled_flag = hevcPicParams->entropy_coding_sync_enabled_flag;
81 m_ppsParams.slice_segment_header_extension_present_flag = 0;
82 m_ppsParams.deblocking_filter_disabled_flag = hevcPicParams->pps_deblocking_filter_disabled_flag;
83 m_ppsParams.beta_offset_div2 = 0;
84 m_ppsParams.tc_offset_div2 = 0;
85 m_sliceParams.no_output_of_prior_pics_flag = hevcPicParams->no_output_of_prior_pics_flag;
86 m_sliceParams.pic_parameter_set_id = hevcPicParams->slice_pic_parameter_set_id;
87 m_sliceParams.collocated_ref_idx = hevcPicParams->CollocatedRefPicIndex; //NA
88 m_sliceParams.pic_order_cnt_lsb = hevcPicParams->CurrPicOrderCnt; // need reset poc_lsb later, store cur poc now for later lsb calculation
89 nalType = hevcPicParams->nal_unit_type;
90 return MOS_STATUS_SUCCESS;
91 }
92
GetSliceParams(const CODEC_HEVC_ENCODE_SLICE_PARAMS hevcSliceParams)93 MOS_STATUS HevcHeaderPacker::GetSliceParams(const CODEC_HEVC_ENCODE_SLICE_PARAMS hevcSliceParams)
94 {
95 m_sliceParams.first_slice_segment_in_pic_flag = (bool)!hevcSliceParams.slice_segment_address; //?
96 m_sliceParams.dependent_slice_segment_flag = hevcSliceParams.dependent_slice_segment_flag;
97 m_sliceParams.segment_address = hevcSliceParams.slice_segment_address;
98 m_sliceParams.reserved_flags = 0; //could be got, but seems always 0
99 m_sliceParams.type = hevcSliceParams.slice_type;
100 m_sliceParams.pic_output_flag = 1;
101 m_sliceParams.colour_plane_id = 0; //pre=0, unused
102 m_sliceParams.short_term_ref_pic_set_sps_flag = 0; //NA
103 for (int i = 0; i < MAX_NUM_LONG_TERM_PICS; i++) //NA
104 {
105 m_sliceParams.lt[i] = {};
106 } //NA
107 m_sliceParams.short_term_ref_pic_set_idx = 0; //NA
108 m_sliceParams.strps = {}; //NA
109 m_sliceParams.num_long_term_sps = 0; //NA
110 m_sliceParams.num_long_term_pics = 0; //NA
111 m_sliceParams.temporal_mvp_enabled_flag = hevcSliceParams.slice_temporal_mvp_enable_flag;
112 m_sliceParams.sao_luma_flag = hevcSliceParams.slice_sao_luma_flag;
113 m_sliceParams.sao_chroma_flag = hevcSliceParams.slice_sao_chroma_flag;
114 m_sliceParams.collocated_from_l0_flag = hevcSliceParams.collocated_from_l0_flag; //NA
115 m_sliceParams.num_ref_idx_l0_active_minus1 = hevcSliceParams.num_ref_idx_l0_active_minus1; //NA
116 m_sliceParams.num_ref_idx_l1_active_minus1 = hevcSliceParams.num_ref_idx_l1_active_minus1; //NA
117 //m_sliceParams.ref_pic_list_modification_flag_lx={0};//NA
118 //m_sliceParams.list_entry_lx=0;//NA
119 m_sliceParams.num_ref_idx_active_override_flag = 1; //NA
120 m_sliceParams.mvd_l1_zero_flag = hevcSliceParams.mvd_l1_zero_flag; //NA
121 m_sliceParams.cabac_init_flag = hevcSliceParams.cabac_init_flag; //NA
122 m_sliceParams.five_minus_max_num_merge_cand = 5 - hevcSliceParams.MaxNumMergeCand; //NA
123 m_sliceParams.slice_qp_delta = hevcSliceParams.slice_qp_delta; //transfered and recieved, but wrong data/ Maybe transfered too late?
124 m_sliceParams.slice_cb_qp_offset = hevcSliceParams.slice_cb_qp_offset;
125 m_sliceParams.slice_cr_qp_offset = hevcSliceParams.slice_cr_qp_offset;
126 m_sliceParams.beta_offset_div2 = hevcSliceParams.beta_offset_div2;
127 m_sliceParams.tc_offset_div2 = hevcSliceParams.tc_offset_div2;
128 m_sliceParams.loop_filter_across_slices_enabled_flag = 1; //>=CNL,else =0
129 m_sliceParams.num_entry_point_offsets = 0; //*= !(m_ppsParams.tiles_enabled_flag || m_ppsParams.entropy_coding_sync_enabled_flag);
130 m_sliceParams.luma_log2_weight_denom = 0; //NA
131 m_sliceParams.chroma_log2_weight_denom = 0; //NA
132 m_sliceParams.deblocking_filter_disabled_flag = hevcSliceParams.slice_deblocking_filter_disable_flag;
133 m_sliceParams.deblocking_filter_override_flag = (m_sliceParams.deblocking_filter_disabled_flag != m_ppsParams.deblocking_filter_disabled_flag);
134 m_sliceParams.deblocking_filter_override_flag |=
135 !m_sliceParams.deblocking_filter_disabled_flag && (m_sliceParams.beta_offset_div2 != m_ppsParams.beta_offset_div2 || m_sliceParams.tc_offset_div2 != m_ppsParams.tc_offset_div2);
136 return MOS_STATUS_SUCCESS;
137 }
138
PackSSH(BitstreamWriter & bs,HevcNALU const & nalu,HevcSPS const & sps,HevcPPS const & pps,HevcSlice const & slice,bool dyn_slice_size=false)139 void HevcHeaderPacker::PackSSH(
140 BitstreamWriter &bs,
141 HevcNALU const & nalu,
142 HevcSPS const & sps,
143 HevcPPS const & pps,
144 HevcSlice const &slice,
145 bool dyn_slice_size = false)
146 {
147 PackNALU(bs, nalu);
148
149 if (!dyn_slice_size)
150 PackSSHPartIdAddr(bs, nalu, sps, pps, slice);
151
152 if (!slice.dependent_slice_segment_flag)
153 PackSSHPartIndependent(bs, nalu, sps, pps, slice);
154
155 if (pps.tiles_enabled_flag || pps.entropy_coding_sync_enabled_flag)
156 {
157 ENCODE_ASSERT(slice.num_entry_point_offsets == 0);
158
159 bs.PutUE(slice.num_entry_point_offsets);
160 }
161
162 ENCODE_ASSERT(0 == pps.slice_segment_header_extension_present_flag);
163
164 if (!dyn_slice_size) // no trailing bits for dynamic slice size
165 bs.PutTrailingBits();
166 }
167
PackNALU(BitstreamWriter & bs,NALU const & h)168 void HevcHeaderPacker::PackNALU(BitstreamWriter &bs, NALU const &h)
169 {
170 bool bLong_SC =
171 h.nal_unit_type == VPS_NUT || h.nal_unit_type == SPS_NUT || h.nal_unit_type == PPS_NUT || h.nal_unit_type == AUD_NUT || h.nal_unit_type == PREFIX_SEI_NUT || h.long_start_code;
172
173 if (bLong_SC)
174 bs.PutBits(8, 0); //zero_byte
175
176 bs.PutBits(24, 0x000001); //start_code
177
178 bs.PutBit(0);
179 bs.PutBits(6, h.nal_unit_type);
180 bs.PutBits(6, h.nuh_layer_id);
181 bs.PutBits(3, h.nuh_temporal_id_plus1);
182 }
183
PackSSHPartIdAddr(BitstreamWriter & bs,NALU const & nalu,SPS const & sps,PPS const & pps,Slice const & slice)184 void HevcHeaderPacker::PackSSHPartIdAddr(
185 BitstreamWriter &bs,
186 NALU const & nalu,
187 SPS const & sps,
188 PPS const & pps,
189 Slice const & slice)
190 {
191 mfxU32 MaxCU = (1 << (sps.log2_min_luma_coding_block_size_minus3 + 3 + sps.log2_diff_max_min_luma_coding_block_size));
192 mfxU32 PicSizeInCtbsY = CeilDiv(sps.pic_width_in_luma_samples, MaxCU) * CeilDiv(sps.pic_height_in_luma_samples, MaxCU);
193
194 bs.PutBit(slice.first_slice_segment_in_pic_flag);
195
196 bool bIRAP = nalu.nal_unit_type >= BLA_W_LP && nalu.nal_unit_type <= RSV_IRAP_VCL23;
197
198 if (bIRAP)
199 bs.PutBit(slice.no_output_of_prior_pics_flag);
200
201 bs.PutUE(slice.pic_parameter_set_id);
202
203 if (!slice.first_slice_segment_in_pic_flag)
204 {
205 if (pps.dependent_slice_segments_enabled_flag)
206 bs.PutBit(slice.dependent_slice_segment_flag);
207
208 bs.PutBits(CeilLog2(PicSizeInCtbsY), slice.segment_address);
209 }
210 }
211
PackSSHPartIndependent(BitstreamWriter & bs,NALU const & nalu,SPS const & sps,PPS const & pps,Slice const & slice)212 void HevcHeaderPacker::PackSSHPartIndependent(
213 BitstreamWriter &bs,
214 NALU const & nalu,
215 SPS const & sps,
216 PPS const & pps,
217 Slice const & slice)
218 {
219 const mfxU8 I = 2;
220 mfxU32 nSE = 0;
221
222 nSE += PutBits(bs, pps.num_extra_slice_header_bits, slice.reserved_flags);
223 nSE += PutUE(bs, slice.type);
224 nSE += pps.output_flag_present_flag && PutBit(bs, slice.pic_output_flag);
225 nSE += (sps.separate_colour_plane_flag == 1) && PutBits(bs, 2, slice.colour_plane_id);
226
227 bool bNonIDR = nalu.nal_unit_type != IDR_W_RADL && nalu.nal_unit_type != IDR_N_LP;
228
229 if (bNonIDR)
230 PackSSHPartNonIDR(bs, sps, slice);
231
232 if (sps.sample_adaptive_offset_enabled_flag)
233 {
234 bs.AddInfo(PACK_SAOOffset, bs.GetOffset());
235
236 nSE += PutBit(bs, slice.sao_luma_flag);
237 nSE += PutBit(bs, slice.sao_chroma_flag);
238 }
239
240 if (slice.type != I)
241 PackSSHPartPB(bs, sps, pps, slice);
242
243 bs.AddInfo(PACK_QPDOffset, bs.GetOffset());
244
245 nSE += PutSE(bs, slice.slice_qp_delta);
246 nSE += pps.slice_chroma_qp_offsets_present_flag && PutSE(bs, slice.slice_cb_qp_offset);
247 nSE += pps.slice_chroma_qp_offsets_present_flag && PutSE(bs, slice.slice_cr_qp_offset);
248 nSE += pps.deblocking_filter_override_enabled_flag && PutBit(bs, slice.deblocking_filter_override_flag);
249 nSE += slice.deblocking_filter_override_flag && PutBit(bs, slice.deblocking_filter_disabled_flag);
250
251 bool bPackDblkOffsets = slice.deblocking_filter_override_flag && !slice.deblocking_filter_disabled_flag;
252 nSE += bPackDblkOffsets && PutSE(bs, slice.beta_offset_div2);
253 nSE += bPackDblkOffsets && PutSE(bs, slice.tc_offset_div2);
254
255 bool bPackSliceLF =
256 (pps.loop_filter_across_slices_enabled_flag && (slice.sao_luma_flag || slice.sao_chroma_flag || !slice.deblocking_filter_disabled_flag));
257
258 nSE += bPackSliceLF && PutBit(bs, slice.loop_filter_across_slices_enabled_flag);
259
260 ENCODE_ASSERT(nSE >= 2);
261 }
262
PackSSHPartNonIDR(BitstreamWriter & bs,SPS const & sps,Slice const & slice)263 void HevcHeaderPacker::PackSSHPartNonIDR(
264 BitstreamWriter &bs,
265 SPS const & sps,
266 Slice const & slice)
267 {
268 mfxU32 nSE = 0;
269 bool bNeedStIdx = slice.short_term_ref_pic_set_sps_flag && (sps.num_short_term_ref_pic_sets > 1);
270 auto PutSpsLT = [&](const Slice::LongTerm <) {
271 nSE += (sps.num_long_term_ref_pics_sps > 1) && PutBits(bs, CeilLog2(sps.num_long_term_ref_pics_sps), lt.lt_idx_sps);
272 nSE += PutBit(bs, lt.delta_poc_msb_present_flag);
273 nSE += lt.delta_poc_msb_present_flag && PutUE(bs, lt.delta_poc_msb_cycle_lt);
274 };
275 auto PutSliceLT = [&](const Slice::LongTerm <) {
276 nSE += PutBits(bs, sps.log2_max_pic_order_cnt_lsb_minus4 + 4, lt.poc_lsb_lt);
277 nSE += PutBit(bs, lt.used_by_curr_pic_lt_flag);
278 nSE += PutBit(bs, lt.delta_poc_msb_present_flag);
279 nSE += lt.delta_poc_msb_present_flag && PutUE(bs, lt.delta_poc_msb_cycle_lt);
280 };
281
282 nSE += PutBits(bs, sps.log2_max_pic_order_cnt_lsb_minus4 + 4, slice.pic_order_cnt_lsb);
283 nSE += PutBit(bs, slice.short_term_ref_pic_set_sps_flag);
284
285 if (!slice.short_term_ref_pic_set_sps_flag)
286 {
287 std::vector<STRPS> strps(sps.strps, sps.strps + sps.num_short_term_ref_pic_sets);
288 strps.push_back(slice.strps);
289 PackSTRPS(bs, strps.data(), sps.num_short_term_ref_pic_sets, sps.num_short_term_ref_pic_sets);
290 }
291
292 nSE += bNeedStIdx && PutBits(bs, CeilLog2(sps.num_short_term_ref_pic_sets), slice.short_term_ref_pic_set_idx);
293
294 if (sps.long_term_ref_pics_present_flag)
295 {
296 nSE += (sps.num_long_term_ref_pics_sps > 0) && PutUE(bs, slice.num_long_term_sps);
297 nSE += PutUE(bs, slice.num_long_term_pics);
298
299 std::for_each(slice.lt, slice.lt + slice.num_long_term_sps, PutSpsLT);
300 std::for_each(slice.lt, slice.lt + slice.num_long_term_pics, PutSliceLT);
301 }
302
303 nSE += sps.temporal_mvp_enabled_flag && PutBit(bs, slice.temporal_mvp_enabled_flag);
304
305 ENCODE_ASSERT(nSE >= 2);
306 }
307
PackSTRPS(BitstreamWriter & bs,const STRPS * sets,mfxU32 num,mfxU32 idx)308 void HevcHeaderPacker::PackSTRPS(BitstreamWriter &bs, const STRPS *sets, mfxU32 num, mfxU32 idx)
309 {
310 //This function is not needed for I frame.
311 STRPS const &strps = sets[idx];
312
313 if (idx != 0)
314 bs.PutBit(strps.inter_ref_pic_set_prediction_flag);
315
316 if (strps.inter_ref_pic_set_prediction_flag)
317 {
318 if (idx == num)
319 bs.PutUE(strps.delta_idx_minus1);
320
321 bs.PutBit(strps.delta_rps_sign);
322 bs.PutUE(strps.abs_delta_rps_minus1);
323
324 mfxU32 RefRpsIdx = idx - (strps.delta_idx_minus1 + 1);
325 mfxU32 NumDeltaPocs = sets[RefRpsIdx].num_negative_pics + sets[RefRpsIdx].num_positive_pics;
326
327 std::for_each(
328 strps.pic, strps.pic + NumDeltaPocs + 1, [&](const STRPS::Pic &pic) {
329 bs.PutBit(pic.used_by_curr_pic_flag);
330
331 if (!pic.used_by_curr_pic_flag)
332 bs.PutBit(pic.use_delta_flag);
333 });
334 }
335 else
336 {
337 bs.PutUE(strps.num_negative_pics);
338 bs.PutUE(strps.num_positive_pics);
339
340 std::for_each(
341 strps.pic, strps.pic + strps.num_positive_pics + strps.num_negative_pics, [&](const STRPS::Pic &pic) {
342 bs.PutUE(pic.delta_poc_sx_minus1);
343 bs.PutBit(pic.used_by_curr_pic_sx_flag);
344 });
345 }
346 };
347
PackSSHPartPB(BitstreamWriter & bs,SPS const & sps,PPS const & pps,Slice const & slice)348 void HevcHeaderPacker::PackSSHPartPB(
349 BitstreamWriter &bs,
350 SPS const & sps,
351 PPS const & pps,
352 Slice const & slice)
353 {
354 //This function is not needed for I frame.
355 auto IsSTUsed = [](const STRPSPic &pic) { return !!pic.used_by_curr_pic_sx_flag; };
356 auto IsLTUsed = [](const Slice::LongTerm <) { return !!lt.used_by_curr_pic_lt_flag; };
357 bool bB = (slice.type == 0);
358 mfxU32 nSE = 0;
359 auto stEnd = slice.strps.pic + slice.strps.num_negative_pics + slice.strps.num_positive_pics;
360 auto ltEnd = slice.lt + slice.num_long_term_sps + slice.num_long_term_pics;
361 mfxU16 NumPocTotalCurr = mfxU16(std::count_if(slice.strps.pic, stEnd, IsSTUsed) + std::count_if(slice.lt, ltEnd, IsLTUsed));
362 bool bNeedRefPicListM0 = pps.lists_modification_present_flag && NumPocTotalCurr > 1;
363 bool bNeedRefPicListM1 = bNeedRefPicListM0 && bB;
364 bool bNeedCRefIdx0 = (slice.collocated_from_l0_flag && slice.num_ref_idx_l0_active_minus1 > 0);
365 bool bNeedCRefIdx1 = (!slice.collocated_from_l0_flag && slice.num_ref_idx_l1_active_minus1 > 0);
366 bool bNeedCRefIdx = slice.temporal_mvp_enabled_flag && (bNeedCRefIdx0 || bNeedCRefIdx1);
367 auto PackRefPicListM = [&](mfxU8 lx, mfxU8 num) {
368 nSE += PutBit(bs, !!slice.ref_pic_list_modification_flag_lx[lx]);
369
370 num *= !!slice.ref_pic_list_modification_flag_lx[lx];
371
372 std::for_each(slice.list_entry_lx[lx], slice.list_entry_lx[lx] + num, [&](mfxU8 entry) {
373 nSE += PutBits(bs, CeilLog2(NumPocTotalCurr), entry);
374 });
375 };
376
377 nSE += PutBit(bs, slice.num_ref_idx_active_override_flag);
378 nSE += slice.num_ref_idx_active_override_flag && PutUE(bs, slice.num_ref_idx_l0_active_minus1);
379 nSE += slice.num_ref_idx_active_override_flag && bB && PutUE(bs, slice.num_ref_idx_l1_active_minus1);
380
381 if (bNeedRefPicListM0)
382 {
383 PackRefPicListM(0, slice.num_ref_idx_l0_active_minus1 + 1);
384 }
385
386 if (bNeedRefPicListM1)
387 {
388 PackRefPicListM(1, slice.num_ref_idx_l1_active_minus1 + 1);
389 }
390
391 nSE += bB && PutBit(bs, slice.mvd_l1_zero_flag);
392 nSE += pps.cabac_init_present_flag && PutBit(bs, slice.cabac_init_flag);
393 nSE += slice.temporal_mvp_enabled_flag && bB && PutBit(bs, slice.collocated_from_l0_flag);
394 nSE += bNeedCRefIdx && PutUE(bs, slice.collocated_ref_idx);
395
396 PackSSHPWT(bs, sps, pps, slice);
397
398 nSE += PutUE(bs, slice.five_minus_max_num_merge_cand);
399
400 ENCODE_ASSERT(nSE >= 2);
401 }
402
PackSSHPWT(BitstreamWriter & bs,const SPS & sps,const PPS & pps,const Slice & slice)403 bool HevcHeaderPacker::PackSSHPWT(
404 BitstreamWriter &bs, const SPS &sps, const PPS &pps, const Slice &slice)
405 {
406 //This function is not needed for I frame.
407 constexpr mfxU16 Y = 0, Cb = 1, Cr = 2, W = 0, O = 1, P = 1, B = 0;
408
409 struct AccWFlag : std::pair<mfxU16, mfxI16>
410 {
411 AccWFlag(mfxU16 idx, mfxI16 w) : std::pair<mfxU16, mfxI16>(idx, w) {}
412 mfxU16 operator()(mfxU16 wf, const mfxI16 (&pwt)[3][2])
413 {
414 return (wf << 1) + !(pwt[first][O] == 0 && pwt[first][W] == second);
415 };
416 };
417
418 bool bNeedY = (pps.weighted_pred_flag && slice.type == P) || (pps.weighted_bipred_flag && slice.type == B);
419 bool bNeedC = bNeedY && (sps.chroma_format_idc != 0);
420 mfxI16 BdOffsetC =
421 sps.high_precision_offsets_enabled_flag * (sps.bit_depth_chroma_minus8 + 8 - 1) + !sps.high_precision_offsets_enabled_flag * 7;
422 mfxU32 nSE = 0;
423 mfxI16 WpOffC = (1 << BdOffsetC);
424 mfxI16 wY = (1 << slice.luma_log2_weight_denom);
425 mfxI16 wC = (1 << slice.chroma_log2_weight_denom);
426 mfxI16 l2WDc = slice.chroma_log2_weight_denom;
427 auto startOffset = bs.GetOffset();
428
429 auto PutPwtLX = [&](const mfxI16(&pwtLX)[16][3][2], mfxU32 sz) {
430 mfxU32 szY = sz * bNeedY;
431 mfxU32 szC = sz * bNeedC;
432 mfxU16 wfmap = (1 << (szY - 1));
433 mfxU16 lumaw = 0;
434 mfxU16 chromaw = 0;
435 auto PutWOVal = [&](const mfxI16(&pwt)[3][2]) {
436 bool bPutY = !!(lumaw & wfmap);
437 bool bPutC = !!(chromaw & wfmap);
438
439 nSE += bPutY && PutSE(bs, pwt[Y][W] - wY);
440 nSE += bPutY && PutSE(bs, pwt[Y][O]);
441
442 nSE += bPutC && PutSE(bs, pwt[Cb][W] - wC);
443 nSE += bPutC && PutSE(bs, clamp(((WpOffC * pwt[Cb][W]) >> l2WDc) + pwt[Cb][O] - WpOffC, -4 * WpOffC, 4 * WpOffC - 1));
444
445 nSE += bPutC && PutSE(bs, pwt[Cb][W] - wC);
446 nSE += bPutC && PutSE(bs, clamp(((WpOffC * pwt[Cr][W]) >> l2WDc) + pwt[Cr][O] - WpOffC, -4 * WpOffC, 4 * WpOffC - 1));
447
448 wfmap >>= 1;
449 };
450
451 lumaw = std::accumulate(pwtLX, pwtLX + szY, mfxU16(0), AccWFlag(Y, wY));
452 chromaw = std::accumulate(pwtLX, pwtLX + szC, mfxU16(0), AccWFlag(Cb, wC));
453 chromaw |= std::accumulate(pwtLX, pwtLX + szC, mfxU16(0), AccWFlag(Cr, wC));
454
455 nSE += szY && PutBits(bs, szY, lumaw);
456 nSE += szC && PutBits(bs, szC, chromaw);
457
458 std::for_each(pwtLX, pwtLX + szY, PutWOVal);
459 };
460
461 bs.AddInfo(PACK_PWTOffset, startOffset);
462
463 nSE += bNeedY && PutUE(bs, slice.luma_log2_weight_denom);
464 nSE += bNeedC && PutSE(bs, mfxI32(slice.chroma_log2_weight_denom) - slice.luma_log2_weight_denom);
465
466 PutPwtLX(slice.pwt[0], slice.num_ref_idx_l0_active_minus1 + 1);
467 PutPwtLX(slice.pwt[1], (slice.num_ref_idx_l1_active_minus1 + 1) * (slice.type == B));
468
469 bs.AddInfo(PACK_PWTLength, bs.GetOffset() - startOffset);
470
471 return !!nSE;
472 }
473
LoadSliceHeaderParams(CodecEncodeHevcSliceHeaderParams * pSH)474 MOS_STATUS HevcHeaderPacker::LoadSliceHeaderParams(CodecEncodeHevcSliceHeaderParams* pSH)
475 {
476 ENCODE_CHK_NULL_RETURN(pSH);
477
478 m_spsParams.log2_max_pic_order_cnt_lsb_minus4 = pSH->log2_max_pic_order_cnt_lsb_minus4;
479 m_sliceParams.pic_order_cnt_lsb &= ~(0xFFFFFFFF << (m_spsParams.log2_max_pic_order_cnt_lsb_minus4 + 4));
480 m_sliceParams.num_long_term_pics = pSH->num_long_term_pics;
481
482 if(m_sliceParams.num_long_term_pics > MAX_NUM_LONG_TERM_PICS)
483 {
484 return MOS_STATUS_INVALID_PARAMETER;
485 }
486 for (int i = 0; i < m_sliceParams.num_long_term_pics; i++)
487 {
488 m_sliceParams.lt[i].used_by_curr_pic_lt_flag = pSH->lt[i].used_by_curr_pic_lt_flag;
489 m_sliceParams.lt[i].delta_poc_msb_present_flag = pSH->lt[i].delta_poc_msb_present_flag;
490 m_sliceParams.lt[i].poc_lsb_lt = pSH->lt[i].poc_lsb_lt;
491 m_sliceParams.lt[i].delta_poc_msb_cycle_lt = pSH->lt[i].delta_poc_msb_cycle_lt;
492 }
493 m_ppsParams.lists_modification_present_flag = pSH->lists_modification_present_flag;
494 for (int i = 0; i < 2; i++)
495 {
496 m_sliceParams.ref_pic_list_modification_flag_lx[i] = pSH->ref_pic_list_modification_flag_lx[i];
497 for (int j = 0; j < 16; j++)
498 {
499 m_sliceParams.list_entry_lx[i][j] = pSH->list_entry_lx[i][j];
500 }
501 }
502 m_sliceParams.strps.num_negative_pics = pSH->num_negative_pics;
503 m_sliceParams.strps.num_positive_pics = pSH->num_positive_pics;
504
505 if (pSH->num_negative_pics > 16 || pSH->num_positive_pics > 16 || pSH->num_negative_pics + pSH->num_positive_pics > 16)
506 {
507 return MOS_STATUS_INVALID_PARAMETER;
508 }
509
510 for (int i = 0; i < pSH->num_negative_pics + pSH->num_positive_pics; i++)
511 {
512 if (i < pSH->num_negative_pics)
513 {
514 m_sliceParams.strps.pic[i].delta_poc_s0_minus1 = pSH->delta_poc_minus1[0][i];
515 m_sliceParams.strps.pic[i].used_by_curr_pic_s0_flag = pSH->used_by_curr_pic_flag[0][i];
516 }
517 else
518 {
519 m_sliceParams.strps.pic[i].delta_poc_s1_minus1 = pSH->delta_poc_minus1[1][i - pSH->num_negative_pics];
520 m_sliceParams.strps.pic[i].used_by_curr_pic_s1_flag = pSH->used_by_curr_pic_flag[1][i - pSH->num_negative_pics];
521 }
522 }
523
524 return MOS_STATUS_SUCCESS;
525 }
526
SliceHeaderPacker(EncoderParams * encodeParams)527 MOS_STATUS HevcHeaderPacker::SliceHeaderPacker(EncoderParams *encodeParams)
528 {
529 MOS_OS_FUNCTION_ENTER;
530 MOS_STATUS eStatus;
531 BitstreamWriter rbsp(m_rbsp.data(), (mfxU32)m_rbsp.size());
532 mfxU8 * pBegin = rbsp.GetStart();
533 mfxU8 * startplace = pBegin;
534 mfxU8 * pEnd = pBegin + m_rbsp.size();
535 mfxU32 BitLen;
536 mfxU32 BitLenRecorded = 0;
537
538 EncoderParams *pCodecHalEncodeParams = encodeParams;
539 ENCODE_CHK_NULL_RETURN(pCodecHalEncodeParams);
540 BSBuffer *pBSBuffer = pCodecHalEncodeParams->pBSBuffer;
541 ENCODE_CHK_NULL_RETURN(pBSBuffer);
542 PCODEC_ENCODER_SLCDATA pSlcData = (PCODEC_ENCODER_SLCDATA)pCodecHalEncodeParams->pSlcHeaderData;
543 ENCODE_CHK_STATUS_RETURN(GetSPSParams(static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams)));
544 ENCODE_CHK_STATUS_RETURN(GetPPSParams(static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams)));
545 ENCODE_CHK_STATUS_RETURN(GetNaluParams(nalType, 0, 0, pBSBuffer->pCurrent == pBSBuffer->pBase));
546
547 //uint8_t *pCurrent = pBSBuffer->pCurrent;
548 //uint32_t
549 for (uint32_t startLcu = 0, slcCount = 0; slcCount < encodeParams->dwNumSlices; slcCount++)
550 {
551 //startLcu += m_hevcSliceParams[slcCount].NumLCUsInSlice;
552 ENCODE_CHK_STATUS_RETURN(GetSliceParams(static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams)[slcCount]));
553 ENCODE_CHK_STATUS_RETURN(LoadSliceHeaderParams((CodecEncodeHevcSliceHeaderParams*) pCodecHalEncodeParams->pSliceHeaderParams));
554
555 rbsp.Reset(pBegin, mfxU32(pEnd - pBegin));
556 m_naluParams.long_start_code = 0/*pBSBuffer->pCurrent + (BitLenRecorded + 7) / 8 == pBSBuffer->pBase*/;
557 PackSSH(rbsp, m_naluParams, m_spsParams, m_ppsParams, m_sliceParams, m_bDssEnabled);
558 BitLen = rbsp.GetOffset();
559 pBegin += CeilDiv(BitLen, 8u);
560 pSlcData[slcCount].SliceOffset = (uint32_t)(pBSBuffer->pCurrent + (BitLenRecorded + 7) / 8 - pBSBuffer->pBase);
561 pSlcData[slcCount].BitSize = BitLen * 1 + (BitLen + 7) / 8 * !1;
562 pSlcData[slcCount].SkipEmulationByteCount = 3 /*+ (pBSBuffer->pCurrent + (BitLenRecorded + 7) / 8 == pBSBuffer->pBase)*/;
563 BitLenRecorded = BitLenRecorded + BitLen;
564 }
565
566 MOS_SecureMemcpy(pBSBuffer->pCurrent,
567 (BitLenRecorded + 7) / 8,
568 startplace,
569 (BitLenRecorded + 7) / 8);
570
571 return MOS_STATUS_SUCCESS;
572 }