• 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
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     if (pSPS->chroma_format_idc == 3) {
285         pBitstream->put_bits(1, pSPS->separate_colour_plane_flag);
286     }
287 
288     pBitstream->exp_Golomb_ue(pSPS->pic_width_in_luma_samples);
289     pBitstream->exp_Golomb_ue(pSPS->pic_height_in_luma_samples);
290 
291     pBitstream->put_bits(1, pSPS->conformance_window_flag);
292     if (pSPS->conformance_window_flag) {
293         pBitstream->exp_Golomb_ue(pSPS->conf_win_left_offset);
294         pBitstream->exp_Golomb_ue(pSPS->conf_win_right_offset);
295         pBitstream->exp_Golomb_ue(pSPS->conf_win_top_offset);
296         pBitstream->exp_Golomb_ue(pSPS->conf_win_bottom_offset);
297     }
298 
299     pBitstream->exp_Golomb_ue(pSPS->bit_depth_luma_minus8);
300     pBitstream->exp_Golomb_ue(pSPS->bit_depth_chroma_minus8);
301 
302     pBitstream->exp_Golomb_ue(pSPS->log2_max_pic_order_cnt_lsb_minus4);
303 
304     pBitstream->put_bits(1, pSPS->sps_sub_layer_ordering_info_present_flag);
305 
306     for (int i = 0; i <= pSPS->sps_max_sub_layers_minus1; i++) {
307         pBitstream->exp_Golomb_ue(pSPS->sps_max_dec_pic_buffering_minus1[i]);
308         pBitstream->exp_Golomb_ue(pSPS->sps_max_num_reorder_pics[i]);
309         pBitstream->exp_Golomb_ue(pSPS->sps_max_latency_increase_plus1[i]);
310     }
311 
312     pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
313     pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
314     pBitstream->exp_Golomb_ue(pSPS->log2_min_transform_block_size_minus2);
315     pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_transform_block_size);
316 
317     pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_inter);
318     pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_intra);
319 
320     pBitstream->put_bits(1, pSPS->scaling_list_enabled_flag);
321 
322     pBitstream->put_bits(1, pSPS->amp_enabled_flag);
323     pBitstream->put_bits(1, pSPS->sample_adaptive_offset_enabled_flag);
324 
325     pBitstream->put_bits(1, pSPS->pcm_enabled_flag);
326     if (pSPS->pcm_enabled_flag) {
327     pBitstream->put_bits(4, pSPS->bit_depth_luma_minus8 + 7);
328     pBitstream->put_bits(4, pSPS->bit_depth_chroma_minus8 + 7);
329         pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
330         pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
331     pBitstream->put_bits(1, pSPS->pcm_loop_filter_disabled_flag);
332     }
333 
334     pBitstream->exp_Golomb_ue(pSPS->num_short_term_ref_pic_sets);
335     for (int i = 0; i < pSPS->num_short_term_ref_pic_sets; i++) {
336         write_rps(pBitstream, pSPS, i, false);
337     }
338 
339     pBitstream->put_bits(1, pSPS->long_term_ref_pics_present_flag);
340     if (pSPS->long_term_ref_pics_present_flag) {
341         pBitstream->exp_Golomb_ue(pSPS->num_long_term_ref_pics_sps);
342         for (int i = 0; i < pSPS->num_long_term_ref_pics_sps; i++) {
343             pBitstream->put_bits(pSPS->log2_max_pic_order_cnt_lsb_minus4 + 4, pSPS->lt_ref_pic_poc_lsb_sps[i]);
344             pBitstream->put_bits(1, pSPS->used_by_curr_pic_lt_sps_flag[i]);
345         }
346     }
347 
348     pBitstream->put_bits(1, pSPS->sps_temporal_mvp_enabled_flag);
349     pBitstream->put_bits(1, pSPS->strong_intra_smoothing_enabled_flag);
350     pBitstream->put_bits(1, pSPS->vui_parameters_present_flag);
351 
352     pBitstream->put_bits(1, pSPS->vui.aspect_ratio_info_present_flag);
353     if (pSPS->vui.aspect_ratio_info_present_flag) {
354         pBitstream->put_bits(8, pSPS->vui.aspect_ratio_idc);
355         if (pSPS->vui.aspect_ratio_idc == 255) {
356             pBitstream->put_bits(16, pSPS->vui.sar_width);
357             pBitstream->put_bits(16, pSPS->vui.sar_height);
358         }
359     }
360 
361     pBitstream->put_bits(1, pSPS->vui.overscan_info_present_flag);
362     if (pSPS->vui.overscan_info_present_flag) {
363         pBitstream->put_bits(1, pSPS->vui.overscan_appropriate_flag);
364     }
365 
366     pBitstream->put_bits(1, pSPS->vui.video_signal_type_present_flag);
367     if (pSPS->vui.video_signal_type_present_flag) {
368         pBitstream->put_bits(3, pSPS->vui.video_format);
369         pBitstream->put_bits(1, pSPS->vui.video_full_range_flag);
370         pBitstream->put_bits(1, pSPS->vui.colour_description_present_flag);
371         if (pSPS->vui.colour_description_present_flag) {
372             pBitstream->put_bits(8, pSPS->vui.colour_primaries);
373             pBitstream->put_bits(8, pSPS->vui.transfer_characteristics);
374             pBitstream->put_bits(8, pSPS->vui.matrix_coeffs);
375         }
376     }
377 
378     pBitstream->put_bits(1, pSPS->vui.chroma_loc_info_present_flag);
379     if (pSPS->vui.chroma_loc_info_present_flag) {
380         pBitstream->exp_Golomb_ue(pSPS->vui.chroma_sample_loc_type_top_field);
381         pBitstream->exp_Golomb_ue(pSPS->vui.chroma_sample_loc_type_bottom_field);
382     }
383 
384     pBitstream->put_bits(1, pSPS->vui.neutral_chroma_indication_flag);
385     pBitstream->put_bits(1, pSPS->vui.field_seq_flag);
386     pBitstream->put_bits(1, pSPS->vui.frame_field_info_present_flag);
387     pBitstream->put_bits(1, pSPS->vui.default_display_window_flag);
388     if (pSPS->vui.default_display_window_flag) {
389         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_left_offset);
390         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_right_offset);
391         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_top_offset);
392         pBitstream->exp_Golomb_ue(pSPS->vui.def_disp_win_bottom_offset);
393     }
394 
395     pBitstream->put_bits(1, pSPS->vui.timing_info_present_flag);
396     if (pSPS->vui.timing_info_present_flag) {
397         pBitstream->put_bits(16, pSPS->vui.num_units_in_tick >> 16);
398         pBitstream->put_bits(16, pSPS->vui.num_units_in_tick & 0xffff);
399         pBitstream->put_bits(16, pSPS->vui.time_scale >> 16);
400         pBitstream->put_bits(16, pSPS->vui.time_scale & 0xffff);
401         pBitstream->put_bits(1, pSPS->vui.poc_proportional_to_timing_flag);
402         if (pSPS->vui.poc_proportional_to_timing_flag) {
403             pBitstream->exp_Golomb_ue(pSPS->vui.num_ticks_poc_diff_one_minus1);
404         }
405 
406         assert(pSPS->vui.hrd_parameters_present_flag == 0);
407         pBitstream->put_bits(1, 0); // hrd_parameters_present_flag = 0 until implementing HRD params
408     }
409 
410     pBitstream->put_bits(1, pSPS->vui.bitstream_restriction_flag);
411     if (pSPS->vui.bitstream_restriction_flag) {
412         pBitstream->put_bits(1, pSPS->vui.tiles_fixed_structure_flag);
413         pBitstream->put_bits(1, pSPS->vui.motion_vectors_over_pic_boundaries_flag);
414         pBitstream->put_bits(1, pSPS->vui.restricted_ref_pic_lists_flag);
415         pBitstream->exp_Golomb_ue(pSPS->vui.min_spatial_segmentation_idc);
416         pBitstream->exp_Golomb_ue(pSPS->vui.max_bytes_per_pic_denom);
417         pBitstream->exp_Golomb_ue(pSPS->vui.max_bits_per_min_cu_denom);
418         pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_horizontal);
419         pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_vertical);
420     }
421 
422     // Set sps_extension_present_flag if sps_range_extension_flag present
423     pSPS->sps_extension_present_flag = pSPS->sps_range_extension.sps_range_extension_flag ? 1u : 0u;
424 
425     pBitstream->put_bits(1, pSPS->sps_extension_present_flag);
426     if (pSPS->sps_extension_present_flag)
427     {
428         pBitstream->put_bits(1, pSPS->sps_range_extension.sps_range_extension_flag);
429         pBitstream->put_bits(1, 0);// sps_multilayer_extension_flag u(1)
430         pBitstream->put_bits(1, 0);// sps_3d_extension_flag u(1)
431         pBitstream->put_bits(1, 0);// sps_scc_extension_flag u(1)
432         pBitstream->put_bits(4, 0);// sps_extension_4bits u(4)
433     }
434 
435     if (pSPS->sps_range_extension.sps_range_extension_flag)
436     {
437         // sps_range_extension( )
438         pBitstream->put_bits(1, pSPS->sps_range_extension.transform_skip_rotation_enabled_flag);
439         pBitstream->put_bits(1, pSPS->sps_range_extension.transform_skip_context_enabled_flag);
440         pBitstream->put_bits(1, pSPS->sps_range_extension.implicit_rdpcm_enabled_flag);
441         pBitstream->put_bits(1, pSPS->sps_range_extension.explicit_rdpcm_enabled_flag);
442         pBitstream->put_bits(1, pSPS->sps_range_extension.extended_precision_processing_flag);
443         pBitstream->put_bits(1, pSPS->sps_range_extension.intra_smoothing_disabled_flag);
444         pBitstream->put_bits(1, pSPS->sps_range_extension.high_precision_offsets_enabled_flag);
445         pBitstream->put_bits(1, pSPS->sps_range_extension.persistent_rice_adaptation_enabled_flag);
446         pBitstream->put_bits(1, pSPS->sps_range_extension.cabac_bypass_alignment_enabled_flag);
447     }
448 
449     rbsp_trailing(pBitstream);
450     pBitstream->flush();
451 
452     iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
453     return (uint32_t) iBytesWritten;
454 }
455 
456 uint32_t
write_pps_bytes(d3d12_video_encoder_bitstream * pBitstream,HevcPicParameterSet * pPPS)457 d3d12_video_nalu_writer_hevc::write_pps_bytes(d3d12_video_encoder_bitstream *pBitstream,
458                                             HevcPicParameterSet *pPPS)
459 {
460     int32_t iBytesWritten = pBitstream->get_byte_count();
461 
462     pBitstream->exp_Golomb_ue(pPPS->pps_pic_parameter_set_id);
463     pBitstream->exp_Golomb_ue(pPPS->pps_seq_parameter_set_id);
464 
465     pBitstream->put_bits(1, pPPS->dependent_slice_segments_enabled_flag);
466 
467     pBitstream->put_bits(1, pPPS->output_flag_present_flag);
468     pBitstream->put_bits(3, pPPS->num_extra_slice_header_bits);
469 
470     pBitstream->put_bits(1, pPPS->sign_data_hiding_enabled_flag);
471     pBitstream->put_bits(1, pPPS->cabac_init_present_flag);
472 
473     pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[0]);
474     pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[1]);
475 
476     pBitstream->exp_Golomb_se(pPPS->init_qp_minus26);
477 
478     pBitstream->put_bits(1, pPPS->constrained_intra_pred_flag);
479     pBitstream->put_bits(1, pPPS->transform_skip_enabled_flag);
480     pBitstream->put_bits(1, pPPS->cu_qp_delta_enabled_flag);
481 
482     if (pPPS->cu_qp_delta_enabled_flag) {
483         pBitstream->exp_Golomb_se(pPPS->diff_cu_qp_delta_depth);
484     }
485 
486     pBitstream->exp_Golomb_se(pPPS->pps_cb_qp_offset);
487     pBitstream->exp_Golomb_se(pPPS->pps_cr_qp_offset);
488 
489     pBitstream->put_bits(1, pPPS->pps_slice_chroma_qp_offsets_present_flag);
490 
491     pBitstream->put_bits(1, pPPS->weighted_pred_flag);
492     pBitstream->put_bits(1, pPPS->weighted_bipred_flag);
493     pBitstream->put_bits(1, pPPS->transquant_bypass_enabled_flag);
494 
495     pBitstream->put_bits(1, pPPS->tiles_enabled_flag);
496     pBitstream->put_bits(1, pPPS->entropy_coding_sync_enabled_flag);
497 
498     if (pPPS->tiles_enabled_flag) {
499         pBitstream->exp_Golomb_ue(pPPS->num_tile_columns_minus1);
500         pBitstream->exp_Golomb_ue(pPPS->num_tile_rows_minus1);
501         pBitstream->put_bits(1, pPPS->uniform_spacing_flag);
502         if (!pPPS->uniform_spacing_flag) {
503             for (int i = 0; i < pPPS->num_tile_columns_minus1; i++) {
504                 pBitstream->exp_Golomb_ue(pPPS->column_width_minus1[i]);
505             }
506             for (int i = 0; i < pPPS->num_tile_rows_minus1; i++) {
507                 pBitstream->exp_Golomb_ue(pPPS->row_height_minus1[i]);
508             }
509         }
510         pBitstream->put_bits(1, pPPS->loop_filter_across_tiles_enabled_flag);
511     }
512 
513     pBitstream->put_bits(1, pPPS->pps_loop_filter_across_slices_enabled_flag);
514     pBitstream->put_bits(1, pPPS->deblocking_filter_control_present_flag);
515     if (pPPS->deblocking_filter_control_present_flag) {
516         pBitstream->put_bits(1, pPPS->deblocking_filter_override_enabled_flag);
517         pBitstream->put_bits(1, pPPS->pps_deblocking_filter_disabled_flag);
518         if (!pPPS->pps_deblocking_filter_disabled_flag) {
519             pBitstream->exp_Golomb_se(pPPS->pps_beta_offset_div2);
520             pBitstream->exp_Golomb_se(pPPS->pps_tc_offset_div2);
521         }
522     }
523 
524     pBitstream->put_bits(1, pPPS->pps_scaling_list_data_present_flag);
525     if (pPPS->pps_scaling_list_data_present_flag) {
526         assert(0); //, "scaling list syntax is not implemented yet");
527     }
528 
529     pBitstream->put_bits(1, pPPS->lists_modification_present_flag);
530     pBitstream->exp_Golomb_ue(pPPS->log2_parallel_merge_level_minus2);
531     pBitstream->put_bits(1, pPPS->slice_segment_header_extension_present_flag);
532 
533     // Set pps_extension_present_flag if sps_range_extension_flag present
534     pPPS->pps_extension_present_flag = pPPS->pps_range_extension.pps_range_extension_flag ? 1u : 0u;
535 
536     pBitstream->put_bits(1, pPPS->pps_extension_present_flag);
537     if (pPPS->pps_extension_present_flag)
538     {
539         pBitstream->put_bits(1, pPPS->pps_range_extension.pps_range_extension_flag);
540         pBitstream->put_bits(1, 0);// pps_multilayer_extension_flag u(1)
541         pBitstream->put_bits(1, 0);// pps_3d_extension_flag u(1)
542         pBitstream->put_bits(1, 0);// pps_scc_extension_flag u(1)
543         pBitstream->put_bits(4, 0);// pps_extension_4bits u(4)
544     }
545 
546     if (pPPS->pps_range_extension.pps_range_extension_flag)
547     {
548         // pps_range_extension( )
549         if( pPPS->transform_skip_enabled_flag )
550             pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_max_transform_skip_block_size_minus2);
551         pBitstream->put_bits(1, pPPS->pps_range_extension.cross_component_prediction_enabled_flag);
552         pBitstream->put_bits(1, pPPS->pps_range_extension.chroma_qp_offset_list_enabled_flag);
553         if(pPPS->pps_range_extension.chroma_qp_offset_list_enabled_flag) {
554             pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.diff_cu_chroma_qp_offset_depth);
555             pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.chroma_qp_offset_list_len_minus1);
556             for( unsigned i = 0; i <= pPPS->pps_range_extension.chroma_qp_offset_list_len_minus1; i++ ) {
557                 pBitstream->exp_Golomb_se(pPPS->pps_range_extension.cb_qp_offset_list[i]);
558                 pBitstream->exp_Golomb_se(pPPS->pps_range_extension.cr_qp_offset_list[i]);
559             }
560         }
561         pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_sao_offset_scale_luma);
562         pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_sao_offset_scale_chroma);
563     }
564 
565     rbsp_trailing(pBitstream);
566     pBitstream->flush();
567 
568     iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
569     return (uint32_t) iBytesWritten;
570 }
571 
572 uint32_t
wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream * pNALU,d3d12_video_encoder_bitstream * pRBSP,HEVCNaluHeader * pHeader)573 d3d12_video_nalu_writer_hevc::wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream *pNALU,
574                     d3d12_video_encoder_bitstream *pRBSP,
575                     HEVCNaluHeader *pHeader)
576 {
577     ASSERTED bool isAligned = pRBSP->is_byte_aligned();   // causes side-effects in object state, don't put inside assert()
578     assert(isAligned);
579 
580     int32_t iBytesWritten = pNALU->get_byte_count();
581 
582     pNALU->set_start_code_prevention(false);
583 
584     // NAL start code
585     pNALU->put_bits(24, 0);
586     pNALU->put_bits(8, 1);
587 
588     // NAL header
589     pNALU->put_bits(1, pHeader->forbidden_zero_bit);
590     pNALU->put_bits(6, pHeader->nal_unit_type);
591     pNALU->put_bits(6, pHeader->nuh_layer_id);
592     pNALU->put_bits(3, pHeader->nuh_temporal_id_plus1);
593     pNALU->flush();
594 
595     // NAL body
596     pRBSP->flush();
597 
598     if (pRBSP->get_start_code_prevention_status()) {
599         // Direct copying.
600         pNALU->append_byte_stream(pRBSP);
601     } else {
602         // Copy with start code prevention.
603         pNALU->set_start_code_prevention(true);
604         int32_t  iLength = pRBSP->get_byte_count();
605         uint8_t *pBuffer = pRBSP->get_bitstream_buffer();
606 
607         for (int32_t i = 0; i < iLength; i++) {
608             pNALU->put_bits(8, pBuffer[i]);
609         }
610     }
611 
612     isAligned = pNALU->is_byte_aligned();   // causes side-effects in object state, don't put inside assert()
613     assert(isAligned);
614     write_nalu_end(pNALU);
615 
616     pNALU->flush();
617 
618     iBytesWritten = pNALU->get_byte_count() - iBytesWritten;
619     return (uint32_t) iBytesWritten;
620 }
621 
622 void
write_nalu_end(d3d12_video_encoder_bitstream * pNALU)623 d3d12_video_nalu_writer_hevc::write_nalu_end(d3d12_video_encoder_bitstream *pNALU)
624 {
625     pNALU->flush();
626     pNALU->set_start_code_prevention(false);
627     int32_t iNALUnitLen = pNALU->get_byte_count();
628 
629     if (false == pNALU->m_bBufferOverflow && 0x00 == pNALU->get_bitstream_buffer()[iNALUnitLen - 1]) {
630         pNALU->put_bits(8, 0x03);
631         pNALU->flush();
632     }
633 }
634 
635 void
rbsp_trailing(d3d12_video_encoder_bitstream * pBitstream)636 d3d12_video_nalu_writer_hevc::rbsp_trailing(d3d12_video_encoder_bitstream *pBitstream)
637 {
638     pBitstream->put_bits(1, 1);
639     int32_t iLeft = pBitstream->get_num_bits_for_byte_align();
640 
641     if (iLeft) {
642         pBitstream->put_bits(iLeft, 0);
643     }
644 
645     ASSERTED bool isAligned = pBitstream->is_byte_aligned();   // causes side-effects in object state, don't put inside assert()
646     assert(isAligned);
647 }
648 
649 void
write_profile_tier_level(d3d12_video_encoder_bitstream * rbsp,HEVCProfileTierLevel * ptl)650 d3d12_video_nalu_writer_hevc::write_profile_tier_level(d3d12_video_encoder_bitstream* rbsp, HEVCProfileTierLevel* ptl)
651 {
652     rbsp->put_bits(2, ptl->general_profile_space);
653     rbsp->put_bits(1, ptl->general_tier_flag);
654     rbsp->put_bits(5, ptl->general_profile_idc);
655 
656     for (int j = 0; j < 32; j++) {
657         rbsp->put_bits(1, ptl->general_profile_compatibility_flag[j]);
658     }
659 
660     rbsp->put_bits(1, ptl->general_progressive_source_flag);
661     rbsp->put_bits(1, ptl->general_interlaced_source_flag);
662     rbsp->put_bits(1, ptl->general_non_packed_constraint_flag);
663     rbsp->put_bits(1, ptl->general_frame_only_constraint_flag);
664     if( (ptl->general_profile_idc == 4) || ptl->general_profile_compatibility_flag[4]  ||
665         (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[5]  ||
666         (ptl->general_profile_idc == 6) || ptl->general_profile_compatibility_flag[6]  ||
667         (ptl->general_profile_idc == 7) || ptl->general_profile_compatibility_flag[7]  ||
668         (ptl->general_profile_idc == 8) || ptl->general_profile_compatibility_flag[8]  ||
669         (ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[9]  ||
670         (ptl->general_profile_idc == 10) || ptl->general_profile_compatibility_flag[10] ||
671         (ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[11])
672     {
673         rbsp->put_bits(1, ptl->general_max_12bit_constraint_flag);
674         rbsp->put_bits(1, ptl->general_max_10bit_constraint_flag);
675         rbsp->put_bits(1, ptl->general_max_8bit_constraint_flag);
676         rbsp->put_bits(1, ptl->general_max_422chroma_constraint_flag);
677         rbsp->put_bits(1, ptl->general_max_420chroma_constraint_flag);
678         rbsp->put_bits(1, ptl->general_max_monochrome_constraint_flag);
679         rbsp->put_bits(1, ptl->general_intra_constraint_flag);
680         rbsp->put_bits(1, ptl->general_one_picture_only_constraint_flag);
681         rbsp->put_bits(1, ptl->general_lower_bit_rate_constraint_flag);
682         if( (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[5] ||
683             (ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[9] ||
684             (ptl->general_profile_idc == 10) || ptl->general_profile_compatibility_flag[10] ||
685             (ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[11])
686             {
687                 rbsp->put_bits(1, ptl->general_max_14bit_constraint_flag);
688                 rbsp->put_bits(33, 0); // general_reserved_zero_33bits u(33)
689             }
690             else
691             {
692                 rbsp->put_bits(32, 0); // general_reserved_zero_34bits u(34)
693                 rbsp->put_bits(2, 0); // general_reserved_zero_34bits u(34)
694             }
695 
696     }
697     else if( (ptl->general_profile_idc == 2) || ptl->general_profile_compatibility_flag[2])
698     {
699         rbsp->put_bits(7, 0); // general_reserved_zero_7bits
700         rbsp->put_bits(1, ptl->general_one_picture_only_constraint_flag);
701         rbsp->put_bits(32, 0); // general_reserved_zero_35bits u(35)
702         rbsp->put_bits(3, 0); // general_reserved_zero_35bits u(35)
703     }
704     else
705     {
706         rbsp->put_bits(32, 0); // general_reserved_zero_43bits u(43)
707         rbsp->put_bits(11, 0); // general_reserved_zero_43bits u(43)
708     }
709 
710     if( (ptl->general_profile_idc == 1) || ptl->general_profile_compatibility_flag[ 1 ] ||
711         (ptl->general_profile_idc == 2) || ptl->general_profile_compatibility_flag[ 2 ] ||
712         (ptl->general_profile_idc == 3) || ptl->general_profile_compatibility_flag[ 3 ] ||
713         (ptl->general_profile_idc == 4) || ptl->general_profile_compatibility_flag[ 4 ] ||
714         (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[ 5 ] ||
715         (ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[ 9 ] ||
716         (ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[ 11 ] )
717     {
718         rbsp->put_bits(1, ptl->general_inbld_flag);
719     }
720     else
721     {
722         rbsp->put_bits(1, 0); // general_reserved_zero_bit u(1)
723     }
724 
725     rbsp->put_bits(8, ptl->general_level_idc);
726 }
727 
728 void
write_rps(d3d12_video_encoder_bitstream * rbsp,HevcSeqParameterSet * pSPS,int stRpsIdx,bool sliceRPS)729 d3d12_video_nalu_writer_hevc::write_rps(d3d12_video_encoder_bitstream* rbsp, HevcSeqParameterSet* pSPS, int stRpsIdx, bool sliceRPS)
730 {
731     HEVCReferencePictureSet* rps = &(pSPS->rpsShortTerm[stRpsIdx]);
732 
733     if (stRpsIdx != 0) {
734         rbsp->put_bits(1, rps->inter_ref_pic_set_prediction_flag);
735     }
736 
737     if (rps->inter_ref_pic_set_prediction_flag) {
738         if (sliceRPS) {
739             rbsp->exp_Golomb_ue(rps->delta_idx_minus1);
740         }
741         int RefRpsIdx = stRpsIdx - (rps->delta_idx_minus1 + 1);
742         rbsp->put_bits(1, rps->delta_rps_sign);
743         rbsp->exp_Golomb_ue(rps->abs_delta_rps_minus1);
744 
745         HEVCReferencePictureSet* rpsRef = &(pSPS->rpsShortTerm[RefRpsIdx]);
746         auto numDeltaPocs = rpsRef->num_negative_pics + rpsRef->num_positive_pics;
747         for (int j = 0; j <= numDeltaPocs; j++) {
748             rbsp->put_bits(1, rps->used_by_curr_pic_flag[j]);
749             if (!rps->used_by_curr_pic_flag[j]) {
750                 rbsp->put_bits(1, rps->use_delta_flag[j]);
751             }
752         }
753     } else {
754         rbsp->exp_Golomb_ue(rps->num_negative_pics);
755         rbsp->exp_Golomb_ue(rps->num_positive_pics);
756 
757         for (int i = 0; i < rps->num_negative_pics; i++) {
758             rbsp->exp_Golomb_ue(rps->delta_poc_s0_minus1[i]);
759             rbsp->put_bits(1, rps->used_by_curr_pic_s0_flag[i]);
760         }
761 
762         for (int i = 0; i < rps->num_positive_pics; i++) {
763             rbsp->exp_Golomb_ue(rps->delta_poc_s1_minus1[i]);
764             rbsp->put_bits(1, rps->used_by_curr_pic_s1_flag[i]);
765         }
766     }
767 }
768