• 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 
29 using namespace std;
30 
d3d12_video_encoder_references_manager_h264(bool gopHasIorPFrames,d3d12_video_dpb_storage_manager_interface & rDpbStorageManager,uint32_t MaxDPBCapacity)31 d3d12_video_encoder_references_manager_h264::d3d12_video_encoder_references_manager_h264(
32    bool gopHasIorPFrames, d3d12_video_dpb_storage_manager_interface &rDpbStorageManager, uint32_t MaxDPBCapacity)
33    : m_MaxDPBCapacity(MaxDPBCapacity),
34      m_rDPBStorageManager(rDpbStorageManager),
35      m_CurrentFrameReferencesData({}),
36      m_gopHasInterFrames(gopHasIorPFrames)
37 {
38    assert((m_MaxDPBCapacity + 1 /*extra for cur frame output recon pic*/) ==
39           m_rDPBStorageManager.get_number_of_tracked_allocations());
40 
41    debug_printf("[D3D12 Video Encoder Picture Manager H264] Completed construction of "
42                  "d3d12_video_encoder_references_manager_h264 instance, settings are\n");
43    debug_printf("[D3D12 Video Encoder Picture Manager H264] m_MaxDPBCapacity: %d\n", m_MaxDPBCapacity);
44 }
45 
46 void
reset_gop_tracking_and_dpb()47 d3d12_video_encoder_references_manager_h264::reset_gop_tracking_and_dpb()
48 {
49    // Reset m_CurrentFrameReferencesData tracking
50    m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.clear();
51    m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.reserve(m_MaxDPBCapacity);
52    m_CurrentFrameReferencesData.ReconstructedPicTexture = { nullptr, 0 };
53 
54    // Reset DPB storage
55    ASSERTED uint32_t numPicsBeforeClearInDPB = m_rDPBStorageManager.get_number_of_pics_in_dpb();
56    ASSERTED uint32_t cFreedResources = m_rDPBStorageManager.clear_decode_picture_buffer();
57    assert(numPicsBeforeClearInDPB == cFreedResources);
58 
59    // Initialize if needed the reconstructed picture allocation for the first IDR picture in the GOP
60    // This needs to be done after initializing the GOP tracking state above since it makes decisions based on the
61    // current picture type.
62    prepare_current_frame_recon_pic_allocation();
63 
64    // After clearing the DPB, outstanding used allocations should be 1u only for the first allocation for the
65    // reconstructed picture of the initial IDR in the GOP
66    assert(m_rDPBStorageManager.get_number_of_in_use_allocations() == (m_gopHasInterFrames ? 1u : 0u));
67    assert(m_rDPBStorageManager.get_number_of_tracked_allocations() <=
68           (m_MaxDPBCapacity + 1));   // pool is not extended beyond maximum expected usage
69 }
70 
71 // Calculates the picture control structure for the current frame
72 bool
get_current_frame_picture_control_data(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA & codecAllocation)73 d3d12_video_encoder_references_manager_h264::get_current_frame_picture_control_data(
74    D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &codecAllocation)
75 {
76    // Update reference picture control structures (L0/L1 and DPB descriptors lists based on current frame and next frame
77    // in GOP) for next frame
78 
79    debug_printf("[D3D12 Video Encoder Picture Manager H264] %d resources IN USE out of a total of %d ALLOCATED "
80                  "resources at frame with POC: %d\n",
81                  m_rDPBStorageManager.get_number_of_in_use_allocations(),
82                  m_rDPBStorageManager.get_number_of_tracked_allocations(),
83                  m_curFrameState.PictureOrderCountNumber);
84 
85    // See casts below
86    assert(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size() < UINT32_MAX);
87 
88    bool needsL0List = (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_P_FRAME) ||
89                       (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME);
90    bool needsL1List = (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME);
91 
92    assert(codecAllocation.DataSize == sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264));
93 
94    // See D3D12 Encode spec below
95    // pList0ReferenceFrames
96    //    List of past frame reference frames to be used for this frame. Each integer value in this array indices into
97    //    pReferenceFramesReconPictureDescriptors to reference pictures kept in the DPB.
98    // pList1ReferenceFrames
99    //    List of future frame reference frames to be used for this frame. Each integer value in this array indices into
100    //    pReferenceFramesReconPictureDescriptors to reference pictures kept in the DPB.
101 
102    // Need to map from frame_num in the receiving ref_idx_l0_list/ref_idx_l1_list to the position with that
103    // FrameDecodingOrderNumber in the DPB descriptor
104 
105    if (needsL0List && (m_curFrameState.List0ReferenceFramesCount > 0)) {
106       std::vector<uint32_t> tmpL0(m_curFrameState.List0ReferenceFramesCount, 0);
107       memcpy(tmpL0.data(),
108              m_curFrameState.pList0ReferenceFrames,
109              m_curFrameState.List0ReferenceFramesCount * sizeof(m_curFrameState.pList0ReferenceFrames[0]));
110 
111       for (size_t l0Idx = 0; l0Idx < m_curFrameState.List0ReferenceFramesCount; l0Idx++) {
112          // tmpL0[l0Idx] has frame_num's (FrameDecodingOrderNumber)
113          // m_curFrameState.pList0ReferenceFrames[l0Idx] needs to have the index j of
114          // pReferenceFramesReconPictureDescriptors where
115          // pReferenceFramesReconPictureDescriptors[j].FrameDecodingOrderNumber == tmpL0[l0Idx]
116 
117          auto value = tmpL0[l0Idx];
118          auto foundItemIt = std::find_if(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(),
119                                          m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end(),
120                                          [&value](const D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_H264 &p) {
121                                             return p.FrameDecodingOrderNumber == value;
122                                          });
123 
124          assert(foundItemIt != m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end());
125          if (foundItemIt == m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end())
126          {
127             return false;
128          }
129          m_curFrameState.pList0ReferenceFrames[l0Idx] =
130             std::distance(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(), foundItemIt);
131       }
132    }
133 
134    if (needsL1List && (m_curFrameState.List1ReferenceFramesCount > 0)) {
135       std::vector<uint32_t> tmpL1(m_curFrameState.List1ReferenceFramesCount, 0);
136       memcpy(tmpL1.data(),
137              m_curFrameState.pList1ReferenceFrames,
138              m_curFrameState.List1ReferenceFramesCount * sizeof(m_curFrameState.pList1ReferenceFrames[0]));
139 
140       for (size_t l1Idx = 0; l1Idx < m_curFrameState.List1ReferenceFramesCount; l1Idx++) {
141          // tmpL1[l1Idx] has frame_num's (FrameDecodingOrderNumber)
142          // m_curFrameState.pList1ReferenceFrames[l1Idx] needs to have the index j of
143          // pReferenceFramesReconPictureDescriptors where
144          // pReferenceFramesReconPictureDescriptors[j].FrameDecodingOrderNumber == tmpL1[l1Idx]
145 
146          auto value = tmpL1[l1Idx];
147          auto foundItemIt = std::find_if(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(),
148                                          m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end(),
149                                          [&value](const D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_H264 &p) {
150                                             return p.FrameDecodingOrderNumber == value;
151                                          });
152 
153          assert(foundItemIt != m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end());
154          if (foundItemIt == m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end())
155          {
156             return false;
157          }
158          m_curFrameState.pList1ReferenceFrames[l1Idx] =
159             std::distance(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(), foundItemIt);
160       }
161    }
162 
163    m_curFrameState.List0ReferenceFramesCount = needsL0List ? m_curFrameState.List0ReferenceFramesCount : 0;
164    m_curFrameState.pList0ReferenceFrames = needsL0List ? m_curFrameState.pList0ReferenceFrames : nullptr,
165    m_curFrameState.List1ReferenceFramesCount = needsL1List ? m_curFrameState.List1ReferenceFramesCount : 0,
166    m_curFrameState.pList1ReferenceFrames = needsL1List ? m_curFrameState.pList1ReferenceFrames : nullptr,
167    m_curFrameState.ReferenceFramesReconPictureDescriptorsCount =
168       needsL0List ? static_cast<uint32_t>(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size()) :
169                     0,
170    m_curFrameState.pReferenceFramesReconPictureDescriptors =
171       needsL0List ? m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.data() : nullptr,
172 
173    *codecAllocation.pH264PicData = m_curFrameState;
174 
175    print_l0_l1_lists();
176    print_dpb();
177 
178    return true;
179 }
180 
181 // Returns the resource allocation for a reconstructed picture output for the current frame
182 D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE
get_current_frame_recon_pic_output_allocation()183 d3d12_video_encoder_references_manager_h264::get_current_frame_recon_pic_output_allocation()
184 {
185    return m_CurrentFrameReferencesData.ReconstructedPicTexture;
186 }
187 
188 D3D12_VIDEO_ENCODE_REFERENCE_FRAMES
get_current_reference_frames()189 d3d12_video_encoder_references_manager_h264::get_current_reference_frames()
190 {
191    D3D12_VIDEO_ENCODE_REFERENCE_FRAMES retVal = { 0,
192                                                   // ppTexture2Ds
193                                                   nullptr,
194                                                   // pSubresources
195                                                   nullptr };
196 
197    // Return nullptr for fully intra frames (eg IDR)
198    // and return references information for inter frames (eg.P/B) and I frame that doesn't flush DPB
199 
200    if ((m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME) &&
201        (m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_I_FRAME) && m_gopHasInterFrames) {
202       auto curRef = m_rDPBStorageManager.get_current_reference_frames();
203       retVal.NumTexture2Ds = curRef.NumTexture2Ds;
204       retVal.ppTexture2Ds = curRef.ppTexture2Ds;
205       retVal.pSubresources = curRef.pSubresources;
206    }
207 
208    return retVal;
209 }
210 
211 void
prepare_current_frame_recon_pic_allocation()212 d3d12_video_encoder_references_manager_h264::prepare_current_frame_recon_pic_allocation()
213 {
214    m_CurrentFrameReferencesData.ReconstructedPicTexture = { nullptr, 0 };
215 
216    // If all GOP are intra frames, no point in doing reference pic allocations
217    if (is_current_frame_used_as_reference() && m_gopHasInterFrames) {
218       auto reconPic = m_rDPBStorageManager.get_new_tracked_picture_allocation();
219       m_CurrentFrameReferencesData.ReconstructedPicTexture.pReconstructedPicture = reconPic.pReconstructedPicture;
220       m_CurrentFrameReferencesData.ReconstructedPicTexture.ReconstructedPictureSubresource =
221          reconPic.ReconstructedPictureSubresource;
222    }
223 }
224 
225 void
update_fifo_dpb_push_front_cur_recon_pic()226 d3d12_video_encoder_references_manager_h264::update_fifo_dpb_push_front_cur_recon_pic()
227 {
228    // Keep the order of the dpb storage and dpb descriptors in a circular buffer
229    // order such that the DPB array consists of a sequence of frames in DECREASING encoding order
230    // eg. last frame encoded at first, followed by one to last frames encoded, and at the end
231    // the most distant frame encoded (currentFrameEncodeOrderNumber - MaxDPBSize)
232 
233    // If current pic was not used as reference, current reconstructed picture resource is empty,
234    // No need to to anything in that case.
235    // Otherwise extract the reconstructed picture result and add it to the DPB
236 
237    // If GOP are all intra frames, do nothing also.
238    if (is_current_frame_used_as_reference() && m_gopHasInterFrames) {
239       debug_printf("[D3D12 Video Encoder Picture Manager H264] MaxDPBCapacity is %d - Number of pics in DPB is %d "
240                     "when trying to put frame with POC %d at front of the DPB\n",
241                     m_MaxDPBCapacity,
242                     m_rDPBStorageManager.get_number_of_pics_in_dpb(),
243                     m_curFrameState.PictureOrderCountNumber);
244 
245       // Release least recently used in DPB if we filled the m_MaxDPBCapacity allowed
246       if (m_rDPBStorageManager.get_number_of_pics_in_dpb() == m_MaxDPBCapacity) {
247          bool untrackedRes = false;
248          m_rDPBStorageManager.remove_reference_frame(m_rDPBStorageManager.get_number_of_pics_in_dpb() - 1,
249                                                      &untrackedRes);   // Remove last entry
250          // Verify that resource was untracked since this class is using the pool completely for allocations
251          assert(untrackedRes);
252          m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.pop_back();   // Remove last entry
253       }
254 
255       // Add new dpb to front of DPB
256       D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE recAlloc = get_current_frame_recon_pic_output_allocation();
257       d3d12_video_reconstructed_picture refFrameDesc = {};
258       refFrameDesc.pReconstructedPicture = recAlloc.pReconstructedPicture;
259       refFrameDesc.ReconstructedPictureSubresource = recAlloc.ReconstructedPictureSubresource;
260       refFrameDesc.pVideoHeap = nullptr;   // D3D12 Video Encode does not need the D3D12VideoEncoderHeap struct for H264
261                                            // (used for no-key-frame resolution change in VC1, AV1, etc)
262       m_rDPBStorageManager.insert_reference_frame(refFrameDesc, 0);
263 
264       // Prepare D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_H264 for added DPB member
265       D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_H264 newDPBDescriptor = {
266          // uint32_t ReconstructedPictureResourceIndex;
267          0,   // the associated reconstructed picture is also being pushed_front in m_rDPBStorageManager
268               // BOOL IsLongTermReference;
269          false,
270          // uint32_t LongTermPictureIdx;
271          0,
272          // uint32_t PictureOrderCountNumber;
273          m_curFrameState.PictureOrderCountNumber,
274          // uint32_t FrameDecodingOrderNumber;
275          m_curFrameState.FrameDecodingOrderNumber,
276          // uint32_t TemporalLayerIndex;
277          0   // NO B-hierarchy in this impl of the picture manager
278       };
279 
280       // Add DPB entry
281       m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.insert(
282          m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(),
283          newDPBDescriptor);
284 
285       // Update the indices for ReconstructedPictureResourceIndex in pReferenceFramesReconPictureDescriptors
286       // to be in identity mapping with m_rDPBStorageManager indices
287       // after pushing the elements to the right in the push_front operation
288       for (uint32_t dpbResIdx = 1;
289            dpbResIdx < m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size();
290            dpbResIdx++) {
291          auto &dpbDesc = m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[dpbResIdx];
292          dpbDesc.ReconstructedPictureResourceIndex = dpbResIdx;
293       }
294    }
295 
296    // Number of allocations, disregarding if they are used or not, should not exceed this limit due to reuse policies on
297    // DPB items removal.
298    assert(m_rDPBStorageManager.get_number_of_tracked_allocations() <= (m_MaxDPBCapacity + 1));
299 }
300 
301 void
print_l0_l1_lists()302 d3d12_video_encoder_references_manager_h264::print_l0_l1_lists()
303 {
304    if ((D3D12_DEBUG_VERBOSE & d3d12_debug) &&
305        ((m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_P_FRAME) ||
306         (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_B_FRAME))) {
307       std::string list0ContentsString;
308       for (uint32_t idx = 0; idx < m_curFrameState.List0ReferenceFramesCount; idx++) {
309          uint32_t value = m_curFrameState.pList0ReferenceFrames[idx];
310          list0ContentsString += "{ DPBidx: ";
311          list0ContentsString += std::to_string(value);
312          list0ContentsString += " - POC: ";
313          list0ContentsString += std::to_string(
314             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].PictureOrderCountNumber);
315          list0ContentsString += " - FrameDecodingOrderNumber: ";
316          list0ContentsString += std::to_string(
317             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].FrameDecodingOrderNumber);
318          list0ContentsString += "}\n";
319       }
320 
321       debug_printf(
322          "[D3D12 Video Encoder Picture Manager H264] L0 list for frame with POC %d - frame_num (%d) is: \n %s \n",
323          m_curFrameState.PictureOrderCountNumber,
324          m_curFrameState.FrameDecodingOrderNumber,
325          list0ContentsString.c_str());
326 
327       std::string list1ContentsString;
328       for (uint32_t idx = 0; idx < m_curFrameState.List1ReferenceFramesCount; idx++) {
329          uint32_t value = m_curFrameState.pList1ReferenceFrames[idx];
330          list1ContentsString += "{ DPBidx: ";
331          list1ContentsString += std::to_string(value);
332          list1ContentsString += " - POC: ";
333          list1ContentsString += std::to_string(
334             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].PictureOrderCountNumber);
335          list1ContentsString += " - FrameDecodingOrderNumber: ";
336          list1ContentsString += std::to_string(
337             m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].FrameDecodingOrderNumber);
338          list1ContentsString += "}\n";
339       }
340 
341       debug_printf(
342          "[D3D12 Video Encoder Picture Manager H264] L1 list for frame with POC %d - frame_num (%d) is: \n %s \n",
343          m_curFrameState.PictureOrderCountNumber,
344          m_curFrameState.FrameDecodingOrderNumber,
345          list1ContentsString.c_str());
346    }
347 }
348 
349 void
print_dpb()350 d3d12_video_encoder_references_manager_h264::print_dpb()
351 {
352    if (D3D12_DEBUG_VERBOSE & d3d12_debug) {
353       std::string dpbContents;
354       for (uint32_t dpbResIdx = 0;
355            dpbResIdx < m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size();
356            dpbResIdx++) {
357          auto &dpbDesc = m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[dpbResIdx];
358          auto dpbEntry = m_rDPBStorageManager.get_reference_frame(dpbDesc.ReconstructedPictureResourceIndex);
359 
360          dpbContents += "{ DPBidx: ";
361          dpbContents += std::to_string(dpbResIdx);
362          dpbContents += " - POC: ";
363          dpbContents += std::to_string(dpbDesc.PictureOrderCountNumber);
364          dpbContents += " - FrameDecodingOrderNumber: ";
365          dpbContents += std::to_string(dpbDesc.FrameDecodingOrderNumber);
366          dpbContents += " - DPBStorageIdx: ";
367          dpbContents += std::to_string(dpbDesc.ReconstructedPictureResourceIndex);
368          dpbContents += " - DPBStorageResourcePtr: ";
369          char strBuf[256];
370          memset(&strBuf, '\0', 256);
371          sprintf(strBuf, "%p", dpbEntry.pReconstructedPicture);
372          dpbContents += std::string(strBuf);
373          dpbContents += " - DPBStorageSubresource: ";
374          dpbContents += std::to_string(dpbEntry.ReconstructedPictureSubresource);
375          dpbContents += "}\n";
376       }
377 
378       debug_printf("[D3D12 Video Encoder Picture Manager H264] DPB Current output reconstructed picture %p subresource %d\n",
379                      m_CurrentFrameReferencesData.ReconstructedPicTexture.pReconstructedPicture,
380                      m_CurrentFrameReferencesData.ReconstructedPicTexture.ReconstructedPictureSubresource);
381       debug_printf("[D3D12 Video Encoder Picture Manager H264] DPB has %d frames - DPB references for frame with POC "
382                     "%d (frame_num: %d) are: \n %s \n",
383                     m_rDPBStorageManager.get_number_of_pics_in_dpb(),
384                     m_curFrameState.PictureOrderCountNumber,
385                     m_curFrameState.FrameDecodingOrderNumber,
386                     dpbContents.c_str());
387    }
388 }
389 
390 // Advances state to next frame in GOP; subsequent calls to GetCurrentFrame* point to the advanced frame status
391 void
end_frame()392 d3d12_video_encoder_references_manager_h264::end_frame()
393 {
394    debug_printf("[D3D12 Video Encoder Picture Manager H264] %d resources IN USE out of a total of %d ALLOCATED "
395                  "resources at end_frame for frame with POC: %d\n",
396                  m_rDPBStorageManager.get_number_of_in_use_allocations(),
397                  m_rDPBStorageManager.get_number_of_tracked_allocations(),
398                  m_curFrameState.PictureOrderCountNumber);
399 
400    // Adds last used (if not null) get_current_frame_recon_pic_output_allocation to DPB for next EncodeFrame if
401    // necessary updates pReferenceFramesReconPictureDescriptors and updates the dpb storage
402 
403    update_fifo_dpb_push_front_cur_recon_pic();
404 }
405 
406 bool
is_current_frame_used_as_reference()407 d3d12_video_encoder_references_manager_h264::is_current_frame_used_as_reference()
408 {
409    return m_isCurrentFrameUsedAsReference;
410 }
411 
412 void
begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,bool bUsedAsReference,struct pipe_picture_desc * picture)413 d3d12_video_encoder_references_manager_h264::begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,
414                                                          bool bUsedAsReference, struct pipe_picture_desc* picture)
415 {
416    m_curFrameState = *curFrameData.pH264PicData;
417    m_isCurrentFrameUsedAsReference = bUsedAsReference;
418    debug_printf("[Entrypoint: %d] - Marking frame_num %d (POC %d) as reference ? %d\n",
419                  picture->entry_point,
420                  curFrameData.pH264PicData->FrameDecodingOrderNumber,
421                  curFrameData.pH264PicData->PictureOrderCountNumber,
422                  bUsedAsReference);
423 
424    // Advance the GOP tracking state
425    bool isDPBFlushNeeded = (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME);
426    if (isDPBFlushNeeded) {
427       reset_gop_tracking_and_dpb();
428    } else {
429       // Get new allocation from DPB storage for reconstructed picture
430       // This is only necessary for the frames that come after an IDR
431       // since in the initial state already has this initialized
432       // and re-initialized by reset_gop_tracking_and_dpb above
433 
434       prepare_current_frame_recon_pic_allocation();
435    }
436 }
437