• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
generic_write_bytes(std::vector<BYTE> & headerBitstream,std::vector<BYTE>::iterator placingPositionStart,size_t & writtenBytes,void * pStructure)94 d3d12_video_nalu_writer_hevc::generic_write_bytes( std::vector<BYTE> &headerBitstream,
95                                                 std::vector<BYTE>::iterator placingPositionStart,
96                                                 size_t &writtenBytes,
97                                                 void *pStructure)
98 {
99     // Wrap pSPS into NALU and copy full NALU into output byte array
100     d3d12_video_encoder_bitstream rbsp, nalu;
101 
102     /*HEVCNaluHeader nalu is in all Hevc*ParameterSet structures at the beggining*/
103     HEVCNaluHeader* nal_header = ((HEVCNaluHeader *) pStructure);
104 
105     if (!rbsp.create_bitstream(MAX_COMPRESSED_NALU)) {
106         debug_printf("rbsp.create_bitstream(MAX_COMPRESSED_NALU) failed\n");
107         assert(false);
108     }
109 
110     if (!nalu.create_bitstream(2 * MAX_COMPRESSED_NALU)) {
111         debug_printf("nalu.create_bitstream(2 * MAX_COMPRESSED_NALU) failed\n");
112         assert(false);
113     }
114 
115     rbsp.set_start_code_prevention(true);
116     if (write_bytes_from_struct(&rbsp, pStructure, nal_header->nal_unit_type) <= 0u) {
117         debug_printf("write_bytes_from_struct(&rbsp, pStructure, nal_header->nal_unit_type) didn't write any bytes.\n");
118         assert(false);
119     }
120 
121     if (wrap_rbsp_into_nalu(&nalu, &rbsp, nal_header) <= 0u) {
122         debug_printf("wrap_rbsp_into_nalu(&nalu, &rbsp, nal_header) didn't write any bytes.\n");
123         assert(false);
124     }
125 
126     // Deep copy nalu into headerBitstream, nalu gets out of scope here and its destructor frees the nalu object buffer
127     // memory.
128     uint8_t *naluBytes    = nalu.get_bitstream_buffer();
129     size_t   naluByteSize = nalu.get_byte_count();
130 
131     auto startDstIndex = std::distance(headerBitstream.begin(), placingPositionStart);
132     if (headerBitstream.size() < (startDstIndex + naluByteSize)) {
133         headerBitstream.resize(startDstIndex + naluByteSize);
134     }
135 
136     std::copy_n(&naluBytes[0], naluByteSize, &headerBitstream.data()[startDstIndex]);
137 
138     writtenBytes = naluByteSize;
139 }
140 
141 uint32_t
write_bytes_from_struct(d3d12_video_encoder_bitstream * pBitstream,void * pData,uint8_t nal_unit_type)142 d3d12_video_nalu_writer_hevc::write_bytes_from_struct(d3d12_video_encoder_bitstream *pBitstream, void *pData, uint8_t nal_unit_type)
143 {
144     switch(nal_unit_type)
145     {
146         case HEVC_NALU_VPS_NUT:
147         {
148             return write_vps_bytes(pBitstream, (HevcVideoParameterSet *) pData);
149         } break;
150         case HEVC_NALU_SPS_NUT:
151         {
152             return write_sps_bytes(pBitstream, (HevcSeqParameterSet *) pData);
153         } break;
154         case HEVC_NALU_PPS_NUT:
155         {
156             return write_pps_bytes(pBitstream, (HevcPicParameterSet *) pData);
157         } break;
158         case HEVC_NALU_EOS_NUT:
159         case HEVC_NALU_EOB_NUT:
160         {
161             // Do nothing for these two, just the header suffices
162             return 1;
163         } break;
164         default:
165         {
166             unreachable("Unsupported NALU value");
167         } break;
168     }
169 }
170 
171 uint32_t
write_vps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcVideoParameterSet * vps)172 d3d12_video_nalu_writer_hevc::write_vps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcVideoParameterSet *vps)
173 {
174     int32_t iBytesWritten = pBitstream->get_byte_count();
175 
176     pBitstream->put_bits(4, vps->vps_video_parameter_set_id);
177     pBitstream->put_bits(2, 3); //vps_reserved_three_2bits
178     pBitstream->put_bits(6, vps->vps_max_layers_minus1);
179     pBitstream->put_bits(3, vps->vps_max_sub_layers_minus1);
180     pBitstream->put_bits(1, vps->vps_temporal_id_nesting_flag);
181     pBitstream->put_bits(16, 0xffff); //vps_reserved_ffff_16bits
182 
183     write_profile_tier_level(pBitstream, &vps->ptl);
184 
185     pBitstream->put_bits(1,vps->vps_sub_layer_ordering_info_present_flag);
186 
187     for (int i = 0; i <= vps->vps_max_sub_layers_minus1; i++) {
188         pBitstream->exp_Golomb_ue(vps->vps_max_dec_pic_buffering_minus1[i]);
189         pBitstream->exp_Golomb_ue(vps->vps_max_num_reorder_pics[i]);
190         pBitstream->exp_Golomb_ue(vps->vps_max_latency_increase_plus1[i]);
191     }
192 
193     pBitstream->put_bits(6, vps->vps_max_layer_id);
194     pBitstream->exp_Golomb_ue(vps->vps_num_layer_sets_minus1);
195     pBitstream->put_bits(1, vps->vps_timing_info_present_flag);
196 
197     pBitstream->put_bits(1, 0); // vps_extension_flag
198 
199     rbsp_trailing(pBitstream);
200     pBitstream->flush();
201 
202     iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
203     return (uint32_t) iBytesWritten;
204 }
205 
206 uint32_t
write_sps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcSeqParameterSet * pSPS)207 d3d12_video_nalu_writer_hevc::write_sps_bytes(d3d12_video_encoder_bitstream *pBitstream,
208                                             HevcSeqParameterSet *pSPS)
209 {
210     int32_t iBytesWritten = pBitstream->get_byte_count();
211 
212     pBitstream->put_bits(4, pSPS->sps_video_parameter_set_id);
213     pBitstream->put_bits(3, pSPS->sps_max_sub_layers_minus1);
214     pBitstream->put_bits(1, pSPS->sps_temporal_id_nesting_flag);
215 
216     write_profile_tier_level(pBitstream, &pSPS->ptl);
217 
218     pBitstream->exp_Golomb_ue(pSPS->sps_seq_parameter_set_id);
219 
220     pBitstream->exp_Golomb_ue(pSPS->chroma_format_idc);
221 
222     pBitstream->exp_Golomb_ue(pSPS->pic_width_in_luma_samples);
223     pBitstream->exp_Golomb_ue(pSPS->pic_height_in_luma_samples);
224 
225     pBitstream->put_bits(1, pSPS->conformance_window_flag);
226     if (pSPS->conformance_window_flag) {
227         pBitstream->exp_Golomb_ue(pSPS->conf_win_left_offset);
228         pBitstream->exp_Golomb_ue(pSPS->conf_win_right_offset);
229         pBitstream->exp_Golomb_ue(pSPS->conf_win_top_offset);
230         pBitstream->exp_Golomb_ue(pSPS->conf_win_bottom_offset);
231     }
232 
233     pBitstream->exp_Golomb_ue(pSPS->bit_depth_luma_minus8);
234     pBitstream->exp_Golomb_ue(pSPS->bit_depth_chroma_minus8);
235 
236     pBitstream->exp_Golomb_ue(pSPS->log2_max_pic_order_cnt_lsb_minus4);
237 
238     pBitstream->put_bits(1, pSPS->sps_sub_layer_ordering_info_present_flag);
239 
240     for (int i = 0; i <= pSPS->sps_max_sub_layers_minus1; i++) {
241         pBitstream->exp_Golomb_ue(pSPS->sps_max_dec_pic_buffering_minus1[i]);
242         pBitstream->exp_Golomb_ue(pSPS->sps_max_num_reorder_pics[i]);
243         pBitstream->exp_Golomb_ue(pSPS->sps_max_latency_increase_plus1[i]);
244     }
245 
246     pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
247     pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
248     pBitstream->exp_Golomb_ue(pSPS->log2_min_transform_block_size_minus2);
249     pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_transform_block_size);
250 
251     pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_inter);
252     pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_intra);
253 
254     pBitstream->put_bits(1, pSPS->scaling_list_enabled_flag);
255 
256     pBitstream->put_bits(1, pSPS->amp_enabled_flag);
257     pBitstream->put_bits(1, pSPS->sample_adaptive_offset_enabled_flag);
258 
259     pBitstream->put_bits(1, pSPS->pcm_enabled_flag);
260     if (pSPS->pcm_enabled_flag) {
261     pBitstream->put_bits(4, pSPS->bit_depth_luma_minus8 + 7);
262     pBitstream->put_bits(4, pSPS->bit_depth_chroma_minus8 + 7);
263         pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
264         pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
265     pBitstream->put_bits(1, pSPS->pcm_loop_filter_disabled_flag);
266     }
267 
268     pBitstream->exp_Golomb_ue(pSPS->num_short_term_ref_pic_sets);
269     for (int i = 0; i < pSPS->num_short_term_ref_pic_sets; i++) {
270         write_rps(pBitstream, pSPS, i, false);
271     }
272 
273     pBitstream->put_bits(1, pSPS->long_term_ref_pics_present_flag);
274     if (pSPS->long_term_ref_pics_present_flag) {
275         pBitstream->exp_Golomb_ue(pSPS->num_long_term_ref_pics_sps);
276         for (int i = 0; i < pSPS->num_long_term_ref_pics_sps; i++) {
277             pBitstream->put_bits(pSPS->log2_max_pic_order_cnt_lsb_minus4 + 4, pSPS->lt_ref_pic_poc_lsb_sps[i]);
278             pBitstream->put_bits(1, pSPS->used_by_curr_pic_lt_sps_flag[i]);
279         }
280     }
281 
282     pBitstream->put_bits(1, pSPS->sps_temporal_mvp_enabled_flag);
283     pBitstream->put_bits(1, pSPS->strong_intra_smoothing_enabled_flag);
284     pBitstream->put_bits(1, pSPS->vui_parameters_present_flag);
285 
286     pBitstream->put_bits(1, pSPS->vui.aspect_ratio_info_present_flag);
287     if (pSPS->vui.aspect_ratio_info_present_flag) {
288         pBitstream->put_bits(8, pSPS->vui.aspect_ratio_idc);
289         if (pSPS->vui.aspect_ratio_idc == 255) {
290             pBitstream->put_bits(16, pSPS->vui.sar_width);
291             pBitstream->put_bits(16, pSPS->vui.sar_height);
292         }
293     }
294 
295     pBitstream->put_bits(1, pSPS->vui.overscan_info_present_flag);
296     if (pSPS->vui.overscan_info_present_flag) {
297         pBitstream->put_bits(1, pSPS->vui.overscan_appropriate_flag);
298     }
299 
300     pBitstream->put_bits(1, pSPS->vui.video_signal_type_present_flag);
301     if (pSPS->vui.video_signal_type_present_flag) {
302         pBitstream->put_bits(3, pSPS->vui.video_format);
303         pBitstream->put_bits(1, pSPS->vui.video_full_range_flag);
304         pBitstream->put_bits(1, pSPS->vui.colour_description_present_flag);
305         if (pSPS->vui.colour_description_present_flag) {
306             pBitstream->put_bits(8, pSPS->vui.colour_primaries);
307             pBitstream->put_bits(8, pSPS->vui.transfer_characteristics);
308             pBitstream->put_bits(8, pSPS->vui.matrix_coeffs);
309         }
310     }
311 
312     pBitstream->put_bits(1, pSPS->vui.chroma_loc_info_present_flag);
313     if (pSPS->vui.chroma_loc_info_present_flag) {
314         pBitstream->exp_Golomb_ue(pSPS->vui.chroma_sample_loc_type_top_field);
315         pBitstream->exp_Golomb_ue(pSPS->vui.chroma_sample_loc_type_bottom_field);
316     }
317 
318     pBitstream->put_bits(1, pSPS->vui.neutral_chroma_indication_flag);
319     pBitstream->put_bits(1, pSPS->vui.field_seq_flag);
320     pBitstream->put_bits(1, pSPS->vui.frame_field_info_present_flag);
321     pBitstream->put_bits(1, pSPS->vui.default_display_window_flag);
322     if (pSPS->vui.default_display_window_flag) {
323         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_left_offset);
324         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_right_offset);
325         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_top_offset);
326         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_bottom_offset);
327     }
328 
329     pBitstream->put_bits(1, pSPS->vui.timing_info_present_flag);
330     if (pSPS->vui.timing_info_present_flag) {
331         pBitstream->put_bits(16, pSPS->vui.num_units_in_tick >> 16);
332         pBitstream->put_bits(16, pSPS->vui.num_units_in_tick & 0xffff);
333         pBitstream->put_bits(16, pSPS->vui.time_scale >> 16);
334         pBitstream->put_bits(16, pSPS->vui.time_scale & 0xffff);
335         pBitstream->put_bits(1, pSPS->vui.poc_proportional_to_timing_flag);
336         if (pSPS->vui.poc_proportional_to_timing_flag) {
337             pBitstream->exp_Golomb_ue(pSPS->vui.num_ticks_poc_diff_one_minus1);
338         }
339 
340         assert(pSPS->vui.hrd_parameters_present_flag == 0);
341         pBitstream->put_bits(1, 0); // hrd_parameters_present_flag = 0 until implementing HRD params
342     }
343 
344     pBitstream->put_bits(1, pSPS->vui.bitstream_restriction_flag);
345     if (pSPS->vui.bitstream_restriction_flag) {
346         pBitstream->put_bits(1, pSPS->vui.tiles_fixed_structure_flag);
347         pBitstream->put_bits(1, pSPS->vui.motion_vectors_over_pic_boundaries_flag);
348         pBitstream->put_bits(1, pSPS->vui.restricted_ref_pic_lists_flag);
349         pBitstream->exp_Golomb_ue(pSPS->vui.min_spatial_segmentation_idc);
350         pBitstream->exp_Golomb_ue(pSPS->vui.max_bytes_per_pic_denom);
351         pBitstream->exp_Golomb_ue(pSPS->vui.max_bits_per_min_cu_denom);
352         pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_horizontal);
353         pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_vertical);
354     }
355 
356     //  pSps_extension_flag
357     pBitstream->put_bits(1, 0);
358 
359     rbsp_trailing(pBitstream);
360     pBitstream->flush();
361 
362     iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
363     return (uint32_t) iBytesWritten;
364 }
365 
366 uint32_t
write_pps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcPicParameterSet * pPPS)367 d3d12_video_nalu_writer_hevc::write_pps_bytes(d3d12_video_encoder_bitstream *pBitstream,
368                                             HevcPicParameterSet *pPPS)
369 {
370     int32_t iBytesWritten = pBitstream->get_byte_count();
371 
372     pBitstream->exp_Golomb_ue(pPPS->pps_pic_parameter_set_id);
373     pBitstream->exp_Golomb_ue(pPPS->pps_seq_parameter_set_id);
374 
375     pBitstream->put_bits(1, pPPS->dependent_slice_segments_enabled_flag);
376 
377     pBitstream->put_bits(1, pPPS->output_flag_present_flag);
378     pBitstream->put_bits(3, pPPS->num_extra_slice_header_bits);
379 
380     pBitstream->put_bits(1, pPPS->sign_data_hiding_enabled_flag);
381     pBitstream->put_bits(1, pPPS->cabac_init_present_flag);
382 
383     pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[0]);
384     pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[1]);
385 
386     pBitstream->exp_Golomb_se(pPPS->init_qp_minus26);
387 
388     pBitstream->put_bits(1, pPPS->constrained_intra_pred_flag);
389     pBitstream->put_bits(1, pPPS->transform_skip_enabled_flag);
390     pBitstream->put_bits(1, pPPS->cu_qp_delta_enabled_flag);
391 
392     if (pPPS->cu_qp_delta_enabled_flag) {
393         pBitstream->exp_Golomb_se(pPPS->diff_cu_qp_delta_depth);
394     }
395 
396     pBitstream->exp_Golomb_se(pPPS->pps_cb_qp_offset);
397     pBitstream->exp_Golomb_se(pPPS->pps_cr_qp_offset);
398 
399     pBitstream->put_bits(1, pPPS->pps_slice_chroma_qp_offsets_present_flag);
400 
401     pBitstream->put_bits(1, pPPS->weighted_pred_flag);
402     pBitstream->put_bits(1, pPPS->weighted_bipred_flag);
403     pBitstream->put_bits(1, pPPS->transquant_bypass_enabled_flag);
404 
405     pBitstream->put_bits(1, pPPS->tiles_enabled_flag);
406     pBitstream->put_bits(1, pPPS->entropy_coding_sync_enabled_flag);
407 
408     if (pPPS->tiles_enabled_flag) {
409         pBitstream->exp_Golomb_ue(pPPS->num_tile_columns_minus1);
410         pBitstream->exp_Golomb_ue(pPPS->num_tile_rows_minus1);
411         pBitstream->put_bits(1, pPPS->uniform_spacing_flag);
412         if (!pPPS->uniform_spacing_flag) {
413             for (int i = 0; i < pPPS->num_tile_columns_minus1; i++) {
414                 pBitstream->exp_Golomb_ue(pPPS->column_width_minus1[i]);
415             }
416             for (int i = 0; i < pPPS->num_tile_rows_minus1; i++) {
417                 pBitstream->exp_Golomb_ue(pPPS->row_height_minus1[i]);
418             }
419         }
420         pBitstream->put_bits(1, pPPS->loop_filter_across_tiles_enabled_flag);
421     }
422 
423     pBitstream->put_bits(1, pPPS->pps_loop_filter_across_slices_enabled_flag);
424     pBitstream->put_bits(1, pPPS->deblocking_filter_control_present_flag);
425     if (pPPS->deblocking_filter_control_present_flag) {
426         pBitstream->put_bits(1, pPPS->deblocking_filter_override_enabled_flag);
427         pBitstream->put_bits(1, pPPS->pps_deblocking_filter_disabled_flag);
428         if (!pPPS->pps_deblocking_filter_disabled_flag) {
429             pBitstream->exp_Golomb_se(pPPS->pps_beta_offset_div2);
430             pBitstream->exp_Golomb_se(pPPS->pps_tc_offset_div2);
431         }
432     }
433 
434     pBitstream->put_bits(1, pPPS->pps_scaling_list_data_present_flag);
435     if (pPPS->pps_scaling_list_data_present_flag) {
436         assert(0); //, "scaling list syntax is not implemented yet");
437     }
438 
439     pBitstream->put_bits(1, pPPS->lists_modification_present_flag);
440     pBitstream->exp_Golomb_ue(pPPS->log2_parallel_merge_level_minus2);
441     pBitstream->put_bits(1, pPPS->slice_segment_header_extension_present_flag);
442 
443     //pps_extension_flag
444     pBitstream->put_bits(1, 0);
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
wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream * pNALU,d3d12_video_encoder_bitstream * pRBSP,HEVCNaluHeader * pHeader)454 d3d12_video_nalu_writer_hevc::wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream *pNALU,
455                     d3d12_video_encoder_bitstream *pRBSP,
456                     HEVCNaluHeader *pHeader)
457 {
458     ASSERTED bool isAligned = pRBSP->is_byte_aligned();   // causes side-effects in object state, don't put inside assert()
459     assert(isAligned);
460 
461     int32_t iBytesWritten = pNALU->get_byte_count();
462 
463     pNALU->set_start_code_prevention(false);
464 
465     // NAL start code
466     pNALU->put_bits(24, 0);
467     pNALU->put_bits(8, 1);
468 
469     // NAL header
470     pNALU->put_bits(1, pHeader->forbidden_zero_bit);
471     pNALU->put_bits(6, pHeader->nal_unit_type);
472     pNALU->put_bits(6, pHeader->nuh_layer_id);
473     pNALU->put_bits(3, pHeader->nuh_temporal_id_plus1);
474     pNALU->flush();
475 
476     // NAL body
477     pRBSP->flush();
478 
479     if (pRBSP->get_start_code_prevention_status()) {
480         // Direct copying.
481         pNALU->append_byte_stream(pRBSP);
482     } else {
483         // Copy with start code prevention.
484         pNALU->set_start_code_prevention(true);
485         int32_t  iLength = pRBSP->get_byte_count();
486         uint8_t *pBuffer = pRBSP->get_bitstream_buffer();
487 
488         for (int32_t i = 0; i < iLength; i++) {
489             pNALU->put_bits(8, pBuffer[i]);
490         }
491     }
492 
493     isAligned = pNALU->is_byte_aligned();   // causes side-effects in object state, don't put inside assert()
494     assert(isAligned);
495     write_nalu_end(pNALU);
496 
497     pNALU->flush();
498 
499     iBytesWritten = pNALU->get_byte_count() - iBytesWritten;
500     return (uint32_t) iBytesWritten;
501 }
502 
503 void
write_nalu_end(d3d12_video_encoder_bitstream * pNALU)504 d3d12_video_nalu_writer_hevc::write_nalu_end(d3d12_video_encoder_bitstream *pNALU)
505 {
506     pNALU->flush();
507     pNALU->set_start_code_prevention(false);
508     int32_t iNALUnitLen = pNALU->get_byte_count();
509 
510     if (false == pNALU->m_bBufferOverflow && 0x00 == pNALU->get_bitstream_buffer()[iNALUnitLen - 1]) {
511         pNALU->put_bits(8, 0x03);
512         pNALU->flush();
513     }
514 }
515 
516 void
rbsp_trailing(d3d12_video_encoder_bitstream * pBitstream)517 d3d12_video_nalu_writer_hevc::rbsp_trailing(d3d12_video_encoder_bitstream *pBitstream)
518 {
519     pBitstream->put_bits(1, 1);
520     int32_t iLeft = pBitstream->get_num_bits_for_byte_align();
521 
522     if (iLeft) {
523         pBitstream->put_bits(iLeft, 0);
524     }
525 
526     ASSERTED bool isAligned = pBitstream->is_byte_aligned();   // causes side-effects in object state, don't put inside assert()
527     assert(isAligned);
528 }
529 
530 void
write_profile_tier_level(d3d12_video_encoder_bitstream * rbsp,HEVCProfileTierLevel * ptl)531 d3d12_video_nalu_writer_hevc::write_profile_tier_level(d3d12_video_encoder_bitstream* rbsp, HEVCProfileTierLevel* ptl)
532 {
533     rbsp->put_bits(2, ptl->general_profile_space);
534     rbsp->put_bits(1, ptl->general_tier_flag);
535     rbsp->put_bits(5, ptl->general_profile_idc);
536 
537     for (int j = 0; j < 32; j++) {
538         rbsp->put_bits(1, ptl->general_profile_compatibility_flag[j]);
539     }
540 
541     rbsp->put_bits(1, ptl->general_progressive_source_flag);
542     rbsp->put_bits(1, ptl->general_interlaced_source_flag);
543     rbsp->put_bits(1, ptl->general_non_packed_constraint_flag);
544     rbsp->put_bits(1, ptl->general_frame_only_constraint_flag);
545     rbsp->put_bits(31, 0); //first 31 bits of general_reserved_zero_44bits
546     rbsp->put_bits(13, 0); //last 13 bits of general_reserved_zero_44bits
547     rbsp->put_bits(8, ptl->general_level_idc);
548 }
549 
550 void
write_rps(d3d12_video_encoder_bitstream * rbsp,HevcSeqParameterSet * pSPS,int stRpsIdx,bool sliceRPS)551 d3d12_video_nalu_writer_hevc::write_rps(d3d12_video_encoder_bitstream* rbsp, HevcSeqParameterSet* pSPS, int stRpsIdx, bool sliceRPS)
552 {
553     HEVCReferencePictureSet* rps = &(pSPS->rpsShortTerm[stRpsIdx]);
554 
555     if (stRpsIdx != 0) {
556         rbsp->put_bits(1, rps->inter_ref_pic_set_prediction_flag);
557     }
558 
559     if (rps->inter_ref_pic_set_prediction_flag) {
560         if (sliceRPS) {
561             rbsp->exp_Golomb_ue(rps->delta_idx_minus1);
562         }
563         int RefRpsIdx = stRpsIdx - (rps->delta_idx_minus1 + 1);
564         rbsp->put_bits(1, rps->delta_rps_sign);
565         rbsp->exp_Golomb_ue(rps->abs_delta_rps_minus1);
566 
567         HEVCReferencePictureSet* rpsRef = &(pSPS->rpsShortTerm[RefRpsIdx]);
568         auto numDeltaPocs = rpsRef->num_negative_pics + rpsRef->num_positive_pics;
569         for (int j = 0; j <= numDeltaPocs; j++) {
570             rbsp->put_bits(1, rps->used_by_curr_pic_flag[j]);
571             if (!rps->used_by_curr_pic_flag[j]) {
572                 rbsp->put_bits(1, rps->use_delta_flag[j]);
573             }
574         }
575     } else {
576         rbsp->exp_Golomb_ue(rps->num_negative_pics);
577         rbsp->exp_Golomb_ue(rps->num_positive_pics);
578 
579         for (int i = 0; i < rps->num_negative_pics; i++) {
580             rbsp->exp_Golomb_ue(rps->delta_poc_s0_minus1[i]);
581             rbsp->put_bits(1, rps->used_by_curr_pic_s0_flag[i]);
582         }
583 
584         for (int i = 0; i < rps->num_positive_pics; i++) {
585             rbsp->exp_Golomb_ue(rps->delta_poc_s1_minus1[i]);
586             rbsp->put_bits(1, rps->used_by_curr_pic_s1_flag[i]);
587         }
588     }
589 }
590