1 /*
2 * Copyright (c) 2011-2018, 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_jpeg.cpp
24 //! \brief    Implements the decode interface extension for JPEG.
25 //! \details  Implements all functions required by CodecHal for JPEG decoding.
26 //!
27 
28 #include "codechal_decode_jpeg.h"
29 #include "codechal_mmc_decode_jpeg.h"
30 #include "hal_oca_interface.h"
31 #if USE_CODECHAL_DEBUG_TOOL
32 #include <sstream>
33 #include "codechal_debug.h"
34 #endif
35 
36 #define CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE       8
37 #define CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2    16
38 #define CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X4    32
39 #define CODECHAL_DECODE_JPEG_ERR_FRAME_WIDTH        32
40 #define CODECHAL_DECODE_JPEG_ERR_FRAME_HEIGHT       32
41 
~CodechalDecodeJpeg()42 CodechalDecodeJpeg::~CodechalDecodeJpeg()
43 {
44     CODECHAL_DECODE_FUNCTION_ENTER;
45 
46     m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectWaContextInUse);
47     m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse);
48 
49     if (!Mos_ResourceIsNull(&m_resCopiedDataBuffer))
50     {
51         m_osInterface->pfnFreeResource(
52             m_osInterface,
53             &m_resCopiedDataBuffer);
54     }
55 
56 #ifdef _DECODE_PROCESSING_SUPPORTED
57     if (m_sfcState)
58     {
59         MOS_Delete(m_sfcState);
60         m_sfcState = nullptr;
61     }
62 #endif
63 
64     return;
65 }
66 
CodechalDecodeJpeg(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)67 CodechalDecodeJpeg::CodechalDecodeJpeg(
68     CodechalHwInterface *   hwInterface,
69     CodechalDebugInterface *debugInterface,
70     PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecode(hwInterface, debugInterface, standardInfo),
71                                             m_dataSize(0),
72                                             m_dataOffset(0),
73                                             m_copiedDataBufferSize(0),
74                                             m_nextCopiedDataOffset(0),
75                                             m_totalDataLength(0),
76                                             m_preNumScans(0),
77                                             m_copiedDataBufferInUse(false)
78 
79 {
80     CODECHAL_DECODE_FUNCTION_ENTER;
81 
82     MOS_ZeroMemory(&m_resCopiedDataBuffer, sizeof(m_resCopiedDataBuffer));
83     MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface));
84     MOS_ZeroMemory(&m_jpegHuffmanTable, sizeof(m_jpegHuffmanTable));
85     MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer));
86     MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse));
87     MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse));
88 }
89 
InitializeBeginFrame()90 MOS_STATUS CodechalDecodeJpeg::InitializeBeginFrame()
91 {
92     CODECHAL_DECODE_FUNCTION_ENTER;
93 
94     m_incompletePicture = false;
95     m_incompleteJpegScan = false;
96     m_copiedDataBufferInUse = false;
97     m_nextCopiedDataOffset  = 0;
98     m_totalDataLength       = 0;
99     m_preNumScans           = 0;
100 
101     return MOS_STATUS_SUCCESS;
102 }
103 
CopyDataSurface()104 MOS_STATUS CodechalDecodeJpeg::CopyDataSurface()
105 {
106     MOS_STATUS                              eStatus = MOS_STATUS_SUCCESS;
107 
108     CODECHAL_DECODE_FUNCTION_ENTER;
109 
110     if (m_hwInterface->m_noHuC)
111     {
112         uint32_t               alignedSize = MOS_ALIGN_CEIL(m_dataSize, 16);  // 16 byte aligned
113         CodechalDataCopyParams dataCopyParams;
114         MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams));
115         dataCopyParams.srcResource = &m_resDataBuffer;
116         dataCopyParams.srcSize = alignedSize;
117         dataCopyParams.srcOffset = 0;
118         dataCopyParams.dstResource = &m_resCopiedDataBuffer;
119         dataCopyParams.dstSize = alignedSize;
120         dataCopyParams.dstOffset   = m_nextCopiedDataOffset;
121 
122         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(
123             &dataCopyParams));
124 
125         m_nextCopiedDataOffset += MOS_ALIGN_CEIL(m_dataSize, MHW_CACHELINE_SIZE);  // 64-byte aligned
126         return MOS_STATUS_SUCCESS;
127     }
128 
129     CODECHAL_DECODE_CHK_COND_RETURN(
130         ((m_nextCopiedDataOffset + m_dataSize) > m_copiedDataBufferSize),
131         "Copied data buffer is not large enough.");
132 
133     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
134         m_osInterface,
135         m_videoContextForWa));
136     m_osInterface->pfnResetOsStates(m_osInterface);
137 
138     m_osInterface->pfnSetPerfTag(
139         m_osInterface,
140         (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE));
141     m_osInterface->pfnResetPerfBufferID(m_osInterface);
142 
143     MOS_COMMAND_BUFFER cmdBuffer;
144     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
145         m_osInterface,
146         &cmdBuffer,
147         0));
148 
149     // Send command buffer header at the beginning (OS dependent)
150     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
151         &cmdBuffer,
152         false));
153 
154     // Use huc stream out to do the copy
155     CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy(
156         &cmdBuffer,                // pCmdBuffer
157         &m_resDataBuffer,          // presSrc
158         &m_resCopiedDataBuffer,    // presDst
159         m_dataSize,                // u32CopyLength
160         0,                         // u32CopyInputOffset
161         m_nextCopiedDataOffset));  // u32CopyOutputOffset
162 
163     m_nextCopiedDataOffset += MOS_ALIGN_CEIL(m_dataSize, MHW_CACHELINE_SIZE);
164 
165     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
166     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
167     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
168         &cmdBuffer,
169         &flushDwParams));
170 
171     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
172         &cmdBuffer,
173         nullptr));
174 
175     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
176 
177     if (!m_incompletePicture)
178     {
179         MOS_SYNC_PARAMS syncParams;
180         syncParams = g_cInitSyncParams;
181         syncParams.GpuContext = m_videoContext;
182         syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;
183 
184         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(
185             m_osInterface,
186             &syncParams));
187 
188         syncParams = g_cInitSyncParams;
189         syncParams.GpuContext = m_videoContextForWa;
190         syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;
191 
192         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(
193             m_osInterface,
194             &syncParams));
195     }
196 
197     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
198         m_osInterface,
199         &cmdBuffer,
200         m_videoContextForWaUsesNullHw));
201 
202     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
203         m_osInterface,
204         m_videoContext));
205 
206     return eStatus;
207 }
208 
CheckAndCopyIncompleteBitStream()209 MOS_STATUS CodechalDecodeJpeg::CheckAndCopyIncompleteBitStream()
210 {
211     MOS_STATUS  eStatus = MOS_STATUS_SUCCESS;
212 
213     uint32_t maxBufferSize =
214         MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth * m_jpegPicParams->m_frameHeight * 3, 64);
215 
216     if (m_jpegPicParams->m_totalScans == 1)  // Single scan
217     {
218         if (!m_incompleteJpegScan) // The first bitstream buffer
219         {
220             m_totalDataLength =
221                 m_jpegScanParams->ScanHeader[0].DataOffset + m_jpegScanParams->ScanHeader[0].DataLength;
222 
223             if (m_dataSize < m_totalDataLength)  // if the bitstream data is incomplete
224             {
225                 CODECHAL_DECODE_CHK_COND_RETURN(
226                     m_totalDataLength > maxBufferSize,
227                     "The bitstream size exceeds the copied data buffer size.");
228 
229                 CODECHAL_DECODE_CHK_COND_RETURN(
230                     m_dataSize & 0x3f,
231                     "The data size of the incomplete bitstream is not aligned with 64.");
232 
233                 // Allocate the copy data buffer.
234                 if (Mos_ResourceIsNull(&m_resCopiedDataBuffer))
235                 {
236                     CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
237                                                                   &m_resCopiedDataBuffer,
238                                                                   maxBufferSize,
239                                                                   "CopiedDataBuffer"),
240                         "Failed to allocate copied data Buffer.");
241                 }
242                 m_copiedDataBufferSize = maxBufferSize;
243 
244                 // copy the bitstream buffer
245                 if (m_dataSize)
246                 {
247                     CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface());
248                     m_copiedDataBufferInUse = true;
249                 }
250 
251                 m_incompleteJpegScan = true;
252                 m_incompletePicture = true;
253             }
254             else //the bitstream data is complete
255             {
256                 m_incompleteJpegScan = false;
257                 m_incompletePicture = false;
258             }
259         }
260         else // the next bitstream buffers
261         {
262             CODECHAL_DECODE_CHK_COND_RETURN(
263                 m_nextCopiedDataOffset + m_dataSize > m_copiedDataBufferSize,
264                 "The bitstream size exceeds the copied data buffer size.")
265 
266             CODECHAL_DECODE_CHK_COND_RETURN(
267                 (m_nextCopiedDataOffset + m_dataSize < m_totalDataLength) && (m_dataSize & 0x3f),
268                 "The data size of the incomplete bitstream is not aligned with 64.");
269 
270             // copy the bitstream
271             if (m_dataSize)
272             {
273                 CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface());
274             }
275 
276             if (m_nextCopiedDataOffset >= m_totalDataLength)
277             {
278                 m_incompleteJpegScan = false;
279                 m_incompletePicture = false;
280             }
281 
282         }
283     }
284     else  // multi-scans
285     {
286         if (!m_incompleteJpegScan) // The first bitstream buffer of each scan;
287         {
288             for (uint32_t idxScan = m_preNumScans; idxScan < m_jpegScanParams->NumScans; idxScan++)
289             {
290                 m_jpegScanParams->ScanHeader[idxScan].DataOffset += m_nextCopiedDataOffset;  // modify the data offset for the new incoming scan data
291             }
292             m_totalDataLength = m_jpegScanParams->ScanHeader[m_jpegScanParams->NumScans - 1].DataOffset + m_jpegScanParams->ScanHeader[m_jpegScanParams->NumScans - 1].DataLength;
293             m_preNumScans     = m_jpegScanParams->NumScans;
294 
295             // judge whether the bitstream is complete in the first execute() call
296             if (IsFirstExecuteCall() &&
297                 m_dataSize <= m_jpegScanParams->ScanHeader[0].DataOffset + m_jpegScanParams->ScanHeader[0].DataLength)
298             {
299                 CODECHAL_DECODE_CHK_COND_RETURN(
300                     (m_nextCopiedDataOffset + m_dataSize < m_totalDataLength) && (m_dataSize & 0x3f),
301                     "The buffer size of the incomplete bitstream is not aligned with 64.");
302 
303                 // Allocate the copy data buffer.
304                 if (Mos_ResourceIsNull(&m_resCopiedDataBuffer))
305                 {
306                     CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
307                                                                   &m_resCopiedDataBuffer,
308                                                                   maxBufferSize,
309                                                                   "CopiedDataBuffer"),
310                         "Failed to allocate copied data Buffer.");
311                 }
312                 m_copiedDataBufferSize = maxBufferSize;
313 
314                 // copy the bitstream buffer
315                 if (m_dataSize)
316                 {
317                     CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface());
318                     m_copiedDataBufferInUse = true;
319                 }
320 
321                 m_incompleteJpegScan = m_nextCopiedDataOffset < m_totalDataLength;
322                 m_incompletePicture  = m_incompleteJpegScan || m_jpegScanParams->NumScans < m_jpegPicParams->m_totalScans;
323             }
324             else // the bitstream is complete
325             {
326                 m_incompleteJpegScan = false;
327                 if (m_jpegScanParams->NumScans == m_jpegPicParams->m_totalScans)
328                 {
329                     m_incompletePicture = false;
330                 }
331                 else
332                 {
333                     m_incompletePicture = true;
334                 }
335             }
336         }
337         else //The next bitstream buffer of each scan
338         {
339             CODECHAL_DECODE_CHK_COND_RETURN(
340                 m_nextCopiedDataOffset + m_dataSize > m_copiedDataBufferSize,
341                 "The bitstream size exceeds the copied data buffer size.")
342 
343             CODECHAL_DECODE_CHK_COND_RETURN(
344                 (m_nextCopiedDataOffset + m_dataSize < m_totalDataLength) && (m_dataSize & 0x3f),
345                 "The data size of the incomplete bitstream is not aligned with 64.");
346 
347             // copy the bitstream buffer
348             if (m_dataSize)
349             {
350                 CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface());
351             }
352 
353             if (m_nextCopiedDataOffset >= m_totalDataLength)
354             {
355                 m_incompleteJpegScan = false;
356                 if (m_jpegScanParams->NumScans >= m_jpegPicParams->m_totalScans)
357                 {
358                     m_incompletePicture = false;
359                 }
360             }
361 
362         }
363     }
364 
365     return eStatus;
366 }
367 
CheckSupportedFormat(PMOS_FORMAT format)368 MOS_STATUS CodechalDecodeJpeg::CheckSupportedFormat(
369     PMOS_FORMAT format)
370 {
371     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
372 
373     // App must use 420_OPAQUE as DecodeRT for other JPEG output formats except NV12 and YUY2 due to runtime
374     // restriction, so the real JPEG format is passed to driver in PPS data. The code here is just to get the real output format.
375     // On SKL+, app would use AYUV (instead of 420_OPAQUE) as DecodeRT for direct YUV to ARGB8888 conversion; in such case,
376     // real output format (ARGB8888) should also be from JPEG PPS; MSDK would handle the details of treating AYUV as ARGB.
377     if (*format == Format_420O || *format == Format_AYUV)
378     {
379         *format = m_osInterface->pfnFmt_OsToMos((MOS_OS_FORMAT)m_jpegPicParams->m_renderTargetFormat);
380     }
381 
382     //No support for RGBP/BGRP channel swap or YUV/RGB conversion!
383     switch (*format)
384     {
385     case Format_BGRP:
386         if (m_jpegPicParams->m_chromaType == jpegRGB ||
387             m_jpegPicParams->m_chromaType == jpegYUV444)
388         {
389             eStatus = MOS_STATUS_PLATFORM_NOT_SUPPORTED;
390         }
391         break;
392     case Format_RGBP:
393         if (m_jpegPicParams->m_chromaType == jpegYUV444)
394         {
395             eStatus = MOS_STATUS_PLATFORM_NOT_SUPPORTED;
396         }
397         break;
398     case Format_Y416:
399     case Format_AYUV:
400     case Format_AUYV:
401     case Format_Y410:
402         if (m_jpegPicParams->m_chromaType == jpegRGB ||
403             m_jpegPicParams->m_chromaType == jpegBGR)
404         {
405             eStatus = MOS_STATUS_PLATFORM_NOT_SUPPORTED;
406         }
407         break;
408     default:
409         break;
410     }
411 
412     return eStatus;
413 }
414 
SetFrameStates()415 MOS_STATUS CodechalDecodeJpeg::SetFrameStates()
416 {
417     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
418 
419     CODECHAL_DECODE_FUNCTION_ENTER;
420 
421     CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface);
422     CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer);
423 
424     //Set wPerfType as I_TYPE so that PerTag can be recognized by performance reportor
425     m_perfType = I_TYPE;
426 
427     m_dataSize         = m_decodeParams.m_dataSize;
428     m_dataOffset       = m_decodeParams.m_dataOffset;
429     m_resDataBuffer    = *(m_decodeParams.m_dataBuffer);
430     m_jpegPicParams    = (CodecDecodeJpegPicParams *)m_decodeParams.m_picParams;
431     m_jpegQMatrix      = (CodecJpegQuantMatrix *)m_decodeParams.m_iqMatrixBuffer;
432     m_jpegHuffmanTable = (PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE)m_decodeParams.m_huffmanTable;
433     m_jpegScanParams   = (CodecDecodeJpegScanParameter *)m_decodeParams.m_sliceParams;
434 
435     CODECHAL_DECODE_CHK_NULL_RETURN(m_jpegPicParams);
436 
437     CODECHAL_DECODE_CHK_STATUS_RETURN(CheckSupportedFormat(
438         &m_decodeParams.m_destSurface->Format));
439 
440     m_hwInterface->GetCpInterface()->SetCpSecurityType();
441 
442     if (IsFirstExecuteCall())
443     {
444         CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeBeginFrame());
445     }
446 
447     // Check whether the bitstream buffer is completed. If not, allocate a larger buffer and copy the bitstream.
448     CODECHAL_DECODE_CHK_STATUS_RETURN(CheckAndCopyIncompleteBitStream());
449 
450     // if the bitstream is not completed, don't do any decoding work.
451     if (m_incompletePicture)
452     {
453         return MOS_STATUS_SUCCESS;
454     }
455 
456     uint32_t widthAlign = 0;
457     uint32_t heightAlign = 0;
458 
459     // Overwriting surface width and height of destination surface, so it comes from Picture Parameters struct
460     if (!m_jpegPicParams->m_interleavedData)
461     {
462         widthAlign  = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
463         heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
464     }
465     else
466     {
467         switch (m_jpegPicParams->m_chromaType)
468         {
469         case jpegYUV400:
470         case jpegYUV444:
471         case jpegRGB:
472         case jpegBGR:
473             widthAlign  = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
474             heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
475             break;
476         case jpegYUV422V2Y:
477             widthAlign  = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
478             heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2);
479             break;
480         case jpegYUV422H2Y:
481             widthAlign  = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2);
482             heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
483             break;
484         case jpegYUV411:
485             widthAlign  = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X4);
486             heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE);
487             break;
488         default: // YUV422H_4Y, YUV422V_4Y & YUV420
489             widthAlign  = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameWidth, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2);
490             heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2);
491             break;
492         }
493     }
494 
495     //BDW has a limitation:Height should aligned by 16 when input is YUV422H_2Y and output is NV12.
496     if (MEDIA_IS_WA(m_waTable, WaJPEGHeightAlignYUV422H2YToNV12) &&
497         m_jpegPicParams->m_chromaType == jpegYUV422H2Y &&
498         m_decodeParams.m_destSurface->Format == Format_NV12)
499     {
500         heightAlign = MOS_ALIGN_CEIL(m_jpegPicParams->m_frameHeight, CODECHAL_DECODE_JPEG_BLOCK_ALIGN_SIZE_X2);
501     }
502 
503     if ((m_jpegPicParams->m_rotation == jpegRotation90) || (m_jpegPicParams->m_rotation == jpegRotation270))
504     {
505         // Interchanging picture width and height for 90/270 degree rotation
506         m_decodeParams.m_destSurface->dwWidth  = heightAlign;
507         m_decodeParams.m_destSurface->dwHeight = widthAlign;
508     }
509     else
510     {
511         m_decodeParams.m_destSurface->dwWidth  = widthAlign;
512         m_decodeParams.m_destSurface->dwHeight = heightAlign;
513     }
514 
515     m_destSurface = *(m_decodeParams.m_destSurface);
516     if (m_copiedDataBufferInUse)
517     {
518         m_resDataBuffer = m_resCopiedDataBuffer;  // set resDataBuffer to copy data buffer
519     }
520 
521     m_statusReportFeedbackNumber = m_jpegPicParams->m_statusReportFeedbackNumber;
522 
523 #ifdef _DECODE_PROCESSING_SUPPORTED
524     m_sfcState->CheckAndInitialize(&m_destSurface, m_jpegPicParams);
525 #endif
526 
527     CODECHAL_DEBUG_TOOL(
528         if (m_jpegPicParams) {
529             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams(m_jpegPicParams))
530         }
531 
532         if (m_jpegScanParams) {
533             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpScanParams(m_jpegScanParams))
534         }
535 
536         if (m_jpegHuffmanTable) {
537             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpHuffmanTable(m_jpegHuffmanTable))
538         }
539 
540         if (m_jpegQMatrix) {
541             CODECHAL_DECODE_CHK_STATUS_RETURN(DumpIQParams(m_jpegQMatrix))
542         }
543 
544         if (&(m_resDataBuffer)) {
545             CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
546                 &m_resDataBuffer,
547                 CodechalDbgAttr::attrBitstream,
548                 "_DEC",
549                 m_dataSize,
550                 0,
551                 CODECHAL_NUM_MEDIA_STATES));
552         })
553 
554     return eStatus;
555 }
556 
AllocateResources()557 MOS_STATUS CodechalDecodeJpeg::AllocateResources()
558 {
559     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
560 
561     CODECHAL_DECODE_FUNCTION_ENTER;
562 
563     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(
564         m_osInterface,
565         &m_resSyncObjectWaContextInUse));
566     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(
567         m_osInterface,
568         &m_resSyncObjectVideoContextInUse));
569 
570     return eStatus;
571 }
572 
SetOutputSurfaceLayout(CodecDecodeJpegImageLayout * outputSurfLayout)573 void CodechalDecodeJpeg::SetOutputSurfaceLayout(
574     CodecDecodeJpegImageLayout *outputSurfLayout)
575 {
576     uint32_t ucbOffset = MOS_ALIGN_CEIL(m_destSurface.UPlaneOffset.iYOffset, MHW_VDBOX_MFX_UV_PLANE_ALIGNMENT_LEGACY);
577     uint32_t vcrOffset = MOS_ALIGN_CEIL(m_destSurface.VPlaneOffset.iYOffset, MHW_VDBOX_MFX_UV_PLANE_ALIGNMENT_LEGACY);
578 
579     uint32_t ucbOffsetInBytes = ucbOffset * m_destSurface.dwPitch;
580     uint32_t vcrOffsetInBytes = vcrOffset * m_destSurface.dwPitch;
581 
582     outputSurfLayout->m_pitch = m_destSurface.dwPitch;
583 
584     for (uint32_t scanCount = 0; scanCount < m_jpegScanParams->NumScans; scanCount++)
585     {
586         for (uint32_t scanComponent = 0; scanComponent < m_jpegScanParams->ScanHeader[scanCount].NumComponents; scanComponent++)
587         {
588             if (m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent] == m_jpegPicParams->m_componentIdentifier[jpegComponentY])
589             {
590                 outputSurfLayout->m_componentDataOffset[jpegComponentY] = 0;
591             }
592             else if (m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent] == m_jpegPicParams->m_componentIdentifier[jpegComponentU])
593             {
594                 outputSurfLayout->m_componentDataOffset[jpegComponentU] = ucbOffsetInBytes;
595             }
596             else if (m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent] == m_jpegPicParams->m_componentIdentifier[jpegComponentV])
597             {
598                 outputSurfLayout->m_componentDataOffset[jpegComponentV] = vcrOffsetInBytes;
599             }
600         }
601     }
602 }
603 
DecodeStateLevel()604 MOS_STATUS CodechalDecodeJpeg::DecodeStateLevel()
605 {
606     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
607 
608     CODECHAL_DECODE_FUNCTION_ENTER;
609 
610     MHW_VDBOX_JPEG_DECODE_PIC_STATE jpegPicState;
611     jpegPicState.dwOutputFormat = m_decodeParams.m_destSurface->Format;
612 
613 #ifdef _DECODE_PROCESSING_SUPPORTED
614     if (m_sfcState->m_sfcPipeOut)
615     {
616         jpegPicState.dwOutputFormat = m_sfcState->m_sfcInSurface.Format;
617     }
618 #endif
619 
620     //Three new formats from HSW C0,HSW ULT can only be supported in specific conditions.
621     if (jpegPicState.dwOutputFormat == Format_NV12 ||
622         jpegPicState.dwOutputFormat == Format_YUY2 ||
623         jpegPicState.dwOutputFormat == Format_UYVY)
624     {
625         //Only interleaved single scan are supported.
626         if (m_jpegPicParams->m_totalScans != 1 ||
627             m_jpegPicParams->m_interleavedData == 0)
628         {
629             return MOS_STATUS_UNKNOWN;
630         }
631 
632         switch (m_jpegPicParams->m_chromaType)
633         {
634         case jpegYUV420:
635         case jpegYUV422H2Y:
636         case jpegYUV422H4Y:
637             break;
638         case jpegYUV422V2Y:
639         case jpegYUV422V4Y:
640             if (GFX_IS_GEN_8_OR_LATER(m_hwInterface->GetPlatform()) &&
641                 jpegPicState.dwOutputFormat == Format_NV12)
642             {
643                 break;
644             }
645         default:
646             return MOS_STATUS_UNKNOWN;
647         }
648     }
649 
650     MOS_COMMAND_BUFFER cmdBuffer;
651     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
652         m_osInterface,
653         &cmdBuffer,
654         0));
655 
656     auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex);
657     HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters);
658 
659     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
660         &cmdBuffer, true));
661 
662     // Set PIPE_MODE_SELECT
663     MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
664     pipeModeSelectParams.Mode                       = CODECHAL_DECODE_MODE_JPEG;
665     pipeModeSelectParams.bStreamOutEnabled          = m_streamOutEnabled;
666     pipeModeSelectParams.bDeblockerStreamOutEnable  = false;
667     pipeModeSelectParams.bPostDeblockOutEnable      = false;
668     pipeModeSelectParams.bPreDeblockOutEnable       = true;
669 
670     // Set CMD_MFX_SURFACE_STATE
671     MHW_VDBOX_SURFACE_PARAMS surfaceParams;
672     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
673     surfaceParams.Mode          = CODECHAL_DECODE_MODE_JPEG;
674     surfaceParams.psSurface     = &m_destSurface;
675     surfaceParams.ChromaType    = m_jpegPicParams->m_chromaType;
676 
677 #ifdef _DECODE_PROCESSING_SUPPORTED
678     if (m_sfcState->m_sfcPipeOut)
679     {
680         surfaceParams.psSurface = &m_sfcState->m_sfcInSurface;
681     }
682 #endif
683 
684     // Set MFX_PIPE_BUF_ADDR_STATE_CMD
685     MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams;
686     pipeBufAddrParams.Mode = CODECHAL_DECODE_MODE_JPEG;
687     // Predeblock surface is the same as destination surface here because there is no deblocking for JPEG
688     pipeBufAddrParams.psPreDeblockSurface = &m_destSurface;
689 
690 #ifdef _MMC_SUPPORTED
691     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams));
692 #endif
693 
694     // Set MFX_IND_OBJ_BASE_ADDR_STATE_CMD
695     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
696     MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
697     indObjBaseAddrParams.Mode = CODECHAL_DECODE_MODE_JPEG;
698     indObjBaseAddrParams.dwDataSize     = m_copiedDataBufferInUse ? m_nextCopiedDataOffset : m_dataSize;
699     indObjBaseAddrParams.presDataBuffer = &m_resDataBuffer;
700 
701     // Set MFX_JPEG_PIC_STATE_CMD
702     jpegPicState.pJpegPicParams = m_jpegPicParams;
703     if ((m_jpegPicParams->m_rotation == jpegRotation90) || (m_jpegPicParams->m_rotation == jpegRotation270))
704     {
705         jpegPicState.dwWidthInBlocks  = (m_destSurface.dwHeight / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1;
706         jpegPicState.dwHeightInBlocks = (m_destSurface.dwWidth / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1;
707     }
708     else
709     {
710         jpegPicState.dwWidthInBlocks  = (m_destSurface.dwWidth / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1;
711         jpegPicState.dwHeightInBlocks = (m_destSurface.dwHeight / CODECHAL_DECODE_JPEG_BLOCK_SIZE) - 1;
712     }
713 
714     // Add commands to command buffer
715     // MI_FLUSH_DW command -> must be before to MFX_PIPE_MODE_SELECT
716     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
717     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
718     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
719         &cmdBuffer,
720         &flushDwParams));
721 
722     if (m_statusQueryReportingEnabled)
723     {
724         CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(
725             &cmdBuffer));
726     }
727 
728     // MFX_PIPE_MODE_SELECT_CMD
729     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(
730         &cmdBuffer,
731         &pipeModeSelectParams));
732 
733 #ifdef _DECODE_PROCESSING_SUPPORTED
734     // Output decode result through SFC
735     CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->AddSfcCommands(&cmdBuffer));
736 #endif
737 
738     // CMD_MFX_SURFACE_STATE
739     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(
740         &cmdBuffer,
741         &surfaceParams));
742 
743     // MFX_PIPE_BUF_ADDR_STATE_CMD
744     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(
745         &cmdBuffer,
746         &pipeBufAddrParams));
747 
748     // MFX_IND_OBJ_BASE_ADDR_STATE_CMD
749     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(
750         &cmdBuffer,
751         &indObjBaseAddrParams));
752 
753     // MFX_JPEG_PIC_STATE_CMD
754     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegPicCmd(
755         &cmdBuffer,
756         &jpegPicState));
757 
758     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
759 
760     return eStatus;
761 }
762 
DecodePrimitiveLevel()763 MOS_STATUS CodechalDecodeJpeg::DecodePrimitiveLevel()
764 {
765     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
766 
767     CODECHAL_DECODE_FUNCTION_ENTER;
768 
769     // if the bitstream is not complete, don't do any decoding work.
770     if (m_incompletePicture)
771     {
772         return MOS_STATUS_SUCCESS;
773 
774     }
775 
776     MOS_COMMAND_BUFFER cmdBuffer;
777     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
778         m_osInterface,
779         &cmdBuffer,
780         0));
781 
782     // MFX_QM_STATE_CMD
783     MHW_VDBOX_QM_PARAMS qmParams;
784     MOS_ZeroMemory(&qmParams, sizeof(qmParams));
785     qmParams.Standard = CODECHAL_JPEG;
786     qmParams.pJpegQuantMatrix = (CodecJpegQuantMatrix *)m_jpegQMatrix;
787 
788     // Swapping QM(x,y) to QM(y,x) for 90/270 degree rotation
789     if ((m_jpegPicParams->m_rotation == jpegRotation90) ||
790         (m_jpegPicParams->m_rotation == jpegRotation270))
791     {
792         qmParams.bJpegQMRotation = true;
793     }
794     else
795     {
796         qmParams.bJpegQMRotation = false;
797     }
798 
799     for (uint16_t scanCount = 0; scanCount < m_jpegPicParams->m_numCompInFrame; scanCount++)
800     {
801         // Using scanCount here because the same command is used for JPEG decode and encode
802         uint32_t quantTableSelector                                      = m_jpegPicParams->m_quantTableSelector[scanCount];
803         qmParams.pJpegQuantMatrix->m_jpegQMTableType[quantTableSelector] = scanCount;
804         qmParams.JpegQMTableSelector = quantTableSelector;
805         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd(
806             &cmdBuffer,
807             &qmParams));
808     }
809 
810     uint32_t dcCurHuffTblIndex[2] = { 0xff, 0xff };
811     uint32_t acCurHuffTblIndex[2] = { 0xff, 0xff };
812 
813     for (uint16_t scanCount = 0; scanCount < m_jpegScanParams->NumScans; scanCount++)
814     {
815         // MFX_JPEG_HUFF_TABLE
816         uint16_t numComponents = m_jpegScanParams->ScanHeader[scanCount].NumComponents;
817         for (uint16_t scanComponent = 0; scanComponent < numComponents; scanComponent++)
818         {
819             // Determine which huffman table we will be writing to
820             // For gray image, componentIdentifier[jpegComponentU] and componentIdentifier[jpegComponentV] are initialized to 0,
821             // and when ComponentSelector[scanComponent] is equal 0, variable huffTableID is set to 1, and wrong Huffman table is used,
822             // so it is more reasonable to use componentIdentifier[jpegComponentY] to determine which huffman table we will be writing to.
823             uint8_t ComponentSelector =
824                 m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent];
825             uint16_t huffTableID = 0;
826             if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentY])
827             {
828                 huffTableID = 0;
829             }
830             else
831             {
832                 huffTableID = 1;
833             }
834 
835             uint32_t AcTableSelector =
836                 m_jpegScanParams->ScanHeader[scanCount].AcHuffTblSelector[scanComponent];
837             uint32_t DcTableSelector =
838                 m_jpegScanParams->ScanHeader[scanCount].DcHuffTblSelector[scanComponent];
839 
840             // Send the huffman table state command only if the table changed
841             if ((DcTableSelector != dcCurHuffTblIndex[huffTableID]) ||
842                 (AcTableSelector != acCurHuffTblIndex[huffTableID]))
843             {
844                 MHW_VDBOX_HUFF_TABLE_PARAMS huffmanTableParams;
845                 MOS_ZeroMemory(&huffmanTableParams, sizeof(huffmanTableParams));
846 
847                 huffmanTableParams.HuffTableID = huffTableID;
848 
849                 huffmanTableParams.pACBits   = &m_jpegHuffmanTable->HuffTable[AcTableSelector].AC_BITS[0];
850                 huffmanTableParams.pDCBits   = &m_jpegHuffmanTable->HuffTable[DcTableSelector].DC_BITS[0];
851                 huffmanTableParams.pACValues = &m_jpegHuffmanTable->HuffTable[AcTableSelector].AC_HUFFVAL[0];
852                 huffmanTableParams.pDCValues = &m_jpegHuffmanTable->HuffTable[DcTableSelector].DC_HUFFVAL[0];
853 
854                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegHuffTableCmd(
855                     &cmdBuffer,
856                     &huffmanTableParams));
857 
858                 // Set the current huffman table indices for the next scan
859                 dcCurHuffTblIndex[huffTableID] = DcTableSelector;
860                 acCurHuffTblIndex[huffTableID] = AcTableSelector;
861             }
862         }
863 
864         MHW_VDBOX_JPEG_BSD_PARAMS jpegBsdObject;
865         MOS_ZeroMemory(&jpegBsdObject, sizeof(jpegBsdObject));
866 
867         // MFX_JPEG_BSD_OBJECT
868         jpegBsdObject.dwIndirectDataLength     = m_jpegScanParams->ScanHeader[scanCount].DataLength;
869         jpegBsdObject.dwDataStartAddress       = m_jpegScanParams->ScanHeader[scanCount].DataOffset;
870         jpegBsdObject.dwScanHorizontalPosition = m_jpegScanParams->ScanHeader[scanCount].ScanHoriPosition;
871         jpegBsdObject.dwScanVerticalPosition   = m_jpegScanParams->ScanHeader[scanCount].ScanVertPosition;
872         jpegBsdObject.bInterleaved = (numComponents > 1) ? 1 : 0;
873         jpegBsdObject.dwMCUCount               = m_jpegScanParams->ScanHeader[scanCount].MCUCount;
874         jpegBsdObject.dwRestartInterval        = m_jpegScanParams->ScanHeader[scanCount].RestartInterval;
875 
876         uint16_t scanComponentIndex = 0;
877 
878         for (uint16_t scanComponent = 0; scanComponent < numComponents; scanComponent++)
879         {
880             uint8_t ComponentSelector =
881                 m_jpegScanParams->ScanHeader[scanCount].ComponentSelector[scanComponent];
882 
883             if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentY])
884             {
885                 scanComponentIndex = 0;
886             }
887             else if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentU])
888             {
889                 scanComponentIndex = 1;
890             }
891             else if (ComponentSelector == m_jpegPicParams->m_componentIdentifier[jpegComponentV])
892             {
893                 scanComponentIndex = 2;
894             }
895             // Add logic for component identifier JPEG_A
896 
897             jpegBsdObject.sScanComponent |= (1 << scanComponentIndex);
898         }
899 
900         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegBsdObjCmd(
901             &cmdBuffer,
902             &jpegBsdObject));
903     }
904 
905     // Check if destination surface needs to be synchronized
906     MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
907     syncParams.GpuContext = m_videoContext;
908     syncParams.presSyncResource         = &m_destSurface.OsResource;
909     syncParams.bReadOnly = false;
910     syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
911     syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
912 
913     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(
914         m_osInterface,
915         &syncParams));
916     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(
917         m_osInterface,
918         &syncParams));
919 
920     // Update the resource tag (s/w tag) for On-Demand Sync
921     m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
922 
923     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
924     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
925     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
926         &cmdBuffer,
927         &flushDwParams));
928 
929     // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
930     if (m_osInterface->bTagResourceSync)
931     {
932         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(
933             &cmdBuffer,
934             &syncParams));
935     }
936 
937     if (m_statusQueryReportingEnabled)
938     {
939         CodechalDecodeStatusReport decodeStatusReport;
940         decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
941         decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE;
942         decodeStatusReport.m_currDecodedPicRes  = m_destSurface.OsResource;
943 
944         CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(
945             decodeStatusReport,
946             &cmdBuffer));
947     }
948 
949     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
950         &cmdBuffer,
951         nullptr));
952 
953     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
954 
955     CODECHAL_DEBUG_TOOL(
956         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
957             &cmdBuffer,
958             CODECHAL_NUM_MEDIA_STATES,
959             "_DEC"));
960     )
961 
962     if (m_copiedDataBufferInUse)
963     {
964         //Sync up complete frame
965         syncParams = g_cInitSyncParams;
966         syncParams.GpuContext = m_videoContextForWa;
967         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
968 
969         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(
970             m_osInterface,
971             &syncParams));
972 
973         syncParams = g_cInitSyncParams;
974         syncParams.GpuContext = m_videoContext;
975         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
976 
977         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(
978             m_osInterface,
979             &syncParams));
980     }
981 
982     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface->pOsContext);
983 
984     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
985         m_osInterface,
986         &cmdBuffer,
987         m_videoContextUsesNullHw));
988 
989     CODECHAL_DEBUG_TOOL(
990         m_mmc->UpdateUserFeatureKey(&m_destSurface);)
991 
992     if (m_statusQueryReportingEnabled)
993     {
994         CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(
995             m_videoContextUsesNullHw));
996         }
997 
998     // Set output surface layout
999     SetOutputSurfaceLayout(&m_decodeParams.m_outputSurfLayout);
1000 
1001     // Send the signal to indicate decode completion, in case On-Demand Sync is not present
1002     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(
1003         m_osInterface,
1004         &syncParams));
1005 
1006     CODECHAL_DEBUG_TOOL(
1007         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
1008             &m_destSurface,
1009             CodechalDbgAttr::attrDecodeOutputSurface,
1010             "DstSurf"));)
1011     return eStatus;
1012 }
1013 
InitMmcState()1014 MOS_STATUS CodechalDecodeJpeg::InitMmcState()
1015 {
1016 #ifdef _MMC_SUPPORTED
1017     m_mmc = MOS_New(CodechalMmcDecodeJpeg, m_hwInterface, this);
1018     CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc);
1019 #endif
1020 
1021     return MOS_STATUS_SUCCESS;
1022 }
1023 
1024 #ifdef _DECODE_PROCESSING_SUPPORTED
InitSfcState()1025 MOS_STATUS CodechalDecodeJpeg::InitSfcState()
1026 {
1027     m_sfcState = MOS_New(CodechalJpegSfcState);
1028     CODECHAL_DECODE_CHK_NULL_RETURN(m_sfcState);
1029 
1030     return MOS_STATUS_SUCCESS;
1031 }
1032 #endif
1033 
AllocateStandard(CodechalSetting * settings)1034 MOS_STATUS CodechalDecodeJpeg::AllocateStandard(
1035     CodechalSetting *settings)
1036 {
1037     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
1038 
1039     CODECHAL_DECODE_FUNCTION_ENTER;
1040 
1041     CODECHAL_DECODE_CHK_NULL_RETURN(settings);
1042 
1043     CODECHAL_DECODE_CHK_STATUS_RETURN(InitMmcState());
1044 #ifdef _DECODE_PROCESSING_SUPPORTED
1045     CODECHAL_DECODE_CHK_STATUS_RETURN(InitSfcState());
1046 #endif
1047 
1048     m_width = settings->width;
1049     m_height = settings->height;
1050 
1051 #ifdef _DECODE_PROCESSING_SUPPORTED
1052     CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->InitializeSfcState(
1053         this,
1054         m_hwInterface,
1055         m_osInterface));
1056 #endif
1057 
1058     CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResources());
1059 
1060     return eStatus;
1061 }
1062 
1063 #if USE_CODECHAL_DEBUG_TOOL
DumpIQParams(CodecJpegQuantMatrix * matrixData)1064 MOS_STATUS CodechalDecodeJpeg::DumpIQParams(
1065     CodecJpegQuantMatrix *matrixData)
1066 {
1067     CODECHAL_DEBUG_FUNCTION_ENTER;
1068 
1069     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrIqParams))
1070     {
1071         return MOS_STATUS_SUCCESS;
1072     }
1073 
1074     CODECHAL_DEBUG_CHK_NULL(matrixData);
1075 
1076     std::ostringstream oss;
1077     oss.setf(std::ios::showbase | std::ios::uppercase);
1078 
1079     for (uint32_t j = 0; j < jpegNumComponent; j++)
1080     {
1081         oss << "Qmatrix " << std::dec << +j << ": " << std::endl;
1082 
1083         for (int8_t i = 0; i < 56; i += 8)
1084         {
1085             oss << "Qmatrix[" << std::dec << +i / 8 << "]:";
1086             for (uint8_t k = 0; k < 8; k++)
1087                 oss << std::hex << +matrixData->m_quantMatrix[j][i + k]<< " ";
1088             oss << std::endl;
1089         }
1090     }
1091 
1092     const char *fileName = m_debugInterface->CreateFileName(
1093         "_DEC",
1094         CodechalDbgBufferType::bufIqParams,
1095         CodechalDbgExtType::txt);
1096 
1097     std::ofstream ofs(fileName, std::ios::out);
1098     ofs << oss.str();
1099     ofs.close();
1100 
1101     return MOS_STATUS_SUCCESS;
1102 }
1103 
DumpPicParams(CodecDecodeJpegPicParams * picParams)1104 MOS_STATUS CodechalDecodeJpeg::DumpPicParams(
1105     CodecDecodeJpegPicParams *picParams)
1106 {
1107     CODECHAL_DEBUG_FUNCTION_ENTER;
1108 
1109     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
1110     {
1111         return MOS_STATUS_SUCCESS;
1112     }
1113 
1114     CODECHAL_DEBUG_CHK_NULL(picParams);
1115 
1116     std::ostringstream oss;
1117     oss.setf(std::ios::showbase | std::ios::uppercase);
1118     oss.setf(std::ios::hex, std::ios::basefield);
1119 
1120     oss << "destPic.FrameIdx: " << +picParams->m_destPic.FrameIdx << std::endl;
1121     oss << "destPic.PicFlags: " << +picParams->m_destPic.PicFlags << std::endl;
1122     oss << "frameWidth: " << +picParams->m_frameWidth << std::endl;
1123     oss << "frameHeight: " << +picParams->m_frameHeight << std::endl;
1124     oss << "numCompInFrame: " << +picParams->m_numCompInFrame << std::endl;
1125 
1126     //Dump componentIdentifier[jpegNumComponent]
1127     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1128     {
1129         oss << "componentIdentifier[" << +i << "]: " << +picParams->m_componentIdentifier[i] << std::endl;
1130     }
1131 
1132     //Dump quantTableSelector[jpegNumComponent]
1133     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1134     {
1135         oss << "quantTableSelector[" << +i << "]: " << +picParams->m_quantTableSelector[i] << std::endl;
1136     }
1137     oss << "chromaType: " << +picParams->m_chromaType << std::endl;
1138     oss << "rotation: " << +picParams->m_rotation << std::endl;
1139     oss << "totalScans: " << +picParams->m_totalScans << std::endl;
1140     oss << "interleavedData: " << +picParams->m_interleavedData << std::endl;
1141     oss << "reserved: " << +picParams->m_reserved << std::endl;
1142     oss << "statusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl;
1143 
1144     const char *fileName = m_debugInterface->CreateFileName(
1145         "_DEC",
1146         CodechalDbgBufferType::bufPicParams,
1147         CodechalDbgExtType::txt);
1148 
1149     std::ofstream ofs(fileName, std::ios::out);
1150     ofs << oss.str();
1151     ofs.close();
1152 
1153     return MOS_STATUS_SUCCESS;
1154 }
1155 
DumpScanParams(CodecDecodeJpegScanParameter * scanParams)1156 MOS_STATUS CodechalDecodeJpeg::DumpScanParams(
1157     CodecDecodeJpegScanParameter *scanParams)
1158 {
1159     CODECHAL_DEBUG_FUNCTION_ENTER;
1160 
1161     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrScanParams))
1162     {
1163         return MOS_STATUS_SUCCESS;
1164     }
1165     CODECHAL_DEBUG_CHK_NULL(scanParams);
1166 
1167     std::ostringstream oss;
1168     oss.setf(std::ios::showbase | std::ios::uppercase);
1169 
1170     //Dump ScanHeader[jpegNumComponent]
1171     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1172     {
1173         oss << "ScanHeader[" << +i << "].NumComponents: " << +scanParams->ScanHeader[i].NumComponents << std::endl;
1174         //Dump ComponentSelector[jpegNumComponent]
1175         for (uint32_t j = 0; j < jpegNumComponent; ++j)
1176         {
1177             oss << "ScanHeader[" << +i << "].ComponentSelector[" << +j << "]: " << +scanParams->ScanHeader[i].ComponentSelector[j] << std::endl;
1178         }
1179 
1180         //Dump DcHuffTblSelector[jpegNumComponent]
1181         for (uint32_t j = 0; j < jpegNumComponent; ++j)
1182         {
1183             oss << "ScanHeader[" << +i << "].DcHuffTblSelector[" << +j << "]: " << +scanParams->ScanHeader[i].DcHuffTblSelector[j] << std::endl;
1184         }
1185 
1186         //Dump AcHuffTblSelector[jpegNumComponent]
1187         for (uint32_t j = 0; j < jpegNumComponent; ++j)
1188         {
1189             oss << "ScanHeader[" << +i << "].AcHuffTblSelector[" << +j << "]: " << +scanParams->ScanHeader[i].AcHuffTblSelector[j] << std::endl;
1190         }
1191         oss << "ScanHeader[" << +i << "].RestartInterval: " << +scanParams->ScanHeader[i].RestartInterval << std::endl;
1192         oss << "ScanHeader[" << +i << "].MCUCount: " << +scanParams->ScanHeader[i].MCUCount << std::endl;
1193         oss << "ScanHeader[" << +i << "].ScanHoriPosition: " << +scanParams->ScanHeader[i].ScanHoriPosition << std::endl;
1194         oss << "ScanHeader[" << +i << "].ScanVertPosition: " << +scanParams->ScanHeader[i].ScanVertPosition << std::endl;
1195         oss << "ScanHeader[" << +i << "].DataOffset: " << +scanParams->ScanHeader[i].DataOffset << std::endl;
1196         oss << "ScanHeader[" << +i << "].DataLength: " << +scanParams->ScanHeader[i].DataLength << std::endl;
1197     }
1198 
1199     oss << "NumScans: " << +scanParams->NumScans << std::endl;
1200 
1201     const char *fileName = m_debugInterface->CreateFileName(
1202         "_DEC",
1203         CodechalDbgBufferType::bufScanParams,
1204         CodechalDbgExtType::txt);
1205 
1206     std::ofstream ofs(fileName, std::ios::out);
1207     ofs << oss.str();
1208     ofs.close();
1209     return MOS_STATUS_SUCCESS;
1210 }
1211 
DumpHuffmanTable(PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE huffmanTable)1212 MOS_STATUS CodechalDecodeJpeg::DumpHuffmanTable(
1213     PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE huffmanTable)
1214 {
1215     CODECHAL_DEBUG_FUNCTION_ENTER;
1216     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrHuffmanTbl))
1217     {
1218         return MOS_STATUS_SUCCESS;
1219     }
1220     CODECHAL_DEBUG_CHK_NULL(huffmanTable);
1221 
1222     std::ostringstream oss;
1223     oss.setf(std::ios::showbase | std::ios::uppercase);
1224 
1225     //Dump HuffTable[JPEG_MAX_NUM_HUFF_TABLE_INDEX]
1226     for (uint32_t i = 0; i < JPEG_MAX_NUM_HUFF_TABLE_INDEX; ++i)
1227     {
1228         //Dump DC_BITS[JPEG_NUM_HUFF_TABLE_DC_BITS]
1229         oss << "HuffTable[" << +i << "].DC_BITS[0-" << (JPEG_NUM_HUFF_TABLE_DC_BITS - 1) << "]: " << std::endl;
1230 
1231         for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_DC_BITS; ++j)
1232         {
1233             oss << +huffmanTable->HuffTable[i].DC_BITS[j] << " ";
1234             if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_DC_BITS - 1)
1235             {
1236                 oss << std::endl;
1237             }
1238         }
1239         //Dump DC_HUFFVAL[JPEG_NUM_HUFF_TABLE_DC_HUFFVAL]
1240         oss << "HuffTable[" << +i << "].DC_HUFFVAL[0-" << (JPEG_NUM_HUFF_TABLE_DC_HUFFVAL - 1) << "]: " << std::endl;
1241         for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_DC_HUFFVAL; ++j)
1242         {
1243             oss << +huffmanTable->HuffTable[i].DC_HUFFVAL[j] << ' ';
1244             if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_DC_HUFFVAL - 1)
1245             {
1246                 oss << std::endl;
1247             }
1248         }
1249         //Dump AC_BITS[JPEG_NUM_HUFF_TABLE_AC_BITS]
1250         oss << "HuffTable[" << +i << "].AC_BITS[0-" << (JPEG_NUM_HUFF_TABLE_AC_BITS - 1) << "]: " << std::endl;
1251 
1252         for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_BITS; ++j)
1253         {
1254             oss << +huffmanTable->HuffTable[i].AC_BITS[j] << ' ';
1255             if (j % 8 == 7 || j == JPEG_NUM_HUFF_TABLE_AC_BITS - 1)
1256             {
1257                 oss << std::endl;
1258             }
1259         }
1260 
1261         //Dump AC_HUFFVAL[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL]
1262         oss << "HuffTable[" << +i << "].AC_HUFFVAL[0-" << (JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1) << "]: " << std::endl;
1263 
1264         for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_HUFFVAL; ++j)
1265         {
1266             oss << +huffmanTable->HuffTable[i].AC_HUFFVAL[j] << ' ';
1267             if (j % 9 == 8 || j == JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1)
1268             {
1269                 oss << std::endl;
1270             }
1271         }
1272     }
1273 
1274     const char *fileName = m_debugInterface->CreateFileName(
1275         "_DEC",
1276         CodechalDbgBufferType::bufHuffmanTbl,
1277         CodechalDbgExtType::txt);
1278 
1279     std::ofstream ofs(fileName, std::ios::out);
1280     ofs << oss.str();
1281     ofs.close();
1282     return MOS_STATUS_SUCCESS;
1283 }
1284 
1285 #endif
1286