xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_ddi_decode_jpeg.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2009-2017, 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     media_ddi_decode_jpeg.cpp
24 //! \brief    The class implementation of DdiDecodeJPEG  for JPEG decode
25 //!
26 //!
27 
28 #include <va/va_dec_jpeg.h>
29 #include "media_libva_decoder.h"
30 #include "media_libva_util.h"
31 #include "media_ddi_decode_jpeg.h"
32 #include "mos_solo_generic.h"
33 #include "codechal_decode_jpeg.h"
34 #include "media_ddi_decode_const.h"
35 #include "media_ddi_factory.h"
36 
37 typedef enum _DDI_DECODE_JPEG_BUFFER_STATE
38 {
39     BUFFER_UNLOADED = 0,
40     BUFFER_LOADED   = 1,
41 } DDI_DECODE_JPEG_BUFFER_STATE;
42 
43 #define DDI_DECODE_JPEG_MAXIMUM_HUFFMAN_TABLE    2
44 #define DDI_DECODE_JPEG_MAXIMUM_QMATRIX_NUM      4
45 #define DDI_DECODE_JPEG_MAXIMUM_QMATRIX_ENTRIES  64
46 
47 #define DDI_DECODE_JPEG_SLICE_PARAM_BUF_NUM      0x4     //According to JPEG SPEC, max slice per frame is 4
48 
49 static const uint32_t zigzag_order[64] =
50 {
51     0,   1,  8, 16,  9,  2,  3, 10,
52     17, 24, 32, 25, 18, 11,  4,  5,
53     12, 19, 26, 33, 40, 48, 41, 34,
54     27, 20, 13,  6,  7, 14, 21, 28,
55     35, 42, 49, 56, 57, 50, 43, 36,
56     29, 22, 15, 23, 30, 37, 44, 51,
57     58, 59, 52, 45, 38, 31, 39, 46,
58     53, 60, 61, 54, 47, 55, 62, 63
59 };
60 
ParseSliceParams(DDI_MEDIA_CONTEXT * mediaCtx,VASliceParameterBufferJPEGBaseline * slcParam,uint32_t numSlices)61 VAStatus DdiDecodeJPEG::ParseSliceParams(
62     DDI_MEDIA_CONTEXT                   *mediaCtx,
63     VASliceParameterBufferJPEGBaseline  *slcParam,
64     uint32_t                             numSlices)
65 {
66     CodecDecodeJpegScanParameter *jpegSliceParam =
67         (CodecDecodeJpegScanParameter *)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
68 
69     CodecDecodeJpegPicParams *picParam = (CodecDecodeJpegPicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
70 
71     if ((jpegSliceParam == nullptr) ||
72         (picParam == nullptr) ||
73         (slcParam == nullptr))
74     {
75         DDI_ASSERTMESSAGE("Invalid Parameter for Parsing JPEG Slice parameter\n");
76         return VA_STATUS_ERROR_INVALID_PARAMETER;
77     }
78 
79     jpegSliceParam->NumScans += numSlices;
80     picParam->m_totalScans += numSlices;
81     if (picParam->m_totalScans == 1 && slcParam[0].num_components > 1)
82     {
83         picParam->m_interleavedData = 1;
84     }
85 
86     uint32_t j, i;
87     int32_t startIdx = m_numScans;
88     for (j = 0; j < numSlices; j++)
89     {
90         if (j + startIdx >= jpegNumComponent ||
91             slcParam[j].num_components > jpegNumComponent)
92         {
93             return VA_STATUS_ERROR_INVALID_PARAMETER;
94         }
95 
96         for (i = 0; i < slcParam[j].num_components; i++)
97         {
98             jpegSliceParam->ScanHeader[j + startIdx].ComponentSelector[i] = slcParam[j].components[i].component_selector;
99             jpegSliceParam->ScanHeader[j + startIdx].DcHuffTblSelector[i] = slcParam[j].components[i].dc_table_selector;
100             jpegSliceParam->ScanHeader[j + startIdx].AcHuffTblSelector[i] = slcParam[j].components[i].ac_table_selector;
101         }
102         jpegSliceParam->ScanHeader[j + startIdx].NumComponents    = slcParam[j].num_components;
103         jpegSliceParam->ScanHeader[j + startIdx].RestartInterval  = slcParam[j].restart_interval;
104         jpegSliceParam->ScanHeader[j + startIdx].MCUCount         = slcParam[j].num_mcus;
105         jpegSliceParam->ScanHeader[j + startIdx].ScanHoriPosition = slcParam[j].slice_horizontal_position;
106         jpegSliceParam->ScanHeader[j + startIdx].ScanVertPosition = slcParam[j].slice_vertical_position;
107         jpegSliceParam->ScanHeader[j + startIdx].DataOffset       = slcParam[j].slice_data_offset;
108         jpegSliceParam->ScanHeader[j + startIdx].DataLength       = slcParam[j].slice_data_size;
109     }
110 
111     return VA_STATUS_SUCCESS;
112 }
113 
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,VAPictureParameterBufferJPEGBaseline * picParam)114 VAStatus DdiDecodeJPEG::ParsePicParams(
115     DDI_MEDIA_CONTEXT                    *mediaCtx,
116     VAPictureParameterBufferJPEGBaseline *picParam)
117 {
118     CodecDecodeJpegPicParams *jpegPicParam = (CodecDecodeJpegPicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
119 
120     if ((jpegPicParam == nullptr) ||
121         (picParam == nullptr))
122     {
123         DDI_ASSERTMESSAGE("Null Parameter for Parsing JPEG Picture parameter\n");
124         return VA_STATUS_ERROR_INVALID_PARAMETER;
125     }
126 
127     jpegPicParam->m_frameWidth     = picParam->picture_width;
128     jpegPicParam->m_frameHeight    = picParam->picture_height;
129     jpegPicParam->m_numCompInFrame = picParam->num_components;
130 
131     switch (picParam->rotation)
132     {
133     case VA_ROTATION_NONE:
134         jpegPicParam->m_rotation = jpegRotation0;
135         break;
136     case VA_ROTATION_90:
137         jpegPicParam->m_rotation = jpegRotation90;
138         break;
139     case VA_ROTATION_180:
140         jpegPicParam->m_rotation = jpegRotation180;
141         break;
142     case VA_ROTATION_270:
143         jpegPicParam->m_rotation = jpegRotation270;
144         break;
145     default:
146         /* For the other rotation type, the rotation is disabled. */
147         jpegPicParam->m_rotation = jpegRotation0;
148         break;
149         ;
150     }
151 
152     if (jpegPicParam->m_numCompInFrame == 1)
153     {
154         jpegPicParam->m_chromaType = jpegYUV400;
155     }
156     else if (jpegPicParam->m_numCompInFrame == 3)
157     {
158         int32_t h1 = picParam->components[0].h_sampling_factor;
159         int32_t h2 = picParam->components[1].h_sampling_factor;
160         int32_t h3 = picParam->components[2].h_sampling_factor;
161         int32_t v1 = picParam->components[0].v_sampling_factor;
162         int32_t v2 = picParam->components[1].v_sampling_factor;
163         int32_t v3 = picParam->components[2].v_sampling_factor;
164 
165         if (h1 == 2 && h2 == 1 && h3 == 1 &&
166             v1 == 2 && v2 == 1 && v3 == 1)
167         {
168             jpegPicParam->m_chromaType = jpegYUV420;
169         }
170         else if (h1 == 2 && h2 == 1 && h3 == 1 &&
171                  v1 == 1 && v2 == 1 && v3 == 1)
172         {
173             jpegPicParam->m_chromaType = jpegYUV422H2Y;
174         }
175         else if (h1 == 1 && h2 == 1 && h3 == 1 &&
176                  v1 == 1 && v2 == 1 && v3 == 1)
177         {
178             switch (picParam->color_space)
179             {
180             case 0:  //YUV
181                 jpegPicParam->m_chromaType = jpegYUV444;
182                 break;
183             case 1:  //RGB
184                 jpegPicParam->m_chromaType = jpegRGB;
185                 break;
186             case 2:  //BGR
187                 jpegPicParam->m_chromaType = jpegBGR;
188                 break;
189             default:
190                 /* For the other type, the default YUV444 is used */
191                 jpegPicParam->m_chromaType = jpegYUV444;
192                 break;
193                 ;
194             }
195         }
196         else if (h1 == 4 && h2 == 1 && h3 == 1 &&
197                  v1 == 1 && v2 == 1 && v3 == 1)
198         {
199             jpegPicParam->m_chromaType = jpegYUV411;
200         }
201         else if (h1 == 1 && h2 == 1 && h3 == 1 &&
202                  v1 == 2 && v2 == 1 && v3 == 1)
203         {
204             jpegPicParam->m_chromaType = jpegYUV422V2Y;
205         }
206         else if (h1 == 2 && h2 == 1 && h3 == 1 &&
207                  v1 == 2 && v2 == 2 && v3 == 2)
208         {
209             jpegPicParam->m_chromaType = jpegYUV422H4Y;
210         }
211         else if (h1 == 2 && h2 == 2 && h3 == 2 &&
212                  v1 == 2 && v2 == 1 && v3 == 1)
213         {
214             jpegPicParam->m_chromaType = jpegYUV422V4Y;
215         }
216         else
217         {
218             DDI_NORMALMESSAGE("Unsupported sampling factor in JPEG Picture  parameter\n");
219             return VA_STATUS_ERROR_INVALID_PARAMETER;
220         }
221     }
222 
223     memset(jpegPicParam->m_componentIdentifier, 0, jpegNumComponent);
224     memset(jpegPicParam->m_quantTableSelector, 0, jpegNumComponent);
225 
226     if (picParam->num_components > jpegNumComponent)
227     {
228         DDI_NORMALMESSAGE("Unsupported component num in JPEG Picture  parameter\n");
229         return VA_STATUS_ERROR_INVALID_PARAMETER;
230     }
231     for (int32_t i = 0; i < picParam->num_components; i++)
232     {
233         jpegPicParam->m_componentIdentifier[i] = picParam->components[i].component_id;
234         jpegPicParam->m_quantTableSelector[i]  = picParam->components[i].quantiser_table_selector;
235     }
236 
237     return VA_STATUS_SUCCESS;
238 }
239 
ParseHuffmanTbl(DDI_MEDIA_CONTEXT * mediaCtx,VAHuffmanTableBufferJPEGBaseline * huffmanTbl)240 VAStatus DdiDecodeJPEG::ParseHuffmanTbl(
241     DDI_MEDIA_CONTEXT *               mediaCtx,
242     VAHuffmanTableBufferJPEGBaseline *huffmanTbl)
243 {
244     PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE jpegHuffTbl = (PCODECHAL_DECODE_JPEG_HUFFMAN_TABLE)(m_ddiDecodeCtx->DecodeParams.m_huffmanTable);
245     int32_t sumBITS = 0;
246 
247     if ((jpegHuffTbl == nullptr) ||
248         (huffmanTbl == nullptr))
249     {
250         DDI_ASSERTMESSAGE("Null Parameter for Parsing JPEG Huffman Tableparameter\n");
251         return VA_STATUS_ERROR_INVALID_PARAMETER;
252     }
253 
254     memset(jpegHuffTbl, 0, sizeof(CODECHAL_DECODE_JPEG_HUFFMAN_TABLE));
255 
256     for (int32_t i = 0; i < DDI_DECODE_JPEG_MAXIMUM_HUFFMAN_TABLE; i++)
257     {
258         if (huffmanTbl->load_huffman_table[i] == BUFFER_LOADED)
259         {
260             sumBITS = 0;
261             for (int32_t j = 0; j < JPEG_NUM_HUFF_TABLE_DC_BITS; j++)
262             {
263                 sumBITS += huffmanTbl->huffman_table[i].num_dc_codes[j];
264             }
265 
266             if (sumBITS > JPEG_NUM_HUFF_TABLE_DC_HUFFVAL)
267             {
268                 DDI_ASSERTMESSAGE("Huffman table DC entries number is out of HW limitation.");
269                 return VA_STATUS_ERROR_INVALID_PARAMETER;
270             }
271 
272             //the size of jpegHuffTbl->HuffTable[i].DC_BITS is 12 (defined in driver)
273             //the size of huffmanTbl->huffman_table[i].num_dc_codes is 16 (defined in libva)
274             //it is using the size of "DC_BITS" for solve the overflow
275             MOS_SecureMemcpy(jpegHuffTbl->HuffTable[i].DC_BITS,
276                 sizeof(jpegHuffTbl->HuffTable[i].DC_BITS),
277                 huffmanTbl->huffman_table[i].num_dc_codes,
278                 sizeof(jpegHuffTbl->HuffTable[i].DC_BITS));
279             MOS_SecureMemcpy(jpegHuffTbl->HuffTable[i].DC_HUFFVAL,
280                 sizeof(jpegHuffTbl->HuffTable[i].DC_HUFFVAL),
281                 huffmanTbl->huffman_table[i].dc_values,
282                 sizeof(huffmanTbl->huffman_table[i].dc_values));
283             MOS_SecureMemcpy(jpegHuffTbl->HuffTable[i].AC_BITS,
284                 sizeof(jpegHuffTbl->HuffTable[i].AC_BITS),
285                 huffmanTbl->huffman_table[i].num_ac_codes,
286                 sizeof(huffmanTbl->huffman_table[i].num_ac_codes));
287             MOS_SecureMemcpy(jpegHuffTbl->HuffTable[i].AC_HUFFVAL,
288                 sizeof(jpegHuffTbl->HuffTable[i].AC_HUFFVAL),
289                 huffmanTbl->huffman_table[i].ac_values,
290                 sizeof(huffmanTbl->huffman_table[i].ac_values));
291         }
292     }
293 
294     return VA_STATUS_SUCCESS;
295 }
296 
297 /////////////////////////////////////////////////////////////////////////////////////////
298 //
299 //   Function:    JpegQMatrixDecode
300 //   Description: Parse the QMatrix table from VAAPI, and load the valid Qmatrix to the Buffer used by
301 //                    CodecHal
302 //
303 /////////////////////////////////////////////////////////////////////////////////////////
ParseIQMatrix(DDI_MEDIA_CONTEXT * mediaCtx,VAIQMatrixBufferJPEGBaseline * matrix)304 VAStatus DdiDecodeJPEG::ParseIQMatrix(
305         DDI_MEDIA_CONTEXT            *mediaCtx,
306         VAIQMatrixBufferJPEGBaseline *matrix)
307 {
308     CodecJpegQuantMatrix *jpegQMatrix = (CodecJpegQuantMatrix *)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
309 
310     if ((matrix == nullptr) || (jpegQMatrix == nullptr))
311     {
312         DDI_ASSERTMESSAGE("Null Parameter for Parsing JPEG IQMatrix \n");
313         return VA_STATUS_ERROR_INVALID_PARAMETER;
314     }
315 
316     memset(jpegQMatrix, 0, sizeof(CodecJpegQuantMatrix));
317 
318     int32_t idx, idx2;
319     for (idx = 0; idx < DDI_DECODE_JPEG_MAXIMUM_QMATRIX_NUM; idx++)
320     {
321         if (matrix->load_quantiser_table[idx] == BUFFER_LOADED)
322         {
323             for (idx2 = 0; idx2 < DDI_DECODE_JPEG_MAXIMUM_QMATRIX_ENTRIES; idx2++)
324             {
325                 jpegQMatrix->m_quantMatrix[idx][zigzag_order[idx2]] = matrix->quantiser_table[idx][idx2];
326             }
327         }
328     }
329 
330     return VA_STATUS_SUCCESS;
331 }
332 
SetBufferRendered(VABufferID bufferID)333 VAStatus DdiDecodeJPEG::SetBufferRendered(VABufferID bufferID)
334 {
335     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
336 
337     if (bufMgr == nullptr)
338     {
339         DDI_ASSERTMESSAGE("Null Parameter for Parsing Data buffer for JPEG\n");
340         return VA_STATUS_ERROR_INVALID_PARAMETER;
341     }
342 
343     bool renderFlag = false;
344     for (uint32_t i = 0; i < bufMgr->dwNumSliceData; i++)
345     {
346         // Depend on the ID we tracked, if application want to rendered one of them
347         // we set some flags
348         if (bufMgr->pSliceData[i].vaBufferId == bufferID)
349         {
350             if (bufMgr->pSliceData[i].bRendered == false)
351             {
352                 // set the rendered flags. which will be used when EndPicture.
353                 bufMgr->pSliceData[i].bRendered = true;
354                 // calculate the size of a bunch of rendered buffers. for endpicture to allocate appropriate memory size of GPU.
355                 bufMgr->dwSizeOfRenderedSliceData += bufMgr->pSliceData[i].uiLength;
356                 // keep record the render order, so that we can calculate the offset correctly when endpicture.
357                 // in this array we save the buffer index in pSliceData which render in sequence. if application create buffers like: 4,3,5,1,2.
358                 // but only render 2,3,5. the content in this array is: [4,1,2], which is the index of created buffer.
359                 bufMgr->pRenderedOrder[bufMgr->dwNumOfRenderedSliceData] = i;
360                 bufMgr->dwNumOfRenderedSliceData++;
361             }
362             renderFlag = true;
363             break;
364         }
365     }
366 
367     if (renderFlag)
368     {
369         return VA_STATUS_SUCCESS;
370     }
371     else
372     {
373         return VA_STATUS_ERROR_INVALID_BUFFER;
374     }
375 }
376 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)377 VAStatus DdiDecodeJPEG::RenderPicture(
378     VADriverContextP ctx,
379     VAContextID      context,
380     VABufferID       *buffers,
381     int32_t          numBuffers)
382 {
383     DDI_FUNCTION_ENTER();
384 
385     VAStatus           va = VA_STATUS_SUCCESS;
386     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
387 
388     void              *data = nullptr;
389     for (int32_t i = 0; i < numBuffers; i++)
390     {
391         if (!buffers || (buffers[i] == VA_INVALID_ID))
392         {
393             return VA_STATUS_ERROR_INVALID_BUFFER;
394         }
395 
396         DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
397         if (nullptr == buf)
398         {
399             return VA_STATUS_ERROR_INVALID_BUFFER;
400         }
401 
402         uint32_t dataSize = buf->iSize;
403         DdiMedia_MapBuffer(ctx, buffers[i], &data);
404 
405         if (data == nullptr)
406         {
407             return VA_STATUS_ERROR_INVALID_BUFFER;
408         }
409 
410         switch ((int32_t)buf->uiType)
411         {
412         case VASliceDataBufferType:
413         {
414             DDI_CHK_RET(SetBufferRendered(buffers[i]),"SetBufferRendered failed!");
415             m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
416             break;
417         }
418         case VASliceParameterBufferType:
419         {
420             if (buf->uiNumElements == 0)
421             {
422                 return VA_STATUS_ERROR_INVALID_BUFFER;
423             }
424 
425             uint32_t numSlices = buf->uiNumElements;
426 
427             if ((m_numScans + numSlices) > jpegNumComponent)
428             {
429                 DDI_NORMALMESSAGE("the total number of JPEG scans are beyond the supported num(4)\n");
430                 return VA_STATUS_ERROR_INVALID_PARAMETER;
431             }
432             DDI_CHK_RET(AllocSliceParamContext(numSlices),"AllocSliceParamContext failed!");
433             VASliceParameterBufferJPEGBaseline *slcInfo = (VASliceParameterBufferJPEGBaseline *)data;
434             DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfo, numSlices),"ParseSliceParams failed!");
435             m_ddiDecodeCtx->BufMgr.pNumOfRenderedSliceParaForOneBuffer[m_ddiDecodeCtx->BufMgr.dwNumOfRenderedSlicePara] = numSlices;
436             m_ddiDecodeCtx->BufMgr.dwNumOfRenderedSlicePara ++;
437 
438             m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices;
439             m_numScans += numSlices;
440             m_groupIndex++;
441             break;
442         }
443         case VAIQMatrixBufferType:
444         {
445             VAIQMatrixBufferJPEGBaseline *imxBuf = (VAIQMatrixBufferJPEGBaseline *)data;
446             DDI_CHK_RET(ParseIQMatrix(mediaCtx, imxBuf),"ParseIQMatrix failed!");
447             break;
448         }
449         case VAPictureParameterBufferType:
450         {
451             VAPictureParameterBufferJPEGBaseline *picParam = (VAPictureParameterBufferJPEGBaseline *)data;
452             DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
453             break;
454         }
455         case VAHuffmanTableBufferType:
456         {
457             VAHuffmanTableBufferJPEGBaseline *huffTbl = (VAHuffmanTableBufferJPEGBaseline *)data;
458             DDI_CHK_RET(ParseHuffmanTbl(mediaCtx, huffTbl),"ParseHuffmanTbl failed!");
459             break;
460         }
461         case VAProcPipelineParameterBufferType:
462         {
463             DDI_NORMALMESSAGE("ProcPipeline is not supported for JPEGBaseline decoding\n");
464             break;
465         }
466         case VADecodeStreamoutBufferType:
467         {
468             DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
469             m_streamOutEnabled = true;
470             break;
471         }
472         default:
473             va = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
474             break;
475         }
476         DdiMedia_UnmapBuffer(ctx, buffers[i]);
477     }
478 
479     DDI_FUNCTION_EXIT(va);
480     return va;
481 }
482 
BeginPicture(VADriverContextP ctx,VAContextID context,VASurfaceID renderTarget)483 VAStatus DdiDecodeJPEG::BeginPicture(
484     VADriverContextP ctx,
485     VAContextID      context,
486     VASurfaceID      renderTarget)
487 {
488     VAStatus vaStatus = DdiMediaDecode::BeginPicture(ctx, context, renderTarget);
489 
490     if (vaStatus != VA_STATUS_SUCCESS)
491     {
492         return vaStatus;
493     }
494 
495     if (m_jpegBitstreamBuf)
496     {
497         DdiMediaUtil_FreeBuffer(m_jpegBitstreamBuf);
498         MOS_FreeMemory(m_jpegBitstreamBuf);
499         m_jpegBitstreamBuf = nullptr;
500     }
501 
502     CodecDecodeJpegScanParameter *jpegSliceParam =
503         (CodecDecodeJpegScanParameter *)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
504     jpegSliceParam->NumScans = 0;
505 
506     CodecDecodeJpegPicParams *picParam = (CodecDecodeJpegPicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
507     picParam->m_totalScans             = 0;
508 
509     m_numScans = 0;
510     return vaStatus;
511 }
512 
CheckFormat(MOS_FORMAT format)513 bool DdiDecodeJPEG::CheckFormat(MOS_FORMAT format)
514 {
515     bool isSupported = false;
516     CodecDecodeJpegPicParams *jpegPicParam = (CodecDecodeJpegPicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
517     switch (jpegPicParam->m_chromaType)
518     {
519     case jpegYUV400:
520         if (format == Format_400P || format == Format_A8R8G8B8)
521         {
522             isSupported = true;
523         }
524         break;
525     case jpegYUV420:
526         if (format == Format_NV12 || format == Format_YUY2 || format == Format_UYVY || format == Format_IMC3 || format == Format_A8R8G8B8)
527         {
528             isSupported = true;
529         }
530         break;
531     case jpegYUV411:
532         if (format == Format_411P)
533         {
534             isSupported = true;
535         }
536         break;
537     case jpegYUV422H2Y:
538     case jpegYUV422H4Y:
539         if (format == Format_NV12 || format == Format_YUY2 || format == Format_UYVY || format == Format_422H || format == Format_A8R8G8B8)
540         {
541             isSupported = true;
542         }
543         break;
544     case jpegYUV422V2Y:
545     case jpegYUV422V4Y:
546         if (format == Format_NV12 || format == Format_422V || format == Format_A8R8G8B8)
547         {
548             isSupported = true;
549         }
550         break;
551     case jpegYUV444:
552         if (format == Format_444P || format == Format_A8R8G8B8)
553         {
554             isSupported = true;
555         }
556         break;
557     case jpegRGB:
558     case jpegBGR:
559         if (format == Format_RGBP || format == Format_BGRP ||format == Format_A8R8G8B8)
560         {
561             isSupported = true;
562         }
563         break;
564     default:
565         break;
566     }
567 
568     return isSupported;
569 }
570 
InitDecodeParams(VADriverContextP ctx,VAContextID context)571 VAStatus DdiDecodeJPEG::InitDecodeParams(
572     VADriverContextP ctx,
573     VAContextID      context)
574 {
575     /* skip the mediaCtx check as it is checked in caller */
576     PDDI_MEDIA_CONTEXT mediaCtx;
577     mediaCtx = DdiMedia_GetMediaContext(ctx);
578     DDI_CHK_RET(DecodeCombineBitstream(mediaCtx),"DecodeCombineBitstream failed!");
579     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
580     bufMgr->dwNumSliceControl    = 0;
581     memset(&m_destSurface, 0, sizeof(MOS_SURFACE));
582     m_destSurface.dwOffset = 0;
583     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_ddiDecodeCtx->RTtbl);
584 
585     if ((rtTbl == nullptr) || (rtTbl->pCurrentRT == nullptr))
586     {
587         return VA_STATUS_ERROR_INVALID_PARAMETER;
588     }
589     return VA_STATUS_SUCCESS;
590 }
591 
SetDecodeParams()592 VAStatus DdiDecodeJPEG::SetDecodeParams()
593 {
594     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
595 
596     // we do not support mismatched usecase.
597     if ((bufMgr->dwNumOfRenderedSlicePara != bufMgr->dwNumOfRenderedSliceData) ||
598         (bufMgr->dwNumOfRenderedSlicePara == 0))
599     {
600         DDI_NORMALMESSAGE("DDI: Unsupported buffer mismatch usage!\n");
601         return VA_STATUS_ERROR_INVALID_PARAMETER;
602     }
603 
604     // Allocate GPU Buffer description keeper.
605     m_jpegBitstreamBuf = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
606     if (m_jpegBitstreamBuf == nullptr)
607     {
608         DDI_ASSERTMESSAGE("DDI: Allocate  Jpeg Media Buffer Failed!\n");
609         return VA_STATUS_ERROR_UNKNOWN;
610     }
611 
612     m_jpegBitstreamBuf->iSize         = bufMgr->dwSizeOfRenderedSliceData;
613     m_jpegBitstreamBuf->uiNumElements = bufMgr->dwNumOfRenderedSliceData;
614     m_jpegBitstreamBuf->uiType        = VASliceDataBufferType;
615     m_jpegBitstreamBuf->format        = Media_Format_Buffer;
616     m_jpegBitstreamBuf->uiOffset      = 0;
617     m_jpegBitstreamBuf->bCFlushReq    = false;
618     m_jpegBitstreamBuf->pMediaCtx     = m_ddiDecodeCtx->pMediaCtx;
619 
620     // Create GPU buffer
621     VAStatus va  = DdiMediaUtil_CreateBuffer(m_jpegBitstreamBuf, m_ddiDecodeCtx->pMediaCtx->pDrmBufMgr);
622     if (va  != VA_STATUS_SUCCESS)
623     {
624         DdiMediaUtil_FreeBuffer(m_jpegBitstreamBuf);
625         MOS_FreeMemory(m_jpegBitstreamBuf);
626         m_jpegBitstreamBuf = nullptr;
627         return va;
628     }
629 
630     // For the first time you call DdiMediaUtil_LockBuffer for a fresh GPU memory, it will map GPU address to a virtual address.
631     // and then, DdiMediaUtil_LockBuffer is acutally to increase the reference count. so we used here for 2 resaons:
632     //
633     // 1. Map GPU address to virtual at the beginning when we combine the CPU -> GPU.
634     uint8_t *mappedBuf = (uint8_t *)DdiMediaUtil_LockBuffer(m_jpegBitstreamBuf, MOS_LOCKFLAG_WRITEONLY);
635 
636     if (mappedBuf == nullptr)
637     {
638         DdiMediaUtil_FreeBuffer(m_jpegBitstreamBuf);
639         MOS_FreeMemory(m_jpegBitstreamBuf);
640         m_jpegBitstreamBuf = nullptr;
641         return VA_STATUS_ERROR_ALLOCATION_FAILED;
642     }
643 
644     // get the JPEG Slice Header Params for offset recaculated.
645     CodecDecodeJpegScanParameter *sliceParam =
646         (CodecDecodeJpegScanParameter *)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
647 
648     uint32_t bufOffset      = 0;
649     int32_t  orderSlicePara = 0;
650     int32_t  orderSliceData = 0;
651     for (uint32_t i = 0; i < bufMgr->dwNumOfRenderedSliceData; i++)
652     {
653         // get the rendered slice data index in rendered order.
654         int32_t renderedBufIdx = bufMgr->pRenderedOrder[i];
655         if (bufMgr->pSliceData[renderedBufIdx].bRendered)
656         {
657             MOS_SecureMemcpy((void *)(mappedBuf + bufOffset),
658                 bufMgr->pSliceData[renderedBufIdx].uiLength,
659                 bufMgr->pSliceData[renderedBufIdx].pBaseAddress,
660                 bufMgr->pSliceData[renderedBufIdx].uiLength);
661 
662             // since we assume application must make sure ONE slice parameter buffer ONE slice data buffer, so we recaculate header offset here.
663             for (int32_t j = 0; j < bufMgr->pNumOfRenderedSliceParaForOneBuffer[orderSliceData]; j++)
664             {
665                 sliceParam->ScanHeader[orderSlicePara].DataOffset += bufOffset;
666                 orderSlicePara++;
667             }
668             bufOffset += bufMgr->pSliceData[renderedBufIdx].uiLength;
669             bufMgr->pNumOfRenderedSliceParaForOneBuffer[orderSliceData] = 0;
670             orderSliceData++;
671             bufMgr->pSliceData[renderedBufIdx].bRendered = false;
672         }
673     }
674     DdiMediaUtil_UnlockBuffer(m_jpegBitstreamBuf);
675     DdiMedia_MediaBufferToMosResource(m_jpegBitstreamBuf, &(bufMgr->resBitstreamBuffer));
676     bufMgr->dwNumOfRenderedSliceData  = 0;
677     bufMgr->dwNumOfRenderedSlicePara  = 0;
678     bufMgr->dwSizeOfRenderedSliceData = 0;
679 
680     m_destSurface.dwOffset = 0;
681     m_destSurface.Format   = Format_NV12;
682 
683     CodecDecodeJpegPicParams *jpegPicParam = (CodecDecodeJpegPicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
684     if((m_ddiDecodeCtx->RTtbl.pCurrentRT->format == Media_Format_NV12)
685         &&(jpegPicParam->m_chromaType == jpegYUV444))
686     {
687         UnRegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT);
688         m_ddiDecodeCtx->RTtbl.pCurrentRT = DdiMedia_ReplaceSurfaceWithNewFormat(m_ddiDecodeCtx->RTtbl.pCurrentRT, Media_Format_444P);
689         RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT);
690     }
691     if(m_ddiDecodeCtx->RTtbl.pCurrentRT != nullptr)
692     {
693         DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pCurrentRT, &(m_destSurface.OsResource));
694     }
695 
696     if (!CheckFormat(m_destSurface.OsResource.Format))
697     {
698         DDI_ASSERTMESSAGE("Surface fomrat of decoded surface is inconsistent with Codec bitstream!\n");
699         return VA_STATUS_ERROR_INVALID_PARAMETER;
700     }
701 
702     (&m_ddiDecodeCtx->DecodeParams)->m_destSurface = &m_destSurface;
703 
704     (&m_ddiDecodeCtx->DecodeParams)->m_deblockSurface = nullptr;
705 
706     (&m_ddiDecodeCtx->DecodeParams)->m_dataBuffer       = &bufMgr->resBitstreamBuffer;
707     (&m_ddiDecodeCtx->DecodeParams)->m_bitStreamBufData = bufMgr->pBitstreamBuffer;
708     Mos_Solo_OverrideBufferSize((&m_ddiDecodeCtx->DecodeParams)->m_dataSize, (&m_ddiDecodeCtx->DecodeParams)->m_dataBuffer);
709 
710     (&m_ddiDecodeCtx->DecodeParams)->m_bitplaneBuffer = nullptr;
711 
712     if (m_streamOutEnabled)
713     {
714         (&m_ddiDecodeCtx->DecodeParams)->m_streamOutEnabled        = true;
715         (&m_ddiDecodeCtx->DecodeParams)->m_externalStreamOutBuffer = &bufMgr->resExternalStreamOutBuffer;
716     }
717     else
718     {
719         (&m_ddiDecodeCtx->DecodeParams)->m_streamOutEnabled        = false;
720         (&m_ddiDecodeCtx->DecodeParams)->m_externalStreamOutBuffer = nullptr;
721     }
722     return VA_STATUS_SUCCESS;
723 }
724 
AllocSliceParamContext(uint32_t numSlices)725 VAStatus DdiDecodeJPEG::AllocSliceParamContext(
726     uint32_t numSlices)
727 {
728     uint32_t baseSize = sizeof(CodecDecodeJpegScanParameter);
729 
730     if (m_sliceParamBufNum < (m_ddiDecodeCtx->DecodeParams.m_numSlices + numSlices))
731     {
732         // in order to avoid that the buffer is reallocated multi-times,
733         // extra 10 slices are added.
734         uint32_t extraSlices = numSlices + 10;
735 
736         m_ddiDecodeCtx->DecodeParams.m_sliceParams = realloc(m_ddiDecodeCtx->DecodeParams.m_sliceParams,
737             baseSize * (m_sliceParamBufNum + extraSlices));
738 
739         if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
740         {
741             return VA_STATUS_ERROR_ALLOCATION_FAILED;
742         }
743 
744         memset((void *)((uint8_t *)m_ddiDecodeCtx->DecodeParams.m_sliceParams + baseSize * m_sliceParamBufNum), 0, baseSize * extraSlices);
745         m_sliceParamBufNum += extraSlices;
746     }
747 
748     return VA_STATUS_SUCCESS;
749 }
750 
DestroyContext(VADriverContextP ctx)751 void DdiDecodeJPEG::DestroyContext(
752     VADriverContextP ctx)
753 {
754     FreeResourceBuffer();
755     // explicitly call the base function to do the further clean-up
756     DdiMediaDecode::DestroyContext(ctx);
757 }
758 
GetPicParamBuf(DDI_CODEC_COM_BUFFER_MGR * bufMgr)759 uint8_t* DdiDecodeJPEG::GetPicParamBuf(
760     DDI_CODEC_COM_BUFFER_MGR    *bufMgr)
761 {
762     return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_JPEG.PicParamJPEG));
763 }
764 
AllocBsBuffer(DDI_CODEC_COM_BUFFER_MGR * bufMgr,DDI_MEDIA_BUFFER * buf)765 VAStatus DdiDecodeJPEG::AllocBsBuffer(
766     DDI_CODEC_COM_BUFFER_MGR   *bufMgr,
767     DDI_MEDIA_BUFFER           *buf)
768 {
769     // Allocate JPEG slice data memory from CPU.
770     uint8_t                   *bsAddr;
771     uint32_t                   index;
772 
773     index = bufMgr->dwNumSliceData;
774 
775     /* the pSliceData needs to be reallocated in order to contain more SliceDataBuf */
776     if (index >= bufMgr->m_maxNumSliceData)
777     {
778         /* In theroy it can resize the m_maxNumSliceData one by one. But in order to
779          * avoid calling realloc frequently, it will try to allocate 10 to  hold more
780          * SliceDataBuf. This is only for the optimized purpose.
781          */
782         int32_t reallocSize = bufMgr->m_maxNumSliceData + 10;
783 
784         bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)realloc(bufMgr->pSliceData, sizeof(bufMgr->pSliceData[0]) * reallocSize);
785 
786         if (bufMgr->pSliceData == nullptr)
787         {
788             DDI_ASSERTMESSAGE("fail to reallocate pSliceData for JPEG\n.");
789             return VA_STATUS_ERROR_ALLOCATION_FAILED;
790         }
791         memset((void *)(bufMgr->pSliceData + bufMgr->m_maxNumSliceData), 0,
792                sizeof(bufMgr->pSliceData[0]) * 10);
793 
794         bufMgr->m_maxNumSliceData += 10;
795     }
796 
797     bsAddr = (uint8_t*)MOS_AllocAndZeroMemory(buf->iSize);
798     if(bsAddr == 0)
799     {
800         return VA_STATUS_ERROR_ALLOCATION_FAILED;
801     }
802 
803     buf->pData                             = bsAddr;
804     buf->format                            = Media_Format_CPU;
805     buf->bCFlushReq                        = false;
806     buf->uiOffset                          = 0;
807     bufMgr->pSliceData[index].uiLength     = buf->iSize;
808     bufMgr->pSliceData[index].uiOffset     = buf->uiOffset;
809     bufMgr->pSliceData[index].pBaseAddress = buf->pData;
810     bufMgr->dwNumSliceData ++;
811     return VA_STATUS_SUCCESS;
812 }
813 
AllocSliceControlBuffer(DDI_MEDIA_BUFFER * buf)814 VAStatus DdiDecodeJPEG::AllocSliceControlBuffer(
815     DDI_MEDIA_BUFFER       *buf)
816 {
817     DDI_CODEC_COM_BUFFER_MGR   *bufMgr;
818     uint32_t                    availSize;
819     uint32_t                    newSize;
820 
821     bufMgr     = &(m_ddiDecodeCtx->BufMgr);
822     availSize = m_sliceCtrlBufNum - bufMgr->dwNumSliceControl;
823 
824     if(availSize < buf->uiNumElements)
825     {
826         newSize   = sizeof(VASliceParameterBufferJPEGBaseline) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements);
827         bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG = (VASliceParameterBufferJPEGBaseline *)realloc(bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG, newSize);
828         if(bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG == nullptr)
829         {
830             return VA_STATUS_ERROR_ALLOCATION_FAILED;
831         }
832         MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferJPEGBaseline) * (buf->uiNumElements - availSize));
833         m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements;
834     }
835     buf->pData      = (uint8_t*)bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG;
836     buf->uiOffset   = sizeof(VASliceParameterBufferJPEGBaseline) * bufMgr->dwNumSliceControl;
837 
838     bufMgr->dwNumSliceControl += buf->uiNumElements;
839 
840     return VA_STATUS_SUCCESS;
841 }
842 
ContextInit(int32_t picWidth,int32_t picHeight)843 void DdiDecodeJPEG::ContextInit(
844     int32_t picWidth,
845     int32_t picHeight)
846 {
847     // call the function in base class to initialize it.
848     DdiMediaDecode::ContextInit(picWidth, picHeight);
849 
850     m_ddiDecodeCtx->wMode    = CODECHAL_DECODE_MODE_JPEG;
851 }
852 
InitResourceBuffer()853 VAStatus DdiDecodeJPEG::InitResourceBuffer()
854 {
855     VAStatus                  vaStatus = VA_STATUS_SUCCESS;
856     DDI_CODEC_COM_BUFFER_MGR *bufMgr   = &(m_ddiDecodeCtx->BufMgr);
857     bufMgr->pSliceData                 = nullptr;
858 
859     bufMgr->ui64BitstreamOrder = 0;
860     bufMgr->dwMaxBsSize        = m_width *
861                           m_height * 3 / 2;
862 
863     bufMgr->dwNumSliceData    = 0;
864     bufMgr->dwNumSliceControl = 0;
865 
866     m_sliceCtrlBufNum = DDI_DECODE_JPEG_SLICE_PARAM_BUF_NUM;
867     bufMgr->m_maxNumSliceData         = DDI_DECODE_JPEG_SLICE_PARAM_BUF_NUM;
868     bufMgr->pSliceData                = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) * DDI_DECODE_JPEG_SLICE_PARAM_BUF_NUM);
869     if (bufMgr->pSliceData == nullptr)
870     {
871         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
872         goto finish;
873     }
874     bufMgr->dwNumOfRenderedSlicePara                         = 0;
875     bufMgr->dwNumOfRenderedSliceData                         = 0;
876     bufMgr->pNumOfRenderedSliceParaForOneBuffer              = (int32_t *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pNumOfRenderedSliceParaForOneBuffer[0]) * m_sliceCtrlBufNum);
877     bufMgr->pRenderedOrder                                   = (int32_t *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pRenderedOrder[0]) * m_sliceCtrlBufNum);
878     bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG = (VASliceParameterBufferJPEGBaseline *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferJPEGBaseline) * m_sliceCtrlBufNum);
879     if (bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG == nullptr)
880     {
881         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
882         goto finish;
883     }
884 
885     return VA_STATUS_SUCCESS;
886 
887 finish:
888     FreeResourceBuffer();
889     return vaStatus;
890 }
891 
FreeResourceBuffer()892 void DdiDecodeJPEG::FreeResourceBuffer()
893 {
894     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
895 
896     if (bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG)
897     {
898         MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG);
899         bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG = nullptr;
900     }
901     bufMgr->dwNumOfRenderedSlicePara = 0;
902     bufMgr->dwNumOfRenderedSliceData = 0;
903     MOS_FreeMemory(bufMgr->pNumOfRenderedSliceParaForOneBuffer);
904     bufMgr->pNumOfRenderedSliceParaForOneBuffer = nullptr;
905     MOS_FreeMemory(bufMgr->pRenderedOrder);
906     bufMgr->pRenderedOrder = nullptr;
907 
908     for (uint32_t i = 0; i < bufMgr->dwNumSliceData && (bufMgr->pSliceData != nullptr); i++)
909     {
910         if (bufMgr->pSliceData[i].pBaseAddress != nullptr)
911         {
912             MOS_FreeMemory(bufMgr->pSliceData[i].pBaseAddress);
913             bufMgr->pSliceData[i].pBaseAddress = nullptr;
914         }
915     }
916 
917     bufMgr->dwNumSliceData    = 0;
918 
919     if (m_jpegBitstreamBuf)
920     {
921         DdiMediaUtil_FreeBuffer(m_jpegBitstreamBuf);
922         MOS_FreeMemory(m_jpegBitstreamBuf);
923         m_jpegBitstreamBuf = nullptr;
924     }
925 
926     // free decode bitstream buffer object
927     MOS_FreeMemory(bufMgr->pSliceData);
928     bufMgr->pSliceData = nullptr;
929 
930     return;
931 }
932 
CodecHalInit(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)933 VAStatus DdiDecodeJPEG::CodecHalInit(
934     DDI_MEDIA_CONTEXT *mediaCtx,
935     void              *ptr)
936 {
937     VAStatus     vaStatus = VA_STATUS_SUCCESS;
938     MOS_CONTEXT *mosCtx   = (MOS_CONTEXT *)ptr;
939 
940     CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
941     m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
942 
943     CODECHAL_STANDARD_INFO standardInfo;
944     memset(&standardInfo, 0, sizeof(standardInfo));
945 
946     standardInfo.CodecFunction = codecFunction;
947     standardInfo.Mode          = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
948 
949     m_codechalSettings->codecFunction                = codecFunction;
950     m_codechalSettings->width                      = m_width;
951     m_codechalSettings->height                     = m_height;
952     m_codechalSettings->intelEntrypointInUse        = false;
953 
954     m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
955 
956     m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
957 
958     m_codechalSettings->mode     = CODECHAL_DECODE_MODE_JPEG;
959     m_codechalSettings->standard = CODECHAL_JPEG;
960 
961 #ifdef _DECODE_PROCESSING_SUPPORTED
962     m_codechalSettings->sfcEnablingHinted = true;
963 #endif
964 
965     m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = MOS_AllocAndZeroMemory(sizeof(CodecJpegQuantMatrix));
966     if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr)
967     {
968         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
969         goto CleanUpandReturn;
970     }
971     m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CodecDecodeJpegPicParams));
972     if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
973     {
974         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
975         goto CleanUpandReturn;
976     }
977 
978     m_ddiDecodeCtx->DecodeParams.m_huffmanTable = (void*)MOS_AllocAndZeroMemory(sizeof(CODECHAL_DECODE_JPEG_HUFFMAN_TABLE));
979     if (!m_ddiDecodeCtx->DecodeParams.m_huffmanTable)
980     {
981         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
982         goto CleanUpandReturn;
983     }
984 
985     m_sliceParamBufNum         = DDI_DECODE_JPEG_SLICE_PARAM_BUF_NUM;
986     m_ddiDecodeCtx->DecodeParams.m_sliceParams = (void *)MOS_AllocAndZeroMemory(m_sliceParamBufNum * sizeof(CodecDecodeJpegScanParameter));
987 
988     if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
989     {
990         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
991         goto CleanUpandReturn;
992     }
993 
994     vaStatus = CreateCodecHal(mediaCtx,
995         ptr,
996         &standardInfo);
997 
998     if (vaStatus != VA_STATUS_SUCCESS)
999     {
1000         goto CleanUpandReturn;
1001     }
1002 
1003     if (InitResourceBuffer() != VA_STATUS_SUCCESS)
1004     {
1005         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1006         goto CleanUpandReturn;
1007     }
1008 
1009     return vaStatus;
1010 
1011 CleanUpandReturn:
1012     FreeResourceBuffer();
1013 
1014     if (m_ddiDecodeCtx->pCodecHal)
1015     {
1016         m_ddiDecodeCtx->pCodecHal->Destroy();
1017         MOS_Delete(m_ddiDecodeCtx->pCodecHal);
1018         m_ddiDecodeCtx->pCodecHal = nullptr;
1019     }
1020 
1021     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
1022     m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
1023     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
1024     m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
1025     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_huffmanTable);
1026     m_ddiDecodeCtx->DecodeParams.m_huffmanTable = nullptr;
1027     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
1028     m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
1029 
1030     return vaStatus;
1031 }
1032 
1033 extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
1034 
1035 static bool jpegRegistered =
1036     MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeJPEG>(DECODE_ID_JPEG);
1037