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