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 
     31 #include <stdlib.h>
     32 #include <stdint.h>
     33 #include <string.h>
     34 
     35 #include "psb_def.h"
     36 #include "psb_drv_debug.h"
     37 #include "psb_surface.h"
     38 #include "psb_cmdbuf.h"
     39 #include "pnw_jpeg.h"
     40 #include "pnw_hostcode.h"
     41 #include "pnw_hostheader.h"
     42 #include "pnw_hostjpeg.h"
     43 
     44 #define INIT_CONTEXT_JPEG       context_ENC_p ctx = (context_ENC_p) obj_context->format_data
     45 #define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
     46 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
     47 
     48 /*
     49   Balancing the workloads of executing MTX_CMDID_ISSUEBUFF commands to 2-cores:
     50   1 commands: 0 (0b/0x0)
     51   2 commands: 1-0 (01b/0x1)
     52   3 commands: 1-0-0 (001b/0x1)
     53   4 commands: 1-0-1-0 (0101b/0x5)
     54   5 commands: 1-0-1-0-0 (00101b/0x5)
     55   6 commands: 1-0-1-0-1-0 (010101b/0x15)
     56   7 commands: 1-0-1-0-1-0-0 (0010101b/0x15)
     57 */
     58 static const uint32_t aui32_jpg_mtx_num[PNW_JPEG_MAX_SCAN_NUM] = {0x0, 0x1, 0x1, 0x5, 0x5, 0x15, 0x15};
     59 
     60 static void pnw_jpeg_QueryConfigAttributes(
     61     VAProfile __maybe_unused profile,
     62     VAEntrypoint __maybe_unused entrypoint,
     63     VAConfigAttrib *attrib_list,
     64     int num_attribs)
     65 {
     66     int i;
     67 
     68     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_QueryConfigAttributes\n");
     69 
     70     /* RateControl attributes */
     71     for (i = 0; i < num_attribs; i++) {
     72         switch (attrib_list[i].type) {
     73         case VAConfigAttribRTFormat:
     74             /* Already handled in psb_GetConfigAttributes */
     75             break;
     76         case VAConfigAttribEncJPEG:
     77             /* The below JPEG ENC capabilities are fixed by TopazSC and not changable. */
     78             {
     79                 VAConfigAttribValEncJPEG* ptr = (VAConfigAttribValEncJPEG *)&(attrib_list[i].value);
     80                 (ptr->bits).arithmatic_coding_mode = 0; /* Unsupported */
     81                 (ptr->bits).progressive_dct_mode = 0; /* Unsupported */
     82                 (ptr->bits).non_interleaved_mode = 1; /* Supported */
     83                 (ptr->bits).differential_mode = 0; /* Unsupported */
     84                 (ptr->bits).max_num_components = PNW_JPEG_COMPONENTS_NUM; /* Only 3 is supported */
     85                 (ptr->bits).max_num_scans = PNW_JPEG_MAX_SCAN_NUM;
     86                 (ptr->bits).max_num_huffman_tables = 4; /* Only 4 is supported */
     87                 (ptr->bits).max_num_huffman_tables = 2; /* Only 2 is supported */
     88             }
     89             break;
     90         case VAConfigAttribMaxPictureWidth:
     91         case VAConfigAttribMaxPictureHeight:
     92             /* No pure limitation on an image's width or height seperately,
     93                as long as the image's MCUs need less than max_num_scans rounds of encoding
     94                and a surface of that source size is allocatable. */
     95             attrib_list[i].value = 0; /* No pure limitation */
     96             break;
     97         default:
     98             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
     99             break;
    100         }
    101     }
    102 
    103     return;
    104 }
    105 
    106 
    107 static VAStatus pnw_jpeg_ValidateConfig(
    108     object_config_p obj_config)
    109 {
    110     int i;
    111     /* Check all attributes */
    112     for (i = 0; i < obj_config->attrib_count; i++) {
    113         switch (obj_config->attrib_list[i].type) {
    114         case VAConfigAttribRTFormat:
    115             /* Ignore */
    116             break;
    117         case VAConfigAttribRateControl:
    118             break;
    119         default:
    120             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
    121         }
    122     }
    123 
    124     return VA_STATUS_SUCCESS;
    125 
    126 }
    127 
    128 /*Init JPEG context. Ported from IMG_JPEG_EncoderInitialise*/
    129 static VAStatus pnw_jpeg_CreateContext(
    130     object_context_p obj_context,
    131     object_config_p obj_config)
    132 {
    133     VAStatus vaStatus = VA_STATUS_SUCCESS;
    134     context_ENC_p ctx;
    135     TOPAZSC_JPEG_ENCODER_CONTEXT *jpeg_ctx_p;
    136     int i;
    137 
    138     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_CreateContext\n");
    139 
    140     vaStatus = pnw_CreateContext(obj_context, obj_config, 1);
    141     if (VA_STATUS_SUCCESS != vaStatus)
    142         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    143 
    144     ctx = (context_ENC_p) obj_context->format_data;
    145 
    146     ctx->eCodec = IMG_CODEC_JPEG;
    147 
    148     for (i = 0; i < obj_config->attrib_count; i++) {
    149         if (VAConfigAttribRTFormat ==  obj_config->attrib_list[i].type) {
    150             switch (obj_config->attrib_list[i].value) {
    151             case VA_RT_FORMAT_YUV420:
    152                 if (obj_context->render_targets != NULL) {
    153                     object_surface_p surface_p = SURFACE(obj_context->render_targets[0]);
    154                     if (NULL == surface_p) {
    155                         ctx->eFormat = IMG_CODEC_PL12;
    156                         drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n");
    157                         break;
    158                     }
    159 
    160                     if ((surface_p->psb_surface)->extra_info[4] == VA_FOURCC_NV12) {
    161                         ctx->eFormat = IMG_CODEC_PL12;
    162                         drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: Choose NV12 format\n");
    163                     }
    164                     else if ((surface_p->psb_surface)->extra_info[4] == VA_FOURCC_IYUV) {
    165                         ctx->eFormat = IMG_CODEC_IYUV;
    166                         drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: Choose IYUV format\n");
    167                     }
    168                     else {
    169                         ctx->eFormat = IMG_CODEC_PL12;
    170                         drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n");
    171                     }
    172                 }
    173                 else {
    174                     ctx->eFormat = IMG_CODEC_PL12;
    175                     drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n");
    176                 }
    177                 break;
    178             case VA_RT_FORMAT_YUV422:
    179                 ctx->eFormat = IMG_CODEC_YV16;
    180                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: Choose YUV422 format\n");
    181                 break;
    182             default:
    183                 ctx->eFormat = IMG_CODEC_PL12;
    184                 drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n");
    185                 break;
    186             }
    187             break;
    188         }
    189     }
    190 
    191     ctx->Slices = 2;
    192     ctx->ParallelCores = 2;
    193     ctx->NumCores = 2;
    194     ctx->jpeg_ctx = (TOPAZSC_JPEG_ENCODER_CONTEXT *)calloc(1, sizeof(TOPAZSC_JPEG_ENCODER_CONTEXT));
    195     CHECK_ALLOCATION(ctx->jpeg_ctx);
    196 
    197     jpeg_ctx_p = ctx->jpeg_ctx;
    198     jpeg_ctx_p->eFormat = ctx->eFormat;
    199 
    200     /*Chroma sampling step x_step X y_step*/
    201     jpeg_ctx_p->ui8ScanNum = JPEG_SCANNING_COUNT(ctx->Width, ctx->Height, ctx->NumCores, jpeg_ctx_p->eFormat);
    202 
    203     if (jpeg_ctx_p->ui8ScanNum < 2 || jpeg_ctx_p->ui8ScanNum > PNW_JPEG_MAX_SCAN_NUM) {
    204         drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG MCU scanning number(%d) is wrong!\n", jpeg_ctx_p->ui8ScanNum);
    205         free(ctx->jpeg_ctx);
    206         ctx->jpeg_ctx = NULL;
    207         return VA_STATUS_ERROR_UNKNOWN;
    208     }
    209 
    210     jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers = jpeg_ctx_p->ui8ScanNum;
    211 
    212     drv_debug_msg(VIDEO_DEBUG_GENERAL, " JPEG Scanning Number %d\n", jpeg_ctx_p->ui8ScanNum);
    213     jpeg_ctx_p->sScan_Encode_Info.aBufferTable =
    214         (TOPAZSC_JPEG_BUFFER_INFO *)calloc(1, sizeof(TOPAZSC_JPEG_BUFFER_INFO)
    215                                            * jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers);
    216 
    217     if (NULL == jpeg_ctx_p->sScan_Encode_Info.aBufferTable)
    218         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    219 
    220     /*It will be figured out when known the size of whole coded buffer.*/
    221     jpeg_ctx_p->ui32SizePerCodedBuffer = 0;
    222 
    223     jpeg_ctx_p->ctx = (unsigned char *)ctx;
    224     /*Reuse header_mem(76*4 bytes) and pic_params_size(256 bytes)
    225      *  as pMemInfoMTXSetup(JPEG_MTX_DMA_SETUP 24x4 bytes) and
    226      *  pMemInfoTableBlock JPEG_MTX_QUANT_TABLE(128byes)*/
    227     return vaStatus;
    228 }
    229 
    230 
    231 static void pnw_jpeg_DestroyContext(
    232     object_context_p obj_context)
    233 {
    234     context_ENC_p ctx;
    235 
    236     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_DestroyPicture\n");
    237 
    238     ctx = (context_ENC_p)(obj_context->format_data);
    239 
    240     if (ctx->jpeg_ctx) {
    241         if (ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable) {
    242             free(ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable);
    243             ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable = NULL;
    244         }
    245 
    246         free(ctx->jpeg_ctx);
    247     }
    248     pnw_DestroyContext(obj_context);
    249 
    250 }
    251 
    252 static VAStatus pnw_jpeg_BeginPicture(
    253     object_context_p obj_context)
    254 {
    255     INIT_CONTEXT_JPEG;
    256     VAStatus vaStatus = VA_STATUS_SUCCESS;
    257     int ret;
    258     pnw_cmdbuf_p cmdbuf;
    259 
    260     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_BeginPicture: Frame %d\n", ctx->obj_context->frame_count);
    261 
    262     ctx->src_surface = ctx->obj_context->current_render_target;
    263 
    264     /* Initialise the command buffer */
    265     ret = pnw_context_get_next_cmdbuf(ctx->obj_context);
    266     if (ret) {
    267         drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
    268         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    269         return vaStatus;
    270     }
    271     cmdbuf = ctx->obj_context->pnw_cmdbuf;
    272 
    273     /* map start_pic param */
    274     vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p);
    275     if (vaStatus) {
    276         return vaStatus;
    277     }
    278     vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p);
    279     if (vaStatus) {
    280         psb_buffer_unmap(&cmdbuf->pic_params);
    281         return vaStatus;
    282     }
    283 
    284     memset(ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable, 0,
    285            sizeof(TOPAZSC_JPEG_BUFFER_INFO) * ctx->jpeg_ctx->sScan_Encode_Info.ui8NumberOfCodedBuffers);
    286 
    287     /*Store the QMatrix data*/
    288     ctx->jpeg_ctx->pMemInfoTableBlock = cmdbuf->pic_params_p;
    289     ctx->jpeg_ctx->psTablesBlock = (JPEG_MTX_QUANT_TABLE *)ctx->jpeg_ctx->pMemInfoTableBlock;
    290 
    291     /*Store MTX_SETUP data*/
    292     ctx->jpeg_ctx->pMemInfoMTXSetup = cmdbuf->header_mem_p;
    293     ctx->jpeg_ctx->pMTXSetup = (JPEG_MTX_DMA_SETUP*)ctx->jpeg_ctx->pMemInfoMTXSetup;
    294 
    295     ctx->jpeg_ctx->pMTXSetup->ui32ComponentsInScan = PNW_JPEG_COMPONENTS_NUM;
    296 
    297     if (ctx->obj_context->frame_count == 0) { /* first picture */
    298 
    299         psb_driver_data_p driver_data = ctx->obj_context->driver_data;
    300 
    301         *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
    302                              (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
    303         pnw_cmdbuf_insert_command_param(ctx->eCodec);
    304         pnw_cmdbuf_insert_command_param((ctx->Width << 16) | ctx->Height);
    305     }
    306 
    307     pnw_jpeg_set_default_qmatix(ctx->jpeg_ctx->pMemInfoTableBlock);
    308 
    309     return vaStatus;
    310 }
    311 
    312 static VAStatus pnw__jpeg_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer)
    313 {
    314     VAStatus vaStatus = VA_STATUS_SUCCESS;
    315     VAEncPictureParameterBufferJPEG *pBuffer;
    316     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
    317     BUFFER_HEADER *pBufHeader;
    318     //unsigned long *pPictureHeaderMem;
    319     //MTX_HEADER_PARAMS *psPicHeader;
    320     int i;
    321     TOPAZSC_JPEG_ENCODER_CONTEXT *jpeg_ctx = ctx->jpeg_ctx;
    322     JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *)
    323                                      (ctx->jpeg_ctx->pMemInfoTableBlock);
    324     IMG_ERRORCODE rc;
    325 
    326     ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
    327 
    328     if ((obj_buffer->num_elements != 1) ||
    329         (obj_buffer->size != sizeof(VAEncPictureParameterBufferJPEG))) {
    330         return VA_STATUS_ERROR_UNKNOWN;
    331     }
    332 
    333     /* Transfer ownership of VAEncPictureParameterBufferMPEG4 data */
    334     pBuffer = (VAEncPictureParameterBufferJPEG *) obj_buffer->buffer_data;
    335     obj_buffer->buffer_data = NULL;
    336     obj_buffer->size = 0;
    337 
    338     /* Parameters checking */
    339     if (((pBuffer->pic_flags).bits.profile != 0) || /* Only "0 - Baseline" is supported */
    340        ((pBuffer->pic_flags).bits.progressive != 0) || /* Only "0 - sequential" is supported */
    341        ((pBuffer->pic_flags).bits.huffman != 1) || /* Only "1 - huffman" is supported */
    342        ((pBuffer->pic_flags).bits.interleaved != 0) || /* Only "0 - non interleaved" is supported */
    343        ((pBuffer->pic_flags).bits.differential != 0)) /* Only "0 - non differential" is supported */
    344         return VA_STATUS_ERROR_INVALID_PARAMETER;
    345 
    346     if ((pBuffer->sample_bit_depth != 8) || /* Only 8-bits sample depth is supported */
    347        (pBuffer->num_components != PNW_JPEG_COMPONENTS_NUM) || /* Only 3 components setting is supported */
    348        (pBuffer->quality > 100))
    349         return VA_STATUS_ERROR_INVALID_PARAMETER;
    350 
    351     /* Set quality */
    352     if (pBuffer->quality != 0) { /* Quality value is set */
    353         customize_quantization_tables(pQMatrix->aui8LumaQuantParams,
    354                                       pQMatrix->aui8ChromaQuantParams,
    355                                       pBuffer->quality);
    356     }
    357 
    358     /* Get the width and height of encode destination */
    359     jpeg_ctx->ui32OutputWidth = (unsigned short)(~0x1 & (pBuffer->picture_width + 0x1));
    360     jpeg_ctx->ui32OutputHeight = (unsigned short)(~0x1 & (pBuffer->picture_height + 0x1));
    361 
    362     ASSERT(ctx->Width >= jpeg_ctx->ui32OutputWidth);
    363     ASSERT(ctx->Height >= jpeg_ctx->ui32OutputHeight);
    364 
    365     /*Overwrite the scan info if destination's sizes are different from source's */
    366     if ((ctx->Width!=jpeg_ctx->ui32OutputWidth) || (ctx->Height!=jpeg_ctx->ui32OutputHeight)) {
    367         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overwriting the scan info...\n");
    368 
    369         jpeg_ctx->ui8ScanNum = JPEG_SCANNING_COUNT(jpeg_ctx->ui32OutputWidth, jpeg_ctx->ui32OutputHeight, ctx->NumCores, jpeg_ctx->eFormat);
    370 
    371         if (jpeg_ctx->ui8ScanNum < 2 || jpeg_ctx->ui8ScanNum > PNW_JPEG_MAX_SCAN_NUM) {
    372             drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG MCU scanning number(%d) is wrong!\n", jpeg_ctx->ui8ScanNum);
    373             free(ctx->jpeg_ctx);
    374             ctx->jpeg_ctx = NULL;
    375             return VA_STATUS_ERROR_UNKNOWN;
    376     	}
    377 
    378         drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG Scanning Number %d\n", jpeg_ctx->ui8ScanNum);
    379         jpeg_ctx->sScan_Encode_Info.ui8NumberOfCodedBuffers = jpeg_ctx->ui8ScanNum;
    380     }
    381 
    382     ctx->coded_buf = BUFFER(pBuffer->coded_buf);
    383     free(pBuffer);
    384 
    385     if (NULL == ctx->coded_buf) {
    386         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__);
    387         return VA_STATUS_ERROR_INVALID_BUFFER;
    388     }
    389 
    390     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Set Quant Tables\n");
    391     /*Set Quant Tables*/
    392     for (i = ctx->NumCores - 1; i >= 0; i--)
    393         pnw_cmdbuf_insert_command_package(ctx->obj_context,
    394                                           i,
    395                                           MTX_CMDID_SETQUANT,
    396                                           &cmdbuf->pic_params,
    397                                           0);
    398 
    399     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Quant Table \n");
    400 
    401     for (i=0; i<128; i+=8) {
    402         if (0 == i) {
    403             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Table 0:\n");
    404         }
    405         else if (64 == i) {
    406             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Table 1:\n");
    407         }
    408         drv_debug_msg(VIDEO_DEBUG_GENERAL, "%d %d %d %d %d %d %d %d\n",
    409                       *((unsigned char *)cmdbuf->pic_params_p+i),
    410                       *((unsigned char *)cmdbuf->pic_params_p+i+1),
    411                       *((unsigned char *)cmdbuf->pic_params_p+i+2),
    412                       *((unsigned char *)cmdbuf->pic_params_p+i+3),
    413                       *((unsigned char *)cmdbuf->pic_params_p+i+4),
    414                       *((unsigned char *)cmdbuf->pic_params_p+i+5),
    415                       *((unsigned char *)cmdbuf->pic_params_p+i+6),
    416                       *((unsigned char *)cmdbuf->pic_params_p+i+7));
    417     }
    418 
    419     jpeg_ctx->ui32SizePerCodedBuffer =
    420         JPEG_CODED_BUF_SEGMENT_SIZE(ctx->coded_buf->size,
    421                                     jpeg_ctx->ui32OutputWidth, jpeg_ctx->ui32OutputHeight,
    422                                     ctx->NumCores, jpeg_ctx->eFormat);
    423     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded buffer total size is %d,"
    424                              "coded segment size per scan is %d\n",
    425                              ctx->coded_buf->size, jpeg_ctx->ui32SizePerCodedBuffer);
    426 
    427     vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, (unsigned char **)&jpeg_ctx->jpeg_coded_buf.pMemInfo);
    428     if (vaStatus) {
    429         drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Map coded_buf failed!");
    430         return vaStatus;
    431     }
    432     jpeg_ctx->jpeg_coded_buf.ui32Size = ctx->coded_buf->size;
    433     jpeg_ctx->jpeg_coded_buf.sLock = BUFFER_FREE;
    434     jpeg_ctx->jpeg_coded_buf.ui32BytesWritten = 0;
    435 
    436     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Setup JPEG Tables\n");
    437     rc = SetupJPEGTables(ctx->jpeg_ctx, &jpeg_ctx->jpeg_coded_buf,  ctx->src_surface);
    438 
    439     if (rc != IMG_ERR_OK)
    440         return VA_STATUS_ERROR_UNKNOWN;
    441 
    442     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Write JPEG Headers to coded buf\n");
    443 
    444     pBufHeader = (BUFFER_HEADER *)jpeg_ctx->jpeg_coded_buf.pMemInfo;
    445     pBufHeader->ui32BytesUsed = 0; /* Not include BUFFER_HEADER*/
    446     rc = PrepareHeader(jpeg_ctx, &jpeg_ctx->jpeg_coded_buf, sizeof(BUFFER_HEADER), IMG_TRUE);
    447     if (rc != IMG_ERR_OK)
    448         return VA_STATUS_ERROR_UNKNOWN;
    449 
    450     pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE;//Next coded buffer offset
    451     pBufHeader->ui32BytesUsed = jpeg_ctx->jpeg_coded_buf.ui32BytesWritten - sizeof(BUFFER_HEADER);
    452 
    453     drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG Buffer Header size: %d, File Header size :%d, next codef buffer offset: %d\n",
    454                              sizeof(BUFFER_HEADER), pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
    455     return vaStatus;
    456 }
    457 
    458 static VAStatus pnw__jpeg_process_qmatrix_param(context_ENC_p ctx, object_buffer_p obj_buffer)
    459 {
    460     VAStatus vaStatus = VA_STATUS_SUCCESS;
    461     VAQMatrixBufferJPEG *pBuffer;
    462     JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *)
    463                                      (ctx->jpeg_ctx->pMemInfoTableBlock);
    464     int i;
    465 
    466     ASSERT(obj_buffer->type == VAQMatrixBufferType);
    467 
    468     pBuffer = (VAQMatrixBufferJPEG *) obj_buffer->buffer_data;
    469 
    470     /* Zero value isn't allowed. It will cause JPEG firmware time out */
    471     if (0 != pBuffer->load_lum_quantiser_matrix) {
    472         for (i=0; i<QUANT_TABLE_SIZE_BYTES; ++i)
    473             if (pBuffer->lum_quantiser_matrix[i] != 0)
    474                 pQMatrix->aui8LumaQuantParams[i] =
    475                     pBuffer->lum_quantiser_matrix[i];
    476     }
    477 
    478     if (0 != pBuffer->load_chroma_quantiser_matrix) {
    479         for (i=0; i<QUANT_TABLE_SIZE_BYTES; ++i)
    480             if (pBuffer->chroma_quantiser_matrix[i] != 0)
    481                 pQMatrix->aui8ChromaQuantParams[i] =
    482                     pBuffer->chroma_quantiser_matrix[i];
    483     }
    484 
    485     free(obj_buffer->buffer_data);
    486     obj_buffer->buffer_data = NULL;
    487 
    488     return vaStatus;
    489 }
    490 
    491 
    492 static VAStatus pnw_jpeg_RenderPicture(
    493     object_context_p obj_context,
    494     object_buffer_p *buffers,
    495     int num_buffers)
    496 {
    497     INIT_CONTEXT_JPEG;
    498     VAStatus vaStatus = VA_STATUS_SUCCESS;
    499     int i;
    500 
    501     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture\n");
    502 
    503     for (i = 0; i < num_buffers; i++) {
    504         object_buffer_p obj_buffer = buffers[i];
    505 
    506         switch (obj_buffer->type) {
    507         case VAQMatrixBufferType:
    508             drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture got VAQMatrixBufferType\n");
    509             vaStatus = pnw__jpeg_process_qmatrix_param(ctx, obj_buffer);
    510             DEBUG_FAILURE;
    511             break;
    512         case VAEncPictureParameterBufferType:
    513             drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture got VAEncPictureParameterBufferType\n");
    514             vaStatus = pnw__jpeg_process_picture_param(ctx, obj_buffer);
    515             DEBUG_FAILURE;
    516             break;
    517         case VAEncSliceParameterBufferType:
    518             drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture got VAEncSliceParameterBufferJPEG\n");
    519             drv_debug_msg(VIDEO_DEBUG_WARNING, "VAEncSliceParameterBufferJPEG is ignored on TopazSC\n");
    520             vaStatus = VA_STATUS_SUCCESS;
    521             DEBUG_FAILURE;
    522             break;
    523         default:
    524             vaStatus = VA_STATUS_ERROR_UNKNOWN;
    525             DEBUG_FAILURE;
    526         }
    527     }
    528 
    529     return vaStatus;
    530 }
    531 
    532 /* Add Restart interval termination (RSTm)to coded buf 1 ~ NumCores-1*/
    533 static inline VAStatus pnw_OutputResetIntervalToCB(IMG_UINT8 *pui8Buf, IMG_UINT8 ui8_marker)
    534 {
    535     if (NULL == pui8Buf)
    536         return VA_STATUS_ERROR_UNKNOWN;
    537     /*Refer to CCITT Rec. T.81 (1992 E), B.2.1*/
    538     /*RSTm: Restart marker conditional marker which is placed between
    539      * entropy-coded segments only if restartis enabled. There are 8 unique
    540      * restart markers (m = 0 - 7) which repeat in sequence from 0 to 7, starting with
    541      * zero for each scan, to provide a modulo 8 restart interval count*/
    542     *pui8Buf++ = 0xff;
    543     *pui8Buf = (ui8_marker | 0xd0);
    544     return 0;
    545 }
    546 
    547 
    548 static VAStatus pnw_jpeg_EndPicture(
    549     object_context_p obj_context)
    550 {
    551     INIT_CONTEXT_JPEG;
    552     IMG_UINT16 ui16BCnt;
    553     TOPAZSC_JPEG_ENCODER_CONTEXT *pContext = ctx->jpeg_ctx;
    554     IMG_UINT32 rc = 0;
    555     pnw_cmdbuf_p cmdbuf = (pnw_cmdbuf_p)ctx->obj_context->pnw_cmdbuf;
    556     VAStatus vaStatus = VA_STATUS_SUCCESS;
    557     IMG_UINT32 ui32NoMCUsToEncode;
    558     IMG_UINT32 ui32RemainMCUs;
    559 
    560     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_EndPicture\n");
    561 
    562     ui32RemainMCUs = pContext->sScan_Encode_Info.ui32NumberMCUsToEncode;
    563 
    564     for (ui16BCnt = 0; ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers
    565          && pContext->sScan_Encode_Info.ui16SScan > 0; ui16BCnt++) {
    566         pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber =
    567             pContext->sScan_Encode_Info.ui16SScan--;
    568 	if (pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers < 2 ||
    569 		pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers > PNW_JPEG_MAX_SCAN_NUM) {
    570 	    vaStatus = VA_STATUS_ERROR_UNKNOWN;
    571             DEBUG_FAILURE;
    572             return vaStatus;
    573 	}
    574         /*i8MTXNumber is the core number.*/
    575         pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].i8MTXNumber =
    576             (aui32_jpg_mtx_num[pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers - 1]
    577              >> ui16BCnt) & 0x1;
    578 
    579         if (pContext->sScan_Encode_Info.ui16SScan == 0) {
    580             ui32NoMCUsToEncode = ui32RemainMCUs;
    581             // Final scan, may need fewer MCUs than buffer size, calculate the remainder
    582         } else
    583             ui32NoMCUsToEncode = pContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan;
    584 
    585         pContext->sScan_Encode_Info.ui32CurMCUsOffset =
    586             pContext->sScan_Encode_Info.ui32NumberMCUsToEncode - ui32RemainMCUs;
    587 
    588         rc = SubmitScanToMTX(pContext, ui16BCnt,
    589                              pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].i8MTXNumber, ui32NoMCUsToEncode);
    590         if (rc != IMG_ERR_OK) {
    591             vaStatus = VA_STATUS_ERROR_UNKNOWN;
    592             DEBUG_FAILURE;
    593             return vaStatus;
    594         }
    595 
    596         ui32RemainMCUs -= ui32NoMCUsToEncode;
    597     }
    598     pnw_cmdbuf_insert_command_package(ctx->obj_context,
    599                                       1 ,
    600                                       MTX_CMDID_NULL,
    601                                       NULL,
    602                                       0);
    603 
    604 
    605     psb_buffer_unmap(&cmdbuf->pic_params);
    606     cmdbuf->pic_params_p = NULL;
    607     psb_buffer_unmap(&cmdbuf->header_mem);
    608     cmdbuf->header_mem_p = NULL;
    609     /*psb_buffer_unmap(&cmdbuf->slice_params);
    610     cmdbuf->slice_params_p = NULL;*/
    611     psb_buffer_unmap(ctx->coded_buf->psb_buffer);
    612     pContext->jpeg_coded_buf.pMemInfo = NULL;
    613     if (pnw_context_flush_cmdbuf(ctx->obj_context)) {
    614         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    615         return vaStatus;
    616     }
    617 
    618     ctx->obj_context->frame_count++;
    619     return VA_STATUS_SUCCESS;
    620 }
    621 
    622 VAStatus pnw_jpeg_AppendMarkers(object_context_p obj_context, unsigned char *raw_coded_buf)
    623 {
    624     INIT_CONTEXT_JPEG;
    625     IMG_UINT16 ui16BCnt;
    626     TOPAZSC_JPEG_ENCODER_CONTEXT *pContext = ctx->jpeg_ctx;
    627     BUFFER_HEADER* pBufHeader;
    628     STREAMTYPEW s_streamW;
    629     unsigned char *pSegStart = raw_coded_buf;
    630 
    631     if (pSegStart == NULL) {
    632         return VA_STATUS_ERROR_UNKNOWN;
    633     }
    634 
    635     pBufHeader = (BUFFER_HEADER *)pSegStart;
    636 
    637     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of Coded buffers %d, Per Coded Buffer size : %d\n",
    638                              pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers, pContext->ui32SizePerCodedBuffer);
    639 
    640     /*The first part of coded buffer contains JPEG headers*/
    641     pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE;
    642 
    643     pContext->jpeg_coded_buf.ui32BytesWritten = 0;
    644 
    645     for (ui16BCnt = 0;
    646          ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers;
    647          ui16BCnt++) {
    648         pBufHeader = (BUFFER_HEADER *)pSegStart;
    649         pBufHeader->ui32Reserved3 =
    650             PNW_JPEG_HEADER_MAX_SIZE + pContext->ui32SizePerCodedBuffer * ui16BCnt ;
    651 
    652         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded Buffer Part %d, size %d, next part offset: %d\n",
    653                                  ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
    654 
    655         if (ui16BCnt > 0 && pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers > 1) {
    656             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Append 2 bytes Reset Interval %d "
    657                                      "to Coded Buffer Part %d\n", ui16BCnt - 1, ui16BCnt);
    658 
    659             while(*(pSegStart +sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed - 1) == 0xff)
    660                 pBufHeader->ui32BytesUsed--;
    661 
    662             pnw_OutputResetIntervalToCB(
    663                 (IMG_UINT8 *)(pSegStart +
    664                               sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed),
    665                 ui16BCnt - 1);
    666 
    667             pBufHeader->ui32BytesUsed += 2;
    668         }
    669 
    670         pContext->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed;
    671         pSegStart = raw_coded_buf + pBufHeader->ui32Reserved3;
    672     }
    673     pBufHeader = (BUFFER_HEADER *)pSegStart;
    674     pBufHeader->ui32Reserved3 = 0; /*Last Part of Coded Buffer*/
    675     pContext->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed;
    676 
    677     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded Buffer Part %d, size %d, next part offset: %d\n",
    678                              ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
    679 
    680     while(*(pSegStart +sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed - 1) == 0xff)
    681         pBufHeader->ui32BytesUsed--;
    682 
    683     s_streamW.Buffer = pSegStart;
    684     s_streamW.Offset = (sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed);
    685 
    686     fPutBitsToBuffer(&s_streamW, 2, END_OF_IMAGE);
    687 
    688     pBufHeader->ui32BytesUsed += 2;
    689     pContext->jpeg_coded_buf.ui32BytesWritten += 2;
    690 
    691     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Add two bytes to last part of coded buffer,"
    692                              " total: %d\n", pContext->jpeg_coded_buf.ui32BytesWritten);
    693     return VA_STATUS_SUCCESS;
    694 }
    695 
    696 struct format_vtable_s pnw_JPEG_vtable = {
    697 queryConfigAttributes:
    698     pnw_jpeg_QueryConfigAttributes,
    699 validateConfig:
    700     pnw_jpeg_ValidateConfig,
    701 createContext:
    702     pnw_jpeg_CreateContext,
    703 destroyContext:
    704     pnw_jpeg_DestroyContext,
    705 beginPicture:
    706     pnw_jpeg_BeginPicture,
    707 renderPicture:
    708     pnw_jpeg_RenderPicture,
    709 endPicture:
    710     pnw_jpeg_EndPicture
    711 };
    712