1 /*
2 * Copyright (c) 2019-2024, 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     decode_status_report.cpp
24 //! \brief    Defines the common interface for decode status reporter
25 //! \details
26 //!
27 #include "decode_status_report.h"
28 #include "decode_allocator.h"
29 #include "mos_utilities.h"
30 
31 namespace decode {
32 
DecodeStatusReport(DecodeAllocator * allocator,bool enableRcs,PMOS_INTERFACE osInterface)33     DecodeStatusReport::DecodeStatusReport(
34         DecodeAllocator* allocator, bool enableRcs, PMOS_INTERFACE osInterface):
35         m_enableRcs(enableRcs),
36         m_allocator(allocator),
37         m_osInterface(osInterface)
38     {
39         m_sizeOfReport = sizeof(DecodeStatusReportData);
40     }
41 
~DecodeStatusReport()42     DecodeStatusReport::~DecodeStatusReport()
43     {
44         Destroy();
45     }
46 
Create()47     MOS_STATUS DecodeStatusReport::Create()
48     {
49         DECODE_FUNC_CALL();
50 
51         SetSizeForStatusBuf();
52         // Allocate status buffer which includes decode status and completed count
53         uint32_t bufferSize = m_statusBufSizeMfx * m_statusNum + m_completedCountSize;
54         m_statusBufMfx = m_allocator->AllocateBuffer(
55             bufferSize, "StatusQueryBufferMfx", resourceInternalWrite, lockableSystemMem, true, 0, true);
56         DECODE_CHK_NULL(m_statusBufMfx);
57         m_completedCountBuf = &(m_statusBufMfx->OsResource);
58 
59         DECODE_CHK_STATUS(m_allocator->SkipResourceSync(m_statusBufMfx));
60         uint8_t *data = (uint8_t *)m_allocator->LockResourceForRead(m_statusBufMfx);
61         DECODE_CHK_NULL(data);
62 
63         // Decode status located at the beginging of the status buffer, following with complete count
64         m_dataStatusMfx  = data;
65         m_completedCount = (uint32_t *)(data + m_statusBufSizeMfx * m_statusNum);
66 
67         if (m_enableRcs)
68         {
69             m_statusBufRcs = m_allocator->AllocateBuffer(
70                 m_statusBufSizeRcs * m_statusNum, "StatusQueryBufferRcs", resourceInternalWrite, lockableSystemMem, true, 0, true);
71 
72             DECODE_CHK_STATUS(m_allocator->SkipResourceSync(m_statusBufRcs));
73             m_dataStatusRcs = (uint8_t *)m_allocator->LockResourceForRead(m_statusBufRcs);
74             DECODE_CHK_NULL(m_dataStatusRcs);
75         }
76 
77         m_submittedCount = 0;
78         m_reportedCount = 0;
79 
80         m_statusBufAddr = MOS_NewArray(StatusBufAddr, statusReportMaxNum);
81         DECODE_CHK_NULL(m_statusBufAddr);
82 
83         m_statusBufAddr[statusReportGlobalCount].osResource = m_completedCountBuf;
84         m_statusBufAddr[statusReportGlobalCount].offset = m_statusBufSizeMfx * m_statusNum;
85         m_statusBufAddr[statusReportGlobalCount].bufSize = sizeof(uint32_t) * 2;
86 
87         for (int i = statusReportMfx; i < statusReportMaxNum; i++)
88         {
89             m_statusBufAddr[i].osResource = &m_statusBufMfx->OsResource;
90             m_statusBufAddr[i].bufSize = m_statusBufSizeMfx;
91         }
92 
93         m_statusBufAddr[statusReportRcs].osResource = &m_statusBufRcs->OsResource;
94         m_statusBufAddr[statusReportRcs].bufSize = m_statusBufSizeRcs;
95 
96         SetOffsetsForStatusBuf();
97 
98         return MOS_STATUS_SUCCESS;
99     }
100 
Init(void * inputPar)101     MOS_STATUS DecodeStatusReport::Init(void *inputPar)
102     {
103         DECODE_FUNC_CALL();
104 
105         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
106 
107         DecodeStatusParameters* inputParameters = (DecodeStatusParameters*)inputPar;
108         uint32_t submitIndex = CounterToIndex(m_submittedCount);
109 
110         if (inputParameters)
111         {
112             m_statusReportData[submitIndex].codecStatus        = CODECHAL_STATUS_UNAVAILABLE;
113             m_statusReportData[submitIndex].statusReportNumber = inputParameters->statusReportFeedbackNumber;
114             m_statusReportData[submitIndex].currDecodedPic     = inputParameters->currOriginalPic;
115             m_statusReportData[submitIndex].currDecodedPicRes  = inputParameters->currDecodedPicRes;
116 #if (_DEBUG || _RELEASE_INTERNAL)
117             m_statusReportData[submitIndex].currSfcOutputSurface = inputParameters->sfcOutputSurface;
118             m_statusReportData[submitIndex].currHistogramOutBuf  = inputParameters->histogramOutputBuf;
119             m_statusReportData[submitIndex].frameType            = inputParameters->pictureCodingType;
120             m_statusReportData[submitIndex].secondField          = inputParameters->isSecondField;
121             m_statusReportData[submitIndex].currFgOutputPicRes   = inputParameters->fgOutputPicRes;
122             m_statusReportData[submitIndex].streamSize           = inputParameters->streamSize;
123 
124             if (inputParameters->streamOutBufRes != nullptr)
125             {
126                 m_statusReportData[submitIndex].streamOutBufRes = *(inputParameters->streamOutBufRes);
127             }
128             else
129             {
130                 m_statusReportData[submitIndex].streamOutBufRes = {0};
131             }
132 
133             if (inputParameters->streamInBufRes != nullptr)
134             {
135                 m_statusReportData[submitIndex].streamInBufRes = *(inputParameters->streamInBufRes);
136             }
137             else
138             {
139                 m_statusReportData[submitIndex].streamInBufRes = {0};
140             }
141 #endif
142         }
143 
144         DecodeStatusMfx* decodeStatusMfx = (DecodeStatusMfx*)(m_dataStatusMfx + submitIndex * m_statusBufSizeMfx);
145         decodeStatusMfx->status = querySkipped;
146 
147         if (m_enableRcs)
148         {
149             DecodeStatusRcs *decodeStatusRcs = (DecodeStatusRcs *)(m_dataStatusRcs + submitIndex * m_statusBufSizeRcs);
150             decodeStatusRcs->status = querySkipped;
151         }
152 
153         return eStatus;
154     }
155 
Reset()156     MOS_STATUS DecodeStatusReport::Reset()
157     {
158         DECODE_FUNC_CALL();
159 
160         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
161 
162         m_submittedCount++;
163         uint32_t submitIndex = CounterToIndex(m_submittedCount);
164 
165         DecodeStatusMfx* decodeStatusMfx = (DecodeStatusMfx*)(m_dataStatusMfx + submitIndex * m_statusBufSizeMfx);
166         MOS_ZeroMemory((uint8_t*)decodeStatusMfx, m_statusBufSizeMfx);
167 
168         if (m_enableRcs)
169         {
170             DecodeStatusRcs *decodeStatusRcs = (DecodeStatusRcs *)(m_dataStatusRcs + submitIndex * m_statusBufSizeRcs);
171             MOS_ZeroMemory((uint8_t *)decodeStatusRcs, m_statusBufSizeRcs);
172         }
173 
174         return eStatus;
175     }
176 
ParseStatus(void * report,uint32_t index)177     MOS_STATUS DecodeStatusReport::ParseStatus(void* report, uint32_t index)
178     {
179         DECODE_FUNC_CALL();
180 
181         DecodeStatusMfx* decodeStatusMfx = nullptr;
182         DecodeStatusRcs* decodeStatusRcs = nullptr;
183 
184         DecodeStatusReportData* statusReportData = &m_statusReportData[index];
185 
186         decodeStatusMfx = (DecodeStatusMfx*)(m_dataStatusMfx + index * m_statusBufSizeMfx);
187         bool mfxCompleted = (decodeStatusMfx->status == queryEnd) || (decodeStatusMfx->status == querySkipped);
188 
189         bool rcsCompleted = false;
190         if (m_enableRcs)
191         {
192             decodeStatusRcs = (DecodeStatusRcs *)(m_dataStatusRcs + index * m_statusBufSizeRcs);
193             rcsCompleted    = (decodeStatusRcs->status == queryEnd) || (decodeStatusRcs->status == querySkipped);
194         }
195         else
196         {
197             rcsCompleted    = true;
198         }
199 
200         UpdateCodecStatus(statusReportData, decodeStatusMfx, mfxCompleted && rcsCompleted);
201 
202         // The frame is completed, notify the observers
203         if (statusReportData->codecStatus == CODECHAL_STATUS_SUCCESSFUL)
204         {
205             NotifyObservers(decodeStatusMfx, decodeStatusRcs, statusReportData);
206         }
207 
208         *((DecodeStatusReportData*)report) = *statusReportData;
209 
210         return MOS_STATUS_SUCCESS;
211     }
212 
SetStatus(void * report,uint32_t index,bool outOfRange)213     MOS_STATUS DecodeStatusReport::SetStatus(void *report, uint32_t index, bool outOfRange)
214     {
215         DECODE_FUNC_CALL();
216 
217         DecodeStatusReportData* statusReportData = &m_statusReportData[index];
218 
219         statusReportData->codecStatus = outOfRange ? CODECHAL_STATUS_UNAVAILABLE : CODECHAL_STATUS_INCOMPLETE;
220 
221         *((DecodeStatusReportData*)report) = *statusReportData;
222 
223         return MOS_STATUS_SUCCESS;
224     }
225 
SetSizeForStatusBuf()226     void DecodeStatusReport::SetSizeForStatusBuf()
227     {
228         m_statusBufSizeMfx = MOS_ALIGN_CEIL(sizeof(DecodeStatusMfx), sizeof(uint64_t));
229         m_statusBufSizeRcs = MOS_ALIGN_CEIL(sizeof(DecodeStatusRcs), sizeof(uint64_t));
230     }
231 
SetOffsetsForStatusBuf()232     void DecodeStatusReport::SetOffsetsForStatusBuf()
233     {
234         const uint32_t mfxStatusOffset = 0;
235         m_statusBufAddr[statusReportMfx].offset      = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, status);
236         m_statusBufAddr[DecErrorStatusOffset].offset = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioErrorStatusReg);
237         m_statusBufAddr[DecMBCountOffset].offset     = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioMBCountReg);
238         m_statusBufAddr[DecFrameCrcOffset].offset    = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioFrameCrcReg);
239         m_statusBufAddr[CsEngineIdOffset_0].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[0]);
240         m_statusBufAddr[CsEngineIdOffset_1].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[1]);
241         m_statusBufAddr[CsEngineIdOffset_2].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[2]);
242         m_statusBufAddr[CsEngineIdOffset_3].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[3]);
243         m_statusBufAddr[CsEngineIdOffset_4].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[4]);
244         m_statusBufAddr[CsEngineIdOffset_5].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[5]);
245         m_statusBufAddr[CsEngineIdOffset_6].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[6]);
246         m_statusBufAddr[CsEngineIdOffset_7].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_mmioCsEngineIdReg[7]);
247         m_statusBufAddr[HucErrorStatus2Mask].offset  = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_hucErrorStatus2);
248         m_statusBufAddr[HucErrorStatus2Reg].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_hucErrorStatus2) + sizeof(uint32_t);
249         m_statusBufAddr[HucErrorStatusMask].offset   = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_hucErrorStatus);
250         m_statusBufAddr[HucErrorStatusReg].offset    = mfxStatusOffset + CODECHAL_OFFSETOF(DecodeStatusMfx, m_hucErrorStatus) + sizeof(uint32_t);
251 
252         const uint32_t rcsStatusOffset = 0;
253         m_statusBufAddr[statusReportRcs].offset      = rcsStatusOffset + CODECHAL_OFFSETOF(DecodeStatusRcs, status);
254     }
255 
UpdateCodecStatus(DecodeStatusReportData * statusReportData,DecodeStatusMfx * decodeStatus,bool completed)256     MOS_STATUS DecodeStatusReport::UpdateCodecStatus(
257         DecodeStatusReportData* statusReportData,
258         DecodeStatusMfx* decodeStatus,
259         bool completed)
260     {
261         DECODE_CHK_NULL(statusReportData);
262         DECODE_CHK_NULL(decodeStatus);
263 
264         if(m_osInterface != nullptr && m_osInterface->pfnIsGPUHung(m_osInterface))
265         {
266             statusReportData->codecStatus = CODECHAL_STATUS_INCOMPLETE;
267             DECODE_ASSERTMESSAGE("Gpu hang may have occured.");
268         }
269         else if (!completed)
270         {
271             statusReportData->codecStatus = CODECHAL_STATUS_RESET;
272             DECODE_ASSERTMESSAGE("Media reset may have occured.");
273         }
274         else
275         {
276             statusReportData->codecStatus = CODECHAL_STATUS_SUCCESSFUL;
277         }
278 
279         return MOS_STATUS_SUCCESS;
280     }
281 
GetMfxStatus(uint32_t counter)282     const DecodeStatusMfx& DecodeStatusReport::GetMfxStatus(uint32_t counter)
283     {
284         uint32_t index = CounterToIndex(counter);
285         DecodeStatusMfx* decodeStatusMfx = (DecodeStatusMfx*)(m_dataStatusMfx + index * m_statusBufSizeMfx);
286         return *decodeStatusMfx;
287     }
288 
GetReportData(uint32_t counter)289     const DecodeStatusReportData& DecodeStatusReport::GetReportData(uint32_t counter)
290     {
291         uint32_t index = CounterToIndex(counter);
292         return m_statusReportData[index];
293     }
294 
Destroy()295     MOS_STATUS DecodeStatusReport::Destroy()
296     {
297         DECODE_FUNC_CALL();
298 
299         if (m_allocator != nullptr && m_statusBufMfx != nullptr)
300         {
301             m_allocator->UnLock(m_statusBufMfx);
302             m_allocator->Destroy(m_statusBufMfx);
303             m_statusBufMfx = nullptr;
304             m_completedCountBuf = nullptr;
305         }
306 
307         if (m_allocator != nullptr && m_statusBufRcs != nullptr)
308         {
309             m_allocator->UnLock(m_statusBufRcs);
310             m_allocator->Destroy(m_statusBufRcs);
311             m_statusBufRcs = nullptr;
312         }
313 
314         if (m_statusBufAddr != nullptr)
315         {
316             MOS_DeleteArray(m_statusBufAddr);
317             m_statusBufAddr = nullptr;
318         }
319 
320         return MOS_STATUS_SUCCESS;
321     }
322 }
323