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