1 /*
2 * Copyright (c) 2018, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     codechal_encode_jpeg_g11.cpp
24 //! \brief    Defines state class for JPEG encoder.
25 //!
26 
27 #include "codechal_encode_jpeg.h"
28 #include "codechal_encode_jpeg_g11.h"
29 #if USE_CODECHAL_DEBUG_TOOL
30 #include "mos_util_user_interface.h"
31 #endif
32 
33 
CodechalEncodeJpegStateG11(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)34 CodechalEncodeJpegStateG11::CodechalEncodeJpegStateG11(
35         CodechalHwInterface* hwInterface,
36         CodechalDebugInterface* debugInterface,
37         PCODECHAL_STANDARD_INFO standardInfo): CodechalEncodeJpegState(hwInterface, debugInterface, standardInfo),
38     m_sinlgePipeVeState(nullptr)
39 {
40     CODECHAL_ENCODE_FUNCTION_ENTER;
41 
42     memset(m_refList, 0, sizeof(m_refList));
43 
44     CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
45     m_osInterface->pfnVirtualEngineSupported(m_osInterface, false, true);
46     Mos_SetVirtualEngineSupported(m_osInterface, true);
47 }
48 
49 
~CodechalEncodeJpegStateG11()50 CodechalEncodeJpegStateG11::~CodechalEncodeJpegStateG11()
51 {
52     if (m_sinlgePipeVeState)
53     {
54         MOS_FreeMemAndSetNull(m_sinlgePipeVeState);
55     }
56 }
57 
SetAndPopulateVEHintParams(PMOS_COMMAND_BUFFER cmdBuffer)58 MOS_STATUS CodechalEncodeJpegStateG11::SetAndPopulateVEHintParams(
59     PMOS_COMMAND_BUFFER  cmdBuffer)
60 {
61     MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;
62 
63     CODECHAL_ENCODE_FUNCTION_ENTER;
64 
65     if (!MOS_VE_SUPPORTED(m_osInterface))
66     {
67         return eStatus;
68     }
69 
70     if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
71     {
72         MOS_VIRTUALENGINE_SET_PARAMS  vesetParams;
73         MOS_ZeroMemory(&vesetParams, sizeof(vesetParams));
74         vesetParams.bNeedSyncWithPrevious = true;
75         vesetParams.bSFCInUse = false;
76         CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_SetHintParams(m_sinlgePipeVeState, &vesetParams));
77     }
78     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_PopulateHintParams(m_sinlgePipeVeState, cmdBuffer, true));
79 
80     return eStatus;
81 }
82 
UserFeatureKeyReport()83 MOS_STATUS CodechalEncodeJpegStateG11::UserFeatureKeyReport()
84 {
85     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
86 
87     CODECHAL_ENCODE_FUNCTION_ENTER;
88 
89     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::UserFeatureKeyReport());
90 
91 #if (_DEBUG || _RELEASE_INTERNAL)
92 
93     // VE2.0 Reporting
94     CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_ENABLE_ENCODE_VE_CTXSCHEDULING_ID, MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface), m_osInterface->pOsContext);
95 
96 #endif // _DEBUG || _RELEASE_INTERNAL
97     return eStatus;
98 }
99 
ExecuteSliceLevel()100 MOS_STATUS CodechalEncodeJpegStateG11::ExecuteSliceLevel()
101 {
102     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
103 
104     CODECHAL_ENCODE_FUNCTION_ENTER;
105 
106     MOS_COMMAND_BUFFER cmdBuffer;
107     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
108 
109     if (m_encodeParams.dwNumSlices != 1)
110     {
111         CODECHAL_ENCODE_ASSERTMESSAGE("JPEG encode only one scan is supported.");
112     }
113 
114     MOS_SURFACE *surface = &m_rawSurface;
115 
116     bool useSingleDefaultQuantTable = (m_jpegQuantMatrixSent == false &&
117         ((surface->Format == Format_A8R8G8B8) ||
118         (surface->Format == Format_X8R8G8B8) ||
119             (surface->Format == Format_A8B8G8R8) ||
120             (surface->Format == Format_X8B8G8R8)));
121 
122     CodecJpegQuantMatrix *tempJpegQuantMatrix = (CodecJpegQuantMatrix *)MOS_AllocAndZeroMemory(sizeof(CodecJpegQuantMatrix));
123     CODECHAL_ENCODE_CHK_NULL_RETURN(tempJpegQuantMatrix);
124 
125     static_assert(JPEG_MAX_NUM_QUANT_TABLE_INDEX <= JPEG_MAX_NUM_OF_QUANTMATRIX,
126         "access to CodecJpegQuantMatrix is controlled by numQuantTables");
127 
128     uint32_t numQuantTables = JPEG_MAX_NUM_QUANT_TABLE_INDEX;
129     for (uint32_t scanCount = 0; scanCount < m_encodeParams.dwNumSlices; scanCount++)
130     {
131         MHW_VDBOX_QM_PARAMS fqmParams;
132         MOS_ZeroMemory(&fqmParams, sizeof(fqmParams));
133 
134         // set MFX_FQM_STATE
135         fqmParams.pJpegQuantMatrix = tempJpegQuantMatrix;
136 
137         // For monochrome inputs there will be only 1 quantization table and huffman table sent
138         if (m_jpegPicParams->m_inputSurfaceFormat == codechalJpegY8)
139         {
140             numQuantTables = 1;
141             m_encodeParams.dwNumHuffBuffers = 2; //for Y8 only 2 huff tables
142         }
143         // If there is only 1 quantization table copy over the table to 2nd and 3rd table in JPEG state (used for frame header)
144         // OR For RGB input surfaces, if the app does not send quantization tables, then use luma quant table for all 3 components
145         else if (m_jpegPicParams->m_numQuantTable == 1 || useSingleDefaultQuantTable)
146         {
147             for (auto i = 1; i < JPEG_MAX_NUM_QUANT_TABLE_INDEX; i++)
148             {
149                 m_jpegQuantTables->m_quantTable[i].m_precision = m_jpegQuantTables->m_quantTable[0].m_precision;
150                 m_jpegQuantTables->m_quantTable[i].m_tableID = m_jpegQuantTables->m_quantTable[0].m_tableID;
151 
152                 eStatus = MOS_SecureMemcpy(&m_jpegQuantTables->m_quantTable[i].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t),
153                     &m_jpegQuantTables->m_quantTable[0].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t));
154                 if (eStatus != MOS_STATUS_SUCCESS)
155                 {
156                     CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
157                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
158                     return eStatus;
159                 }
160             }
161         }
162         // If there are 2 quantization tables copy over the second table to 3rd table in JPEG state since U and V share the same table (used for frame header)
163         else if (m_jpegPicParams->m_numQuantTable == 2)
164         {
165             m_jpegQuantTables->m_quantTable[2].m_precision = m_jpegQuantTables->m_quantTable[1].m_precision;
166             m_jpegQuantTables->m_quantTable[2].m_tableID = m_jpegQuantTables->m_quantTable[1].m_tableID;
167 
168             eStatus = MOS_SecureMemcpy(&m_jpegQuantTables->m_quantTable[2].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t),
169                 &m_jpegQuantTables->m_quantTable[1].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t));
170             if (eStatus != MOS_STATUS_SUCCESS)
171             {
172                 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
173                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
174                 return eStatus;
175             }
176 
177         }
178         // else 3 quantization tables are sent by the application for non monochrome input formats. In that case, do nothing.
179 
180         for (uint32_t i = 0; i < numQuantTables; i++)
181         {
182             fqmParams.pJpegQuantMatrix->m_jpegQMTableType[i] = m_jpegQuantTables->m_quantTable[i].m_tableID; // Used to distinguish between Y,U,V quantization tables for the same scan
183 
184             for (auto j = 0; j < JPEG_NUM_QUANTMATRIX; j++)
185             {
186                 uint32_t k = jpeg_qm_scan_8x8[j];
187 
188                 // copy over Quant matrix in raster order from zig zag
189                 fqmParams.pJpegQuantMatrix->m_quantMatrix[i][k] = (uint8_t)m_jpegQuantTables->m_quantTable[i].m_qm[j];
190             }
191         }
192 
193         eStatus = (MOS_STATUS) m_mfxInterface->AddMfxJpegFqmCmd(&cmdBuffer, &fqmParams, numQuantTables);
194         if (eStatus != MOS_STATUS_SUCCESS)
195         {
196             MOS_SafeFreeMemory(tempJpegQuantMatrix);
197             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
198         }
199 
200         // set MFC_JPEG_HUFF_TABLE - Convert encoded huffman table to actual table for HW
201         // We need a different params struct for JPEG Encode Huffman table because JPEG decode huffman table has Bits and codes,
202         // whereas JPEG encode huffman table has huffman code lengths and values
203         MHW_VDBOX_ENCODE_HUFF_TABLE_PARAMS   huffTableParams[JPEG_MAX_NUM_HUFF_TABLE_INDEX] = {};
204         for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers; i++)
205         {
206             CodechalEncodeJpegHuffTable huffmanTable;// intermediate table for each AC/DC component which will be copied to huffTableParams
207             MOS_ZeroMemory(&huffmanTable, sizeof(huffmanTable));
208 
209             eStatus = (MOS_STATUS) ConvertHuffDataToTable(m_jpegHuffmanTable->m_huffmanData[i], &huffmanTable);
210             if (eStatus != MOS_STATUS_SUCCESS)
211             {
212                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
213                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
214             }
215 
216             huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].HuffTableID = m_jpegHuffmanTable->m_huffmanData[i].m_tableID;
217 
218             if (m_jpegHuffmanTable->m_huffmanData[i].m_tableClass == 0) // DC table
219             {
220                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(
221                     huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pDCCodeValues,
222                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint16_t),
223                     &huffmanTable.m_huffCode,
224                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint16_t));
225                 if (eStatus != MOS_STATUS_SUCCESS)
226                 {
227                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
228                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
229                 }
230 
231                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pDCCodeLength,
232                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint8_t),
233                     &huffmanTable.m_huffSize,
234                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint8_t));
235                 if (eStatus != MOS_STATUS_SUCCESS)
236                 {
237                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
238                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
239                 }
240             }
241             else // AC Table
242             {
243                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pACCodeValues,
244                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t),
245                     &huffmanTable.m_huffCode,
246                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t));
247                 if (eStatus != MOS_STATUS_SUCCESS)
248                 {
249                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
250                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
251                 }
252 
253                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pACCodeLength,
254                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t),
255                     &huffmanTable.m_huffSize,
256                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t));
257                 if (eStatus != MOS_STATUS_SUCCESS)
258                 {
259                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
260                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
261                 }
262             }
263         }
264 
265         // Send 2 huffman table commands - 1 for Luma and one for chroma for non-monchrome input formats
266         // If only one table is sent by the app (2 buffers), send the same table for Luma and chroma
267         bool repeatHuffTable = false;
268         if ((m_encodeParams.dwNumHuffBuffers / 2 < JPEG_MAX_NUM_HUFF_TABLE_INDEX)
269             && (m_jpegPicParams->m_inputSurfaceFormat != codechalJpegY8))
270         {
271             repeatHuffTable = true;
272 
273             // Copy over huffman data to the other two data buffers for JPEG picture header
274             for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers; i++)
275             {
276                 m_jpegHuffmanTable->m_huffmanData[i + 2].m_tableClass = m_jpegHuffmanTable->m_huffmanData[i].m_tableClass;
277                 m_jpegHuffmanTable->m_huffmanData[i + 2].m_tableID = m_jpegHuffmanTable->m_huffmanData[i].m_tableID;
278 
279                 eStatus = MOS_SecureMemcpy(&m_jpegHuffmanTable->m_huffmanData[i + 2].m_bits[0],
280                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_BITS,
281                     &m_jpegHuffmanTable->m_huffmanData[i].m_bits[0],
282                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_BITS);
283                 if (eStatus != MOS_STATUS_SUCCESS)
284                 {
285                     CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
286                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
287                     return eStatus;
288                 }
289 
290                 eStatus = MOS_SecureMemcpy(&m_jpegHuffmanTable->m_huffmanData[i + 2].m_huffVal[0],
291                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_HUFFVAL,
292                     &m_jpegHuffmanTable->m_huffmanData[i].m_huffVal[0],
293                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_HUFFVAL);
294                 if (eStatus != MOS_STATUS_SUCCESS)
295                 {
296                     CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
297                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
298                     return eStatus;
299                 }
300             }
301         }
302 
303         // the number of huffman commands is half of the huffman buffers sent by the app, since AC and DC buffers are combined into one command
304         for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers / 2; i++)
305         {
306             if (repeatHuffTable)
307             {
308                 eStatus = (MOS_STATUS) (m_mfxInterface->AddMfcJpegHuffTableStateCmd(&cmdBuffer, &huffTableParams[i]));
309                 if (eStatus != MOS_STATUS_SUCCESS)
310                 {
311                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
312                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
313                 }
314             }
315 
316             eStatus = (MOS_STATUS) m_mfxInterface->AddMfcJpegHuffTableStateCmd(&cmdBuffer, &huffTableParams[i]);
317             if (eStatus != MOS_STATUS_SUCCESS)
318             {
319                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
320                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
321             }
322         }
323 
324         // set MFC_JPEG_SCAN_OBJECT
325         MhwVdboxJpegScanParams scanObjectParams;
326         scanObjectParams.mode = m_mode;
327         scanObjectParams.inputSurfaceFormat = (CodecEncodeJpegInputSurfaceFormat)m_jpegPicParams->m_inputSurfaceFormat;
328         scanObjectParams.dwPicWidth = m_jpegPicParams->m_picWidth;
329         scanObjectParams.dwPicHeight = m_jpegPicParams->m_picHeight;
330         scanObjectParams.pJpegEncodeScanParams = m_jpegScanParams;
331 
332         eStatus = (MOS_STATUS) m_mfxInterface->AddMfcJpegScanObjCmd(&cmdBuffer, &scanObjectParams);
333         if (eStatus != MOS_STATUS_SUCCESS)
334         {
335             MOS_SafeFreeMemory(tempJpegQuantMatrix);
336             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
337         }
338 
339         // set MFC_JPEG_PAK_INSERT_OBJECT
340         MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
341         MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
342 
343         // The largest component written through the MFC_JPEG_PAK_INSERT_OBJECT command is Huffman table
344         pakInsertObjectParams.pBsBuffer = (BSBuffer *)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeJpegFrameHeader));
345         if (pakInsertObjectParams.pBsBuffer == nullptr)
346         {
347             MOS_SafeFreeMemory(tempJpegQuantMatrix);
348             CODECHAL_ENCODE_CHK_NULL_RETURN(nullptr);
349         }
350 
351         if(!m_fullHeaderInAppData)
352         {
353             // Add SOI (0xFFD8) (only if it was sent by the application)
354             eStatus = (MOS_STATUS)PackSOI(pakInsertObjectParams.pBsBuffer);
355             if (eStatus != MOS_STATUS_SUCCESS)
356             {
357                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
358                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
359                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
360                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
361             }
362             pakInsertObjectParams.dwOffset = 0;
363             pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
364             pakInsertObjectParams.bLastHeader = false;
365             pakInsertObjectParams.bEndOfSlice = false;
366             pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
367             eStatus = (MOS_STATUS) m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr, &pakInsertObjectParams);
368             if (eStatus != MOS_STATUS_SUCCESS)
369             {
370                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
371                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
372                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
373                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
374             }
375             MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
376         }
377 
378         // Add Application data if it was sent by application
379         if (m_applicationData != nullptr)
380         {
381             uint8_t* appDataChunk = nullptr;
382             uint32_t appDataChunkSize = m_appDataSize;
383 
384             // We can write a maximum of 1020 words per command, so if the size of the app data is
385             // more than 1020 we need to send multiple commands for writing out app data
386             uint32_t numAppDataCmdsNeeded = 1;
387             uint32_t appDataCmdSizeResidue = 0;
388             if (m_appDataSize > 1020)
389             {
390                 numAppDataCmdsNeeded = m_appDataSize / 1020;
391                 appDataCmdSizeResidue = m_appDataSize % 1020;
392 
393                 appDataChunkSize = 1020;
394             }
395 
396             appDataChunk = (uint8_t*)MOS_AllocAndZeroMemory(appDataChunkSize);
397             if (appDataChunk == nullptr)
398             {
399                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
400                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
401                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
402                 CODECHAL_ENCODE_CHK_NULL_RETURN(nullptr);
403             }
404 
405             for (uint32_t i = 0; i < numAppDataCmdsNeeded; i++)
406             {
407                 uint8_t *copyAddress = (uint8_t*)(m_applicationData)+(i * appDataChunkSize);
408 
409                 MOS_SecureMemcpy(appDataChunk, appDataChunkSize,
410                     copyAddress, appDataChunkSize);
411 
412                 eStatus = (MOS_STATUS)PackApplicationData(pakInsertObjectParams.pBsBuffer, appDataChunk, appDataChunkSize);
413                 if (eStatus != MOS_STATUS_SUCCESS)
414                 {
415                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
416                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
417                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
418                     MOS_SafeFreeMemory(appDataChunk);
419                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
420                 }
421                 pakInsertObjectParams.dwOffset = 0;
422                 pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
423                 //if full header is included in application data, it will be the last header to insert and last chunk of it should be marked with EndOfSlice
424                 if ((appDataCmdSizeResidue == 0) && m_fullHeaderInAppData && (i == numAppDataCmdsNeeded - 1))
425                 {
426                     pakInsertObjectParams.bLastHeader = true;
427                     pakInsertObjectParams.bEndOfSlice = true;
428                 }
429                 else
430                 {
431                     pakInsertObjectParams.bLastHeader = false;
432                     pakInsertObjectParams.bEndOfSlice = false;
433                 }
434                 pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
435                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
436                     &pakInsertObjectParams);
437                 if (eStatus != MOS_STATUS_SUCCESS)
438                 {
439                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
440                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
441                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
442                     MOS_SafeFreeMemory(appDataChunk);
443                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
444                 }
445             }
446 
447             if (appDataCmdSizeResidue != 0)
448             {
449                 uint8_t* lastAddress = (uint8_t*)(m_applicationData)+(numAppDataCmdsNeeded * appDataChunkSize);
450                 appDataChunkSize = appDataCmdSizeResidue;
451 
452                 MOS_SecureMemcpy(appDataChunk, appDataChunkSize,
453                     lastAddress,
454                     appDataChunkSize);
455 
456                 eStatus = (MOS_STATUS)PackApplicationData(pakInsertObjectParams.pBsBuffer, appDataChunk, appDataCmdSizeResidue);
457                 if (eStatus != MOS_STATUS_SUCCESS)
458                 {
459                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
460                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
461                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
462                     MOS_SafeFreeMemory(appDataChunk);
463                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
464                 }
465                 pakInsertObjectParams.dwOffset = 0;
466                 pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
467                 if(m_fullHeaderInAppData)
468                 {
469                     pakInsertObjectParams.bLastHeader = true;
470                     pakInsertObjectParams.bEndOfSlice = true;
471                 }
472                 else
473                 {
474                     pakInsertObjectParams.bLastHeader = false;
475                     pakInsertObjectParams.bEndOfSlice = false;
476                 }
477                 pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
478                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
479                     &pakInsertObjectParams);
480                 if (eStatus != MOS_STATUS_SUCCESS)
481                 {
482                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
483                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
484                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
485                     MOS_SafeFreeMemory(appDataChunk);
486                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
487                 }
488             }
489 
490             MOS_FreeMemory(appDataChunk);
491         }
492 
493         if(!m_fullHeaderInAppData)
494         {
495         // Add Quant Table for Y
496         eStatus = (MOS_STATUS)PackQuantTable(pakInsertObjectParams.pBsBuffer, jpegComponentY);
497         if (eStatus != MOS_STATUS_SUCCESS)
498         {
499             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
500             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
501             MOS_SafeFreeMemory(tempJpegQuantMatrix);
502             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
503         }
504 
505         pakInsertObjectParams.dwOffset = 0;
506         pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
507         pakInsertObjectParams.bLastHeader = false;
508         pakInsertObjectParams.bEndOfSlice = false;
509         pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
510         eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
511             &pakInsertObjectParams);
512         if (eStatus != MOS_STATUS_SUCCESS)
513         {
514             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
515             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
516             MOS_SafeFreeMemory(tempJpegQuantMatrix);
517             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
518         }
519         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
520 
521         if (!useSingleDefaultQuantTable)
522         {
523             // Since there is no U and V in monochrome format, donot add Quantization table header for U and V components
524             if (m_jpegPicParams->m_inputSurfaceFormat != codechalJpegY8)
525             {
526                 // Add quant table for U
527                 eStatus = (MOS_STATUS)PackQuantTable(pakInsertObjectParams.pBsBuffer, jpegComponentU);
528                 if (eStatus != MOS_STATUS_SUCCESS)
529                 {
530                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
531                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
532                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
533                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
534                 }
535                 pakInsertObjectParams.dwOffset = 0;
536                 pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
537                 pakInsertObjectParams.bLastHeader = false;
538                 pakInsertObjectParams.bEndOfSlice = false;
539                 pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
540                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
541                     &pakInsertObjectParams);
542                 if (eStatus != MOS_STATUS_SUCCESS)
543                 {
544                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
545                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
546                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
547                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
548                 }
549                 MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
550 
551                 // Add quant table for V
552                 eStatus = (MOS_STATUS)PackQuantTable(pakInsertObjectParams.pBsBuffer, jpegComponentV);
553                 if (eStatus != MOS_STATUS_SUCCESS)
554                 {
555                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
556                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
557                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
558                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
559                 }
560                 pakInsertObjectParams.dwOffset = 0;
561                 pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
562                 pakInsertObjectParams.bLastHeader = false;
563                 pakInsertObjectParams.bEndOfSlice = false;
564                 pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
565                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
566                     &pakInsertObjectParams);
567                 if (eStatus != MOS_STATUS_SUCCESS)
568                 {
569                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
570                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
571                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
572                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
573                 }
574                 MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
575             }
576         }
577 
578         // Add Frame Header
579         eStatus = (MOS_STATUS)PackFrameHeader(pakInsertObjectParams.pBsBuffer, useSingleDefaultQuantTable);
580         if (eStatus != MOS_STATUS_SUCCESS)
581         {
582             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
583             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
584             MOS_SafeFreeMemory(tempJpegQuantMatrix);
585             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
586         }
587         pakInsertObjectParams.dwOffset = 0;
588         pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
589         pakInsertObjectParams.bLastHeader = false;
590         pakInsertObjectParams.bEndOfSlice = false;
591         pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
592         eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
593             &pakInsertObjectParams);
594         if (eStatus != MOS_STATUS_SUCCESS)
595         {
596             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
597             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
598             MOS_SafeFreeMemory(tempJpegQuantMatrix);
599             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
600         }
601         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
602 
603         // Add Huffman Table for Y - DC table, Y- AC table, U/V - DC table, U/V - AC table
604         for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers; i++)
605         {
606             eStatus = (MOS_STATUS)PackHuffmanTable(pakInsertObjectParams.pBsBuffer, i);
607             if (eStatus != MOS_STATUS_SUCCESS)
608             {
609                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
610                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
611                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
612                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
613             }
614             pakInsertObjectParams.dwOffset = 0;
615             pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
616             pakInsertObjectParams.bLastHeader = false;
617             pakInsertObjectParams.bEndOfSlice = false;
618             pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
619             eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
620                 &pakInsertObjectParams);
621             if (eStatus != MOS_STATUS_SUCCESS)
622             {
623                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
624                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
625                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
626                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
627             }
628             MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
629         }
630 
631         // Restart Interval - Add only if the restart interval is not zero
632         if (m_jpegScanParams->m_restartInterval != 0)
633         {
634             eStatus = (MOS_STATUS)PackRestartInterval(pakInsertObjectParams.pBsBuffer);
635             if (eStatus != MOS_STATUS_SUCCESS)
636             {
637                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
638                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
639                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
640                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
641             }
642             pakInsertObjectParams.dwOffset = 0;
643             pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
644             pakInsertObjectParams.bLastHeader = false;
645             pakInsertObjectParams.bEndOfSlice = false;
646             pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
647             eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
648                 &pakInsertObjectParams);
649             if (eStatus != MOS_STATUS_SUCCESS)
650             {
651                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
652                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
653                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
654                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
655             }
656             MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
657         }
658 
659         // Add scan header
660         eStatus = (MOS_STATUS)PackScanHeader(pakInsertObjectParams.pBsBuffer);
661         if (eStatus != MOS_STATUS_SUCCESS)
662         {
663             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
664             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
665             MOS_SafeFreeMemory(tempJpegQuantMatrix);
666             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
667         }
668         pakInsertObjectParams.dwOffset = 0;
669         pakInsertObjectParams.dwBitSize = pakInsertObjectParams.pBsBuffer->BufferSize;
670         pakInsertObjectParams.bLastHeader = true;
671         pakInsertObjectParams.bEndOfSlice = true;
672         pakInsertObjectParams.bResetBitstreamStartingPos = 1; // from discussion with HW Architect
673         eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
674             &pakInsertObjectParams);
675         if (eStatus != MOS_STATUS_SUCCESS)
676         {
677             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
678             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
679             MOS_SafeFreeMemory(tempJpegQuantMatrix);
680             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
681         }
682         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
683         }
684         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer);
685     }
686 
687     eStatus = ReadMfcStatus(&cmdBuffer);
688     if (eStatus != MOS_STATUS_SUCCESS)
689     {
690         MOS_SafeFreeMemory(tempJpegQuantMatrix);
691         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
692     }
693 
694     eStatus = EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES);
695     if (eStatus != MOS_STATUS_SUCCESS)
696     {
697         MOS_SafeFreeMemory(tempJpegQuantMatrix);
698         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
699     }
700 
701     eStatus = m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr);
702     if (eStatus != MOS_STATUS_SUCCESS)
703     {
704         MOS_SafeFreeMemory(tempJpegQuantMatrix);
705         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
706     }
707 
708     std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_currPass));
709     CODECHAL_DEBUG_TOOL(
710         eStatus = m_debugInterface->DumpCmdBuffer(
711             &cmdBuffer,
712             CODECHAL_NUM_MEDIA_STATES,
713             pakPassName.data());
714         if (eStatus != MOS_STATUS_SUCCESS)
715         {
716             MOS_SafeFreeMemory(tempJpegQuantMatrix);
717             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
718         }
719 
720     //CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
721     //    m_debugInterface,
722     //    &cmdBuffer));
723     )
724 
725         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
726 
727     eStatus = SetAndPopulateVEHintParams(&cmdBuffer);
728     if (eStatus != MOS_STATUS_SUCCESS)
729     {
730         MOS_SafeFreeMemory(tempJpegQuantMatrix);
731         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
732     }
733     eStatus = m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw);
734     if (eStatus != MOS_STATUS_SUCCESS)
735     {
736         MOS_SafeFreeMemory(tempJpegQuantMatrix);
737         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
738     }
739 
740     if (tempJpegQuantMatrix != nullptr)
741     {
742         MOS_FreeMemory(tempJpegQuantMatrix);
743         tempJpegQuantMatrix = nullptr;
744     }
745 
746     return eStatus;
747 }
748 
Initialize(CodechalSetting * settings)749 MOS_STATUS CodechalEncodeJpegStateG11::Initialize(CodechalSetting  *settings)
750 {
751     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
752 
753     CODECHAL_ENCODE_FUNCTION_ENTER;
754 
755     CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
756     CODECHAL_ENCODE_CHK_NULL_RETURN(m_miInterface);
757     CODECHAL_ENCODE_CHK_NULL_RETURN(settings);
758 
759     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::Initialize(settings));
760 
761     // Picture Level Commands
762     CODECHAL_ENCODE_CHK_STATUS_RETURN(
763         m_hwInterface->GetMfxStateCommandsDataSize(
764             CODECHAL_ENCODE_MODE_JPEG,
765             &m_pictureStatesSize,
766             &m_picturePatchListSize,
767             0));
768 
769     // Slice Level Commands (cannot be placed in 2nd level batch)
770     CODECHAL_ENCODE_CHK_STATUS_RETURN(
771         m_hwInterface->GetMfxPrimitiveCommandsDataSize(
772             CODECHAL_ENCODE_MODE_JPEG,
773             &m_sliceStatesSize,
774             &m_slicePatchListSize,
775             0));
776 
777     if (MOS_VE_SUPPORTED(m_osInterface))
778     {
779         m_sinlgePipeVeState = (PCODECHAL_ENCODE_SINGLEPIPE_VIRTUALENGINE_STATE)MOS_AllocAndZeroMemory(sizeof(CODECHAL_ENCODE_SINGLEPIPE_VIRTUALENGINE_STATE));
780         CODECHAL_ENCODE_CHK_NULL_RETURN(m_sinlgePipeVeState);
781         eStatus = (MOS_STATUS) CodecHalEncodeSinglePipeVE_InitInterface(m_hwInterface, m_sinlgePipeVeState);
782         if (eStatus != MOS_STATUS_SUCCESS)
783         {
784             MOS_SafeFreeMemory(m_sinlgePipeVeState);
785             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
786         }
787     }
788 
789     return eStatus;
790 }
791 
SetGpuCtxCreatOption()792 MOS_STATUS CodechalEncodeJpegStateG11::SetGpuCtxCreatOption()
793 {
794     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
795 
796     CODECHAL_ENCODE_FUNCTION_ENTER;
797 
798     if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
799     {
800         CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::SetGpuCtxCreatOption());
801     }
802     else
803     {
804         m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
805         CODECHAL_ENCODE_CHK_NULL_RETURN(m_gpuCtxCreatOpt);
806 
807         CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_ConstructParmsForGpuCtxCreation(
808             m_sinlgePipeVeState,
809             (PMOS_GPUCTX_CREATOPTIONS_ENHANCED)m_gpuCtxCreatOpt));
810     }
811 
812     return eStatus;
813 }
814 
815