xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/hw/vdbox/mhw_vdbox_mfx_generic.h (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2017-2021, Intel 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 shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 
23 //! \file     mhw_vdbox_mfx_generic.h
24 //! \brief    MHW interface for constructing MFX commands for the Vdbox engine
25 //! \details  Impelements shared Vdbox MFX command construction functions across all platforms as templates
26 //!
27 
28 #ifndef _MHW_VDBOX_MFX_GENERIC_H_
29 #define _MHW_VDBOX_MFX_GENERIC_H_
30 
31 #include "mhw_vdbox_mfx_interface.h"
32 #include "mhw_cp_interface.h"
33 
34 //!  MHW Vdbox Mfx generic interface
35 /*!
36 This class defines the shared Mfx command construction functions across all platforms as templates
37 */
38 template <class TMfxCmds, class TMiCmds>
39 class MhwVdboxMfxInterfaceGeneric : public MhwVdboxMfxInterface
40 {
41 protected:
42     //!
43     //! \brief    Constructor
44     //!
MhwVdboxMfxInterfaceGeneric(PMOS_INTERFACE osInterface,MhwMiInterface * miInterface,MhwCpInterface * cpInterface,bool decodeInUse)45     MhwVdboxMfxInterfaceGeneric(
46         PMOS_INTERFACE osInterface,
47         MhwMiInterface *miInterface,
48         MhwCpInterface *cpInterface,
49         bool decodeInUse) :
50         MhwVdboxMfxInterface(osInterface, miInterface, cpInterface, decodeInUse)
51     {
52         MHW_FUNCTION_ENTER;
53     }
54 
55     //!
56     //! \brief   Destructor
57     //!
~MhwVdboxMfxInterfaceGeneric()58     virtual ~MhwVdboxMfxInterfaceGeneric() {}
59 
AddMfdAvcPicidCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_PIC_ID_PARAMS params)60     MOS_STATUS AddMfdAvcPicidCmd(
61         PMOS_COMMAND_BUFFER cmdBuffer,
62         PMHW_VDBOX_PIC_ID_PARAMS params)
63     {
64         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
65 
66         MHW_FUNCTION_ENTER;
67 
68         MHW_MI_CHK_NULL(m_osInterface);
69         MHW_MI_CHK_NULL(cmdBuffer);
70         MHW_MI_CHK_NULL(params);
71         MHW_MI_CHK_NULL(params->pAvcPicIdx);
72 
73         typename TMfxCmds::MFD_AVC_PICID_STATE_CMD cmd;
74 
75         cmd.DW1.PictureidRemappingDisable = 1;
76         if (params->bPicIdRemappingInUse)
77         {
78             uint32_t j = 0;
79             cmd.DW1.PictureidRemappingDisable = 0;
80 
81             for (auto i = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++)
82             {
83                 cmd.Pictureidlist1616Bits[i] = avcPicidDefault;
84 
85                 if (params->pAvcPicIdx[j++].bValid)
86                 {
87                     cmd.Pictureidlist1616Bits[i] = (cmd.Pictureidlist1616Bits[i] & 0xffff0000) | params->pAvcPicIdx[j - 1].ucPicIdx;
88                 }
89 
90                 if (params->pAvcPicIdx[j++].bValid)
91                 {
92                     cmd.Pictureidlist1616Bits[i] = (cmd.Pictureidlist1616Bits[i] & 0x0000ffff) | (params->pAvcPicIdx[j - 1].ucPicIdx << 16);
93                 }
94             }
95         }
96         else
97         {
98             for (auto i = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++)
99             {
100                 cmd.Pictureidlist1616Bits[i] = avcPicidDisabled;
101             }
102         }
103 
104         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
105 
106         return eStatus;
107     }
108 
AddMfxQmCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_QM_PARAMS params)109     MOS_STATUS AddMfxQmCmd(
110         PMOS_COMMAND_BUFFER cmdBuffer,
111         PMHW_VDBOX_QM_PARAMS params)
112     {
113         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
114 
115         MHW_FUNCTION_ENTER;
116 
117         MHW_MI_CHK_NULL(m_osInterface);
118         MHW_MI_CHK_NULL(cmdBuffer);
119         MHW_MI_CHK_NULL(params);
120 
121         typename TMfxCmds::MFX_QM_STATE_CMD cmd;
122 
123         uint8_t* qMatrix = (uint8_t*)cmd.ForwardQuantizerMatrix;
124 
125         if (params->Standard == CODECHAL_AVC)
126         {
127             MHW_MI_CHK_NULL(params->pAvcIqMatrix);
128 
129             for (auto i = 0; i < 16; i++)
130             {
131                 cmd.ForwardQuantizerMatrix[i] = 0;
132             }
133 
134             cmd.DW1.Obj0.Avc = avcQmIntra4x4;
135             for (auto i = 0; i < 3; i++)
136             {
137                 for (auto ii = 0; ii < 16; ii++)
138                 {
139                     qMatrix[i * 16 + ii] = params->pAvcIqMatrix->List4x4[i][ii];
140                 }
141             }
142             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
143 
144             cmd.DW1.Obj0.Avc = avcQmInter4x4;
145             for (auto i = 3; i < 6; i++)
146             {
147                 for (auto ii = 0; ii < 16; ii++)
148                 {
149                     qMatrix[(i - 3) * 16 + ii] = params->pAvcIqMatrix->List4x4[i][ii];
150                 }
151             }
152             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
153 
154             cmd.DW1.Obj0.Avc = avcQmIntra8x8;
155             for (auto ii = 0; ii < 64; ii++)
156             {
157                 qMatrix[ii] = params->pAvcIqMatrix->List8x8[0][ii];
158             }
159             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
160 
161             cmd.DW1.Obj0.Avc = avcQmInter8x8;
162             for (auto ii = 0; ii < 64; ii++)
163             {
164                 qMatrix[ii] = params->pAvcIqMatrix->List8x8[1][ii];
165             }
166             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
167         }
168         else if (params->Standard == CODECHAL_MPEG2)
169         {
170             MHW_MI_CHK_NULL(params->pMpeg2IqMatrix);
171 
172             if (params->Mode == CODECHAL_ENCODE_MODE_MPEG2)
173             {
174                 cmd.DW1.Obj0.Avc = mpeg2QmIntra;
175                 if (params->pMpeg2IqMatrix->m_loadIntraQuantiserMatrix)
176                 {
177                     for (auto i = 0; i < 64; i++)
178                     {
179                         qMatrix[i] = (uint8_t)(params->pMpeg2IqMatrix->m_intraQuantiserMatrix[m_mpeg2QuantMatrixScan[i]]);
180                     }
181                 }
182                 else
183                 {
184                     for (auto i = 0; i < 64; i++)
185                     {
186                         qMatrix[i] = (uint8_t)(m_mpeg2DefaultIntraQuantizerMatrix[i]);
187                     }
188                 }
189                 MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
190 
191                 cmd.DW1.Obj0.Avc = mpeg2QmNonIntra;
192                 if (params->pMpeg2IqMatrix->m_loadNonIntraQuantiserMatrix)
193                 {
194                     for (auto i = 0; i < 64; i++)
195                     {
196                         qMatrix[i] = (uint8_t)(params->pMpeg2IqMatrix->m_nonIntraQuantiserMatrix[m_mpeg2QuantMatrixScan[i]]);
197                     }
198                 }
199                 else
200                 {
201                     for (auto i = 0; i < 64; i++)
202                     {
203                         qMatrix[i] = (uint8_t)(m_mpeg2DefaultNonIntraQuantizerMatrix[i]);
204                     }
205                 }
206                 MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
207             }
208             else
209             {
210                 cmd.DW1.Obj0.Avc = mpeg2QmIntra;
211                 if (params->pMpeg2IqMatrix->m_loadIntraQuantiserMatrix)
212                 {
213                     uint8_t *src = params->pMpeg2IqMatrix->m_intraQuantiserMatrix;
214                     for (auto i = 0; i < 64; i++)
215                     {
216                         qMatrix[i] = (uint8_t)(src[m_mpeg2QuantMatrixScan[i]]);
217                     }
218                 }
219                 else
220                 {
221                     for (auto i = 0; i < 64; i++)
222                     {
223                         qMatrix[i] = (uint8_t)(m_mpeg2DefaultIntraQuantizerMatrix[i]);
224                     }
225                 }
226 
227                 MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
228 
229                 cmd.DW1.Obj0.Avc = mpeg2QmNonIntra;
230                 if (params->pMpeg2IqMatrix->m_loadNonIntraQuantiserMatrix)
231                 {
232                     uint8_t *src = params->pMpeg2IqMatrix->m_nonIntraQuantiserMatrix;
233                     for (auto i = 0; i < 64; i++)
234                     {
235                         qMatrix[i] = (uint8_t)(src[m_mpeg2QuantMatrixScan[i]]);
236                     }
237                 }
238                 else
239                 {
240                     for (auto i = 0; i < 64; i++)
241                     {
242                         qMatrix[i] = (uint8_t)(m_mpeg2DefaultNonIntraQuantizerMatrix[i]);
243                     }
244                 }
245 
246                 MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
247             }
248         }
249         else if (params->Standard == CODECHAL_JPEG)
250         {
251             MHW_MI_CHK_NULL(params->pJpegQuantMatrix);
252             cmd.DW1.Obj0.Avc = params->pJpegQuantMatrix->m_jpegQMTableType[params->JpegQMTableSelector];
253 
254             if (params->bJpegQMRotation)
255             {
256                 for (auto i = 0; i < 8; i++)
257                 {
258                     for (auto ii = 0; ii < 8; ii++)
259                     {
260                         qMatrix[i + 8 * ii] = params->pJpegQuantMatrix->m_quantMatrix[params->JpegQMTableSelector][i * 8 + ii];
261                     }
262                 }
263             }
264             else
265             {
266                 for (auto i = 0; i < 64; i++)
267                 {
268                     qMatrix[i] = params->pJpegQuantMatrix->m_quantMatrix[params->JpegQMTableSelector][i];
269                 }
270             }
271 
272             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
273         }
274         else
275         {
276             eStatus = MOS_STATUS_INVALID_PARAMETER;
277         }
278 
279         return eStatus;
280     }
281 
AddMfxFqmCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_QM_PARAMS params)282     MOS_STATUS AddMfxFqmCmd(
283         PMOS_COMMAND_BUFFER cmdBuffer,
284         PMHW_VDBOX_QM_PARAMS params)
285     {
286         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
287 
288         MHW_FUNCTION_ENTER;
289 
290         MHW_MI_CHK_NULL(m_osInterface);
291         MHW_MI_CHK_NULL(cmdBuffer);
292         MHW_MI_CHK_NULL(params);
293 
294         typename TMfxCmds::MFX_FQM_STATE_CMD cmd;
295 
296         if (params->Standard == CODECHAL_AVC)
297         {
298             MHW_MI_CHK_NULL(params->pAvcIqMatrix);
299 
300             PMHW_VDBOX_AVC_QM_PARAMS iqMatrix = params->pAvcIqMatrix;
301             uint16_t *fqMatrix = (uint16_t*)cmd.ForwardQuantizerMatrix;
302 
303             for (auto i = 0; i < 32; i++)
304             {
305                 cmd.ForwardQuantizerMatrix[i] = 0;
306             }
307 
308             cmd.DW1.Obj0.Avc = avcQmIntra4x4;
309             for (auto i = 0; i < 3; i++)
310             {
311                 for (auto ii = 0; ii < 16; ii++)
312                 {
313                     fqMatrix[i * 16 + ii] =
314                         GetReciprocalScalingValue(iqMatrix->List4x4[i][m_columnScan4x4[ii]]);
315                 }
316             }
317             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
318 
319             cmd.DW1.Obj0.Avc = avcQmInter4x4;
320             for (auto i = 0; i < 3; i++)
321             {
322                 for (auto ii = 0; ii < 16; ii++)
323                 {
324                     fqMatrix[i * 16 + ii] =
325                         GetReciprocalScalingValue(iqMatrix->List4x4[i + 3][m_columnScan4x4[ii]]);
326                 }
327             }
328             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
329 
330             cmd.DW1.Obj0.Avc = avcQmIntra8x8;
331             for (auto i = 0; i < 64; i++)
332             {
333                 fqMatrix[i] = GetReciprocalScalingValue(iqMatrix->List8x8[0][m_columnScan8x8[i]]);
334             }
335             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
336 
337             cmd.DW1.Obj0.Avc = avcQmInter8x8;
338             for (auto i = 0; i < 64; i++)
339             {
340                 fqMatrix[i] = GetReciprocalScalingValue(iqMatrix->List8x8[1][m_columnScan8x8[i]]);
341             }
342             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
343         }
344         else if (params->Standard == CODECHAL_MPEG2)
345         {
346             uint16_t *fqMatrix = (uint16_t*)cmd.ForwardQuantizerMatrix;
347 
348             cmd.DW1.Obj0.Avc = mpeg2QmIntra;
349             if (params->pMpeg2IqMatrix->m_loadIntraQuantiserMatrix)
350             {
351                 for (auto i = 0; i < 64; i++)
352                 {
353                     fqMatrix[i] = GetReciprocalScalingValue(
354                         (uint8_t)(params->pMpeg2IqMatrix->m_intraQuantiserMatrix[m_mpeg2QuantMatrixScan[m_columnScan8x8[i]]]));
355                 }
356             }
357             else
358             {
359                 for (auto i = 0; i < 64; i++)
360                 {
361                     fqMatrix[i] = GetReciprocalScalingValue(
362                         (uint8_t)m_mpeg2DefaultIntraQuantizerMatrix[m_columnScan8x8[i]]);
363                 }
364             }
365             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
366 
367             cmd.DW1.Obj0.Avc = mpeg2QmNonIntra;
368             if (params->pMpeg2IqMatrix->m_loadNonIntraQuantiserMatrix)
369             {
370                 for (auto i = 0; i < 64; i++)
371                 {
372                     fqMatrix[i] = GetReciprocalScalingValue(
373                         (uint8_t)(params->pMpeg2IqMatrix->m_nonIntraQuantiserMatrix[m_mpeg2QuantMatrixScan[m_columnScan8x8[i]]]));
374                 }
375             }
376             else
377             {
378                 for (auto i = 0; i < 64; i++)
379                 {
380                     fqMatrix[i] = GetReciprocalScalingValue(
381                         (uint8_t)m_mpeg2DefaultNonIntraQuantizerMatrix[m_columnScan8x8[i]]);
382                 }
383             }
384             MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
385         }
386 
387         return eStatus;
388     }
389 
AddMfxAvcRefIdx(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_AVC_REF_IDX_PARAMS params)390     MOS_STATUS AddMfxAvcRefIdx(
391         PMOS_COMMAND_BUFFER cmdBuffer,
392         PMHW_BATCH_BUFFER batchBuffer,
393         PMHW_VDBOX_AVC_REF_IDX_PARAMS params)
394     {
395         MHW_FUNCTION_ENTER;
396 
397         MHW_MI_CHK_NULL(params);
398 
399         if (cmdBuffer == nullptr && batchBuffer == nullptr)
400         {
401             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
402             return MOS_STATUS_INVALID_PARAMETER;
403         }
404 
405         typename TMfxCmds::MFX_AVC_REF_IDX_STATE_CMD cmd;
406 
407         // Need to add an empty MFX_AVC_REF_IDX_STATE_CMD for dummy reference on I-Frame
408         if (!params->bDummyReference)
409         {
410             auto uiList = params->uiList;
411 
412             cmd.DW1.RefpiclistSelect = uiList;
413 
414             CODEC_REF_LIST  **avcRefList        = (CODEC_REF_LIST **)params->avcRefList;
415             AvcRefListWrite *cmdAvcRefListWrite = (AvcRefListWrite *)&(cmd.ReferenceListEntry);
416 
417             uint8_t picIDOneOnOneMapping = 0;
418             if (params->bVdencInUse && uiList == LIST_1)
419             {
420                 picIDOneOnOneMapping += params->uiNumRefForList[LIST_0] << 1;
421             }
422 
423             for (uint32_t i = 0; i < params->uiNumRefForList[uiList]; i++)
424             {
425                 uint8_t idx = params->RefPicList[uiList][i].FrameIdx;
426 
427                 if (!params->bIntelEntrypointInUse)
428                 {
429                     if (idx >= CODEC_MAX_NUM_REF_FRAME)
430                     {
431                         MHW_ASSERT(false); // Idx must be within 0 to 15
432                         idx = 0;
433                     }
434 
435                     idx = params->pAvcPicIdx[idx].ucPicIdx;
436                 }
437 
438                 uint8_t picID = params->bPicIdRemappingInUse ?
439                     params->RefPicList[uiList][i].FrameIdx : avcRefList[idx]->ucFrameId;
440 
441                 // When one on one ref idx mapping is enabled, program picID count from 0, 2 ...
442                 if (params->oneOnOneMapping)
443                 {
444                     picID = picIDOneOnOneMapping;
445                     picIDOneOnOneMapping += 2;
446                 }
447                 cmdAvcRefListWrite->UC[i].frameStoreID = picID;
448                 cmdAvcRefListWrite->UC[i].bottomField =
449                     CodecHal_PictureIsBottomField(params->RefPicList[uiList][i]);
450                 cmdAvcRefListWrite->UC[i].fieldPicFlag =
451                     CodecHal_PictureIsField(params->RefPicList[uiList][i]);
452                 cmdAvcRefListWrite->UC[i].longTermFlag =
453                     CodecHal_PictureIsLongTermRef(avcRefList[idx]->RefPic);
454                 cmdAvcRefListWrite->UC[i].nonExisting = 0;
455             }
456 
457             for (auto i = params->uiNumRefForList[uiList]; i < 32; i++)
458             {
459                 cmdAvcRefListWrite->UC[i].value = 0x80;
460             }
461         }
462 
463         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
464 
465         return MOS_STATUS_SUCCESS;
466     }
467 
AddMfxDecodeAvcWeightOffset(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params)468     MOS_STATUS AddMfxDecodeAvcWeightOffset(
469         PMOS_COMMAND_BUFFER cmdBuffer,
470         PMHW_BATCH_BUFFER batchBuffer,
471         PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params)
472     {
473         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
474 
475         MHW_FUNCTION_ENTER;
476 
477         MHW_MI_CHK_NULL(params);
478 
479         if (cmdBuffer == nullptr && batchBuffer == nullptr)
480         {
481             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
482             return MOS_STATUS_INVALID_PARAMETER;
483         }
484 
485         typename TMfxCmds::MFX_AVC_WEIGHTOFFSET_STATE_CMD cmd;
486 
487         cmd.DW1.WeightAndOffsetSelect = params->uiList;
488 
489         //The correct explicit calculation (like in Cantiga)
490         for (auto i = 0; i < CODEC_MAX_NUM_REF_FIELD; i++)
491         {
492             cmd.Weightoffset[3 * i] = params->Weights[params->uiList][i][0][0] & 0xFFFF; // Y weight
493             cmd.Weightoffset[3 * i] |= (params->Weights[params->uiList][i][0][1] & 0xFFFF) << 16; // Y offset
494             cmd.Weightoffset[3 * i + 1] = params->Weights[params->uiList][i][1][0] & 0xFFFF; // Cb weight
495             cmd.Weightoffset[3 * i + 1] |= (params->Weights[params->uiList][i][1][1] & 0xFFFF) << 16; // Cb offset
496             cmd.Weightoffset[3 * i + 2] = params->Weights[params->uiList][i][2][0] & 0xFFFF; // Cr weight
497             cmd.Weightoffset[3 * i + 2] |= (params->Weights[params->uiList][i][2][1] & 0xFFFF) << 16; // Cr offset
498         }
499 
500         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
501 
502         return eStatus;
503     }
504 
AddMfxEncodeAvcWeightOffset(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params)505     MOS_STATUS AddMfxEncodeAvcWeightOffset(
506         PMOS_COMMAND_BUFFER cmdBuffer,
507         PMHW_BATCH_BUFFER batchBuffer,
508         PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params)
509     {
510         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
511 
512         MHW_FUNCTION_ENTER;
513 
514         MHW_MI_CHK_NULL(params);
515 
516         if (cmdBuffer == nullptr && batchBuffer == nullptr)
517         {
518             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
519             return MOS_STATUS_INVALID_PARAMETER;
520         }
521 
522         typename TMfxCmds::MFX_AVC_WEIGHTOFFSET_STATE_CMD cmd;
523 
524         cmd.DW1.WeightAndOffsetSelect = params->uiList;
525 
526         for (uint32_t i = 0; i < params->uiNumRefForList; i++)
527         {
528             if (params->uiLumaWeightFlag & (1 << i))
529             {
530                 cmd.Weightoffset[3 * i] = params->Weights[params->uiList][i][0][0] & 0xFFFF; // Y weight
531                 cmd.Weightoffset[3 * i] |= (params->Weights[params->uiList][i][0][1] & 0xFFFF) << 16; // Y offset
532             }
533             else
534             {
535                 cmd.Weightoffset[3 * i] = 1 << (params->uiLumaLogWeightDenom); // Y weight
536                 cmd.Weightoffset[3 * i] = cmd.Weightoffset[3 * i] | (0 << 16); // Y offset
537             }
538 
539             if (params->uiChromaWeightFlag & (1 << i))
540             {
541                 cmd.Weightoffset[3 * i + 1] = params->Weights[params->uiList][i][1][0] & 0xFFFF; // Cb weight
542                 cmd.Weightoffset[3 * i + 1] |= (params->Weights[params->uiList][i][1][1] & 0xFFFF) << 16; // Cb offset
543                 cmd.Weightoffset[3 * i + 2] = params->Weights[params->uiList][i][2][0] & 0xFFFF; // Cr weight
544                 cmd.Weightoffset[3 * i + 2] |= (params->Weights[params->uiList][i][2][1] & 0xFFFF) << 16; // Cr offset
545             }
546             else
547             {
548                 cmd.Weightoffset[3 * i + 1] = 1 << (params->uiChromaLogWeightDenom); // Cb  weight
549                 cmd.Weightoffset[3 * i + 1] = cmd.Weightoffset[3 * i + 1] | (0 << 16); // Cb offset
550                 cmd.Weightoffset[3 * i + 2] = 1 << (params->uiChromaLogWeightDenom); // Cr  weight
551                 cmd.Weightoffset[3 * i + 2] = cmd.Weightoffset[3 * i + 2] | (0 << 16); // Cr offset
552             }
553         }
554 
555         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
556 
557         return eStatus;
558     }
559 
AddMfxDecodeAvcSlice(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_AVC_SLICE_STATE avcSliceState)560     MOS_STATUS AddMfxDecodeAvcSlice(
561         PMOS_COMMAND_BUFFER cmdBuffer,
562         PMHW_BATCH_BUFFER batchBuffer,
563         PMHW_VDBOX_AVC_SLICE_STATE avcSliceState)
564     {
565         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
566 
567         MHW_FUNCTION_ENTER;
568 
569         MHW_MI_CHK_NULL(avcSliceState);
570         MHW_MI_CHK_NULL(avcSliceState->pAvcPicParams);
571         MHW_MI_CHK_NULL(avcSliceState->pAvcSliceParams);
572 
573         if (cmdBuffer == nullptr && batchBuffer == nullptr)
574         {
575             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
576             return MOS_STATUS_INVALID_PARAMETER;
577         }
578 
579         auto picParams = avcSliceState->pAvcPicParams;
580         uint32_t mbaffMultiplier = 1;
581         if (picParams->seq_fields.mb_adaptive_frame_field_flag &&
582             !picParams->pic_fields.field_pic_flag)
583         {
584             mbaffMultiplier++;
585         }
586 
587         uint16_t frameFieldHeightInMb = 0;
588         CodecHal_GetFrameFieldHeightInMb(
589             picParams->CurrPic,
590             picParams->pic_height_in_mbs_minus1 + 1,
591             frameFieldHeightInMb);
592 
593         auto sliceParams = avcSliceState->pAvcSliceParams;
594         typename TMfxCmds::MFX_AVC_SLICE_STATE_CMD cmd;
595 
596         // Set MFX_AVC_SLICE_STATE_CMD
597         cmd.DW1.SliceType = m_AvcBsdSliceType[sliceParams->slice_type];
598         cmd.DW2.Log2WeightDenomChroma = sliceParams->chroma_log2_weight_denom;
599         cmd.DW2.Log2WeightDenomLuma = sliceParams->luma_log2_weight_denom;
600         cmd.DW3.WeightedPredictionIndicator = 0;
601         cmd.DW3.DisableDeblockingFilterIndicator = avcSliceState->ucDisableDeblockingFilterIdc;
602         cmd.DW3.CabacInitIdc10 = sliceParams->cabac_init_idc;
603         cmd.DW3.SliceQuantizationParameter = 26 + picParams->pic_init_qp_minus26 + sliceParams->slice_qp_delta;
604         cmd.DW3.SliceBetaOffsetDiv2 = avcSliceState->ucSliceBetaOffsetDiv2;
605         cmd.DW3.SliceAlphaC0OffsetDiv2 = avcSliceState->ucSliceAlphaC0OffsetDiv2;
606 
607         auto widthInMb = picParams->pic_width_in_mbs_minus1 + 1;
608         cmd.DW4.SliceStartMbNum = sliceParams->first_mb_in_slice * mbaffMultiplier;
609         cmd.DW4.SliceVerticalPosition = (sliceParams->first_mb_in_slice / widthInMb) * mbaffMultiplier;
610         cmd.DW4.SliceHorizontalPosition = sliceParams->first_mb_in_slice % widthInMb;
611 
612         if (avcSliceState->bLastSlice)
613         {
614             cmd.DW5.NextSliceVerticalPosition = frameFieldHeightInMb;
615             cmd.DW5.NextSliceHorizontalPosition = 0;
616         }
617         else
618         {
619             cmd.DW5.NextSliceVerticalPosition = (sliceParams->first_mb_in_next_slice / widthInMb) * mbaffMultiplier;
620             cmd.DW5.NextSliceHorizontalPosition = sliceParams->first_mb_in_next_slice % widthInMb;
621         }
622 
623         cmd.DW6.IsLastSlice = avcSliceState->bLastSlice;
624 
625         cmd.DW9.Roundintra = 5;
626         cmd.DW9.Roundintraenable = 1;
627         cmd.DW9.Roundinter = 2;
628 
629         if (IsAvcPSlice(sliceParams->slice_type))
630         {
631             cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1 + 1;
632             cmd.DW3.WeightedPredictionIndicator = picParams->pic_fields.weighted_pred_flag;
633         }
634         else if (IsAvcBSlice(sliceParams->slice_type))
635         {
636             cmd.DW2.NumberOfReferencePicturesInInterPredictionList1 = sliceParams->num_ref_idx_l1_active_minus1 + 1;
637             cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1 + 1;
638             cmd.DW3.WeightedPredictionIndicator = picParams->pic_fields.weighted_bipred_idc;
639             cmd.DW3.DirectPredictionType = sliceParams->direct_spatial_mv_pred_flag;
640 
641             // Set MFX_AVC_WEIGHTOFFSET_STATE_CMD_G6
642             if (picParams->pic_fields.weighted_bipred_idc != 1)
643             {
644                 // luma/chroma_log2_weight_denoms need to be set to default value in the case of implicit mode
645                 cmd.DW2.Log2WeightDenomChroma = m_log2WeightDenomDefault;
646                 cmd.DW2.Log2WeightDenomLuma = m_log2WeightDenomDefault;
647             }
648         }
649 
650         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
651 
652         return eStatus;
653     }
654 
AddMfxEncodeAvcSlice(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_AVC_SLICE_STATE avcSliceState)655     MOS_STATUS AddMfxEncodeAvcSlice(
656         PMOS_COMMAND_BUFFER cmdBuffer,
657         PMHW_BATCH_BUFFER batchBuffer,
658         PMHW_VDBOX_AVC_SLICE_STATE avcSliceState)
659     {
660         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
661 
662         MHW_FUNCTION_ENTER;
663 
664         MHW_MI_CHK_NULL(avcSliceState);
665         MHW_MI_CHK_NULL(avcSliceState->pEncodeAvcSeqParams);
666         MHW_MI_CHK_NULL(avcSliceState->pEncodeAvcPicParams);
667         MHW_MI_CHK_NULL(avcSliceState->pEncodeAvcSliceParams);
668 
669         if (cmdBuffer == nullptr && batchBuffer == nullptr)
670         {
671             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
672             return MOS_STATUS_INVALID_PARAMETER;
673         }
674 
675         auto seqParams = avcSliceState->pEncodeAvcSeqParams;
676         auto sliceParams = avcSliceState->pEncodeAvcSliceParams;
677         auto picParams = avcSliceState->pEncodeAvcPicParams;
678 
679         uint16_t widthInMb = seqParams->pic_width_in_mbs_minus1 + 1;
680         uint16_t frameFieldHeightInMb = avcSliceState->wFrameFieldHeightInMB;
681         bool mbaffFrameFlag = seqParams->mb_adaptive_frame_field_flag ? true : false;
682         uint32_t startMbNum = sliceParams->first_mb_in_slice * (1 + mbaffFrameFlag);
683 
684         typename TMfxCmds::MFX_AVC_SLICE_STATE_CMD cmd;
685 
686         //DW1
687         cmd.DW1.SliceType = Slice_Type[sliceParams->slice_type];
688         //DW2
689         cmd.DW2.Log2WeightDenomLuma = sliceParams->luma_log2_weight_denom;
690         cmd.DW2.Log2WeightDenomChroma = sliceParams->chroma_log2_weight_denom;
691         cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = 0;
692         cmd.DW2.NumberOfReferencePicturesInInterPredictionList1 = 0;
693         //DW3
694         cmd.DW3.SliceAlphaC0OffsetDiv2 = sliceParams->slice_alpha_c0_offset_div2;
695         cmd.DW3.SliceBetaOffsetDiv2 = sliceParams->slice_beta_offset_div2;
696         cmd.DW3.SliceQuantizationParameter = 26 + picParams->pic_init_qp_minus26 + sliceParams->slice_qp_delta;
697         cmd.DW3.CabacInitIdc10 = sliceParams->cabac_init_idc;
698         cmd.DW3.DisableDeblockingFilterIndicator = sliceParams->disable_deblocking_filter_idc;
699         cmd.DW3.DirectPredictionType =
700             IsAvcBSlice(sliceParams->slice_type) ? sliceParams->direct_spatial_mv_pred_flag : 0;
701         cmd.DW3.WeightedPredictionIndicator = DEFAULT_WEIGHTED_INTER_PRED_MODE;
702         //DW4
703         cmd.DW4.SliceHorizontalPosition = startMbNum % widthInMb;
704         cmd.DW4.SliceVerticalPosition = startMbNum / widthInMb;
705         //DW5
706         cmd.DW5.NextSliceHorizontalPosition = (startMbNum + sliceParams->NumMbsForSlice) % widthInMb;
707         cmd.DW5.NextSliceVerticalPosition = (startMbNum + sliceParams->NumMbsForSlice) / widthInMb;
708         //DW6
709         cmd.DW6.StreamId10 = 0;
710         cmd.DW6.SliceId30 = sliceParams->slice_id;
711         cmd.DW6.Cabaczerowordinsertionenable = 1;
712         cmd.DW6.Emulationbytesliceinsertenable = 1;
713         cmd.DW6.IsLastSlice =
714             (startMbNum + sliceParams->NumMbsForSlice) >= (uint32_t)(widthInMb * frameFieldHeightInMb);
715         // Driver only programs 1st slice state, VDENC will detect the last slice
716         if (avcSliceState->bVdencInUse)
717         {
718             cmd.DW6.TailInsertionPresentInBitstream = avcSliceState->bVdencNoTailInsertion ?
719                 0 : (picParams->bLastPicInSeq || picParams->bLastPicInStream);
720         }
721         else
722         {
723             cmd.DW6.TailInsertionPresentInBitstream = (picParams->bLastPicInSeq || picParams->bLastPicInStream) && cmd.DW6.IsLastSlice;
724         }
725         cmd.DW6.SlicedataInsertionPresentInBitstream = 1;
726         cmd.DW6.HeaderInsertionPresentInBitstream = 1;
727         cmd.DW6.MbTypeSkipConversionDisable = 0;
728         cmd.DW6.MbTypeDirectConversionDisable = 0;
729         cmd.DW6.RateControlCounterEnable = (avcSliceState->bBrcEnabled && (!avcSliceState->bFirstPass));
730 
731         if (cmd.DW6.RateControlCounterEnable == true)
732         {
733             // These fields are valid only when RateControlCounterEnable = 1
734             cmd.DW6.RcPanicType = 1;    // CBP Panic
735             cmd.DW6.RcPanicEnable =
736                 (avcSliceState->bRCPanicEnable &&
737                 (seqParams->RateControlMethod != RATECONTROL_AVBR) &&
738                     (seqParams->RateControlMethod != RATECONTROL_IWD_VBR) &&
739                     (seqParams->RateControlMethod != RATECONTROL_ICQ) &&
740                     (seqParams->RateControlMethod != RATECONTROL_VCM) &&
741                     (seqParams->RateControlMethod != RATECONTROL_CQP) &&
742                     avcSliceState->bLastPass);    // Enable only in the last pass
743             cmd.DW6.RcStableTolerance = 0;
744             cmd.DW6.RcTriggleMode = 2;    // Loose Rate Control
745             cmd.DW6.Resetratecontrolcounter = !startMbNum;
746         }
747 
748         cmd.DW9.Roundinter = 2;
749 
750         if (IsAvcPSlice(sliceParams->slice_type))
751         {
752             cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1_from_DDI + 1;
753             cmd.DW3.WeightedPredictionIndicator = picParams->weighted_pred_flag;
754 
755             cmd.DW9.Roundinterenable = avcSliceState->bRoundingInterEnable;
756             cmd.DW9.Roundinter = avcSliceState->dwRoundingValue;
757         }
758         else if (IsAvcBSlice(sliceParams->slice_type))
759         {
760             cmd.DW2.NumberOfReferencePicturesInInterPredictionList1 = sliceParams->num_ref_idx_l1_active_minus1_from_DDI + 1;
761             cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1_from_DDI + 1;
762             cmd.DW3.WeightedPredictionIndicator = picParams->weighted_bipred_idc;
763             if (picParams->weighted_bipred_idc == IMPLICIT_WEIGHTED_INTER_PRED_MODE)
764             {
765                 if (avcSliceState->bVdencInUse)
766                 {
767                     cmd.DW2.Log2WeightDenomLuma = 0;
768                     cmd.DW2.Log2WeightDenomChroma = 0;
769                 }
770                 else
771                 {
772                     // SNB requirement
773                     cmd.DW2.Log2WeightDenomLuma = 5;
774                     cmd.DW2.Log2WeightDenomChroma = 5;
775                 }
776             }
777 
778             cmd.DW9.Roundinterenable = avcSliceState->bRoundingInterEnable;
779             cmd.DW9.Roundinter = avcSliceState->dwRoundingValue;
780         }
781 
782         cmd.DW9.Roundintra = avcSliceState->dwRoundingIntraValue;
783         cmd.DW9.Roundintraenable = 1;
784 
785         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
786 
787         return eStatus;
788     }
789 
AddMfdAvcDpbCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_AVC_DPB_PARAMS params)790     MOS_STATUS AddMfdAvcDpbCmd(
791         PMOS_COMMAND_BUFFER cmdBuffer,
792         PMHW_VDBOX_AVC_DPB_PARAMS params)
793     {
794         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
795 
796         MHW_FUNCTION_ENTER;
797 
798         MHW_MI_CHK_NULL(m_osInterface);
799         MHW_MI_CHK_NULL(cmdBuffer);
800         MHW_MI_CHK_NULL(params);
801         MHW_MI_CHK_NULL(params->pAvcPicParams);
802 
803         auto avcPicParams = params->pAvcPicParams;
804         auto currFrameIdx = avcPicParams->CurrPic.FrameIdx;
805         auto currAvcRefList = params->ppAvcRefList[currFrameIdx];
806 
807         int16_t refFrameOrder[CODEC_MAX_NUM_REF_FRAME] = { 0 };
808         uint32_t usedForRef = 0;
809         uint16_t nonExistingFrameFlags = 0;
810         uint16_t longTermFrame = 0;
811 
812         for (uint8_t i = 0; i < currAvcRefList->ucNumRef; i++)
813         {
814             auto picIdx = currAvcRefList->RefList[i].FrameIdx;
815             auto refAvcRefList = params->ppAvcRefList[picIdx];
816             bool longTermFrameFlag = (currAvcRefList->RefList[i].PicFlags == PICTURE_LONG_TERM_REFERENCE);
817 
818             uint8_t frameID = params->bPicIdRemappingInUse ? i : refAvcRefList->ucFrameId;
819             int16_t frameNum = refAvcRefList->sFrameNumber;
820 
821             refFrameOrder[frameID] = frameNum;
822             usedForRef |= (((currAvcRefList->uiUsedForReferenceFlags >> (i * 2)) & 3) << (frameID * 2));
823             nonExistingFrameFlags |= (((currAvcRefList->usNonExistingFrameFlags >> i) & 1) << frameID);
824             longTermFrame |= (((uint16_t)longTermFrameFlag) << frameID);
825         }
826 
827         typename TMfxCmds::MFD_AVC_DPB_STATE_CMD cmd;
828 
829         cmd.DW1.NonExistingframeFlag161Bit = nonExistingFrameFlags;
830         cmd.DW1.LongtermframeFlag161Bit = longTermFrame;
831         cmd.DW2.Value = usedForRef;
832 
833         for (auto i = 0, j = 0; i < 8; i++, j++)
834         {
835             cmd.Ltstframenumlist1616Bits[i] = (refFrameOrder[j++] & 0xFFFF); //FirstEntry
836             cmd.Ltstframenumlist1616Bits[i] = cmd.Ltstframenumlist1616Bits[i] | ((refFrameOrder[j] & 0xFFFF) << 16);    //SecondEntry
837         }
838 
839         auto mvcExtPicParams = params->pMvcExtPicParams;
840         if (mvcExtPicParams)
841         {
842             for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++, j++)
843             {
844                 cmd.Viewidlist1616Bits[i] = mvcExtPicParams->ViewIDList[j++];
845                 cmd.Viewidlist1616Bits[i] = cmd.Viewidlist1616Bits[i] | (mvcExtPicParams->ViewIDList[j] << 16);
846             }
847 
848             for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
849             {
850                 cmd.Vieworderlistl0168Bits[i] = GetViewOrder(params, j++, LIST_0); //FirstEntry
851                 cmd.Vieworderlistl0168Bits[i] = cmd.Vieworderlistl0168Bits[i] | (GetViewOrder(params, j++, LIST_0) << 8);  //SecondEntry
852                 cmd.Vieworderlistl0168Bits[i] = cmd.Vieworderlistl0168Bits[i] | (GetViewOrder(params, j++, LIST_0) << 16); //ThirdEntry
853                 cmd.Vieworderlistl0168Bits[i] = cmd.Vieworderlistl0168Bits[i] | (GetViewOrder(params, j, LIST_0) << 24);   //FourthEntry
854             }
855 
856             for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
857             {
858                 cmd.Vieworderlistl1168Bits[i] = GetViewOrder(params, j++, LIST_1); //FirstEntry
859                 cmd.Vieworderlistl1168Bits[i] = cmd.Vieworderlistl1168Bits[i] | (GetViewOrder(params, j++, LIST_1) << 8); //SecondEntry
860                 cmd.Vieworderlistl1168Bits[i] = cmd.Vieworderlistl1168Bits[i] | (GetViewOrder(params, j++, LIST_1) << 16); //ThirdEntry
861                 cmd.Vieworderlistl1168Bits[i] = cmd.Vieworderlistl1168Bits[i] | (GetViewOrder(params, j, LIST_1) << 24); //FourthEntry
862             }
863         }
864         else
865         {
866             for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++, j++)
867             {
868                 cmd.Viewidlist1616Bits[i] = 0;
869             }
870 
871             for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
872             {
873                 cmd.Vieworderlistl0168Bits[i] = 0; //FirstEntry
874             }
875 
876             for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
877             {
878                 cmd.Vieworderlistl1168Bits[i] = 0; //FirstEntry
879             }
880         }
881 
882         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
883 
884         return eStatus;
885     }
886 
AddMfxAvcImgBrcBuffer(PMOS_RESOURCE brcImgBuffer,PMHW_VDBOX_AVC_IMG_PARAMS params)887     MOS_STATUS AddMfxAvcImgBrcBuffer(
888         PMOS_RESOURCE brcImgBuffer,
889         PMHW_VDBOX_AVC_IMG_PARAMS params)
890     {
891         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
892 
893         MHW_FUNCTION_ENTER;
894 
895         MHW_MI_CHK_NULL(brcImgBuffer);
896         MHW_MI_CHK_NULL(params);
897 
898         MOS_LOCK_PARAMS lockFlags;
899         MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
900         lockFlags.WriteOnly = 1;
901         uint8_t *data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, brcImgBuffer, &lockFlags);
902         MHW_MI_CHK_NULL(data);
903 
904         MOS_COMMAND_BUFFER constructedCmdBuf;
905         constructedCmdBuf.pCmdBase = (uint32_t *)data;
906         constructedCmdBuf.pCmdPtr = (uint32_t *)data;
907         constructedCmdBuf.iOffset = 0;
908         constructedCmdBuf.iRemaining = BRC_IMG_STATE_SIZE_PER_PASS * m_numBrcPakPasses;
909 
910         MHW_MI_CHK_STATUS(AddMfxAvcImgCmd(&constructedCmdBuf, nullptr, params));
911 
912         typename TMfxCmds::MFX_AVC_IMG_STATE_CMD cmd = *(typename TMfxCmds::MFX_AVC_IMG_STATE_CMD *)data;
913 
914         for (uint32_t i = 0; i < m_numBrcPakPasses; i++)
915         {
916             if (i == 0)
917             {
918                 cmd.DW4.Mbstatenabled =
919                     cmd.DW5.Nonfirstpassflag = false;
920             }
921             else
922             {
923                 cmd.DW4.Mbstatenabled = true;
924                 cmd.DW5.IntraIntermbipcmflagForceipcmcontrolmask = true;
925                 cmd.DW5.Nonfirstpassflag = true;
926             }
927 
928             /* Setting the MbRateCtrlFlag to 0 so that the accumulative delta QP for consecutive passes is applied on top of
929             the macroblock QP values in inline data. This is changed because the streamout QP behavior is causing a mismatch
930             between the HW output and prototype output.*/
931             cmd.DW5.MbratectrlflagMbLevelRateControlEnablingFlag = false;
932             *(typename TMfxCmds::MFX_AVC_IMG_STATE_CMD *)data = cmd;
933 
934             /* add batch buffer end insertion flag */
935             uint32_t* insertion = (uint32_t*)(data + (TMfxCmds::MFX_AVC_IMG_STATE_CMD::byteSize));
936             *insertion = 0x05000000;
937 
938             data += BRC_IMG_STATE_SIZE_PER_PASS;
939         }
940 
941         return eStatus;
942     }
943 
AddMfxDecodeMpeg2PicCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_MPEG2_PIC_STATE params)944     MOS_STATUS AddMfxDecodeMpeg2PicCmd(
945         PMOS_COMMAND_BUFFER cmdBuffer,
946         PMHW_VDBOX_MPEG2_PIC_STATE params)
947     {
948         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
949 
950         MHW_FUNCTION_ENTER;
951 
952         MHW_MI_CHK_NULL(m_osInterface);
953         MHW_MI_CHK_NULL(cmdBuffer);
954         MHW_MI_CHK_NULL(params);
955         MHW_MI_CHK_NULL(params->pMpeg2PicParams);
956 
957         typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD cmd;
958         auto picParams = params->pMpeg2PicParams;
959 
960         cmd.DW1.ScanOrder = picParams->W0.m_scanOrder;
961         cmd.DW1.IntraVlcFormat = picParams->W0.m_intraVlcFormat;
962         cmd.DW1.QuantizerScaleType = picParams->W0.m_quantizerScaleType;
963         cmd.DW1.ConcealmentMotionVectorFlag = picParams->W0.m_concealmentMVFlag;
964         cmd.DW1.FramePredictionFrameDct = picParams->W0.m_frameDctPrediction;
965         cmd.DW1.TffTopFieldFirst = (CodecHal_PictureIsFrame(picParams->m_currPic)) ?
966             picParams->W0.m_topFieldFirst : picParams->m_topFieldFirst;
967 
968         cmd.DW1.PictureStructure = (CodecHal_PictureIsFrame(picParams->m_currPic)) ?
969             mpeg2Vc1Frame : (CodecHal_PictureIsTopField(picParams->m_currPic)) ?
970             mpeg2Vc1TopField : mpeg2Vc1BottomField;
971         cmd.DW1.IntraDcPrecision = picParams->W0.m_intraDCPrecision;
972         cmd.DW1.FCode00 = picParams->W1.m_fcode00;
973         cmd.DW1.FCode01 = picParams->W1.m_fcode01;
974         cmd.DW1.FCode10 = picParams->W1.m_fcode10;
975         cmd.DW1.FCode11 = picParams->W1.m_fcode11;
976 
977         cmd.DW2.PictureCodingType = picParams->m_pictureCodingType;
978 
979         if (params->Mode == CODECHAL_DECODE_MODE_MPEG2VLD)
980         {
981             cmd.DW2.ISliceConcealmentMode = params->dwMPEG2ISliceConcealmentMode;
982             cmd.DW2.PBSliceConcealmentMode = params->dwMPEG2PBSliceConcealmentMode;
983             cmd.DW2.PBSlicePredictedBidirMotionTypeOverrideBiDirectionMvTypeOverride = params->dwMPEG2PBSlicePredBiDirMVTypeOverride;
984             cmd.DW2.PBSlicePredictedMotionVectorOverrideFinalMvValueOverride = params->dwMPEG2PBSlicePredMVOverride;
985 
986             cmd.DW3.SliceConcealmentDisableBit = 1;
987         }
988 
989         uint16_t widthInMbs =
990             (picParams->m_horizontalSize + CODECHAL_MACROBLOCK_WIDTH - 1) /
991             CODECHAL_MACROBLOCK_WIDTH;
992 
993         uint16_t heightInMbs =
994             (picParams->m_verticalSize + CODECHAL_MACROBLOCK_HEIGHT - 1) /
995             CODECHAL_MACROBLOCK_HEIGHT;
996 
997         cmd.DW3.Framewidthinmbsminus170PictureWidthInMacroblocks = widthInMbs - 1;
998         cmd.DW3.Frameheightinmbsminus170PictureHeightInMacroblocks = (CodecHal_PictureIsField(picParams->m_currPic)) ?
999             ((heightInMbs * 2) - 1) : heightInMbs - 1;
1000 
1001         if (params->bDeblockingEnabled)
1002         {
1003             cmd.DW3.Reserved120 = 9;
1004         }
1005 
1006         cmd.DW4.Roundintradc = 3;
1007         cmd.DW4.Roundinterdc = 1;
1008         cmd.DW4.Roundintraac = 5;
1009         cmd.DW4.Roundinterac = 1;
1010 
1011         cmd.DW6.Intrambmaxsize = 0xfff;
1012         cmd.DW6.Intermbmaxsize = 0xfff;
1013 
1014         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
1015 
1016         return eStatus;
1017     }
1018 
AddMfxEncodeMpeg2PicCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_MPEG2_PIC_STATE params)1019     MOS_STATUS AddMfxEncodeMpeg2PicCmd(
1020         PMOS_COMMAND_BUFFER cmdBuffer,
1021         PMHW_VDBOX_MPEG2_PIC_STATE params)
1022     {
1023         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1024 
1025         MHW_FUNCTION_ENTER;
1026 
1027         MHW_MI_CHK_NULL(m_osInterface);
1028         MHW_MI_CHK_NULL(cmdBuffer);
1029         MHW_MI_CHK_NULL(params);
1030         MHW_MI_CHK_NULL(params->pEncodeMpeg2PicParams);
1031 
1032         typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD cmd;
1033         auto picParams = params->pEncodeMpeg2PicParams;
1034 
1035         cmd.DW1.ScanOrder = picParams->m_alternateScan;
1036         cmd.DW1.IntraVlcFormat = picParams->m_intraVlcFormat;
1037         cmd.DW1.QuantizerScaleType = picParams->m_qscaleType;
1038         cmd.DW1.ConcealmentMotionVectorFlag = picParams->m_concealmentMotionVectors;
1039         cmd.DW1.FramePredictionFrameDct = picParams->m_framePredFrameDCT;
1040         cmd.DW1.TffTopFieldFirst = !picParams->m_interleavedFieldBFF;
1041         cmd.DW1.PictureStructure = (CodecHal_PictureIsFrame(picParams->m_currOriginalPic)) ?
1042             mpeg2Vc1Frame : (CodecHal_PictureIsTopField(picParams->m_currOriginalPic)) ?
1043             mpeg2Vc1TopField : mpeg2Vc1BottomField;
1044         cmd.DW1.IntraDcPrecision = picParams->m_intraDCprecision;
1045         if (picParams->m_pictureCodingType == I_TYPE)
1046         {
1047             cmd.DW1.FCode00 = 0xf;
1048             cmd.DW1.FCode01 = 0xf;
1049         }
1050         else
1051         {
1052             cmd.DW1.FCode00 = picParams->m_fcode00;
1053             cmd.DW1.FCode01 = picParams->m_fcode01;
1054         }
1055         cmd.DW1.FCode10 = picParams->m_fcode10;
1056         cmd.DW1.FCode11 = picParams->m_fcode11;
1057 
1058         cmd.DW2.PictureCodingType = picParams->m_pictureCodingType;
1059         cmd.DW2.LoadslicepointerflagLoadbitstreampointerperslice = 0; // Do not reload bitstream pointer for each slice
1060 
1061         cmd.DW3.Framewidthinmbsminus170PictureWidthInMacroblocks = params->wPicWidthInMb - 1;
1062         cmd.DW3.Frameheightinmbsminus170PictureHeightInMacroblocks = params->wPicHeightInMb - 1;
1063 
1064         cmd.DW4.Roundintradc = 3;
1065         cmd.DW4.Roundinterdc = 1;
1066         cmd.DW4.Roundintraac = 5;
1067         cmd.DW4.Roundinterac = 1;
1068         cmd.DW4.Mbstatenabled = 0;
1069 
1070         cmd.DW5.Mbratecontrolmask = 0;
1071         cmd.DW5.Framesizecontrolmask = 0; // Disable first for PAK pass, used when MacroblockStatEnable is 1
1072 
1073         cmd.DW6.Intrambmaxsize = 0xfff;
1074         cmd.DW6.Intermbmaxsize = 0xfff;
1075 
1076         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
1077 
1078         return eStatus;
1079     }
1080 
AddMfdMpeg2BsdObject(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_MPEG2_SLICE_STATE params)1081     MOS_STATUS AddMfdMpeg2BsdObject(
1082         PMOS_COMMAND_BUFFER cmdBuffer,
1083         PMHW_BATCH_BUFFER batchBuffer,
1084         PMHW_VDBOX_MPEG2_SLICE_STATE params)
1085     {
1086         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1087 
1088         MHW_FUNCTION_ENTER;
1089 
1090         MHW_MI_CHK_NULL(params);
1091         MHW_MI_CHK_NULL(params->pMpeg2SliceParams);
1092 
1093         if (cmdBuffer == nullptr && batchBuffer == nullptr)
1094         {
1095             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
1096             return MOS_STATUS_INVALID_PARAMETER;
1097         }
1098 
1099         typename TMfxCmds::MFD_MPEG2_BSD_OBJECT_CMD  cmd;
1100         auto sliceParams = params->pMpeg2SliceParams;
1101 
1102         uint32_t endMb = params->dwSliceStartMbOffset + sliceParams->m_numMbsForSlice;
1103         uint32_t slcLocation = (uint32_t)(sliceParams->m_sliceDataOffset + params->dwOffset);
1104 
1105         cmd.DW1.IndirectBsdDataLength = params->dwLength;
1106         cmd.DW2.IndirectDataStartAddress = slcLocation;
1107         cmd.DW3.FirstMacroblockBitOffset = (sliceParams->m_macroblockOffset & 0x0007);
1108 
1109         cmd.DW3.IsLastMb = cmd.DW3.LastPicSlice = params->bLastSlice;
1110         cmd.DW3.Reserved100 =
1111             ((endMb / params->wPicWidthInMb) != sliceParams->m_sliceVerticalPosition) ? 1 : 0;
1112 
1113         cmd.DW3.MacroblockCount = sliceParams->m_numMbsForSlice;
1114         cmd.DW3.SliceHorizontalPosition = sliceParams->m_sliceHorizontalPosition;
1115         cmd.DW3.SliceVerticalPosition = sliceParams->m_sliceVerticalPosition;
1116         cmd.DW4.QuantizerScaleCode = sliceParams->m_quantiserScaleCode;
1117 
1118         if (cmd.DW3.IsLastMb)
1119         {
1120             cmd.DW4.NextSliceHorizontalPosition = 0;
1121             cmd.DW4.NextSliceVerticalPosition = params->wPicHeightInMb;
1122         }
1123         else
1124         {
1125             cmd.DW4.NextSliceHorizontalPosition = endMb % params->wPicWidthInMb;
1126             cmd.DW4.NextSliceVerticalPosition = endMb / params->wPicWidthInMb;
1127         }
1128 
1129         uint32_t offset = ((sliceParams->m_macroblockOffset & 0x0000fff8) >> 3); // #of bytes of header data in bitstream buffer (before video data)
1130 
1131         MHW_CP_SLICE_INFO_PARAMS sliceInfoParam;
1132         sliceInfoParam.presDataBuffer = params->presDataBuffer;
1133         sliceInfoParam.dwDataStartOffset[0] = sliceParams->m_sliceDataOffset + offset;
1134 
1135         MHW_MI_CHK_STATUS(m_cpInterface->SetMfxProtectionState(
1136             m_decodeInUse,
1137             cmdBuffer,
1138             batchBuffer,
1139             &sliceInfoParam));
1140 
1141         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
1142 
1143         return eStatus;
1144     }
1145 
1146     //!
1147     //! \struct   MFD_MPEG2_IT_OBJECT_CMD
1148     //! \brief    MFD MPEG2 it object command
1149     //!
1150     struct MFD_MPEG2_IT_OBJECT_CMD
1151     {
1152         typename TMfxCmds::MFD_IT_OBJECT_CMD m_header;
1153         typename TMfxCmds::MFD_IT_OBJECT_MPEG2_INLINE_DATA_CMD m_inlineData;
1154     };
1155 
AddMfdMpeg2ITObject(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_MPEG2_MB_STATE params)1156     MOS_STATUS AddMfdMpeg2ITObject(
1157         PMOS_COMMAND_BUFFER cmdBuffer,
1158         PMHW_BATCH_BUFFER batchBuffer,
1159         PMHW_VDBOX_MPEG2_MB_STATE params)
1160     {
1161         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1162 
1163         MHW_FUNCTION_ENTER;
1164 
1165         MHW_MI_CHK_NULL(params);
1166 
1167         if (cmdBuffer == nullptr && batchBuffer == nullptr)
1168         {
1169             MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
1170             return MOS_STATUS_INVALID_PARAMETER;
1171         }
1172 
1173         MFD_MPEG2_IT_OBJECT_CMD cmd;
1174         cmd.m_inlineData.DW0.MacroblockIntraType = mpeg2Vc1MacroblockIntra;
1175 
1176         typename TMfxCmds::MFD_IT_OBJECT_MPEG2_INLINE_DATA_CMD *inlineDataMpeg2 = &(cmd.m_inlineData);
1177         typename TMfxCmds::MFD_IT_OBJECT_CMD *cmdMfdItObject = &(cmd.m_header);
1178 
1179         //------------------------------------
1180         // Shared indirect data
1181         //------------------------------------
1182         cmdMfdItObject->DW0.DwordLength += TMfxCmds::MFD_IT_OBJECT_MPEG2_INLINE_DATA_CMD::dwSize;
1183 
1184         cmdMfdItObject->DW3.IndirectItCoeffDataLength = (params->dwDCTLength) << 2;
1185         cmdMfdItObject->DW4.IndirectItCoeffDataStartAddressOffset = params->dwITCoffDataAddrOffset;
1186 
1187         //------------------------------------
1188         // Shared inline data
1189         //------------------------------------
1190         auto mbParams = params->pMBParams;
1191         inlineDataMpeg2->DW0.DctType = mbParams->MBType.m_fieldResidual;
1192         inlineDataMpeg2->DW0.CodedBlockPattern = mbParams->m_codedBlockPattern;
1193         inlineDataMpeg2->DW1.Horzorigin = mbParams->m_mbAddr % params->wPicWidthInMb;
1194         inlineDataMpeg2->DW1.Vertorigin = mbParams->m_mbAddr / params->wPicWidthInMb;
1195         inlineDataMpeg2->DW0.Lastmbinrow = (inlineDataMpeg2->DW1.Horzorigin == (params->wPicWidthInMb - 1));
1196 
1197         if (params->wPicCodingType != I_TYPE)
1198         {
1199             inlineDataMpeg2->DW0.MacroblockIntraType = mbParams->MBType.m_intraMb;
1200             inlineDataMpeg2->DW0.MacroblockMotionForward = mbParams->MBType.m_motionFwd;
1201             inlineDataMpeg2->DW0.MacroblockMotionBackward = mbParams->MBType.m_motionBwd;
1202             inlineDataMpeg2->DW0.MotionType = mbParams->MBType.m_motionType;
1203             inlineDataMpeg2->DW0.MotionVerticalFieldSelect = mbParams->MBType.m_mvertFieldSel;
1204 
1205             // Next, copy in the motion vectors
1206             if (mbParams->MBType.m_intraMb == 0)
1207             {
1208                 uint32_t *point = (uint32_t*)(params->sPackedMVs0);
1209                 inlineDataMpeg2->DW2.Value = *point++;
1210                 inlineDataMpeg2->DW3.Value = *point++;
1211 
1212                 point = (uint32_t*)(params->sPackedMVs1);
1213                 inlineDataMpeg2->DW4.Value = *point++;
1214                 inlineDataMpeg2->DW5.Value = *point++;
1215             }
1216         }
1217 
1218         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
1219 
1220         return eStatus;
1221     }
1222 
AddMfcMpeg2SliceGroupCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_MPEG2_SLICE_STATE mpeg2SliceState)1223     MOS_STATUS AddMfcMpeg2SliceGroupCmd(
1224         PMOS_COMMAND_BUFFER cmdBuffer,
1225         PMHW_VDBOX_MPEG2_SLICE_STATE mpeg2SliceState)
1226     {
1227         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1228 
1229         MHW_FUNCTION_ENTER;
1230 
1231         MHW_MI_CHK_NULL(m_osInterface);
1232         MHW_MI_CHK_NULL(cmdBuffer);
1233         MHW_MI_CHK_NULL(mpeg2SliceState);
1234         MHW_MI_CHK_NULL(mpeg2SliceState->pEncodeMpeg2PicParams);
1235         MHW_MI_CHK_NULL(mpeg2SliceState->pEncodeMpeg2SliceParams);
1236         MHW_MI_CHK_NULL(mpeg2SliceState->pSlcData);
1237 
1238         auto sliceParams = mpeg2SliceState->pEncodeMpeg2SliceParams;
1239         auto picParams = mpeg2SliceState->pEncodeMpeg2PicParams;
1240         auto seqParams = mpeg2SliceState->pEncodeMpeg2SeqParams;
1241         auto slcData = mpeg2SliceState->pSlcData;
1242 
1243         typename TMfxCmds::MFC_MPEG2_SLICEGROUP_STATE_CMD cmd;
1244 
1245         cmd.DW1.Streamid10EncoderOnly = 0;
1246         cmd.DW1.Sliceid30EncoderOnly = 0;
1247         cmd.DW1.Intrasliceflag = 1;
1248         cmd.DW1.Intraslice = sliceParams->m_intraSlice;
1249         cmd.DW1.Firstslicehdrdisabled = 0;
1250         cmd.DW1.TailpresentflagTailInsertionPresentInBitstreamEncoderOnly =
1251             (picParams->m_lastPicInStream && (slcData->SliceGroup & SLICE_GROUP_LAST));
1252         cmd.DW1.SlicedataPresentflagSlicedataInsertionPresentInBitstreamEncoderOnly = 1;
1253         cmd.DW1.HeaderpresentflagHeaderInsertionPresentInBitstreamEncoderOnly = 1;
1254         cmd.DW1.BitstreamoutputflagCompressedBitstreamOutputDisableFlagEncoderOnly = 0;
1255         cmd.DW1.Islastslicegrp = (slcData->SliceGroup & SLICE_GROUP_LAST) ? 1 : 0;
1256         cmd.DW1.SkipconvdisabledMbTypeSkipConversionDisableEncoderOnly = sliceParams->m_intraSlice; // Disable for I slice
1257 
1258         cmd.DW1.MbratectrlflagRatecontrolcounterenableEncoderOnly = (mpeg2SliceState->bBrcEnabled && (!mpeg2SliceState->bFirstPass));
1259         cmd.DW1.MbratectrlresetResetratecontrolcounterEncoderOnly = 1;
1260         cmd.DW1.RatectrlpanictypeRcPanicTypeEncoderOnly = 1; // CBP type
1261         cmd.DW1.MbratectrlmodeRcTriggleModeEncoderOnly = 2; // Loose Rate Control Mode
1262         cmd.DW1.RatectrlpanicflagRcPanicEnableEncoderOnly =
1263             (mpeg2SliceState->bRCPanicEnable &&
1264             (seqParams->m_rateControlMethod != RATECONTROL_AVBR) &&
1265                 (seqParams->m_rateControlMethod != RATECONTROL_IWD_VBR) &&
1266                 (seqParams->m_rateControlMethod != RATECONTROL_ICQ) &&
1267                 (seqParams->m_rateControlMethod != RATECONTROL_VCM) &&
1268                 (seqParams->m_rateControlMethod != RATECONTROL_CQP) &&
1269                 mpeg2SliceState->bLastPass);    // Enable only in the last pass
1270 
1271         cmd.DW2.FirstmbxcntAlsoCurrstarthorzpos = sliceParams->m_firstMbX;
1272         cmd.DW2.FirstmbycntAlsoCurrstartvertpos = sliceParams->m_firstMbY;
1273         cmd.DW2.NextsgmbxcntAlsoNextstarthorzpos = slcData->NextSgMbXCnt;
1274         cmd.DW2.NextsgmbycntAlsoNextstartvertpos = slcData->NextSgMbYCnt;
1275 
1276         cmd.DW3.Slicegroupqp = sliceParams->m_quantiserScaleCode;
1277         cmd.DW3.Slicegroupskip = 0; // MBZ for MPEG2
1278 
1279         // H/W should use this start addr only for the first slice, since LoadSlicePointerFlag = 0 in PIC_STATE
1280         cmd.DW4.BitstreamoffsetIndirectPakBseDataStartAddressWrite = 0;
1281 
1282         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
1283 
1284         return eStatus;
1285     }
1286 
AddMfcMpeg2PakInsertBrcBuffer(PMOS_RESOURCE brcPicHeaderInputBuffer,PMHW_VDBOX_PAK_INSERT_PARAMS params)1287     MOS_STATUS AddMfcMpeg2PakInsertBrcBuffer(
1288         PMOS_RESOURCE brcPicHeaderInputBuffer,
1289         PMHW_VDBOX_PAK_INSERT_PARAMS params)
1290     {
1291         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1292 
1293         MHW_FUNCTION_ENTER;
1294 
1295         MHW_MI_CHK_NULL(brcPicHeaderInputBuffer);
1296         MHW_MI_CHK_NULL(params);
1297         MHW_MI_CHK_NULL(params->pBsBuffer);
1298 
1299         typename TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD cmd;
1300 
1301         uint32_t byteSize = (params->pBsBuffer->BitSize + 7) >> 3;
1302         uint32_t dataBitsInLastDw = params->pBsBuffer->BitSize % 32;
1303         if (dataBitsInLastDw == 0)
1304         {
1305             dataBitsInLastDw = 32;
1306         }
1307 
1308         uint32_t dwordsUsed = TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::dwSize + ((byteSize + 3) >> 2);
1309         cmd.DW0.DwordLength = OP_LENGTH(dwordsUsed);
1310         cmd.DW1.BitstreamstartresetResetbitstreamstartingpos = 0;
1311         cmd.DW1.EndofsliceflagLastdstdatainsertcommandflag = 0;
1312         cmd.DW1.LastheaderflagLastsrcheaderdatainsertcommandflag = 1;
1313         cmd.DW1.EmulationflagEmulationbytebitsinsertenable = 0;
1314         cmd.DW1.SkipemulbytecntSkipEmulationByteCount = 0;
1315         cmd.DW1.DatabitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
1316         cmd.DW1.DatabyteoffsetSrcdatastartingbyteoffset10 = 0;
1317 
1318         MOS_LOCK_PARAMS lockFlags;
1319         MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
1320         lockFlags.WriteOnly = 1;
1321         uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
1322             m_osInterface,
1323             brcPicHeaderInputBuffer,
1324             &lockFlags);
1325         MHW_MI_CHK_NULL(data);
1326 
1327         eStatus = MOS_SecureMemcpy(data, TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize, &cmd, TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize);
1328         if (eStatus != MOS_STATUS_SUCCESS)
1329         {
1330             MHW_ASSERTMESSAGE("Failed to copy memory.");
1331             return eStatus;
1332         }
1333 
1334         // Use the exact data byte size to make sure that we don't overrun the bit buffer.
1335         eStatus = MOS_SecureMemcpy(data + TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize, byteSize, params->pBsBuffer->pBase, byteSize);
1336         if (eStatus != MOS_STATUS_SUCCESS)
1337         {
1338             MHW_ASSERTMESSAGE("Failed to copy memory.");
1339             return eStatus;
1340         }
1341 
1342         // Need to make sure that the batch buffer end command begins on a dword boundary. So use
1343         // a dword aligned data size in the offset calculation instead of the straight byte size.
1344         // Note: The variable dwDwordsUsed already contains the size of the INSERT command.
1345         typename TMiCmds::MI_BATCH_BUFFER_END_CMD cmdMiBatchBufferEnd;
1346         eStatus = MOS_SecureMemcpy(data + sizeof(uint32_t)*dwordsUsed,
1347             sizeof(cmdMiBatchBufferEnd),
1348             &cmdMiBatchBufferEnd,
1349             cmdMiBatchBufferEnd.byteSize);
1350         if (eStatus != MOS_STATUS_SUCCESS)
1351         {
1352             MHW_ASSERTMESSAGE("Failed to copy memory.");
1353             return eStatus;
1354         }
1355 
1356         MHW_MI_CHK_STATUS(m_osInterface->pfnUnlockResource(m_osInterface, brcPicHeaderInputBuffer));
1357 
1358         *(params->pdwMpeg2PicHeaderTotalBufferSize) = sizeof(uint32_t)* dwordsUsed +
1359             cmdMiBatchBufferEnd.byteSize;
1360         *(params->pdwMpeg2PicHeaderDataStartOffset) = TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize;
1361 
1362         return eStatus;
1363     }
1364 
AddMfxMpeg2PicBrcBuffer(PMOS_RESOURCE brcImgBuffer,PMHW_VDBOX_MPEG2_PIC_STATE params)1365     MOS_STATUS AddMfxMpeg2PicBrcBuffer(
1366         PMOS_RESOURCE brcImgBuffer,
1367         PMHW_VDBOX_MPEG2_PIC_STATE params)
1368     {
1369         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1370 
1371         MHW_FUNCTION_ENTER;
1372 
1373         MHW_MI_CHK_NULL(brcImgBuffer);
1374         MHW_MI_CHK_NULL(params);
1375 
1376         MOS_LOCK_PARAMS lockFlags;
1377         MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
1378         lockFlags.WriteOnly = 1;
1379         uint8_t *data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, brcImgBuffer, &lockFlags);
1380         MHW_MI_CHK_NULL(data);
1381 
1382         MOS_COMMAND_BUFFER constructedCmdBuf;
1383         constructedCmdBuf.pCmdBase = (uint32_t *)data;
1384         constructedCmdBuf.pCmdPtr = (uint32_t *)data;
1385         constructedCmdBuf.iOffset = 0;
1386         constructedCmdBuf.iRemaining = BRC_IMG_STATE_SIZE_PER_PASS * m_numBrcPakPasses;
1387 
1388         MHW_MI_CHK_STATUS(AddMfxMpeg2PicCmd(&constructedCmdBuf, params));
1389 
1390         typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD cmd = *(typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD *)data;
1391 
1392         for (uint32_t i = 0; i < m_numBrcPakPasses; i++)
1393         {
1394             cmd.DW5.Framebitratemaxreportmask = 1;
1395             cmd.DW5.Framebitrateminreportmask = 1;
1396 
1397             if (i == 0)
1398             {
1399                 cmd.DW4.Mbstatenabled = 0; // Disable for first PAK pass
1400                 cmd.DW5.Mbratecontrolmask = 0;
1401                 cmd.DW5.Framesizecontrolmask = 0; // Disable first for PAK pass
1402             }
1403             else
1404             {
1405                 cmd.DW4.Mbstatenabled = 1; // Disable for first PAK pass
1406                 cmd.DW5.Mbratecontrolmask = 1;
1407                 cmd.DW5.Framesizecontrolmask = 1;
1408             }
1409 
1410             cmd.DW8.Value = m_mpeg2SliceDeltaQPMax[i];
1411             cmd.DW9.Value = m_mpeg2InitSliceDeltaQPMin[i];
1412             cmd.DW10.Value = m_mpeg2FrameBitrateMinMax[i];
1413             cmd.DW11.Value = m_mpeg2FrameBitrateMinMaxDelta[i];
1414 
1415             *(typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD *)data = cmd;
1416             data += BRC_IMG_STATE_SIZE_PER_PASS;
1417         }
1418 
1419         return eStatus;
1420     }
1421 
AddMfxVc1PredPipeCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_VC1_PRED_PIPE_PARAMS params)1422     MOS_STATUS AddMfxVc1PredPipeCmd(
1423         PMOS_COMMAND_BUFFER cmdBuffer,
1424         PMHW_VDBOX_VC1_PRED_PIPE_PARAMS params)
1425     {
1426         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1427 
1428         MHW_FUNCTION_ENTER;
1429 
1430         MHW_MI_CHK_NULL(m_osInterface);
1431         MHW_MI_CHK_NULL(cmdBuffer);
1432         MHW_MI_CHK_NULL(params);
1433         MHW_MI_CHK_NULL(params->pVc1PicParams);
1434 
1435         auto vc1PicParams = params->pVc1PicParams;
1436         auto destParams = params->ppVc1RefList[vc1PicParams->CurrPic.FrameIdx];
1437         auto fwdRefParams = params->ppVc1RefList[vc1PicParams->ForwardRefIdx];
1438         auto bwdRefParams = params->ppVc1RefList[vc1PicParams->BackwardRefIdx];
1439 
1440         bool isPPicture = IsVc1PPicture(
1441             vc1PicParams->CurrPic,
1442             vc1PicParams->picture_fields.is_first_field,
1443             vc1PicParams->picture_fields.picture_type);
1444 
1445         bool isBPicture = IsVc1BPicture(
1446             vc1PicParams->CurrPic,
1447             vc1PicParams->picture_fields.is_first_field,
1448             vc1PicParams->picture_fields.picture_type);
1449 
1450         bool isSecondField = !vc1PicParams->picture_fields.is_first_field;
1451 
1452         RefBoundaryReplicationMode refBoundaryReplicationMode;
1453         refBoundaryReplicationMode.BY0.value = 0;
1454 
1455         if (isPPicture || isBPicture)
1456         {
1457             if (fwdRefParams->dwRefSurfaceFlags & CODECHAL_VC1_PROGRESSIVE)
1458             {
1459                 if (!vc1PicParams->picture_fields.is_first_field)
1460                 {
1461                     if (vc1PicParams->picture_fields.top_field_first)
1462                     {
1463                         refBoundaryReplicationMode.BY0.ref0 = vc1InterlacedBoundary;
1464                         refBoundaryReplicationMode.BY0.ref2 = vc1ProgressiveBoundary;
1465                     }
1466                     else
1467                     {
1468                         refBoundaryReplicationMode.BY0.ref2 = vc1InterlacedBoundary;
1469                         refBoundaryReplicationMode.BY0.ref0 = vc1ProgressiveBoundary;
1470                     }
1471                 }
1472                 else
1473                 {
1474                     refBoundaryReplicationMode.BY0.ref0 = vc1ProgressiveBoundary;
1475                     refBoundaryReplicationMode.BY0.ref2 = vc1ProgressiveBoundary;
1476                 }
1477             }
1478             else
1479             {
1480                 refBoundaryReplicationMode.BY0.ref0 = refBoundaryReplicationMode.BY0.ref2 = vc1InterlacedBoundary;
1481             }
1482         }
1483         if (isBPicture)
1484         {
1485             if (bwdRefParams->dwRefSurfaceFlags & CODECHAL_VC1_PROGRESSIVE)
1486             {
1487                 refBoundaryReplicationMode.BY0.ref1 = refBoundaryReplicationMode.BY0.ref3 = vc1ProgressiveBoundary;
1488             }
1489             else
1490             {
1491                 refBoundaryReplicationMode.BY0.ref1 = refBoundaryReplicationMode.BY0.ref3 = vc1InterlacedBoundary;
1492             }
1493         }
1494 
1495         typename TMfxCmds::MFX_VC1_PRED_PIPE_STATE_CMD cmd;
1496         cmd.DW1.ReferenceFrameBoundaryReplicationMode = refBoundaryReplicationMode.BY0.value;
1497 
1498         uint32_t fwdDoubleIcEnable = 0, fwdSingleIcEnable = 0;
1499         uint32_t bwdDoubleIcEnable = 0, bwdSingleIcEnable = 0;
1500         uint8_t icField = 0;
1501 
1502         // Interlaced Frame & Frame
1503         if (!CodecHal_PictureIsField(vc1PicParams->CurrPic))
1504         {
1505             if (isPPicture)
1506             {
1507                 if (vc1PicParams->picture_fields.intensity_compensation)
1508                 {
1509                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1510                     {
1511                         fwdDoubleIcEnable = TOP_FIELD;
1512                         cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1513                         cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1514                         // IC values for the bottom out of bound pixels (replicated lines of the last
1515                         // line of top field)
1516                         cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1517                         cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1518 
1519                         MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2);
1520                         icField++;
1521                     }
1522                     else if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1523                     {
1524                         fwdDoubleIcEnable = BOTTOM_FIELD;
1525                         // IC values for the top out of bound pixels (replicated lines of the first
1526                         // line of bottom field)
1527                         cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1528                         cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1529                         cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1530                         cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1531 
1532                         MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2);
1533                         icField++;
1534                     }
1535 
1536                     uint16_t lumaScale = vc1PicParams->luma_scale;
1537                     uint16_t lumaShift = vc1PicParams->luma_shift;
1538 
1539                     MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_FRAME_COMP);
1540 
1541                     fwdSingleIcEnable = TOP_FIELD | BOTTOM_FIELD;
1542                     cmd.DW2.Lumscale1SingleFwd = lumaScale;
1543                     cmd.DW2.Lumshift1SingleFwd = lumaShift;
1544 
1545                     cmd.DW2.Lumscale2SingleFwd = lumaScale;
1546                     cmd.DW2.Lumshift2SingleFwd = lumaShift;
1547 
1548                     // Set double backward values for top and bottom out of bound pixels
1549                     bwdDoubleIcEnable = TOP_FIELD | BOTTOM_FIELD;
1550                     cmd.DW5.Lumscale1DoubleBwd = lumaScale;
1551                     cmd.DW5.Lumshift1DoubleBwd = lumaShift;
1552                     cmd.DW5.Lumscale2DoubleBwd = lumaScale;
1553                     cmd.DW5.Lumshift2DoubleBwd = lumaShift;
1554 
1555                     // Save IC
1556                     fwdRefParams->Vc1IcValues[icField].wICCScale1 =
1557                         fwdRefParams->Vc1IcValues[icField].wICCScale2 = lumaScale;
1558                     fwdRefParams->Vc1IcValues[icField].wICCShiftL1 =
1559                         fwdRefParams->Vc1IcValues[icField].wICCShiftL2 = lumaShift;
1560                 }
1561                 else
1562                 {
1563                     // special case for interlaced field references when no IC is indicated
1564                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1565                     {
1566                         cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1567                         cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1568 
1569                         fwdSingleIcEnable = TOP_FIELD;
1570                         icField++;
1571                     }
1572 
1573                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1574                     {
1575                         cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1576                         cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1577 
1578                         fwdSingleIcEnable |= BOTTOM_FIELD;
1579                         icField++;
1580                     }
1581 
1582                 }
1583             }
1584             else if (isBPicture)
1585             {
1586                 // Forward reference IC
1587                 if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2))
1588                 {
1589                     fwdDoubleIcEnable = TOP_FIELD;
1590                     cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1591                     cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1592                     // IC values for the bottom out of bound pixels (replicated lines of the last
1593                     // line of top field)
1594                     cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1595                     cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1596                 }
1597                 if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2))
1598                 {
1599                     fwdDoubleIcEnable |= BOTTOM_FIELD;
1600                     // IC values for the top out of bound pixels (replicated lines of the first
1601                     // line of bottom field)
1602                     cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1603                     cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1604                     cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1605                     cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1606                 }
1607                 if (fwdDoubleIcEnable)
1608                 {
1609                     icField++;
1610                 }
1611 
1612                 if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1613                 {
1614                     fwdSingleIcEnable = TOP_FIELD;
1615                     cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1616                     cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1617                 }
1618                 if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1619                 {
1620                     fwdSingleIcEnable |= BOTTOM_FIELD;
1621                     cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1622                     cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1623                 }
1624 
1625                 // If the reference picture is interlaced field, set double backward values for top
1626                 // and bottom out of bound pixels
1627                 if (fwdSingleIcEnable == (TOP_FIELD | BOTTOM_FIELD))
1628                 {
1629                     bwdDoubleIcEnable = TOP_FIELD | BOTTOM_FIELD;
1630                     cmd.DW5.Lumscale1DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1631                     cmd.DW5.Lumshift1DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1632                     cmd.DW5.Lumscale2DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1633                     cmd.DW5.Lumshift2DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1634                 }
1635 
1636                 // Backward reference IC
1637                 icField = 0;
1638                 if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1639                 {
1640                     bwdSingleIcEnable = TOP_FIELD;
1641                     cmd.DW4.Lumscale1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale1;
1642                     cmd.DW4.Lumshift1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1643                 }
1644                 else if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1645                 {
1646                     bwdSingleIcEnable = BOTTOM_FIELD;
1647                     cmd.DW4.Lumscale2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale2;
1648                     cmd.DW4.Lumshift2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1649                 }
1650             }
1651         }
1652         // Interlace field
1653         else
1654         {
1655             if (isPPicture)
1656             {
1657                 fwdSingleIcEnable =
1658                     vc1PicParams->picture_fields.intensity_compensation ? (TOP_FIELD | BOTTOM_FIELD) : 0;
1659 
1660                 // Top field IC
1661                 uint16_t lumaScale = vc1PicParams->luma_scale >> 8;
1662                 uint16_t lumaShift = vc1PicParams->luma_shift >> 8;
1663 
1664                 if (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) && isSecondField)
1665                 {
1666                     fwdRefParams = destParams;
1667                 }
1668 
1669                 if (((lumaScale == 32) && (lumaShift == 0)) || !(fwdSingleIcEnable & TOP_FIELD))
1670                 {
1671                     // No IC for top field
1672                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1673                     {
1674                         cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1675                         cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1676                         fwdSingleIcEnable |= TOP_FIELD;
1677                     }
1678                     else
1679                     {
1680                         fwdSingleIcEnable &= BOTTOM_FIELD;
1681                     }
1682                 }
1683                 else
1684                 {
1685                     // IC for top field is enabled
1686                     cmd.DW2.Lumscale1SingleFwd = lumaScale;
1687                     cmd.DW2.Lumshift1SingleFwd = lumaShift;
1688 
1689                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1690                     {
1691                         fwdDoubleIcEnable = TOP_FIELD;
1692                         cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1693                         cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1694 
1695                         MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2);
1696                         icField++;
1697                     }
1698                     else
1699                     {
1700                         MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP);
1701                     }
1702 
1703                     // set double backward values for top out of bound pixels
1704                     if (vc1PicParams->picture_fields.intensity_compensation)
1705                     {
1706                         bwdDoubleIcEnable = TOP_FIELD;
1707                         // If the reference picture is not interlaced field and current picture is bottom field
1708                         // and second field, double backwards values are identical to the the single forward
1709                         // values used by the p interlaced field top field
1710                         if (!CodecHal_PictureIsField((params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->RefPic) &&
1711                             (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) && isSecondField))
1712                         {
1713                             cmd.DW5.Lumscale1DoubleBwd =
1714                                 (params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCScale1;
1715                             cmd.DW5.Lumshift1DoubleBwd =
1716                                 (params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCShiftL1;
1717                         }
1718                         else
1719                         {
1720                             cmd.DW5.Lumscale1DoubleBwd = lumaScale;
1721                             cmd.DW5.Lumshift1DoubleBwd = lumaShift;
1722                         }
1723                     }
1724 
1725                     // Save IC
1726                     fwdRefParams->Vc1IcValues[icField].wICCScale1 = lumaScale;
1727                     fwdRefParams->Vc1IcValues[icField].wICCShiftL1 = lumaShift;
1728                 }
1729 
1730                 // Bottom field IC
1731                 icField = 0;
1732                 lumaScale = vc1PicParams->luma_scale & 0x00ff;
1733                 lumaShift = vc1PicParams->luma_shift & 0x00ff;
1734 
1735                 if (CodecHal_PictureIsTopField(vc1PicParams->CurrPic) && isSecondField)
1736                 {
1737                     fwdRefParams = destParams;
1738                 }
1739                 else
1740                 {
1741                     fwdRefParams = params->ppVc1RefList[vc1PicParams->ForwardRefIdx];
1742                 }
1743 
1744                 if (((lumaScale == 32) && (lumaShift == 0)) || !(fwdSingleIcEnable & BOTTOM_FIELD))
1745                 {
1746                     // No IC for bottom field
1747 
1748                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1749                     {
1750                         cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1751                         cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1752                         fwdSingleIcEnable |= BOTTOM_FIELD;
1753                     }
1754                     else
1755                     {
1756                         fwdSingleIcEnable &= TOP_FIELD;
1757                     }
1758                 }
1759                 else
1760                 {
1761                     // IC is on
1762                     cmd.DW2.Lumscale2SingleFwd = lumaScale;
1763                     cmd.DW2.Lumshift2SingleFwd = lumaShift;
1764 
1765                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1766                     {
1767                         fwdDoubleIcEnable |= BOTTOM_FIELD;
1768                         cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1769                         cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1770 
1771                         MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2);
1772                         icField++;
1773                     }
1774                     else
1775                     {
1776                         MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP);
1777                     }
1778 
1779                     // set double backward values for bottom out of bound pixels
1780                     if (vc1PicParams->picture_fields.intensity_compensation)
1781                     {
1782                         bwdDoubleIcEnable |= BOTTOM_FIELD;
1783                         // If the reference picture is not interlaced field and current picture is top field and
1784                         // second field, double backwards values are identical to the the single forward values
1785                         // used by the p interlaced field bottom field
1786                         if (!CodecHal_PictureIsField((params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->RefPic) &&
1787                             (CodecHal_PictureIsTopField(vc1PicParams->CurrPic) && isSecondField))
1788                         {
1789                             cmd.DW5.Lumscale2DoubleBwd =
1790                                 (params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCScale2;
1791                             cmd.DW5.Lumshift2DoubleBwd =
1792                                 (params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCShiftL2;
1793                         }
1794                         else
1795                         {
1796                             cmd.DW5.Lumscale2DoubleBwd = lumaScale;
1797                             cmd.DW5.Lumshift2DoubleBwd = lumaShift;
1798                         }
1799                     }
1800 
1801                     // Save IC
1802                     fwdRefParams->Vc1IcValues[icField].wICCScale2 = lumaScale;
1803                     fwdRefParams->Vc1IcValues[icField].wICCShiftL2 = lumaShift;
1804                 }
1805             }
1806             else if (isBPicture)
1807             {
1808                 // Forward reference IC
1809                 if (CodecHal_PictureIsTopField(vc1PicParams->CurrPic) || !isSecondField)
1810                 {
1811                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2))
1812                     {
1813                         cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1814                         cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1815                         fwdDoubleIcEnable = TOP_FIELD;
1816                         icField++;
1817                     }
1818 
1819                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1820                     {
1821                         cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
1822                         cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1823                         fwdSingleIcEnable = TOP_FIELD;
1824                     }
1825                 }
1826 
1827                 if ((vc1PicParams->CurrPic.PicFlags == PICTURE_BOTTOM_FIELD) || !isSecondField)
1828                 {
1829                     icField = 0;
1830                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2))
1831                     {
1832                         cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1833                         cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1834                         fwdDoubleIcEnable |= BOTTOM_FIELD;
1835                         icField++;
1836                     }
1837                     if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1838                     {
1839                         cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
1840                         cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1841                         fwdSingleIcEnable |= BOTTOM_FIELD;
1842                     }
1843                 }
1844 
1845                 // Backward reference IC
1846                 icField = 0;
1847                 if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
1848                 {
1849                     cmd.DW4.Lumscale1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale1;
1850                     cmd.DW4.Lumshift1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL1;
1851                     bwdSingleIcEnable = TOP_FIELD;
1852                 }
1853 
1854                 if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
1855                 {
1856                     cmd.DW4.Lumscale2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale2;
1857                     cmd.DW4.Lumshift2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL2;
1858                     bwdSingleIcEnable |= BOTTOM_FIELD;
1859                 }
1860             }
1861         }
1862 
1863         cmd.DW1.VinIntensitycompDoubleFwden = fwdDoubleIcEnable;
1864         cmd.DW1.VinIntensitycompDoubleBwden = bwdDoubleIcEnable;
1865         cmd.DW1.VinIntensitycompSingleFwden = fwdSingleIcEnable;
1866         cmd.DW1.VinIntensitycompSingleBwden = bwdSingleIcEnable;
1867 
1868         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
1869 
1870         return eStatus;
1871     }
1872 
AddMfxVc1LongPicCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_VC1_PIC_STATE vc1PicState)1873     MOS_STATUS AddMfxVc1LongPicCmd(
1874         PMOS_COMMAND_BUFFER cmdBuffer,
1875         PMHW_VDBOX_VC1_PIC_STATE vc1PicState)
1876     {
1877         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1878 
1879         MHW_FUNCTION_ENTER;
1880 
1881         MHW_MI_CHK_NULL(m_osInterface);
1882         MHW_MI_CHK_NULL(cmdBuffer);
1883         MHW_MI_CHK_NULL(vc1PicState);
1884         MHW_MI_CHK_NULL(vc1PicState->pVc1PicParams);
1885 
1886         auto vc1PicParams = vc1PicState->pVc1PicParams;
1887 
1888         bool isFramePicture =
1889             ((vc1PicParams->CurrPic.PicFlags == PICTURE_FRAME) |
1890             (vc1PicParams->CurrPic.PicFlags == PICTURE_INTERLACED_FRAME));
1891 
1892         uint16_t widthInMbs = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(vc1PicParams->coded_width);
1893         uint16_t heightInMbs = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(vc1PicParams->coded_height);
1894 
1895         uint16_t frameFieldHeightInMb = 0;
1896         CodecHal_GetFrameFieldHeightInMb(
1897             vc1PicParams->CurrPic,
1898             heightInMbs,
1899             frameFieldHeightInMb);
1900 
1901         bool isIPicture = IsVc1IPicture(
1902             vc1PicParams->CurrPic,
1903             vc1PicParams->picture_fields.is_first_field,
1904             vc1PicParams->picture_fields.picture_type);
1905 
1906         bool isPPicture = IsVc1PPicture(
1907             vc1PicParams->CurrPic,
1908             vc1PicParams->picture_fields.is_first_field,
1909             vc1PicParams->picture_fields.picture_type);
1910 
1911         bool isBPicture = IsVc1BPicture(
1912             vc1PicParams->CurrPic,
1913             vc1PicParams->picture_fields.is_first_field,
1914             vc1PicParams->picture_fields.picture_type);
1915 
1916         bool isBIPicture = IsVc1BIPicture(
1917             vc1PicParams->CurrPic,
1918             vc1PicParams->picture_fields.is_first_field,
1919             vc1PicParams->picture_fields.picture_type);
1920 
1921         auto destParams = vc1PicState->ppVc1RefList[vc1PicParams->CurrPic.FrameIdx];
1922         auto fwdRefParams = vc1PicState->ppVc1RefList[vc1PicParams->ForwardRefIdx];
1923 
1924         typename TMfxCmds::MFD_VC1_LONG_PIC_STATE_CMD cmd;
1925 
1926         cmd.DW1.Picturewidthinmbsminus1PictureWidthMinus1InMacroblocks = widthInMbs - 1;
1927         cmd.DW1.Pictureheightinmbsminus1PictureHeightMinus1InMacroblocks = frameFieldHeightInMb - 1;
1928 
1929         cmd.DW2.Vc1Profile = vc1PicParams->sequence_fields.AdvancedProfileFlag;
1930         cmd.DW2.Secondfield = !vc1PicParams->picture_fields.is_first_field;
1931         cmd.DW2.OverlapSmoothingEnableFlag = vc1PicParams->sequence_fields.overlap;
1932         cmd.DW2.LoopfilterEnableFlag = vc1PicParams->entrypoint_fields.loopfilter;
1933         cmd.DW2.InterpolationRounderContro = vc1PicParams->rounding_control;
1934         cmd.DW2.MotionVectorMode = (vc1PicParams->mv_fields.MvMode & 0x9);
1935 
1936         // Simple and Main profile dynamic range adjustment
1937         if ((!vc1PicParams->sequence_fields.AdvancedProfileFlag) && isPPicture)
1938         {
1939             if ((destParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT) &&
1940                 !(fwdRefParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT))
1941             {
1942                 cmd.DW2.RangereductionEnable = 1;
1943                 cmd.DW2.Rangereductionscale = 0;
1944             }
1945             else if (!(destParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT) &&
1946                 (fwdRefParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT))
1947             {
1948                 cmd.DW2.RangereductionEnable = 1;
1949                 cmd.DW2.Rangereductionscale = 1;
1950             }
1951         }
1952 
1953         cmd.DW3.PquantPictureQuantizationValue = vc1PicParams->pic_quantizer_fields.pic_quantizer_scale;
1954 
1955         if (vc1PicState->Mode == CODECHAL_DECODE_MODE_VC1IT)
1956         {
1957             if (isIPicture || isBIPicture)
1958             {
1959                 cmd.DW3.PictypePictureType = vc1IFrame; // 0 = I or I/I
1960             }
1961             else if (isPPicture)
1962             {
1963                 cmd.DW3.PictypePictureType = isFramePicture ? (uint32_t)vc1PFrame: (uint32_t)vc1PPField;
1964             }
1965             else if (isBPicture)
1966             {
1967                 cmd.DW3.PictypePictureType = isFramePicture ? (uint32_t)vc1BFrame: (uint32_t)vc1BBField;
1968             }
1969 
1970             if (isFramePicture)
1971             {
1972                 cmd.DW3.FcmFrameCodingMode = (vc1PicParams->CurrPic.PicFlags == PICTURE_INTERLACED_FRAME);
1973             }
1974             else
1975             {
1976                 cmd.DW3.FcmFrameCodingMode = (vc1PicParams->picture_fields.top_field_first) ? vc1TffFrame : vc1BffFrame;
1977             }
1978 
1979             cmd.DW4.FastuvmcflagFastUvMotionCompensationFlag = (vc1PicParams->mv_fields.MvMode & 0x1);
1980             cmd.DW4.Pquantuniform = 1; // uniform
1981             cmd.DW2.Implicitquantizer = 1; // implicit
1982         }
1983         else // CODECHAL_DECODE_MODE_VC1VLD
1984         {
1985             cmd.DW2.Syncmarker = vc1PicParams->sequence_fields.syncmarker;
1986             cmd.DW2.Implicitquantizer = (vc1PicParams->pic_quantizer_fields.quantizer == vc1QuantizerImplicit);
1987             if (isBPicture &&
1988                 (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) ?
1989                     vc1PicState->bPrevOddAnchorPictureIsP : vc1PicState->bPrevEvenAnchorPictureIsP)) // OR if I not before B in decoding order
1990             {
1991                 cmd.DW2.Dmvsurfacevalid = true;
1992             }
1993 
1994             if (vc1PicParams->raw_coding.bitplane_present)
1995             {
1996                 cmd.DW2.BitplaneBufferPitchMinus1 = (widthInMbs - 1) >> 1;
1997             }
1998 
1999             cmd.DW3.Bscalefactor = vc1PicParams->ScaleFactor;
2000             cmd.DW3.AltpquantAlternativePictureQuantizationValue = vc1PicParams->pic_quantizer_fields.alt_pic_quantizer;
2001             cmd.DW3.FcmFrameCodingMode = vc1PicParams->picture_fields.frame_coding_mode;
2002             cmd.DW3.PictypePictureType = vc1PicParams->picture_fields.picture_type;
2003             cmd.DW3.Condover = vc1PicParams->conditional_overlap_flag;
2004 
2005             cmd.DW4.Pquantuniform = vc1PicParams->pic_quantizer_fields.pic_quantizer_type;
2006             cmd.DW4.Halfqp = vc1PicParams->pic_quantizer_fields.half_qp;
2007             cmd.DW4.AltpquantconfigAlternativePictureQuantizationConfiguration = vc1PicParams->pic_quantizer_fields.AltPQuantConfig;
2008             cmd.DW4.AltpquantedgemaskAlternativePictureQuantizationEdgeMask = vc1PicParams->pic_quantizer_fields.AltPQuantEdgeMask;
2009 
2010             // AltPQuant parameters must be set to 0 for I or BI pictures in simple/main profile
2011             if (!vc1PicParams->sequence_fields.AdvancedProfileFlag && (isIPicture || isBIPicture))
2012             {
2013                 cmd.DW4.AltpquantconfigAlternativePictureQuantizationConfiguration = 0;
2014                 cmd.DW4.AltpquantedgemaskAlternativePictureQuantizationEdgeMask = 0;
2015                 cmd.DW3.AltpquantAlternativePictureQuantizationValue = 0;
2016             }
2017 
2018             cmd.DW4.ExtendedmvrangeExtendedMotionVectorRangeFlag = vc1PicParams->mv_fields.extended_mv_range;
2019             cmd.DW4.ExtendeddmvrangeExtendedDifferentialMotionVectorRangeFlag = vc1PicParams->mv_fields.extended_dmv_range;
2020             cmd.DW4.FwdrefdistReferenceDistance = vc1PicParams->reference_fields.reference_distance;
2021             cmd.DW4.BwdrefdistReferenceDistance = vc1PicParams->reference_fields.BwdReferenceDistance;
2022 
2023             if (!isFramePicture && isBPicture)
2024             {
2025                 // For B field pictures, NumberOfReferencePictures is always 2 (i.e. set to 1).
2026                 cmd.DW4.NumrefNumberOfReferences = 1;
2027             }
2028             else
2029             {
2030                 cmd.DW4.NumrefNumberOfReferences = vc1PicParams->reference_fields.num_reference_pictures;
2031             }
2032 
2033             if (isPPicture &&
2034                 CodecHal_PictureIsField(vc1PicParams->CurrPic) &&
2035                 (cmd.DW4.NumrefNumberOfReferences == 0))
2036             {
2037                 // Derive polarity of the reference field: Top = 0, Bottom = 1
2038                 if (vc1PicParams->reference_fields.reference_field_pic_indicator == 0)
2039                 {
2040                     // Temporally closest reference
2041                     if (vc1PicParams->picture_fields.is_first_field)
2042                     {
2043                         // Reference frame
2044                         cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = vc1PicState->wPrevAnchorPictureTFF;
2045                     }
2046                     else
2047                     {
2048                         // Same frame
2049                         cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = !vc1PicParams->picture_fields.top_field_first;
2050                     }
2051                 }
2052                 else
2053                 {
2054                     // Second most temporally closest reference
2055                     if (vc1PicParams->picture_fields.is_first_field)
2056                     {
2057                         // First field of reference frame
2058                         cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = !vc1PicState->wPrevAnchorPictureTFF;
2059                     }
2060                     else
2061                     {
2062                         // Second field of reference frame
2063                         cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = vc1PicState->wPrevAnchorPictureTFF;
2064                     }
2065                 }
2066             }
2067 
2068             cmd.DW4.FastuvmcflagFastUvMotionCompensationFlag = vc1PicParams->fast_uvmc_flag;
2069             cmd.DW4.FourmvswitchFourMotionVectorSwitch = vc1PicParams->mv_fields.four_mv_switch;
2070             cmd.DW4.UnifiedmvmodeUnifiedMotionVectorMode = vc1PicParams->mv_fields.UnifiedMvMode;
2071 
2072             // If bitplane is present (BitplanePresentFlag == 1) update the "raw" bitplane
2073             // flags. If bitplane is not present leave all "raw" flags to their initialized
2074             // value which is all bitplanes are present "raw".
2075             cmd.DW5.BitplanepresentflagBitplaneBufferPresentFlag = vc1PicParams->raw_coding.bitplane_present;
2076 
2077             cmd.DW5.Fieldtxraw = vc1RawMode;
2078             cmd.DW5.Acpredraw = vc1RawMode;
2079             cmd.DW5.Overflagsraw = vc1RawMode;
2080             cmd.DW5.Directmbraw = vc1RawMode;
2081             cmd.DW5.Skipmbraw = vc1RawMode;
2082             cmd.DW5.Mvtypembraw = vc1RawMode;
2083             cmd.DW5.Forwardmbraw = vc1RawMode;
2084 
2085             if (vc1PicParams->raw_coding.bitplane_present)
2086             {
2087                 cmd.DW5.Fieldtxraw = vc1PicParams->raw_coding.field_tx;
2088                 cmd.DW5.Acpredraw = vc1PicParams->raw_coding.ac_pred;
2089                 cmd.DW5.Overflagsraw = vc1PicParams->raw_coding.overflags;
2090                 cmd.DW5.Directmbraw = vc1PicParams->raw_coding.direct_mb;
2091                 cmd.DW5.Skipmbraw = vc1PicParams->raw_coding.skip_mb;
2092                 cmd.DW5.Mvtypembraw = vc1PicParams->raw_coding.mv_type_mb;
2093                 cmd.DW5.Forwardmbraw = vc1PicParams->raw_coding.forward_mb;
2094             }
2095 
2096             cmd.DW5.CbptabCodedBlockPatternTable = vc1PicParams->cbp_table;
2097             cmd.DW5.TransdctabIntraTransformDcTable = vc1PicParams->transform_fields.intra_transform_dc_table;
2098             cmd.DW5.TransacuvPictureLevelTransformChromaAcCodingSetIndexTransactable = vc1PicParams->transform_fields.transform_ac_codingset_idx1;
2099             cmd.DW5.TransacyPictureLevelTransformLumaAcCodingSetIndexTransactable2 = (isIPicture || isBIPicture) ?
2100                 vc1PicParams->transform_fields.transform_ac_codingset_idx2 : cmd.DW5.TransacuvPictureLevelTransformChromaAcCodingSetIndexTransactable;
2101             cmd.DW5.MbmodetabMacroblockModeTable = vc1PicParams->mb_mode_table;
2102 
2103             if (vc1PicParams->transform_fields.variable_sized_transform_flag == 0)
2104             {
2105                 // H/W decodes TTMB, TTBLK and SUBBLKPAT if the picture level TTMBF flag is not set.
2106                 // If the VSTRANSFORM is 0, 8x8 TransformType is used for all the pictures belonging to this Entry-Point.
2107                 // Hence H/W overloads the TTMBF = 1 and TTFRM = 8x8 in this case.
2108                 cmd.DW5.TranstypembflagMacroblockTransformTypeFlag = 1;
2109                 cmd.DW5.TranstypePictureLevelTransformType = 0;
2110             }
2111             else
2112             {
2113                 cmd.DW5.TranstypembflagMacroblockTransformTypeFlag = vc1PicParams->transform_fields.mb_level_transform_type_flag;
2114                 cmd.DW5.TranstypePictureLevelTransformType = vc1PicParams->transform_fields.frame_level_transform_type;
2115             }
2116             cmd.DW5.Twomvbptab2MvBlockPatternTable = vc1PicParams->mv_fields.two_mv_block_pattern_table;
2117             cmd.DW5.Fourmvbptab4MvBlockPatternTable = vc1PicParams->mv_fields.four_mv_block_pattern_table;
2118             cmd.DW5.MvtabMotionVectorTable = vc1PicParams->mv_fields.mv_table;
2119         }
2120 
2121         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2122 
2123         return eStatus;
2124     }
2125 
AddMfdVc1ShortPicCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_VC1_PIC_STATE vc1PicState)2126     MOS_STATUS AddMfdVc1ShortPicCmd(
2127         PMOS_COMMAND_BUFFER cmdBuffer,
2128         PMHW_VDBOX_VC1_PIC_STATE vc1PicState)
2129     {
2130         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2131 
2132         MHW_FUNCTION_ENTER;
2133 
2134         MHW_MI_CHK_NULL(m_osInterface);
2135         MHW_MI_CHK_NULL(cmdBuffer);
2136         MHW_MI_CHK_NULL(vc1PicState);
2137         MHW_MI_CHK_NULL(vc1PicState->pVc1PicParams);
2138 
2139         auto vc1PicParams = vc1PicState->pVc1PicParams;
2140 
2141         uint16_t widthInMbs = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(vc1PicParams->coded_width);
2142         uint16_t heightInMbs = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(vc1PicParams->coded_height);
2143 
2144         uint16_t frameFieldHeightInMb = 0;
2145         CodecHal_GetFrameFieldHeightInMb(
2146             vc1PicParams->CurrPic,
2147             heightInMbs,
2148             frameFieldHeightInMb);
2149 
2150         bool isIPicture = IsVc1IPicture(
2151             vc1PicParams->CurrPic,
2152             vc1PicParams->picture_fields.is_first_field,
2153             vc1PicParams->picture_fields.picture_type);
2154 
2155         bool isPPicture = IsVc1PPicture(
2156             vc1PicParams->CurrPic,
2157             vc1PicParams->picture_fields.is_first_field,
2158             vc1PicParams->picture_fields.picture_type);
2159 
2160         bool isBPicture = IsVc1BPicture(
2161             vc1PicParams->CurrPic,
2162             vc1PicParams->picture_fields.is_first_field,
2163             vc1PicParams->picture_fields.picture_type);
2164 
2165         bool isBIPicture = IsVc1BIPicture(
2166             vc1PicParams->CurrPic,
2167             vc1PicParams->picture_fields.is_first_field,
2168             vc1PicParams->picture_fields.picture_type);
2169 
2170         typename TMfxCmds::MFD_VC1_SHORT_PIC_STATE_CMD cmd;
2171 
2172         // DW 1
2173         cmd.DW1.PictureWidth = widthInMbs - 1;
2174         cmd.DW1.PictureHeight = frameFieldHeightInMb - 1;
2175 
2176         // DW 2
2177         cmd.DW2.PictureStructure =
2178             (CodecHal_PictureIsTopField(vc1PicParams->CurrPic)) ?
2179             mpeg2Vc1TopField : (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic)) ?
2180             mpeg2Vc1BottomField : mpeg2Vc1Frame;
2181         cmd.DW2.Secondfield = !vc1PicParams->picture_fields.is_first_field;
2182         cmd.DW2.IntraPictureFlag = isIPicture || isBIPicture;
2183         cmd.DW2.BackwardPredictionPresentFlag = isBPicture;
2184 
2185         cmd.DW2.Vc1Profile = vc1PicParams->sequence_fields.AdvancedProfileFlag;
2186         if (isBPicture &&
2187             (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) ?
2188                 vc1PicState->bPrevOddAnchorPictureIsP : vc1PicState->bPrevEvenAnchorPictureIsP)) // OR if I not before B in decoding order
2189         {
2190             cmd.DW2.Dmvsurfacevalid = true;
2191         }
2192 
2193         cmd.DW2.MotionVectorMode = vc1PicParams->mv_fields.MvMode & 0x9;
2194         cmd.DW2.InterpolationRounderControl = vc1PicParams->rounding_control;
2195         cmd.DW2.BitplaneBufferPitchMinus1 = (vc1PicParams->coded_width <= 2048) ?
2196             (MHW_VDBOX_VC1_BITPLANE_BUFFER_PITCH_SMALL - 1) : (MHW_VDBOX_VC1_BITPLANE_BUFFER_PITCH_LARGE - 1);
2197 
2198         // DW 3
2199         cmd.DW3.VstransformFlag = vc1PicParams->transform_fields.variable_sized_transform_flag;
2200         cmd.DW3.Dquant = vc1PicParams->pic_quantizer_fields.dquant;
2201         cmd.DW3.ExtendedMvPresentFlag = vc1PicParams->mv_fields.extended_mv_flag;
2202         cmd.DW3.FastuvmcflagFastUvMotionCompensationFlag = vc1PicParams->fast_uvmc_flag;
2203         cmd.DW3.LoopfilterEnableFlag = vc1PicParams->entrypoint_fields.loopfilter;
2204         cmd.DW3.RefdistFlag = (vc1PicParams->sequence_fields.AdvancedProfileFlag) ?
2205             vc1PicParams->reference_fields.reference_distance_flag : 1;
2206         cmd.DW3.PanscanPresentFlag = vc1PicParams->entrypoint_fields.panscan_flag;
2207 
2208         cmd.DW3.Maxbframes = vc1PicParams->sequence_fields.max_b_frames;
2209         cmd.DW3.RangeredPresentFlagForSimpleMainProfileOnly = vc1PicParams->sequence_fields.rangered;
2210         cmd.DW3.SyncmarkerPresentFlagForSimpleMainProfileOnly = vc1PicParams->sequence_fields.syncmarker;
2211         cmd.DW3.MultiresPresentFlagForSimpleMainProfileOnly = vc1PicParams->sequence_fields.multires;
2212         cmd.DW3.Quantizer = vc1PicParams->pic_quantizer_fields.quantizer;
2213         cmd.DW3.PPicRefDistance = vc1PicParams->reference_fields.reference_distance;
2214 
2215         cmd.DW3.ProgressivePicType = (CodecHal_PictureIsFrame(vc1PicParams->CurrPic)) ? 1 : 2;
2216         // Dynamic range adjustment disabled
2217         cmd.DW3.RangeReductionEnable = 0;
2218         cmd.DW3.RangeReductionScale = 1;
2219         if (vc1PicParams->sequence_fields.AdvancedProfileFlag)
2220         {
2221             cmd.DW3.OverlapSmoothingEnableFlag = vc1PicParams->sequence_fields.overlap;
2222         }
2223         else
2224         {
2225             cmd.DW3.OverlapSmoothingEnableFlag = 1;
2226             if (isBPicture || (vc1PicParams->pic_quantizer_fields.pic_quantizer_scale < 9) || !vc1PicParams->sequence_fields.overlap)
2227             {
2228                 cmd.DW3.OverlapSmoothingEnableFlag = 0;
2229             }
2230         }
2231 
2232         // DW 4
2233         cmd.DW4.ExtendedDmvPresentFlag = vc1PicParams->mv_fields.extended_dmv_flag;
2234         cmd.DW4.Psf = vc1PicParams->sequence_fields.psf;
2235         cmd.DW4.Finterflag = vc1PicParams->sequence_fields.finterpflag;
2236         cmd.DW4.Tfcntrflag = vc1PicParams->sequence_fields.tfcntrflag;
2237         cmd.DW4.Interlace = vc1PicParams->sequence_fields.interlace;
2238         cmd.DW4.Pulldown = vc1PicParams->sequence_fields.pulldown;
2239         cmd.DW4.PostprocFlag = vc1PicParams->post_processing;
2240         if (isPPicture || (isBPicture && vc1PicParams->sequence_fields.interlace))
2241         {
2242             cmd.DW4._4MvAllowedFlag = vc1PicParams->mv_fields.four_mv_allowed;
2243         }
2244         cmd.DW4.RefpicFlag = vc1PicParams->reference_fields.reference_picture_flag;
2245         if (isBPicture)
2246         {
2247             cmd.DW4.BfractionEnumeration = vc1PicParams->b_picture_fraction;
2248         }
2249 
2250         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2251 
2252         return eStatus;
2253     }
2254 
AddMfxVc1DirectmodeCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_VC1_DIRECTMODE_PARAMS params)2255     MOS_STATUS AddMfxVc1DirectmodeCmd(
2256         PMOS_COMMAND_BUFFER cmdBuffer,
2257         PMHW_VDBOX_VC1_DIRECTMODE_PARAMS params)
2258     {
2259         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2260 
2261         MHW_FUNCTION_ENTER;
2262 
2263         MHW_MI_CHK_NULL(m_osInterface);
2264         MHW_MI_CHK_NULL(cmdBuffer);
2265         MHW_MI_CHK_NULL(params);
2266 
2267         typename TMfxCmds::MFX_VC1_DIRECTMODE_STATE_CMD cmd;
2268 
2269         MHW_RESOURCE_PARAMS resourceParams;
2270         MOS_ZeroMemory(&resourceParams, sizeof(resourceParams));
2271         resourceParams.dwLsbNum = MHW_VDBOX_MFX_GENERAL_STATE_SHIFT;
2272         resourceParams.HwCommandType = MOS_MFX_VC1_DIRECT_MODE;
2273 
2274         cmd.DW3.MemoryObjectControlState =
2275             m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_DIRECTMV_BUFFER_CODEC].Value;
2276 
2277         resourceParams.presResource = params->presDmvWriteBuffer;
2278         resourceParams.dwOffset = 0;
2279         resourceParams.pdwCmd = &(cmd.DW1.Value);
2280         resourceParams.dwLocationInCmd = 1;
2281         resourceParams.bIsWritable = true;
2282 
2283         MHW_MI_CHK_STATUS(AddResourceToCmd(
2284             m_osInterface,
2285             cmdBuffer,
2286             &resourceParams));
2287 
2288         cmd.DW6.MemoryObjectControlState =
2289             m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_DIRECTMV_BUFFER_CODEC].Value;
2290 
2291         resourceParams.presResource = params->presDmvReadBuffer;
2292         resourceParams.dwOffset = 0;
2293         resourceParams.pdwCmd = &(cmd.DW4.Value);
2294         resourceParams.dwLocationInCmd = 4;
2295         resourceParams.bIsWritable = false;
2296 
2297         MHW_MI_CHK_STATUS(AddResourceToCmd(
2298             m_osInterface,
2299             cmdBuffer,
2300             &resourceParams));
2301 
2302         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2303 
2304         return eStatus;
2305     }
2306 
AddMfdVc1BsdObjectCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_VC1_SLICE_STATE vc1SliceState)2307     MOS_STATUS AddMfdVc1BsdObjectCmd(
2308         PMOS_COMMAND_BUFFER cmdBuffer,
2309         PMHW_VDBOX_VC1_SLICE_STATE vc1SliceState)
2310     {
2311         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2312 
2313         MHW_FUNCTION_ENTER;
2314 
2315         MHW_MI_CHK_NULL(m_osInterface);
2316         MHW_MI_CHK_NULL(cmdBuffer);
2317         MHW_MI_CHK_NULL(vc1SliceState);
2318         MHW_MI_CHK_NULL(vc1SliceState->pSlc);
2319 
2320         typename TMfxCmds::MFD_VC1_BSD_OBJECT_CMD cmd;
2321         auto slcParams = vc1SliceState->pSlc;
2322 
2323         cmd.DW1.IndirectBsdDataLength = vc1SliceState->dwLength;
2324 
2325         cmd.DW2.IndirectDataStartAddress = slcParams->slice_data_offset + vc1SliceState->dwOffset; // byte aligned
2326 
2327         cmd.DW3.SliceStartVerticalPosition = slcParams->slice_vertical_position;
2328         cmd.DW3.NextSliceVerticalPosition = vc1SliceState->dwNextVerticalPosition;
2329 
2330         cmd.DW4.FirstMbByteOffsetOfSliceDataOrSliceHeader = (slcParams->macroblock_offset >> 3) - vc1SliceState->dwOffset;
2331         cmd.DW4.FirstmbbitoffsetFirstMacroblockBitOffset = slcParams->macroblock_offset & 0x7; // bit offset
2332 
2333         MHW_CP_SLICE_INFO_PARAMS sliceInfoParam;
2334         sliceInfoParam.presDataBuffer = vc1SliceState->presDataBuffer;
2335         sliceInfoParam.dwDataStartOffset[0] = cmd.DW2.IndirectDataStartAddress;
2336 
2337         MHW_MI_CHK_STATUS(m_cpInterface->SetMfxProtectionState(
2338             m_decodeInUse,
2339             cmdBuffer,
2340             nullptr,
2341             &sliceInfoParam));
2342 
2343         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2344 
2345         return eStatus;
2346     }
2347 
2348     //!
2349     //! \struct   MFD_VC1_IT_OBJECT_CMD
2350     //! \brief    MFD VC1 it object command
2351     //!
2352     struct MFD_VC1_IT_OBJECT_CMD
2353     {
2354         typename TMfxCmds::MFD_IT_OBJECT_CMD m_header;
2355         typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD m_inlineData;
2356     };
2357 
2358     //!
2359     //! \brief    Get VC1 intra flag
2360     //!
2361     //! \param    [in] mbState
2362     //!           Pointer to MHW vdbox VC1 mb state
2363     //! \param    [in] mbParams
2364     //!           Pointer to codec VC1 mb parameters
2365     //!
2366     //! \return   uint8_t
2367     //!           VC1 intra flag
2368     //!
GetVc1IntraFlag(PMHW_VDBOX_VC1_MB_STATE mbState,PCODEC_VC1_MB_PARAMS mbParams)2369     uint8_t GetVc1IntraFlag(PMHW_VDBOX_VC1_MB_STATE mbState, PCODEC_VC1_MB_PARAMS mbParams)
2370     {
2371         const uint8_t PATTERN_CODE_INTRA_MB = 0xF;
2372         uint8_t intra8x8Flag = 0;
2373 
2374         if(mbState == nullptr || mbParams == nullptr)
2375         {
2376             MHW_ASSERTMESSAGE("mbState or mbParams is nullptr!");
2377             return 0;
2378         }
2379 
2380         if (mbParams->mb_type.intra_mb)
2381         {
2382             intra8x8Flag = PATTERN_CODE_INTRA_MB;
2383         }
2384         else if (mbParams->mb_type.motion_4mv && (mbState->PicFlags == PICTURE_FRAME))
2385         {
2386             intra8x8Flag = mbParams->pattern_code.block_luma_intra;
2387         }
2388         else
2389         {
2390             intra8x8Flag = 0;
2391         }
2392 
2393         return intra8x8Flag;
2394     }
2395 
2396     #define GET_VC1_BLOCK(mb, i) ((mb >> (3 - i)) & 1)
2397 
2398     //!
2399     //! \brief    VC1 it object set overlap smoothing filter
2400     //!
2401     //! \param    [in] inlineDataVc1
2402     //!           MFD it object VC1 inline data command
2403     //! \param    [in] mbState
2404     //!           Pointer to MHW vdbox VC1 mb state
2405     //! \param    [in] mbParams
2406     //!           Pointer to codec VC1 mb parameters
2407     //! \param    [in] mbHorizOrigin
2408     //!           Mb horizontal origin
2409     //! \param    [in] mbVertOrigin
2410     //!           Mb vertical origin
2411     //!
Vc1ItObjectSetOverlapSmoothingFilter(typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD * inlineDataVc1,PMHW_VDBOX_VC1_MB_STATE mbState,PCODEC_VC1_MB_PARAMS mbParams,uint8_t mbHorizOrigin,uint8_t mbVertOrigin)2412     MOS_STATUS Vc1ItObjectSetOverlapSmoothingFilter(
2413         typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD *inlineDataVc1,
2414         PMHW_VDBOX_VC1_MB_STATE mbState,
2415         PCODEC_VC1_MB_PARAMS mbParams,
2416         uint8_t mbHorizOrigin,
2417         uint8_t mbVertOrigin)
2418     {
2419         static const uint8_t chromaIntra[16] =
2420         {
2421             0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1
2422         };
2423         MHW_CHK_NULL_RETURN(inlineDataVc1);
2424         MHW_CHK_NULL_RETURN(mbState);
2425         MHW_CHK_NULL_RETURN(mbParams);
2426 
2427         auto vc1PicParams = mbState->pVc1PicParams;
2428         MHW_CHK_NULL_RETURN(vc1PicParams);
2429 
2430         //------------------------------------
2431         // Overlap smoothing enabled for this mb?
2432         //------------------------------------
2433         uint8_t mbOverlapSmoothing = mbParams->mb_type.h261_loopfilter;
2434         inlineDataVc1->DW0.Overlaptransform = mbOverlapSmoothing;
2435 
2436         // Horizontal origin is last mb of the row
2437         inlineDataVc1->DW0.Lastmbinrow = (mbHorizOrigin == (mbState->wPicWidthInMb - 1));
2438         // Vertical origin is last mb of the column
2439         inlineDataVc1->DW0.LastRowFlag = (mbVertOrigin == (mbState->wPicHeightInMb - 1));
2440 
2441         if (mbOverlapSmoothing)
2442         {
2443             uint8_t intra8x8 = GetVc1IntraFlag(mbState, mbParams);
2444 
2445             if ((vc1PicParams->picture_fields.picture_type == vc1BBField) || !intra8x8)
2446             {
2447                 // Reset parameters
2448                 inlineDataVc1->DW0.Overlaptransform = 0;
2449                 inlineDataVc1->DW1.Osedgemaskluma = 0;
2450                 inlineDataVc1->DW1.Osedgemaskchroma = 0;
2451 
2452                 return MOS_STATUS_SUCCESS;
2453             }
2454 
2455             //------------------------------------
2456             // Set edge control bitmasks (luma & chroma)
2457             //------------------------------------
2458 
2459             // Overlap smoothing applied to an edge when
2460             // 1. Edge between two 8x8 luma regions or corresponding 4x4
2461             //    chroma regions of the same mb for which the H261loopFilter
2462             //    flag is equal to 1
2463             // 2. Edge between 8x8 luma regions or corresponding 4x4 chroma
2464             //    regions in different MBs for which both are true:
2465             //    a. H261loopFilter flag is equal to 1 in both macroblocks, and
2466             //    b. Edge is a vertical edge between horizontally-neighboring macroblocks,
2467             //       OR is a horizontal edge between vertically-neighboring macroblocks and
2468             //       ReservedBits flag (bit 11) is equal to 0 in the wMBtype element of the
2469             //       macroblock control command for the lower macroblock and the picture is not an
2470             //       interlaced frame (i.e., a picture with bPicStructure equal to '11' and
2471             //        bPicExtrapolation equal to 2).
2472 
2473             // Condition 1: Top Y2, Top Y3, Left Y1, Left Y3
2474             uint16_t edgeMaskLuma = 0, edgeMaskChroma = 0;
2475             edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(intra8x8, 2)) << 2;
2476             edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 1) & GET_VC1_BLOCK(intra8x8, 3)) << 3;
2477             edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(intra8x8, 1)) << 5;
2478             edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 2) & GET_VC1_BLOCK(intra8x8, 3)) << 7;
2479 
2480             // Condition 2:
2481             // Top Y0, Top Y1, Top Cb/Cr: horizontal edges
2482             if (mbVertOrigin != 0)
2483             {
2484                 // Not the top row, so get upper pMB
2485                 auto upperMbParams = mbParams - mbState->wPicWidthInMb;
2486 
2487                 if (upperMbParams                          &&
2488                     upperMbParams->mb_type.h261_loopfilter &&
2489                     !mbParams->mb_type.reserved &&
2490                     (mbState->PicFlags != PICTURE_INTERLACED_FRAME))
2491                 {
2492                     uint8_t adjIntra8x8 = GetVc1IntraFlag(mbState, upperMbParams);
2493                     edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(adjIntra8x8, 2));
2494                     edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 1) & GET_VC1_BLOCK(adjIntra8x8, 3)) << 1;
2495                     edgeMaskChroma |= (chromaIntra[intra8x8] & chromaIntra[adjIntra8x8]);
2496                 }
2497             }
2498 
2499             // Left Y0, Left Y2, Left Cb/Cr: vertical edges
2500             if (mbHorizOrigin != 0)
2501             {
2502                 // Not the first column, so get left pMB
2503                 auto leftMbParams = mbParams - 1;
2504 
2505                 if (leftMbParams                           &&
2506                     leftMbParams->mb_type.h261_loopfilter)
2507                 {
2508                     uint8_t adjIntra8x8 = GetVc1IntraFlag(mbState, leftMbParams);
2509                     edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(adjIntra8x8, 1)) << 4;
2510                     edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 2) & GET_VC1_BLOCK(adjIntra8x8, 3)) << 6;
2511                     edgeMaskChroma |= (chromaIntra[intra8x8] & chromaIntra[adjIntra8x8]) << 1;
2512                 }
2513             }
2514 
2515             // Right Y1, Right Y3, Right Cb/Cr: vertical edges
2516             if (mbHorizOrigin != (mbState->wPicWidthInMb - 1))
2517             {
2518                 // Not the last column, so get right pMB
2519                 auto rightMbParams = mbParams + 1;
2520 
2521                 if (rightMbParams                           &&
2522                     rightMbParams->mb_type.h261_loopfilter)
2523                 {
2524                     uint8_t adjIntra8x8 = GetVc1IntraFlag(mbState, rightMbParams);
2525                     edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 1) & GET_VC1_BLOCK(adjIntra8x8, 0)) << 8;
2526                     edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 3) & GET_VC1_BLOCK(adjIntra8x8, 2)) << 9;
2527                     edgeMaskChroma |= (chromaIntra[intra8x8] & chromaIntra[adjIntra8x8]) << 2;
2528                 }
2529             }
2530 
2531             inlineDataVc1->DW1.Osedgemaskluma = edgeMaskLuma;
2532             inlineDataVc1->DW1.Osedgemaskchroma = edgeMaskChroma;
2533         }
2534         else
2535         {
2536             // Reset parameters
2537             inlineDataVc1->DW1.Osedgemaskluma = 0;
2538             inlineDataVc1->DW1.Osedgemaskchroma = 0;
2539         }
2540 
2541         return MOS_STATUS_SUCCESS;
2542     }
2543 
AddMfdVc1ItObjectCmd(PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_VC1_MB_STATE mbState)2544     MOS_STATUS AddMfdVc1ItObjectCmd(
2545         PMHW_BATCH_BUFFER batchBuffer,
2546         PMHW_VDBOX_VC1_MB_STATE mbState)
2547     {
2548         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2549 
2550         MHW_FUNCTION_ENTER;
2551 
2552         MHW_MI_CHK_NULL(batchBuffer);
2553         MHW_MI_CHK_NULL(mbState);
2554 
2555         auto mbParams = mbState->pMb;
2556         auto vc1PicParams = mbState->pVc1PicParams;
2557 
2558         MFD_VC1_IT_OBJECT_CMD cmd;
2559         typename TMfxCmds::MFD_IT_OBJECT_CMD *cmdMfdItObject = &cmd.m_header;
2560         typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD *inlineDataVc1 = &cmd.m_inlineData;
2561 
2562         inlineDataVc1->DW0.MacroblockIntraType = mpeg2Vc1MacroblockIntra;
2563 
2564         cmdMfdItObject->DW0.DwordLength += TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD::dwSize;
2565 
2566         if (mbState->bSkipped)
2567         {
2568             inlineDataVc1->DW0.DctType = mbParams->mb_type.field_residual;
2569 
2570             if (vc1PicParams->picture_fields.picture_type != vc1IIField)
2571             {
2572                 inlineDataVc1->DW0.MacroblockIntraType = mpeg2Vc1MacroblockNonintra;
2573                 inlineDataVc1->DW0.MacroblockMotionForward = mbParams->mb_type.motion_forward;
2574                 inlineDataVc1->DW0.MacroblockMotionBackward = mbParams->mb_type.motion_backward;
2575                 inlineDataVc1->DW0.MotionType = mbParams->mb_type.motion_type;
2576                 inlineDataVc1->DW0.MotionVerticalFieldSelect = (mbParams->mb_type.value & 0xF000) >> 12;
2577                 inlineDataVc1->DW1.Horzorigin = mbState->bMbHorizOrigin;
2578                 inlineDataVc1->DW1.Vertorigin = mbState->bMbVertOrigin;
2579                 inlineDataVc1->DW0.Lastmbinrow =
2580                     ((inlineDataVc1->DW1.Horzorigin == (mbState->wPicWidthInMb - 1)) &&
2581                     ((inlineDataVc1->DW1.Vertorigin == (mbState->wPicHeightInMb - 1))));
2582             }
2583 
2584             MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
2585 
2586             return eStatus;
2587         }
2588 
2589         // For VC-1 IT VFE Dword is Reserved : MBZ
2590         cmdMfdItObject->DW3.IndirectItCoeffDataLength = mbState->dwLength;
2591         cmdMfdItObject->DW4.IndirectItCoeffDataStartAddressOffset = mbState->dwOffset;
2592 
2593         // VC-1 inline data
2594         inlineDataVc1->DW0.MotionType = mbParams->mb_type.motion_type;
2595         inlineDataVc1->DW0.DctType = mbParams->mb_type.field_residual;
2596 
2597         inlineDataVc1->DW1.Horzorigin = mbState->bMbHorizOrigin;
2598         inlineDataVc1->DW1.Vertorigin = mbState->bMbVertOrigin;
2599 
2600         inlineDataVc1->DW7.SubblockCodeForY0 = mbParams->num_coef[0];
2601         inlineDataVc1->DW7.SubblockCodeForY1 = mbParams->num_coef[1];
2602         inlineDataVc1->DW7.SubblockCodeForY2 = mbParams->num_coef[2];
2603         inlineDataVc1->DW7.SubblockCodeForY3 = mbParams->num_coef[3];
2604         inlineDataVc1->DW8.SubblockCodeForCb = mbParams->num_coef[4];
2605         inlineDataVc1->DW8.SubblockCodeForCr = mbParams->num_coef[5];
2606 
2607         // Subblock coding information not present in bNumCoef for Interlace Frame
2608         // intra MBs, so when all 0 (i.e. subblock partition is 8x8) assume subblock present = 1
2609         if (MEDIA_IS_WA(m_waTable, WaAssumeSubblockPresent))
2610         {
2611             if ((mbState->PicFlags == PICTURE_INTERLACED_FRAME) && mbParams->mb_type.intra_mb &&
2612                 (inlineDataVc1->DW7.Value == 0) && (inlineDataVc1->DW8.Value == 0))
2613             {
2614                 inlineDataVc1->DW7.SubblockCodeForY0 |= 4;
2615                 inlineDataVc1->DW7.SubblockCodeForY1 |= 4;
2616                 inlineDataVc1->DW7.SubblockCodeForY2 |= 4;
2617                 inlineDataVc1->DW7.SubblockCodeForY3 |= 4;
2618                 inlineDataVc1->DW8.SubblockCodeForCb |= 4;
2619                 inlineDataVc1->DW8.SubblockCodeForCr |= 4;
2620             }
2621         }
2622 
2623         if (vc1PicParams->picture_fields.picture_type == vc1PFrame ||
2624             vc1PicParams->sequence_fields.AdvancedProfileFlag)
2625         {
2626             inlineDataVc1->DW9.IldbControlDataForBlockY0 = mbState->DeblockData[0];
2627             inlineDataVc1->DW9.IldbControlDataForBlockY1 = mbState->DeblockData[1];
2628             inlineDataVc1->DW9.IldbControlDataForBlockY2 = mbState->DeblockData[2];
2629             inlineDataVc1->DW9.IldbControlDataForBlockY3 = mbState->DeblockData[3];
2630             inlineDataVc1->DW10.IldbControlDataForCbBlock = mbState->DeblockData[4];
2631             inlineDataVc1->DW10.IldbControlDataForCrBlock = mbState->DeblockData[5];
2632         }
2633         else if (vc1PicParams->entrypoint_fields.loopfilter)
2634         {
2635             //driver generates the edge control value for I and B frames in VC1 Simple and Main profile
2636             if (mbState->bMbHorizOrigin == 0 && mbState->bMbVertOrigin == 0)
2637             {
2638                 inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X0Y0;
2639                 inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X0Y0;
2640             }
2641             else if (mbState->bMbHorizOrigin == 0)
2642             {
2643                 inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X0Y1;
2644                 inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X0Y1;
2645             }
2646             else if (mbState->bMbVertOrigin == 0)
2647             {
2648                 inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X1Y0;
2649                 inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X1Y0;
2650             }
2651             else
2652             {
2653                 inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X1Y1;
2654                 inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X1Y1;
2655             }
2656         }
2657         else
2658         {
2659             inlineDataVc1->DW9.Value = 0;
2660             inlineDataVc1->DW10.Value = 0;
2661         }
2662 
2663         if (vc1PicParams->picture_fields.picture_type == vc1IFrame)
2664         {
2665             // Intra MB
2666             inlineDataVc1->DW0.CodedBlockPattern = 63;
2667 
2668             MHW_MI_CHK_STATUS(Vc1ItObjectSetOverlapSmoothingFilter(
2669                 inlineDataVc1,
2670                 mbState,
2671                 mbParams,
2672                 mbState->bMbHorizOrigin,
2673                 mbState->bMbVertOrigin));
2674 
2675             MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
2676         }
2677         else
2678         {
2679             // Motion vectors
2680             inlineDataVc1->DW0.MotionVerticalFieldSelect = (mbParams->mb_type.value & 0xF000) >> 12;
2681             inlineDataVc1->DW0.Motion4Mv = mbParams->mb_type.motion_4mv;
2682             inlineDataVc1->DW0.MacroblockMotionForward = mbParams->mb_type.motion_forward;
2683             inlineDataVc1->DW0.MacroblockMotionBackward = mbParams->mb_type.motion_backward;
2684             inlineDataVc1->DW0.MacroblockIntraType = mbParams->mb_type.intra_mb;
2685             inlineDataVc1->DW0.CodedBlockPattern =
2686                 mbParams->mb_type.intra_mb ? 63 : mbParams->pattern_code.block_coded_pattern;
2687 
2688             if (mbParams->mb_type.motion_4mv && (mbState->PicFlags == PICTURE_FRAME))
2689             {
2690                 uint8_t cbp = (uint8_t)mbParams->pattern_code.block_luma_intra;
2691                 inlineDataVc1->DW0.CodedBlockPattern |= (cbp << 2); // Update luma residue blocks from intra Flags
2692                 inlineDataVc1->DW0.LumaIntra8X8Flag = mbParams->pattern_code.block_luma_intra;
2693                 inlineDataVc1->DW0.ChromaIntraFlag = mbParams->pattern_code.block_chroma_intra;
2694 
2695                 if (!mbParams->mb_type.intra_mb && (cbp == 0xF)) // top 4 bits of wPatternCode all set means intra
2696                 {
2697                     mbParams->mb_type.intra_mb = 1;
2698                     inlineDataVc1->DW0.MacroblockIntraType = 1;
2699                     inlineDataVc1->DW0.MotionType = 0; // Intra
2700                     inlineDataVc1->DW0.MacroblockMotionForward = 0;
2701                     inlineDataVc1->DW0.MacroblockMotionBackward = 0;
2702                 }
2703             }
2704 
2705             // Next, copy in the motion vectors if not skipped frame
2706             if (!mbParams->mb_type.intra_mb && mbState->dwDataSize)
2707             {
2708                 inlineDataVc1->DW2.Value = mbState->PackedLumaMvs[0];
2709                 inlineDataVc1->DW3.Value = mbState->PackedLumaMvs[1];
2710                 inlineDataVc1->DW4.Value = mbState->PackedLumaMvs[2];
2711                 inlineDataVc1->DW5.Value = mbState->PackedLumaMvs[3];
2712                 inlineDataVc1->DW6.Value =
2713                     (mbState->PicFlags == PICTURE_INTERLACED_FRAME) ? 0 : mbState->PackedChromaMv;
2714 
2715                 inlineDataVc1->DW0.MotionVerticalFieldSelect = (mbParams->mb_type.value & 0xF000) >> 12;
2716                 inlineDataVc1->DW0.Mvfieldselectchroma = mbState->bFieldPolarity;
2717                 inlineDataVc1->DW0.Mvswitch = mbState->bMotionSwitch;
2718             }
2719 
2720             if (!mbParams->mb_skips_following)
2721             {
2722                 MHW_MI_CHK_STATUS(Vc1ItObjectSetOverlapSmoothingFilter(
2723                     inlineDataVc1,
2724                     mbState,
2725                     mbParams,
2726                     mbState->bMbHorizOrigin,
2727                     mbState->bMbVertOrigin));
2728 
2729                 MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
2730             }
2731             else
2732             {
2733                 // Skipped MB's are inter MB's (no residual data, only MV's) so no overlap smoothing
2734                 uint16_t skippedMBs = (uint16_t)mbParams->mb_skips_following + 1;
2735 
2736                 for (uint16_t num = 0; num < skippedMBs; num++)
2737                 {
2738                     inlineDataVc1->DW0.CodedBlockPattern = 0;
2739                     inlineDataVc1->DW1.Horzorigin = (mbParams->mb_address + num) % mbState->wPicWidthInMb;
2740                     inlineDataVc1->DW1.Vertorigin = (mbParams->mb_address + num) / mbState->wPicWidthInMb;
2741 
2742                     // Reset overlap smoothing params
2743                     inlineDataVc1->DW0.Lastmbinrow = (inlineDataVc1->DW1.Horzorigin == (mbState->wPicWidthInMb - 1));
2744                     inlineDataVc1->DW0.LastRowFlag = (inlineDataVc1->DW1.Vertorigin == (mbState->wPicHeightInMb - 1));
2745                     inlineDataVc1->DW1.Osedgemaskluma = 0;
2746                     inlineDataVc1->DW1.Osedgemaskchroma = 0;
2747 
2748                     MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
2749                 }
2750             }
2751         }
2752 
2753         return eStatus;
2754     }
2755 
AddMfxJpegHuffTableCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_HUFF_TABLE_PARAMS params)2756     MOS_STATUS AddMfxJpegHuffTableCmd(
2757         PMOS_COMMAND_BUFFER cmdBuffer,
2758         PMHW_VDBOX_HUFF_TABLE_PARAMS params)
2759     {
2760         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2761 
2762         MHW_FUNCTION_ENTER;
2763 
2764         MHW_MI_CHK_NULL(m_osInterface);
2765         MHW_MI_CHK_NULL(cmdBuffer);
2766         MHW_MI_CHK_NULL(params);
2767         MHW_MI_CHK_NULL(params->pDCBits);
2768         MHW_MI_CHK_NULL(params->pDCValues);
2769         MHW_MI_CHK_NULL(params->pACBits);
2770         MHW_MI_CHK_NULL(params->pACValues);
2771 
2772         typename TMfxCmds::MFX_JPEG_HUFF_TABLE_STATE_CMD cmd;
2773 
2774         cmd.DW1.Hufftableid1Bit = params->HuffTableID;
2775 
2776         MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
2777             cmd.DcBits128BitArray,
2778             sizeof(cmd.DcBits128BitArray),
2779             params->pDCBits,
2780             sizeof(cmd.DcBits128BitArray)));
2781         MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
2782             cmd.DcHuffval128BitArray,
2783             sizeof(cmd.DcHuffval128BitArray),
2784             params->pDCValues,
2785             sizeof(cmd.DcHuffval128BitArray)));
2786         MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
2787             cmd.AcBits168BitArray,
2788             sizeof(cmd.AcBits168BitArray),
2789             params->pACBits,
2790             sizeof(cmd.AcBits168BitArray)));
2791         MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
2792             cmd.AcHuffval1608BitArray,
2793             sizeof(cmd.AcHuffval1608BitArray),
2794             params->pACValues,
2795             sizeof(cmd.AcHuffval1608BitArray)));
2796 
2797         MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
2798             &cmd.DW52.Value,
2799             sizeof(uint16_t),
2800             (uint8_t*)params->pACValues + sizeof(cmd.AcHuffval1608BitArray),
2801             sizeof(uint16_t)));
2802 
2803         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2804 
2805         return eStatus;
2806     }
2807 
AddMfxJpegBsdObjCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_JPEG_BSD_PARAMS params)2808     MOS_STATUS AddMfxJpegBsdObjCmd(
2809         PMOS_COMMAND_BUFFER cmdBuffer,
2810         PMHW_VDBOX_JPEG_BSD_PARAMS params)
2811     {
2812         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2813 
2814         MHW_FUNCTION_ENTER;
2815 
2816         MHW_MI_CHK_NULL(m_osInterface);
2817         MHW_MI_CHK_NULL(cmdBuffer);
2818         MHW_MI_CHK_NULL(params);
2819 
2820         typename TMfxCmds::MFD_JPEG_BSD_OBJECT_CMD cmd;
2821 
2822         cmd.DW1.IndirectDataLength = params->dwIndirectDataLength;
2823         cmd.DW2.IndirectDataStartAddress = params->dwDataStartAddress;
2824         cmd.DW3.ScanVerticalPosition = params->dwScanVerticalPosition;
2825         cmd.DW3.ScanHorizontalPosition = params->dwScanHorizontalPosition;
2826         cmd.DW4.McuCount = params->dwMCUCount;
2827         cmd.DW4.ScanComponents = params->sScanComponent;
2828         cmd.DW4.Interleaved = params->bInterleaved;
2829         cmd.DW5.Restartinterval16Bit = params->dwRestartInterval;
2830 
2831         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2832 
2833         return eStatus;
2834     }
2835 
AddMfdVp8BsdObjectCmd(PMOS_COMMAND_BUFFER cmdBuffer,PMHW_VDBOX_VP8_BSD_PARAMS params)2836     MOS_STATUS AddMfdVp8BsdObjectCmd(
2837         PMOS_COMMAND_BUFFER cmdBuffer,
2838         PMHW_VDBOX_VP8_BSD_PARAMS params)
2839     {
2840         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2841 
2842         MHW_FUNCTION_ENTER;
2843 
2844         MHW_MI_CHK_NULL(m_osInterface);
2845         MHW_MI_CHK_NULL(cmdBuffer);
2846         MHW_MI_CHK_NULL(params);
2847 
2848         typename TMfxCmds::MFD_VP8_BSD_OBJECT_CMD cmd;
2849         auto vp8PicParams = params->pVp8PicParams;
2850 
2851         uint8_t numPartitions = (1 << vp8PicParams->CodedCoeffTokenPartition);
2852 
2853         cmd.DW1.CodedNumOfCoeffTokenPartitions = vp8PicParams->CodedCoeffTokenPartition;
2854         cmd.DW1.Partition0CpbacEntropyRange = vp8PicParams->uiP0EntropyRange;
2855         cmd.DW1.Partition0CpbacEntropyCount = vp8PicParams->ucP0EntropyCount;
2856         cmd.DW2.Partition0CpbacEntropyValue = vp8PicParams->ucP0EntropyValue;
2857 
2858         cmd.DW3.IndirectPartition0DataLength = vp8PicParams->uiPartitionSize[0] + 1;
2859         cmd.DW4.IndirectPartition0DataStartOffset = vp8PicParams->uiFirstMbByteOffset;
2860 
2861         cmd.DW5.IndirectPartition1DataLength = vp8PicParams->uiPartitionSize[1] + 1;
2862         cmd.DW6.IndirectPartition1DataStartOffset = cmd.DW4.IndirectPartition0DataStartOffset +
2863             vp8PicParams->uiPartitionSize[0] +
2864             (numPartitions - 1) * 3;      // Account for P Sizes: 3 bytes per partition
2865                                             // excluding partition 0 and last partition.
2866 
2867         int32_t i = 2;
2868         if (i < ((1 + numPartitions)))
2869         {
2870             cmd.DW7.IndirectPartition2DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2871             cmd.DW8.IndirectPartition2DataStartOffset = cmd.DW6.IndirectPartition1DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2872         }
2873 
2874         i = 3;
2875         if (i < ((1 + numPartitions)))
2876         {
2877             cmd.DW9.IndirectPartition3DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2878             cmd.DW10.IndirectPartition3DataStartOffset = cmd.DW8.IndirectPartition2DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2879         }
2880 
2881         i = 4;
2882         if (i < ((1 + numPartitions)))
2883         {
2884             cmd.DW11.IndirectPartition4DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2885             cmd.DW12.IndirectPartition4DataStartOffset = cmd.DW10.IndirectPartition3DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2886         }
2887 
2888         i = 5;
2889         if (i < ((1 + numPartitions)))
2890         {
2891             cmd.DW13.IndirectPartition5DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2892             cmd.DW14.IndirectPartition5DataStartOffset = cmd.DW12.IndirectPartition4DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2893         }
2894 
2895         i = 6;
2896         if (i < ((1 + numPartitions)))
2897         {
2898             cmd.DW15.IndirectPartition6DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2899             cmd.DW16.IndirectPartition6DataStartOffset = cmd.DW14.IndirectPartition5DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2900         }
2901 
2902         i = 7;
2903         if (i < ((1 + numPartitions)))
2904         {
2905             cmd.DW17.IndirectPartition7DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2906             cmd.DW18.IndirectPartition7DataStartOffset = cmd.DW16.IndirectPartition6DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2907         }
2908 
2909         i = 8;
2910         if (i < ((1 + numPartitions)))
2911         {
2912             cmd.DW19.IndirectPartition8DataLength = vp8PicParams->uiPartitionSize[i] + 1;
2913             cmd.DW20.IndirectPartition8DataStartOffset = cmd.DW18.IndirectPartition7DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
2914         }
2915 
2916         MHW_MI_CHK_STATUS(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));
2917 
2918         return eStatus;
2919     }
2920 
2921 public:
GetAvcImgStateSize()2922     inline uint32_t GetAvcImgStateSize()
2923     {
2924         return TMfxCmds::MFX_AVC_IMG_STATE_CMD::byteSize;
2925     }
2926 
GetAvcSlcStateSize()2927     inline uint32_t GetAvcSlcStateSize()
2928     {
2929         return TMfxCmds::MFX_AVC_SLICE_STATE_CMD::byteSize;
2930     }
2931 
2932 };
2933 
2934 #endif
2935