1 /*
2 * Copyright © Microsoft 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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "d3d12_video_encoder_nalu_writer_hevc.h"
25 #include <algorithm>
26
27 // Writes the HEVC VPS structure into a bitstream passed in headerBitstream
28 // Function resizes bitstream accordingly and puts result in byte vector
29 void
vps_to_nalu_bytes(HevcVideoParameterSet * pVPS,std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes)30 d3d12_video_nalu_writer_hevc::vps_to_nalu_bytes(HevcVideoParameterSet *pVPS,
31 std::vector<BYTE> &headerBitstream,
32 std::vector<BYTE>::iterator placingPositionStart,
33 size_t &writtenBytes) {
34 generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, pVPS);
35 }
36
37 // Writes the HEVC pSPS structure into a bitstream passed in headerBitstream
38 // Function resizes bitstream accordingly and puts result in byte vector
39 void
sps_to_nalu_bytes(HevcSeqParameterSet * pSPS,std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes)40 d3d12_video_nalu_writer_hevc::sps_to_nalu_bytes(HevcSeqParameterSet *pSPS,
41 std::vector<BYTE> &headerBitstream,
42 std::vector<BYTE>::iterator placingPositionStart,
43 size_t &writtenBytes) {
44 generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, pSPS);
45 }
46
47 // Writes the HEVC PPS structure into a bitstream passed in headerBitstream
48 // Function resizes bitstream accordingly and puts result in byte vector
49 void
pps_to_nalu_bytes(HevcPicParameterSet * pPPS,std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes)50 d3d12_video_nalu_writer_hevc::pps_to_nalu_bytes(HevcPicParameterSet *pPPS,
51 std::vector<BYTE> &headerBitstream,
52 std::vector<BYTE>::iterator placingPositionStart,
53 size_t &writtenBytes) {
54 generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, pPPS);
55 }
56
57 void
write_end_of_stream_nalu(std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes)58 d3d12_video_nalu_writer_hevc::write_end_of_stream_nalu(std::vector<BYTE> &headerBitstream,
59 std::vector<BYTE>::iterator placingPositionStart,
60 size_t &writtenBytes) {
61 HEVCNaluHeader endOfStreamNALU =
62 {
63 // uint8_t forbidden_zero_bit;
64 static_cast<uint8_t>(0u),
65 // uint8_t nal_unit_type
66 static_cast<uint8_t>(HEVC_NALU_EOB_NUT),
67 // uint8_t nuh_layer_id
68 static_cast<uint8_t>(0u),
69 // uint8_t nuh_temporal_id_plus1
70 static_cast<uint8_t>(1u)
71 };
72 generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &endOfStreamNALU);
73 }
74
75 void
write_end_of_sequence_nalu(std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes)76 d3d12_video_nalu_writer_hevc::write_end_of_sequence_nalu(std::vector<BYTE> &headerBitstream,
77 std::vector<BYTE>::iterator placingPositionStart,
78 size_t &writtenBytes) {
79 HEVCNaluHeader endOfSeqNALU =
80 {
81 // uint8_t forbidden_zero_bit;
82 static_cast<uint8_t>(0u),
83 // uint8_t nal_unit_type
84 static_cast<uint8_t>(HEVC_NALU_EOS_NUT),
85 // uint8_t nuh_layer_id
86 static_cast<uint8_t>(0u),
87 // uint8_t nuh_temporal_id_plus1
88 static_cast<uint8_t>(1u)
89 };
90 generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &endOfSeqNALU);
91 }
92
93 void
write_aud(std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType,size_t & writtenBytes)94 d3d12_video_nalu_writer_hevc::write_aud(std::vector<BYTE> &headerBitstream,
95 std::vector<BYTE>::iterator placingPositionStart,
96 D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType,
97 size_t &writtenBytes) {
98 HevcAccessUnitDelimiter AUD = {};
99
100 AUD.nalu =
101 {
102 // uint8_t forbidden_zero_bit;
103 static_cast<uint8_t>(0u),
104 // uint8_t nal_unit_type
105 static_cast<uint8_t>(HEVC_NALU_AUD_NUT),
106 // uint8_t nuh_layer_id
107 static_cast<uint8_t>(0u),
108 // uint8_t nuh_temporal_id_plus1
109 static_cast<uint8_t>(1u)
110 };
111
112 // pic_type slice_type values that may be present in the coded picture
113 switch (frameType)
114 {
115 case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME:
116 case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_I_FRAME:
117 {
118 AUD.pic_type = 0u; // 0 I
119 } break;
120 case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME:
121 {
122 AUD.pic_type = 1u; // 1 P, I
123 } break;
124 case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME:
125 {
126 AUD.pic_type = 2u; // 2 B, P, I
127 } break;
128 default:
129 {
130 debug_printf("d3d12_video_nalu_writer_hevc::write_aud failed: Invalid D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType argument \n");
131 assert(false);
132 } break;
133 }
134
135 generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &AUD);
136 }
137
138 void
generic_write_bytes(std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes,void * pStructure)139 d3d12_video_nalu_writer_hevc::generic_write_bytes( std::vector<BYTE> &headerBitstream,
140 std::vector<BYTE>::iterator placingPositionStart,
141 size_t &writtenBytes,
142 void *pStructure)
143 {
144 // Wrap pSPS into NALU and copy full NALU into output byte array
145 d3d12_video_encoder_bitstream rbsp, nalu;
146
147 /*HEVCNaluHeader nalu is in all Hevc*ParameterSet structures at the beggining*/
148 HEVCNaluHeader* nal_header = ((HEVCNaluHeader *) pStructure);
149
150 if (!rbsp.create_bitstream(MAX_COMPRESSED_NALU)) {
151 debug_printf("rbsp.create_bitstream(MAX_COMPRESSED_NALU) failed\n");
152 assert(false);
153 }
154
155 if (!nalu.create_bitstream(2 * MAX_COMPRESSED_NALU)) {
156 debug_printf("nalu.create_bitstream(2 * MAX_COMPRESSED_NALU) failed\n");
157 assert(false);
158 }
159
160 rbsp.set_start_code_prevention(true);
161 if (write_bytes_from_struct(&rbsp, pStructure, nal_header->nal_unit_type) <= 0u) {
162 debug_printf("write_bytes_from_struct(&rbsp, pStructure, nal_header->nal_unit_type) didn't write any bytes.\n");
163 assert(false);
164 }
165
166 if (wrap_rbsp_into_nalu(&nalu, &rbsp, nal_header) <= 0u) {
167 debug_printf("wrap_rbsp_into_nalu(&nalu, &rbsp, nal_header) didn't write any bytes.\n");
168 assert(false);
169 }
170
171 // Deep copy nalu into headerBitstream, nalu gets out of scope here and its destructor frees the nalu object buffer
172 // memory.
173 uint8_t *naluBytes = nalu.get_bitstream_buffer();
174 size_t naluByteSize = nalu.get_byte_count();
175
176 auto startDstIndex = std::distance(headerBitstream.begin(), placingPositionStart);
177 if (headerBitstream.size() < (startDstIndex + naluByteSize)) {
178 headerBitstream.resize(startDstIndex + naluByteSize);
179 }
180
181 std::copy_n(&naluBytes[0], naluByteSize, &headerBitstream.data()[startDstIndex]);
182
183 writtenBytes = naluByteSize;
184 }
185
186 uint32_t
write_bytes_from_struct(d3d12_video_encoder_bitstream * pBitstream,void * pData,uint8_t nal_unit_type)187 d3d12_video_nalu_writer_hevc::write_bytes_from_struct(d3d12_video_encoder_bitstream *pBitstream, void *pData, uint8_t nal_unit_type)
188 {
189 switch(nal_unit_type)
190 {
191 case HEVC_NALU_VPS_NUT:
192 {
193 return write_vps_bytes(pBitstream, (HevcVideoParameterSet *) pData);
194 } break;
195 case HEVC_NALU_SPS_NUT:
196 {
197 return write_sps_bytes(pBitstream, (HevcSeqParameterSet *) pData);
198 } break;
199 case HEVC_NALU_PPS_NUT:
200 {
201 return write_pps_bytes(pBitstream, (HevcPicParameterSet *) pData);
202 } break;
203 case HEVC_NALU_EOS_NUT:
204 case HEVC_NALU_EOB_NUT:
205 {
206 // Do nothing for these two, just the header suffices
207 return 1;
208 } break;
209 case HEVC_NALU_AUD_NUT:
210 {
211 return write_aud_bytes(pBitstream, (HevcAccessUnitDelimiter *) pData);
212 } break;
213 default:
214 {
215 unreachable("Unsupported NALU value");
216 } break;
217 }
218 }
219
220 uint32_t
write_aud_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcAccessUnitDelimiter * pAUD)221 d3d12_video_nalu_writer_hevc::write_aud_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcAccessUnitDelimiter *pAUD)
222 {
223 int32_t iBytesWritten = pBitstream->get_byte_count();
224
225 pBitstream->put_bits(3, pAUD->pic_type);
226
227 rbsp_trailing(pBitstream);
228 pBitstream->flush();
229
230 iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
231 return (uint32_t) iBytesWritten;
232 }
233
234 uint32_t
write_vps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcVideoParameterSet * vps)235 d3d12_video_nalu_writer_hevc::write_vps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcVideoParameterSet *vps)
236 {
237 int32_t iBytesWritten = pBitstream->get_byte_count();
238
239 pBitstream->put_bits(4, vps->vps_video_parameter_set_id);
240 pBitstream->put_bits(2, 3); //vps_reserved_three_2bits
241 pBitstream->put_bits(6, vps->vps_max_layers_minus1);
242 pBitstream->put_bits(3, vps->vps_max_sub_layers_minus1);
243 pBitstream->put_bits(1, vps->vps_temporal_id_nesting_flag);
244 pBitstream->put_bits(16, 0xffff); //vps_reserved_ffff_16bits
245
246 write_profile_tier_level(pBitstream, &vps->ptl);
247
248 pBitstream->put_bits(1,vps->vps_sub_layer_ordering_info_present_flag);
249
250 for (int i = 0; i <= vps->vps_max_sub_layers_minus1; i++) {
251 pBitstream->exp_Golomb_ue(vps->vps_max_dec_pic_buffering_minus1[i]);
252 pBitstream->exp_Golomb_ue(vps->vps_max_num_reorder_pics[i]);
253 pBitstream->exp_Golomb_ue(vps->vps_max_latency_increase_plus1[i]);
254 }
255
256 pBitstream->put_bits(6, vps->vps_max_layer_id);
257 pBitstream->exp_Golomb_ue(vps->vps_num_layer_sets_minus1);
258 pBitstream->put_bits(1, vps->vps_timing_info_present_flag);
259
260 pBitstream->put_bits(1, 0); // vps_extension_flag
261
262 rbsp_trailing(pBitstream);
263 pBitstream->flush();
264
265 iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
266 return (uint32_t) iBytesWritten;
267 }
268
269 uint32_t
write_sps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcSeqParameterSet * pSPS)270 d3d12_video_nalu_writer_hevc::write_sps_bytes(d3d12_video_encoder_bitstream *pBitstream,
271 HevcSeqParameterSet *pSPS)
272 {
273 int32_t iBytesWritten = pBitstream->get_byte_count();
274
275 pBitstream->put_bits(4, pSPS->sps_video_parameter_set_id);
276 pBitstream->put_bits(3, pSPS->sps_max_sub_layers_minus1);
277 pBitstream->put_bits(1, pSPS->sps_temporal_id_nesting_flag);
278
279 write_profile_tier_level(pBitstream, &pSPS->ptl);
280
281 pBitstream->exp_Golomb_ue(pSPS->sps_seq_parameter_set_id);
282
283 pBitstream->exp_Golomb_ue(pSPS->chroma_format_idc);
284
285 pBitstream->exp_Golomb_ue(pSPS->pic_width_in_luma_samples);
286 pBitstream->exp_Golomb_ue(pSPS->pic_height_in_luma_samples);
287
288 pBitstream->put_bits(1, pSPS->conformance_window_flag);
289 if (pSPS->conformance_window_flag) {
290 pBitstream->exp_Golomb_ue(pSPS->conf_win_left_offset);
291 pBitstream->exp_Golomb_ue(pSPS->conf_win_right_offset);
292 pBitstream->exp_Golomb_ue(pSPS->conf_win_top_offset);
293 pBitstream->exp_Golomb_ue(pSPS->conf_win_bottom_offset);
294 }
295
296 pBitstream->exp_Golomb_ue(pSPS->bit_depth_luma_minus8);
297 pBitstream->exp_Golomb_ue(pSPS->bit_depth_chroma_minus8);
298
299 pBitstream->exp_Golomb_ue(pSPS->log2_max_pic_order_cnt_lsb_minus4);
300
301 pBitstream->put_bits(1, pSPS->sps_sub_layer_ordering_info_present_flag);
302
303 for (int i = 0; i <= pSPS->sps_max_sub_layers_minus1; i++) {
304 pBitstream->exp_Golomb_ue(pSPS->sps_max_dec_pic_buffering_minus1[i]);
305 pBitstream->exp_Golomb_ue(pSPS->sps_max_num_reorder_pics[i]);
306 pBitstream->exp_Golomb_ue(pSPS->sps_max_latency_increase_plus1[i]);
307 }
308
309 pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
310 pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
311 pBitstream->exp_Golomb_ue(pSPS->log2_min_transform_block_size_minus2);
312 pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_transform_block_size);
313
314 pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_inter);
315 pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_intra);
316
317 pBitstream->put_bits(1, pSPS->scaling_list_enabled_flag);
318
319 pBitstream->put_bits(1, pSPS->amp_enabled_flag);
320 pBitstream->put_bits(1, pSPS->sample_adaptive_offset_enabled_flag);
321
322 pBitstream->put_bits(1, pSPS->pcm_enabled_flag);
323 if (pSPS->pcm_enabled_flag) {
324 pBitstream->put_bits(4, pSPS->bit_depth_luma_minus8 + 7);
325 pBitstream->put_bits(4, pSPS->bit_depth_chroma_minus8 + 7);
326 pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
327 pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
328 pBitstream->put_bits(1, pSPS->pcm_loop_filter_disabled_flag);
329 }
330
331 pBitstream->exp_Golomb_ue(pSPS->num_short_term_ref_pic_sets);
332 for (int i = 0; i < pSPS->num_short_term_ref_pic_sets; i++) {
333 write_rps(pBitstream, pSPS, i, false);
334 }
335
336 pBitstream->put_bits(1, pSPS->long_term_ref_pics_present_flag);
337 if (pSPS->long_term_ref_pics_present_flag) {
338 pBitstream->exp_Golomb_ue(pSPS->num_long_term_ref_pics_sps);
339 for (int i = 0; i < pSPS->num_long_term_ref_pics_sps; i++) {
340 pBitstream->put_bits(pSPS->log2_max_pic_order_cnt_lsb_minus4 + 4, pSPS->lt_ref_pic_poc_lsb_sps[i]);
341 pBitstream->put_bits(1, pSPS->used_by_curr_pic_lt_sps_flag[i]);
342 }
343 }
344
345 pBitstream->put_bits(1, pSPS->sps_temporal_mvp_enabled_flag);
346 pBitstream->put_bits(1, pSPS->strong_intra_smoothing_enabled_flag);
347 pBitstream->put_bits(1, pSPS->vui_parameters_present_flag);
348
349 pBitstream->put_bits(1, pSPS->vui.aspect_ratio_info_present_flag);
350 if (pSPS->vui.aspect_ratio_info_present_flag) {
351 pBitstream->put_bits(8, pSPS->vui.aspect_ratio_idc);
352 if (pSPS->vui.aspect_ratio_idc == 255) {
353 pBitstream->put_bits(16, pSPS->vui.sar_width);
354 pBitstream->put_bits(16, pSPS->vui.sar_height);
355 }
356 }
357
358 pBitstream->put_bits(1, pSPS->vui.overscan_info_present_flag);
359 if (pSPS->vui.overscan_info_present_flag) {
360 pBitstream->put_bits(1, pSPS->vui.overscan_appropriate_flag);
361 }
362
363 pBitstream->put_bits(1, pSPS->vui.video_signal_type_present_flag);
364 if (pSPS->vui.video_signal_type_present_flag) {
365 pBitstream->put_bits(3, pSPS->vui.video_format);
366 pBitstream->put_bits(1, pSPS->vui.video_full_range_flag);
367 pBitstream->put_bits(1, pSPS->vui.colour_description_present_flag);
368 if (pSPS->vui.colour_description_present_flag) {
369 pBitstream->put_bits(8, pSPS->vui.colour_primaries);
370 pBitstream->put_bits(8, pSPS->vui.transfer_characteristics);
371 pBitstream->put_bits(8, pSPS->vui.matrix_coeffs);
372 }
373 }
374
375 pBitstream->put_bits(1, pSPS->vui.chroma_loc_info_present_flag);
376 if (pSPS->vui.chroma_loc_info_present_flag) {
377 pBitstream->exp_Golomb_ue(pSPS->vui.chroma_sample_loc_type_top_field);
378 pBitstream->exp_Golomb_ue(pSPS->vui.chroma_sample_loc_type_bottom_field);
379 }
380
381 pBitstream->put_bits(1, pSPS->vui.neutral_chroma_indication_flag);
382 pBitstream->put_bits(1, pSPS->vui.field_seq_flag);
383 pBitstream->put_bits(1, pSPS->vui.frame_field_info_present_flag);
384 pBitstream->put_bits(1, pSPS->vui.default_display_window_flag);
385 if (pSPS->vui.default_display_window_flag) {
386 pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_left_offset);
387 pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_right_offset);
388 pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_top_offset);
389 pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_bottom_offset);
390 }
391
392 pBitstream->put_bits(1, pSPS->vui.timing_info_present_flag);
393 if (pSPS->vui.timing_info_present_flag) {
394 pBitstream->put_bits(16, pSPS->vui.num_units_in_tick >> 16);
395 pBitstream->put_bits(16, pSPS->vui.num_units_in_tick & 0xffff);
396 pBitstream->put_bits(16, pSPS->vui.time_scale >> 16);
397 pBitstream->put_bits(16, pSPS->vui.time_scale & 0xffff);
398 pBitstream->put_bits(1, pSPS->vui.poc_proportional_to_timing_flag);
399 if (pSPS->vui.poc_proportional_to_timing_flag) {
400 pBitstream->exp_Golomb_ue(pSPS->vui.num_ticks_poc_diff_one_minus1);
401 }
402
403 assert(pSPS->vui.hrd_parameters_present_flag == 0);
404 pBitstream->put_bits(1, 0); // hrd_parameters_present_flag = 0 until implementing HRD params
405 }
406
407 pBitstream->put_bits(1, pSPS->vui.bitstream_restriction_flag);
408 if (pSPS->vui.bitstream_restriction_flag) {
409 pBitstream->put_bits(1, pSPS->vui.tiles_fixed_structure_flag);
410 pBitstream->put_bits(1, pSPS->vui.motion_vectors_over_pic_boundaries_flag);
411 pBitstream->put_bits(1, pSPS->vui.restricted_ref_pic_lists_flag);
412 pBitstream->exp_Golomb_ue(pSPS->vui.min_spatial_segmentation_idc);
413 pBitstream->exp_Golomb_ue(pSPS->vui.max_bytes_per_pic_denom);
414 pBitstream->exp_Golomb_ue(pSPS->vui.max_bits_per_min_cu_denom);
415 pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_horizontal);
416 pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_vertical);
417 }
418
419 // Set sps_extension_present_flag if sps_range_extension_flag present
420 pSPS->sps_extension_present_flag = pSPS->sps_range_extension.sps_range_extension_flag ? 1u : 0u;
421
422 pBitstream->put_bits(1, pSPS->sps_extension_present_flag);
423 if (pSPS->sps_extension_present_flag)
424 {
425 pBitstream->put_bits(1, pSPS->sps_range_extension.sps_range_extension_flag);
426 pBitstream->put_bits(1, 0);// sps_multilayer_extension_flag u(1)
427 pBitstream->put_bits(1, 0);// sps_3d_extension_flag u(1)
428 pBitstream->put_bits(1, 0);// sps_scc_extension_flag u(1)
429 pBitstream->put_bits(4, 0);// sps_extension_4bits u(4)
430 }
431
432 if (pSPS->sps_range_extension.sps_range_extension_flag)
433 {
434 // sps_range_extension( )
435 pBitstream->put_bits(1, pSPS->sps_range_extension.transform_skip_rotation_enabled_flag);
436 pBitstream->put_bits(1, pSPS->sps_range_extension.transform_skip_context_enabled_flag);
437 pBitstream->put_bits(1, pSPS->sps_range_extension.implicit_rdpcm_enabled_flag);
438 pBitstream->put_bits(1, pSPS->sps_range_extension.explicit_rdpcm_enabled_flag);
439 pBitstream->put_bits(1, pSPS->sps_range_extension.extended_precision_processing_flag);
440 pBitstream->put_bits(1, pSPS->sps_range_extension.intra_smoothing_disabled_flag);
441 pBitstream->put_bits(1, pSPS->sps_range_extension.high_precision_offsets_enabled_flag);
442 pBitstream->put_bits(1, pSPS->sps_range_extension.persistent_rice_adaptation_enabled_flag);
443 pBitstream->put_bits(1, pSPS->sps_range_extension.cabac_bypass_alignment_enabled_flag);
444 }
445
446 rbsp_trailing(pBitstream);
447 pBitstream->flush();
448
449 iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
450 return (uint32_t) iBytesWritten;
451 }
452
453 uint32_t
write_pps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcPicParameterSet * pPPS)454 d3d12_video_nalu_writer_hevc::write_pps_bytes(d3d12_video_encoder_bitstream *pBitstream,
455 HevcPicParameterSet *pPPS)
456 {
457 int32_t iBytesWritten = pBitstream->get_byte_count();
458
459 pBitstream->exp_Golomb_ue(pPPS->pps_pic_parameter_set_id);
460 pBitstream->exp_Golomb_ue(pPPS->pps_seq_parameter_set_id);
461
462 pBitstream->put_bits(1, pPPS->dependent_slice_segments_enabled_flag);
463
464 pBitstream->put_bits(1, pPPS->output_flag_present_flag);
465 pBitstream->put_bits(3, pPPS->num_extra_slice_header_bits);
466
467 pBitstream->put_bits(1, pPPS->sign_data_hiding_enabled_flag);
468 pBitstream->put_bits(1, pPPS->cabac_init_present_flag);
469
470 pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[0]);
471 pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[1]);
472
473 pBitstream->exp_Golomb_se(pPPS->init_qp_minus26);
474
475 pBitstream->put_bits(1, pPPS->constrained_intra_pred_flag);
476 pBitstream->put_bits(1, pPPS->transform_skip_enabled_flag);
477 pBitstream->put_bits(1, pPPS->cu_qp_delta_enabled_flag);
478
479 if (pPPS->cu_qp_delta_enabled_flag) {
480 pBitstream->exp_Golomb_se(pPPS->diff_cu_qp_delta_depth);
481 }
482
483 pBitstream->exp_Golomb_se(pPPS->pps_cb_qp_offset);
484 pBitstream->exp_Golomb_se(pPPS->pps_cr_qp_offset);
485
486 pBitstream->put_bits(1, pPPS->pps_slice_chroma_qp_offsets_present_flag);
487
488 pBitstream->put_bits(1, pPPS->weighted_pred_flag);
489 pBitstream->put_bits(1, pPPS->weighted_bipred_flag);
490 pBitstream->put_bits(1, pPPS->transquant_bypass_enabled_flag);
491
492 pBitstream->put_bits(1, pPPS->tiles_enabled_flag);
493 pBitstream->put_bits(1, pPPS->entropy_coding_sync_enabled_flag);
494
495 if (pPPS->tiles_enabled_flag) {
496 pBitstream->exp_Golomb_ue(pPPS->num_tile_columns_minus1);
497 pBitstream->exp_Golomb_ue(pPPS->num_tile_rows_minus1);
498 pBitstream->put_bits(1, pPPS->uniform_spacing_flag);
499 if (!pPPS->uniform_spacing_flag) {
500 for (int i = 0; i < pPPS->num_tile_columns_minus1; i++) {
501 pBitstream->exp_Golomb_ue(pPPS->column_width_minus1[i]);
502 }
503 for (int i = 0; i < pPPS->num_tile_rows_minus1; i++) {
504 pBitstream->exp_Golomb_ue(pPPS->row_height_minus1[i]);
505 }
506 }
507 pBitstream->put_bits(1, pPPS->loop_filter_across_tiles_enabled_flag);
508 }
509
510 pBitstream->put_bits(1, pPPS->pps_loop_filter_across_slices_enabled_flag);
511 pBitstream->put_bits(1, pPPS->deblocking_filter_control_present_flag);
512 if (pPPS->deblocking_filter_control_present_flag) {
513 pBitstream->put_bits(1, pPPS->deblocking_filter_override_enabled_flag);
514 pBitstream->put_bits(1, pPPS->pps_deblocking_filter_disabled_flag);
515 if (!pPPS->pps_deblocking_filter_disabled_flag) {
516 pBitstream->exp_Golomb_se(pPPS->pps_beta_offset_div2);
517 pBitstream->exp_Golomb_se(pPPS->pps_tc_offset_div2);
518 }
519 }
520
521 pBitstream->put_bits(1, pPPS->pps_scaling_list_data_present_flag);
522 if (pPPS->pps_scaling_list_data_present_flag) {
523 assert(0); //, "scaling list syntax is not implemented yet");
524 }
525
526 pBitstream->put_bits(1, pPPS->lists_modification_present_flag);
527 pBitstream->exp_Golomb_ue(pPPS->log2_parallel_merge_level_minus2);
528 pBitstream->put_bits(1, pPPS->slice_segment_header_extension_present_flag);
529
530 // Set pps_extension_present_flag if sps_range_extension_flag present
531 pPPS->pps_extension_present_flag = pPPS->pps_range_extension.pps_range_extension_flag ? 1u : 0u;
532
533 pBitstream->put_bits(1, pPPS->pps_extension_present_flag);
534 if (pPPS->pps_extension_present_flag)
535 {
536 pBitstream->put_bits(1, pPPS->pps_range_extension.pps_range_extension_flag);
537 pBitstream->put_bits(1, 0);// pps_multilayer_extension_flag u(1)
538 pBitstream->put_bits(1, 0);// pps_3d_extension_flag u(1)
539 pBitstream->put_bits(1, 0);// pps_scc_extension_flag u(1)
540 pBitstream->put_bits(4, 0);// pps_extension_4bits u(4)
541 }
542
543 if (pPPS->pps_range_extension.pps_range_extension_flag)
544 {
545 // pps_range_extension( )
546 if( pPPS->transform_skip_enabled_flag )
547 pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_max_transform_skip_block_size_minus2);
548 pBitstream->put_bits(1, pPPS->pps_range_extension.cross_component_prediction_enabled_flag);
549 pBitstream->put_bits(1, pPPS->pps_range_extension.chroma_qp_offset_list_enabled_flag);
550 if(pPPS->pps_range_extension.chroma_qp_offset_list_enabled_flag) {
551 pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.diff_cu_chroma_qp_offset_depth);
552 pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.chroma_qp_offset_list_len_minus1);
553 for( unsigned i = 0; i <= pPPS->pps_range_extension.chroma_qp_offset_list_len_minus1; i++ ) {
554 pBitstream->exp_Golomb_se(pPPS->pps_range_extension.cb_qp_offset_list[i]);
555 pBitstream->exp_Golomb_se(pPPS->pps_range_extension.cr_qp_offset_list[i]);
556 }
557 }
558 pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_sao_offset_scale_luma);
559 pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_sao_offset_scale_chroma);
560 }
561
562 rbsp_trailing(pBitstream);
563 pBitstream->flush();
564
565 iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
566 return (uint32_t) iBytesWritten;
567 }
568
569 uint32_t
wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream * pNALU,d3d12_video_encoder_bitstream * pRBSP,HEVCNaluHeader * pHeader)570 d3d12_video_nalu_writer_hevc::wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream *pNALU,
571 d3d12_video_encoder_bitstream *pRBSP,
572 HEVCNaluHeader *pHeader)
573 {
574 ASSERTED bool isAligned = pRBSP->is_byte_aligned(); // causes side-effects in object state, don't put inside assert()
575 assert(isAligned);
576
577 int32_t iBytesWritten = pNALU->get_byte_count();
578
579 pNALU->set_start_code_prevention(false);
580
581 // NAL start code
582 pNALU->put_bits(24, 0);
583 pNALU->put_bits(8, 1);
584
585 // NAL header
586 pNALU->put_bits(1, pHeader->forbidden_zero_bit);
587 pNALU->put_bits(6, pHeader->nal_unit_type);
588 pNALU->put_bits(6, pHeader->nuh_layer_id);
589 pNALU->put_bits(3, pHeader->nuh_temporal_id_plus1);
590 pNALU->flush();
591
592 // NAL body
593 pRBSP->flush();
594
595 if (pRBSP->get_start_code_prevention_status()) {
596 // Direct copying.
597 pNALU->append_byte_stream(pRBSP);
598 } else {
599 // Copy with start code prevention.
600 pNALU->set_start_code_prevention(true);
601 int32_t iLength = pRBSP->get_byte_count();
602 uint8_t *pBuffer = pRBSP->get_bitstream_buffer();
603
604 for (int32_t i = 0; i < iLength; i++) {
605 pNALU->put_bits(8, pBuffer[i]);
606 }
607 }
608
609 isAligned = pNALU->is_byte_aligned(); // causes side-effects in object state, don't put inside assert()
610 assert(isAligned);
611 write_nalu_end(pNALU);
612
613 pNALU->flush();
614
615 iBytesWritten = pNALU->get_byte_count() - iBytesWritten;
616 return (uint32_t) iBytesWritten;
617 }
618
619 void
write_nalu_end(d3d12_video_encoder_bitstream * pNALU)620 d3d12_video_nalu_writer_hevc::write_nalu_end(d3d12_video_encoder_bitstream *pNALU)
621 {
622 pNALU->flush();
623 pNALU->set_start_code_prevention(false);
624 int32_t iNALUnitLen = pNALU->get_byte_count();
625
626 if (false == pNALU->m_bBufferOverflow && 0x00 == pNALU->get_bitstream_buffer()[iNALUnitLen - 1]) {
627 pNALU->put_bits(8, 0x03);
628 pNALU->flush();
629 }
630 }
631
632 void
rbsp_trailing(d3d12_video_encoder_bitstream * pBitstream)633 d3d12_video_nalu_writer_hevc::rbsp_trailing(d3d12_video_encoder_bitstream *pBitstream)
634 {
635 pBitstream->put_bits(1, 1);
636 int32_t iLeft = pBitstream->get_num_bits_for_byte_align();
637
638 if (iLeft) {
639 pBitstream->put_bits(iLeft, 0);
640 }
641
642 ASSERTED bool isAligned = pBitstream->is_byte_aligned(); // causes side-effects in object state, don't put inside assert()
643 assert(isAligned);
644 }
645
646 void
write_profile_tier_level(d3d12_video_encoder_bitstream * rbsp,HEVCProfileTierLevel * ptl)647 d3d12_video_nalu_writer_hevc::write_profile_tier_level(d3d12_video_encoder_bitstream* rbsp, HEVCProfileTierLevel* ptl)
648 {
649 rbsp->put_bits(2, ptl->general_profile_space);
650 rbsp->put_bits(1, ptl->general_tier_flag);
651 rbsp->put_bits(5, ptl->general_profile_idc);
652
653 for (int j = 0; j < 32; j++) {
654 rbsp->put_bits(1, ptl->general_profile_compatibility_flag[j]);
655 }
656
657 rbsp->put_bits(1, ptl->general_progressive_source_flag);
658 rbsp->put_bits(1, ptl->general_interlaced_source_flag);
659 rbsp->put_bits(1, ptl->general_non_packed_constraint_flag);
660 rbsp->put_bits(1, ptl->general_frame_only_constraint_flag);
661 if( (ptl->general_profile_idc == 4) || ptl->general_profile_compatibility_flag[4] ||
662 (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[5] ||
663 (ptl->general_profile_idc == 6) || ptl->general_profile_compatibility_flag[6] ||
664 (ptl->general_profile_idc == 7) || ptl->general_profile_compatibility_flag[7] ||
665 (ptl->general_profile_idc == 8) || ptl->general_profile_compatibility_flag[8] ||
666 (ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[9] ||
667 (ptl->general_profile_idc == 10) || ptl->general_profile_compatibility_flag[10] ||
668 (ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[11])
669 {
670 rbsp->put_bits(1, ptl->general_max_12bit_constraint_flag);
671 rbsp->put_bits(1, ptl->general_max_10bit_constraint_flag);
672 rbsp->put_bits(1, ptl->general_max_8bit_constraint_flag);
673 rbsp->put_bits(1, ptl->general_max_422chroma_constraint_flag);
674 rbsp->put_bits(1, ptl->general_max_420chroma_constraint_flag);
675 rbsp->put_bits(1, ptl->general_max_monochrome_constraint_flag);
676 rbsp->put_bits(1, ptl->general_intra_constraint_flag);
677 rbsp->put_bits(1, ptl->general_one_picture_only_constraint_flag);
678 rbsp->put_bits(1, ptl->general_lower_bit_rate_constraint_flag);
679 if( (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[5] ||
680 (ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[9] ||
681 (ptl->general_profile_idc == 10) || ptl->general_profile_compatibility_flag[10] ||
682 (ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[11])
683 {
684 rbsp->put_bits(1, ptl->general_max_14bit_constraint_flag);
685 rbsp->put_bits(33, 0); // general_reserved_zero_33bits u(33)
686 }
687 else
688 {
689 rbsp->put_bits(32, 0); // general_reserved_zero_34bits u(34)
690 rbsp->put_bits(2, 0); // general_reserved_zero_34bits u(34)
691 }
692
693 }
694 else if( (ptl->general_profile_idc == 2) || ptl->general_profile_compatibility_flag[2])
695 {
696 rbsp->put_bits(7, 0); // general_reserved_zero_7bits
697 rbsp->put_bits(1, ptl->general_one_picture_only_constraint_flag);
698 rbsp->put_bits(32, 0); // general_reserved_zero_35bits u(35)
699 rbsp->put_bits(3, 0); // general_reserved_zero_35bits u(35)
700 }
701 else
702 {
703 rbsp->put_bits(32, 0); // general_reserved_zero_43bits u(43)
704 rbsp->put_bits(11, 0); // general_reserved_zero_43bits u(43)
705 }
706
707 if( (ptl->general_profile_idc == 1) || ptl->general_profile_compatibility_flag[ 1 ] ||
708 (ptl->general_profile_idc == 2) || ptl->general_profile_compatibility_flag[ 2 ] ||
709 (ptl->general_profile_idc == 3) || ptl->general_profile_compatibility_flag[ 3 ] ||
710 (ptl->general_profile_idc == 4) || ptl->general_profile_compatibility_flag[ 4 ] ||
711 (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[ 5 ] ||
712 (ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[ 9 ] ||
713 (ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[ 11 ] )
714 {
715 rbsp->put_bits(1, ptl->general_inbld_flag);
716 }
717 else
718 {
719 rbsp->put_bits(1, 0); // general_reserved_zero_bit u(1)
720 }
721
722 rbsp->put_bits(8, ptl->general_level_idc);
723 }
724
725 void
write_rps(d3d12_video_encoder_bitstream * rbsp,HevcSeqParameterSet * pSPS,int stRpsIdx,bool sliceRPS)726 d3d12_video_nalu_writer_hevc::write_rps(d3d12_video_encoder_bitstream* rbsp, HevcSeqParameterSet* pSPS, int stRpsIdx, bool sliceRPS)
727 {
728 HEVCReferencePictureSet* rps = &(pSPS->rpsShortTerm[stRpsIdx]);
729
730 if (stRpsIdx != 0) {
731 rbsp->put_bits(1, rps->inter_ref_pic_set_prediction_flag);
732 }
733
734 if (rps->inter_ref_pic_set_prediction_flag) {
735 if (sliceRPS) {
736 rbsp->exp_Golomb_ue(rps->delta_idx_minus1);
737 }
738 int RefRpsIdx = stRpsIdx - (rps->delta_idx_minus1 + 1);
739 rbsp->put_bits(1, rps->delta_rps_sign);
740 rbsp->exp_Golomb_ue(rps->abs_delta_rps_minus1);
741
742 HEVCReferencePictureSet* rpsRef = &(pSPS->rpsShortTerm[RefRpsIdx]);
743 auto numDeltaPocs = rpsRef->num_negative_pics + rpsRef->num_positive_pics;
744 for (int j = 0; j <= numDeltaPocs; j++) {
745 rbsp->put_bits(1, rps->used_by_curr_pic_flag[j]);
746 if (!rps->used_by_curr_pic_flag[j]) {
747 rbsp->put_bits(1, rps->use_delta_flag[j]);
748 }
749 }
750 } else {
751 rbsp->exp_Golomb_ue(rps->num_negative_pics);
752 rbsp->exp_Golomb_ue(rps->num_positive_pics);
753
754 for (int i = 0; i < rps->num_negative_pics; i++) {
755 rbsp->exp_Golomb_ue(rps->delta_poc_s0_minus1[i]);
756 rbsp->put_bits(1, rps->used_by_curr_pic_s0_flag[i]);
757 }
758
759 for (int i = 0; i < rps->num_positive_pics; i++) {
760 rbsp->exp_Golomb_ue(rps->delta_poc_s1_minus1[i]);
761 rbsp->put_bits(1, rps->used_by_curr_pic_s1_flag[i]);
762 }
763 }
764 }
765