1 /*
2 * Copyright (c) 2011-2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file codechal_debug.cpp
24 //! \brief Defines the debug interface shared by codec only.
25 //! \details The debug interface dumps output from Media based on in input config file.
26 //!
27 #include "codechal_debug.h"
28 #if USE_CODECHAL_DEBUG_TOOL
29 #include "codechal_debug_config_manager.h"
30 #include "codechal_encoder_base.h"
31 #include <iomanip>
32
CodechalDebugInterface()33 CodechalDebugInterface::CodechalDebugInterface()
34 {
35 memset(&m_currPic, 0, sizeof(CODEC_PICTURE));
36 memset(m_fileName, 0, sizeof(m_fileName));
37 memset(m_path, 0, sizeof(m_path));
38 }
39
~CodechalDebugInterface()40 CodechalDebugInterface::~CodechalDebugInterface()
41 {
42 if (nullptr != m_configMgr)
43 {
44 MOS_Delete(m_configMgr);
45 }
46 }
47
CheckGoldenReferenceExist()48 void CodechalDebugInterface::CheckGoldenReferenceExist()
49 {
50 std::ifstream crcGoldenRefStream(m_crcGoldenRefFileName);
51 m_goldenReferenceExist = crcGoldenRefStream.good() ? true : false;
52 }
53
Initialize(CodechalHwInterface * hwInterface,CODECHAL_FUNCTION codecFunction)54 MOS_STATUS CodechalDebugInterface::Initialize(
55 CodechalHwInterface *hwInterface,
56 CODECHAL_FUNCTION codecFunction)
57 {
58 CODECHAL_DEBUG_FUNCTION_ENTER;
59
60 CODECHAL_DEBUG_CHK_NULL(hwInterface);
61 m_hwInterface = hwInterface;
62 m_codecFunction = codecFunction;
63 m_osInterface = m_hwInterface->GetOsInterface();
64 m_cpInterface = m_hwInterface->GetCpInterface();
65 m_miInterface = m_hwInterface->GetMiInterface();
66
67 //dump loctaion is codechaldump
68 MediaDebugInterface::SetOutputFilePath();
69
70 m_configMgr = MOS_New(CodecDebugConfigMgr, this, m_codecFunction, m_outputFilePath);
71 CODECHAL_DEBUG_CHK_NULL(m_configMgr);
72 CODECHAL_DEBUG_CHK_STATUS(m_configMgr->ParseConfig(m_osInterface->pOsContext));
73
74 MediaDebugInterface::InitDumpLocation();
75
76 #if (_DEBUG || _RELEASE_INTERNAL)
77 MOS_USER_FEATURE_VALUE_DATA userFeatureData;
78 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
79 userFeatureData.i32Data = 0;
80 userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
81 MOS_UserFeature_ReadValue_ID(
82 NULL,
83 __MEDIA_USER_FEATURE_ENABLE_HW_DEBUG_HOOKS_ID,
84 &userFeatureData,
85 m_osInterface->pOsContext);
86 m_enableHwDebugHooks = userFeatureData.u32Data ? true : false;
87 CheckGoldenReferenceExist();
88 if (m_enableHwDebugHooks && m_goldenReferenceExist)
89 {
90 LoadGoldenReference();
91 }
92
93 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
94 userFeatureData.i32Data = -1;
95 userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
96 MOS_UserFeature_ReadValue_ID(
97 nullptr,
98 __MEDIA_USER_FEATURE_VALUE_CODECHAL_FRAME_NUMBER_TO_STOP_ID,
99 &userFeatureData,
100 m_osInterface->pOsContext);
101 m_stopFrameNumber = userFeatureData.i32Data;
102
103 MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
104 userFeatureData.i32Data = 0;
105 userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
106 MOS_UserFeature_ReadValue_ID(
107 nullptr,
108 __MEDIA_USER_FEATURE_VALUE_CODECHAL_ENABLE_SW_CRC_ID,
109 &userFeatureData,
110 m_osInterface->pOsContext);
111 m_swCRC = userFeatureData.i32Data == 0 ? false : true;
112 #endif
113
114 return MOS_STATUS_SUCCESS;
115 }
116
DumpHucDmem(PMOS_RESOURCE dmemResource,uint32_t dmemSize,uint32_t hucPassNum,CodechalHucRegionDumpType dumpType)117 MOS_STATUS CodechalDebugInterface::DumpHucDmem(
118 PMOS_RESOURCE dmemResource,
119 uint32_t dmemSize,
120 uint32_t hucPassNum,
121 CodechalHucRegionDumpType dumpType)
122 {
123 CODECHAL_DEBUG_FUNCTION_ENTER;
124
125 if (!m_configMgr->AttrIsEnabled(MediaDbgAttr::attrHuCDmem))
126 {
127 return MOS_STATUS_SUCCESS;
128 }
129
130 CODECHAL_DEBUG_CHK_NULL(dmemResource);
131 if (Mos_ResourceIsNull(dmemResource))
132 {
133 return MOS_STATUS_NULL_POINTER;
134 }
135
136 std::string funcName = "";
137 if (m_codecFunction == CODECHAL_FUNCTION_DECODE)
138 {
139 funcName = "DEC_";
140 }
141 else if (m_codecFunction == CODECHAL_FUNCTION_CENC_DECODE)
142 {
143 funcName = "DEC_Cenc_";
144 }
145 else
146 {
147 funcName = "ENC_";
148 }
149
150 std::string dmemName = MediaDbgBufferType::bufHucDmem;
151 std::string passName = std::to_string(hucPassNum);
152 switch (dumpType)
153 {
154 case hucRegionDumpInit:
155 funcName = funcName + dmemName + "_InitPass" + passName;
156 break;
157 case hucRegionDumpUpdate:
158 funcName = funcName + dmemName + "_UpdatePass" + passName;
159 break;
160 case hucRegionDumpRegionLocked:
161 funcName = funcName + dmemName + "_RegionLocked" + passName;
162 break;
163 case hucRegionDumpCmdInitializer:
164 funcName = funcName + dmemName + "_CmdInitializerPass" + passName;
165 break;
166 case hucRegionDumpPakIntegrate:
167 funcName = funcName + dmemName + "_PakIntPass" + passName;
168 break;
169 case hucRegionDumpHpu:
170 funcName = funcName + dmemName + "_HpuPass" + passName;
171 break;
172 case hucRegionDumpHpuSuperFrame:
173 funcName = funcName + dmemName + "_HpuPass" + passName + "_SuperFramePass";
174 break;
175 case hucRegionDumpBackAnnotation:
176 funcName = funcName + dmemName + "_BackAnnotationPass" + passName;
177 break;
178 default:
179 funcName = funcName + dmemName + "_Pass" + passName;
180 break;
181 }
182
183 return DumpBuffer(dmemResource, nullptr, funcName.c_str(), dmemSize);
184 }
185
SetOutputPathKey()186 MOS_USER_FEATURE_VALUE_ID CodechalDebugInterface::SetOutputPathKey()
187 {
188 return __MEDIA_USER_FEATURE_VALUE_CODECHAL_DEBUG_OUTPUT_DIRECTORY_ID;
189 }
190
InitDefaultOutput()191 MOS_USER_FEATURE_VALUE_ID CodechalDebugInterface::InitDefaultOutput()
192 {
193 m_outputFilePath.append(MEDIA_DEBUG_CODECHAL_DUMP_OUTPUT_FOLDER);
194 return SetOutputPathKey();
195 }
196
DetectCorruptionSw(std::vector<MOS_RESOURCE> & vResource,PMOS_RESOURCE frameCntRes,uint8_t * buf,uint32_t & size,uint32_t frameNum)197 MOS_STATUS CodechalDebugInterface::DetectCorruptionSw(std::vector<MOS_RESOURCE> &vResource, PMOS_RESOURCE frameCntRes, uint8_t *buf, uint32_t &size, uint32_t frameNum)
198 {
199 if (m_enableHwDebugHooks &&
200 m_goldenReferenceExist &&
201 m_goldenReferences.size() > 0 &&
202 vResource.size() > 0)
203 {
204 MOS_COMMAND_BUFFER cmdBuffer = {};
205 std::vector<uint32_t *> vSemaData;
206 MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
207 MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
208 genericPrologParams.pOsInterface = m_osInterface;
209 genericPrologParams.pvMiInterface = m_miInterface;
210
211 CODECHAL_DEBUG_CHK_STATUS(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
212 CODECHAL_DEBUG_CHK_STATUS(Mhw_SendGenericPrologCmd(
213 &cmdBuffer,
214 &genericPrologParams));
215 LockSemaResource(vSemaData, vResource);
216 // for CRC mismatch detection
217 for (uint32_t i = 0; i < vResource.size(); i++)
218 {
219 CODECHAL_DEBUG_CHK_STATUS(m_hwInterface->SendHwSemaphoreWaitCmd(
220 &vResource[i],
221 m_goldenReferences[frameNum][i],
222 MHW_MI_SAD_EQUAL_SDD,
223 &cmdBuffer));
224 }
225 StoreNumFrame(m_miInterface, frameCntRes, frameNum, &cmdBuffer);
226
227 SubmitDummyWorkload(&cmdBuffer, false);
228 //Get Decode output
229 std::vector<uint32_t> data = {CalculateCRC(buf, size)};
230 CODECHAL_DEBUG_CHK_STATUS(FillSemaResource(vSemaData, data));
231 }
232 return MOS_STATUS_SUCCESS;
233 }
234
DumpHucRegion(PMOS_RESOURCE region,uint32_t regionOffset,uint32_t regionSize,uint32_t regionNum,const char * regionName,bool inputBuffer,uint32_t hucPassNum,CodechalHucRegionDumpType dumpType)235 MOS_STATUS CodechalDebugInterface::DumpHucRegion(
236 PMOS_RESOURCE region,
237 uint32_t regionOffset,
238 uint32_t regionSize,
239 uint32_t regionNum,
240 const char * regionName,
241 bool inputBuffer,
242 uint32_t hucPassNum,
243 CodechalHucRegionDumpType dumpType)
244 {
245 CODECHAL_DEBUG_FUNCTION_ENTER;
246
247 if (!m_configMgr->AttrIsEnabled(MediaDbgAttr::attrHucRegions))
248 {
249 return MOS_STATUS_SUCCESS;
250 }
251 CODECHAL_DEBUG_ASSERT(regionNum < 16);
252 CODECHAL_DEBUG_CHK_NULL(region);
253
254 if (Mos_ResourceIsNull(region))
255 {
256 return MOS_STATUS_NULL_POINTER;
257 }
258
259 std::string funcName = "";
260 if (m_codecFunction == CODECHAL_FUNCTION_DECODE)
261 {
262 funcName = "DEC_";
263 }
264 else if (m_codecFunction == CODECHAL_FUNCTION_CENC_DECODE)
265 {
266 funcName = "DEC_CENC_";
267 }
268 else
269 {
270 funcName = "ENC_";
271 }
272
273 std::string bufName = MediaDbgBufferType::bufHucRegion;
274 std::string inputName = (inputBuffer) ? "Input_" : "Output_";
275 std::string regionNumName = std::to_string(regionNum);
276 std::string passName = std::to_string(hucPassNum);
277 switch (dumpType)
278 {
279 case hucRegionDumpInit:
280 funcName = funcName + inputName + bufName + regionNumName + regionName + "_InitPass" + passName;
281 break;
282 case hucRegionDumpUpdate:
283 funcName = funcName + inputName + bufName + regionNumName + regionName + "_UpdatePass" + passName;
284 break;
285 case hucRegionDumpRegionLocked:
286 funcName = funcName + inputName + bufName + regionNumName + regionName + "_RegionLockedPass" + passName;
287 break;
288 case hucRegionDumpCmdInitializer:
289 funcName = funcName + inputName + bufName + regionNumName + regionName + "_CmdInitializerPass" + passName;
290 break;
291 case hucRegionDumpPakIntegrate:
292 funcName = funcName + inputName + bufName + regionNumName + regionName + "_PakIntPass" + passName;
293 break;
294 case hucRegionDumpHpu:
295 funcName = funcName + inputName + bufName + regionNumName + regionName + "_HpuPass" + passName;
296 break;
297 case hucRegionDumpBackAnnotation:
298 funcName = funcName + inputName + bufName + regionNumName + regionName + "_BackAnnotationPass" + passName;
299 break;
300 default:
301 funcName = funcName + inputName + bufName + regionNumName + regionName + "_Pass" + passName;
302 break;
303 }
304
305 return DumpBuffer(region, nullptr, funcName.c_str(), regionSize, regionOffset);
306 }
307
DumpEncodeStatusReport(void * report)308 MOS_STATUS CodechalDebugInterface::DumpEncodeStatusReport(void* report)
309 {
310 CODECHAL_DEBUG_ASSERTMESSAGE("WARNING: DumpEncodeStatusReport(void* report) is used. Make sure that pointer contains ::EncodeStatusReport or similar struct");
311 return DumpEncodeStatusReport((EncodeStatusReport*)report);
312 }
313
314 #define FIELD_TO_OFS(field_name) ofs << print_shift << std::setfill(' ') << std::setw(25) << std::left << std::string(#field_name) + ": " << (int64_t)report->field_name << std::endl;
315 #define PTR_TO_OFS(ptr_name) ofs << print_shift << std::setfill(' ') << std::setw(25) << std::left << std::string(#ptr_name) + ": " << report->ptr_name << std::endl;
DumpEncodeStatusReport(const EncodeStatusReport * report)316 MOS_STATUS CodechalDebugInterface::DumpEncodeStatusReport(const EncodeStatusReport *report)
317 {
318 CODECHAL_DEBUG_FUNCTION_ENTER;
319
320 CODECHAL_DEBUG_CHK_NULL(report);
321
322 const char *bufferName = "EncodeStatusReport_Parsed";
323 const char *attrName = MediaDbgAttr::attrStatusReport;
324 if (!m_configMgr->AttrIsEnabled(attrName))
325 {
326 return MOS_STATUS_SUCCESS;
327 }
328
329 const char * filePath = CreateFileName(bufferName, attrName, MediaDbgExtType::txt);
330 std::ofstream ofs(filePath);
331
332 if (ofs.fail())
333 {
334 return MOS_STATUS_UNKNOWN;
335 }
336 std::string print_shift = "";
337 sizeof(report->CodecStatus);
338 FIELD_TO_OFS(CodecStatus);
339 FIELD_TO_OFS(StatusReportNumber);
340 FIELD_TO_OFS(CurrOriginalPic.FrameIdx);
341 FIELD_TO_OFS(CurrOriginalPic.PicFlags);
342 FIELD_TO_OFS(CurrOriginalPic.PicEntry);
343 FIELD_TO_OFS(Func);
344 PTR_TO_OFS( pCurrRefList);
345 ofs << std::endl;
346
347 FIELD_TO_OFS(bSequential);
348 FIELD_TO_OFS(bitstreamSize);
349 FIELD_TO_OFS(QpY);
350 FIELD_TO_OFS(SuggestedQpYDelta);
351 FIELD_TO_OFS(NumberPasses);
352 FIELD_TO_OFS(AverageQp);
353 FIELD_TO_OFS(HWCounterValue.IV);
354 FIELD_TO_OFS(HWCounterValue.Count);
355 PTR_TO_OFS( hwctr);
356 FIELD_TO_OFS(QueryStatusFlags);
357
358 print_shift = " ";
359 FIELD_TO_OFS(PanicMode);
360 FIELD_TO_OFS(SliceSizeOverflow);
361 FIELD_TO_OFS(NumSlicesNonCompliant);
362 FIELD_TO_OFS(LongTermReference);
363 FIELD_TO_OFS(FrameSkipped);
364 FIELD_TO_OFS(SceneChangeDetected);
365 print_shift = "";
366 ofs << std::endl;
367
368 FIELD_TO_OFS(MAD);
369 FIELD_TO_OFS(loopFilterLevel);
370 FIELD_TO_OFS(LongTermIndication);
371 FIELD_TO_OFS(NextFrameWidthMinus1);
372 FIELD_TO_OFS(NextFrameHeightMinus1);
373 FIELD_TO_OFS(NumberSlices);
374
375 FIELD_TO_OFS(PSNRx100[0]);
376 FIELD_TO_OFS(PSNRx100[1]);
377 FIELD_TO_OFS(PSNRx100[2]);
378
379 FIELD_TO_OFS(NumberTilesInFrame);
380 FIELD_TO_OFS(UsedVdBoxNumber);
381 FIELD_TO_OFS(SizeOfSliceSizesBuffer);
382 PTR_TO_OFS( pSliceSizes);
383 FIELD_TO_OFS(SizeOfTileInfoBuffer);
384 PTR_TO_OFS( pHEVCTileinfo);
385 FIELD_TO_OFS(NumTileReported);
386 ofs << std::endl;
387
388 FIELD_TO_OFS(StreamId);
389 PTR_TO_OFS( pLookaheadStatus);
390 ofs.close();
391
392 return MOS_STATUS_SUCCESS;
393 }
394
CodechalDebugInterfaceG12()395 CodechalDebugInterfaceG12::CodechalDebugInterfaceG12()
396 {
397 memset(&m_currPic, 0, sizeof(CODEC_PICTURE));
398 memset(m_fileName, 0, sizeof(m_fileName));
399 memset(m_path, 0, sizeof(m_path));
400 }
~CodechalDebugInterfaceG12()401 CodechalDebugInterfaceG12::~CodechalDebugInterfaceG12()
402 {
403 if (nullptr != m_configMgr)
404 {
405 MOS_Delete(m_configMgr);
406 }
407 }
408
DumpYUVSurface(PMOS_SURFACE surface,const char * attrName,const char * surfName,MEDIA_DEBUG_STATE_TYPE mediaState,uint32_t width_in,uint32_t height_in)409 MOS_STATUS CodechalDebugInterfaceG12::DumpYUVSurface(
410 PMOS_SURFACE surface,
411 const char * attrName,
412 const char * surfName,
413 MEDIA_DEBUG_STATE_TYPE mediaState,
414 uint32_t width_in,
415 uint32_t height_in)
416 {
417 bool hasAuxSurf = false;
418 bool isPlanar = false;
419 bool hasRefSurf = false;
420 uint8_t *surfBaseAddr = nullptr;
421 uint8_t *lockedAddr = nullptr;
422 if (!DumpIsEnabled(attrName, mediaState))
423 {
424 return MOS_STATUS_SUCCESS;
425 }
426
427 MOS_LOCK_PARAMS lockFlags;
428 GMM_RESOURCE_FLAG gmmFlags;
429
430 MOS_ZeroMemory(&gmmFlags, sizeof(gmmFlags));
431 CODECHAL_DEBUG_CHK_NULL(surface);
432 gmmFlags = surface->OsResource.pGmmResInfo->GetResFlags();
433 hasAuxSurf = (gmmFlags.Gpu.MMC || gmmFlags.Info.MediaCompressed) && gmmFlags.Gpu.UnifiedAuxSurface;
434
435 if (!m_configMgr->AttrIsEnabled(CodechalDbgAttr::attrDecodeAuxSurface))
436 {
437 hasAuxSurf = false;
438 }
439
440 if (strcmp(attrName, CodechalDbgAttr::attrReferenceSurfaces) == 0)
441 {
442 hasRefSurf = true;
443 }
444
445 if(m_osInterface->pfnGetGmmClientContext(m_osInterface)->IsPlanar(surface->OsResource.pGmmResInfo->GetResourceFormat()))
446 {
447 isPlanar = true;
448 }
449
450 MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
451 lockFlags.ReadOnly = 1;
452 lockFlags.TiledAsTiled = 1; // Bypass GMM CPU blit due to some issues in GMM CpuBlt function
453 if (hasAuxSurf)
454 {
455 // Dump MMC surface as raw layout
456 lockFlags.NoDecompress = 1;
457 }
458
459 lockedAddr = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &surface->OsResource, &lockFlags);
460
461 if (lockedAddr == nullptr) // Failed to lock. Try to submit copy task and dump another surface
462 {
463 uint32_t sizeToBeCopied = 0;
464 MOS_GFXRES_TYPE ResType = MOS_GFXRES_2D;
465
466 CODECHAL_DEBUG_CHK_STATUS(ReAllocateSurface(
467 &m_temp2DSurfForCopy,
468 surface,
469 "Temp2DSurfForSurfDumper",
470 ResType));
471
472 if (!hasRefSurf)
473 {
474 uint32_t arraySize = surface->OsResource.pGmmResInfo->GetArraySize();
475
476 if (arraySize == 0)
477 {
478 return MOS_STATUS_UNKNOWN;
479 }
480
481 uint32_t sizeSrcSurface = (uint32_t)(surface->OsResource.pGmmResInfo->GetSizeMainSurface()) / arraySize;
482 // Ensure allocated buffer size contains the source surface size
483 if (m_temp2DSurfForCopy.OsResource.pGmmResInfo->GetSizeMainSurface() >= sizeSrcSurface)
484 {
485 sizeToBeCopied = sizeSrcSurface;
486 }
487
488 if (sizeToBeCopied == 0)
489 {
490 // Currently, MOS's pfnAllocateResource does not support allocate a surface reference to another surface.
491 // When the source surface is not created from Media, it is possible that we cannot allocate the same size as source.
492 // For example, on Gen9, Render target might have GMM set CCS=1 MMC=0, but MOS cannot allocate surface with such combination.
493 // When Gmm allocation parameter is different, the resulting surface size/padding/pitch will be differnt.
494 // Once if MOS can support allocate a surface by reference another surface, we can do a bit to bit copy without problem.
495 CODECHAL_DEBUG_ASSERTMESSAGE("Cannot allocate correct size, failed to copy nonlockable resource");
496 return MOS_STATUS_NULL_POINTER;
497 }
498
499 CODECHAL_DEBUG_VERBOSEMESSAGE("Temp2DSurfaceForCopy width %d, height %d, pitch %d, TileType %d, bIsCompressed %d, CompressionMode %d",
500 m_temp2DSurfForCopy.dwWidth,
501 m_temp2DSurfForCopy.dwHeight,
502 m_temp2DSurfForCopy.dwPitch,
503 m_temp2DSurfForCopy.TileType,
504 m_temp2DSurfForCopy.bIsCompressed,
505 m_temp2DSurfForCopy.CompressionMode);
506
507 uint32_t bpp = surface->OsResource.pGmmResInfo->GetBitsPerPixel();
508
509 CODECHAL_DEBUG_CHK_STATUS(m_osInterface->pfnMediaCopyResource2D(m_osInterface, &surface->OsResource, &m_temp2DSurfForCopy.OsResource, surface->dwPitch, sizeSrcSurface / (surface->dwPitch), 0, 0, bpp, false));
510 }
511 else
512 {
513 CODECHAL_DEBUG_CHK_STATUS(m_osInterface->pfnDoubleBufferCopyResource(m_osInterface, &surface->OsResource, &m_temp2DSurfForCopy.OsResource, false));
514 }
515
516 lockedAddr = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, &m_temp2DSurfForCopy.OsResource, &lockFlags);
517 CODECHAL_DEBUG_CHK_NULL(lockedAddr);
518
519 surface = &m_temp2DSurfForCopy;
520 gmmFlags = surface->OsResource.pGmmResInfo->GetResFlags();
521 }
522
523 if (hasAuxSurf)
524 {
525 uint32_t sizeMain = (uint32_t)(surface->OsResource.pGmmResInfo->GetSizeMainSurface());
526 surfBaseAddr = (uint8_t*)MOS_AllocMemory(sizeMain);
527 CODECHAL_DEBUG_CHK_NULL(surfBaseAddr);
528
529 Mos_SwizzleData(lockedAddr, surfBaseAddr, surface->TileType, MOS_TILE_LINEAR, sizeMain / surface->dwPitch, surface->dwPitch,true);
530 }
531 else
532 {
533 surfBaseAddr = lockedAddr;
534 }
535
536 // Always use MOS swizzle instead of GMM Cpu blit
537 uint32_t sizeMain = (uint32_t)(surface->OsResource.pGmmResInfo->GetSizeMainSurface());
538 surfBaseAddr = (uint8_t*)MOS_AllocMemory(sizeMain);
539 CODECHAL_DEBUG_CHK_NULL(surfBaseAddr);
540 Mos_SwizzleData(lockedAddr, surfBaseAddr, surface->TileType, MOS_TILE_LINEAR, sizeMain / surface->dwPitch, surface->dwPitch,
541 !MEDIA_IS_SKU(m_osInterface->pfnGetSkuTable(m_osInterface), FtrTileY) || gmmFlags.Info.Tile4);
542
543 uint8_t *data = surfBaseAddr;
544 data += surface->dwOffset + surface->YPlaneOffset.iYOffset * surface->dwPitch;
545
546 uint32_t width = width_in ? width_in : surface->dwWidth;
547 uint32_t height = height_in? height_in : surface->dwHeight;
548 uint32_t lumaheight = 0;
549
550 switch (surface->Format)
551 {
552 case Format_YUY2:
553 case Format_P010:
554 case Format_P016:
555 width = width << 1;
556 break;
557 case Format_Y216:
558 case Format_Y210: //422 10bit -- Y0[15:0]:U[15:0]:Y1[15:0]:V[15:0] = 32bits per pixel = 4Bytes per pixel
559 case Format_Y410: //444 10bit -- A[31:30]:V[29:20]:Y[19:10]:U[9:0] = 32bits per pixel = 4Bytes per pixel
560 case Format_R10G10B10A2:
561 case Format_AYUV: //444 8bit -- A[31:24]:Y[23:16]:U[15:8]:V[7:0] = 32bits per pixel = 4Bytes per pixel
562 case Format_A8R8G8B8:
563 width = width << 2;
564 break;
565 case Format_Y416:
566 width = width << 3;
567 break;
568 default:
569 break;
570 }
571
572 uint32_t pitch = surface->dwPitch;
573 if (surface->Format == Format_UYVY)
574 pitch = width;
575
576 if (CodecHal_PictureIsBottomField(m_currPic))
577 {
578 data += pitch;
579 }
580
581 if (CodecHal_PictureIsField(m_currPic))
582 {
583 pitch *= 2;
584 height /= 2;
585 }
586
587 lumaheight = hasAuxSurf ? GFX_ALIGN(height, 32) : height;
588
589 const char *funcName = (m_codecFunction == CODECHAL_FUNCTION_DECODE) ? "_DEC" :(m_codecFunction == CODECHAL_FUNCTION_CENC_DECODE ? "_DEC" : "_ENC");
590 std::string bufName = std::string(surfName) + "_w[" + std::to_string(surface->dwWidth) + "]_h[" + std::to_string(surface->dwHeight) + "]_p[" + std::to_string(pitch) + "]";
591
592 const char *filePath = CreateFileName(funcName, bufName.c_str(), hasAuxSurf ? ".Y" : ".yuv");
593
594 std::ofstream ofs(filePath, std::ios_base::out | std::ios_base::binary);
595 if (ofs.fail())
596 {
597 return MOS_STATUS_UNKNOWN;
598 }
599
600 // write luma data to file
601 for (uint32_t h = 0; h < lumaheight; h++)
602 {
603 ofs.write((char*)data, hasAuxSurf ? pitch : width);
604 data += pitch;
605 }
606
607 switch (surface->Format)
608 {
609 case Format_NV12:
610 case Format_P010:
611 case Format_P016:
612 height = height>>1;
613 break;
614 case Format_Y416: //444 16bit
615 case Format_AYUV: //444 8bit
616 case Format_AUYV:
617 case Format_Y410: //444 10bit
618 case Format_R10G10B10A2:
619 height =height<<1;
620 break;
621 case Format_YUY2:
622 case Format_YUYV:
623 case Format_YVYU:
624 case Format_UYVY:
625 case Format_VYUY:
626 case Format_Y216: //422 16bit
627 case Format_Y210: //422 10bit
628 case Format_P208: //422 8bit
629 break;
630 case Format_422V:
631 case Format_IMC3:
632 height = height / 2;
633 break;
634 default:
635 height = 0;
636 break;
637 }
638
639 uint8_t *vPlaneData = surfBaseAddr;
640 if (isPlanar)
641 {
642 if (hasAuxSurf)
643 {
644 data = surfBaseAddr + surface->UPlaneOffset.iSurfaceOffset;
645 }
646 else
647 {
648 data = surfBaseAddr + surface->UPlaneOffset.iSurfaceOffset;
649 if (surface->Format == Format_422V
650 || surface->Format == Format_IMC3)
651 {
652 vPlaneData = surfBaseAddr + surface->VPlaneOffset.iSurfaceOffset;
653 }
654 }
655
656 //No seperate chroma for linear surfaces
657 // Seperate Y/UV if MMC is enabled
658 if (hasAuxSurf)
659 {
660 const char *uvfilePath = CreateFileName(funcName, bufName.c_str(), ".UV");
661 std::ofstream ofs1(uvfilePath, std::ios_base::out | std::ios_base::binary);
662 if (ofs1.fail())
663 {
664 return MOS_STATUS_UNKNOWN;
665 }
666 // write chroma data to file
667 for (uint32_t h = 0; h < GFX_ALIGN(height, 32); h++)
668 {
669 ofs1.write((char*)data, pitch);
670 data += pitch;
671 }
672 ofs1.close();
673 }
674 else
675 {
676 // write chroma data to file
677 for (uint32_t h = 0; h < height; h++)
678 {
679 ofs.write((char *)data, hasAuxSurf ? pitch : width);
680 data += pitch;
681 }
682
683 // write v planar data to file
684 if (surface->Format == Format_422V
685 || surface->Format == Format_IMC3)
686 {
687 for (uint32_t h = 0; h < height; h++)
688 {
689 ofs.write((char *)vPlaneData, hasAuxSurf ? pitch : width);
690 vPlaneData += pitch;
691 }
692 }
693
694 }
695 ofs.close();
696 }
697
698 if (hasAuxSurf)
699 {
700 uint32_t resourceIndex = m_osInterface->pfnGetResourceIndex(&surface->OsResource);
701 uint8_t *yAuxData = (uint8_t*)lockedAddr + surface->OsResource.pGmmResInfo->GetPlanarAuxOffset(resourceIndex, GMM_AUX_Y_CCS);
702 uint32_t yAuxSize = isPlanar ? ((uint32_t)(surface->OsResource.pGmmResInfo->GetPlanarAuxOffset(resourceIndex, GMM_AUX_UV_CCS) -
703 surface->OsResource.pGmmResInfo->GetPlanarAuxOffset(resourceIndex, GMM_AUX_Y_CCS))) :
704 (uint32_t)surface->OsResource.pGmmResInfo->GetAuxQPitch();
705
706 // Y Aux data
707 const char *yAuxfilePath = CreateFileName(funcName, bufName.c_str(), ".Yaux");
708 std::ofstream ofs2(yAuxfilePath, std::ios_base::out | std::ios_base::binary);
709 if (ofs2.fail())
710 {
711 return MOS_STATUS_UNKNOWN;
712 }
713 ofs2.write((char*)yAuxData, yAuxSize);
714 ofs2.close();
715
716 if (isPlanar)
717 {
718 uint8_t *uvAuxData = (uint8_t*)lockedAddr + surface->OsResource.pGmmResInfo->GetPlanarAuxOffset(resourceIndex, GMM_AUX_UV_CCS);
719 uint32_t uvAuxSize = (uint32_t)surface->OsResource.pGmmResInfo->GetAuxQPitch() - yAuxSize;
720
721 // UV Aux data
722 const char *uvAuxfilePath = CreateFileName(funcName, bufName.c_str(), ".UVaux");
723 std::ofstream ofs3(uvAuxfilePath, std::ios_base::out | std::ios_base::binary);
724 if (ofs3.fail())
725 {
726 return MOS_STATUS_UNKNOWN;
727 }
728 ofs3.write((char*)uvAuxData, uvAuxSize);
729
730 ofs3.close();
731 }
732 }
733
734 if (surfBaseAddr)
735 {
736 MOS_FreeMemory(surfBaseAddr);
737 }
738 if (lockedAddr)
739 {
740 m_osInterface->pfnUnlockResource(m_osInterface, &surface->OsResource);
741 }
742
743 return MOS_STATUS_SUCCESS;
744 }
745
746 #undef FIELD_TO_OFS
747 #undef PTR_TO_OFS
748
749 #endif // USE_CODECHAL_DEBUG_TOOL
750