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