1 /*
2 * Copyright (c) 2011-2020, 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     codechal_decode_mpeg2.cpp
24 //! \brief    Implements the decode interface extension for MPEG2.
25 //! \details  Implements all functions and constants required by CodecHal for MPEG2 decoding.
26 //!
27 
28 #include "codechal_decoder.h"
29 #include "codechal_decode_mpeg2.h"
30 #include "codechal_secure_decode_interface.h"
31 #include "codechal_mmc_decode_mpeg2.h"
32 #include "hal_oca_interface.h"
33 #if USE_CODECHAL_DEBUG_TOOL
34 #include <sstream>
35 #include <fstream>
36 #include "codechal_debug.h"
37 #endif
38 #include "mos_os_cp_interface_specific.h"
39 
40 #define CODECHAL_DECODE_MPEG2_IDCTBLOCK_SIZE   64
41 
42 // One MB size (16x16) intra MB, color = RGB[4, 4, 4]
43 const uint32_t CODECHAL_DECODE_MPEG2_WaDummyBitstream[] =
44 {0x01010000, 0x54e29752, 0x002022a5, //Dummy Slice 0, q_scale_type = 0, intra_vlc_format = 0
45  0x01010000, 0x4de29752, 0x8661341a, //Dummy Slice 1, q_scale_type = 0, intra_vlc_format = 1
46  0x01010000, 0x54e2a772, 0x002022a5, //Dummy Slice 2, q_scale_type = 1, intra_vlc_format = 0
47  0x01010000, 0x4de2a772, 0x8661341a  //Dummy Slice 3, q_scale_type = 1, intra_vlc_format = 1
48 };
49 
50 const uint32_t CODECHAL_DECODE_MPEG2_WaDummySliceLengths[] = {0x8, 0x8, 0x8, 0x8};
51 const uint32_t CODECHAL_DECODE_MPEG2_WaDummySliceOffsets[] = {0x4, 0x10, 0x1c, 0x28};
52 
DetectSliceError(uint16_t slcNum,uint32_t prevSliceMbEnd,bool firstValidSlice)53 bool CodechalDecodeMpeg2::DetectSliceError(
54     uint16_t                        slcNum,
55     uint32_t                        prevSliceMbEnd,
56     bool                            firstValidSlice)
57 {
58     bool                        result         = false;
59     CODECHAL_VLD_SLICE_RECORD   currSliceRecord = m_vldSliceRecord[slcNum];
60 
61     if (currSliceRecord.dwLength == 0 || currSliceRecord.dwLength > (uint32_t)(1 << (sizeof(uint32_t) * 8 - 1)))
62     {
63         result = true;
64     }
65     else if ((m_sliceParams[slcNum].m_sliceDataOffset + currSliceRecord.dwLength) >
66              m_dataSize)
67     {
68         // error handling for garbage data
69         result = true;
70     }
71     else if (m_slicesInvalid)
72     {
73         // If cp copy failed for this interation due to lack of buffer space, cannot use any
74         // slices in this iteration since there is no bitstream data for them
75         result = true;
76     }
77     else if (prevSliceMbEnd > currSliceRecord.dwSliceStartMbOffset ||
78              m_sliceParams[slcNum].m_sliceVerticalPosition >= m_picHeightInMb ||
79              m_sliceParams[slcNum].m_sliceHorizontalPosition >= m_picWidthInMb)
80     {
81         result = true;
82         m_slicesInvalid = true;
83     }
84     else if (!m_sliceParams[slcNum].m_numMbsForSlice)
85     {
86         // For SNB HW will not process BSD objects where the MbCount is 0, and if an invalid
87         // slice start position has been detected or the number of MBs in the current slice
88         // is invalid, the rest of the data may be garbage since SNB does not have
89         // robust error concealment for MPEG2 VLD, skipping these slices prevents HW hangs
90 
91         result = true;
92         m_slicesInvalid = true;
93     }
94     else if (m_sliceParams[slcNum].m_numMbsForSliceOverflow)
95     {
96         // Special case for last slice of an incomplete frame
97         if ((slcNum == m_numSlices - 1) &&
98             !firstValidSlice &&
99             ((currSliceRecord.dwSliceStartMbOffset + m_sliceParams[slcNum].m_numMbsForSlice) <
100                 (uint32_t)(m_picHeightInMb * m_picWidthInMb)))
101         {
102             m_sliceParams[slcNum].m_numMbsForSlice = m_picWidthInMb;
103         }
104         else
105         {
106             result = true;
107             m_slicesInvalid = true;
108         }
109     }
110 
111     return result;
112 }
113 
InsertDummySlices(PMHW_BATCH_BUFFER batchBuffer,uint16_t startMB,uint16_t endMB)114 MOS_STATUS CodechalDecodeMpeg2::InsertDummySlices(
115     PMHW_BATCH_BUFFER               batchBuffer,
116     uint16_t                        startMB,
117     uint16_t                        endMB)
118 {
119     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
120     bool      cpEnable = false;
121 
122     CODECHAL_DECODE_FUNCTION_ENTER;
123 
124     CODECHAL_DECODE_CHK_NULL_RETURN(batchBuffer);
125     CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface);
126     CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface->osCpInterface);
127 
128     //  A copied data buffer must be present
129     if (m_nextCopiedDataOffset && !m_dummySliceDataPresent)
130     {
131         // slice header uses 4 bytes
132         CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface(
133             sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream),
134             m_resMpeg2DummyBistream,
135             &m_resCopiedDataBuffer[m_currCopiedData],
136             &m_dummySliceDataOffset));
137 
138         m_dummySliceDataPresent = true;
139     }
140 
141     // force disable cp for dummy slices
142     cpEnable = m_osInterface->osCpInterface->IsCpEnabled();
143     if (cpEnable)
144     {
145         m_osInterface->osCpInterface->SetCpEnabled(false);
146     }
147 
148     uint16_t intraVLDFormat                = m_picParams->W0.m_intraVlcFormat;
149     uint16_t quantizerScaleType            = m_picParams->W0.m_quantizerScaleType;
150     uint16_t dummySliceIndex               = quantizerScaleType * 2 + intraVLDFormat;
151 
152     MHW_VDBOX_MPEG2_SLICE_STATE         mpeg2SliceState;
153     mpeg2SliceState.presDataBuffer      = nullptr;
154     mpeg2SliceState.wPicWidthInMb       = m_picWidthInMb;
155     mpeg2SliceState.wPicHeightInMb      = m_picHeightInMb;
156     mpeg2SliceState.dwLength            =
157         CODECHAL_DECODE_MPEG2_WaDummySliceLengths[dummySliceIndex];
158     mpeg2SliceState.dwOffset =
159         m_dummySliceDataOffset + CODECHAL_DECODE_MPEG2_WaDummySliceOffsets[dummySliceIndex];
160 
161     bool isLastSlice                   = false;
162     uint16_t expectedEndMB                 = m_picWidthInMb * m_picHeightInMb;
163 
164     CodecDecodeMpeg2SliceParams slc;
165     MOS_ZeroMemory(&slc, sizeof(CodecDecodeMpeg2SliceParams));
166 
167     while (startMB < endMB)
168     {
169         slc.m_macroblockOffset           = 6;
170         slc.m_sliceHorizontalPosition     = startMB % m_picWidthInMb;
171         slc.m_sliceVerticalPosition       = startMB / m_picWidthInMb;
172         slc.m_quantiserScaleCode        = 10;
173         slc.m_numMbsForSlice              = 1;
174 
175         isLastSlice = ((startMB + 1) == expectedEndMB);
176 
177         mpeg2SliceState.pMpeg2SliceParams       = &slc;
178         mpeg2SliceState.dwSliceStartMbOffset    = startMB;
179         mpeg2SliceState.bLastSlice              = isLastSlice;
180 
181         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2BsdObject(
182             nullptr,
183             batchBuffer,
184             &mpeg2SliceState));
185 
186         startMB++;
187     }
188 
189     // restore Cp state
190     if (cpEnable)
191     {
192         m_osInterface->osCpInterface->SetCpEnabled(true);
193     }
194 
195     if (isLastSlice)
196     {
197         m_incompletePicture = false;
198     }
199 
200     return eStatus;
201 }
202 
CopyDataSurface(uint32_t dataSize,MOS_RESOURCE sourceSurface,PMOS_RESOURCE copiedSurface,uint32_t * currOffset)203 MOS_STATUS CodechalDecodeMpeg2::CopyDataSurface(
204     uint32_t                        dataSize,
205     MOS_RESOURCE                    sourceSurface,
206     PMOS_RESOURCE                   copiedSurface,
207     uint32_t                        *currOffset)
208 {
209     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
210 
211     CODECHAL_DECODE_FUNCTION_ENTER;
212 
213     if (Mos_ResourceIsNull(copiedSurface))
214     {
215         // Allocate resCopiedDataBuffer if not already allocated.
216         CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
217                                                       copiedSurface,
218                                                       m_copiedDataBufferSize,
219                                                       "CopiedDataBuffer"),
220             "Failed to allocate copied residual data buffer.");
221     }
222 
223     if ((m_nextCopiedDataOffset + dataSize) > m_copiedDataBufferSize)
224     {
225         CODECHAL_DECODE_ASSERTMESSAGE("Copied data buffer is not large enough.");
226 
227         m_slicesInvalid = true;
228         return MOS_STATUS_UNKNOWN;
229     }
230 
231     uint32_t size = MOS_ALIGN_CEIL(dataSize, 16); // 16 byte aligned
232 
233     // HuC is not supported on BDW
234     if (m_hwInterface->m_noHuC)
235     {
236         CodechalDataCopyParams dataCopyParams;
237         MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams));
238         dataCopyParams.srcResource = &sourceSurface;
239         dataCopyParams.srcSize = size;
240         dataCopyParams.srcOffset = 0;
241         dataCopyParams.dstResource = copiedSurface;
242         dataCopyParams.dstSize = size;
243         dataCopyParams.dstOffset   = m_nextCopiedDataOffset;
244 
245         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(
246             &dataCopyParams));
247 
248         *currOffset = m_nextCopiedDataOffset;
249         m_nextCopiedDataOffset += MOS_ALIGN_CEIL(size, MHW_CACHELINE_SIZE);  // 64-byte aligned
250         return MOS_STATUS_SUCCESS;
251     }
252 
253     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
254         m_osInterface,
255         m_videoContextForWa));
256     m_osInterface->pfnResetOsStates(m_osInterface);
257 
258     m_osInterface->pfnSetPerfTag(
259         m_osInterface,
260         (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE));
261     m_osInterface->pfnResetPerfBufferID(m_osInterface);
262 
263     MOS_COMMAND_BUFFER cmdBuffer;
264     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
265         m_osInterface,
266         &cmdBuffer,
267         0));
268 
269     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
270         &cmdBuffer,
271         false));
272 
273     // Use huc stream out to do the copy
274     CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy(
275         &cmdBuffer,                // pCmdBuffer
276         &sourceSurface,            // presSrc
277         copiedSurface,             // presDst
278         size,                      // u32CopyLength
279         0,                         // u32CopyInputOffset
280         m_nextCopiedDataOffset));  // u32CopyOutputOffset
281 
282     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
283     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
284     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
285         &cmdBuffer,
286         &flushDwParams));
287 
288     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
289         &cmdBuffer,
290         nullptr));
291 
292     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
293 
294     if (!m_incompletePicture)
295     {
296         MOS_SYNC_PARAMS syncParams      = g_cInitSyncParams;
297         syncParams.GpuContext           = m_videoContext;
298         syncParams.presSyncResource     = &m_resSyncObjectVideoContextInUse;
299 
300         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
301 
302         syncParams                      = g_cInitSyncParams;
303         syncParams.GpuContext           = m_videoContextForWa;
304         syncParams.presSyncResource     = &m_resSyncObjectVideoContextInUse;
305 
306         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
307     }
308 
309     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
310         m_osInterface,
311         &cmdBuffer,
312         m_videoContextForWaUsesNullHw));
313 
314     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
315         m_osInterface,
316         m_videoContext));
317 
318     *currOffset = m_nextCopiedDataOffset;
319     m_nextCopiedDataOffset += MOS_ALIGN_CEIL(size, 64);  // offsets are 64-byte aligned
320 
321     return eStatus;
322 }
323 
324 /*--------------------------------------------------------------------------
325 | Name      : CodecHalMpeg2Decode_InitializeBeginFrame
326 | Purpose   : Initialize MPEG2 incomplete frame values in the DecodeBeginFrame
327 | Arguments : IN -> pMpeg2State    : the pointer to mpeg2 state
328 IN -> pDecoder       : the pointer to codechal decoder structure
329 | Returns   : MOS_STATUS_SUCCESS : Function successfully completed its task
330 |             MOS_STATUS_UNKNOWN: Error condition encountered (frame will not be rendered)
331 \---------------------------------------------------------------------------*/
InitializeBeginFrame()332 MOS_STATUS CodechalDecodeMpeg2::InitializeBeginFrame()
333 {
334     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
335 
336     CODECHAL_DECODE_FUNCTION_ENTER;
337 
338     m_incompletePicture  = false;
339     m_copiedDataBufferInUse = false;
340     m_copiedDataOffset      = 0;
341     m_nextCopiedDataOffset  = 0;
342     m_lastMbAddress         = 0;
343     m_slicesInvalid         = false;
344 
345     m_currCopiedData =
346         (m_currCopiedData + 1) % CODECHAL_DECODE_MPEG2_COPIED_SURFACES;
347     m_dummySliceDataPresent = false;
348     m_dummySliceDataOffset  = 0;
349     m_bbInUsePerFrame       = 0;
350 
351     return eStatus;
352 }
353 
AllocateResources()354 MOS_STATUS CodechalDecodeMpeg2::AllocateResources ()
355 {
356     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
357 
358     CODECHAL_DECODE_FUNCTION_ENTER;
359 
360     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(
361         m_osInterface,
362         &m_resSyncObjectWaContextInUse));
363     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(
364         m_osInterface,
365         &m_resSyncObjectVideoContextInUse));
366 
367     CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalAllocateDataList(
368         m_mpeg2RefList,
369         CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2));
370 
371     for (uint32_t i = 0; i < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2; i++)
372     {
373         m_mpeg2RefList[i]->RefPic.PicFlags = PICTURE_INVALID;
374     }
375 
376     uint32_t numMacroblocks = m_picWidthInMb * m_picHeightInMb;
377 
378     if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD)
379     {
380         m_vldSliceRecord =
381             (PCODECHAL_VLD_SLICE_RECORD)MOS_AllocAndZeroMemory(numMacroblocks * sizeof(CODECHAL_VLD_SLICE_RECORD));
382         CODECHAL_DECODE_CHK_NULL_RETURN(m_vldSliceRecord);
383     }
384 
385     for (uint16_t i = 0; i < m_bbAllocated; i++)
386     {
387         MOS_ZeroMemory(&m_mediaObjectBatchBuffer[i], sizeof(MHW_BATCH_BUFFER));
388         uint32_t size = (m_standardDecodeSizeNeeded * numMacroblocks) + m_hwInterface->m_sizeOfCmdBatchBufferEnd;
389         CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
390             m_osInterface,
391             &m_mediaObjectBatchBuffer[i],
392             nullptr,
393             size));
394     }
395 
396     // Deblocking Filter Row Store Scratch buffer
397     //(Num MacroBlock Width) * (Num Cachlines) * (Cachline size)
398     CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
399                                                   &m_resMfdDeblockingFilterRowStoreScratchBuffer,
400                                                   m_picWidthInMb * 7 * CODECHAL_CACHELINE_SIZE,
401                                                   "DeblockingFilterScratch"),
402         "Failed to allocate BSD/MPC Row Store Scratch Buffer.");
403 
404     // MPR Row Store Scratch buffer
405     // (FrameWidth in MB) * (CacheLine size per MB) * 2
406     // IVB+ platforms need to have double MPR size for MBAFF
407     CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
408                                                   &m_resBsdMpcRowStoreScratchBuffer,
409                                                   ((uint32_t)(m_picWidthInMb * CODECHAL_CACHELINE_SIZE)) * 2,
410                                                   "MprScratchBuffer"),
411         "Failed to allocate AVC BSD MPR Row Store Scratch Buffer.");
412 
413     m_consecutiveMbErrorConcealmentInUse = true;
414 
415     // Dummy slice buffer
416     if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD)
417     {
418         uint32_t size = MOS_ALIGN_CEIL(sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream), 64);
419         CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
420                                                       &m_resMpeg2DummyBistream,
421                                                       size,
422                                                       "Mpeg2DummyBitstream"),
423             "Failed to allocate MPEG2 bitstream buffer for format switching WA.");
424 
425         CodechalResLock DummyBitstreamLock(m_osInterface, &m_resMpeg2DummyBistream);
426         auto data = DummyBitstreamLock.Lock(CodechalResLock::writeOnly);
427 
428         CODECHAL_DECODE_CHK_NULL_RETURN(data);
429 
430         MOS_ZeroMemory(data, size);
431         CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy(
432             data,
433             size,
434             (void *)CODECHAL_DECODE_MPEG2_WaDummyBitstream,
435             sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream)),
436             "Failed to copy memory.");
437 
438     }
439 
440     if (m_mode == CODECHAL_DECODE_MODE_MPEG2IDCT)
441     {
442         // The common indirect IT-COEFF data structure is defined as a uint32_t.
443         m_copiedDataBufferSize = (numMacroblocks + 2) *
444                                  (CODEC_NUM_BLOCK_PER_MB * CODECHAL_DECODE_MPEG2_IDCTBLOCK_SIZE * sizeof(uint32_t));
445     }
446     else
447     {
448         // Bitstream buffer size = height * width + dummy slice + 512 (for padding)
449         m_copiedDataBufferSize =
450             (m_picWidthInMb * m_picHeightInMb * CODECHAL_DECODE_MPEG2_BYTES_PER_MB) +
451             sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream) +
452             512;
453     }
454 
455     return eStatus;
456 }
457 
~CodechalDecodeMpeg2()458 CodechalDecodeMpeg2::~CodechalDecodeMpeg2 ()
459 {
460     CODECHAL_DECODE_FUNCTION_ENTER;
461 
462     CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
463 
464     m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectWaContextInUse);
465     m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse);
466 
467     CodecHalFreeDataList(m_mpeg2RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2);
468 
469     MOS_FreeMemory(m_vldSliceRecord);
470 
471     for (uint32_t i = 0; i < m_bbAllocated; i++)
472     {
473         Mhw_FreeBb(m_osInterface, &m_mediaObjectBatchBuffer[i], nullptr);
474     }
475 
476     m_osInterface->pfnFreeResource(
477         m_osInterface,
478         &m_resMfdDeblockingFilterRowStoreScratchBuffer);
479 
480     m_osInterface->pfnFreeResource(
481         m_osInterface,
482         &m_resBsdMpcRowStoreScratchBuffer);
483 
484     // Dummy slice buffer
485     if (!Mos_ResourceIsNull(&m_resMpeg2DummyBistream))
486     {
487         m_osInterface->pfnFreeResource(
488             m_osInterface,
489             &m_resMpeg2DummyBistream);
490     }
491 
492     for (uint32_t i = 0; i < CODECHAL_DECODE_MPEG2_COPIED_SURFACES; i++)
493     {
494         m_osInterface->pfnFreeResource(
495             m_osInterface,
496             &m_resCopiedDataBuffer[i]);
497     }
498 }
499 
SetFrameStates()500 MOS_STATUS CodechalDecodeMpeg2::SetFrameStates ()
501 {
502     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
503 
504     CODECHAL_DECODE_FUNCTION_ENTER;
505 
506     uint32_t totalMBInFrame = 0;
507 
508     CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface);
509     CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer);
510     CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_picParams);
511 
512     m_dataSize                            = m_decodeParams.m_dataSize;
513     m_dataOffset                          = m_decodeParams.m_dataOffset;
514     m_numSlices                           = m_decodeParams.m_numSlices;
515     m_picParams                           = (CodecDecodeMpeg2PicParams *)m_decodeParams.m_picParams;
516     m_sliceParams                         = (CodecDecodeMpeg2SliceParams *)m_decodeParams.m_sliceParams;
517     m_iqMatrixBuffer                      = (CodecMpeg2IqMatrix *)m_decodeParams.m_iqMatrixBuffer;
518     m_destSurface                         = *m_decodeParams.m_destSurface;
519     m_resDataBuffer                       = *m_decodeParams.m_dataBuffer;
520     m_numMacroblocks                      = m_decodeParams.m_numMacroblocks;
521     m_mbParams                            = (CodecDecodeMpeg2MbParams *)m_decodeParams.m_macroblockParams;
522     m_mpeg2ISliceConcealmentMode          = m_decodeParams.m_mpeg2ISliceConcealmentMode;
523     m_mpeg2PbSliceConcealmentMode         = m_decodeParams.m_mpeg2PBSliceConcealmentMode;
524     m_mpeg2PbSlicePredBiDirMvTypeOverride = m_decodeParams.m_mpeg2PBSlicePredBiDirMVTypeOverride;
525     m_mpeg2PbSlicePredMvOverride          = m_decodeParams.m_mpeg2PBSlicePredMVOverride;
526 
527     m_picWidthInMb  = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_picParams->m_horizontalSize);
528     m_picHeightInMb = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_picParams->m_verticalSize);
529 
530     // For some corrupted mpeg2 streams, need to use dwHeight or dwWidth because they are updated at decode create time.
531     // Horizontal_size or vertical_size may be different and wrong in first pic parameter.
532     totalMBInFrame = (m_picParams->m_currPic.PicFlags == PICTURE_FRAME) ? (CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width) * CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height))
533                                                                         : (CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width) * CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height) / 2);
534 
535     if (m_numSlices > totalMBInFrame)
536     {
537         CODECHAL_DECODE_ASSERTMESSAGE("Invalid slice number due to larger than MB number.");
538         return MOS_STATUS_INVALID_PARAMETER;
539     }
540 
541     PCODEC_REF_LIST destEntry = m_mpeg2RefList[m_picParams->m_currPic.FrameIdx];
542     MOS_ZeroMemory(destEntry, sizeof(CODEC_REF_LIST));
543     destEntry->RefPic    = m_picParams->m_currPic;
544     destEntry->resRefPic = m_destSurface.OsResource;
545 
546     m_statusReportFeedbackNumber = m_picParams->m_statusReportFeedbackNumber;
547 
548     MOS_ZeroMemory(m_vldSliceRecord, (m_numSlices * sizeof(CODECHAL_VLD_SLICE_RECORD)));
549 
550     if (IsFirstExecuteCall())
551     {
552         CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(InitializeBeginFrame(),
553             "Initial Beginframe in CodecHal failed.");
554     }
555 
556     uint32_t    firstMbAddress       = 0;
557     bool        skippedSlicePresent    = false;
558     bool        invalidFrame           = true;
559     uint32_t    numMBs               = 0;
560 
561     // Determine the number of MBs for MPEG2 VLD
562     if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD)
563     {
564         CODECHAL_DECODE_CHK_NULL_RETURN(m_sliceParams);
565 
566         CodecDecodeMpeg2SliceParams *slc = m_sliceParams;
567 
568         if (m_numSlices == 0)
569         {
570             CODECHAL_DECODE_ASSERTMESSAGE(
571                 "MPEG2 VLD slice data invalid, unable to determine final MB address.");
572             numMBs = m_lastMbAddress = 0;
573             return MOS_STATUS_INVALID_PARAMETER;
574         }
575         else
576         {
577             uint16_t lastSlice       = 0;
578             uint32_t prevSliceMbEnd        = m_lastMbAddress;
579             bool firstValidSlice       = m_incompletePicture ? true : false;
580 
581             for (uint16_t i = 0; i < m_numSlices; i++)
582             {
583                 uint32_t sliceStartMbOffset =
584                     slc->m_sliceHorizontalPosition +
585                     (slc->m_sliceVerticalPosition * m_picWidthInMb);
586 
587                 uint32_t slcLength = ((slc->m_sliceDataSize + 0x0007) >> 3);
588 
589                 // HW limitation and won't be fixed
590                 if (slcLength > 0x1FFE0)
591                 {
592                     slcLength = 0x1FFE0;
593                 }
594 
595                 uint32_t u32Offset = ((slc ->m_macroblockOffset & 0x0000fff8) >> 3); // #of bytes of header data in bitstream buffer (before video data)
596 
597                 slcLength                            -= u32Offset;
598                 m_vldSliceRecord[i].dwLength             = slcLength;
599                 m_vldSliceRecord[i].dwOffset             = u32Offset;
600                 m_vldSliceRecord[i].dwSliceStartMbOffset = sliceStartMbOffset;
601 
602                 if (DetectSliceError(i, prevSliceMbEnd, firstValidSlice))
603                 {
604                     m_vldSliceRecord[i].dwSkip = true;
605                     skippedSlicePresent        = true;
606                 }
607                 else
608                 {
609                     if (firstValidSlice)
610                     {
611                         // First MB Address
612                         firstMbAddress =
613                             slc->m_sliceHorizontalPosition +
614                             (slc->m_sliceVerticalPosition * m_picWidthInMb);
615                     }
616 
617                     lastSlice = i;
618                     firstValidSlice = false;
619                     invalidFrame = false;
620                 }
621 
622                 prevSliceMbEnd =
623                     m_vldSliceRecord[i].dwSliceStartMbOffset +
624                     slc->m_numMbsForSlice;
625 
626                 slc++;
627             }
628 
629             slc -= m_numSlices;
630             m_vldSliceRecord[lastSlice].bIsLastSlice = true;
631 
632             // Last MB Address
633             slc += lastSlice;
634 
635             numMBs =
636                 (uint16_t)(m_vldSliceRecord[lastSlice].dwSliceStartMbOffset +
637                            slc->m_numMbsForSlice);
638         }
639     }
640     else if (m_mode == CODECHAL_DECODE_MODE_MPEG2IDCT)
641     {
642         CODECHAL_DECODE_CHK_NULL_RETURN(m_mbParams);
643         numMBs = m_numMacroblocks;
644     }
645 
646     // It means all slices in the frame are wrong, we just need skip decoding for this frame
647     // and don't insert any dummy slices
648     if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD &&
649         invalidFrame && m_numSlices && !m_incompletePicture)
650     {
651         CODECHAL_DECODE_ASSERTMESSAGE("Current frame is invalid.");
652         return MOS_STATUS_UNKNOWN;
653     }
654 
655     // MPEG2 Error Concealment for Gen6+
656     // Applicable for both IT and VLD modes
657     bool copiedDataNeeded = (m_incompletePicture ||
658                              (numMBs != (m_picWidthInMb * m_picHeightInMb)));
659 
660     if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD)
661     {
662         copiedDataNeeded |= (skippedSlicePresent || firstMbAddress);
663     }
664 
665     if (copiedDataNeeded)
666     {
667         if (m_dataSize)
668         {
669             CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface(
670                 m_dataSize,
671                 m_resDataBuffer,
672                 &m_resCopiedDataBuffer[m_currCopiedData],
673                 &m_copiedDataOffset));
674         }
675 
676         m_copiedDataBufferInUse = true;
677     }
678 
679     m_perfType = (uint16_t)m_picParams->m_pictureCodingType;
680 
681     m_crrPic      = m_picParams->m_currPic;
682     m_secondField = m_picParams->m_secondField ? true : false;
683 
684     CODECHAL_DEBUG_TOOL(
685         CODECHAL_DECODE_CHK_NULL_RETURN(m_debugInterface);
686         m_debugInterface->m_currPic     = m_crrPic;
687         m_debugInterface->m_secondField = m_secondField;
688         m_debugInterface->m_frameType   = m_perfType;
689 
690         if (m_picParams) {
691             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams(
692                 m_picParams));
693         }
694 
695         if (m_iqMatrixBuffer) {
696             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpIQParams(
697                 m_iqMatrixBuffer));
698         }
699 
700         if (m_sliceParams) {
701             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpSliceParams(
702                 m_sliceParams,
703                 m_numSlices));
704         }
705 
706         if (m_mbParams) {
707             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpMbParams(
708                 m_mbParams));
709         }
710 
711     )
712 
713     return eStatus;
714 }
715 
DecodeStateLevel()716 MOS_STATUS CodechalDecodeMpeg2::DecodeStateLevel()
717 {
718     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
719 
720     CODECHAL_DECODE_FUNCTION_ENTER;
721 
722     uint8_t fwdRefIdx = (uint8_t)m_picParams->m_forwardRefIdx;
723     uint8_t bwdRefIdx = (uint8_t)m_picParams->m_backwardRefIdx;
724 
725     // Do not use data that has not been initialized
726     if (CodecHal_PictureIsInvalid(m_mpeg2RefList[fwdRefIdx]->RefPic))
727     {
728         fwdRefIdx = m_picParams->m_currPic.FrameIdx;
729     }
730     if (CodecHal_PictureIsInvalid(m_mpeg2RefList[bwdRefIdx]->RefPic))
731     {
732         bwdRefIdx = m_picParams->m_currPic.FrameIdx;
733     }
734 
735     MOS_COMMAND_BUFFER cmdBuffer;
736     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
737 
738     auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex);
739     HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters);
740 
741     MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
742     pipeModeSelectParams.Mode                  = m_mode;
743     pipeModeSelectParams.bStreamOutEnabled     = m_streamOutEnabled;
744     pipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled;
745     pipeModeSelectParams.bPreDeblockOutEnable  = !m_deblockingEnabled;
746 
747     MHW_VDBOX_SURFACE_PARAMS surfaceParams;
748     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
749     surfaceParams.Mode                      = m_mode;
750     surfaceParams.psSurface                 = &m_destSurface;
751 
752     MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams;
753     pipeBufAddrParams.Mode                      = m_mode;
754     if (m_deblockingEnabled)
755     {
756         pipeBufAddrParams.psPostDeblockSurface = &m_destSurface;
757     }
758     else
759     {
760         pipeBufAddrParams.psPreDeblockSurface = &m_destSurface;
761     }
762 
763 #ifdef _MMC_SUPPORTED
764     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams));
765 #endif
766 
767     // when there is not a forward or backward reference,
768     // the index is set to the destination frame index
769     m_presReferences[CodechalDecodeFwdRefTop] =
770         m_presReferences[CodechalDecodeFwdRefBottom] =
771             m_presReferences[CodechalDecodeBwdRefTop] =
772                 m_presReferences[CodechalDecodeBwdRefBottom] = &m_destSurface.OsResource;
773 
774     if (fwdRefIdx < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2)
775     {
776         m_presReferences[CodechalDecodeFwdRefTop] =
777             m_presReferences[CodechalDecodeFwdRefBottom] = &m_mpeg2RefList[fwdRefIdx]->resRefPic;
778     }
779     if (bwdRefIdx < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2)
780     {
781         m_presReferences[CodechalDecodeBwdRefTop] =
782             m_presReferences[CodechalDecodeBwdRefBottom] = &m_mpeg2RefList[bwdRefIdx]->resRefPic;
783     }
784 
785     // special case for second fields
786     if (m_picParams->m_secondField && m_picParams->m_pictureCodingType == P_TYPE)
787     {
788         if (m_picParams->m_topFieldFirst)
789         {
790             m_presReferences[CodechalDecodeFwdRefTop] =
791                 &m_destSurface.OsResource;
792         }
793         else
794         {
795             m_presReferences[CodechalDecodeFwdRefBottom] =
796                 &m_destSurface.OsResource;
797         }
798     }
799 
800     // set all ref pic addresses to valid addresses for error concealment purpose
801     for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++)
802     {
803         if (m_presReferences[i] == nullptr &&
804             MEDIA_IS_WA(m_waTable, WaDummyReference) &&
805             !Mos_ResourceIsNull(&m_dummyReference.OsResource))
806         {
807             m_presReferences[i] = &m_dummyReference.OsResource;
808         }
809     }
810 
811     CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
812         pipeBufAddrParams.presReferences,
813         sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC,
814         m_presReferences,
815         sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC));
816 
817     pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer =
818         &m_resMfdDeblockingFilterRowStoreScratchBuffer;
819 
820     if (m_streamOutEnabled)
821     {
822         pipeBufAddrParams.presStreamOutBuffer =
823             &(m_streamOutBuffer[m_streamOutCurrBufIdx]);
824     }
825 
826 #ifdef _MMC_SUPPORTED
827     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&pipeBufAddrParams));
828 #endif
829 
830     CODECHAL_DEBUG_TOOL(
831         for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++)
832         {
833             if (pipeBufAddrParams.presReferences[i])
834             {
835                 MOS_SURFACE dstSurface;
836 
837                 MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE));
838                 dstSurface.Format     = Format_NV12;
839                 dstSurface.OsResource = *(pipeBufAddrParams.presReferences[i]);
840                 CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
841                     m_osInterface,
842                     &dstSurface));
843 
844                 m_debugInterface->m_refIndex = (uint16_t)i;
845                 std::string refSurfName      = "RefSurf[" + std::to_string(static_cast<uint32_t>(m_debugInterface->m_refIndex)) + "]";
846                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
847                     &dstSurface,
848                     CodechalDbgAttr::attrDecodeReferenceSurfaces,
849                     refSurfName.data()));
850             }
851         }
852     )
853 
854     //set correctly indirect BSD object base address.
855     PMOS_RESOURCE indObjBase;
856     if (m_copiedDataBufferInUse)
857     {
858         indObjBase = &m_resCopiedDataBuffer[m_currCopiedData];
859     }
860     else
861     {
862         indObjBase = &m_resDataBuffer;
863     }
864 
865     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
866     MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
867     indObjBaseAddrParams.Mode               = m_mode;
868     indObjBaseAddrParams.dwDataSize =
869         m_copiedDataBufferInUse ? m_copiedDataBufferSize : m_dataSize;
870     indObjBaseAddrParams.presDataBuffer     = indObjBase;
871 
872     MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams;
873     MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams));
874     bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer;
875 
876     MHW_VDBOX_MPEG2_PIC_STATE mpeg2PicState;
877     mpeg2PicState.Mode                                  = m_mode;
878     mpeg2PicState.pMpeg2PicParams                       = m_picParams;
879     mpeg2PicState.bDeblockingEnabled                    = m_deblockingEnabled;
880     mpeg2PicState.dwMPEG2ISliceConcealmentMode          = m_mpeg2ISliceConcealmentMode;
881     mpeg2PicState.dwMPEG2PBSliceConcealmentMode         = m_mpeg2PbSliceConcealmentMode;
882     mpeg2PicState.dwMPEG2PBSlicePredBiDirMVTypeOverride = m_mpeg2PbSlicePredBiDirMvTypeOverride;
883     mpeg2PicState.dwMPEG2PBSlicePredMVOverride          = m_mpeg2PbSlicePredMvOverride;
884 
885     MHW_VDBOX_QM_PARAMS qmParams;
886     qmParams.Standard                       = CODECHAL_MPEG2;
887     qmParams.pMpeg2IqMatrix                 = m_iqMatrixBuffer;
888 
889     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
890         &cmdBuffer, true));
891 
892     if (m_statusQueryReportingEnabled)
893     {
894         CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(
895             &cmdBuffer));
896     }
897 
898     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(
899         &cmdBuffer,
900         &pipeModeSelectParams));
901 
902     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(
903         &cmdBuffer,
904         &surfaceParams));
905 
906     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(
907         &cmdBuffer,
908         &pipeBufAddrParams));
909 
910     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(
911         &cmdBuffer,
912         &indObjBaseAddrParams));
913 
914     if (CodecHalIsDecodeModeVLD(m_mode))
915     {
916         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(
917             &cmdBuffer,
918             &bspBufBaseAddrParams));
919     }
920 
921     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxMpeg2PicCmd(
922         &cmdBuffer,
923         &mpeg2PicState));
924 
925     if (CodecHalIsDecodeModeVLD(m_mode))
926     {
927         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd(
928             &cmdBuffer,
929             &qmParams));
930     }
931 
932     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
933 
934     return eStatus;
935 }
936 
DecodePrimitiveLevel()937 MOS_STATUS CodechalDecodeMpeg2::DecodePrimitiveLevel()
938 {
939     if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD)
940     {
941         return SliceLevel();
942     }
943     else
944     {
945         return MacroblockLevel();
946     }
947 }
948 
SliceLevel()949 MOS_STATUS CodechalDecodeMpeg2::SliceLevel()
950 {
951     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
952 
953     CODECHAL_DECODE_FUNCTION_ENTER;
954 
955     if ((m_decodePhantomMbs) || (m_incompletePicture))
956     {
957         if (m_bbInUsePerFrame >= m_bbAllocated / CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP)
958         {
959             m_bbAllocated += CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP;
960             if (m_bbAllocated >= CODECHAL_DECODE_MPEG2_MAXIMUM_BATCH_BUFFERS)
961             {
962                 CODECHAL_DECODE_ASSERTMESSAGE(
963                     "The number of MPEG2 second level batch buffer is not big enough to hold the whole frame.");
964                 return MOS_STATUS_EXCEED_MAX_BB_SIZE;
965             }
966 
967             for (uint32_t i = 0; i < CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; i++)
968             {
969                 uint32_t j = m_bbAllocated - i - 1;
970                 MOS_ZeroMemory(&m_mediaObjectBatchBuffer[j], sizeof(MHW_BATCH_BUFFER));
971 
972                 uint32_t u32Size = m_standardDecodeSizeNeeded * CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width) * CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height) +
973                     m_hwInterface->m_sizeOfCmdBatchBufferEnd;
974 
975                 CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
976                     m_osInterface,
977                     &m_mediaObjectBatchBuffer[j],
978                     nullptr,
979                     u32Size));
980                 m_mediaObjectBatchBuffer[j].bSecondLevel = true;
981             }
982         }
983     }
984 
985     MOS_COMMAND_BUFFER cmdBuffer;
986     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
987         m_osInterface,
988         &cmdBuffer,
989         0));
990 
991     MHW_BATCH_BUFFER batchBuffer = m_mediaObjectBatchBuffer[m_bbInUse];
992 
993     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
994         &cmdBuffer,
995         &batchBuffer));
996 
997     CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb(
998         m_osInterface,
999         &batchBuffer));
1000 
1001     if (m_decodePhantomMbs)
1002     {
1003         CODECHAL_DECODE_CHK_STATUS_RETURN(InsertDummySlices(
1004             &batchBuffer,
1005             m_lastMbAddress,
1006             m_picWidthInMb * m_picHeightInMb));
1007     }
1008     else
1009     {
1010         CodecDecodeMpeg2SliceParams *slc = m_sliceParams;
1011 
1012         uint16_t prevSliceMBEnd = m_lastMbAddress;
1013 
1014         for (uint16_t slcCount = 0; slcCount < m_numSlices; slcCount++)
1015         {
1016             if (!m_vldSliceRecord[slcCount].dwSkip)
1017             {
1018                 if (prevSliceMBEnd != m_vldSliceRecord[slcCount].dwSliceStartMbOffset)
1019                 {
1020                     CODECHAL_DECODE_CHK_STATUS_RETURN(InsertDummySlices(
1021                         &batchBuffer,
1022                         prevSliceMBEnd,
1023                         (uint16_t)m_vldSliceRecord[slcCount].dwSliceStartMbOffset));
1024                 }
1025 
1026                 if (m_vldSliceRecord[slcCount].bIsLastSlice)
1027                 {
1028                     uint16_t expectedFinalMb = m_picWidthInMb * m_picHeightInMb;
1029 
1030                     m_lastMbAddress =
1031                         (uint16_t)(m_vldSliceRecord[slcCount].dwSliceStartMbOffset +
1032                                    slc->m_numMbsForSlice);
1033 
1034                     if (m_lastMbAddress < expectedFinalMb)
1035                     {
1036                         m_incompletePicture              = true;
1037                         m_vldSliceRecord[slcCount].bIsLastSlice = false;
1038                     }
1039                     else
1040                     {
1041                         //Indicate It's complete picture now
1042                         m_incompletePicture              = false;
1043                     }
1044                 }
1045 
1046                 // static MPEG2 slice parameters
1047                 MHW_VDBOX_MPEG2_SLICE_STATE mpeg2SliceState;
1048                 mpeg2SliceState.presDataBuffer          = &m_resDataBuffer;
1049                 mpeg2SliceState.wPicWidthInMb           = m_picWidthInMb;
1050                 mpeg2SliceState.wPicHeightInMb          = m_picHeightInMb;
1051                 mpeg2SliceState.pMpeg2SliceParams       = slc;
1052                 mpeg2SliceState.dwLength                = m_vldSliceRecord[slcCount].dwLength;
1053                 mpeg2SliceState.dwOffset =
1054                     m_vldSliceRecord[slcCount].dwOffset + m_copiedDataOffset;
1055                 mpeg2SliceState.dwSliceStartMbOffset = m_vldSliceRecord[slcCount].dwSliceStartMbOffset;
1056                 mpeg2SliceState.bLastSlice           = m_vldSliceRecord[slcCount].bIsLastSlice;
1057 
1058                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2BsdObject(
1059                     nullptr,
1060                     &batchBuffer,
1061                     &mpeg2SliceState));
1062 
1063                 prevSliceMBEnd =
1064                     (uint16_t)(m_vldSliceRecord[slcCount].dwSliceStartMbOffset +
1065                                slc->m_numMbsForSlice);
1066             }
1067 
1068             slc++;
1069         }
1070     }
1071 
1072     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
1073         nullptr,
1074         &batchBuffer));
1075 
1076     CODECHAL_DEBUG_TOOL(
1077         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch(
1078             &batchBuffer,
1079             CODECHAL_NUM_MEDIA_STATES,
1080             "_DEC"));
1081     )
1082 
1083     CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb(
1084         m_osInterface,
1085         &batchBuffer,
1086         true));
1087 
1088     m_bbInUse = (m_bbInUse + 1) % m_bbAllocated;
1089     m_bbInUsePerFrame++;
1090 
1091     if (!m_incompletePicture)
1092     {
1093         // Check if destination surface needs to be synchronized
1094         MOS_SYNC_PARAMS syncParams          = g_cInitSyncParams;
1095         syncParams.GpuContext               = m_videoContext;
1096         syncParams.presSyncResource         = &m_destSurface.OsResource;
1097         syncParams.bReadOnly                = false;
1098         syncParams.bDisableDecodeSyncLock   = m_disableDecodeSyncLock;
1099         syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
1100 
1101         if (!CodecHal_PictureIsField(m_picParams->m_currPic) ||
1102             !m_picParams->m_secondField)
1103         {
1104             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(
1105                 m_osInterface,
1106                 &syncParams));
1107             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(
1108                 m_osInterface,
1109                 &syncParams));
1110 
1111             // Update the resource tag (s/w tag) for On-Demand Sync
1112             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
1113         }
1114 
1115         MHW_MI_FLUSH_DW_PARAMS flushDwParams;
1116         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
1117 
1118         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
1119             &cmdBuffer,
1120             &flushDwParams));
1121 
1122         // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
1123         if (m_osInterface->bTagResourceSync &&
1124             (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField))
1125         {
1126             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(
1127                 &cmdBuffer,
1128                 &syncParams));
1129         }
1130 
1131         if (m_statusQueryReportingEnabled)
1132         {
1133             CodechalDecodeStatusReport decodeStatusReport;
1134 
1135             decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
1136             decodeStatusReport.m_currDecodedPic     = m_picParams->m_currPic;
1137             decodeStatusReport.m_currDeblockedPic   = m_picParams->m_currPic;
1138             decodeStatusReport.m_codecStatus        = CODECHAL_STATUS_UNAVAILABLE;
1139             decodeStatusReport.m_currDecodedPicRes  = m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic;
1140 
1141             CODECHAL_DEBUG_TOOL(
1142                 decodeStatusReport.m_secondField = m_picParams->m_secondField ? true : false;
1143                 decodeStatusReport.m_frameType   = m_perfType;)
1144 
1145             CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(
1146                 decodeStatusReport,
1147                 &cmdBuffer));
1148         }
1149 
1150         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
1151             &cmdBuffer,
1152             nullptr));
1153 
1154         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1155 
1156         CODECHAL_DEBUG_TOOL(
1157             CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
1158                 &cmdBuffer,
1159                 CODECHAL_NUM_MEDIA_STATES,
1160                 "_DEC"));
1161 
1162             //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
1163             //    m_debugInterface,
1164             //    &cmdBuffer));
1165         )
1166 
1167         //Sync up complete frame
1168         syncParams                      = g_cInitSyncParams;
1169         syncParams.GpuContext           = m_videoContextForWa;
1170         syncParams.presSyncResource     = &m_resSyncObjectWaContextInUse;
1171 
1172         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
1173 
1174         syncParams                      = g_cInitSyncParams;
1175         syncParams.GpuContext           = m_videoContext;
1176         syncParams.presSyncResource     = &m_resSyncObjectWaContextInUse;
1177 
1178         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
1179 
1180         HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
1181 
1182         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
1183             m_osInterface,
1184             &cmdBuffer,
1185             m_videoContextUsesNullHw));
1186 
1187         CODECHAL_DEBUG_TOOL(
1188             m_mmc->UpdateUserFeatureKey(&m_destSurface);)
1189 
1190         if (m_statusQueryReportingEnabled)
1191         {
1192             CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(
1193                 m_videoContextUsesNullHw));
1194         }
1195 
1196         // Needs to be re-set for Linux buffer re-use scenarios
1197         m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic =
1198             m_destSurface.OsResource;
1199 
1200         // Send the signal to indicate decode completion, in case On-Demand Sync is not present
1201         if (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField)
1202         {
1203             syncParams                      = g_cInitSyncParams;
1204             syncParams.GpuContext           = m_videoContext;
1205             syncParams.presSyncResource     = &m_destSurface.OsResource;
1206 
1207             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
1208         }
1209     }
1210     else
1211     {
1212         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1213     }
1214 
1215     return eStatus;
1216 }
1217 
PackMotionVectors(CODEC_PICTURE_FLAG pic_flag,PMHW_VDBOX_MPEG2_MB_STATE mpeg2MbState)1218 void CodechalDecodeMpeg2::PackMotionVectors(
1219     CODEC_PICTURE_FLAG          pic_flag,
1220     PMHW_VDBOX_MPEG2_MB_STATE   mpeg2MbState)
1221 {
1222     CodecDecodeMpeg2MbParams *mbParams = mpeg2MbState->pMBParams;
1223 
1224     uint16_t motionType     = mbParams->MBType.m_motionType;
1225     uint16_t intelMotionType = CODECHAL_MPEG2_IMT_NONE;
1226 
1227     //convert to Intel Motion Type
1228     if (pic_flag == PICTURE_FRAME)
1229     {
1230         switch(motionType)
1231         {
1232         case CodechalDecodeMcFrame:
1233             intelMotionType = CODECHAL_MPEG2_IMT_FRAME_FRAME;
1234             break;
1235         case CodechalDecodeMcField:
1236             intelMotionType = CODECHAL_MPEG2_IMT_FRAME_FIELD;
1237             break;
1238         case CodechalDecodeMcDmv:
1239             intelMotionType = CODECHAL_MPEG2_IMT_FRAME_DUAL_PRIME;
1240             break;
1241         default:
1242             break;
1243         }
1244     }
1245     else // must be field picture...
1246     {
1247         switch(motionType)
1248         {
1249         case CodechalDecodeMcField:
1250             intelMotionType = CODECHAL_MPEG2_IMT_FIELD_FIELD;
1251             break;
1252         case CodechalDecodeMcDmv:
1253             intelMotionType = CODECHAL_MPEG2_IMT_FIELD_DUAL_PRIME;
1254             break;
1255         case CodechalDecodeMc16x8:
1256             intelMotionType = CODECHAL_MPEG2_IMT_16X8;
1257             break;
1258         default:
1259             break;
1260         }
1261     }
1262 
1263     int16_t *mv = mbParams->m_motionVectors;
1264 
1265     switch (intelMotionType)
1266     {
1267     case CODECHAL_MPEG2_IMT_16X8:
1268     case CODECHAL_MPEG2_IMT_FIELD_FIELD:
1269     case CODECHAL_MPEG2_IMT_FRAME_FRAME:
1270     case CODECHAL_MPEG2_IMT_FIELD_DUAL_PRIME:
1271         mpeg2MbState->sPackedMVs0[0] = (short)mv[CodechalDecodeRstFirstForwHorz];
1272         mpeg2MbState->sPackedMVs0[1] = (short)mv[CodechalDecodeRstFirstForwVert];
1273         mpeg2MbState->sPackedMVs0[2] = (short)mv[CodechalDecodeRstFirstBackHorz];
1274         mpeg2MbState->sPackedMVs0[3] = (short)mv[CodechalDecodeRstFirstBackVert];
1275         break;
1276 
1277     case CODECHAL_MPEG2_IMT_FRAME_FIELD:
1278     case CODECHAL_MPEG2_IMT_FRAME_DUAL_PRIME:
1279         mpeg2MbState->sPackedMVs0[0] = (short)mv[CodechalDecodeRstFirstForwHorz];
1280         mpeg2MbState->sPackedMVs0[1] = (short)(mv[CodechalDecodeRstFirstForwVert] >> 1) ;
1281         mpeg2MbState->sPackedMVs0[2] = (short)mv[CodechalDecodeRstFirstBackHorz];
1282         mpeg2MbState->sPackedMVs0[3] = (short)(mv[CodechalDecodeRstFirstBackVert] >> 1);
1283         break;
1284 
1285     default:
1286         break;
1287     }
1288 
1289     switch (intelMotionType)
1290     {
1291     case CODECHAL_MPEG2_IMT_16X8:
1292         mpeg2MbState->sPackedMVs1[0] = (short)mv[CodechalDecodeRstSecndForwHorz];
1293         mpeg2MbState->sPackedMVs1[1] = (short)mv[CodechalDecodeRstSecndForwVert];
1294         mpeg2MbState->sPackedMVs1[2] = (short)mv[CodechalDecodeRstSecndBackHorz];
1295         mpeg2MbState->sPackedMVs1[3] = (short)mv[CodechalDecodeRstSecndBackVert];
1296         break;
1297 
1298     case CODECHAL_MPEG2_IMT_FRAME_DUAL_PRIME:
1299         mpeg2MbState->sPackedMVs1[0] = (short)mv[CodechalDecodeRstFirstForwHorz];
1300         mpeg2MbState->sPackedMVs1[1] = (short)(mv[CodechalDecodeRstFirstForwVert] >> 1);
1301         mpeg2MbState->sPackedMVs1[2] = (short)mv[CodechalDecodeRstSecndBackHorz];
1302         mpeg2MbState->sPackedMVs1[3] = (short)(mv[CodechalDecodeRstSecndBackVert] >> 1);
1303         break;
1304 
1305     case CODECHAL_MPEG2_IMT_FRAME_FIELD:
1306         mpeg2MbState->sPackedMVs1[0] = (short)mv[CodechalDecodeRstSecndForwHorz];
1307         mpeg2MbState->sPackedMVs1[1] = (short)(mv[CodechalDecodeRstSecndForwVert] >> 1);
1308         mpeg2MbState->sPackedMVs1[2] = (short)mv[CodechalDecodeRstSecndBackHorz];
1309         mpeg2MbState->sPackedMVs1[3] = (short)(mv[CodechalDecodeRstSecndBackVert] >> 1);
1310         break;
1311 
1312     default:
1313         break;
1314     }
1315 }
InsertSkippedMacroblocks(PMHW_BATCH_BUFFER batchBuffer,PMHW_VDBOX_MPEG2_MB_STATE params,uint16_t nextMBStart,uint16_t skippedMBs)1316 MOS_STATUS CodechalDecodeMpeg2::InsertSkippedMacroblocks(
1317     PMHW_BATCH_BUFFER               batchBuffer,
1318     PMHW_VDBOX_MPEG2_MB_STATE       params,
1319     uint16_t                        nextMBStart,
1320     uint16_t                        skippedMBs)
1321 {
1322     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1323 
1324     CODECHAL_DECODE_FUNCTION_ENTER;
1325 
1326     CODECHAL_DECODE_CHK_NULL_RETURN(batchBuffer);
1327     CODECHAL_DECODE_CHK_NULL_RETURN(params);
1328     CODECHAL_DECODE_CHK_NULL_RETURN(params->pMBParams);
1329 
1330     //save the original MB params, and restore the orignal MB params when function exit.
1331     CodechalDecodeRestoreData<CodecDecodeMpeg2MbParams> MBParamsRestore(params->pMBParams);
1332 
1333     params->dwDCTLength                    = 0;
1334     params->dwITCoffDataAddrOffset         = 0;
1335     params->pMBParams->m_codedBlockPattern  = 0;
1336 
1337     MOS_ZeroMemory(params->sPackedMVs0,sizeof(params->sPackedMVs0));
1338     MOS_ZeroMemory(params->sPackedMVs1,sizeof(params->sPackedMVs1));
1339 
1340     for (uint16_t i = 0; i < skippedMBs; i++)
1341     {
1342         params->pMBParams->m_mbAddr = nextMBStart + i;
1343         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2ITObject(
1344             nullptr,
1345             batchBuffer,
1346             params));
1347     }
1348 
1349     return eStatus;
1350 }
1351 
MacroblockLevel()1352 MOS_STATUS CodechalDecodeMpeg2::MacroblockLevel()
1353 {
1354     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1355 
1356     CODECHAL_DECODE_FUNCTION_ENTER;
1357 
1358     if ((m_decodePhantomMbs) || (m_incompletePicture))
1359     {
1360         if (m_bbInUsePerFrame >= m_bbAllocated / CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP)
1361         {
1362             m_bbAllocated += CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP;
1363             if (m_bbAllocated >= CODECHAL_DECODE_MPEG2_MAXIMUM_BATCH_BUFFERS)
1364             {
1365                 CODECHAL_DECODE_ASSERTMESSAGE(
1366                     "The number of MPEG2 second level batch buffer is not big enough to hold the whole frame.");
1367                 return MOS_STATUS_EXCEED_MAX_BB_SIZE;
1368             }
1369 
1370             for (uint32_t i = 0; i < CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; i++)
1371             {
1372                 uint32_t j = m_bbAllocated - i - 1;
1373                 MOS_ZeroMemory(&m_mediaObjectBatchBuffer[j], sizeof(MHW_BATCH_BUFFER));
1374 
1375                 uint32_t u32Size = m_standardDecodeSizeNeeded * m_picWidthInMb * m_picHeightInMb +
1376                                    m_hwInterface->m_sizeOfCmdBatchBufferEnd;
1377 
1378                 CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
1379                     m_osInterface,
1380                     &m_mediaObjectBatchBuffer[j],
1381                     nullptr,
1382                     u32Size));
1383                 m_mediaObjectBatchBuffer[j].bSecondLevel = true;
1384             }
1385         }
1386     }
1387 
1388     MOS_COMMAND_BUFFER cmdBuffer;
1389     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
1390         m_osInterface,
1391         &cmdBuffer,
1392         0));
1393 
1394     MHW_BATCH_BUFFER batchBuffer = m_mediaObjectBatchBuffer[m_bbInUse];
1395 
1396     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
1397         &cmdBuffer,
1398         &batchBuffer));
1399 
1400     CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb(m_osInterface, &batchBuffer));
1401 
1402     //static member
1403     MHW_VDBOX_MPEG2_MB_STATE    mpeg2MbState;
1404     mpeg2MbState.wPicWidthInMb  = m_picWidthInMb;
1405     mpeg2MbState.wPicHeightInMb = m_picHeightInMb;
1406     mpeg2MbState.wPicCodingType = (uint16_t)m_picParams->m_pictureCodingType;
1407 
1408     if (m_decodePhantomMbs)
1409     {
1410         uint16_t u16NextMBStart = m_savedMpeg2MbParam.m_mbAddr + 1;  // = 1 + saved last MB's address in this picture.
1411         uint16_t numMBs      = (mpeg2MbState.wPicWidthInMb * mpeg2MbState.wPicHeightInMb) - u16NextMBStart;
1412 
1413         mpeg2MbState.pMBParams = &m_savedMpeg2MbParam;  //use saved last MB param to insert Skipped MBs.
1414         CODECHAL_DECODE_CHK_STATUS_RETURN(InsertSkippedMacroblocks(
1415             &batchBuffer,
1416             &mpeg2MbState,
1417             u16NextMBStart,
1418             numMBs));
1419         m_incompletePicture = false;
1420     }
1421     else
1422     {
1423         uint16_t expectedMBAddress = (m_incompletePicture) ? m_lastMbAddress : 0;
1424 
1425         for (uint16_t mbcount = 0; mbcount < m_numMacroblocks; mbcount++)
1426         {
1427             if (m_mbParams[mbcount].m_mbAddr >= expectedMBAddress)
1428             {
1429                 uint16_t skippedMBs = m_mbParams[mbcount].m_mbAddr - expectedMBAddress;
1430 
1431                 if (skippedMBs)
1432                 {
1433                     //insert skipped Macroblock, use the first available MB params to insert skipped MBs.
1434                     mpeg2MbState.pMBParams = &(m_mbParams[mbcount]);
1435                     CODECHAL_DECODE_CHK_STATUS_RETURN(InsertSkippedMacroblocks(
1436                         &batchBuffer,
1437                         &mpeg2MbState,
1438                         expectedMBAddress,
1439                         skippedMBs));
1440                 }
1441             }
1442 
1443             //common field for MBs in I picture and PB picture .
1444             mpeg2MbState.pMBParams   = &m_mbParams[mbcount];
1445             mpeg2MbState.dwDCTLength = 0;
1446             for (uint32_t i = 0; i < CODEC_NUM_BLOCK_PER_MB; i++)
1447             {
1448                 mpeg2MbState.dwDCTLength += m_mbParams[mbcount].m_numCoeff[i];
1449             }
1450 
1451             mpeg2MbState.dwITCoffDataAddrOffset = m_copiedDataOffset + (m_mbParams[mbcount].m_mbDataLoc << 2);  // byte offset
1452 
1453             //only for MB in PB picture.
1454             if (mpeg2MbState.wPicCodingType != I_TYPE)
1455             {
1456                 bool intraMB = mpeg2MbState.pMBParams->MBType.m_intraMb? true: false;
1457 
1458                 MOS_ZeroMemory(mpeg2MbState.sPackedMVs0,sizeof(mpeg2MbState.sPackedMVs0));
1459                 MOS_ZeroMemory(mpeg2MbState.sPackedMVs1,sizeof(mpeg2MbState.sPackedMVs1));
1460                 if ((!intraMB) && (mpeg2MbState.pMBParams->MBType.m_value &
1461                     (CODECHAL_DECODE_MPEG2_MB_MOTION_BACKWARD | CODECHAL_DECODE_MPEG2_MB_MOTION_FORWARD)))
1462                 {
1463                     PackMotionVectors(m_picParams->m_currPic.PicFlags, &mpeg2MbState);
1464                 }
1465             }
1466 
1467             // add IT OBJECT command for each macroblock
1468             CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2ITObject(
1469                 nullptr,
1470                 &batchBuffer,
1471                 &mpeg2MbState));
1472 
1473             if (mpeg2MbState.wPicCodingType != I_TYPE && m_mbParams[mbcount].m_mbSkipFollowing)
1474             {
1475                 uint16_t skippedMBs    = m_mbParams[mbcount].m_mbSkipFollowing;
1476                 uint16_t skippedMBSart = m_mbParams[mbcount].m_mbAddr + 1;
1477 
1478                 // Insert Skipped MBs
1479                 CODECHAL_DECODE_CHK_STATUS_RETURN(InsertSkippedMacroblocks(
1480                     &batchBuffer,
1481                     &mpeg2MbState,
1482                     skippedMBSart,
1483                     skippedMBs));
1484 
1485                 m_mbParams[mbcount].m_mbAddr += skippedMBs;
1486             }
1487 
1488             //save the last MB's parameters for later use to insert skipped MBs.
1489             m_savedMpeg2MbParam = m_mbParams[mbcount];
1490 
1491             expectedMBAddress = m_mbParams[mbcount].m_mbAddr + 1;
1492 
1493             // insert extra MBs to ensure expected number of MBs sent to HW
1494             if (mbcount + 1 == m_numMacroblocks)
1495             {
1496                 uint16_t expectedFinalMB = m_picWidthInMb * m_picHeightInMb;
1497 
1498                 if (expectedMBAddress != expectedFinalMB)
1499                 {
1500                     m_incompletePicture = true;
1501                     m_lastMbAddress     = expectedMBAddress;
1502                 }
1503                 else
1504                 {
1505                     m_incompletePicture = false;
1506                 }
1507             }
1508         }
1509     }
1510 
1511     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
1512         nullptr,
1513         &batchBuffer));
1514 
1515     CODECHAL_DEBUG_TOOL(
1516         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch(
1517             &batchBuffer,
1518             CODECHAL_NUM_MEDIA_STATES,
1519             "_DEC"));
1520     )
1521 
1522     CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb(m_osInterface, &batchBuffer, true));
1523 
1524     m_bbInUse = (m_bbInUse + 1) % m_bbAllocated;
1525     m_bbInUsePerFrame++;
1526 
1527     if (!m_incompletePicture)
1528     {
1529         // Check if destination surface needs to be synchronized
1530         MOS_SYNC_PARAMS syncParams          = g_cInitSyncParams;
1531         syncParams.GpuContext               = m_videoContext;
1532         syncParams.presSyncResource         = &m_destSurface.OsResource;
1533         syncParams.bReadOnly                = false;
1534         syncParams.bDisableDecodeSyncLock   = m_disableDecodeSyncLock;
1535         syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
1536 
1537         if (!CodecHal_PictureIsField(m_picParams->m_currPic) ||
1538             !m_picParams->m_secondField)
1539         {
1540             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(
1541                 m_osInterface,
1542                 &syncParams));
1543             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(
1544                 m_osInterface,
1545                 &syncParams));
1546 
1547             // Update the resource tag (s/w tag) for On-Demand Sync
1548             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
1549         }
1550 
1551         MHW_MI_FLUSH_DW_PARAMS flushDwParams;
1552         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
1553 
1554         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
1555             &cmdBuffer,
1556             &flushDwParams));
1557 
1558         // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
1559         if (m_osInterface->bTagResourceSync &&
1560             (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField))
1561         {
1562             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(
1563                 &cmdBuffer,
1564                 &syncParams));
1565         }
1566 
1567         if (m_statusQueryReportingEnabled)
1568         {
1569             CodechalDecodeStatusReport decodeStatusReport;
1570 
1571             decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
1572             decodeStatusReport.m_currDecodedPic     = m_picParams->m_currPic;
1573             decodeStatusReport.m_currDeblockedPic   = m_picParams->m_currPic;
1574             decodeStatusReport.m_codecStatus        = CODECHAL_STATUS_UNAVAILABLE;
1575             decodeStatusReport.m_currDecodedPicRes =
1576                 m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic;
1577 
1578             CODECHAL_DEBUG_TOOL(
1579                 decodeStatusReport.m_secondField = m_picParams->m_secondField ? true : false;
1580                 decodeStatusReport.m_frameType   = m_perfType;)
1581 
1582             CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(
1583                 decodeStatusReport,
1584                 &cmdBuffer));
1585         }
1586 
1587         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
1588             &cmdBuffer,
1589             nullptr));
1590 
1591         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1592 
1593         CODECHAL_DEBUG_TOOL(
1594         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
1595             &cmdBuffer,
1596             CODECHAL_NUM_MEDIA_STATES,
1597             "_DEC"));
1598 
1599         //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
1600         //    m_debugInterface,
1601         //    &cmdBuffer));
1602         )
1603 
1604         //Sync up complete frame
1605         syncParams                      = g_cInitSyncParams;
1606         syncParams.GpuContext           = m_videoContextForWa;
1607         syncParams.presSyncResource     = &m_resSyncObjectWaContextInUse;
1608 
1609         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
1610 
1611         syncParams                      = g_cInitSyncParams;
1612         syncParams.GpuContext           = m_videoContext;
1613         syncParams.presSyncResource     = &m_resSyncObjectWaContextInUse;
1614 
1615         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
1616 
1617         HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
1618 
1619         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
1620             m_osInterface,
1621             &cmdBuffer,
1622             m_videoContextUsesNullHw));
1623 
1624         CODECHAL_DEBUG_TOOL(
1625             m_mmc->UpdateUserFeatureKey(&m_destSurface);)
1626 
1627         if (m_statusQueryReportingEnabled)
1628         {
1629             CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(
1630                 m_videoContextUsesNullHw));
1631         }
1632 
1633         // Needs to be re-set for Linux buffer re-use scenarios
1634         m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic = m_destSurface.OsResource;
1635 
1636         // Send the signal to indicate decode completion, in case On-Demand Sync is not present
1637         if (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField)
1638         {
1639             syncParams                      = g_cInitSyncParams;
1640             syncParams.GpuContext           = m_videoContext;
1641             syncParams.presSyncResource     = &m_destSurface.OsResource;
1642 
1643             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
1644         }
1645     }
1646     else
1647     {
1648         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1649     }
1650 
1651     return eStatus;
1652 }
1653 
InitMmcState()1654 MOS_STATUS CodechalDecodeMpeg2::InitMmcState()
1655 {
1656 #ifdef _MMC_SUPPORTED
1657     m_mmc = MOS_New(CodechalMmcDecodeMpeg2, m_hwInterface, this);
1658     CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc);
1659 #endif
1660     return MOS_STATUS_SUCCESS;
1661 }
1662 
AllocateStandard(CodechalSetting * settings)1663 MOS_STATUS CodechalDecodeMpeg2::AllocateStandard (
1664     CodechalSetting *settings)
1665 {
1666     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1667 
1668     CODECHAL_DECODE_FUNCTION_ENTER;
1669 
1670     CODECHAL_DECODE_CHK_NULL_RETURN(settings);
1671 
1672     CODECHAL_DECODE_CHK_STATUS_RETURN(InitMmcState());
1673 
1674     m_width                         = settings->width;
1675     m_height                        = settings->height;
1676     m_picWidthInMb                  = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width);
1677     m_picHeightInMb                 = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height);
1678     m_bbAllocated                   = CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP;
1679 
1680     // Picture Level Commands
1681     CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMfxStateCommandsDataSize(
1682         m_mode,
1683         &m_commandBufferSizeNeeded,
1684         &m_commandPatchListSizeNeeded,
1685         0));
1686 
1687     // Primitive Level Commands
1688     CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMfxPrimitiveCommandsDataSize(
1689         m_mode,
1690         &m_standardDecodeSizeNeeded,
1691         &m_standardDecodePatchListSizeNeeded,
1692         0));
1693 
1694     CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResources());
1695 
1696     return eStatus;
1697 }
1698 
CodechalDecodeMpeg2(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)1699 CodechalDecodeMpeg2::CodechalDecodeMpeg2 (
1700     CodechalHwInterface   *hwInterface,
1701     CodechalDebugInterface* debugInterface,
1702     PCODECHAL_STANDARD_INFO standardInfo) :
1703     CodechalDecode(hwInterface, debugInterface, standardInfo)
1704 {
1705     CODECHAL_DECODE_FUNCTION_ENTER;
1706 
1707     MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface));
1708     MOS_ZeroMemory(m_presReferences, sizeof(m_presReferences));
1709     MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer));
1710     MOS_ZeroMemory(&m_resMfdDeblockingFilterRowStoreScratchBuffer, sizeof(m_resMfdDeblockingFilterRowStoreScratchBuffer));
1711     MOS_ZeroMemory(&m_resBsdMpcRowStoreScratchBuffer, sizeof(m_resBsdMpcRowStoreScratchBuffer));
1712     MOS_ZeroMemory(m_mpeg2RefList, sizeof(m_mpeg2RefList));
1713     MOS_ZeroMemory(m_mediaObjectBatchBuffer, sizeof(m_mediaObjectBatchBuffer));
1714     MOS_ZeroMemory(&m_resMpeg2DummyBistream, sizeof(m_resMpeg2DummyBistream));
1715     MOS_ZeroMemory(m_resCopiedDataBuffer, sizeof(m_resCopiedDataBuffer));
1716     MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse));
1717     MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse));
1718     MOS_ZeroMemory(&m_savedMpeg2MbParam, sizeof(m_savedMpeg2MbParam));
1719 #if (_DEBUG || _RELEASE_INTERNAL)
1720     m_reportFrameCrc = true;
1721 #endif
1722     m_hwInterface = hwInterface;
1723 }
1724 
1725 #if USE_CODECHAL_DEBUG_TOOL
DumpPicParams(CodecDecodeMpeg2PicParams * picParams)1726 MOS_STATUS CodechalDecodeMpeg2::DumpPicParams(
1727     CodecDecodeMpeg2PicParams *picParams)
1728 {
1729     CODECHAL_DEBUG_FUNCTION_ENTER;
1730 
1731     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
1732     {
1733         return MOS_STATUS_SUCCESS;
1734     }
1735 
1736     CODECHAL_DEBUG_CHK_NULL(picParams);
1737 
1738     std::ostringstream oss;
1739     oss.setf(std::ios::showbase | std::ios::uppercase);
1740 
1741     oss << "m_currPic FrameIdx: " << +picParams->m_currPic.FrameIdx << std::endl;
1742     oss << "m_currPic PicFlags: " << +picParams->m_currPic.PicFlags << std::endl;
1743     oss << "m_forwardRefIdx: " << +picParams->m_forwardRefIdx << std::endl;
1744     oss << "m_backwardRefIdx: " << +picParams->m_backwardRefIdx << std::endl;
1745     oss << "m_topFieldFirst: " << +picParams->m_topFieldFirst << std::endl;
1746     oss << "m_secondField: " << +picParams->m_secondField << std::endl;
1747     oss << "m_statusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl;
1748     //Dump union w0
1749     oss << "w0 m_value: " << +picParams->W0.m_value << std::endl;
1750     oss << "m_scanOrder: " << +picParams->W0.m_scanOrder << std::endl;
1751     oss << "m_intraVlcFormat: " << +picParams->W0.m_intraVlcFormat << std::endl;
1752     oss << "m_quantizerScaleType: " << +picParams->W0.m_quantizerScaleType << std::endl;
1753     oss << "m_concealmentMVFlag: " << +picParams->W0.m_concealmentMVFlag << std::endl;
1754     oss << "m_frameDctPrediction: " << +picParams->W0.m_frameDctPrediction << std::endl;
1755     oss << "m_topFieldFirst: " << +picParams->W0.m_topFieldFirst << std::endl;
1756     oss << "m_intraDCPrecision: " << +picParams->W0.m_intraDCPrecision << std::endl;
1757     //Dump union w1
1758     oss << "w1 m_value: " << +picParams->W1.m_value << std::endl;
1759     oss << "m_fcode11: " << +picParams->W1.m_fcode11 << std::endl;
1760     oss << "m_fcode10: " << +picParams->W1.m_fcode10 << std::endl;
1761     oss << "m_fcode01: " << +picParams->W1.m_fcode01 << std::endl;
1762     oss << "m_fcode00: " << +picParams->W1.m_fcode00 << std::endl;
1763     oss << "m_horizontalSize: " << +picParams->m_horizontalSize << std::endl;
1764     oss << "m_verticalSize: " << +picParams->m_verticalSize << std::endl;
1765     oss << "m_pictureCodingType: " << +picParams->m_pictureCodingType << std::endl;
1766 
1767     const char *fileName = m_debugInterface->CreateFileName(
1768         "_DEC",
1769         CodechalDbgBufferType::bufPicParams,
1770         CodechalDbgExtType::txt);
1771 
1772     std::ofstream ofs(fileName, std::ios::out);
1773     ofs << oss.str();
1774     ofs.close();
1775     return MOS_STATUS_SUCCESS;
1776 }
1777 
DumpSliceParams(CodecDecodeMpeg2SliceParams * sliceParams,uint32_t numSlices)1778 MOS_STATUS CodechalDecodeMpeg2::DumpSliceParams(
1779     CodecDecodeMpeg2SliceParams *sliceParams,
1780     uint32_t                     numSlices)
1781 {
1782     CODECHAL_DEBUG_FUNCTION_ENTER;
1783 
1784     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams))
1785     {
1786         return MOS_STATUS_SUCCESS;
1787     }
1788 
1789     CODECHAL_DEBUG_CHK_NULL(sliceParams);
1790 
1791     const char *fileName = m_debugInterface->CreateFileName(
1792         "_DEC",
1793         CodechalDbgBufferType::bufSlcParams,
1794         CodechalDbgExtType::txt);
1795 
1796     std::ostringstream oss;
1797     oss.setf(std::ios::showbase | std::ios::uppercase);
1798 
1799     CodecDecodeMpeg2SliceParams *sliceControl = nullptr;
1800 
1801     for (uint16_t i = 0; i < numSlices; i++)
1802     {
1803         sliceControl = &sliceParams[i];
1804 
1805         oss << "====================================================================================================" << std::endl;
1806         oss << "Data for Slice number = " << +i << std::endl;
1807         oss << "m_sliceDataSize: " << +sliceControl->m_sliceDataSize << std::endl;
1808         oss << "m_sliceDataOffset: " << +sliceControl->m_sliceDataOffset << std::endl;
1809         oss << "m_macroblockOffset: " << +sliceControl->m_macroblockOffset << std::endl;
1810         oss << "m_sliceHorizontalPosition: " << +sliceControl->m_sliceHorizontalPosition << std::endl;
1811         oss << "m_sliceVerticalPosition: " << +sliceControl->m_sliceVerticalPosition << std::endl;
1812         oss << "m_quantiserScaleCode: " << +sliceControl->m_quantiserScaleCode << std::endl;
1813         oss << "m_numMbsForSlice: " << +sliceControl->m_numMbsForSlice << std::endl;
1814         oss << "m_numMbsForSliceOverflow: " << +sliceControl->m_numMbsForSliceOverflow << std::endl;
1815         oss << "m_reservedBits: " << +sliceControl->m_reservedBits << std::endl;
1816         oss << "m_startCodeBitOffset: " << +sliceControl->m_startCodeBitOffset << std::endl;
1817 
1818         std::ofstream ofs;
1819         if (i == 0)
1820         {
1821             ofs.open(fileName, std::ios::out);
1822         }
1823         else
1824         {
1825             ofs.open(fileName, std::ios::app);
1826         }
1827         ofs << oss.str();
1828         ofs.close();
1829     }
1830 
1831     return MOS_STATUS_SUCCESS;
1832 }
1833 
DumpIQParams(CodecMpeg2IqMatrix * matrixData)1834 MOS_STATUS CodechalDecodeMpeg2::DumpIQParams(
1835     CodecMpeg2IqMatrix *matrixData)
1836 {
1837     CODECHAL_DEBUG_FUNCTION_ENTER;
1838 
1839     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrIqParams))
1840     {
1841         return MOS_STATUS_SUCCESS;
1842     }
1843 
1844     CODECHAL_DEBUG_CHK_NULL(matrixData);
1845 
1846     std::ostringstream oss;
1847     oss.setf(std::ios::showbase | std::ios::uppercase);
1848 
1849     if (matrixData->m_loadIntraQuantiserMatrix)
1850     {
1851         oss << "intra_QmatrixData:" << std::endl;
1852 
1853         for (uint8_t i = 0; i < 56; i += 8)
1854         {
1855             oss << "Qmatrix[" << +i / 8 << "]: ";
1856             for (uint8_t j = 0; j < 8; j++)
1857                 oss << +matrixData->m_intraQuantiserMatrix[i + j] << " ";
1858             oss << std::endl;
1859         }
1860     }
1861     if (matrixData->m_loadNonIntraQuantiserMatrix)
1862     {
1863         oss << "non_intra_QmatrixData:" << std::endl;
1864 
1865         for (uint8_t i = 0; i < 56; i += 8)
1866         {
1867             oss << "Qmatrix[" << +i / 8 << "]: ";
1868             for (uint8_t j = 0; j < 8; j++)
1869                 oss << +matrixData->m_nonIntraQuantiserMatrix[i + j] << " ";
1870             oss << std::endl;
1871         }
1872     }
1873     if (matrixData->m_loadChromaIntraQuantiserMatrix)
1874     {
1875         oss << "chroma_intra_QmatrixData:" << std::endl;
1876 
1877         for (uint8_t i = 0; i < 56; i += 8)
1878         {
1879             oss << "Qmatrix[" << +i / 8 << "]: ";
1880             for (uint8_t j = 0; j < 8; j++)
1881                 oss << +matrixData->m_chromaIntraQuantiserMatrix[i + j] << " ";
1882             oss << std::endl;
1883         }
1884     }
1885     if (matrixData->m_loadChromaNonIntraQuantiserMatrix)
1886     {
1887         oss << "chroma_non_intra_QmatrixData:" << std::endl;
1888 
1889         for (uint8_t i = 0; i < 56; i += 8)
1890         {
1891             oss << "Qmatrix[" << +i / 8 << "]: ";
1892             for (uint8_t j = 0; j < 8; j++)
1893                 oss << +matrixData->m_chromaNonIntraQuantiserMatrix[i + j] << " ";
1894             oss << std::endl;
1895         }
1896     }
1897 
1898     const char *fileName = m_debugInterface->CreateFileName(
1899         "_DEC",
1900         CodechalDbgBufferType::bufIqParams,
1901         CodechalDbgExtType::txt);
1902 
1903     std::ofstream ofs(fileName, std::ios::out);
1904     ofs << oss.str();
1905     ofs.close();
1906 
1907     return MOS_STATUS_SUCCESS;
1908 }
1909 
DumpMbParams(CodecDecodeMpeg2MbParams * mbParams)1910 MOS_STATUS CodechalDecodeMpeg2::DumpMbParams(
1911     CodecDecodeMpeg2MbParams *mbParams)
1912 {
1913     CODECHAL_DEBUG_FUNCTION_ENTER;
1914 
1915     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrMbParams))
1916     {
1917         return MOS_STATUS_SUCCESS;
1918     }
1919 
1920     CODECHAL_DEBUG_CHK_NULL(mbParams);
1921 
1922     std::ostringstream oss;
1923     oss.setf(std::ios::showbase | std::ios::uppercase);
1924 
1925     oss << "m_mbAddr: " << +mbParams->m_mbAddr << std::endl;
1926     //Dump union MBType
1927     oss << "MBType.m_intraMb: " << +mbParams->MBType.m_intraMb << std::endl;
1928     oss << "MBType.m_motionFwd: " << +mbParams->MBType.m_motionFwd << std::endl;
1929     oss << "MBType.m_motionBwd: " << +mbParams->MBType.m_motionBwd << std::endl;
1930     oss << "MBType.m_motion4mv: " << +mbParams->MBType.m_motion4mv << std::endl;
1931     oss << "MBType.m_h261Lpfilter: " << +mbParams->MBType.m_h261Lpfilter << std::endl;
1932     oss << "MBType.m_fieldResidual: " << +mbParams->MBType.m_fieldResidual << std::endl;
1933     oss << "MBType.m_mbScanMethod: " << +mbParams->MBType.m_mbScanMethod << std::endl;
1934     oss << "MBType.m_motionType: " << +mbParams->MBType.m_motionType << std::endl;
1935     oss << "MBType.m_hostResidualDiff: " << +mbParams->MBType.m_hostResidualDiff << std::endl;
1936     oss << "MBType.m_mvertFieldSel: " << +mbParams->MBType.m_mvertFieldSel << std::endl;
1937     oss << "m_mbSkipFollowing: " << +mbParams->m_mbSkipFollowing << std::endl;
1938     oss << "m_mbDataLoc: " << +mbParams->m_mbDataLoc << std::endl;
1939     oss << "m_codedBlockPattern: " << +mbParams->m_codedBlockPattern << std::endl;
1940 
1941     //Dump NumCoeff[CODEC_NUM_BLOCK_PER_MB]
1942     for (uint16_t i = 0; i < CODEC_NUM_BLOCK_PER_MB; ++i)
1943     {
1944         oss << "m_numCoeff[" << +i << "]: " << +mbParams->m_numCoeff[i] << std::endl;
1945     }
1946 
1947     //Dump motion_vectors[8],printing them in 4 value chunks per line
1948     for (uint8_t i = 0; i < 2; ++i)
1949     {
1950         oss << "m_motionVectors[" << +i * 4 << "-" << (+i * 4) + 3 << "]: ";
1951         for (uint8_t j = 0; j < 4; j++)
1952             oss << +mbParams->m_motionVectors[i * 4 + j] << " ";
1953         oss << std::endl;
1954     }
1955 
1956     const char *fileName = m_debugInterface->CreateFileName(
1957         "_DEC",
1958         CodechalDbgBufferType::bufMbParams,
1959         CodechalDbgExtType::txt);
1960 
1961     std::ofstream ofs(fileName, std::ios::out);
1962     ofs << oss.str();
1963     ofs.close();
1964     return MOS_STATUS_SUCCESS;
1965 }
1966 
1967 #endif
1968