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