• 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_references_manager_h264.h"
25 #include <algorithm>
26 #include <string>
27 #include "d3d12_screen.h"
28 #include "d3d12_video_buffer.h"
29 #include "d3d12_resource.h"
30 
31 using namespace std;
32 
33 bool
get_current_frame_picture_control_data(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA & codecAllocation)34 d3d12_video_encoder_references_manager_h264::get_current_frame_picture_control_data(
35    D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &codecAllocation)
36 {
37    assert(codecAllocation.DataSize == sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264));
38    if (codecAllocation.DataSize != sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264))
39       return false;
40 
41    *codecAllocation.pH264PicData = m_curFrameState;
42 
43    return true;
44 }
45 
46 D3D12_VIDEO_ENCODE_REFERENCE_FRAMES
get_current_reference_frames()47 d3d12_video_encoder_references_manager_h264::get_current_reference_frames()
48 {
49    D3D12_VIDEO_ENCODE_REFERENCE_FRAMES retVal = { 0,
50                                                   // ppTexture2Ds
51                                                   nullptr,
52                                                   // pSubresources
53                                                   nullptr };
54 
55    // Return nullptr for fully intra frames (eg IDR)
56    // and return references information for inter frames (eg.P/B) and I frame that doesn't flush DPB
57 
58    if ((m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME) &&
59        (m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_I_FRAME)) {
60       retVal.NumTexture2Ds = static_cast<UINT>(m_CurrentFrameReferencesData.ReferenceTextures.pResources.size());
61       retVal.ppTexture2Ds = m_CurrentFrameReferencesData.ReferenceTextures.pResources.data();
62 
63       // D3D12 Encode expects null subresources for AoT
64       bool isAoT = (std::all_of(m_CurrentFrameReferencesData.ReferenceTextures.pSubresources.begin(),
65                                 m_CurrentFrameReferencesData.ReferenceTextures.pSubresources.end(),
66                                 [](UINT i) { return i == 0; }));
67       retVal.pSubresources = isAoT ? nullptr : m_CurrentFrameReferencesData.ReferenceTextures.pSubresources.data();
68    }
69 
70    return retVal;
71 }
72 
73 static const char *
d3d12_video_encoder_friendly_frame_type_h264(D3D12_VIDEO_ENCODER_FRAME_TYPE_H264 picType)74 d3d12_video_encoder_friendly_frame_type_h264(D3D12_VIDEO_ENCODER_FRAME_TYPE_H264 picType)
75 {
76    switch (picType) {
77       case D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_P_FRAME:
78       {
79          return "H264_P_FRAME";
80       } break;
81       case D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME:
82       {
83          return "H264_B_FRAME";
84       } break;
85       case D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_I_FRAME:
86       {
87          return "H264_I_FRAME";
88       } break;
89       case D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME:
90       {
91          return "H264_IDR_FRAME";
92       } break;
93       default:
94       {
95          unreachable("Unsupported pipe_h2645_enc_picture_type");
96       } break;
97    }
98 }
99 
100 void
print_l0_l1_lists()101 d3d12_video_encoder_references_manager_h264::print_l0_l1_lists()
102 {
103    debug_printf(
104       "[D3D12 Video Encoder Picture Manager H264] L0 (%d entries) and L1 (%d entries) lists for frame with POC "
105       "%d (frame_num: %d) and frame_type %s are:\n",
106       m_curFrameState.List0ReferenceFramesCount,
107       m_curFrameState.List1ReferenceFramesCount,
108       m_curFrameState.PictureOrderCountNumber,
109       m_curFrameState.FrameDecodingOrderNumber,
110       d3d12_video_encoder_friendly_frame_type_h264(m_curFrameState.FrameType));
111 
112    if ((D3D12_DEBUG_VERBOSE & d3d12_debug) &&
113        ((m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_P_FRAME) ||
114         (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME))) {
115       std::string list0ContentsString;
116       for (uint32_t idx = 0; idx < m_curFrameState.List0ReferenceFramesCount; idx++) {
117          uint32_t value = m_curFrameState.pList0ReferenceFrames[idx];
118          list0ContentsString += "{ DPBidx: ";
119          list0ContentsString += std::to_string(value);
120          list0ContentsString += " - POC: ";
121          list0ContentsString += std::to_string(
122             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].PictureOrderCountNumber);
123          list0ContentsString += " - FrameDecodingOrderNumber: ";
124          list0ContentsString += std::to_string(
125             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].FrameDecodingOrderNumber);
126          list0ContentsString += "}\n";
127       }
128 
129       debug_printf("[D3D12 Video Encoder Picture Manager H264] L0 list (%d entries) for frame with POC %d - frame_num "
130                    "(%d) is: \n %s \n",
131                    m_curFrameState.List0ReferenceFramesCount,
132                    m_curFrameState.PictureOrderCountNumber,
133                    m_curFrameState.FrameDecodingOrderNumber,
134                    list0ContentsString.c_str());
135 
136       std::string modificationOrderList0ContentsString;
137       for (uint32_t idx = 0; idx < m_curFrameState.List0RefPicModificationsCount; idx++) {
138          D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION value =
139             m_curFrameState.pList0RefPicModifications[idx];
140          modificationOrderList0ContentsString += "{ modification_of_pic_nums_idc: ";
141          modificationOrderList0ContentsString += std::to_string(value.modification_of_pic_nums_idc);
142          modificationOrderList0ContentsString += " - abs_diff_pic_num_minus1: ";
143          modificationOrderList0ContentsString += std::to_string(value.abs_diff_pic_num_minus1);
144          modificationOrderList0ContentsString += " - long_term_pic_num: ";
145          modificationOrderList0ContentsString += std::to_string(value.long_term_pic_num);
146          modificationOrderList0ContentsString += "}\n";
147       }
148       debug_printf("[D3D12 Video Encoder Picture Manager H264] L0 modification list (%d entries) for frame with POC %d "
149                    "- frame_num "
150                    "(%d) temporal_id (%d) is: \n %s \n",
151                    m_curFrameState.List0RefPicModificationsCount,
152                    m_curFrameState.PictureOrderCountNumber,
153                    m_curFrameState.FrameDecodingOrderNumber,
154                    m_curFrameState.TemporalLayerIndex,
155                    modificationOrderList0ContentsString.c_str());
156 
157       std::string list1ContentsString;
158       for (uint32_t idx = 0; idx < m_curFrameState.List1ReferenceFramesCount; idx++) {
159          uint32_t value = m_curFrameState.pList1ReferenceFrames[idx];
160          list1ContentsString += "{ DPBidx: ";
161          list1ContentsString += std::to_string(value);
162          list1ContentsString += " - POC: ";
163          list1ContentsString += std::to_string(
164             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].PictureOrderCountNumber);
165          list1ContentsString += " - FrameDecodingOrderNumber: ";
166          list1ContentsString += std::to_string(
167             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].FrameDecodingOrderNumber);
168          list1ContentsString += "}\n";
169       }
170 
171       debug_printf("[D3D12 Video Encoder Picture Manager H264] L1 list (%d entries) for frame with POC %d - frame_num "
172                    "(%d) is: \n %s \n",
173                    m_curFrameState.List1ReferenceFramesCount,
174                    m_curFrameState.PictureOrderCountNumber,
175                    m_curFrameState.FrameDecodingOrderNumber,
176                    list1ContentsString.c_str());
177 
178       std::string modificationOrderList1ContentsString;
179       for (uint32_t idx = 0; idx < m_curFrameState.List1RefPicModificationsCount; idx++) {
180          D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION value =
181             m_curFrameState.pList1RefPicModifications[idx];
182          modificationOrderList1ContentsString += "{ modification_of_pic_nums_idc: ";
183          modificationOrderList1ContentsString += std::to_string(value.modification_of_pic_nums_idc);
184          modificationOrderList1ContentsString += " - abs_diff_pic_num_minus1: ";
185          modificationOrderList1ContentsString += std::to_string(value.abs_diff_pic_num_minus1);
186          modificationOrderList1ContentsString += " - long_term_pic_num: ";
187          modificationOrderList1ContentsString += std::to_string(value.long_term_pic_num);
188          modificationOrderList1ContentsString += "}\n";
189       }
190 
191       debug_printf("[D3D12 Video Encoder Picture Manager H264] L1 modification list (%d entries) for frame with POC %d "
192                    "- frame_num "
193                    "(%d) temporal_id (%d) is: \n %s \n",
194                    m_curFrameState.List1RefPicModificationsCount,
195                    m_curFrameState.PictureOrderCountNumber,
196                    m_curFrameState.FrameDecodingOrderNumber,
197                    m_curFrameState.TemporalLayerIndex,
198                    modificationOrderList1ContentsString.c_str());
199    }
200 }
201 
202 void
print_dpb()203 d3d12_video_encoder_references_manager_h264::print_dpb()
204 {
205    if (D3D12_DEBUG_VERBOSE & d3d12_debug) {
206       std::string dpbContents;
207       for (uint32_t dpbResIdx = 0;
208            dpbResIdx < m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size();
209            dpbResIdx++) {
210          auto &dpbDesc = m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[dpbResIdx];
211 
212          dpbContents += "{ DPBidx: ";
213          dpbContents += std::to_string(dpbResIdx);
214 
215          if (dpbDesc.PictureOrderCountNumber == m_curFrameState.PictureOrderCountNumber) {
216             dpbContents += " - CURRENT FRAME RECON PIC ";
217          }
218 
219          dpbContents += " - POC: ";
220          dpbContents += std::to_string(dpbDesc.PictureOrderCountNumber);
221          dpbContents += " - FrameDecodingOrderNumber: ";
222          dpbContents += std::to_string(dpbDesc.FrameDecodingOrderNumber);
223          dpbContents += " - DPBStorageIdx: ";
224          dpbContents += std::to_string(dpbDesc.ReconstructedPictureResourceIndex);
225          dpbContents += " - DPBStorageResourcePtr: ";
226          char strBuf[256];
227          memset(&strBuf, '\0', 256);
228          sprintf(strBuf,
229                  "%p",
230                  m_CurrentFrameReferencesData.ReferenceTextures.pResources[dpbDesc.ReconstructedPictureResourceIndex]);
231          dpbContents += std::string(strBuf);
232          dpbContents += " - DPBStorageSubresource: ";
233          dpbContents += std::to_string(
234             m_CurrentFrameReferencesData.ReferenceTextures.pSubresources[dpbDesc.ReconstructedPictureResourceIndex]);
235          dpbContents += "}\n";
236       }
237 
238       debug_printf("[D3D12 Video Encoder Picture Manager H264] DPB has %d frames - DPB references for frame with POC "
239                    "%d (frame_num: %d) are: \n %s \n",
240                    static_cast<UINT>(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size()),
241                    m_curFrameState.PictureOrderCountNumber,
242                    m_curFrameState.FrameDecodingOrderNumber,
243                    dpbContents.c_str());
244    }
245 }
246 
247 static D3D12_VIDEO_ENCODER_FRAME_TYPE_H264
d3d12_video_encoder_convert_frame_type_h264(enum pipe_h2645_enc_picture_type picType)248 d3d12_video_encoder_convert_frame_type_h264(enum pipe_h2645_enc_picture_type picType)
249 {
250    switch (picType) {
251       case PIPE_H2645_ENC_PICTURE_TYPE_P:
252       {
253          return D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_P_FRAME;
254       } break;
255       case PIPE_H2645_ENC_PICTURE_TYPE_B:
256       {
257          return D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME;
258       } break;
259       case PIPE_H2645_ENC_PICTURE_TYPE_I:
260       {
261          return D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_I_FRAME;
262       } break;
263       case PIPE_H2645_ENC_PICTURE_TYPE_IDR:
264       {
265          return D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME;
266       } break;
267       default:
268       {
269          unreachable("Unsupported pipe_h2645_enc_picture_type");
270       } break;
271    }
272 }
273 
274 void
begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,bool bUsedAsReference,struct pipe_picture_desc * picture)275 d3d12_video_encoder_references_manager_h264::begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,
276                                                          bool bUsedAsReference,
277                                                          struct pipe_picture_desc *picture)
278 {
279    m_curFrameState = *curFrameData.pH264PicData;
280    m_isCurrentFrameUsedAsReference = bUsedAsReference;
281 
282    struct pipe_h264_enc_picture_desc *h264Pic = (struct pipe_h264_enc_picture_desc *) picture;
283 
284    ///
285    /// Copy DPB snapshot from pipe params
286    ///
287 
288    m_curFrameState.ReferenceFramesReconPictureDescriptorsCount =
289       static_cast<uint32_t>(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size());
290    m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.resize(h264Pic->dpb_size);
291    m_CurrentFrameReferencesData.ReferenceTextures.pResources.resize(h264Pic->dpb_size);
292    m_CurrentFrameReferencesData.ReferenceTextures.pSubresources.resize(h264Pic->dpb_size);
293    m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.resize(h264Pic->dpb_size);
294    for (uint8_t i = 0; i < h264Pic->dpb_size; i++) {
295       //
296       // Set entry DPB members
297       //
298       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[i].FrameDecodingOrderNumber =
299          h264Pic->dpb[i].frame_idx;
300       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[i].IsLongTermReference =
301          h264Pic->dpb[i].is_ltr;
302       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[i].LongTermPictureIdx =
303          h264Pic->dpb[i].is_ltr ? h264Pic->dpb[i].frame_idx : 0u;
304       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[i].PictureOrderCountNumber =
305          h264Pic->dpb[i].pic_order_cnt;
306       // mirror indices between DPB entries and allocation arrays
307       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[i].ReconstructedPictureResourceIndex = i;
308       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[i].TemporalLayerIndex =
309          h264Pic->dpb[i].temporal_id;
310 
311       //
312       // Set texture allocations
313       //
314 
315       struct d3d12_video_buffer *vidbuf = (struct d3d12_video_buffer *) h264Pic->dpb[i].buffer;
316       m_CurrentFrameReferencesData.ReferenceTextures.pResources[i] = d3d12_resource_resource(vidbuf->texture);
317       m_CurrentFrameReferencesData.ReferenceTextures.pSubresources[i] = vidbuf->idx_texarray_slots;
318 
319       if (h264Pic->dpb[i].pic_order_cnt == h264Pic->pic_order_cnt) {
320          m_CurrentFrameReferencesData.ReconstructedPicTexture.pReconstructedPicture =
321             m_CurrentFrameReferencesData.ReferenceTextures.pResources[i];
322          m_CurrentFrameReferencesData.ReconstructedPicTexture.ReconstructedPictureSubresource =
323             m_CurrentFrameReferencesData.ReferenceTextures.pSubresources[i];
324       }
325    }
326 
327    ///
328    /// Set pic control info
329    ///
330 
331    m_curFrameState.idr_pic_id = h264Pic->idr_pic_id;
332    m_curFrameState.FrameType = d3d12_video_encoder_convert_frame_type_h264(h264Pic->picture_type);
333    m_curFrameState.PictureOrderCountNumber = h264Pic->pic_order_cnt;
334    m_curFrameState.FrameDecodingOrderNumber = h264Pic->slice.frame_num;
335 
336    ///
337    /// Set MMCO info
338    ///
339 
340    // Deep Copy MMCO list
341    m_curFrameState.pRefPicMarkingOperationsCommands = nullptr;
342    m_curFrameState.RefPicMarkingOperationsCommandsCount = 0u;
343    m_curFrameState.adaptive_ref_pic_marking_mode_flag = 0u;
344 
345    if (m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME) {
346 
347       // Only send mmco ops to IHV driver on non-idr frames since dec_ref_pic_marking() in the IDR slice headers doesn't
348       // have the memory operation list coded in the bitstream
349       m_curFrameState.adaptive_ref_pic_marking_mode_flag = h264Pic->slice.adaptive_ref_pic_marking_mode_flag;
350       if (m_curFrameState.adaptive_ref_pic_marking_mode_flag) {
351          m_curFrameState.RefPicMarkingOperationsCommandsCount = h264Pic->slice.num_ref_pic_marking_operations;
352          m_CurrentFrameReferencesData.pMemoryOps.resize(m_curFrameState.RefPicMarkingOperationsCommandsCount);
353          for (unsigned i = 0; i < m_curFrameState.RefPicMarkingOperationsCommandsCount; i++) {
354             m_CurrentFrameReferencesData.pMemoryOps[i].difference_of_pic_nums_minus1 =
355                h264Pic->slice.ref_pic_marking_operations[i].difference_of_pic_nums_minus1;
356             m_CurrentFrameReferencesData.pMemoryOps[i].long_term_frame_idx =
357                h264Pic->slice.ref_pic_marking_operations[i].long_term_frame_idx;
358             m_CurrentFrameReferencesData.pMemoryOps[i].long_term_pic_num =
359                h264Pic->slice.ref_pic_marking_operations[i].long_term_pic_num;
360             m_CurrentFrameReferencesData.pMemoryOps[i].max_long_term_frame_idx_plus1 =
361                h264Pic->slice.ref_pic_marking_operations[i].max_long_term_frame_idx_plus1;
362             m_CurrentFrameReferencesData.pMemoryOps[i].memory_management_control_operation =
363                h264Pic->slice.ref_pic_marking_operations[i].memory_management_control_operation;
364          }
365 
366          // DX12 driver requires "End memory_management_control_operation syntax element loop" to be
367          // sent at the end of the list for coding the slice header when sending down mmco commands
368          if ((m_curFrameState.RefPicMarkingOperationsCommandsCount > 0) &&
369              m_CurrentFrameReferencesData.pMemoryOps[m_curFrameState.RefPicMarkingOperationsCommandsCount - 1]
370                    .memory_management_control_operation != 0) {
371 
372             // Add it if the frontend didn't send it
373             m_curFrameState.RefPicMarkingOperationsCommandsCount++;
374             D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_MARKING_OPERATION endMMCOOperation = {};
375             endMMCOOperation.memory_management_control_operation = 0u;
376             m_CurrentFrameReferencesData.pMemoryOps.push_back(endMMCOOperation);
377          }
378 
379          m_curFrameState.pRefPicMarkingOperationsCommands = m_CurrentFrameReferencesData.pMemoryOps.data();
380       }
381    } else if (h264Pic->slice.long_term_reference_flag) {
382       assert(m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME);
383       // See https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html
384       // Note that for marking an IDR frame as long term reference, the proposed explicit mechanism is to mark it as
385       // short term reference first, by setting D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_USED_AS_REFERENCE_PICTURE when
386       // calling EncodeFrame for such IDR frame, and later promoting it to be a long term reference frame using memory
387       // management operation '3' Mark a short-term reference picture as "used for long-term reference" and assign a
388       // long-term frame index to it.
389       // Alternatively, if encoding an IDR frame and setting adaptive_ref_pic_marking_mode_flag = 1, the driver will
390       // assume that the client is attempting to set the H264 slice header long_term_reference_flag and will do so in
391       // the output bitstream for such EncodeFrame call.
392       m_curFrameState.adaptive_ref_pic_marking_mode_flag = 1;
393 
394       // Workaround for D3D12 validation bug requiring pRefPicMarkingOperationsCommands for IDR frames
395       m_curFrameState.RefPicMarkingOperationsCommandsCount = 1u;
396       m_CurrentFrameReferencesData.pMemoryOps.resize(m_curFrameState.RefPicMarkingOperationsCommandsCount);
397       m_curFrameState.pRefPicMarkingOperationsCommands = m_CurrentFrameReferencesData.pMemoryOps.data();
398    }
399 
400    ///
401    /// Set ref pic modifications info
402    ///
403    // d3d12 needs the array allocations passed in D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264
404    // to avoid copies, and taking advantage of the same memory layout with pipe, shallow copy them
405    // If these static asserts do not pass anymore, change below ALL OCCURRENCES OF reinterpret_casts between
406    // pipe_h264_ref_list_mod_entry and
407    // D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION
408    static_assert(
409       sizeof(struct pipe_h264_ref_list_mod_entry) ==
410       sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION));
411    static_assert(
412       offsetof(struct pipe_h264_ref_list_mod_entry, modification_of_pic_nums_idc) ==
413       offsetof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION,
414                modification_of_pic_nums_idc));
415    static_assert(
416       offsetof(struct pipe_h264_ref_list_mod_entry, abs_diff_pic_num_minus1) ==
417       offsetof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION,
418                abs_diff_pic_num_minus1));
419    static_assert(
420       offsetof(struct pipe_h264_ref_list_mod_entry, long_term_pic_num) ==
421       offsetof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION,
422                long_term_pic_num));
423 
424    m_curFrameState.List0ReferenceFramesCount = 0;
425    m_curFrameState.pList0ReferenceFrames = nullptr;
426    m_curFrameState.List0RefPicModificationsCount = 0;
427    m_curFrameState.pList0RefPicModifications = nullptr;
428    m_curFrameState.List1ReferenceFramesCount = 0;
429    m_curFrameState.pList1ReferenceFrames = nullptr;
430    m_curFrameState.List1RefPicModificationsCount = 0;
431    m_curFrameState.pList1RefPicModifications = nullptr;
432    m_curFrameState.ReferenceFramesReconPictureDescriptorsCount = 0u;
433    m_curFrameState.pReferenceFramesReconPictureDescriptors = nullptr;
434 
435    if ((m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_P_FRAME) ||
436        (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME)) {
437 
438       // Set DPB descriptors
439       m_curFrameState.ReferenceFramesReconPictureDescriptorsCount =
440          static_cast<UINT>(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size());
441       m_curFrameState.pReferenceFramesReconPictureDescriptors =
442          m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.data();
443 
444       // Deep Copy L0 list
445       m_curFrameState.List0ReferenceFramesCount = h264Pic->num_ref_idx_l0_active_minus1 + 1;
446       m_CurrentFrameReferencesData.pList0ReferenceFrames.resize(m_curFrameState.List0ReferenceFramesCount);
447       for (unsigned i = 0; i < m_curFrameState.List0ReferenceFramesCount; i++)
448          m_CurrentFrameReferencesData.pList0ReferenceFrames[i] = h264Pic->ref_list0[i];
449       m_curFrameState.pList0ReferenceFrames = m_CurrentFrameReferencesData.pList0ReferenceFrames.data();
450 
451       // Shallow Copy L0 ref modification list
452       m_curFrameState.List0RefPicModificationsCount = h264Pic->slice.num_ref_list0_mod_operations;
453       if (m_curFrameState.List0RefPicModificationsCount > 0) {
454          m_curFrameState.pList0RefPicModifications = reinterpret_cast<
455             D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION *>(
456             &h264Pic->slice.ref_list0_mod_operations[0]);
457          // DX12 driver requires "End modification_of_pic_nums_idc syntax element loop" to be
458          // sent at the end of the list for coding the slice header when sending down reordering commands
459          assert((m_curFrameState.List0RefPicModificationsCount == 0) ||
460                 m_curFrameState.pList0RefPicModifications[m_curFrameState.List0RefPicModificationsCount - 1]
461                       .modification_of_pic_nums_idc == 3);
462       }
463    }
464 
465    if (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME) {
466 
467       // Deep Copy L1 list
468       m_curFrameState.List1ReferenceFramesCount = h264Pic->num_ref_idx_l1_active_minus1 + 1;
469       m_CurrentFrameReferencesData.pList1ReferenceFrames.resize(m_curFrameState.List1ReferenceFramesCount);
470       for (unsigned i = 0; i < m_curFrameState.List1ReferenceFramesCount; i++)
471          m_CurrentFrameReferencesData.pList1ReferenceFrames[i] = h264Pic->ref_list1[i];
472       m_curFrameState.pList1ReferenceFrames = m_CurrentFrameReferencesData.pList1ReferenceFrames.data();
473 
474       // Shallow Copy L1 ref modification list
475       m_curFrameState.List1RefPicModificationsCount = h264Pic->slice.num_ref_list1_mod_operations;
476       if (m_curFrameState.List1RefPicModificationsCount > 0) {
477          m_curFrameState.pList1RefPicModifications = reinterpret_cast<
478             D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_LIST_MODIFICATION_OPERATION *>(
479             &h264Pic->slice.ref_list1_mod_operations[0]);
480          // DX12 driver requires "End modification_of_pic_nums_idc syntax element loop" to be
481          // sent at the end of the list for coding the slice header when sending down reordering commands
482          assert((m_curFrameState.List1RefPicModificationsCount == 0) ||
483                 m_curFrameState.pList1RefPicModifications[m_curFrameState.List1RefPicModificationsCount - 1]
484                       .modification_of_pic_nums_idc == 3);
485       }
486    }
487 
488    print_dpb();
489    print_l0_l1_lists();
490    print_mmco_lists();
491 }
492 
493 void
print_mmco_lists()494 d3d12_video_encoder_references_manager_h264::print_mmco_lists()
495 {
496    debug_printf("[D3D12 Video Encoder Picture Manager H264] mmco list (%d entries) for frame with POC "
497                 "%d (frame_num: %d) and frame_type %d are:\n",
498                 m_curFrameState.RefPicMarkingOperationsCommandsCount,
499                 m_curFrameState.PictureOrderCountNumber,
500                 m_curFrameState.FrameDecodingOrderNumber,
501                 m_curFrameState.FrameType);
502    for (uint32_t idx = 0; idx < m_curFrameState.RefPicMarkingOperationsCommandsCount; idx++) {
503       D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_REFERENCE_PICTURE_MARKING_OPERATION current_op =
504          m_curFrameState.pRefPicMarkingOperationsCommands[idx];
505       switch (current_op.memory_management_control_operation) {
506          case 0:
507          {
508             debug_printf("End memory_management_control_operation syntax element loop\n");
509          } break;
510          case 1:
511          {
512             debug_printf(
513                "Mark a short-term reference picture as \"unused for reference\" - difference_of_pic_nums_minus1: %d\n",
514                current_op.difference_of_pic_nums_minus1);
515          } break;
516          case 2:
517          {
518             debug_printf("Mark a long-term reference picture as \"unused for reference\"\n - long_term_pic_num: %d\n",
519                          current_op.long_term_pic_num);
520          } break;
521          case 3:
522          {
523             debug_printf("Mark a short-term reference picture as \"used for long-term reference\" and assign a "
524                          "long-term frame index to it - difference_of_pic_nums_minus1: %d - long_term_frame_idx: %d\n",
525                          current_op.difference_of_pic_nums_minus1,
526                          current_op.long_term_frame_idx);
527          } break;
528          case 4:
529          {
530             debug_printf("Specify the maximum long-term frame index and mark all long-term reference pictures having "
531                          "long-term frame indices greater than the maximum value as \"unused for reference\" - "
532                          "max_long_term_frame_idx_plus1: %d",
533                          current_op.max_long_term_frame_idx_plus1);
534          } break;
535          case 5:
536          {
537             debug_printf("Mark all reference pictures as \"unused for reference\" and set the MaxLongTermFrameIdx "
538                          "variable to \"no long-term frame indices\"");
539          } break;
540          case 6:
541          {
542             debug_printf("Mark the current picture as \"used for long-term reference\" and assign a long-term frame "
543                          "index to it - long_term_frame_idx: %d",
544                          current_op.long_term_frame_idx);
545          } break;
546          default:
547          {
548             unreachable("Unsupported memory_management_control_operation");
549          } break;
550       }
551    }
552 }
553