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