1 /*
2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3  * Copyright (c) Imagination Technologies Limited, UK
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Elaine Wang <elaine.wang@intel.com>
27  *
28  */
29 
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <string.h>
33 
34 #include "psb_def.h"
35 #include "psb_drv_debug.h"
36 #include "psb_surface.h"
37 #include "psb_cmdbuf.h"
38 #include "tng_hostcode.h"
39 #include "tng_hostheader.h"
40 #include "tng_jpegES.h"
41 #ifdef _TOPAZHP_PDUMP_
42 #include "tng_trace.h"
43 #endif
44 
tng__trace_cmdbuf(tng_cmdbuf_p cmdbuf)45 static void tng__trace_cmdbuf(tng_cmdbuf_p cmdbuf)
46 {
47     int i;
48     IMG_UINT32 ui32CmdTmp[4];
49     IMG_UINT32 *ptmp = (IMG_UINT32 *)(cmdbuf->cmd_start);
50 
51     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: start\n", __FUNCTION__);
52 
53     //skip the newcodec
54     if (*ptmp != MTX_CMDID_SW_NEW_CODEC) {
55         drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: error new coded\n", __FUNCTION__);
56         return ;
57     }
58     ptmp += 6;
59 
60     if ((*ptmp & 0xf) != MTX_CMDID_SETUP_INTERFACE) {
61         drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: error setup interface\n", __FUNCTION__);
62         return ;
63     }
64 
65     ui32CmdTmp[0] = *ptmp++;
66     ui32CmdTmp[1] = *ptmp++;
67     ui32CmdTmp[2] = *ptmp++;
68     ui32CmdTmp[3] = 0;
69 #ifdef _TOPAZHP_PDUMP_
70     topazhp_dump_command((unsigned int*)ui32CmdTmp);
71 #endif
72     for (i = 0; i < 3; i++) {
73         ui32CmdTmp[0] = *ptmp++;
74         ui32CmdTmp[1] = *ptmp++;
75         ui32CmdTmp[2] = 0;
76         ui32CmdTmp[3] = 0;
77 #ifdef _TOPAZHP_PDUMP_
78         topazhp_dump_command((unsigned int*)ui32CmdTmp);
79 #endif
80     }
81 
82     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end\n", __FUNCTION__);
83 
84     return;
85 }
86 
87 #define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
88 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
89 
90 #define PTG_JPEG_MAX_MCU_PER_SCAN (0x4000)
91 #define PTG_JPEG_HEADER_MAX_SIZE (1024)
92 
93 
94 #define C_INTERLEAVE 1
95 #define LC_YUYVINTERLEAVE 2
96 #define LC_YVYUINTERLEAVE 3
97 #define LC_UYVYINTERLEAVE 4
98 #define LC_VYUYINTERLEAVE 5
99 
100 #define ISCHROMAINTERLEAVED(eSurfaceFormat) ((IMG_UINT)(eSurfaceFormat==IMG_CODEC_PL12) * C_INTERLEAVE)
101 
102 
103 /******************************************************************************
104 General definitions
105 ******************************************************************************/
106 #define BYTE                            8
107 #define BYTES_IN_INT                    4
108 #define BITS_IN_INT                     32
109 #define BLOCK_SIZE                      8
110 #define PELS_IN_BLOCK                   64
111 
112 /******************************************************************************
113 JPEG marker definitions
114 ******************************************************************************/
115 #define START_OF_IMAGE              0xFFD8
116 #define SOF_BASELINE_DCT            0xFFC0
117 #define END_OF_IMAGE                0xFFD9
118 #define START_OF_SCAN               0xFFDA
119 
120 /* Definitions for the huffman table specification in the Marker segment */
121 #define DHT_MARKER                  0xFFC4
122 #define LH_DC                       0x001F
123 #define LH_AC                       0x00B5
124 #define LEVEL_SHIFT                 128
125 
126 /* Definitions for the quantization table specification in the Marker segment */
127 #define DQT_MARKER                  0xFFDB
128 #define ACMAX                       0x03FF
129 #define DCMAX                       0x07FF
130 /* Length and precision of the quantization table parameters */
131 #define LQPQ                        0x00430
132 #define QMAX                        255
133 #define CLIP(Number,Max,Min)    if((Number) > (Max)) (Number) = (Max); \
134                                 else if((Number) < (Min)) (Number) = (Min)
135 
136 /////////////////////////////////////////////////////////////////////////////////////
137 // BMP Reading Header Stuff
138 /////////////////////////////////////////////////////////////////////////////////////
139 
140 static const IMG_UINT8 gQuantLuma[QUANT_TABLE_SIZE_BYTES] = {
141     16, 11, 10, 16, 24, 40, 51, 61,
142     12, 12, 14, 19, 26, 58, 60, 55,
143     14, 13, 16, 24, 40, 57, 69, 56,
144     14, 17, 22, 29, 51, 87, 80, 62,
145     18, 22, 37, 56, 68, 109, 103, 77,
146     24, 35, 55, 64, 81, 104, 113, 92,
147     49, 64, 78, 87, 103, 121, 120, 101,
148     72, 92, 95, 98, 112, 100, 103, 99
149 };
150 
151 /*****************************************************************************/
152 /*  \brief   gQuantChroma                                                    */
153 /*                                                                           */
154 /*  Contains the data that needs to be sent in the marker segment of an      */
155 /*  interchange format JPEG stream or an abbreviated format table            */
156 /*  specification data stream.                                               */
157 /*  Quantizer table for the chrominance component                            */
158 /*****************************************************************************/
159 static const IMG_UINT8 gQuantChroma[QUANT_TABLE_SIZE_BYTES] = {
160     17, 18, 24, 47, 99, 99, 99, 99,
161     18, 21, 26, 66, 99, 99, 99, 99,
162     24, 26, 56, 99, 99, 99, 99, 99,
163     47, 66, 99, 99, 99, 99, 99, 99,
164     99, 99, 99, 99, 99, 99, 99, 99,
165     99, 99, 99, 99, 99, 99, 99, 99,
166     99, 99, 99, 99, 99, 99, 99, 99,
167     99, 99, 99, 99, 99, 99, 99, 99
168 };
169 
170 /*****************************************************************************/
171 /*  \brief   gZigZag                                                         */
172 /*                                                                           */
173 /*  Zigzag scan pattern                                                      */
174 /*****************************************************************************/
175 static const IMG_UINT8 gZigZag[] = {
176     0,  1,  8, 16,  9,  2,  3, 10,
177     17, 24, 32, 25, 18, 11,  4,  5,
178     12, 19, 26, 33, 40, 48, 41, 34,
179     27, 20, 13,  6,  7, 14, 21, 28,
180     35, 42, 49, 56, 57, 50, 43, 36,
181     29, 22, 15, 23, 30, 37, 44, 51,
182     58, 59, 52, 45, 38, 31, 39, 46,
183     53, 60, 61, 54, 47, 55, 62, 63
184 };
185 
186 /*****************************************************************************/
187 /*  \brief   gMarkerDataLumaDc                                               */
188 /*                                                                           */
189 /*  Contains the data that needs to be sent in the marker segment of an      */
190 /*  interchange format JPEG stream or an abbreviated format table            */
191 /*  specification data stream.                                               */
192 /*  Specifies the huffman table used for encoding the luminance DC           */
193 /*  coefficient differences. The table represents Table K.3 of               */
194 /*  IS0/IEC 10918-1:1994(E)                                                  */
195 /*****************************************************************************/
196 static const IMG_UINT8 gMarkerDataLumaDc[] = {
197     //TcTh  Li
198     0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
199     0x00, 0x00, 0x00, 0x00, 0x00,
200     // Vi
201     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
202 };
203 
204 /*****************************************************************************/
205 /*  \brief   gMarkerDataLumaAc                                               */
206 /*                                                                           */
207 /*  Contains the data that needs to be sent in the marker segment of an      */
208 /*  interchange format JPEG stream or an abbreviated format table            */
209 /*  specification data stream.                                               */
210 /*  Specifies the huffman table used for encoding the luminance AC           */
211 /*  coefficients. The table represents Table K.5 of IS0/IEC 10918-1:1994(E)  */
212 /*****************************************************************************/
213 static const IMG_UINT8 gMarkerDataLumaAc[] = {
214     // TcTh  Li
215     0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
216     0x04, 0x00, 0x00, 0x01, 0x7D,
217     // Vi
218     0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
219     0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
220     0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72,
221     0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28,
222     0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45,
223     0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
224     0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75,
225     0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
226     0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3,
227     0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
228     0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
229     0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
230     0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4,
231     0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
232 };
233 
234 /*****************************************************************************/
235 /*  \brief   gMarkerDataChromaDc                                             */
236 /*                                                                           */
237 /*  Contains the data that needs to be sent in the marker segment of an      */
238 /*  interchange format JPEG stream or an abbreviated format table            */
239 /*  specification data stream.                                               */
240 /*  Specifies the huffman table used for encoding the chrominance DC         */
241 /*  coefficient differences. The table represents Table K.4 of               */
242 /*  IS0/IEC 10918-1:1994(E)                                                  */
243 /*****************************************************************************/
244 static const IMG_UINT8 gMarkerDataChromaDc[] = {
245     // TcTh Li
246     0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
247     0x00, 0x00, 0x00, 0x00, 0x00,
248 
249     // Vi
250     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
251 };
252 
253 /*****************************************************************************/
254 /*  \brief   gMarkerDataChromaAc                                             */
255 /*                                                                           */
256 /*  Contains the data that needs to be sent in the marker segment of an      */
257 /*  interchange format JPEG stream or an abbreviated format table            */
258 /*  specification data stream.                                               */
259 /*  Specifies the huffman table used for encoding the chrominance AC         */
260 /*  coefficients. The table represents Table K.6 of IS0/IEC 10918-1:1994(E)  */
261 /*****************************************************************************/
262 static const IMG_UINT8 gMarkerDataChromaAc[] = {
263     // TcTh
264     0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
265     0x04, 0x00, 0x01, 0x02, 0x77,
266 
267     // Vi
268     0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
269     0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
270     0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1,
271     0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26,
272     0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
273     0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
274     0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74,
275     0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
276     0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
277     0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4,
278     0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
279     0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
280     0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4,
281     0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
282 };
283 
CustomizeQuantizationTables(unsigned char * luma_matrix,unsigned char * chroma_matrix,unsigned int ui32Quality)284 static int CustomizeQuantizationTables(unsigned char *luma_matrix,
285                                          unsigned char *chroma_matrix,
286                                          unsigned int ui32Quality)
287 {
288     unsigned int uc_qVal;
289     unsigned int uc_j;
290 
291     if((NULL == luma_matrix) || (NULL == chroma_matrix) ||
292        (ui32Quality < 1) || (ui32Quality > 100))
293         return 1;
294 
295     /* Compute luma quantization table */
296     ui32Quality = (ui32Quality<50) ? (5000/ui32Quality) : (200-ui32Quality*2);
297     for(uc_j=0; uc_j<QUANT_TABLE_SIZE_BYTES; ++uc_j) {
298         uc_qVal = (gQuantLuma[uc_j] * ui32Quality + 50) / 100;
299         uc_qVal =  (uc_qVal>0xFF)? 0xFF:uc_qVal;
300         uc_qVal =  (uc_qVal<1)? 1:uc_qVal;
301         luma_matrix[uc_j] = (unsigned char)uc_qVal;
302     }
303 
304     /* Compute chroma quantization table */
305     for(uc_j=0; uc_j<QUANT_TABLE_SIZE_BYTES; ++uc_j) {
306         uc_qVal = (gQuantChroma[uc_j] * ui32Quality + 50) / 100;
307         uc_qVal =  (uc_qVal>0xFF)? 0xFF:uc_qVal;
308         uc_qVal =  (uc_qVal<1)? 1:uc_qVal;
309         chroma_matrix[uc_j] = (unsigned char)uc_qVal;
310     }
311 
312     return 0;
313 }
314 
SetDefaultQmatix(void * pMemInfoTableBlock)315 static void SetDefaultQmatix(void *pMemInfoTableBlock)
316 {
317     JPEG_MTX_QUANT_TABLE *pQTable =  pMemInfoTableBlock;
318     memcpy(pQTable->aui8LumaQuantParams, gQuantLuma, QUANT_TABLE_SIZE_BYTES);
319     memcpy(pQTable->aui8ChromaQuantParams, gQuantChroma, QUANT_TABLE_SIZE_BYTES);
320     return;
321 }
322 
323 
IssueQmatix(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)324 static void IssueQmatix(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
325 {
326     int i;
327     context_ENC_p ctx = (context_ENC_p)pJPEGContext->ctx;
328 
329     /* Dump MTX setup data for debug */
330     ASSERT(NULL != pJPEGContext->pMemInfoTableBlock);
331 
332     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Issue Quantization Table data\n");
333     for (i=0; i<128; i+=8) {
334         if (0 == i) {
335             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Table 0:\n");
336         }
337         else if (64 == i) {
338             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Table 1:\n");
339         }
340         drv_debug_msg(VIDEO_DEBUG_GENERAL, "%d %d %d %d %d %d %d %d\n",
341                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i),
342                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+1),
343                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+2),
344                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+3),
345                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+4),
346                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+5),
347                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+6),
348                       *((unsigned char *)ctx->obj_context->tng_cmdbuf->jpeg_pic_params_p+i+7));
349     }
350 
351     tng_cmdbuf_insert_command(ctx->obj_context,
352                                       0,
353                                       MTX_CMDID_SETQUANT,
354                                       0,
355                                       &(ctx->obj_context->tng_cmdbuf->jpeg_pic_params),
356                                       0);
357 }
358 
InitializeJpegEncode(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)359 static void InitializeJpegEncode(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
360 {
361     context_ENC_p ctx = (context_ENC_p)pJPEGContext->ctx;
362     IMG_UINT16 ui16_width;
363     IMG_UINT16 ui16_height;
364     IMG_UINT32 ui32UpperLimit;
365 
366     /*********************************************************************/
367     /* Determine the horizonal and the vertical sampling frequency of    */
368     /* each of components in the image                                   */
369     /*********************************************************************/
370 
371     ui16_width = ctx->ui16Width;
372     ui16_height = ctx->ui16FrameHeight; //pTFrame->height isn't the real height of image, because vaCreateSurface has made it aligned with 32
373 
374     switch (pJPEGContext->eFormat) {
375     case IMG_CODEC_PL12:
376     default:
377         pJPEGContext->MCUComponent[0].ui32WidthBlocks = 16;
378         pJPEGContext->MCUComponent[0].ui32HeightBlocks = 16;
379         pJPEGContext->MCUComponent[0].ui32XLimit = ui16_width;
380         pJPEGContext->MCUComponent[0].ui32YLimit = ui16_height;
381 
382         pJPEGContext->MCUComponent[1].ui32WidthBlocks = 8;
383         pJPEGContext->MCUComponent[1].ui32HeightBlocks = 8;
384         pJPEGContext->MCUComponent[1].ui32XLimit = ui16_width >> 1;
385         pJPEGContext->MCUComponent[1].ui32YLimit = ui16_height >> 1;
386 
387         pJPEGContext->MCUComponent[2].ui32WidthBlocks = 8;
388         pJPEGContext->MCUComponent[2].ui32HeightBlocks = 8;
389         pJPEGContext->MCUComponent[2].ui32XLimit = ui16_width >> 1;
390         pJPEGContext->MCUComponent[2].ui32YLimit = ui16_height >> 1;
391 
392         break;
393     }
394 
395     switch (ISCHROMAINTERLEAVED(pJPEGContext->eFormat)) {
396     case C_INTERLEAVE:
397     default:
398         // Chroma format is byte interleaved, as the engine runs using planar colour surfaces we need
399         // to fool the engine into offsetting by 16 instead of 8
400         pJPEGContext->MCUComponent[1].ui32WidthBlocks +=
401             pJPEGContext->MCUComponent[2].ui32WidthBlocks;
402         pJPEGContext->MCUComponent[1].ui32XLimit +=
403             pJPEGContext->MCUComponent[2].ui32XLimit;
404         pJPEGContext->MCUComponent[2].ui32XLimit =
405             pJPEGContext->MCUComponent[2].ui32YLimit =
406                 pJPEGContext->MCUComponent[2].ui32WidthBlocks =
407                     pJPEGContext->MCUComponent[2].ui32HeightBlocks = 0;
408         break;
409     }
410 
411     pJPEGContext->sScan_Encode_Info.ui32NumberMCUsX =
412         (pJPEGContext->MCUComponent[0].ui32XLimit +
413          (pJPEGContext->MCUComponent[0].ui32WidthBlocks - 1)) /
414         pJPEGContext->MCUComponent[0].ui32WidthBlocks;
415     pJPEGContext->sScan_Encode_Info.ui32NumberMCUsY =
416         (pJPEGContext->MCUComponent[0].ui32YLimit +
417          (pJPEGContext->MCUComponent[0].ui32HeightBlocks - 1)) /
418         pJPEGContext->MCUComponent[0].ui32HeightBlocks;
419     pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncode =
420         pJPEGContext->sScan_Encode_Info.ui32NumberMCUsX *
421         pJPEGContext->sScan_Encode_Info.ui32NumberMCUsY;
422 
423     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of X MCUs: %d\n", pJPEGContext->sScan_Encode_Info.ui32NumberMCUsX);
424     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of Y MCUs: %d\n", pJPEGContext->sScan_Encode_Info.ui32NumberMCUsY);
425     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of total MCUs: %d\n", pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncode);
426 
427 
428     // Number of MCUs sent for a scan _must_ lie at the beginning of a line so that the chroma component can't violate the 16 byte DMA start alignment constraint
429     // (Actual memory alignment for final DMA will have width aligned to 64, so start of line will automatically meet the 16 byte alignment required by the DMA engine)
430     pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan =
431         (pJPEGContext->sScan_Encode_Info.ui32NumberMCUsY + (pJPEGContext->NumCores - 1)) / pJPEGContext->NumCores;
432     pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan *=
433         pJPEGContext->sScan_Encode_Info.ui32NumberMCUsX;
434 
435     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of MCUs per core: %d\n", pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan);
436 
437 
438     // Limit the scan size to maximum useable (due to it being used as the 16 bit field for Restart Intervals) = 0xFFFF MCUs
439     // In reality, worst case allocatable bytes is less than this, something around 0x159739C == 0x4b96 MCUs = 139 x 139 MCUS = 2224 * 2224 pixels, approx.
440     // We'll give this upper limit some margin for error, and limit our MCUsPerScan to 2000 * 2000 pixels = 125 * 125 MCUS = 0x3D09 MCUS = 0x116F322 bytes (1170 worst case per MCU)
441     // If more MCUs are required, then the image will be automatically encoded with multiple scans on the same pipes
442     ui32UpperLimit = PTG_JPEG_MAX_MCU_PER_SCAN / pJPEGContext->sScan_Encode_Info.ui32NumberMCUsX;
443     ui32UpperLimit *= pJPEGContext->sScan_Encode_Info.ui32NumberMCUsX;
444 
445     if (pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan > ui32UpperLimit) {
446         // Set MCUs to encode per scan to equal maximum limit and then truncate to ensure it lies at the first MCU of a line (to satisfy the 64 byte requirement)
447         pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan = ui32UpperLimit;
448     }
449 
450     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of MCUs per scan: %d\n", pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan);
451 
452     //Need to set up CB Output slicenumber to equal number of slices required to encode image
453     // Set current CB scan to maximum scan number (will count down as scans are output)
454     pJPEGContext->sScan_Encode_Info.ui16ScansInImage =
455         (pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncode +
456          (pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan - 1)) /
457         pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan;
458 
459     pJPEGContext->sScan_Encode_Info.ui8NumberOfCodedBuffers =
460         pJPEGContext->sScan_Encode_Info.ui16ScansInImage;
461 
462     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Scans in image: %d\n", pJPEGContext->sScan_Encode_Info.ui16ScansInImage);
463     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of coded buffers: %d\n", pJPEGContext->sScan_Encode_Info.ui8NumberOfCodedBuffers);
464 
465     return;
466 }
467 
AssignCodedDataBuffers(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)468 static void AssignCodedDataBuffers(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
469 {
470     IMG_UINT8 ui8Loop;
471     pJPEGContext->ui32SizePerCodedBuffer =
472         (pJPEGContext->jpeg_coded_buf.ui32Size - PTG_JPEG_HEADER_MAX_SIZE) /
473         pJPEGContext->sScan_Encode_Info.ui8NumberOfCodedBuffers;
474     pJPEGContext->ui32SizePerCodedBuffer &= ~0xf;
475 
476     memset((void *)pJPEGContext->sScan_Encode_Info.aBufferTable, 0x0,
477            sizeof(TOPAZHP_JPEG_BUFFER_INFO)*pJPEGContext->sScan_Encode_Info.ui8NumberOfCodedBuffers);
478 
479     drv_debug_msg(VIDEO_DEBUG_GENERAL, "jpeg_coded_buf.pMemInfo: 0x%x\n", (unsigned int)(pJPEGContext->jpeg_coded_buf.pMemInfo));
480 
481     for (ui8Loop = 0 ; ui8Loop < pJPEGContext->sScan_Encode_Info.ui8NumberOfCodedBuffers; ui8Loop++) {
482         //pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].ui32DataBufferSizeBytes = DATA_BUFFER_SIZE(pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan);
483         //pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].ui32DataBufferSizeBytes = (pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].ui32DataBufferSizeBytes+sizeof(BUFFER_HEADER)) + 3 & ~3;
484         pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].ui32DataBufferUsedBytes = 0;
485         pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].i8PipeNumber = 0; // Indicates buffer is idle
486         pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].ui16ScanNumber = 0; // Indicates buffer is idle
487 
488         pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].pMemInfo = (void *)
489                 ((IMG_UINT32)pJPEGContext->jpeg_coded_buf.pMemInfo + PTG_JPEG_HEADER_MAX_SIZE +
490                  ui8Loop * pJPEGContext->ui32SizePerCodedBuffer);
491         drv_debug_msg(VIDEO_DEBUG_GENERAL, "aBufferTable[%d].pMemInfo: 0x%x\n", ui8Loop,
492                                  (unsigned int)(pJPEGContext->sScan_Encode_Info.aBufferTable[ui8Loop].pMemInfo));
493     }
494 
495     return;
496 }
497 
SetSetupInterface(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)498 static void SetSetupInterface(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
499 {
500     context_ENC_p ctx = (context_ENC_p)pJPEGContext->ctx;
501     context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]);
502     context_ENC_mem_size *ps_mem_size = &(ctx->ctx_mem_size);
503 
504     tng_cmdbuf_set_phys(pJPEGContext->pMTXWritebackMemory->apWritebackRegions, WB_FIFO_SIZE,
505                         &(ctx->bufs_writeback), 0, ps_mem_size->writeback);
506 }
507 
IssueSetupInterface(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)508 static void IssueSetupInterface(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
509 {
510     int i;
511     context_ENC_p ctx = (context_ENC_p)pJPEGContext->ctx;
512 
513     ASSERT(NULL != pJPEGContext->pMTXSetup);
514     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Issue SetupInterface\n");
515 
516     for (i = 0; i < WB_FIFO_SIZE; i++) {
517         drv_debug_msg(VIDEO_DEBUG_GENERAL, "apWritebackRegions[%d]: 0x%x\n", i,
518                                  pJPEGContext->pMTXWritebackMemory->apWritebackRegions[i]);
519     }
520 
521     tng_cmdbuf_insert_command(ctx->obj_context,
522                                       0,
523                                       MTX_CMDID_SETUP_INTERFACE,
524                                       0,
525                                       &(ctx->obj_context->tng_cmdbuf->jpeg_header_interface_mem),
526                                       0);
527 }
528 
SetMTXSetup(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,object_surface_p pTFrame)529 static IMG_ERRORCODE SetMTXSetup(
530     TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext,
531     object_surface_p pTFrame)
532 {
533     IMG_UINT32 srf_buf_offset;
534     context_ENC_p ctx = (context_ENC_p)pJPEGContext->ctx;
535     tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf;
536     context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]);
537     context_ENC_mem_size *ps_mem_size = &(ctx->ctx_mem_size);
538 
539     pJPEGContext->pMTXSetup->ui32ComponentsInScan = MTX_MAX_COMPONENTS;
540 
541     switch (pJPEGContext->eFormat) {
542     case IMG_CODEC_PL12:
543         if (pTFrame->psb_surface->stride % 64) {
544             drv_debug_msg(VIDEO_DEBUG_ERROR, "Surface stride isn't aligned to 64 bytes as HW requires: %u!\n",
545                           pTFrame->psb_surface->stride);
546             return IMG_ERR_INVALID_CONTEXT;
547         }
548         pJPEGContext->pMTXSetup->ComponentPlane[0].ui32Stride = pTFrame->psb_surface->stride;
549         pJPEGContext->pMTXSetup->ComponentPlane[1].ui32Stride = pTFrame->psb_surface->stride;
550         pJPEGContext->pMTXSetup->ComponentPlane[2].ui32Stride = pTFrame->psb_surface->stride;
551 
552         pJPEGContext->pMTXSetup->ComponentPlane[0].ui32Height = pJPEGContext->MCUComponent[0].ui32YLimit;
553         pJPEGContext->pMTXSetup->ComponentPlane[1].ui32Height = pJPEGContext->MCUComponent[0].ui32YLimit / 2;
554         pJPEGContext->pMTXSetup->ComponentPlane[2].ui32Height = pJPEGContext->MCUComponent[0].ui32YLimit / 2;
555         break;
556     default:
557         drv_debug_msg(VIDEO_DEBUG_ERROR, "Not supported FOURCC: %x!\n", pJPEGContext->eFormat);
558         return IMG_ERR_INVALID_CONTEXT;
559     }
560 
561     srf_buf_offset = pTFrame->psb_surface->buf.buffer_ofs;
562     RELOC_JPEG_PIC_PARAMS_PTG(&pJPEGContext->pMTXSetup->ComponentPlane[0].ui32PhysAddr, srf_buf_offset,
563                               &pTFrame->psb_surface->buf);
564     switch (pJPEGContext->eFormat) {
565     case IMG_CODEC_PL12:
566         RELOC_JPEG_PIC_PARAMS_PTG(&pJPEGContext->pMTXSetup->ComponentPlane[1].ui32PhysAddr,
567                                   srf_buf_offset + pTFrame->psb_surface->stride * pTFrame->height,
568                                   &pTFrame->psb_surface->buf);
569         //Byte interleaved surface, so need to force chroma to use single surface by fooling it into
570         //thinking it's dealing with standard 8x8 planaerblocks
571         RELOC_JPEG_PIC_PARAMS_PTG(&pJPEGContext->pMTXSetup->ComponentPlane[2].ui32PhysAddr,
572                                   srf_buf_offset + pTFrame->psb_surface->stride * pTFrame->height + 8,
573                                   &pTFrame->psb_surface->buf);
574         break;
575     default:
576         drv_debug_msg(VIDEO_DEBUG_ERROR, "Not supported FOURCC: %x!\n", pJPEGContext->eFormat);
577         return IMG_ERR_INVALID_CONTEXT;
578     }
579 
580     memcpy((void *)pJPEGContext->pMTXSetup->MCUComponent,
581            (void *)pJPEGContext->MCUComponent,
582            sizeof(pJPEGContext->MCUComponent));
583 
584     pJPEGContext->pMTXSetup->ui32TableA = 0;
585     pJPEGContext->pMTXSetup->ui16DataInterleaveStatus = ISCHROMAINTERLEAVED(pJPEGContext->eFormat);
586     pJPEGContext->pMTXSetup->ui16MaxPipes = (IMG_UINT16)pJPEGContext->NumCores;
587 
588     return IMG_ERR_OK;
589 }
590 
IssueMTXSetup(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)591 static void IssueMTXSetup(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
592 {
593     uint32_t i;
594     context_ENC_p ctx = (context_ENC_p)pJPEGContext->ctx;
595 
596     /* Dump MTX setup data for debug */
597     ASSERT(NULL != pJPEGContext->pMTXSetup);
598     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Issue MTX setup data\n");
599 
600     for (i = 0; i < pJPEGContext->pMTXSetup->ui32ComponentsInScan; i++) {
601         drv_debug_msg(VIDEO_DEBUG_GENERAL, "ComponentPlane[%d]: 0x%x, %d, %d\n", i,
602                                  pJPEGContext->pMTXSetup->ComponentPlane[i].ui32PhysAddr,
603                                  pJPEGContext->pMTXSetup->ComponentPlane[i].ui32Stride,
604                                  pJPEGContext->pMTXSetup->ComponentPlane[i].ui32Height);
605         drv_debug_msg(VIDEO_DEBUG_GENERAL, "MCUComponent[%d]: %d, %d, %d, %d\n", i,
606                                  pJPEGContext->pMTXSetup->MCUComponent[i].ui32WidthBlocks,
607                                  pJPEGContext->pMTXSetup->MCUComponent[i].ui32HeightBlocks,
608                                  pJPEGContext->pMTXSetup->MCUComponent[i].ui32XLimit,
609                                  pJPEGContext->pMTXSetup->MCUComponent[i].ui32YLimit);
610     }
611 
612     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32ComponentsInScan: %d\n", pJPEGContext->pMTXSetup->ui32ComponentsInScan);
613     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32TableA: %d\n", pJPEGContext->pMTXSetup->ui32TableA);
614     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui16DataInterleaveStatus: %d\n", pJPEGContext->pMTXSetup->ui16DataInterleaveStatus);
615     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui16MaxPipes: %d\n", pJPEGContext->pMTXSetup->ui16MaxPipes);
616 
617     tng_cmdbuf_insert_command(ctx->obj_context,
618                                       0,
619                                       MTX_CMDID_SETUP,
620                                       0,
621                                       &(ctx->obj_context->tng_cmdbuf->jpeg_header_mem),
622                                       0);
623 
624     return;
625 }
626 
627 
628 
fPutBitsToBuffer(STREAMTYPEW * BitStream,IMG_UINT8 NoOfBytes,IMG_UINT32 ActualBits)629 static void fPutBitsToBuffer(STREAMTYPEW *BitStream, IMG_UINT8 NoOfBytes, IMG_UINT32 ActualBits)
630 {
631     IMG_UINT8 ui8Lp;
632     IMG_UINT8 *pui8S;
633 
634     pui8S = (IMG_UINT8 *)BitStream->Buffer;
635     pui8S += BitStream->Offset;
636 
637     for (ui8Lp = NoOfBytes; ui8Lp > 0; ui8Lp--)
638         *(pui8S++) = ((IMG_UINT8 *) &ActualBits)[ui8Lp-1];
639 
640     BitStream->Offset += NoOfBytes;
641 }
642 
EncodeMarkerSegment(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_UINT8 * puc_stream_buff,IMG_BOOL bIncludeHuffmanTables)643 static IMG_UINT32 EncodeMarkerSegment(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext,
644                                       IMG_UINT8 *puc_stream_buff, IMG_BOOL bIncludeHuffmanTables)
645 {
646     STREAMTYPEW s_streamW;
647     IMG_UINT8 uc_i;
648 
649     s_streamW.Offset = 0;
650     s_streamW.Buffer = puc_stream_buff;
651 
652     /* Writing the start of image marker */
653     fPutBitsToBuffer(&s_streamW, 2, START_OF_IMAGE);
654 
655     /* Writing the quantization table for luminance into the stream */
656     fPutBitsToBuffer(&s_streamW, 2, DQT_MARKER);
657 
658     fPutBitsToBuffer(&s_streamW, 3, LQPQ << 4); // 20 bits = LQPQ, 4 bits = 0 (Destination identifier for the luminance quantizer tables)
659 
660     IMG_ASSERT(PELS_IN_BLOCK <= QUANT_TABLE_SIZE_BYTES);
661     for (uc_i = 0; uc_i < PELS_IN_BLOCK; uc_i++) {
662         // Write zigzag ordered luma quantization values to our JPEG header
663         fPutBitsToBuffer(&s_streamW, 1, pJPEGContext->psTablesBlock->aui8LumaQuantParams[gZigZag[uc_i]]);
664     }
665 
666     /* Writing the quantization table for chrominance into the stream */
667     fPutBitsToBuffer(&s_streamW, 2, DQT_MARKER);
668 
669     fPutBitsToBuffer(&s_streamW, 3, (LQPQ << 4) | 1); // 20 bits = LQPQ, 4 bits = 1 (Destination identifier for the chrominance quantizer tables)
670 
671     for (uc_i = 0; uc_i < PELS_IN_BLOCK; uc_i++) {
672         // Write zigzag ordered chroma quantization values to our JPEG header
673         fPutBitsToBuffer(&s_streamW, 1, pJPEGContext->psTablesBlock->aui8ChromaQuantParams[gZigZag[uc_i]]);
674     }
675 
676 
677 
678 
679     if (bIncludeHuffmanTables) {
680         /* Writing the huffman tables for luminance dc coeffs */
681         /* Write the DHT Marker */
682         fPutBitsToBuffer(&s_streamW, 2, DHT_MARKER);
683         fPutBitsToBuffer(&s_streamW, 2, LH_DC);
684         for (uc_i = 0; uc_i < LH_DC - 2; uc_i++) {
685             fPutBitsToBuffer(&s_streamW, 1, gMarkerDataLumaDc[uc_i]);
686         }
687         /* Writing the huffman tables for luminance ac coeffs */
688         /* Write the DHT Marker */
689         fPutBitsToBuffer(&s_streamW, 2, DHT_MARKER);
690         fPutBitsToBuffer(&s_streamW, 2, LH_AC);
691         for (uc_i = 0; uc_i < LH_AC - 2; uc_i++) {
692             fPutBitsToBuffer(&s_streamW, 1, gMarkerDataLumaAc[uc_i]);
693         }
694         /* Writing the huffman tables for chrominance dc coeffs */
695         fPutBitsToBuffer(&s_streamW, 2, DHT_MARKER);
696         fPutBitsToBuffer(&s_streamW, 2, LH_DC);
697         for (uc_i = 0; uc_i < LH_DC - 2; uc_i++) {
698             fPutBitsToBuffer(&s_streamW, 1, gMarkerDataChromaDc[uc_i]);
699         }
700         /* Writing the huffman tables for luminance ac coeffs */
701         /* Write the DHT Marker */
702         fPutBitsToBuffer(&s_streamW, 2, DHT_MARKER);
703         fPutBitsToBuffer(&s_streamW, 2, LH_AC);
704         for (uc_i = 0; uc_i < LH_AC - 2; uc_i++) {
705             fPutBitsToBuffer(&s_streamW, 1, gMarkerDataChromaAc[uc_i]);
706         }
707     }
708 
709     // Activate Restart markers
710     if (pJPEGContext->sScan_Encode_Info.ui16CScan > 1) {
711         // Only use restart intervals if we need them (ie. multiple Scan encode and/or parallel CB encode)
712         fPutBitsToBuffer(&s_streamW, 2, 0xFFDD); //Marker header
713         fPutBitsToBuffer(&s_streamW, 2, 4); // Byte size of marker (header not included)
714         fPutBitsToBuffer(&s_streamW, 2, pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan); // Restart Interval (same as MCUs per buffer)
715     }
716 
717     return s_streamW.Offset;
718 }
719 
EncodeFrameHeader(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_UINT8 * puc_stream_buff)720 static IMG_UINT32 EncodeFrameHeader(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext,
721                                     IMG_UINT8 *puc_stream_buff)
722 {
723     STREAMTYPEW ps_streamW;
724     IMG_UINT8  uc_num_comp_in_img;
725 
726     uc_num_comp_in_img = pJPEGContext->pMTXSetup->ui32ComponentsInScan;
727 
728     ps_streamW.Offset = 0;
729     ps_streamW.Buffer = puc_stream_buff;
730 
731 
732     //if(ps_jpeg_params->uc_isAbbreviated != 0)
733     //   fPutBitsToBuffer(&ps_streamW, 2, START_OF_IMAGE);
734 
735     /* Writing the frame header */
736     fPutBitsToBuffer(&ps_streamW, 2, SOF_BASELINE_DCT);
737     /* Frame header length */
738     fPutBitsToBuffer(&ps_streamW, 2, 8 + 3 * uc_num_comp_in_img);
739     /* Precision */
740     fPutBitsToBuffer(&ps_streamW, 1, 8);
741     /* Height : sample lines */
742     fPutBitsToBuffer(&ps_streamW, 2, pJPEGContext->ui32OutputHeight);
743     /* Width : samples per line */
744     fPutBitsToBuffer(&ps_streamW, 2, pJPEGContext->ui32OutputWidth);
745     /* Number of image components */
746     fPutBitsToBuffer(&ps_streamW, 1, uc_num_comp_in_img);
747 
748 
749     //Chroma Details
750     if (pJPEGContext->pMTXSetup->ui16DataInterleaveStatus < C_INTERLEAVE) {
751         //Luma Details
752         /* Component identifier */
753         fPutBitsToBuffer(&ps_streamW, 1, 1); //CompId 0 = 1, 1 = 2, 2 = 3
754         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[0].ui32WidthBlocks >> 3) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[0].ui32HeightBlocks >> 3));
755         fPutBitsToBuffer(&ps_streamW, 1, 0); // 0 = Luma(0), 1,2 = Chroma(1)
756 
757         //Chroma planar
758         fPutBitsToBuffer(&ps_streamW, 1, 2); //CompId 0 = 1, 1 = 2, 2 = 3
759         /* 4 bit Horizontal and 4 bit vertical sampling factors */
760         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[1].ui32WidthBlocks >> 3) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[1].ui32HeightBlocks >> 3));
761         fPutBitsToBuffer(&ps_streamW, 1, 1); // 0 = Luma(0), 1,2 = Chroma(1)
762         fPutBitsToBuffer(&ps_streamW, 1, 3); //CompId 0 = 1, 1 = 2, 2 = 3
763         /* 4 bit Horizontal and 4 bit vertical sampling factors */
764         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[2].ui32WidthBlocks >> 3) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[2].ui32HeightBlocks >> 3));
765         fPutBitsToBuffer(&ps_streamW, 1, 1); // 0 = Luma(0), 1,2 = Chroma(1)
766     } else if (pJPEGContext->pMTXSetup->ui16DataInterleaveStatus == C_INTERLEAVE) {
767         //Luma Details
768         /* Component identifier */
769         fPutBitsToBuffer(&ps_streamW, 1, 1); //CompId 0 = 1, 1 = 2, 2 = 3
770         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[0].ui32WidthBlocks >> 3) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[0].ui32HeightBlocks >> 3));
771         fPutBitsToBuffer(&ps_streamW, 1, 0); // 0 = Luma(0), 1,2 = Chroma(1)
772 
773         // Chroma Interleaved
774         fPutBitsToBuffer(&ps_streamW, 1, 2); //CompId 0 = 1, 1 = 2, 2 = 3
775         /* 4 bit Horizontal and 4 bit vertical sampling factors */
776         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[1].ui32WidthBlocks >> 4) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[1].ui32HeightBlocks >> 3));
777         fPutBitsToBuffer(&ps_streamW, 1, 1); // 0 = Luma(0), 1,2 = Chroma(1)
778 
779         fPutBitsToBuffer(&ps_streamW, 1, 3); //CompId 0 = 1, 1 = 2, 2 = 3
780         /* 4 bit Horizontal and 4 bit vertical sampling factors */
781         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[1].ui32WidthBlocks >> 4) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[1].ui32HeightBlocks >> 3));
782         fPutBitsToBuffer(&ps_streamW, 1, 1); // 0 = Luma(0), 1,2 = Chroma(1)
783     } else {
784         //Luma Details
785         /* Component identifier */
786         fPutBitsToBuffer(&ps_streamW, 1, 1); //CompId 0 = 1, 1 = 2, 2 = 3
787         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[0].ui32WidthBlocks >> 4) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[0].ui32HeightBlocks >> 3));
788         fPutBitsToBuffer(&ps_streamW, 1, 0); // 0 = Luma(0), 1,2 = Chroma(1)
789 
790         //Chroma YUYV - Special case
791         fPutBitsToBuffer(&ps_streamW, 1, 2); //CompId 0 = 1, 1 = 2, 2 = 3
792         /* 4 bit Horizontal and 4 bit vertical sampling factors */
793         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[0].ui32WidthBlocks >> 5) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[0].ui32HeightBlocks >> 3));
794         fPutBitsToBuffer(&ps_streamW, 1, 1); // 0 = Luma(0), 1,2 = Chroma(1)
795         fPutBitsToBuffer(&ps_streamW, 1, 3); //CompId 0 = 1, 1 = 2, 2 = 3
796         /* 4 bit Horizontal and 4 bit vertical sampling factors */
797         fPutBitsToBuffer(&ps_streamW, 1, ((pJPEGContext->pMTXSetup->MCUComponent[0].ui32WidthBlocks >> 5) << 4) | (pJPEGContext->pMTXSetup->MCUComponent[0].ui32HeightBlocks >> 3));
798         fPutBitsToBuffer(&ps_streamW, 1, 1); // 0 = Luma(0), 1,2 = Chroma(1)
799     }
800 
801 
802     //Use if you want start of scan (image data) to align to 32
803     //fPutBitsToBuffer(&ps_streamW, 1, 0xFF);
804 
805     return ps_streamW.Offset;
806 }
807 
JPGEncodeMarker(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_UINT8 * pui8BitStreamBuffer,IMG_UINT32 * pui32BytesWritten,IMG_BOOL bIncludeHuffmanTables)808 static IMG_UINT32 JPGEncodeMarker(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext ,
809                                   IMG_UINT8* pui8BitStreamBuffer ,
810                                   IMG_UINT32 *pui32BytesWritten, IMG_BOOL bIncludeHuffmanTables)
811 {
812 #ifdef JPEG_VERBOSE
813     drv_debug_msg(VIDEO_DEBUG_GENERAL, "PVRJPGEncodeMarker");
814 #endif
815 
816 
817     *pui32BytesWritten += EncodeMarkerSegment(pJPEGContext, pui8BitStreamBuffer + *pui32BytesWritten, bIncludeHuffmanTables);
818 
819     return 0;
820 }
821 
JPGEncodeHeader(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_UINT8 * pui8BitStreamBuffer,IMG_UINT32 * pui32BytesWritten)822 static IMG_UINT32 JPGEncodeHeader(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext,
823                                   IMG_UINT8*      pui8BitStreamBuffer ,
824                                   IMG_UINT32*     pui32BytesWritten)
825 {
826 #ifdef JPEG_VERBOSE
827     drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPGEncodeHeader");
828 #endif
829 
830     *pui32BytesWritten += EncodeFrameHeader(pJPEGContext, pui8BitStreamBuffer + *pui32BytesWritten);
831 
832     return 0;
833 }
834 
JPGEncodeSOSHeader(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_UINT8 * pui8BitStreamBuffer,IMG_UINT32 * pui32BytesWritten)835 static IMG_UINT32 JPGEncodeSOSHeader(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext,
836                                      IMG_UINT8*      pui8BitStreamBuffer ,
837                                      IMG_UINT32*     pui32BytesWritten)
838 {
839     IMG_UINT8 uc_comp_id, ui8Comp;
840     STREAMTYPEW s_streamW;
841 
842     s_streamW.Offset = 0;
843     s_streamW.Buffer = pui8BitStreamBuffer + *pui32BytesWritten;
844 
845     /* Start of scan */
846     fPutBitsToBuffer(&s_streamW, 2, START_OF_SCAN);
847     /* Scan header length */
848     fPutBitsToBuffer(&s_streamW, 2, 6 + (pJPEGContext->pMTXSetup->ui32ComponentsInScan << 1));
849     /* Number of image components in scan */
850     fPutBitsToBuffer(&s_streamW, 1, pJPEGContext->pMTXSetup->ui32ComponentsInScan);
851     for (ui8Comp = 0; ui8Comp < pJPEGContext->pMTXSetup->ui32ComponentsInScan; ui8Comp++) {
852         uc_comp_id = ui8Comp + 1;
853 
854         /* Scan component selector */
855         fPutBitsToBuffer(&s_streamW, 1, uc_comp_id);
856 
857         /*4 Bits Dc entropy coding table destination selector */
858         /*4 Bits Ac entropy coding table destination selector */
859         fPutBitsToBuffer(&s_streamW, 1, ((ui8Comp != 0 ? 1 : 0) << 4) | (ui8Comp != 0 ? 1 : 0)); // Huffman table refs = 0 Luma 1 Chroma
860     }
861 
862     /* Start of spectral or predictor selection  */
863     fPutBitsToBuffer(&s_streamW, 1, 0);
864     /* End of spectral selection */
865     fPutBitsToBuffer(&s_streamW, 1, 63);
866     /*4 Bits Successive approximation bit position high (0)*/
867     /*4 Bits Successive approximation bit position low or point transform (0)*/
868     fPutBitsToBuffer(&s_streamW, 1, 0);
869 
870     *pui32BytesWritten += s_streamW.Offset;
871 
872     return 0;
873 }
874 
InitializeScanCounter(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext)875 static void InitializeScanCounter(TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext)
876 {
877     pJPEGContext->sScan_Encode_Info.ui16SScan =
878         pJPEGContext->sScan_Encode_Info.ui16CScan =
879             pJPEGContext->sScan_Encode_Info.ui16ScansInImage;
880 }
881 
PrepareHeader(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_CODED_BUFFER * pCBuffer,IMG_UINT32 ui32StartOffset,IMG_BOOL bIncludeHuffmanTables)882 static IMG_ERRORCODE PrepareHeader(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext, IMG_CODED_BUFFER *pCBuffer, IMG_UINT32 ui32StartOffset, IMG_BOOL bIncludeHuffmanTables)
883 {
884     IMG_ERRORCODE rc;
885     IMG_UINT8 *ui8OutputBuffer;
886 
887     //Locate our JPEG Coded buffer
888     ui8OutputBuffer = (IMG_UINT8 *)pCBuffer->pMemInfo;
889 
890     pCBuffer->ui32BytesWritten = ui32StartOffset;
891     *((IMG_UINT32*)ui8OutputBuffer + pCBuffer->ui32BytesWritten) = 0;
892 
893     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Before writing headers, ui32BytesWritten: %d\n", pCBuffer->ui32BytesWritten);
894 
895     // JPGEncodeMarker - Currently misses out the APP0 header
896     rc = JPGEncodeMarker(pJPEGContext, (IMG_UINT8 *) ui8OutputBuffer,  &pCBuffer->ui32BytesWritten, bIncludeHuffmanTables);
897     if (rc) return rc;
898     drv_debug_msg(VIDEO_DEBUG_GENERAL, "After JPGEncodeMarker, ui32BytesWritten: %d\n", pCBuffer->ui32BytesWritten);
899 
900     rc = JPGEncodeHeader(pJPEGContext , (IMG_UINT8 *) ui8OutputBuffer ,  &pCBuffer->ui32BytesWritten);
901     if (rc) return rc;
902     drv_debug_msg(VIDEO_DEBUG_GENERAL, "After JPGEncodeHeader, ui32BytesWritten: %d\n", pCBuffer->ui32BytesWritten);
903 
904     rc = JPGEncodeSOSHeader(pJPEGContext, (IMG_UINT8 *) ui8OutputBuffer, &pCBuffer->ui32BytesWritten);
905     if (rc) return rc;
906     drv_debug_msg(VIDEO_DEBUG_GENERAL, "After JPGEncodeSOSHeader, ui32BytesWritten: %d\n", pCBuffer->ui32BytesWritten);
907 
908     return IMG_ERR_OK;
909 }
910 
IssueBufferToHW(TOPAZHP_JPEG_ENCODER_CONTEXT * pJPEGContext,IMG_UINT16 ui16BCnt,IMG_INT8 i8PipeNumber,IMG_UINT32 ui32NoMCUsToEncode)911 static IMG_ERRORCODE IssueBufferToHW(
912     TOPAZHP_JPEG_ENCODER_CONTEXT *pJPEGContext,
913     IMG_UINT16 ui16BCnt,
914     IMG_INT8 i8PipeNumber,
915     IMG_UINT32 ui32NoMCUsToEncode)
916 {
917     MTX_ISSUE_BUFFERS *psBufferCmd;
918     context_ENC_p ctx = (context_ENC_p)(pJPEGContext->ctx);
919     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
920 
921     pJPEGContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui32DataBufferUsedBytes = ((BUFFER_HEADER*)(pJPEGContext->sScan_Encode_Info.aBufferTable[ui16BCnt].pMemInfo))->ui32BytesUsed = -1; // Won't be necessary with SC Peek commands enabled
922 
923     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Submit Scan %d which contains %d MCU in Buffer %d to MTX %d\n",
924                              pJPEGContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber,
925                              ui32NoMCUsToEncode, ui16BCnt, i8PipeNumber);
926 
927     // Issue to MTX ////////////////////////////
928 
929     psBufferCmd = (MTX_ISSUE_BUFFERS *)(pJPEGContext->sScan_Encode_Info.aBufferTable[ui16BCnt].pMemInfo);
930     ASSERT(psBufferCmd);
931 
932     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui16ScansInImage: %d\n", pJPEGContext->sScan_Encode_Info.ui16ScansInImage);
933     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui16ScanNumber: %d\n", pJPEGContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber);
934     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32NumberMCUsToEncodePerScan: %d\n", pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan);
935 
936     psBufferCmd->ui32MCUCntAndResetFlag = (ui32NoMCUsToEncode << 1) | 0x1;
937 
938     psBufferCmd->ui32MCUPositionOfScanAndPipeNo =
939         (((pJPEGContext->sScan_Encode_Info.ui16ScansInImage -
940           pJPEGContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber) *
941          pJPEGContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan)<<2)&(~2);
942 
943     ASSERT(0 == i8PipeNumber);
944     if (i8PipeNumber <= 3)
945         psBufferCmd->ui32MCUPositionOfScanAndPipeNo |= i8PipeNumber;
946 
947     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32MCUPositionOfScanAndPipeNo: 0x%x\n", psBufferCmd->ui32MCUPositionOfScanAndPipeNo);
948     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32MCUCntAndResetFlag: 0x%x\n", psBufferCmd->ui32MCUCntAndResetFlag);
949 
950     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psBufferCmd: 0x%x\n", (unsigned int)(psBufferCmd));
951     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Command Data: 0x%x\n", (unsigned int)(PTG_JPEG_HEADER_MAX_SIZE + ui16BCnt * pJPEGContext->ui32SizePerCodedBuffer));
952 
953     // Issue buffers
954     tng_cmdbuf_insert_command(ctx->obj_context,
955                                       0,
956                                       MTX_CMDID_ISSUEBUFF,
957                                       0,
958                                       ps_buf->coded_buf->psb_buffer,
959                                       PTG_JPEG_HEADER_MAX_SIZE + ui16BCnt * pJPEGContext->ui32SizePerCodedBuffer);
960 
961     return IMG_ERR_OK;
962 }
963 
tng_jpeg_QueryConfigAttributes(VAProfile __maybe_unused profile,VAEntrypoint __maybe_unused entrypoint,VAConfigAttrib * attrib_list,int num_attribs)964 static void tng_jpeg_QueryConfigAttributes(
965     VAProfile __maybe_unused profile,
966     VAEntrypoint __maybe_unused entrypoint,
967     VAConfigAttrib *attrib_list,
968     int num_attribs)
969 {
970     int i;
971 
972     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_QueryConfigAttributes\n");
973 
974     /* Return supported attributes */
975     for (i = 0; i < num_attribs; i++) {
976         switch (attrib_list[i].type) {
977         case VAConfigAttribRTFormat:
978             /* Already handled in psb_GetConfigAttributes */
979             break;
980         case VAConfigAttribEncJPEG:
981             /* The below JPEG ENC capabilities are fixed by TopazHP and not changable. */
982             {
983                 VAConfigAttribValEncJPEG* ptr = (VAConfigAttribValEncJPEG *)&(attrib_list[i].value);
984                 (ptr->bits).arithmatic_coding_mode = 0; /* Unsupported */
985                 (ptr->bits).progressive_dct_mode = 0; /* Unsupported */
986                 (ptr->bits).non_interleaved_mode = 1; /* Supported */
987                 (ptr->bits).differential_mode = 0; /* Unsupported */
988                 (ptr->bits).max_num_components = MTX_MAX_COMPONENTS; /* Only 3 is supported */
989                 (ptr->bits).max_num_scans = PTG_JPEG_MAX_SCAN_NUM;
990                 (ptr->bits).max_num_huffman_tables = 4; /* Only 4 is supported */
991                 (ptr->bits).max_num_huffman_tables = 2; /* Only 2 is supported */
992             }
993             break;
994         case VAConfigAttribMaxPictureWidth:
995         case VAConfigAttribMaxPictureHeight:
996             /* No pure limitation on an image's width or height seperately,
997                as long as the image's MCUs need less than max_num_scans rounds of encoding
998                and a surface of that source size is allocatable. */
999             attrib_list[i].value = 0; /* No pure limitation */
1000             break;
1001         default:
1002             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
1003             break;
1004         }
1005     }
1006 
1007     return;
1008 }
1009 
1010 
tng_jpeg_ValidateConfig(object_config_p obj_config)1011 static VAStatus tng_jpeg_ValidateConfig(
1012     object_config_p obj_config)
1013 {
1014     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_ValidateConfig\n");
1015     int i;
1016     /* Check all attributes */
1017     for (i = 0; i < obj_config->attrib_count; i++) {
1018         switch (obj_config->attrib_list[i].type) {
1019         case VAConfigAttribRTFormat:
1020             /* Ignore */
1021             break;
1022         case VAConfigAttribRateControl:
1023             break;
1024         default:
1025             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
1026         }
1027     }
1028 
1029     return VA_STATUS_SUCCESS;
1030 }
1031 
tng_jpeg_CreateContext(object_context_p obj_context,object_config_p obj_config)1032 static VAStatus tng_jpeg_CreateContext(
1033     object_context_p obj_context,
1034     object_config_p obj_config)
1035 {
1036     int i;
1037     VAStatus vaStatus = VA_STATUS_SUCCESS;
1038     context_ENC_p ctx;
1039     TOPAZHP_JPEG_ENCODER_CONTEXT *jpeg_ctx_p;
1040 
1041     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_CreateContext\n");
1042 
1043     vaStatus = tng_CreateContext(obj_context, obj_config, 1);
1044     if (VA_STATUS_SUCCESS != vaStatus)
1045         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1046 
1047     ctx = (context_ENC_p) obj_context->format_data;
1048     ctx->eCodec = IMG_CODEC_JPEG;
1049 
1050     ASSERT(0 == (ctx->ui16Width % 2));
1051     ASSERT(0 == (ctx->ui16FrameHeight % 2));
1052 
1053     for (i = 0; i < obj_config->attrib_count; i++) {
1054         if (VAConfigAttribRTFormat ==  obj_config->attrib_list[i].type) {
1055             switch (obj_config->attrib_list[i].value) {
1056             case VA_RT_FORMAT_YUV420:
1057                 ctx->eFormat = IMG_CODEC_PL12;
1058                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: NV12 format chose.\n");
1059                 break;
1060             default:
1061                 drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: unsupported YUV format and force it to be NV12!\n");
1062                 ctx->eFormat = IMG_CODEC_PL12;
1063                 break;
1064             }
1065             break;
1066         }
1067     }
1068 
1069     ctx->jpeg_ctx = (TOPAZHP_JPEG_ENCODER_CONTEXT *)calloc(1, sizeof(TOPAZHP_JPEG_ENCODER_CONTEXT));
1070     if (NULL == ctx->jpeg_ctx)
1071         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1072     jpeg_ctx_p = ctx->jpeg_ctx;
1073     jpeg_ctx_p->ctx = ctx;
1074 
1075     memset((void *)jpeg_ctx_p, 0x0, sizeof(jpeg_ctx_p));
1076 
1077     jpeg_ctx_p->NumCores = TOPAZHP_PIPE_NUM;
1078     jpeg_ctx_p->eFormat = ctx->eFormat;
1079     jpeg_ctx_p->ui32OutputWidth = ctx->ui16Width;
1080     jpeg_ctx_p->ui32OutputHeight = ctx->ui16FrameHeight;
1081 
1082     InitializeJpegEncode(jpeg_ctx_p);
1083 
1084     if ((jpeg_ctx_p->sScan_Encode_Info.ui16ScansInImage < 1) ||
1085         (jpeg_ctx_p->sScan_Encode_Info.ui16ScansInImage > PTG_JPEG_MAX_SCAN_NUM)) {
1086         drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG MCU scanning number(%d) is wrong!\n", jpeg_ctx_p->sScan_Encode_Info.ui16ScansInImage);
1087         free(ctx->jpeg_ctx);
1088         ctx->jpeg_ctx = NULL;
1089         return VA_STATUS_ERROR_UNKNOWN;
1090     }
1091 
1092     /*Allocate coded buffers' descripters */
1093     jpeg_ctx_p->sScan_Encode_Info.aBufferTable = (TOPAZHP_JPEG_BUFFER_INFO *)calloc(1, (jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers) * (sizeof(TOPAZHP_JPEG_BUFFER_INFO)));
1094     if (NULL == jpeg_ctx_p->sScan_Encode_Info.aBufferTable)
1095         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1096 
1097     return vaStatus;
1098 }
1099 
1100 
tng_jpeg_DestroyContext(object_context_p obj_context)1101 static void tng_jpeg_DestroyContext(
1102     object_context_p obj_context)
1103 {
1104     context_ENC_p ctx;
1105 
1106     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_DestroyPicture\n");
1107 
1108     ctx = (context_ENC_p)(obj_context->format_data);
1109 
1110     if (ctx->jpeg_ctx) {
1111         if (ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable) {
1112             free(ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable);
1113             ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable = NULL;
1114         }
1115 
1116         free(ctx->jpeg_ctx);
1117     }
1118 
1119     tng_DestroyContext(obj_context, 1);
1120 }
1121 
tng__cmdbuf_lowpower(context_ENC_p ctx)1122 static VAStatus tng__cmdbuf_lowpower(context_ENC_p ctx)
1123 {
1124     VAStatus vaStatus = VA_STATUS_SUCCESS;
1125     tng_cmdbuf_p cmdbuf = ctx->obj_context->tng_cmdbuf;
1126     psb_driver_data_p driver_data = ctx->obj_context->driver_data;
1127 
1128     *cmdbuf->cmd_idx++ =
1129         ((MTX_CMDID_SW_LEAVE_LOWPOWER & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
1130         ((ctx->ui32RawFrameCount  & MTX_CMDWORD_CORE_MASK) << MTX_CMDWORD_CORE_SHIFT) |
1131         (((driver_data->context_id & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
1132 
1133     tng_cmdbuf_insert_command_param(ctx->eCodec);
1134 
1135     return vaStatus;
1136 }
1137 
tng_jpeg_BeginPicture(object_context_p obj_context)1138 static VAStatus tng_jpeg_BeginPicture(
1139     object_context_p obj_context)
1140 {
1141     VAStatus vaStatus = VA_STATUS_SUCCESS;
1142     int ret;
1143     tng_cmdbuf_p cmdbuf;
1144 
1145     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
1146     TOPAZHP_JPEG_ENCODER_CONTEXT *jpeg_ctx_p = ctx->jpeg_ctx;
1147     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
1148     psb_driver_data_p driver_data = ctx->obj_context->driver_data;
1149 
1150     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_BeginPicture: Frame %d\n", ctx->obj_context->frame_count);
1151 
1152 
1153     /* Get the current surface */
1154     ps_buf->src_surface = ctx->obj_context->current_render_target;
1155 
1156 
1157     /* Initialize the command buffer */
1158     ret = tng_context_get_next_cmdbuf(ctx->obj_context);
1159     if (ret) {
1160         drv_debug_msg(VIDEO_DEBUG_ERROR, "get next cmdbuf fail\n");
1161         vaStatus = VA_STATUS_ERROR_UNKNOWN;
1162         return vaStatus;
1163     }
1164     cmdbuf = ctx->obj_context->tng_cmdbuf;
1165 
1166 
1167     //For the first picture of a set to be encoded, need to ask kernel to perpare JPEG encoding
1168     if (ctx->obj_context->frame_count == 0) { /* first picture */
1169 
1170         *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
1171 			     ((ctx->eCodec) << MTX_CMDWORD_CORE_SHIFT) |
1172                              (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
1173         tng_cmdbuf_insert_command_param((ctx->ui16Width << 16) | ctx->ui16FrameHeight);
1174     }
1175 
1176 
1177     /* Map MTX setup buffer */
1178     vaStatus = psb_buffer_map(&cmdbuf->jpeg_header_mem, (unsigned char **)&cmdbuf->jpeg_header_mem_p);
1179     if (vaStatus) {
1180         drv_debug_msg(VIDEO_DEBUG_ERROR, "Fail to map MTX setup buffer\n");
1181         return vaStatus;
1182     }
1183     jpeg_ctx_p->pMemInfoMTXSetup = cmdbuf->jpeg_header_mem_p;
1184     jpeg_ctx_p->pMTXSetup = (JPEG_MTX_DMA_SETUP*)jpeg_ctx_p->pMemInfoMTXSetup;
1185     memset(jpeg_ctx_p->pMemInfoMTXSetup, 0x0, ctx->jpeg_header_mem_size);
1186 
1187 
1188     /* Map MTX setup interface buffer */
1189     vaStatus = psb_buffer_map(&cmdbuf->jpeg_header_interface_mem, (unsigned char **)&cmdbuf->jpeg_header_interface_mem_p);
1190     if (vaStatus) {
1191         drv_debug_msg(VIDEO_DEBUG_ERROR, "Fail to map MTX setup interface buffer\n");
1192         psb_buffer_unmap(&cmdbuf->jpeg_header_mem);
1193         return vaStatus;
1194     }
1195     jpeg_ctx_p->pMemInfoWritebackMemory = cmdbuf->jpeg_header_interface_mem_p;
1196     jpeg_ctx_p->pMTXWritebackMemory = (JPEG_MTX_WRITEBACK_MEMORY*)jpeg_ctx_p->pMemInfoWritebackMemory;
1197     memset(jpeg_ctx_p->pMemInfoWritebackMemory, 0x0, ctx->jpeg_header_interface_mem_size);
1198 
1199 
1200     /* Map quantization table buffer */
1201     vaStatus = psb_buffer_map(&cmdbuf->jpeg_pic_params, (unsigned char **)&cmdbuf->jpeg_pic_params_p);
1202     if (vaStatus) {
1203         drv_debug_msg(VIDEO_DEBUG_ERROR, "Fail to map quantization table buffer\n");
1204         psb_buffer_unmap(&cmdbuf->jpeg_header_mem);
1205         psb_buffer_unmap(&cmdbuf->jpeg_header_interface_mem);
1206         return vaStatus;
1207     }
1208     jpeg_ctx_p->pMemInfoTableBlock = cmdbuf->jpeg_pic_params_p;
1209     jpeg_ctx_p->psTablesBlock = (JPEG_MTX_QUANT_TABLE *)jpeg_ctx_p->pMemInfoTableBlock;
1210     memset(jpeg_ctx_p->pMemInfoTableBlock, 0x0, ctx->jpeg_pic_params_size);
1211 
1212     vaStatus = tng__cmdbuf_lowpower(ctx);
1213     if (vaStatus != VA_STATUS_SUCCESS) {
1214         drv_debug_msg(VIDEO_DEBUG_ERROR, "cmdbuf lowpower\n");
1215     }
1216 
1217     /* Set SetupInterface*/
1218     SetSetupInterface(jpeg_ctx_p);
1219     IssueSetupInterface(jpeg_ctx_p);
1220 
1221     /* Set MTX setup struture */
1222     ret = SetMTXSetup(jpeg_ctx_p, ps_buf->src_surface);
1223     if (ret != IMG_ERR_OK)
1224         return ret;
1225     IssueMTXSetup(jpeg_ctx_p);
1226 
1227     /* Initialize the default quantization tables */
1228     SetDefaultQmatix(jpeg_ctx_p->pMemInfoTableBlock);
1229 
1230     /* Initialize scan counters */
1231     InitializeScanCounter(jpeg_ctx_p);
1232 
1233     tng_cmdbuf_buffer_ref(cmdbuf, &(ctx->obj_context->current_render_target->psb_surface->buf));
1234 
1235     return vaStatus;
1236 }
1237 
ProcessQmatrixParam(context_ENC_p ctx,object_buffer_p obj_buffer)1238 static VAStatus ProcessQmatrixParam(context_ENC_p ctx, object_buffer_p obj_buffer)
1239 {
1240     VAStatus vaStatus = VA_STATUS_SUCCESS;
1241     VAQMatrixBufferJPEG *pBuffer;
1242     JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *)(ctx->jpeg_ctx->psTablesBlock);
1243 
1244     ASSERT(obj_buffer->type == VAQMatrixBufferType);
1245 
1246     pBuffer = (VAQMatrixBufferJPEG *)obj_buffer->buffer_data;
1247 
1248     if (0 != pBuffer->load_lum_quantiser_matrix) {
1249         memcpy(pQMatrix->aui8LumaQuantParams,
1250                pBuffer->lum_quantiser_matrix,
1251                QUANT_TABLE_SIZE_BYTES);
1252     }
1253 
1254     if (0 != pBuffer->load_chroma_quantiser_matrix) {
1255         memcpy(pQMatrix->aui8ChromaQuantParams,
1256                pBuffer->chroma_quantiser_matrix,
1257                QUANT_TABLE_SIZE_BYTES);
1258     }
1259 
1260     free(obj_buffer->buffer_data);
1261     obj_buffer->buffer_data = NULL;
1262 
1263     return vaStatus;
1264 }
1265 
ProcessPictureParam(context_ENC_p ctx,object_buffer_p obj_buffer)1266 static VAStatus ProcessPictureParam(context_ENC_p ctx, object_buffer_p obj_buffer)
1267 {
1268     VAStatus vaStatus = VA_STATUS_SUCCESS;
1269     VAEncPictureParameterBufferJPEG *pBuffer = NULL;
1270     BUFFER_HEADER *pBufHeader = NULL;
1271     TOPAZHP_JPEG_ENCODER_CONTEXT *jpeg_ctx = ctx->jpeg_ctx;
1272     JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *)
1273                                      (ctx->jpeg_ctx->pMemInfoTableBlock);
1274     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
1275     IMG_ERRORCODE rc;
1276 
1277     /* Check the input buffer */
1278     ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
1279     if ((obj_buffer->num_elements != 1) ||
1280         (obj_buffer->size != sizeof(VAEncPictureParameterBufferJPEG))) {
1281         return VA_STATUS_ERROR_UNKNOWN;
1282     }
1283 
1284 
1285     /* Lookup and get coded buffer */
1286     pBuffer = (VAEncPictureParameterBufferJPEG *)obj_buffer->buffer_data;
1287 
1288     /* Parameters checking */
1289     if (((pBuffer->pic_flags).bits.profile != 0) || /* Only "0 - Baseline" is supported */
1290        ((pBuffer->pic_flags).bits.progressive != 0) || /* Only "0 - sequential" is supported */
1291        ((pBuffer->pic_flags).bits.huffman != 1) || /* Only "1 - huffman" is supported */
1292        ((pBuffer->pic_flags).bits.interleaved != 0) || /* Only "0 - non interleaved" is supported */
1293        ((pBuffer->pic_flags).bits.differential != 0)) /* Only "0 - non differential" is supported */
1294         return VA_STATUS_ERROR_INVALID_PARAMETER;
1295 
1296     if ((pBuffer->sample_bit_depth != 8) || /* Only 8-bits sample depth is supported */
1297        (pBuffer->num_components != MTX_MAX_COMPONENTS) || /* Only 3 components setting is supported */
1298        (pBuffer->quality > 100))
1299         return VA_STATUS_ERROR_INVALID_PARAMETER;
1300 
1301     /* Set quality */
1302     if (pBuffer->quality != 0) { /* Quality value is set */
1303         CustomizeQuantizationTables(pQMatrix->aui8LumaQuantParams,
1304                                     pQMatrix->aui8ChromaQuantParams,
1305                                     pBuffer->quality);
1306     }
1307 
1308     ASSERT(ctx->ui16Width == pBuffer->picture_width);
1309     ASSERT(ctx->ui16FrameHeight == pBuffer->picture_height);
1310 
1311     ps_buf->coded_buf = BUFFER(pBuffer->coded_buf);
1312 
1313     free(pBuffer);
1314     obj_buffer->buffer_data = NULL;
1315     obj_buffer->size = 0;
1316 
1317     if (NULL == ps_buf->coded_buf) {
1318         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__);
1319         return VA_STATUS_ERROR_INVALID_BUFFER;
1320     }
1321 
1322     /* Map coded buffer */
1323     vaStatus = psb_buffer_map(ps_buf->coded_buf->psb_buffer, (unsigned char **)&jpeg_ctx->jpeg_coded_buf.pMemInfo);
1324     if (vaStatus) {
1325         drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Map coded_buf failed!");
1326         return vaStatus;
1327     }
1328     jpeg_ctx->jpeg_coded_buf.ui32Size = ps_buf->coded_buf->size;
1329     jpeg_ctx->jpeg_coded_buf.sLock = BUFFER_FREE;
1330     jpeg_ctx->jpeg_coded_buf.ui32BytesWritten = 0;
1331 
1332     if ((jpeg_ctx->jpeg_coded_buf.ui32Size) < (9 + 6 + (4 * 3))) {
1333         return VA_STATUS_ERROR_INVALID_BUFFER;
1334     }
1335 
1336 
1337     /* Assign coded buffer to each scan */
1338     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Assign coded buffer to each scan\n");
1339     AssignCodedDataBuffers(jpeg_ctx);
1340 
1341     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded buffer total size is %d,"
1342                              "coded segment size per scan is %d\n",
1343                              jpeg_ctx->jpeg_coded_buf.ui32Size, jpeg_ctx->ui32SizePerCodedBuffer);
1344 
1345 
1346     /* Write JPEG headers to coded buffer */
1347     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Write JPEG Headers to coded buf\n");
1348 
1349     pBufHeader = (BUFFER_HEADER *)jpeg_ctx->jpeg_coded_buf.pMemInfo;
1350     pBufHeader->ui32BytesUsed = 0; /* Not include BUFFER_HEADER*/
1351 
1352     rc = PrepareHeader(jpeg_ctx, &jpeg_ctx->jpeg_coded_buf, sizeof(BUFFER_HEADER), IMG_TRUE);
1353     if (rc != IMG_ERR_OK)
1354         return VA_STATUS_ERROR_UNKNOWN;
1355 
1356     pBufHeader->ui32Reserved3 = PTG_JPEG_HEADER_MAX_SIZE;//Next coded buffer offset
1357     pBufHeader->ui32BytesUsed = jpeg_ctx->jpeg_coded_buf.ui32BytesWritten - sizeof(BUFFER_HEADER);
1358 
1359     drv_debug_msg(VIDEO_DEBUG_GENERAL, "sizeof(BUFFER_HEADER): %d, ui32BytesUsed :%d, ui32Reserved3: %d, ui32BytesWritten: %d\n",
1360                              sizeof(BUFFER_HEADER), pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3, jpeg_ctx->jpeg_coded_buf.ui32BytesWritten);
1361 
1362     return vaStatus;
1363 }
tng_jpeg_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)1364 static VAStatus tng_jpeg_RenderPicture(
1365     object_context_p obj_context,
1366     object_buffer_p *buffers,
1367     int num_buffers)
1368 {
1369     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
1370     VAStatus vaStatus = VA_STATUS_SUCCESS;
1371     int i;
1372 
1373     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_RenderPicture\n");
1374 
1375     for (i = 0; i < num_buffers; i++) {
1376         object_buffer_p obj_buffer = buffers[i];
1377 
1378         switch (obj_buffer->type) {
1379         case VAQMatrixBufferType:
1380             drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_RenderPicture got VAEncSliceParameterBufferType\n");
1381             vaStatus = ProcessQmatrixParam(ctx, obj_buffer);
1382             DEBUG_FAILURE;
1383             break;
1384         case VAEncPictureParameterBufferType:
1385             drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_RenderPicture got VAEncPictureParameterBufferType\n");
1386             vaStatus = ProcessPictureParam(ctx, obj_buffer);
1387             DEBUG_FAILURE;
1388             break;
1389         case VAEncSliceParameterBufferType:
1390             drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_RenderPicture got VAEncSliceParameterBufferType\n");
1391             drv_debug_msg(VIDEO_DEBUG_WARNING, "VAEncSliceParameterBufferType is ignored on TopazHP\n");
1392             vaStatus = VA_STATUS_SUCCESS;
1393             DEBUG_FAILURE;
1394             break;
1395         default:
1396             vaStatus = VA_STATUS_ERROR_UNKNOWN;
1397             DEBUG_FAILURE;
1398         }
1399     }
1400 
1401     return vaStatus;
1402 }
1403 
tng_jpeg_EndPicture(object_context_p obj_context)1404 static VAStatus tng_jpeg_EndPicture(
1405     object_context_p obj_context)
1406 {
1407     IMG_UINT16 ui16BCnt;
1408     IMG_UINT32 rc = 0;
1409     VAStatus vaStatus = VA_STATUS_SUCCESS;
1410     IMG_UINT32 ui32NoMCUsToEncode = 0;
1411     IMG_UINT32 ui32RemainMCUs = 0;
1412 
1413     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
1414     TOPAZHP_JPEG_ENCODER_CONTEXT *jpeg_ctx_p = ctx->jpeg_ctx;
1415     tng_cmdbuf_p cmdbuf = (tng_cmdbuf_p)ctx->obj_context->tng_cmdbuf;
1416     context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]);
1417     context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
1418 
1419     drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_jpeg_EndPicture\n");
1420 
1421     IssueQmatix(jpeg_ctx_p);
1422 
1423     /* Compute the next scan to be sent */
1424     ui32RemainMCUs = jpeg_ctx_p->sScan_Encode_Info.ui32NumberMCUsToEncode;
1425     drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32RemainMCUs: %d\n", ui32RemainMCUs);
1426 
1427     for (ui16BCnt = 0; (ui16BCnt < jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers)
1428          && (jpeg_ctx_p->sScan_Encode_Info.ui16SScan > 0); ui16BCnt++) {
1429 
1430         jpeg_ctx_p->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber = jpeg_ctx_p->sScan_Encode_Info.ui16SScan--;
1431         jpeg_ctx_p->sScan_Encode_Info.aBufferTable[ui16BCnt].i8PipeNumber =
1432             (1 == jpeg_ctx_p->NumCores) ? 0 : ((ui16BCnt+1) % jpeg_ctx_p->NumCores);
1433 
1434         if (jpeg_ctx_p->sScan_Encode_Info.ui16SScan > 0) {
1435             ui32NoMCUsToEncode = jpeg_ctx_p->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan;
1436         } else {
1437             // Final scan, may need fewer MCUs than buffer size, calculate the remainder
1438             ui32NoMCUsToEncode = ui32RemainMCUs;
1439             jpeg_ctx_p->sScan_Encode_Info.aBufferTable[ui16BCnt].i8PipeNumber = 0;
1440         }
1441 
1442         drv_debug_msg(VIDEO_DEBUG_GENERAL, "ui32NoMCUsToEncode: %d\n", ui32NoMCUsToEncode);
1443         //Send scan to MTX
1444         rc = IssueBufferToHW(jpeg_ctx_p, ui16BCnt,
1445                              jpeg_ctx_p->sScan_Encode_Info.aBufferTable[ui16BCnt].i8PipeNumber,
1446                              ui32NoMCUsToEncode);
1447         if (rc != IMG_ERR_OK) {
1448             vaStatus = VA_STATUS_ERROR_UNKNOWN;
1449             DEBUG_FAILURE;
1450             return vaStatus;
1451         }
1452 
1453         ui32RemainMCUs -= ui32NoMCUsToEncode;
1454     }
1455 
1456 
1457     psb_buffer_unmap(&cmdbuf->jpeg_pic_params);
1458     cmdbuf->jpeg_pic_params_p = NULL;
1459     psb_buffer_unmap(&cmdbuf->jpeg_header_mem);
1460     cmdbuf->jpeg_header_mem_p = NULL;
1461     psb_buffer_unmap(ps_buf->coded_buf->psb_buffer);
1462     jpeg_ctx_p->jpeg_coded_buf.pMemInfo = NULL;
1463 
1464     psb_buffer_unmap(&(ctx->bufs_writeback));
1465 
1466 
1467     //tng__trace_cmdbuf(cmdbuf);
1468 
1469     if (tng_context_flush_cmdbuf(ctx->obj_context)) {
1470         vaStatus = VA_STATUS_ERROR_UNKNOWN;
1471         return vaStatus;
1472     }
1473 
1474     ctx->obj_context->frame_count++;
1475     return VA_STATUS_SUCCESS;
1476 }
1477 
1478 /* Add Restart interval termination (RSTm)to coded buf 1 ~ NumCores-1*/
tng_OutputResetIntervalToCB(IMG_UINT8 * pui8Buf,IMG_UINT8 ui8_marker)1479 static inline VAStatus tng_OutputResetIntervalToCB(IMG_UINT8 *pui8Buf, IMG_UINT8 ui8_marker)
1480 {
1481     if (NULL == pui8Buf)
1482         return VA_STATUS_ERROR_UNKNOWN;
1483     /*Refer to CCITT Rec. T.81 (1992 E), B.2.1*/
1484     /*RSTm: Restart marker conditional marker which is placed between
1485      * entropy-coded segments only if restartis enabled. There are 8 unique
1486      * restart markers (m = 0 - 7) which repeat in sequence from 0 to 7, starting with
1487      * zero for each scan, to provide a modulo 8 restart interval count*/
1488 
1489     *pui8Buf++ = 0xff;
1490     *pui8Buf = (ui8_marker & 0x7) | 0xD0;
1491 
1492     return 0;
1493 }
1494 
tng_jpeg_AppendMarkers(object_context_p obj_context,void * raw_coded_buf)1495 VAStatus tng_jpeg_AppendMarkers(object_context_p obj_context, void *raw_coded_buf)
1496 {
1497     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
1498     TOPAZHP_JPEG_ENCODER_CONTEXT *jpeg_ctx_p = ctx->jpeg_ctx;
1499 
1500     IMG_UINT16 ui16BCnt;
1501     BUFFER_HEADER* pBufHeader;
1502     STREAMTYPEW s_streamW;
1503     void *pSegStart = raw_coded_buf;
1504 
1505     if (pSegStart == NULL) {
1506         return VA_STATUS_ERROR_UNKNOWN;
1507     }
1508 
1509     pBufHeader = (BUFFER_HEADER *)pSegStart;
1510 
1511     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of Coded buffers %d, Per Coded Buffer size : %d\n",
1512                              jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers,
1513                              jpeg_ctx_p->ui32SizePerCodedBuffer);
1514 
1515     /*The first part of coded buffer contains JPEG headers*/
1516     pBufHeader->ui32Reserved3 = PTG_JPEG_HEADER_MAX_SIZE;
1517     jpeg_ctx_p->jpeg_coded_buf.ui32BytesWritten = 0;
1518 
1519     for (ui16BCnt = 0;
1520          ui16BCnt < jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers;
1521          ui16BCnt++) {
1522         pBufHeader = (BUFFER_HEADER *)pSegStart;
1523         pBufHeader->ui32Reserved3 =
1524             PTG_JPEG_HEADER_MAX_SIZE + jpeg_ctx_p->ui32SizePerCodedBuffer * ui16BCnt ;
1525 
1526         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded Buffer Part %d, size %d, next part offset: %d\n",
1527                                  ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
1528 
1529         if (ui16BCnt > 0) {
1530             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Append 2 bytes Reset Interval %d "
1531                                      "to Coded Buffer Part %d\n", ui16BCnt - 1, ui16BCnt);
1532 
1533             // OUTPUT RESTART INTERVAL TO CODED BUFFER
1534             tng_OutputResetIntervalToCB(
1535                 (IMG_UINT8 *)((IMG_UINT32)pSegStart + sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed),
1536                 ui16BCnt - 1);
1537 
1538             pBufHeader->ui32BytesUsed += 2;
1539         }
1540 
1541         jpeg_ctx_p->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed;
1542         pSegStart = (void *)((IMG_UINT32)raw_coded_buf + pBufHeader->ui32Reserved3);
1543     }
1544 
1545     pBufHeader = (BUFFER_HEADER *)pSegStart;
1546     pBufHeader->ui32Reserved3 = 0; /*Last Part of Coded Buffer*/
1547     jpeg_ctx_p->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed;
1548 
1549     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded Buffer Part %d, size %d, next part offset: %d\n",
1550                              ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
1551 
1552     s_streamW.Buffer = pSegStart;
1553     s_streamW.Offset = (sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed);
1554 
1555     fPutBitsToBuffer(&s_streamW, 2, END_OF_IMAGE);
1556 
1557     pBufHeader->ui32BytesUsed += 2;
1558     jpeg_ctx_p->jpeg_coded_buf.ui32BytesWritten += 2;
1559 
1560     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Add two bytes to last part of coded buffer,"
1561                              " total: %d\n", jpeg_ctx_p->jpeg_coded_buf.ui32BytesWritten);
1562     return VA_STATUS_SUCCESS;
1563 }
1564 
1565 struct format_vtable_s tng_JPEGES_vtable = {
1566 queryConfigAttributes:
1567     tng_jpeg_QueryConfigAttributes,
1568 validateConfig:
1569     tng_jpeg_ValidateConfig,
1570 createContext:
1571     tng_jpeg_CreateContext,
1572 destroyContext:
1573     tng_jpeg_DestroyContext,
1574 beginPicture:
1575     tng_jpeg_BeginPicture,
1576 renderPicture:
1577     tng_jpeg_RenderPicture,
1578 endPicture:
1579     tng_jpeg_EndPicture
1580 };
1581