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