xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/d3d12/d3d12_video_dec_vp9.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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_dec.h"
25 #include "d3d12_video_dec_vp9.h"
26 #include <cmath>
27 
28 void
d3d12_video_decoder_refresh_dpb_active_references_vp9(struct d3d12_video_decoder * pD3D12Dec)29 d3d12_video_decoder_refresh_dpb_active_references_vp9(struct d3d12_video_decoder *pD3D12Dec)
30 {
31 // Method overview
32    // 1. Codec specific strategy in switch statement regarding reference frames eviction policy. Should only mark active
33    // DPB references, leaving evicted ones as unused
34    // 2. Call release_unused_references_texture_memory(); at the end of this method. Any references (and texture
35    // allocations associated)
36    //    that were left not marked as used in m_spDPBManager by step (2) are lost.
37 
38    // Assign DXVA original Index indices to current frame and references
39    DXVA_PicParams_VP9 *pCurrPicParams = d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_VP9>(pD3D12Dec);
40 
41    for (uint8_t i = 0; i < _countof(pCurrPicParams->ref_frame_map); i++) {
42       if (pD3D12Dec->m_pCurrentReferenceTargets[i]) {
43          pCurrPicParams->ref_frame_map[i].Index7Bits =
44             pD3D12Dec->m_spDPBManager->get_index7bits(pD3D12Dec->m_pCurrentReferenceTargets[i]);
45       }
46    }
47 
48    for (uint8_t i = 0; i < _countof(pCurrPicParams->frame_refs); i++) {
49       if(!pCurrPicParams->frame_refs[i].AssociatedFlag)
50          pCurrPicParams->frame_refs[i].Index7Bits = pCurrPicParams->ref_frame_map[pCurrPicParams->frame_refs[i].Index7Bits].Index7Bits;
51    }
52 
53    pD3D12Dec->m_spDPBManager->mark_all_references_as_unused();
54    pD3D12Dec->m_spDPBManager->mark_references_in_use(pCurrPicParams->ref_frame_map);
55 
56    // Releases the underlying reference picture texture objects of all references that were not marked as used in this
57    // method.
58    pD3D12Dec->m_spDPBManager->release_unused_references_texture_memory();
59 
60    pCurrPicParams->CurrPic.Index7Bits = pD3D12Dec->m_spDPBManager->get_index7bits(pD3D12Dec->m_pCurrentDecodeTarget);
61 }
62 
63 void
d3d12_video_decoder_get_frame_info_vp9(struct d3d12_video_decoder * pD3D12Dec,uint32_t * pWidth,uint32_t * pHeight,uint16_t * pMaxDPB)64 d3d12_video_decoder_get_frame_info_vp9(
65    struct d3d12_video_decoder *pD3D12Dec, uint32_t *pWidth, uint32_t *pHeight, uint16_t *pMaxDPB)
66 {
67    auto pPicParams = d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_VP9>(pD3D12Dec);
68    *pWidth = pPicParams->width;
69    *pHeight = pPicParams->height;
70 
71    /*
72       – The VP9 decoder maintains a pool (ref_frame_map[]) of 8 reference pictures at all times. Each
73       frame picks 3 reference frames (frame_refs[]) from the pool to use for inter prediction (known as Last,
74       Golden, and AltRef) of the current frame.
75    */
76    *pMaxDPB = 8 + 1 /*current picture*/;
77 }
78 
79 void
d3d12_video_decoder_prepare_current_frame_references_vp9(struct d3d12_video_decoder * pD3D12Dec,ID3D12Resource * pTexture2D,uint32_t subresourceIndex)80 d3d12_video_decoder_prepare_current_frame_references_vp9(struct d3d12_video_decoder *pD3D12Dec,
81                                                           ID3D12Resource *pTexture2D,
82                                                           uint32_t subresourceIndex)
83 {
84    DXVA_PicParams_VP9 *pPicParams = d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_VP9>(pD3D12Dec);
85    pPicParams->CurrPic.Index7Bits = pD3D12Dec->m_spDPBManager->store_future_reference(pPicParams->CurrPic.Index7Bits,
86                                                                                       pD3D12Dec->m_spVideoDecoderHeap,
87                                                                                       pTexture2D,
88                                                                                       subresourceIndex);
89    pD3D12Dec->m_spDPBManager->update_entries(
90       d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_VP9>(pD3D12Dec)->frame_refs,
91       pD3D12Dec->m_transitionsStorage);
92 
93    pD3D12Dec->m_spDPBManager->update_entries(
94       d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_VP9>(pD3D12Dec)->ref_frame_map,
95       pD3D12Dec->m_transitionsStorage);
96 
97    pD3D12Dec->m_spDecodeCommandList->ResourceBarrier(pD3D12Dec->m_transitionsStorage.size(), pD3D12Dec->m_transitionsStorage.data());
98 
99    // Schedule reverse (back to common) transitions before command list closes for current frame
100    for (auto BarrierDesc : pD3D12Dec->m_transitionsStorage) {
101       std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
102       pD3D12Dec->m_transitionsBeforeCloseCmdList.push_back(BarrierDesc);
103    }
104 
105    debug_printf(
106       "[d3d12_video_decoder_prepare_current_frame_references_vp9] DXVA_PicParams_VP9 after index remapping)\n");
107    d3d12_video_decoder_log_pic_params_vp9(
108       d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_VP9>(pD3D12Dec));
109 }
110 
111 void
d3d12_video_decoder_log_pic_params_vp9(DXVA_PicParams_VP9 * pPicParams)112 d3d12_video_decoder_log_pic_params_vp9(DXVA_PicParams_VP9 *pPicParams)
113    {
114    debug_printf("\n=============================================\n");
115    debug_printf("[D3D12 Video Decoder VP9 DXVA PicParams info]\n");
116 
117    debug_printf("CurrPic.Index7Bits = %d\n", pPicParams->CurrPic.Index7Bits);
118    debug_printf("CurrPic.AssociatedFlag = %d\n", pPicParams->CurrPic.AssociatedFlag);
119    debug_printf("profile = %d\n", pPicParams->profile);
120    debug_printf("frame_type = %d\n", pPicParams->frame_type);
121    debug_printf("show_frame = %d\n", pPicParams->show_frame);
122    debug_printf("error_resilient_mode = %d\n", pPicParams->error_resilient_mode);
123    debug_printf("subsampling_x = %d\n", pPicParams->subsampling_x);
124    debug_printf("subsampling_y = %d\n", pPicParams->subsampling_y);
125    debug_printf("extra_plane = %d\n", pPicParams->extra_plane);
126    debug_printf("refresh_frame_context = %d\n", pPicParams->refresh_frame_context);
127    debug_printf("frame_parallel_decoding_mode = %d\n", pPicParams->frame_parallel_decoding_mode);
128    debug_printf("intra_only = %d\n", pPicParams->intra_only);
129    debug_printf("frame_context_idx = %d\n", pPicParams->frame_context_idx);
130    debug_printf("reset_frame_context = %d\n", pPicParams->reset_frame_context);
131    debug_printf("allow_high_precision_mv = %d\n", pPicParams->allow_high_precision_mv);
132    debug_printf("ReservedFormatInfo2Bits = %d\n", pPicParams->ReservedFormatInfo2Bits);
133    debug_printf("wFormatAndPictureInfoFlags = %d\n", pPicParams->wFormatAndPictureInfoFlags);
134    debug_printf("width = %d\n", pPicParams->width);
135    debug_printf("height = %d\n", pPicParams->height);
136    debug_printf("BitDepthMinus8Luma = %d\n", pPicParams->BitDepthMinus8Luma);
137    debug_printf("BitDepthMinus8Chroma = %d\n", pPicParams->BitDepthMinus8Chroma);
138    debug_printf("interp_filter = %d\n", pPicParams->interp_filter);
139    debug_printf("Reserved8Bits = %d\n", pPicParams->Reserved8Bits);
140 
141    for (uint32_t i = 0; i < _countof(pPicParams->ref_frame_map); i++) {
142       debug_printf("ref_frame_map[%d].Index7Bits = %d\n", i, pPicParams->ref_frame_map[i].Index7Bits);
143       debug_printf("ref_frame_map[%d].AssociatedFlag = %d\n", i, pPicParams->ref_frame_map[i].AssociatedFlag);
144    }
145 
146    for (uint32_t i = 0; i < _countof(pPicParams->ref_frame_coded_width); i++)
147       debug_printf("ref_frame_coded_width[%d] = %d\n", i, pPicParams->ref_frame_coded_width[i]);
148 
149    for (uint32_t i = 0; i < _countof(pPicParams->ref_frame_coded_height); i++)
150       debug_printf("ref_frame_coded_height[%d] = %d\n", i, pPicParams->ref_frame_coded_height[i]);
151 
152    for (uint32_t i = 0; i < _countof(pPicParams->frame_refs); i++) {
153       debug_printf("frame_refs[%d].Index7Bits = %d\n", i, pPicParams->frame_refs[i].Index7Bits);
154       debug_printf("frame_refs[%d].AssociatedFlag = %d\n", i, pPicParams->frame_refs[i].AssociatedFlag);
155    }
156 
157    for (uint32_t i = 0; i < _countof(pPicParams->ref_frame_sign_bias); i++)
158       debug_printf("ref_frame_sign_bias[%d] = %d\n", i, pPicParams->ref_frame_sign_bias[i]);
159 
160    debug_printf("filter_level = %d\n", pPicParams->filter_level);
161    debug_printf("sharpness_level = %d\n", pPicParams->sharpness_level);
162    debug_printf("mode_ref_delta_enabled = %d\n", pPicParams->mode_ref_delta_enabled);
163    debug_printf("mode_ref_delta_update = %d\n", pPicParams->mode_ref_delta_update);
164    debug_printf("use_prev_in_find_mv_refs = %d\n", pPicParams->use_prev_in_find_mv_refs);
165    debug_printf("ReservedControlInfo5Bits = %d\n", pPicParams->ReservedControlInfo5Bits);
166    debug_printf("wControlInfoFlags; = %d\n", pPicParams->wControlInfoFlags);
167 
168    for (uint32_t i = 0; i < _countof(pPicParams->ref_deltas); i++)
169       debug_printf("ref_deltas[%d] = %d\n", i, pPicParams->ref_deltas[i]);
170    for (uint32_t i = 0; i < _countof(pPicParams->mode_deltas); i++)
171       debug_printf("mode_deltas[%d] = %d\n", i, pPicParams->mode_deltas[i]);
172 
173    debug_printf("base_qindex = %d\n", pPicParams->base_qindex);
174    debug_printf("y_dc_delta_q = %d\n", pPicParams->y_dc_delta_q);
175    debug_printf("uv_dc_delta_q = %d\n", pPicParams->uv_dc_delta_q);
176    debug_printf("uv_ac_delta_q = %d\n", pPicParams->uv_ac_delta_q);
177 
178    debug_printf("stVP9Segments.enabled = %d\n", pPicParams->stVP9Segments.enabled);
179    debug_printf("stVP9Segments.update_map = %d\n", pPicParams->stVP9Segments.update_map);
180    debug_printf("stVP9Segments.temporal_update = %d\n", pPicParams->stVP9Segments.temporal_update);
181    debug_printf("stVP9Segments.abs_delta = %d\n", pPicParams->stVP9Segments.abs_delta);
182    debug_printf("stVP9Segments.ReservedSegmentFlags4Bits = %d\n", pPicParams->stVP9Segments.ReservedSegmentFlags4Bits);
183    debug_printf("stVP9Segments.wSegmentInfoFlags = %d\n", pPicParams->stVP9Segments.wSegmentInfoFlags);
184 
185    for (uint32_t i = 0; i < _countof(pPicParams->stVP9Segments.tree_probs); i++)
186       debug_printf("tree_probs[%d] = %d\n", i, pPicParams->stVP9Segments.tree_probs[i]);
187 
188    for (uint32_t i = 0; i < _countof(pPicParams->stVP9Segments.pred_probs); i++)
189       debug_printf("pred_probs[%d] = %d\n", i, pPicParams->stVP9Segments.pred_probs[i]);
190 
191    for (uint32_t i = 0; i < _countof(pPicParams->stVP9Segments.feature_data); i++)
192       for (uint32_t j = 0; j < _countof(pPicParams->stVP9Segments.feature_data[0]); j++)
193          debug_printf("feature_data[%d][%d] = %d\n", i, j, pPicParams->stVP9Segments.feature_data[i][j]);
194 
195    for (uint32_t i = 0; i < _countof(pPicParams->stVP9Segments.feature_mask); i++)
196       debug_printf("feature_mask[%d] = %d\n", i, pPicParams->stVP9Segments.feature_mask[i]);
197 
198    debug_printf("log2_tile_cols = %d\n", pPicParams->log2_tile_cols);
199    debug_printf("log2_tile_rows = %d\n", pPicParams->log2_tile_rows);
200    debug_printf("uncompressed_header_size_byte_aligned = %d\n", pPicParams->uncompressed_header_size_byte_aligned);
201    debug_printf("first_partition_size = %d\n", pPicParams->first_partition_size);
202    debug_printf("Reserved16Bits = %d\n", pPicParams->Reserved16Bits);
203    debug_printf("Reserved32Bits = %d\n", pPicParams->Reserved32Bits);
204    debug_printf("StatusReportFeedbackNumber = %d\n", pPicParams->StatusReportFeedbackNumber);
205 }
206 
207 void
d3d12_video_decoder_prepare_dxva_slices_control_vp9(struct d3d12_video_decoder * pD3D12Dec,std::vector<uint8_t> & vecOutSliceControlBuffers,struct pipe_vp9_picture_desc * picture_vp9)208 d3d12_video_decoder_prepare_dxva_slices_control_vp9(struct d3d12_video_decoder *pD3D12Dec,
209                                                      std::vector<uint8_t> &vecOutSliceControlBuffers,
210                                                      struct pipe_vp9_picture_desc *picture_vp9)
211 {
212    if(!picture_vp9->slice_parameter.slice_info_present)
213    {
214       unreachable("Unsupported - need pipe_vp9_picture_desc.slice_parameter.slice_info_present");
215    }
216 
217    debug_printf("[d3d12_video_decoder_vp9] Upper layer reported %d slices for this frame, parsing them below...\n",
218                   picture_vp9->slice_parameter.slice_count);
219 
220    uint64_t TotalSlicesDXVAArrayByteSize = picture_vp9->slice_parameter.slice_count * sizeof(DXVA_Slice_VPx_Short);
221    vecOutSliceControlBuffers.resize(TotalSlicesDXVAArrayByteSize);
222 
223    uint8_t* pData = vecOutSliceControlBuffers.data();
224    for (uint32_t sliceIdx = 0; sliceIdx < picture_vp9->slice_parameter.slice_count; sliceIdx++)
225    {
226       DXVA_Slice_VPx_Short currentSliceEntry = {};
227       // From DXVA Spec
228       // wBadSliceChopping
229       // 0	All bits for the slice are located within the corresponding bitstream data buffer.
230       // 1	The bitstream data buffer contains the start of the slice, but not the entire slice, because the buffer is full.
231       // 2	The bitstream data buffer contains the end of the slice. It does not contain the start of the slice, because the start of the slice was located in the previous bitstream data buffer.
232       // 3	The bitstream data buffer does not contain the start of the slice (because the start of the slice was located in the previous bitstream data buffer),
233       //     and it does not contain the end of the slice (because the current bitstream data buffer is also full).
234 
235       switch (picture_vp9->slice_parameter.slice_data_flag[sliceIdx]) {
236          /* whole slice is in the buffer */
237          case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_WHOLE:
238             currentSliceEntry.wBadSliceChopping = 0u;
239             break;
240          /* The beginning of the slice is in the buffer but the end is not */
241          case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_BEGIN:
242             currentSliceEntry.wBadSliceChopping = 1u;
243             break;
244          /* Neither beginning nor end of the slice is in the buffer */
245          case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_MIDDLE:
246             currentSliceEntry.wBadSliceChopping = 3u;
247             break;
248          /* end of the slice is in the buffer */
249          case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_END:
250             currentSliceEntry.wBadSliceChopping = 2u;
251             break;
252          default:
253          {
254             unreachable("Unsupported pipe_slice_buffer_placement_type");
255          } break;
256       }
257 
258       currentSliceEntry.SliceBytesInBuffer = picture_vp9->slice_parameter.slice_data_size[sliceIdx];
259       currentSliceEntry.BSNALunitDataLocation = picture_vp9->slice_parameter.slice_data_offset[sliceIdx];
260 
261       debug_printf("[d3d12_video_decoder_vp9] Detected slice index %" PRIu32 " with SliceBytesInBuffer %d - BSNALunitDataLocation %d - wBadSliceChopping: %" PRIu16
262                   " for frame with "
263                   "fenceValue: %d\n",
264                   sliceIdx,
265                   currentSliceEntry.SliceBytesInBuffer,
266                   currentSliceEntry.BSNALunitDataLocation,
267                   currentSliceEntry.wBadSliceChopping,
268                   pD3D12Dec->m_fenceValue);
269 
270       memcpy(pData, &currentSliceEntry, sizeof(DXVA_Slice_VPx_Short));
271       pData += sizeof(DXVA_Slice_VPx_Short);
272    }
273    assert(vecOutSliceControlBuffers.size() == TotalSlicesDXVAArrayByteSize);
274 }
275 
276 DXVA_PicParams_VP9
d3d12_video_decoder_dxva_picparams_from_pipe_picparams_vp9(struct d3d12_video_decoder * pD3D12Dec,pipe_video_profile profile,pipe_vp9_picture_desc * pipe_vp9)277 d3d12_video_decoder_dxva_picparams_from_pipe_picparams_vp9(
278    struct d3d12_video_decoder *pD3D12Dec,
279    pipe_video_profile profile,
280    pipe_vp9_picture_desc *pipe_vp9)
281 {
282    uint32_t frameNum = pD3D12Dec->m_fenceValue;
283    DXVA_PicParams_VP9 dxvaStructure;
284    memset(&dxvaStructure, 0, sizeof(dxvaStructure));
285 
286    dxvaStructure.profile = pipe_vp9->picture_parameter.profile;
287    dxvaStructure.wFormatAndPictureInfoFlags = ((pipe_vp9->picture_parameter.pic_fields.frame_type != 0)   <<  0) |
288                                     ((pipe_vp9->picture_parameter.pic_fields.show_frame != 0)             <<  1) |
289                                     (pipe_vp9->picture_parameter.pic_fields.error_resilient_mode          <<  2) |
290                                     (pipe_vp9->picture_parameter.pic_fields.subsampling_x                 <<  3) |
291                                     (pipe_vp9->picture_parameter.pic_fields.subsampling_y                 <<  4) |
292                                     (0                                                                    <<  5) |
293                                     (pipe_vp9->picture_parameter.pic_fields.refresh_frame_context         <<  6) |
294                                     (pipe_vp9->picture_parameter.pic_fields.frame_parallel_decoding_mode  <<  7) |
295                                     (pipe_vp9->picture_parameter.pic_fields.intra_only                    <<  8) |
296                                     (pipe_vp9->picture_parameter.pic_fields.frame_context_idx             <<  9) |
297                                     (pipe_vp9->picture_parameter.pic_fields.reset_frame_context           << 11) |
298                                     ((pipe_vp9->picture_parameter.pic_fields.allow_high_precision_mv)     << 13) |
299                                     (0                                                                    << 14);
300 
301    dxvaStructure.width  = pipe_vp9->picture_parameter.frame_width;
302    dxvaStructure.height = pipe_vp9->picture_parameter.frame_height;
303    dxvaStructure.BitDepthMinus8Luma   = pipe_vp9->picture_parameter.bit_depth - 8;
304    dxvaStructure.BitDepthMinus8Chroma = pipe_vp9->picture_parameter.bit_depth - 8;
305    dxvaStructure.interp_filter = pipe_vp9->picture_parameter.pic_fields.mcomp_filter_type;
306    dxvaStructure.Reserved8Bits = 0;
307    for (uint32_t i = 0; i < 8; i++) {
308       if (pipe_vp9->ref[i]) {
309          dxvaStructure.ref_frame_coded_width[i]  = pipe_vp9->ref[i]->width;
310          dxvaStructure.ref_frame_coded_height[i] = pipe_vp9->ref[i]->height;
311       } else
312          dxvaStructure.ref_frame_map[i].bPicEntry = DXVA_VP9_INVALID_PICTURE_ENTRY;
313    }
314 
315    /* DXVA spec The enums and indices for ref_frame_sign_bias[] are defined */
316    const uint8_t signbias_last_index = 1;
317    const uint8_t signbias_golden_index = 2;
318    const uint8_t signbias_alt_index = 3;
319 
320    /* AssociatedFlag When Index7Bits does not contain an index to a valid uncompressed surface, the value shall be set to 127, to indicate that the index is invalid. */
321    memset(&dxvaStructure.frame_refs[0], DXVA_VP9_INVALID_PICTURE_ENTRY, sizeof(dxvaStructure.frame_refs));
322 
323    if (pipe_vp9->ref[pipe_vp9->picture_parameter.pic_fields.last_ref_frame]) {
324       /* AssociatedFlag When Index7Bits does not contain an index to a valid uncompressed surface, the value shall be set to 127, to indicate that the index is invalid. */
325       /* Mark AssociatedFlag = 0 so last_ref_frame will be replaced with the correct reference index in d3d12_video_decoder_refresh_dpb_active_references_vp9 */
326       dxvaStructure.frame_refs[0].AssociatedFlag = 0;
327       dxvaStructure.frame_refs[0].Index7Bits = pipe_vp9->picture_parameter.pic_fields.last_ref_frame;
328       dxvaStructure.ref_frame_sign_bias[signbias_last_index] = pipe_vp9->picture_parameter.pic_fields.last_ref_frame_sign_bias;
329    }
330 
331    if (pipe_vp9->ref[pipe_vp9->picture_parameter.pic_fields.golden_ref_frame]) {
332       /* AssociatedFlag When Index7Bits does not contain an index to a valid uncompressed surface, the value shall be set to 127, to indicate that the index is invalid. */
333       /* Mark AssociatedFlag = 0 so golden_ref_frame will be replaced with the correct reference index in d3d12_video_decoder_refresh_dpb_active_references_vp9 */
334       dxvaStructure.frame_refs[1].AssociatedFlag = 0;
335       dxvaStructure.frame_refs[1].Index7Bits = pipe_vp9->picture_parameter.pic_fields.golden_ref_frame;
336       dxvaStructure.ref_frame_sign_bias[signbias_golden_index] = pipe_vp9->picture_parameter.pic_fields.golden_ref_frame_sign_bias;
337    }
338 
339   if (pipe_vp9->ref[pipe_vp9->picture_parameter.pic_fields.alt_ref_frame]) {
340       /* AssociatedFlag When Index7Bits does not contain an index to a valid uncompressed surface, the value shall be set to 127, to indicate that the index is invalid. */
341       /* Mark AssociatedFlag = 0 so alt_ref_frame will be replaced with the correct reference index in d3d12_video_decoder_refresh_dpb_active_references_vp9 */
342       dxvaStructure.frame_refs[2].AssociatedFlag = 0;
343       dxvaStructure.frame_refs[2].Index7Bits = pipe_vp9->picture_parameter.pic_fields.alt_ref_frame;
344       dxvaStructure.ref_frame_sign_bias[signbias_alt_index] = pipe_vp9->picture_parameter.pic_fields.alt_ref_frame_sign_bias;
345    }
346 
347    dxvaStructure.filter_level    = pipe_vp9->picture_parameter.filter_level;
348    dxvaStructure.sharpness_level = pipe_vp9->picture_parameter.sharpness_level;
349 
350    bool use_prev_in_find_mv_refs =
351       !pipe_vp9->picture_parameter.pic_fields.error_resilient_mode &&
352       !(pipe_vp9->picture_parameter.pic_fields.frame_type == 0 /*KEY_FRAME*/ || pipe_vp9->picture_parameter.pic_fields.intra_only) &&
353       pipe_vp9->picture_parameter.pic_fields.prev_show_frame &&
354       pipe_vp9->picture_parameter.frame_width == pipe_vp9->picture_parameter.prev_frame_width &&
355       pipe_vp9->picture_parameter.frame_height == pipe_vp9->picture_parameter.prev_frame_height;
356 
357    dxvaStructure.wControlInfoFlags = (pipe_vp9->picture_parameter.mode_ref_delta_enabled  << 0) |
358                            (pipe_vp9->picture_parameter.mode_ref_delta_update             << 1) |
359                            (use_prev_in_find_mv_refs                                      << 2) |
360                            (0                                                             << 3);
361 
362    for (uint32_t i = 0; i < 4; i++)
363       dxvaStructure.ref_deltas[i] = pipe_vp9->picture_parameter.ref_deltas[i];
364 
365    for (uint32_t i = 0; i < 2; i++)
366       dxvaStructure.mode_deltas[i] = pipe_vp9->picture_parameter.mode_deltas[i];
367 
368    dxvaStructure.base_qindex   = pipe_vp9->picture_parameter.base_qindex;
369    dxvaStructure.y_dc_delta_q  = pipe_vp9->picture_parameter.y_dc_delta_q;
370    dxvaStructure.uv_dc_delta_q = pipe_vp9->picture_parameter.uv_ac_delta_q;
371    dxvaStructure.uv_ac_delta_q = pipe_vp9->picture_parameter.uv_dc_delta_q;
372 
373    /* segmentation data */
374    dxvaStructure.stVP9Segments.wSegmentInfoFlags = (pipe_vp9->picture_parameter.pic_fields.segmentation_enabled   << 0) |
375                                        (pipe_vp9->picture_parameter.pic_fields.segmentation_update_map            << 1) |
376                                        (pipe_vp9->picture_parameter.pic_fields.segmentation_temporal_update       << 2) |
377                                        (pipe_vp9->picture_parameter.abs_delta                                     << 3) |
378                                        (0                                                                         << 4);
379 
380    for (uint32_t i = 0; i < 7; i++)
381       dxvaStructure.stVP9Segments.tree_probs[i] = pipe_vp9->picture_parameter.mb_segment_tree_probs[i];
382 
383    if (pipe_vp9->picture_parameter.pic_fields.segmentation_temporal_update)
384       for (uint32_t i = 0; i < 3; i++)
385          dxvaStructure.stVP9Segments.pred_probs[i] = pipe_vp9->picture_parameter.segment_pred_probs[i];
386    else
387       memset(dxvaStructure.stVP9Segments.pred_probs, 255, sizeof(dxvaStructure.stVP9Segments.pred_probs));
388 
389    for (uint32_t i = 0; i < 8; i++) {
390       dxvaStructure.stVP9Segments.feature_mask[i] = (pipe_vp9->slice_parameter.seg_param[i].alt_quant_enabled              << 0) |
391                                           (pipe_vp9->slice_parameter.seg_param[i].alt_lf_enabled                           << 1) |
392                                           (pipe_vp9->slice_parameter.seg_param[i].segment_flags.segment_reference_enabled  << 2) |
393                                           (pipe_vp9->slice_parameter.seg_param[i].segment_flags.segment_reference_skipped  << 3);
394 
395       dxvaStructure.stVP9Segments.feature_data[i][0] = pipe_vp9->slice_parameter.seg_param[i].alt_quant;
396       dxvaStructure.stVP9Segments.feature_data[i][1] = pipe_vp9->slice_parameter.seg_param[i].alt_lf;
397       dxvaStructure.stVP9Segments.feature_data[i][2] = pipe_vp9->slice_parameter.seg_param[i].segment_flags.segment_reference;
398       dxvaStructure.stVP9Segments.feature_data[i][3] = 0;
399    }
400 
401    dxvaStructure.log2_tile_cols = pipe_vp9->picture_parameter.log2_tile_columns;
402    dxvaStructure.log2_tile_rows = pipe_vp9->picture_parameter.log2_tile_rows;
403    dxvaStructure.uncompressed_header_size_byte_aligned = pipe_vp9->picture_parameter.frame_header_length_in_bytes;
404    dxvaStructure.first_partition_size = pipe_vp9->picture_parameter.first_partition_size;
405    dxvaStructure.StatusReportFeedbackNumber = frameNum;
406    assert(dxvaStructure.StatusReportFeedbackNumber > 0);
407    return dxvaStructure;
408 }
409