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
45static 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/******************************************************************************
104General 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/******************************************************************************
113JPEG 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
140static 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/*****************************************************************************/
159static 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/*****************************************************************************/
175static 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/*****************************************************************************/
196static 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/*****************************************************************************/
213static 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/*****************************************************************************/
244static 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/*****************************************************************************/
262static 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
284static 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
315static 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
324static 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
359static 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
468static 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
498static 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
508static 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
529static 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
591static 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
629static 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
643static 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
720static 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
808static 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
822static 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
835static 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
875static 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
882static 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
911static 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
964static 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
1011static 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
1032static 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
1101static 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
1122static 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
1138static 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
1238static 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
1266static 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}
1364static 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
1404static 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*/
1479static 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
1495VAStatus 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
1565struct format_vtable_s tng_JPEGES_vtable = {
1566queryConfigAttributes:
1567    tng_jpeg_QueryConfigAttributes,
1568validateConfig:
1569    tng_jpeg_ValidateConfig,
1570createContext:
1571    tng_jpeg_CreateContext,
1572destroyContext:
1573    tng_jpeg_DestroyContext,
1574beginPicture:
1575    tng_jpeg_BeginPicture,
1576renderPicture:
1577    tng_jpeg_RenderPicture,
1578endPicture:
1579    tng_jpeg_EndPicture
1580};
1581