1 /*
2 * Copyright (c) 2021, 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 encode_jpeg_packer_feature.cpp
24 //! \brief Defines header packing logic for avc encode
25 //!
26
27 #include "encode_jpeg_packer_feature.h"
28 #include "encode_utils.h"
29
30 namespace encode
31 {
32
JpegPackerFeature(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)33 JpegPackerFeature::JpegPackerFeature(
34 MediaFeatureManager *featureManager,
35 EncodeAllocator * allocator,
36 CodechalHwInterfaceNext *hwInterface,
37 void * constSettings) :
38 MediaFeature(constSettings)
39 {
40 m_featureManager = featureManager;
41 }
42
PackSOI(BSBuffer * buffer)43 MOS_STATUS JpegPackerFeature::PackSOI(BSBuffer *buffer)
44 {
45 ENCODE_FUNC_CALL();
46
47 ENCODE_CHK_NULL_RETURN(buffer);
48 // Add SOI = 0xFFD8
49 buffer->pBase = (uint8_t *)MOS_AllocAndZeroMemory(2);
50 ENCODE_CHK_NULL_RETURN(buffer->pBase);
51
52 *(buffer->pBase) = (m_jpegEncodeSoi >> 8) & 0xFF;
53 *(buffer->pBase + 1) = (m_jpegEncodeSoi & 0xFF);
54 buffer->BitOffset = 0;
55 buffer->BufferSize = 16;
56
57 return MOS_STATUS_SUCCESS;
58 }
59
PackApplicationData(BSBuffer * buffer,uint8_t * appDataChunk,uint32_t size)60 MOS_STATUS JpegPackerFeature::PackApplicationData(
61 BSBuffer *buffer,
62 uint8_t *appDataChunk,
63 uint32_t size)
64 {
65 ENCODE_FUNC_CALL();
66
67 ENCODE_CHK_NULL_RETURN(buffer);
68 ENCODE_CHK_NULL_RETURN(appDataChunk);
69
70 buffer->pBase = appDataChunk;
71 buffer->BitOffset = 0;
72 buffer->BufferSize = (size * sizeof(uint8_t) * 8);
73
74 return MOS_STATUS_SUCCESS;
75 }
76
PackQuantTable(BSBuffer * buffer,CodecJpegComponents componentType)77 MOS_STATUS JpegPackerFeature::PackQuantTable(
78 BSBuffer * buffer,
79 CodecJpegComponents componentType)
80 {
81 ENCODE_FUNC_CALL();
82
83 ENCODE_CHK_NULL_RETURN(buffer);
84
85 auto basicFeature = dynamic_cast<JpegBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
86 ENCODE_CHK_NULL_RETURN(basicFeature);
87
88 EncodeJpegQuantHeader *quantHeader = (EncodeJpegQuantHeader *)MOS_AllocAndZeroMemory(sizeof(EncodeJpegQuantHeader));
89 ENCODE_CHK_NULL_RETURN(quantHeader);
90
91 quantHeader->m_dqt = 0xDBFF;
92 // Header size including marker
93 uint16_t hdrSize = sizeof(uint16_t) * 2 + sizeof(uint8_t) + sizeof(uint8_t) * JPEG_NUM_QUANTMATRIX;
94 quantHeader->m_lq = (((hdrSize - 2) & 0xFF) << 8) | (((hdrSize - 2) & 0xFF00) >> 8);
95
96 quantHeader->m_tablePrecisionAndDestination = ((basicFeature->m_jpegQuantTables->m_quantTable[componentType].m_precision & 0xF) << 4) | (componentType & 0xF);
97
98 for (auto i = 0; i < JPEG_NUM_QUANTMATRIX; i++)
99 {
100 quantHeader->m_qk[i] = (uint8_t)basicFeature->m_jpegQuantTables->m_quantTable[componentType].m_qm[i];
101 }
102
103 buffer->pBase = (uint8_t *)quantHeader;
104 buffer->BitOffset = 0;
105 buffer->BufferSize = hdrSize * 8;
106
107 return MOS_STATUS_SUCCESS;
108 }
109
PackFrameHeader(BSBuffer * buffer,bool useSingleDefaultQuantTable)110 MOS_STATUS JpegPackerFeature::PackFrameHeader(
111 BSBuffer *buffer,
112 bool useSingleDefaultQuantTable)
113 {
114 ENCODE_FUNC_CALL();
115
116 ENCODE_CHK_NULL_RETURN(buffer);
117
118 JpegBasicFeature *jpegBasicFeature = dynamic_cast<JpegBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
119 ENCODE_CHK_NULL_RETURN(jpegBasicFeature);
120
121 EncodeJpegFrameHeader *frameHeader = (EncodeJpegFrameHeader *)MOS_AllocAndZeroMemory(sizeof(EncodeJpegFrameHeader));
122 ENCODE_CHK_NULL_RETURN(frameHeader);
123
124 auto jpegPicParams = jpegBasicFeature->m_jpegPicParams;
125
126 frameHeader->m_sof = 0xC0FF;
127 frameHeader->m_nf = (uint8_t)jpegPicParams->m_numComponent;
128
129 // Calculate lf - switch btes to match with simulation
130 uint16_t value = 8 + (3 * frameHeader->m_nf); // does not include sof
131 frameHeader->m_lf = ((value & 0xFF) << 8) | ((value & 0xFF00) >> 8);
132
133 frameHeader->m_p = 8;
134 frameHeader->m_y = ((jpegPicParams->m_picHeight & 0xFF) << 8) | ((jpegPicParams->m_picHeight & 0xFF00) >> 8);
135 frameHeader->m_x = ((jpegPicParams->m_picWidth & 0xFF) << 8) | ((jpegPicParams->m_picWidth & 0xFF00) >> 8);
136
137 for (uint8_t i = 0; i < frameHeader->m_nf; i++)
138 {
139 frameHeader->m_codechalJpegFrameComponent[i].m_ci = (uint8_t)jpegPicParams->m_componentID[i];
140
141 if (useSingleDefaultQuantTable)
142 {
143 frameHeader->m_codechalJpegFrameComponent[i].m_tqi = 0; // 0/1/2 based on Y/U/V
144 }
145 else
146 {
147 frameHeader->m_codechalJpegFrameComponent[i].m_tqi = i; // 0/1/2 based on Y/U/V
148 }
149
150 // For all supported formats on JPEG encode, U and V vertical and horizontal sampling is 1
151 uint32_t horizontalSamplingFactor = 0, verticalSamplingFactor = 0;
152 if (i == 0)
153 {
154 horizontalSamplingFactor = jpegBasicFeature->GetJpegHorizontalSamplingFactorForY((CodecEncodeJpegInputSurfaceFormat)jpegPicParams->m_inputSurfaceFormat);
155 verticalSamplingFactor = jpegBasicFeature->GetJpegVerticalSamplingFactorForY((CodecEncodeJpegInputSurfaceFormat)jpegPicParams->m_inputSurfaceFormat);
156 }
157 else
158 {
159 horizontalSamplingFactor = 1;
160 verticalSamplingFactor = 1;
161 }
162
163 frameHeader->m_codechalJpegFrameComponent[i].m_samplingFactori = 0;
164 frameHeader->m_codechalJpegFrameComponent[i].m_samplingFactori = ((horizontalSamplingFactor & 0xF) << 4) | (verticalSamplingFactor & 0xF);
165 }
166
167 buffer->pBase = (uint8_t *)frameHeader;
168 buffer->BitOffset = 0;
169 buffer->BufferSize = (2 * sizeof(uint8_t) * 8) + (4 * sizeof(uint16_t) * 8) + (sizeof(frameHeader->m_codechalJpegFrameComponent[0]) * 8 * jpegPicParams->m_numComponent);
170
171 return MOS_STATUS_SUCCESS;
172 }
173
PackHuffmanTable(BSBuffer * buffer,uint32_t tableIndex)174 MOS_STATUS JpegPackerFeature::PackHuffmanTable(
175 BSBuffer *buffer,
176 uint32_t tableIndex)
177 {
178 ENCODE_FUNC_CALL();
179
180 ENCODE_CHK_NULL_RETURN(buffer);
181
182 auto basicFeature = dynamic_cast<JpegBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
183 ENCODE_CHK_NULL_RETURN(basicFeature);
184
185 EncodeJpegHuffmanHeader *huffmanHeader = (EncodeJpegHuffmanHeader *)MOS_AllocAndZeroMemory(sizeof(EncodeJpegHuffmanHeader));
186 ENCODE_CHK_NULL_RETURN(huffmanHeader);
187
188 huffmanHeader->m_dht = 0xC4FF;
189 huffmanHeader->m_tableClassAndDestn =
190 ((basicFeature->m_jpegHuffmanTable->m_huffmanData[tableIndex].m_tableClass & 0xF) << 4) | ((tableIndex / 2) & 0xF);
191
192 uint16_t totalHuffValues = 0;
193 for (auto i = 0; i < JPEG_NUM_HUFF_TABLE_AC_BITS; i++)
194 {
195 huffmanHeader->m_li[i] = (uint8_t)basicFeature->m_jpegHuffmanTable->m_huffmanData[tableIndex].m_bits[i];
196 totalHuffValues += huffmanHeader->m_li[i];
197 }
198
199 uint16_t hdrSize = 19 + totalHuffValues;
200 huffmanHeader->m_lh = ((hdrSize & 0xFF) << 8) | ((hdrSize & 0xFF00) >> 8);
201
202 for (auto i = 0; i < totalHuffValues; i++)
203 {
204 huffmanHeader->m_vij[i] = (uint8_t)basicFeature->m_jpegHuffmanTable->m_huffmanData[tableIndex].m_huffVal[i];
205 }
206
207 buffer->pBase = (uint8_t *)huffmanHeader;
208 buffer->BitOffset = 0;
209 buffer->BufferSize = (2 * sizeof(uint16_t) * 8) + (sizeof(uint8_t) * 8) + (JPEG_NUM_HUFF_TABLE_AC_BITS * 8) + (totalHuffValues * sizeof(uint8_t) * 8);
210
211 return MOS_STATUS_SUCCESS;
212 }
213
PackRestartInterval(BSBuffer * buffer)214 MOS_STATUS JpegPackerFeature::PackRestartInterval(
215 BSBuffer *buffer)
216 {
217 ENCODE_FUNC_CALL();
218
219 ENCODE_CHK_NULL_RETURN(buffer);
220
221 auto basicFeature = dynamic_cast<JpegBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
222 ENCODE_CHK_NULL_RETURN(basicFeature);
223
224 EncodeJpegRestartHeader *restartHeader = (EncodeJpegRestartHeader *)MOS_AllocAndZeroMemory(sizeof(EncodeJpegRestartHeader));
225 ENCODE_CHK_NULL_RETURN(restartHeader);
226
227 restartHeader->m_dri = 0xDDFF;
228 uint16_t hdrSize = sizeof(uint16_t) * 3;
229 restartHeader->m_lr = (((hdrSize - 2) & 0xFF) << 8) | (((hdrSize - 2) & 0xFF00) >> 8);
230 restartHeader->m_ri = (uint16_t)(((basicFeature->m_jpegScanParams->m_restartInterval & 0xFF) << 8) |
231 ((basicFeature->m_jpegScanParams->m_restartInterval & 0xFF00) >> 8));
232
233 buffer->pBase = (uint8_t *)restartHeader;
234 buffer->BitOffset = 0;
235 buffer->BufferSize = hdrSize * 8;
236
237 return MOS_STATUS_SUCCESS;
238 }
239
PackScanHeader(BSBuffer * buffer)240 MOS_STATUS JpegPackerFeature::PackScanHeader(
241 BSBuffer *buffer)
242 {
243 ENCODE_FUNC_CALL();
244
245 ENCODE_CHK_NULL_RETURN(buffer);
246
247 JpegBasicFeature *jpegBasicFeature = dynamic_cast<JpegBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
248 ENCODE_CHK_NULL_RETURN(jpegBasicFeature);
249 auto jpegPicParams = jpegBasicFeature->m_jpegPicParams;
250
251 // Size of Scan header in bytes = sos (2 bytes) + ls (2 bytes) + ns (1 byte)
252 // + ss (1 byte) + se (1 byte) + ahl (1 byte) + scanComponent (2 bytes) * Number of scan components
253 uint16_t hdrSize = 8 + 2 * jpegPicParams->m_numComponent;
254
255 uint8_t *scanHeader = (uint8_t *)MOS_AllocAndZeroMemory(hdrSize);
256 ENCODE_CHK_NULL_RETURN(scanHeader);
257
258 buffer->pBase = (uint8_t *)scanHeader;
259
260 // scanHeader->sos
261 *scanHeader = (m_jpegEncodeSos >> 8) & 0xFF;
262 scanHeader += 1;
263 *scanHeader = (m_jpegEncodeSos & 0xFF);
264 scanHeader += 1;
265
266 // scanHeader->ls
267 *scanHeader = ((hdrSize - 2) >> 8) & 0xFF;
268 scanHeader += 1;
269 *scanHeader = (hdrSize - 2) & 0xFF;
270 scanHeader += 1;
271
272 // scanHeader->ns
273 *scanHeader = (uint8_t)jpegPicParams->m_numComponent;
274 scanHeader += 1;
275
276 for (uint32_t j = 0; j < jpegPicParams->m_numComponent; j++)
277 {
278 *scanHeader = (uint8_t)jpegPicParams->m_componentID[j];
279 scanHeader += 1;
280
281 // For Y8 image format there is only one scan component, so scanComponent[1] and scanComponent[2] should not be added to the header
282 // scanHeader->scanComponent[j].Tdaj
283 if (j == 0)
284 {
285 *scanHeader = (uint8_t)(((jpegBasicFeature->m_jpegHuffmanTable->m_huffmanData[0].m_tableID & 0x0F) << 4) |
286 ((jpegBasicFeature->m_jpegHuffmanTable->m_huffmanData[1].m_tableID & 0x0F)));
287 scanHeader += 1;
288 }
289 else
290 {
291 *scanHeader = (uint8_t)(((jpegBasicFeature->m_jpegHuffmanTable->m_huffmanData[2].m_tableID & 0x0F) << 4) |
292 ((jpegBasicFeature->m_jpegHuffmanTable->m_huffmanData[3].m_tableID & 0x0F)));
293 scanHeader += 1;
294 }
295 }
296
297 // scanHeader->ss
298 *scanHeader = 0;
299 scanHeader += 1;
300 // scanHeader->se
301 *scanHeader = 63;
302 scanHeader += 1;
303 // scanHeader->ahl
304 *scanHeader = 0;
305 scanHeader += 1;
306
307 buffer->BitOffset = 0;
308 // Buffer size in bits
309 buffer->BufferSize = hdrSize * 8;
310
311 return MOS_STATUS_SUCCESS;
312 }
313
314 } // namespace encode
315