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