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