1 /*
2 * Copyright (c) 2017-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.cpp
24 //! \brief    Defines state class for JPEG encoder.
25 //!
26 
27 #include "codechal_encode_jpeg.h"
28 #if USE_CODECHAL_DEBUG_TOOL
29 #include "codechal_debug.h"
30 #endif
31 
Initialize(CodechalSetting * settings)32 MOS_STATUS CodechalEncodeJpegState::Initialize(CodechalSetting  *settings)
33 {
34     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
35 
36     CODECHAL_ENCODE_FUNCTION_ENTER;
37 
38     CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
39     CODECHAL_ENCODE_CHK_NULL_RETURN(m_miInterface);
40     CODECHAL_ENCODE_CHK_NULL_RETURN(settings);
41 
42     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::Initialize(settings));
43 
44     // Picture Level Commands
45     CODECHAL_ENCODE_CHK_STATUS_RETURN(
46         m_hwInterface->GetMfxStateCommandsDataSize(
47             CODECHAL_ENCODE_MODE_JPEG,
48             &m_pictureStatesSize,
49             &m_picturePatchListSize,
50             0));
51 
52     // Slice Level Commands (cannot be placed in 2nd level batch)
53     CODECHAL_ENCODE_CHK_STATUS_RETURN(
54         m_hwInterface->GetMfxPrimitiveCommandsDataSize(
55             CODECHAL_ENCODE_MODE_JPEG,
56             &m_sliceStatesSize,
57             &m_slicePatchListSize,
58             0));
59 
60     return eStatus;
61 }
62 
AllocateResources()63 MOS_STATUS CodechalEncodeJpegState::AllocateResources()
64 {
65     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
66 
67     CODECHAL_ENCODE_FUNCTION_ENTER;
68 
69     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::AllocateResources());
70 
71     // Allocate Ref Lists
72     CodecHalAllocateDataList(
73         m_refList,
74         CODECHAL_NUM_UNCOMPRESSED_SURFACE_JPEG);
75 
76     return eStatus;
77 }
78 
FreeResources()79 void CodechalEncodeJpegState::FreeResources()
80 {
81     CODECHAL_ENCODE_FUNCTION_ENTER;
82 
83     CodechalEncoderState::FreeResources();
84 
85     // Release Ref Lists
86     CodecHalFreeDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_JPEG);
87 }
88 
InitializePicture(const EncoderParams & params)89 MOS_STATUS CodechalEncodeJpegState::InitializePicture(const EncoderParams& params)
90 {
91     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
92 
93     CODECHAL_ENCODE_FUNCTION_ENTER;
94 
95     m_bitstreamUpperBound = params.dwBitstreamSize;
96 
97     m_jpegPicParams         = (CodecEncodeJpegPictureParams *)(params.pPicParams);
98     m_jpegScanParams        = (CodecEncodeJpegScanHeader *)(params.pSliceParams);
99     m_jpegQuantTables       = (CodecEncodeJpegQuantTable *)(params.pQuantizationTable);
100     m_jpegHuffmanTable      = (CodecEncodeJpegHuffmanDataArray *)(params.pHuffmanTable);
101     m_applicationData       = params.pApplicationData;
102     m_appDataSize           = params.dwAppDataSize;
103     m_jpegQuantMatrixSent   = params.bJpegQuantMatrixSent;
104     m_fullHeaderInAppData   = params.fullHeaderInAppData;
105 
106     CODECHAL_ENCODE_CHK_NULL_RETURN(m_jpegPicParams);
107     CODECHAL_ENCODE_CHK_NULL_RETURN(m_jpegScanParams);
108     CODECHAL_ENCODE_CHK_NULL_RETURN(m_jpegQuantTables);
109     CODECHAL_ENCODE_CHK_NULL_RETURN(m_jpegHuffmanTable);
110 
111     // Set Status Report Feedback Number
112     m_statusReportFeedbackNumber = m_jpegPicParams->m_statusReportFeedbackNumber;
113     m_currRefList                = m_refList[m_currOriginalPic.FrameIdx];
114 
115     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetStatusReportParams(m_refList[m_currOriginalPic.FrameIdx]));
116 
117     m_currRefList->resBitstreamBuffer = m_resBitstreamBuffer;
118     m_currRefList->sRefRawBuffer      = m_rawSurface;
119 
120     CODECHAL_DEBUG_TOOL(
121         CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface);
122 
123          if (m_jpegPicParams)
124         {
125             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpPicParams(
126                 m_jpegPicParams));
127         }
128 
129         if (m_jpegScanParams)
130         {
131             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpScanParams(
132                 m_jpegScanParams));
133         }
134 
135         if (m_jpegHuffmanTable)
136         {
137             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpHuffmanTable(
138                 m_jpegHuffmanTable));
139         }
140 
141         if (m_jpegQuantTables)
142         {
143             CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpQuantTables(
144                 m_jpegQuantTables));
145         }
146     )
147 
148     return eStatus;
149 }
150 
CheckResChangeAndCsc()151 MOS_STATUS CodechalEncodeJpegState::CheckResChangeAndCsc()
152 {
153     return MOS_STATUS_SUCCESS;
154 }
155 
156 // Implemented based on table K.5 in JPEG spec
MapHuffValIndex(uint8_t huffValIndex)157 uint8_t CodechalEncodeJpegState::MapHuffValIndex(uint8_t huffValIndex)
158 {
159     CODECHAL_ENCODE_FUNCTION_ENTER;
160 
161     uint8_t mappedIndex = 0;
162 
163     if (huffValIndex < 0xF0)
164     {
165         mappedIndex = (((huffValIndex >> 4) & 0x0F) * 0xA) + (huffValIndex & 0x0F);
166     }
167     else
168     {
169         mappedIndex = (((huffValIndex >> 4) & 0x0F) * 0xA) + (huffValIndex & 0x0F) + 1;
170     }
171 
172     return mappedIndex;
173 }
174 
175 // Implemented based on Flowchart in figure C.1 in JPEG spec
GenerateSizeTable(uint8_t bits[],uint8_t huffSize[],uint8_t & lastK)176 MOS_STATUS CodechalEncodeJpegState::GenerateSizeTable(
177     uint8_t     bits[],
178     uint8_t     huffSize[],
179     uint8_t&    lastK)
180 {
181     CODECHAL_ENCODE_FUNCTION_ENTER;
182 
183     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
184 
185     uint8_t i = 1, j = 1;
186     uint8_t k = 0;
187     while (i <= 16)
188     {
189         while (j <= (int8_t)bits[i - 1]) // bits index is from 0 to 15
190         {
191             huffSize[k] = i;
192             k = k + 1;
193             j = j + 1;
194         }
195 
196         i++;
197         j = 1;
198     };
199 
200     huffSize[k] = 0;
201     lastK = k;
202 
203     return eStatus;
204 }
205 
206 // Implemented based on Flowchart in figure C.2 in JPEG spec
GenerateCodeTable(uint8_t huffSize[],uint16_t huffCode[])207 MOS_STATUS CodechalEncodeJpegState::GenerateCodeTable(
208     uint8_t     huffSize[],
209     uint16_t    huffCode[])
210 {
211     CODECHAL_ENCODE_FUNCTION_ENTER;
212 
213     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
214 
215     uint8_t    k = 0;
216     uint8_t    si = huffSize[0];
217     uint16_t   code = 0;
218     while (huffSize[k] != 0)
219     {
220         while (huffSize[k] == si)
221         {
222             if (code == 0xFFFF)
223             {
224                 // Invalid code generated - replace with all zeroes
225                 code = 0x0000;
226             }
227 
228             huffCode[k] = code;
229             code = code + 1;
230             k = k + 1;
231         };
232 
233         code <<= 1;
234         si = si + 1;
235     }
236 
237     return eStatus;
238 }
239 
240 // Implemented based on Flowchart in figure C.3 in JPEG spec
OrderCodes(uint8_t huffVal[],uint8_t huffSize[],uint16_t huffCode[],uint8_t lastK)241 MOS_STATUS CodechalEncodeJpegState::OrderCodes(
242     uint8_t     huffVal[],
243     uint8_t     huffSize[],
244     uint16_t    huffCode[],
245     uint8_t     lastK)
246 {
247     CODECHAL_ENCODE_FUNCTION_ENTER;
248 
249     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
250 
251     uint16_t eHuffCo[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL];
252     uint8_t  eHuffSi[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL];
253     MOS_ZeroMemory(&eHuffCo[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t));
254     MOS_ZeroMemory(&eHuffSi[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t));
255 
256     uint8_t k = 0;
257     do
258     {
259         uint8_t i = MapHuffValIndex((uint8_t)huffVal[k]);
260         if (i >= JPEG_NUM_HUFF_TABLE_AC_HUFFVAL)
261         {
262             CODECHAL_ENCODE_ASSERT(false);
263             return MOS_STATUS_UNKNOWN;
264         }
265         eHuffCo[i] = huffCode[k];
266         eHuffSi[i] = huffSize[k];
267         k++;
268     } while (k < lastK);
269 
270     // copy over the first 162 values of reordered arrays to Huffman Code and size arrays
271     CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(&huffCode[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t), &eHuffCo[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t)));
272     CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(&huffSize[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t), &eHuffSi[0], JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t)));
273 
274     return eStatus;
275 }
276 
ConvertHuffDataToTable(CodecEncodeJpegHuffData huffmanData,CodechalEncodeJpegHuffTable * huffmanTable)277 MOS_STATUS CodechalEncodeJpegState::ConvertHuffDataToTable(
278     CodecEncodeJpegHuffData             huffmanData,
279     CodechalEncodeJpegHuffTable         *huffmanTable)
280 {
281     CODECHAL_ENCODE_FUNCTION_ENTER;
282 
283     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
284 
285     huffmanTable->m_tableClass = huffmanData.m_tableClass;
286     huffmanTable->m_tableID    = huffmanData.m_tableID;
287 
288     uint8_t lastK = 0;
289 
290     // Step 1 : Generate size table
291     CODECHAL_ENCODE_CHK_STATUS_RETURN(GenerateSizeTable(huffmanData.m_bits, huffmanTable->m_huffSize, lastK));
292 
293     // Step2: Generate code table
294     CODECHAL_ENCODE_CHK_STATUS_RETURN(GenerateCodeTable(huffmanTable->m_huffSize, huffmanTable->m_huffCode));
295 
296     // Step 3: Order codes
297     CODECHAL_ENCODE_CHK_STATUS_RETURN(OrderCodes(huffmanData.m_huffVal, huffmanTable->m_huffSize, huffmanTable->m_huffCode, lastK));
298 
299     return eStatus;
300 }
301 
PackSOI(BSBuffer * buffer)302 MOS_STATUS CodechalEncodeJpegState::PackSOI(BSBuffer *buffer)
303 {
304     CODECHAL_ENCODE_FUNCTION_ENTER;
305 
306     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
307 
308     CODECHAL_ENCODE_CHK_NULL_RETURN(buffer);
309     // Add SOI = 0xFFD8
310     buffer->pBase = (uint8_t*)MOS_AllocAndZeroMemory(2);
311     CODECHAL_ENCODE_CHK_NULL_RETURN(buffer->pBase);
312 
313     *(buffer->pBase)     = (m_jpegEncodeSoi >> 8) & 0xFF;
314     *(buffer->pBase + 1) = (m_jpegEncodeSoi & 0xFF);
315     buffer->BitOffset    = 0;
316     buffer->BufferSize   = 16;
317 
318     return eStatus;
319 }
320 
PackApplicationData(BSBuffer * buffer,uint8_t * appDataChunk,uint32_t size)321 MOS_STATUS CodechalEncodeJpegState::PackApplicationData(
322     BSBuffer                        *buffer,
323     uint8_t                         *appDataChunk,
324     uint32_t                           size)
325 {
326     CODECHAL_ENCODE_FUNCTION_ENTER;
327 
328     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
329 
330     CODECHAL_ENCODE_CHK_NULL_RETURN(appDataChunk);
331 
332     buffer->pBase        = appDataChunk;
333     buffer->BitOffset    = 0;
334     buffer->BufferSize   = (size * sizeof(uint8_t) * 8);
335 
336     return eStatus;
337 }
338 
PackFrameHeader(BSBuffer * buffer,bool useSingleDefaultQuantTable)339 MOS_STATUS CodechalEncodeJpegState::PackFrameHeader(
340     BSBuffer                        *buffer,
341     bool                            useSingleDefaultQuantTable)
342 {
343     CODECHAL_ENCODE_FUNCTION_ENTER;
344 
345     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
346 
347     CodechalEncodeJpegFrameHeader *frameHeader = (CodechalEncodeJpegFrameHeader *)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeJpegFrameHeader));
348     CODECHAL_ENCODE_CHK_NULL_RETURN(frameHeader);
349 
350     frameHeader->m_sof   = 0xC0FF;
351     frameHeader->m_nf    = (uint8_t)m_jpegPicParams->m_numComponent;
352 
353     // Calculate lf - switch btes to match with simulation
354     uint16_t value = 8 + (3 * frameHeader->m_nf); // does not include sof
355     frameHeader->m_lf    = ((value & 0xFF) << 8) | ((value & 0xFF00) >> 8);
356 
357     frameHeader->m_p     = 8;
358     frameHeader->m_y     = ((m_jpegPicParams->m_picHeight & 0xFF) << 8) | ((m_jpegPicParams->m_picHeight & 0xFF00) >> 8);
359     frameHeader->m_x     = ((m_jpegPicParams->m_picWidth & 0xFF) << 8) | ((m_jpegPicParams->m_picWidth & 0xFF00) >> 8);
360 
361     for (uint8_t i = 0; i < frameHeader->m_nf; i++)
362     {
363         frameHeader->m_codechalJpegFrameComponent[i].m_ci = (uint8_t)m_jpegPicParams->m_componentID[i];
364 
365         if (useSingleDefaultQuantTable)
366         {
367             frameHeader->m_codechalJpegFrameComponent[i].m_tqi = 0; // 0/1/2 based on Y/U/V
368         }
369         else
370         {
371             frameHeader->m_codechalJpegFrameComponent[i].m_tqi = i; // 0/1/2 based on Y/U/V
372         }
373 
374         // For all supported formats on JPEG encode, U and V vertical and horizontal sampling is 1
375         uint32_t horizontalSamplingFactor = 0, verticalSamplingFactor = 0;
376         if (i == 0)
377         {
378             horizontalSamplingFactor    = m_mfxInterface->GetJpegHorizontalSamplingFactorForY((CodecEncodeJpegInputSurfaceFormat)m_jpegPicParams->m_inputSurfaceFormat);
379             verticalSamplingFactor      = m_mfxInterface->GetJpegVerticalSamplingFactorForY((CodecEncodeJpegInputSurfaceFormat)m_jpegPicParams->m_inputSurfaceFormat);
380         }
381         else
382         {
383             horizontalSamplingFactor    = 1;
384             verticalSamplingFactor      = 1;
385         }
386 
387         frameHeader->m_codechalJpegFrameComponent[i].m_samplingFactori = 0;
388         frameHeader->m_codechalJpegFrameComponent[i].m_samplingFactori = ((horizontalSamplingFactor & 0xF) << 4) | (verticalSamplingFactor & 0xF);
389     }
390 
391     buffer->pBase        = (uint8_t*)frameHeader;
392     buffer->BitOffset    = 0;
393     buffer->BufferSize   = (2 * sizeof(uint8_t) * 8) + (4 * sizeof(uint16_t) * 8) + (sizeof(frameHeader->m_codechalJpegFrameComponent[0]) * 8 * m_jpegPicParams->m_numComponent);
394 
395     return eStatus;
396 }
397 
PackHuffmanTable(BSBuffer * buffer,uint32_t tableIndex)398 MOS_STATUS CodechalEncodeJpegState::PackHuffmanTable(
399     BSBuffer                        *buffer,
400     uint32_t                        tableIndex)
401 {
402     CODECHAL_ENCODE_FUNCTION_ENTER;
403 
404     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
405 
406     CodechalJpegHuffmanHeader *huffmanHeader = (CodechalJpegHuffmanHeader *)MOS_AllocAndZeroMemory(sizeof(CodechalJpegHuffmanHeader));
407     CODECHAL_ENCODE_CHK_NULL_RETURN(huffmanHeader);
408 
409     huffmanHeader->m_dht = 0xC4FF;
410     huffmanHeader->m_tableClassAndDestn =
411         ((m_jpegHuffmanTable->m_huffmanData[tableIndex].m_tableClass & 0xF) << 4) | ((tableIndex / 2) & 0xF);
412 
413     uint16_t totalHuffValues = 0;
414     for (auto i = 0; i < JPEG_NUM_HUFF_TABLE_AC_BITS; i++)
415     {
416         huffmanHeader->m_li[i] = (uint8_t)m_jpegHuffmanTable->m_huffmanData[tableIndex].m_bits[i];
417         totalHuffValues += huffmanHeader->m_li[i];
418     }
419 
420     uint16_t hdrSize = 19 + totalHuffValues;
421     huffmanHeader->m_lh = ((hdrSize & 0xFF) << 8) | ((hdrSize & 0xFF00) >> 8);
422 
423     for (auto i = 0; i < totalHuffValues; i++)
424     {
425         huffmanHeader->m_vij[i] = (uint8_t)m_jpegHuffmanTable->m_huffmanData[tableIndex].m_huffVal[i];
426     }
427 
428     buffer->pBase = (uint8_t*)huffmanHeader;
429     buffer->BitOffset = 0;
430     buffer->BufferSize = (2 * sizeof(uint16_t) * 8) + (sizeof(uint8_t) * 8) + (JPEG_NUM_HUFF_TABLE_AC_BITS * 8) + (totalHuffValues * sizeof(uint8_t) * 8);
431 
432     return eStatus;
433 }
434 
PackQuantTable(BSBuffer * buffer,CodecJpegComponents componentType)435 MOS_STATUS CodechalEncodeJpegState::PackQuantTable(
436     BSBuffer                        *buffer,
437     CodecJpegComponents             componentType)
438 {
439     CODECHAL_ENCODE_FUNCTION_ENTER;
440 
441     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
442 
443     CodechalEncodeJpegQuantHeader *quantHeader = (CodechalEncodeJpegQuantHeader *)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeJpegQuantHeader));
444     CODECHAL_ENCODE_CHK_NULL_RETURN(quantHeader);
445 
446     quantHeader->m_dqt = 0xDBFF;
447     // Header size including marker
448     uint16_t hdrSize = sizeof(uint16_t) * 2 + sizeof(uint8_t) + sizeof(uint8_t) * JPEG_NUM_QUANTMATRIX;
449     quantHeader->m_lq = (((hdrSize - 2) & 0xFF) << 8) | (((hdrSize - 2) & 0xFF00) >> 8);
450     quantHeader->m_tablePrecisionAndDestination
451         = ((m_jpegQuantTables->m_quantTable[componentType].m_precision & 0xF) << 4)
452         | (componentType & 0xF);
453 
454     for (auto i = 0; i < JPEG_NUM_QUANTMATRIX; i++)
455     {
456         quantHeader->m_qk[i] = (uint8_t)m_jpegQuantTables->m_quantTable[componentType].m_qm[i];
457     }
458 
459     buffer->pBase        = (uint8_t*)quantHeader;
460     buffer->BitOffset    = 0;
461     buffer->BufferSize   = hdrSize * 8;
462 
463     return eStatus;
464 }
465 
PackRestartInterval(BSBuffer * buffer)466 MOS_STATUS CodechalEncodeJpegState::PackRestartInterval(
467     BSBuffer                        *buffer)
468 {
469     CODECHAL_ENCODE_FUNCTION_ENTER;
470 
471     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
472 
473     CodechalEncodeJpegRestartHeader *restartHeader = (CodechalEncodeJpegRestartHeader *)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeJpegRestartHeader));
474     CODECHAL_ENCODE_CHK_NULL_RETURN(restartHeader);
475 
476     restartHeader->m_dri = 0xDDFF;
477     uint16_t hdrSize  = sizeof(uint16_t) * 3;
478     restartHeader->m_lr  = (((hdrSize - 2) & 0xFF) << 8) | (((hdrSize - 2) & 0xFF00) >> 8);
479     restartHeader->m_ri  = (uint16_t)(((m_jpegScanParams->m_restartInterval & 0xFF) << 8) |
480         ((m_jpegScanParams->m_restartInterval & 0xFF00) >> 8));
481 
482     buffer->pBase        = (uint8_t*)restartHeader;
483     buffer->BitOffset    = 0;
484     buffer->BufferSize   = hdrSize * 8;
485 
486     return eStatus;
487 }
488 
PackScanHeader(BSBuffer * buffer)489 MOS_STATUS CodechalEncodeJpegState::PackScanHeader(
490     BSBuffer                        *buffer)
491 {
492     CODECHAL_ENCODE_FUNCTION_ENTER;
493 
494     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
495 
496     // Size of Scan header in bytes = sos (2 bytes) + ls (2 bytes) + ns (1 byte)
497     // + ss (1 byte) + se (1 byte) + ahl (1 byte) + scanComponent (2 bytes) * Number of scan components
498     uint16_t hdrSize = 8 + 2 * m_jpegPicParams->m_numComponent;
499 
500     uint8_t *scanHeader = (uint8_t*)MOS_AllocAndZeroMemory(hdrSize);
501     CODECHAL_ENCODE_CHK_NULL_RETURN(scanHeader);
502 
503     buffer->pBase = (uint8_t*)scanHeader;
504 
505     // scanHeader->sos
506     *scanHeader = (m_jpegEncodeSos >> 8) & 0xFF;
507     scanHeader += 1;
508     *scanHeader = (m_jpegEncodeSos & 0xFF);
509     scanHeader += 1;
510 
511     // scanHeader->ls
512     *scanHeader = ((hdrSize - 2) >> 8) & 0xFF;
513     scanHeader += 1;
514     *scanHeader = (hdrSize - 2) & 0xFF;
515     scanHeader += 1;
516 
517     // scanHeader->ns
518     *scanHeader = (uint8_t)m_jpegPicParams->m_numComponent;
519     scanHeader += 1;
520 
521     for (uint32_t j = 0; j < m_jpegPicParams->m_numComponent; j++)
522     {
523         *scanHeader = (uint8_t)m_jpegPicParams->m_componentID[j];
524         scanHeader += 1;
525 
526         // For Y8 image format there is only one scan component, so scanComponent[1] and scanComponent[2] should not be added to the header
527         // scanHeader->scanComponent[j].Tdaj
528         if (j == 0)
529         {
530             *scanHeader = (uint8_t)(((m_jpegHuffmanTable->m_huffmanData[0].m_tableID & 0x0F) << 4)
531                 | ((m_jpegHuffmanTable->m_huffmanData[1].m_tableID & 0x0F)));
532             scanHeader += 1;
533         }
534         else
535         {
536             *scanHeader = (uint8_t)(((m_jpegHuffmanTable->m_huffmanData[2].m_tableID & 0x0F) << 4)
537                 | ((m_jpegHuffmanTable->m_huffmanData[3].m_tableID & 0x0F)));
538             scanHeader += 1;
539         }
540 
541     }
542 
543     // scanHeader->ss
544     *scanHeader = 0;
545     scanHeader += 1;
546     // scanHeader->se
547     *scanHeader = 63;
548     scanHeader += 1;
549     // scanHeader->ahl
550     *scanHeader = 0;
551     scanHeader += 1;
552 
553     buffer->BitOffset = 0;
554     // Buffer size in bits
555     buffer->BufferSize = hdrSize * 8;
556 
557     return eStatus;
558 }
559 
ExecutePictureLevel()560 MOS_STATUS CodechalEncodeJpegState::ExecutePictureLevel()
561 {
562     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
563 
564     CODECHAL_ENCODE_FUNCTION_ENTER;
565 
566     PerfTagSetting perfTag;
567     CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE);
568 
569     MOS_COMMAND_BUFFER cmdBuffer;
570     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
571 
572     m_mode = CODECHAL_ENCODE_MODE_JPEG;
573 
574     // set MFX_PIPE_MODE_SELECT
575     MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
576     pipeModeSelectParams.Mode                   = m_mode;
577     pipeModeSelectParams.bStreamOutEnabled      = false;
578     pipeModeSelectParams.bShortFormatInUse      = false;
579     pipeModeSelectParams.bPreDeblockOutEnable   = false;
580     pipeModeSelectParams.bPostDeblockOutEnable  = false;
581 
582     // set MFX_SURFACE_STATE
583     MHW_VDBOX_SURFACE_PARAMS surfaceParams;
584     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
585     surfaceParams.Mode      = m_mode;
586     surfaceParams.psSurface = &m_rawSurface; // original picture to be encoded
587     surfaceParams.ucSurfaceStateId = CODECHAL_MFX_SRC_SURFACE_ID;
588 
589     // set MFX_PIPE_BUF_ADDR_STATE
590     MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams;
591     pipeBufAddrParams.Mode          = m_mode;
592     pipeBufAddrParams.psRawSurface  = &m_rawSurface; // original picture to be encoded
593     pipeBufAddrParams.pRawSurfParam = &surfaceParams;
594 
595     CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
596     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetPipeBufAddr(&pipeBufAddrParams, &cmdBuffer));
597 
598     CODECHAL_DEBUG_TOOL(
599         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
600             &m_rawSurface,
601             CodechalDbgAttr::attrEncodeRawInputSurface,
602             "SrcSurf"))
603     );
604 
605     // No references for JPEG
606     // Setting invalid entries to nullptr
607     for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
608     {
609         pipeBufAddrParams.presReferences[i] = nullptr;
610     }
611 
612     // set MFX_IND_OBJ_BASE_ADDR_STATE
613     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
614     MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
615     indObjBaseAddrParams.Mode                       = m_mode;
616     indObjBaseAddrParams.presPakBaseObjectBuffer    = &m_resBitstreamBuffer;
617     indObjBaseAddrParams.dwPakBaseObjectSize        = m_bitstreamUpperBound;
618 
619     // set MFX_JPEG_PIC_STATE
620     MhwVdboxJpegEncodePicState jpegPicState;
621     MOS_ZeroMemory(&jpegPicState, sizeof(jpegPicState));
622     jpegPicState.pJpegEncodePicParams   = m_jpegPicParams;
623     jpegPicState.mode                   = m_mode;
624 
625     // Send command buffer header at the beginning (OS dependent)
626     CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, true));
627 
628     CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));
629 
630     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));
631 
632     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams));
633 
634     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams));
635 
636     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));
637 
638     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxJpegEncodePicStateCmd(&cmdBuffer, &jpegPicState));
639 
640     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
641 
642     return eStatus;
643 }
644 
ExecuteSliceLevel()645 MOS_STATUS CodechalEncodeJpegState::ExecuteSliceLevel()
646 {
647     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
648 
649     CODECHAL_ENCODE_FUNCTION_ENTER;
650 
651     MOS_COMMAND_BUFFER cmdBuffer;
652     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
653 
654     if (m_encodeParams.dwNumSlices != 1)
655     {
656         CODECHAL_ENCODE_ASSERTMESSAGE("JPEG encode only one scan is supported.");
657     }
658 
659     MOS_SURFACE *surface = &m_rawSurface;
660 
661     bool useSingleDefaultQuantTable = (m_jpegQuantMatrixSent == false &&
662                                        ((surface->Format == Format_A8R8G8B8) ||
663                                         (surface->Format == Format_X8R8G8B8) ||
664                                         (surface->Format == Format_A8B8G8R8) ||
665                                         (surface->Format == Format_X8B8G8R8)));
666 
667     CodecJpegQuantMatrix *tempJpegQuantMatrix = (CodecJpegQuantMatrix *)MOS_AllocAndZeroMemory(sizeof(CodecJpegQuantMatrix));
668     CODECHAL_ENCODE_CHK_NULL_RETURN(tempJpegQuantMatrix);
669 
670     static_assert(JPEG_MAX_NUM_QUANT_TABLE_INDEX <= JPEG_MAX_NUM_OF_QUANTMATRIX,
671         "access to CodecJpegQuantMatrix is controlled by numQuantTables");
672 
673     uint32_t numQuantTables = JPEG_MAX_NUM_QUANT_TABLE_INDEX;
674     for (uint32_t scanCount = 0; scanCount < m_encodeParams.dwNumSlices; scanCount++)
675     {
676         MHW_VDBOX_QM_PARAMS fqmParams;
677         MOS_ZeroMemory(&fqmParams, sizeof(fqmParams));
678 
679         // set MFX_FQM_STATE
680         fqmParams.pJpegQuantMatrix = tempJpegQuantMatrix;
681 
682         // For monochrome inputs there will be only 1 quantization table and huffman table sent
683         if (m_jpegPicParams->m_inputSurfaceFormat == codechalJpegY8)
684         {
685             numQuantTables = 1;
686             m_encodeParams.dwNumHuffBuffers = 2; //for Y8 only 2 huff tables
687         }
688         // If there is only 1 quantization table copy over the table to 2nd and 3rd table in JPEG state (used for frame header)
689         // OR For RGB input surfaces, if the app does not send quantization tables, then use luma quant table for all 3 components
690         else if (m_jpegPicParams->m_numQuantTable == 1 || useSingleDefaultQuantTable)
691         {
692             for (auto i = 1; i < JPEG_MAX_NUM_QUANT_TABLE_INDEX; i++)
693             {
694                 m_jpegQuantTables->m_quantTable[i].m_precision = m_jpegQuantTables->m_quantTable[0].m_precision;
695                 m_jpegQuantTables->m_quantTable[i].m_tableID = m_jpegQuantTables->m_quantTable[0].m_tableID;
696 
697                 eStatus = MOS_SecureMemcpy(&m_jpegQuantTables->m_quantTable[i].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t),
698                     &m_jpegQuantTables->m_quantTable[0].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t));
699                 if (eStatus != MOS_STATUS_SUCCESS)
700                 {
701                     CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
702                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
703                     return eStatus;
704                 }
705             }
706         }
707         // 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)
708         else if (m_jpegPicParams->m_numQuantTable == 2)
709         {
710             m_jpegQuantTables->m_quantTable[2].m_precision    = m_jpegQuantTables->m_quantTable[1].m_precision;
711             m_jpegQuantTables->m_quantTable[2].m_tableID      = m_jpegQuantTables->m_quantTable[1].m_tableID;
712 
713             eStatus = MOS_SecureMemcpy(&m_jpegQuantTables->m_quantTable[2].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t),
714                 &m_jpegQuantTables->m_quantTable[1].m_qm[0], JPEG_NUM_QUANTMATRIX * sizeof(uint16_t));
715             if (eStatus != MOS_STATUS_SUCCESS)
716             {
717                 CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
718                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
719                 return eStatus;
720             }
721 
722         }
723         // else 3 quantization tables are sent by the application for non monochrome input formats. In that case, do nothing.
724 
725         for (uint32_t i = 0; i < numQuantTables; i++)
726         {
727             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
728 
729             for (auto j = 0; j < JPEG_NUM_QUANTMATRIX; j++)
730             {
731                 uint32_t k = jpeg_qm_scan_8x8[j];
732 
733                 // copy over Quant matrix in raster order from zig zag
734                 fqmParams.pJpegQuantMatrix->m_quantMatrix[i][k] = (uint8_t)m_jpegQuantTables->m_quantTable[i].m_qm[j];
735             }
736         }
737 
738         eStatus = (MOS_STATUS) m_mfxInterface->AddMfxJpegFqmCmd(&cmdBuffer, &fqmParams, numQuantTables);
739         if (eStatus != MOS_STATUS_SUCCESS)
740         {
741             MOS_SafeFreeMemory(tempJpegQuantMatrix);
742             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
743         }
744 
745         // set MFC_JPEG_HUFF_TABLE - Convert encoded huffman table to actual table for HW
746         // We need a different params struct for JPEG Encode Huffman table because JPEG decode huffman table has Bits and codes,
747         // whereas JPEG encode huffman table has huffman code lengths and values
748         MHW_VDBOX_ENCODE_HUFF_TABLE_PARAMS huffTableParams[JPEG_MAX_NUM_HUFF_TABLE_INDEX] = {};
749         for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers; i++)
750         {
751             CodechalEncodeJpegHuffTable huffmanTable;// intermediate table for each AC/DC component which will be copied to huffTableParams
752             MOS_ZeroMemory(&huffmanTable, sizeof(huffmanTable));
753 
754             eStatus = (MOS_STATUS) ConvertHuffDataToTable(m_jpegHuffmanTable->m_huffmanData[i], &huffmanTable);
755             if (eStatus != MOS_STATUS_SUCCESS)
756             {
757                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
758                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
759             }
760 
761             huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].HuffTableID = m_jpegHuffmanTable->m_huffmanData[i].m_tableID;
762 
763             if (m_jpegHuffmanTable->m_huffmanData[i].m_tableClass == 0) // DC table
764             {
765                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(
766                     huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pDCCodeValues,
767                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint16_t),
768                     &huffmanTable.m_huffCode,
769                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint16_t));
770                 if (eStatus != MOS_STATUS_SUCCESS)
771                 {
772                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
773                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
774                 }
775 
776                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pDCCodeLength,
777                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint8_t),
778                     &huffmanTable.m_huffSize,
779                     JPEG_NUM_HUFF_TABLE_DC_HUFFVAL * sizeof(uint8_t));
780                 if (eStatus != MOS_STATUS_SUCCESS)
781                 {
782                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
783                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
784                 }
785             }
786             else // AC Table
787             {
788                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pACCodeValues,
789                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t),
790                     &huffmanTable.m_huffCode,
791                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint16_t));
792                 if (eStatus != MOS_STATUS_SUCCESS)
793                 {
794                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
795                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
796                 }
797 
798                 eStatus = (MOS_STATUS) MOS_SecureMemcpy(huffTableParams[m_jpegHuffmanTable->m_huffmanData[i].m_tableID].pACCodeLength,
799                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t),
800                     &huffmanTable.m_huffSize,
801                     JPEG_NUM_HUFF_TABLE_AC_HUFFVAL * sizeof(uint8_t));
802                 if (eStatus != MOS_STATUS_SUCCESS)
803                 {
804                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
805                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
806                 }
807             }
808         }
809 
810         // Send 2 huffman table commands - 1 for Luma and one for chroma for non-monchrome input formats
811         // If only one table is sent by the app (2 buffers), send the same table for Luma and chroma
812         bool repeatHuffTable = false;
813         if ((m_encodeParams.dwNumHuffBuffers / 2 < JPEG_MAX_NUM_HUFF_TABLE_INDEX)
814             && (m_jpegPicParams->m_inputSurfaceFormat != codechalJpegY8))
815         {
816             repeatHuffTable = true;
817 
818             // Copy over huffman data to the other two data buffers for JPEG picture header
819             for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers; i++)
820             {
821                 m_jpegHuffmanTable->m_huffmanData[i + 2].m_tableClass = m_jpegHuffmanTable->m_huffmanData[i].m_tableClass;
822                 m_jpegHuffmanTable->m_huffmanData[i + 2].m_tableID    = m_jpegHuffmanTable->m_huffmanData[i].m_tableID;
823 
824                 eStatus = MOS_SecureMemcpy(&m_jpegHuffmanTable->m_huffmanData[i + 2].m_bits[0],
825                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_BITS,
826                     &m_jpegHuffmanTable->m_huffmanData[i].m_bits[0],
827                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_BITS);
828                 if (eStatus != MOS_STATUS_SUCCESS)
829                 {
830                     CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
831                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
832                     return eStatus;
833                 }
834 
835                 eStatus = MOS_SecureMemcpy(&m_jpegHuffmanTable->m_huffmanData[i + 2].m_huffVal[0],
836                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_HUFFVAL,
837                     &m_jpegHuffmanTable->m_huffmanData[i].m_huffVal[0],
838                     sizeof(uint8_t) * JPEG_NUM_HUFF_TABLE_AC_HUFFVAL);
839                 if (eStatus != MOS_STATUS_SUCCESS)
840                 {
841                     CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
842                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
843                     return eStatus;
844                 }
845             }
846         }
847 
848         // 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
849         for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers / 2; i++)
850         {
851             if (repeatHuffTable)
852             {
853                 eStatus = (MOS_STATUS) (m_mfxInterface->AddMfcJpegHuffTableStateCmd(&cmdBuffer, &huffTableParams[i]));
854                 if (eStatus != MOS_STATUS_SUCCESS)
855                 {
856                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
857                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
858                 }
859             }
860 
861             eStatus = (MOS_STATUS) m_mfxInterface->AddMfcJpegHuffTableStateCmd(&cmdBuffer, &huffTableParams[i]);
862             if (eStatus != MOS_STATUS_SUCCESS)
863             {
864                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
865                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
866             }
867         }
868 
869         // set MFC_JPEG_SCAN_OBJECT
870         MhwVdboxJpegScanParams scanObjectParams;
871         scanObjectParams.mode                   = m_mode;
872         scanObjectParams.inputSurfaceFormat     = (CodecEncodeJpegInputSurfaceFormat)m_jpegPicParams->m_inputSurfaceFormat;
873         scanObjectParams.dwPicWidth             = m_jpegPicParams->m_picWidth;
874         scanObjectParams.dwPicHeight            = m_jpegPicParams->m_picHeight;
875         scanObjectParams.pJpegEncodeScanParams  = m_jpegScanParams;
876 
877         eStatus = (MOS_STATUS) m_mfxInterface->AddMfcJpegScanObjCmd(&cmdBuffer, &scanObjectParams);
878         if (eStatus != MOS_STATUS_SUCCESS)
879         {
880             MOS_SafeFreeMemory(tempJpegQuantMatrix);
881             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
882         }
883         // set MFC_JPEG_PAK_INSERT_OBJECT
884         MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
885         MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
886 
887         // The largest component written through the MFC_JPEG_PAK_INSERT_OBJECT command is Huffman table
888         pakInsertObjectParams.pBsBuffer = (BSBuffer *)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeJpegFrameHeader));
889         if (pakInsertObjectParams.pBsBuffer == nullptr)
890         {
891             MOS_SafeFreeMemory(tempJpegQuantMatrix);
892             CODECHAL_ENCODE_CHK_NULL_RETURN(nullptr);
893         }
894         if(!m_fullHeaderInAppData)
895         {
896             // Add SOI (0xFFD8) (only if it was sent by the application)
897             eStatus = (MOS_STATUS)PackSOI(pakInsertObjectParams.pBsBuffer);
898             if (eStatus != MOS_STATUS_SUCCESS)
899             {
900                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
901                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
902                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
903                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
904             }
905             pakInsertObjectParams.dwOffset                      = 0;
906             pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
907             pakInsertObjectParams.bLastHeader                   = false;
908             pakInsertObjectParams.bEndOfSlice                   = false;
909             pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
910             eStatus = (MOS_STATUS) m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr, &pakInsertObjectParams);
911             if (eStatus != MOS_STATUS_SUCCESS)
912             {
913                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
914                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
915                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
916                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
917             }
918             MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
919         }
920         // Add Application data if it was sent by application
921         if (m_applicationData != nullptr)
922         {
923             uint8_t* appDataChunk = nullptr;
924             uint32_t appDataChunkSize = m_appDataSize;
925 
926             // We can write a maximum of 1020 words per command, so if the size of the app data is
927             // more than 1020 we need to send multiple commands for writing out app data
928             uint32_t numAppDataCmdsNeeded = 1;
929             uint32_t appDataCmdSizeResidue = 0;
930             if (m_appDataSize > 1020)
931             {
932                 numAppDataCmdsNeeded  = m_appDataSize / 1020;
933                 appDataCmdSizeResidue = m_appDataSize % 1020;
934 
935                 appDataChunkSize = 1020;
936             }
937 
938             appDataChunk = (uint8_t*)MOS_AllocAndZeroMemory(appDataChunkSize);
939             if (appDataChunk == nullptr)
940             {
941                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
942                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
943                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
944                 CODECHAL_ENCODE_CHK_NULL_RETURN(nullptr);
945             }
946 
947             for (uint32_t i = 0; i < numAppDataCmdsNeeded; i++)
948             {
949                 uint8_t *copyAddress = (uint8_t*)(m_applicationData) + (i * appDataChunkSize);
950 
951                 MOS_SecureMemcpy(appDataChunk, appDataChunkSize,
952                     copyAddress, appDataChunkSize);
953 
954                 eStatus = (MOS_STATUS)PackApplicationData(pakInsertObjectParams.pBsBuffer, appDataChunk, appDataChunkSize);
955                 if (eStatus != MOS_STATUS_SUCCESS)
956                 {
957                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
958                     appDataChunk = nullptr;
959                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
960                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
961                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
962                 }
963                 pakInsertObjectParams.dwOffset                      = 0;
964                 pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
965                 //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
966                 if((appDataCmdSizeResidue == 0) && m_fullHeaderInAppData && (i == numAppDataCmdsNeeded - 1))
967                 {
968                     pakInsertObjectParams.bLastHeader                   = true;
969                     pakInsertObjectParams.bEndOfSlice                   = true;
970                 }
971                 else
972                 {
973                     pakInsertObjectParams.bLastHeader                   = false;
974                     pakInsertObjectParams.bEndOfSlice                   = false;
975                 }
976                 pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
977                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
978                     &pakInsertObjectParams);
979                 if (eStatus != MOS_STATUS_SUCCESS)
980                 {
981                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
982                     appDataChunk = nullptr;
983                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
984                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
985                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
986                 }
987             }
988 
989             if (appDataCmdSizeResidue != 0)
990             {
991                 uint8_t* lastAddress = (uint8_t*)(m_applicationData) + (numAppDataCmdsNeeded * appDataChunkSize);
992                 appDataChunkSize = appDataCmdSizeResidue;
993 
994                 MOS_SecureMemcpy(appDataChunk, appDataChunkSize,
995                     lastAddress,
996                     appDataChunkSize);
997 
998                 eStatus = (MOS_STATUS)PackApplicationData(pakInsertObjectParams.pBsBuffer, appDataChunk, appDataCmdSizeResidue);
999                 if (eStatus != MOS_STATUS_SUCCESS)
1000                 {
1001                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1002                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1003                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
1004                     MOS_SafeFreeMemory(appDataChunk);
1005                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1006                 }
1007                 pakInsertObjectParams.dwOffset                      = 0;
1008                 pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1009                 //if full header is included in application data, it will be the last insert headers
1010                 if(m_fullHeaderInAppData)
1011                 {
1012                     pakInsertObjectParams.bLastHeader                   = true;
1013                     pakInsertObjectParams.bEndOfSlice                   = true;
1014                 }
1015                 else
1016                 {
1017                     pakInsertObjectParams.bLastHeader                   = false;
1018                     pakInsertObjectParams.bEndOfSlice                   = false;
1019                 }
1020                 pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1021                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1022                     &pakInsertObjectParams);
1023                 if (eStatus != MOS_STATUS_SUCCESS)
1024                 {
1025                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1026                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1027                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
1028                     MOS_SafeFreeMemory(appDataChunk);
1029                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1030                 }
1031             }
1032 
1033             MOS_FreeMemory(appDataChunk);
1034         }
1035         if(!m_fullHeaderInAppData)
1036         {
1037         // Add Quant Table for Y
1038         eStatus = (MOS_STATUS)PackQuantTable(pakInsertObjectParams.pBsBuffer, jpegComponentY);
1039         if (eStatus != MOS_STATUS_SUCCESS)
1040         {
1041             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1042             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1043             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1044             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1045         }
1046         pakInsertObjectParams.dwOffset                      = 0;
1047         pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1048         pakInsertObjectParams.bLastHeader                   = false;
1049         pakInsertObjectParams.bEndOfSlice                   = false;
1050         pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1051         eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1052             &pakInsertObjectParams);
1053         if (eStatus != MOS_STATUS_SUCCESS)
1054         {
1055             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1056             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1057             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1058             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1059         }
1060         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1061 
1062         if (!useSingleDefaultQuantTable)
1063         {
1064             // Since there is no U and V in monochrome format, donot add Quantization table header for U and V components
1065             if (m_jpegPicParams->m_inputSurfaceFormat != codechalJpegY8)
1066             {
1067                 // Add quant table for U
1068                 eStatus = (MOS_STATUS)PackQuantTable(pakInsertObjectParams.pBsBuffer, jpegComponentU);
1069                 if (eStatus != MOS_STATUS_SUCCESS)
1070                 {
1071                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1072                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1073                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
1074                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1075                 }
1076                 pakInsertObjectParams.dwOffset                      = 0;
1077                 pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1078                 pakInsertObjectParams.bLastHeader                   = false;
1079                 pakInsertObjectParams.bEndOfSlice                   = false;
1080                 pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1081                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1082                     &pakInsertObjectParams);
1083                 if (eStatus != MOS_STATUS_SUCCESS)
1084                 {
1085                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1086                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1087                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
1088                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1089                 }
1090                 MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1091 
1092                 // Add quant table for V
1093                 eStatus = (MOS_STATUS)PackQuantTable(pakInsertObjectParams.pBsBuffer, jpegComponentV);
1094                 if (eStatus != MOS_STATUS_SUCCESS)
1095                 {
1096                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1097                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1098                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
1099                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1100                 }
1101                 pakInsertObjectParams.dwOffset                      = 0;
1102                 pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1103                 pakInsertObjectParams.bLastHeader                   = false;
1104                 pakInsertObjectParams.bEndOfSlice                   = false;
1105                 pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1106                 eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1107                     &pakInsertObjectParams);
1108                 if (eStatus != MOS_STATUS_SUCCESS)
1109                 {
1110                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1111                     MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1112                     MOS_SafeFreeMemory(tempJpegQuantMatrix);
1113                     CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1114                 }
1115                 MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1116             }
1117         }
1118 
1119         // Add Frame Header
1120         eStatus = (MOS_STATUS)PackFrameHeader(pakInsertObjectParams.pBsBuffer, useSingleDefaultQuantTable);
1121         if (eStatus != MOS_STATUS_SUCCESS)
1122         {
1123             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1124             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1125             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1126             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1127         }
1128         pakInsertObjectParams.dwOffset                      = 0;
1129         pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1130         pakInsertObjectParams.bLastHeader                   = false;
1131         pakInsertObjectParams.bEndOfSlice                   = false;
1132         pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1133         eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1134             &pakInsertObjectParams);
1135         if (eStatus != MOS_STATUS_SUCCESS)
1136         {
1137             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1138             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1139             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1140             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1141         }
1142         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1143 
1144         // Add Huffman Table for Y - DC table, Y- AC table, U/V - DC table, U/V - AC table
1145         for (uint32_t i = 0; i < m_encodeParams.dwNumHuffBuffers; i++)
1146         {
1147             eStatus = (MOS_STATUS)PackHuffmanTable(pakInsertObjectParams.pBsBuffer, i);
1148             if (eStatus != MOS_STATUS_SUCCESS)
1149             {
1150                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1151                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1152                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
1153                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1154             }
1155             pakInsertObjectParams.dwOffset                      = 0;
1156             pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1157             pakInsertObjectParams.bLastHeader                   = false;
1158             pakInsertObjectParams.bEndOfSlice                   = false;
1159             pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1160             eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1161                 &pakInsertObjectParams);
1162             if (eStatus != MOS_STATUS_SUCCESS)
1163             {
1164                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1165                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1166                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
1167                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1168             }
1169             MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1170         }
1171 
1172         // Restart Interval - Add only if the restart interval is not zero
1173         if (m_jpegScanParams->m_restartInterval != 0)
1174         {
1175             eStatus = (MOS_STATUS)PackRestartInterval(pakInsertObjectParams.pBsBuffer);
1176             if (eStatus != MOS_STATUS_SUCCESS)
1177             {
1178                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1179                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1180                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
1181                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1182             }
1183             pakInsertObjectParams.dwOffset                      = 0;
1184             pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1185             pakInsertObjectParams.bLastHeader                   = false;
1186             pakInsertObjectParams.bEndOfSlice                   = false;
1187             pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1188             eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1189                 &pakInsertObjectParams);
1190             if (eStatus != MOS_STATUS_SUCCESS)
1191             {
1192                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1193                 MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1194                 MOS_SafeFreeMemory(tempJpegQuantMatrix);
1195                 CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1196             }
1197             MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1198         }
1199 
1200         // Add scan header
1201         eStatus = (MOS_STATUS)PackScanHeader(pakInsertObjectParams.pBsBuffer);
1202         if (eStatus != MOS_STATUS_SUCCESS)
1203         {
1204             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1205             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1206             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1207             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1208         }
1209         pakInsertObjectParams.dwOffset                      = 0;
1210         pakInsertObjectParams.dwBitSize                     = pakInsertObjectParams.pBsBuffer->BufferSize;
1211         pakInsertObjectParams.bLastHeader                   = true;
1212         pakInsertObjectParams.bEndOfSlice                   = true;
1213         pakInsertObjectParams.bResetBitstreamStartingPos    = 1; // from discussion with HW Architect
1214         eStatus = (MOS_STATUS)m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr,
1215             &pakInsertObjectParams);
1216         if (eStatus != MOS_STATUS_SUCCESS)
1217         {
1218             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1219             MOS_SafeFreeMemory(pakInsertObjectParams.pBsBuffer);
1220             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1221             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1222         }
1223         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer->pBase);
1224         }
1225         MOS_FreeMemory(pakInsertObjectParams.pBsBuffer);
1226     }
1227 
1228     eStatus = ReadMfcStatus(&cmdBuffer);
1229     if (eStatus != MOS_STATUS_SUCCESS)
1230     {
1231         MOS_SafeFreeMemory(tempJpegQuantMatrix);
1232         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1233     }
1234 
1235     eStatus = EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES);
1236     if (eStatus != MOS_STATUS_SUCCESS)
1237     {
1238         MOS_SafeFreeMemory(tempJpegQuantMatrix);
1239         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1240     }
1241 
1242     eStatus = m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr);
1243     if (eStatus != MOS_STATUS_SUCCESS)
1244     {
1245         MOS_SafeFreeMemory(tempJpegQuantMatrix);
1246         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1247     }
1248 
1249     std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_currPass));
1250     CODECHAL_DEBUG_TOOL(
1251         eStatus = m_debugInterface->DumpCmdBuffer(
1252             &cmdBuffer,
1253             CODECHAL_NUM_MEDIA_STATES,
1254             pakPassName.data());
1255         if (eStatus != MOS_STATUS_SUCCESS)
1256         {
1257             MOS_SafeFreeMemory(tempJpegQuantMatrix);
1258             CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1259         }
1260 
1261     //CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
1262     //    m_debugInterface,
1263     //    &cmdBuffer));
1264     )
1265 
1266     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1267 
1268     eStatus = SubmitCommandBuffer(&cmdBuffer, m_renderContextUsesNullHw);
1269     if (eStatus != MOS_STATUS_SUCCESS)
1270     {
1271         MOS_SafeFreeMemory(tempJpegQuantMatrix);
1272         CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
1273     }
1274 
1275     if (tempJpegQuantMatrix != nullptr)
1276     {
1277         MOS_FreeMemory(tempJpegQuantMatrix);
1278         tempJpegQuantMatrix = nullptr;
1279     }
1280 
1281     return eStatus;
1282 }
1283 
CalculateCommandBufferSize()1284 uint32_t CodechalEncodeJpegState::CalculateCommandBufferSize()
1285 {
1286     uint32_t commandBufferSize =
1287         m_pictureStatesSize        +
1288         m_extraPictureStatesSize   +
1289         (m_sliceStatesSize * m_numSlices);
1290 
1291     // For JPEG encoder, add the size of PAK_INSERT_OBJ commands which is also part of command buffer
1292     if(m_standard == CODECHAL_JPEG)
1293     {
1294         // Add PAK_INSERT_OBJ for app data
1295         // PAK_INSERT_OBJ contains 2 DWORDS + bytes of payload data
1296         // There is a max of 1024 payload bytes of app data per PAK_INSERT_OBJ command, so adding 2 DWORDS for each of them
1297         // Total payload data is the same size as app data
1298         commandBufferSize += (m_encodeParams.dwAppDataSize + (2 * sizeof(uint32_t) * (m_encodeParams.dwAppDataSize / 1020+1)));  //to be consistent with how we split app data into chunks.
1299 
1300         // Add number of bytes of data added through PAK_INSERT_OBJ command
1301         commandBufferSize += (2 + // SOI = 2 bytes
1302                 // Frame header - add sizes of each component of CodechalEncodeJpegFrameHeader
1303                 (2 * sizeof(uint8_t)) + (4 * sizeof(uint16_t)) + 3 * sizeof(uint8_t)*  jpegNumComponent +
1304                 // AC and DC Huffman tables - 2 Huffman tables for each component, and 3 components
1305                 (2 * 3 * sizeof(CodechalJpegHuffmanHeader)) +
1306                 // Quant tables - 1 for Quant table of each component, so 3 quant tables per frame
1307                 (3 * sizeof(CodechalEncodeJpegQuantHeader)) +
1308                 // Restart interval - 1 per frame
1309                 sizeof(CodechalEncodeJpegRestartHeader) +
1310                 // Scan header - 1 per frame
1311                 sizeof(CodechalEncodeJpegScanHeader));
1312     }
1313 
1314     if (m_singleTaskPhaseSupported)
1315     {
1316         commandBufferSize *= (m_numPasses + 1);
1317     }
1318 
1319     // 4K align since allocation is in chunks of 4K bytes.
1320     commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, 0x1000);
1321 
1322     return commandBufferSize;
1323 }
1324 
GetStatusReport(EncodeStatus * encodeStatus,EncodeStatusReport * encodeStatusReport)1325 MOS_STATUS CodechalEncodeJpegState::GetStatusReport(
1326     EncodeStatus* encodeStatus,
1327     EncodeStatusReport* encodeStatusReport)
1328 {
1329     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1330 
1331     PMHW_VDBOX_IMAGE_STATUS_CONTROL imgStatusCtrl = &encodeStatus->ImageStatusCtrl;
1332 
1333     // The huffman tables sent by application were incorrect (used only for JPEG encoding)
1334     if (imgStatusCtrl->MissingHuffmanCode == 1)
1335     {
1336         CODECHAL_ENCODE_ASSERTMESSAGE("Error: JPEG standard encoding: missing huffman code");
1337         encodeStatusReport->CodecStatus = CODECHAL_STATUS_ERROR;
1338         return eStatus;
1339     }
1340 
1341     eStatus = GetStatusReportCommon(encodeStatus, encodeStatusReport);
1342 
1343     return eStatus;
1344 }
1345 
CodechalEncodeJpegState(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)1346 CodechalEncodeJpegState::CodechalEncodeJpegState(
1347         CodechalHwInterface* hwInterface,
1348         CodechalDebugInterface* debugInterface,
1349         PCODECHAL_STANDARD_INFO standardInfo)
1350         :CodechalEncoderState(hwInterface, debugInterface, standardInfo)
1351 {
1352     CODECHAL_ENCODE_FUNCTION_ENTER;
1353 
1354     memset(m_refList, 0, sizeof(m_refList));
1355 
1356     m_codecGetStatusReportDefined = true;
1357 }
1358 
1359 #if USE_CODECHAL_DEBUG_TOOL
DumpQuantTables(CodecEncodeJpegQuantTable * quantTable)1360 MOS_STATUS CodechalEncodeJpegState::DumpQuantTables(
1361     CodecEncodeJpegQuantTable *quantTable)
1362 {
1363     CODECHAL_DEBUG_FUNCTION_ENTER;
1364 
1365     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrIqParams))
1366     {
1367         return MOS_STATUS_SUCCESS;
1368     }
1369 
1370     CODECHAL_DEBUG_CHK_NULL(quantTable);
1371 
1372     std::ostringstream oss;
1373     oss.setf(std::ios::showbase | std::ios::uppercase);
1374 
1375     //Dump quantTable[JPEG_MAX_NUM_QUANT_TABLE_INDEX]
1376     for (uint32_t i = 0; i < JPEG_MAX_NUM_QUANT_TABLE_INDEX; ++i)
1377     {
1378         // Dump Table ID
1379         oss << "TableID: " << +quantTable->m_quantTable[i].m_tableID << std::endl;
1380         // Dump Precision
1381         oss << "TableID: " << +quantTable->m_quantTable[i].m_precision << std::endl;
1382         //Dump usQm[JPEG_NUM_QUANTMATRIX];
1383         oss << "quantTable[" << +i << "].usQm[0-" << (JPEG_NUM_QUANTMATRIX - 1) << "]: " << std::endl;
1384 
1385         for (uint32_t j = 0; j < JPEG_NUM_QUANTMATRIX; ++j)
1386         {
1387             oss << +quantTable->m_quantTable[i].m_qm[j];
1388             if (j % 6 == 5 || j == JPEG_NUM_QUANTMATRIX - 1)
1389             {
1390                 oss << std::endl;
1391             }
1392         }
1393     }
1394     const char *fileName = m_debugInterface->CreateFileName(
1395         "_ENC",
1396         CodechalDbgBufferType::bufIqParams,
1397         CodechalDbgExtType::txt);
1398 
1399     std::ofstream ofs(fileName, std::ios::out);
1400     ofs << oss.str();
1401     ofs.close();
1402 
1403     return MOS_STATUS_SUCCESS;
1404 }
1405 
DumpPicParams(CodecEncodeJpegPictureParams * picParams)1406 MOS_STATUS CodechalEncodeJpegState::DumpPicParams(
1407     CodecEncodeJpegPictureParams *picParams)
1408 {
1409     CODECHAL_DEBUG_FUNCTION_ENTER;
1410     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
1411     {
1412         return MOS_STATUS_SUCCESS;
1413     }
1414 
1415     CODECHAL_DEBUG_CHK_NULL(picParams);
1416 
1417     std::ostringstream oss;
1418     oss.setf(std::ios::showbase | std::ios::uppercase);
1419 
1420     oss << "Profile: " << +picParams->m_profile << std::endl;
1421     oss << "Progressive: " << +picParams->m_progressive << std::endl;
1422     oss << "Huffman: " << +picParams->m_huffman << std::endl;
1423     oss << "Interleaved: " << +picParams->m_interleaved << std::endl;
1424     oss << "Differential: " << +picParams->m_differential << std::endl;
1425     oss << "PicWidth: " << +picParams->m_picWidth << std::endl;
1426     oss << "PicHeight: " << +picParams->m_picHeight << std::endl;
1427     oss << "InputSurfaceFormat: " << +picParams->m_inputSurfaceFormat << std::endl;
1428     oss << "SampleBitDepth: " << +picParams->m_sampleBitDepth << std::endl;
1429     oss << "uiNumComponent: " << +picParams->m_numComponent << std::endl;
1430 
1431     //Dump componentIdentifier[jpegNumComponent]
1432     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1433     {
1434         oss << "ComponentIdentifier[" << +i << "]: " << +picParams->m_componentID[i] << std::endl;
1435     }
1436 
1437     //Dump quantTableSelector[jpegNumComponent]
1438     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1439     {
1440         oss << "QuantTableSelector[" << +i << "]: " << +picParams->m_quantTableSelector[i] << std::endl;
1441     }
1442     oss << "Quality: " << +picParams->m_quality << std::endl;
1443     oss << "NumScan: " << +picParams->m_numScan << std::endl;
1444     oss << "NumQuantTable: " << +picParams->m_numQuantTable << std::endl;
1445     oss << "NumCodingTable: " << +picParams->m_numCodingTable << std::endl;
1446     oss << "StatusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl;
1447 
1448     const char *fileName = m_debugInterface->CreateFileName(
1449         "_ENC",
1450         CodechalDbgBufferType::bufPicParams,
1451         CodechalDbgExtType::txt);
1452 
1453     std::ofstream ofs(fileName, std::ios::out);
1454     ofs << oss.str();
1455     ofs.close();
1456     return MOS_STATUS_SUCCESS;
1457 }
1458 
DumpScanParams(CodecEncodeJpegScanHeader * scanParams)1459 MOS_STATUS CodechalEncodeJpegState::DumpScanParams(
1460     CodecEncodeJpegScanHeader *scanParams)
1461 {
1462     CODECHAL_DEBUG_FUNCTION_ENTER;
1463 
1464     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrScanParams))
1465     {
1466         return MOS_STATUS_SUCCESS;
1467     }
1468 
1469     CODECHAL_DEBUG_CHK_NULL(scanParams);
1470 
1471     std::ostringstream oss;
1472     oss.setf(std::ios::showbase | std::ios::uppercase);
1473 
1474     oss << "RestartInterval: " << +scanParams->m_restartInterval << std::endl;
1475     oss << "NumComponents: " << +scanParams->m_numComponent << std::endl;
1476 
1477     //Dump ComponentSelector[jpegNumComponent]
1478     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1479     {
1480         oss << "ComponentSelector[" << +i << "]: " << +scanParams->m_componentSelector[i] << std::endl;
1481     }
1482 
1483     //Dump DcHuffTblSelector[jpegNumComponent]
1484     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1485     {
1486         oss << "DcHuffTblSelector[" << +i << "]: " << +scanParams->m_dcCodingTblSelector[i] << std::endl;
1487     }
1488 
1489     //Dump AcHuffTblSelector[jpegNumComponent]
1490     for (uint32_t i = 0; i < jpegNumComponent; ++i)
1491     {
1492         oss << "AcHuffTblSelector[" << +i << "]: " << +scanParams->m_acCodingTblSelector[i] << std::endl;
1493     }
1494 
1495     const char *fileName = m_debugInterface->CreateFileName(
1496         "_ENC",
1497         CodechalDbgBufferType::bufScanParams,
1498         CodechalDbgExtType::txt);
1499 
1500     std::ofstream ofs(fileName, std::ios::out);
1501     ofs << oss.str();
1502     ofs.close();
1503 
1504     return MOS_STATUS_SUCCESS;
1505 }
1506 
DumpHuffmanTable(CodecEncodeJpegHuffmanDataArray * huffmanTable)1507 MOS_STATUS CodechalEncodeJpegState::DumpHuffmanTable(
1508     CodecEncodeJpegHuffmanDataArray *huffmanTable)
1509 {
1510     CODECHAL_DEBUG_FUNCTION_ENTER;
1511 
1512     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrHuffmanTbl))
1513     {
1514         return MOS_STATUS_SUCCESS;
1515     }
1516 
1517     CODECHAL_DEBUG_CHK_NULL(huffmanTable);
1518 
1519     std::ostringstream oss;
1520     oss.setf(std::ios::showbase | std::ios::uppercase);
1521 
1522     //Dump HuffTable[JPEG_MAX_NUM_HUFF_TABLE_INDEX]
1523     for (uint32_t i = 0; i < JPEG_NUM_ENCODE_HUFF_BUFF; ++i)
1524     {
1525         // Dump Table Class
1526         oss << "TableClass: " << +huffmanTable->m_huffmanData[i].m_tableClass << std::endl;
1527         // Dump Table ID
1528         oss << "TableID: " << +huffmanTable->m_huffmanData[i].m_tableID << std::endl;
1529         //Dump ucBits[JPEG_NUM_HUFF_TABLE_AC_BITS]
1530         oss << "HuffTable[" << +i << "].ucBits[0-" << (JPEG_NUM_HUFF_TABLE_AC_BITS - 1) << "]: " << std::endl;
1531 
1532         for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_BITS; ++j)
1533         {
1534             oss << +huffmanTable->m_huffmanData[i].m_bits[j];
1535             if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_AC_BITS - 1)
1536             {
1537                 oss << std::endl;
1538             }
1539         }
1540 
1541         //Dump ucHuffVal[JPEG_NUM_HUFF_TABLE_AC_HUFFVAL]
1542         oss << "HuffTable[" << +i << "].ucHuffVal[0-" << (JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1) << "]: " << std::endl;
1543 
1544         for (uint32_t j = 0; j < JPEG_NUM_HUFF_TABLE_AC_HUFFVAL; ++j)
1545         {
1546             oss << +huffmanTable->m_huffmanData[i].m_huffVal[j];
1547             if (j % 6 == 5 || j == JPEG_NUM_HUFF_TABLE_AC_HUFFVAL - 1)
1548             {
1549                 oss << std::endl;
1550             }
1551         }
1552     }
1553 
1554     const char *fileName = m_debugInterface->CreateFileName(
1555         "_ENC",
1556         CodechalDbgBufferType::bufHuffmanTbl,
1557         CodechalDbgExtType::txt);
1558 
1559     std::ofstream ofs(fileName, std::ios::out);
1560     ofs << oss.str();
1561     ofs.close();
1562     return MOS_STATUS_SUCCESS;
1563 }
1564 
1565 #endif
1566