Home | History | Annotate | Download | only in src
      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 (at) 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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 }
   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 
   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*/
   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 
   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