/* * Copyright (c) 2011 Intel Corporation. All Rights Reserved. * Copyright (c) Imagination Technologies Limited, UK * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Elaine Wang <elaine.wang@intel.com> * */ #include <stdlib.h> #include <stdint.h> #include <string.h> #include "psb_def.h" #include "psb_drv_debug.h" #include "psb_surface.h" #include "psb_cmdbuf.h" #include "pnw_jpeg.h" #include "pnw_hostcode.h" #include "pnw_hostheader.h" #include "pnw_hostjpeg.h" #define INIT_CONTEXT_JPEG context_ENC_p ctx = (context_ENC_p) obj_context->format_data #define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id )) #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id )) /* Balancing the workloads of executing MTX_CMDID_ISSUEBUFF commands to 2-cores: 1 commands: 0 (0b/0x0) 2 commands: 1-0 (01b/0x1) 3 commands: 1-0-0 (001b/0x1) 4 commands: 1-0-1-0 (0101b/0x5) 5 commands: 1-0-1-0-0 (00101b/0x5) 6 commands: 1-0-1-0-1-0 (010101b/0x15) 7 commands: 1-0-1-0-1-0-0 (0010101b/0x15) */ static const uint32_t aui32_jpg_mtx_num[PNW_JPEG_MAX_SCAN_NUM] = {0x0, 0x1, 0x1, 0x5, 0x5, 0x15, 0x15}; static void pnw_jpeg_QueryConfigAttributes( VAProfile __maybe_unused profile, VAEntrypoint __maybe_unused entrypoint, VAConfigAttrib *attrib_list, int num_attribs) { int i; drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_QueryConfigAttributes\n"); /* RateControl attributes */ for (i = 0; i < num_attribs; i++) { switch (attrib_list[i].type) { case VAConfigAttribRTFormat: /* Already handled in psb_GetConfigAttributes */ break; case VAConfigAttribEncJPEG: /* The below JPEG ENC capabilities are fixed by TopazSC and not changable. */ { VAConfigAttribValEncJPEG* ptr = (VAConfigAttribValEncJPEG *)&(attrib_list[i].value); (ptr->bits).arithmatic_coding_mode = 0; /* Unsupported */ (ptr->bits).progressive_dct_mode = 0; /* Unsupported */ (ptr->bits).non_interleaved_mode = 1; /* Supported */ (ptr->bits).differential_mode = 0; /* Unsupported */ (ptr->bits).max_num_components = PNW_JPEG_COMPONENTS_NUM; /* Only 3 is supported */ (ptr->bits).max_num_scans = PNW_JPEG_MAX_SCAN_NUM; (ptr->bits).max_num_huffman_tables = 4; /* Only 4 is supported */ (ptr->bits).max_num_huffman_tables = 2; /* Only 2 is supported */ } break; case VAConfigAttribMaxPictureWidth: case VAConfigAttribMaxPictureHeight: /* No pure limitation on an image's width or height seperately, as long as the image's MCUs need less than max_num_scans rounds of encoding and a surface of that source size is allocatable. */ attrib_list[i].value = 0; /* No pure limitation */ break; default: attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED; break; } } return; } static VAStatus pnw_jpeg_ValidateConfig( object_config_p obj_config) { int i; /* Check all attributes */ for (i = 0; i < obj_config->attrib_count; i++) { switch (obj_config->attrib_list[i].type) { case VAConfigAttribRTFormat: /* Ignore */ break; case VAConfigAttribRateControl: break; default: return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; } } return VA_STATUS_SUCCESS; } /*Init JPEG context. Ported from IMG_JPEG_EncoderInitialise*/ static VAStatus pnw_jpeg_CreateContext( object_context_p obj_context, object_config_p obj_config) { VAStatus vaStatus = VA_STATUS_SUCCESS; context_ENC_p ctx; TOPAZSC_JPEG_ENCODER_CONTEXT *jpeg_ctx_p; int i; drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_CreateContext\n"); vaStatus = pnw_CreateContext(obj_context, obj_config, 1); if (VA_STATUS_SUCCESS != vaStatus) return VA_STATUS_ERROR_ALLOCATION_FAILED; ctx = (context_ENC_p) obj_context->format_data; ctx->eCodec = IMG_CODEC_JPEG; for (i = 0; i < obj_config->attrib_count; i++) { if (VAConfigAttribRTFormat == obj_config->attrib_list[i].type) { switch (obj_config->attrib_list[i].value) { case VA_RT_FORMAT_YUV420: if (obj_context->render_targets != NULL) { object_surface_p surface_p = SURFACE(obj_context->render_targets[0]); if (NULL == surface_p) { ctx->eFormat = IMG_CODEC_PL12; drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n"); break; } if ((surface_p->psb_surface)->extra_info[4] == VA_FOURCC_NV12) { ctx->eFormat = IMG_CODEC_PL12; drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: Choose NV12 format\n"); } else if ((surface_p->psb_surface)->extra_info[4] == VA_FOURCC_IYUV) { ctx->eFormat = IMG_CODEC_IYUV; drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: Choose IYUV format\n"); } else { ctx->eFormat = IMG_CODEC_PL12; drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n"); } } else { ctx->eFormat = IMG_CODEC_PL12; drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n"); } break; case VA_RT_FORMAT_YUV422: ctx->eFormat = IMG_CODEC_YV16; drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG encoding: Choose YUV422 format\n"); break; default: ctx->eFormat = IMG_CODEC_PL12; drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG encoding: Unsupported format and set to NV12\n"); break; } break; } } ctx->Slices = 2; ctx->ParallelCores = 2; ctx->NumCores = 2; ctx->jpeg_ctx = (TOPAZSC_JPEG_ENCODER_CONTEXT *)calloc(1, sizeof(TOPAZSC_JPEG_ENCODER_CONTEXT)); CHECK_ALLOCATION(ctx->jpeg_ctx); jpeg_ctx_p = ctx->jpeg_ctx; jpeg_ctx_p->eFormat = ctx->eFormat; /*Chroma sampling step x_step X y_step*/ jpeg_ctx_p->ui8ScanNum = JPEG_SCANNING_COUNT(ctx->Width, ctx->Height, ctx->NumCores, jpeg_ctx_p->eFormat); if (jpeg_ctx_p->ui8ScanNum < 2 || jpeg_ctx_p->ui8ScanNum > PNW_JPEG_MAX_SCAN_NUM) { drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG MCU scanning number(%d) is wrong!\n", jpeg_ctx_p->ui8ScanNum); free(ctx->jpeg_ctx); ctx->jpeg_ctx = NULL; return VA_STATUS_ERROR_UNKNOWN; } jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers = jpeg_ctx_p->ui8ScanNum; drv_debug_msg(VIDEO_DEBUG_GENERAL, " JPEG Scanning Number %d\n", jpeg_ctx_p->ui8ScanNum); jpeg_ctx_p->sScan_Encode_Info.aBufferTable = (TOPAZSC_JPEG_BUFFER_INFO *)calloc(1, sizeof(TOPAZSC_JPEG_BUFFER_INFO) * jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers); if (NULL == jpeg_ctx_p->sScan_Encode_Info.aBufferTable) return VA_STATUS_ERROR_ALLOCATION_FAILED; /*It will be figured out when known the size of whole coded buffer.*/ jpeg_ctx_p->ui32SizePerCodedBuffer = 0; jpeg_ctx_p->ctx = (unsigned char *)ctx; /*Reuse header_mem(76*4 bytes) and pic_params_size(256 bytes) * as pMemInfoMTXSetup(JPEG_MTX_DMA_SETUP 24x4 bytes) and * pMemInfoTableBlock JPEG_MTX_QUANT_TABLE(128byes)*/ return vaStatus; } static void pnw_jpeg_DestroyContext( object_context_p obj_context) { context_ENC_p ctx; drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_DestroyPicture\n"); ctx = (context_ENC_p)(obj_context->format_data); if (ctx->jpeg_ctx) { if (ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable) { free(ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable); ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable = NULL; } free(ctx->jpeg_ctx); } pnw_DestroyContext(obj_context); } static VAStatus pnw_jpeg_BeginPicture( object_context_p obj_context) { INIT_CONTEXT_JPEG; VAStatus vaStatus = VA_STATUS_SUCCESS; int ret; pnw_cmdbuf_p cmdbuf; drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_BeginPicture: Frame %d\n", ctx->obj_context->frame_count); ctx->src_surface = ctx->obj_context->current_render_target; /* Initialise the command buffer */ ret = pnw_context_get_next_cmdbuf(ctx->obj_context); if (ret) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n"); vaStatus = VA_STATUS_ERROR_UNKNOWN; return vaStatus; } cmdbuf = ctx->obj_context->pnw_cmdbuf; /* map start_pic param */ vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p); if (vaStatus) { return vaStatus; } vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p); if (vaStatus) { psb_buffer_unmap(&cmdbuf->pic_params); return vaStatus; } memset(ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable, 0, sizeof(TOPAZSC_JPEG_BUFFER_INFO) * ctx->jpeg_ctx->sScan_Encode_Info.ui8NumberOfCodedBuffers); /*Store the QMatrix data*/ ctx->jpeg_ctx->pMemInfoTableBlock = cmdbuf->pic_params_p; ctx->jpeg_ctx->psTablesBlock = (JPEG_MTX_QUANT_TABLE *)ctx->jpeg_ctx->pMemInfoTableBlock; /*Store MTX_SETUP data*/ ctx->jpeg_ctx->pMemInfoMTXSetup = cmdbuf->header_mem_p; ctx->jpeg_ctx->pMTXSetup = (JPEG_MTX_DMA_SETUP*)ctx->jpeg_ctx->pMemInfoMTXSetup; ctx->jpeg_ctx->pMTXSetup->ui32ComponentsInScan = PNW_JPEG_COMPONENTS_NUM; if (ctx->obj_context->frame_count == 0) { /* first picture */ psb_driver_data_p driver_data = ctx->obj_context->driver_data; *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) | (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT)); pnw_cmdbuf_insert_command_param(ctx->eCodec); pnw_cmdbuf_insert_command_param((ctx->Width << 16) | ctx->Height); } pnw_jpeg_set_default_qmatix(ctx->jpeg_ctx->pMemInfoTableBlock); return vaStatus; } static VAStatus pnw__jpeg_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer) { VAStatus vaStatus = VA_STATUS_SUCCESS; VAEncPictureParameterBufferJPEG *pBuffer; pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf; BUFFER_HEADER *pBufHeader; //unsigned long *pPictureHeaderMem; //MTX_HEADER_PARAMS *psPicHeader; int i; TOPAZSC_JPEG_ENCODER_CONTEXT *jpeg_ctx = ctx->jpeg_ctx; JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *) (ctx->jpeg_ctx->pMemInfoTableBlock); IMG_ERRORCODE rc; ASSERT(obj_buffer->type == VAEncPictureParameterBufferType); if ((obj_buffer->num_elements != 1) || (obj_buffer->size != sizeof(VAEncPictureParameterBufferJPEG))) { return VA_STATUS_ERROR_UNKNOWN; } /* Transfer ownership of VAEncPictureParameterBufferMPEG4 data */ pBuffer = (VAEncPictureParameterBufferJPEG *) obj_buffer->buffer_data; obj_buffer->buffer_data = NULL; obj_buffer->size = 0; /* Parameters checking */ if (((pBuffer->pic_flags).bits.profile != 0) || /* Only "0 - Baseline" is supported */ ((pBuffer->pic_flags).bits.progressive != 0) || /* Only "0 - sequential" is supported */ ((pBuffer->pic_flags).bits.huffman != 1) || /* Only "1 - huffman" is supported */ ((pBuffer->pic_flags).bits.interleaved != 0) || /* Only "0 - non interleaved" is supported */ ((pBuffer->pic_flags).bits.differential != 0)) /* Only "0 - non differential" is supported */ return VA_STATUS_ERROR_INVALID_PARAMETER; if ((pBuffer->sample_bit_depth != 8) || /* Only 8-bits sample depth is supported */ (pBuffer->num_components != PNW_JPEG_COMPONENTS_NUM) || /* Only 3 components setting is supported */ (pBuffer->quality > 100)) return VA_STATUS_ERROR_INVALID_PARAMETER; /* Set quality */ if (pBuffer->quality != 0) { /* Quality value is set */ customize_quantization_tables(pQMatrix->aui8LumaQuantParams, pQMatrix->aui8ChromaQuantParams, pBuffer->quality); } /* Get the width and height of encode destination */ jpeg_ctx->ui32OutputWidth = (unsigned short)(~0x1 & (pBuffer->picture_width + 0x1)); jpeg_ctx->ui32OutputHeight = (unsigned short)(~0x1 & (pBuffer->picture_height + 0x1)); ASSERT(ctx->Width >= jpeg_ctx->ui32OutputWidth); ASSERT(ctx->Height >= jpeg_ctx->ui32OutputHeight); /*Overwrite the scan info if destination's sizes are different from source's */ if ((ctx->Width!=jpeg_ctx->ui32OutputWidth) || (ctx->Height!=jpeg_ctx->ui32OutputHeight)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overwriting the scan info...\n"); jpeg_ctx->ui8ScanNum = JPEG_SCANNING_COUNT(jpeg_ctx->ui32OutputWidth, jpeg_ctx->ui32OutputHeight, ctx->NumCores, jpeg_ctx->eFormat); if (jpeg_ctx->ui8ScanNum < 2 || jpeg_ctx->ui8ScanNum > PNW_JPEG_MAX_SCAN_NUM) { drv_debug_msg(VIDEO_DEBUG_ERROR, "JPEG MCU scanning number(%d) is wrong!\n", jpeg_ctx->ui8ScanNum); free(ctx->jpeg_ctx); ctx->jpeg_ctx = NULL; return VA_STATUS_ERROR_UNKNOWN; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG Scanning Number %d\n", jpeg_ctx->ui8ScanNum); jpeg_ctx->sScan_Encode_Info.ui8NumberOfCodedBuffers = jpeg_ctx->ui8ScanNum; } ctx->coded_buf = BUFFER(pBuffer->coded_buf); free(pBuffer); if (NULL == ctx->coded_buf) { drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__); return VA_STATUS_ERROR_INVALID_BUFFER; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "Set Quant Tables\n"); /*Set Quant Tables*/ for (i = ctx->NumCores - 1; i >= 0; i--) pnw_cmdbuf_insert_command_package(ctx->obj_context, i, MTX_CMDID_SETQUANT, &cmdbuf->pic_params, 0); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Quant Table \n"); for (i=0; i<128; i+=8) { if (0 == i) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Table 0:\n"); } else if (64 == i) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Table 1:\n"); } drv_debug_msg(VIDEO_DEBUG_GENERAL, "%d %d %d %d %d %d %d %d\n", *((unsigned char *)cmdbuf->pic_params_p+i), *((unsigned char *)cmdbuf->pic_params_p+i+1), *((unsigned char *)cmdbuf->pic_params_p+i+2), *((unsigned char *)cmdbuf->pic_params_p+i+3), *((unsigned char *)cmdbuf->pic_params_p+i+4), *((unsigned char *)cmdbuf->pic_params_p+i+5), *((unsigned char *)cmdbuf->pic_params_p+i+6), *((unsigned char *)cmdbuf->pic_params_p+i+7)); } jpeg_ctx->ui32SizePerCodedBuffer = JPEG_CODED_BUF_SEGMENT_SIZE(ctx->coded_buf->size, jpeg_ctx->ui32OutputWidth, jpeg_ctx->ui32OutputHeight, ctx->NumCores, jpeg_ctx->eFormat); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded buffer total size is %d," "coded segment size per scan is %d\n", ctx->coded_buf->size, jpeg_ctx->ui32SizePerCodedBuffer); vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, (unsigned char **)&jpeg_ctx->jpeg_coded_buf.pMemInfo); if (vaStatus) { drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: Map coded_buf failed!"); return vaStatus; } jpeg_ctx->jpeg_coded_buf.ui32Size = ctx->coded_buf->size; jpeg_ctx->jpeg_coded_buf.sLock = BUFFER_FREE; jpeg_ctx->jpeg_coded_buf.ui32BytesWritten = 0; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Setup JPEG Tables\n"); rc = SetupJPEGTables(ctx->jpeg_ctx, &jpeg_ctx->jpeg_coded_buf, ctx->src_surface); if (rc != IMG_ERR_OK) return VA_STATUS_ERROR_UNKNOWN; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Write JPEG Headers to coded buf\n"); pBufHeader = (BUFFER_HEADER *)jpeg_ctx->jpeg_coded_buf.pMemInfo; pBufHeader->ui32BytesUsed = 0; /* Not include BUFFER_HEADER*/ rc = PrepareHeader(jpeg_ctx, &jpeg_ctx->jpeg_coded_buf, sizeof(BUFFER_HEADER), IMG_TRUE); if (rc != IMG_ERR_OK) return VA_STATUS_ERROR_UNKNOWN; pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE;//Next coded buffer offset pBufHeader->ui32BytesUsed = jpeg_ctx->jpeg_coded_buf.ui32BytesWritten - sizeof(BUFFER_HEADER); drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG Buffer Header size: %d, File Header size :%d, next codef buffer offset: %d\n", sizeof(BUFFER_HEADER), pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3); return vaStatus; } static VAStatus pnw__jpeg_process_qmatrix_param(context_ENC_p ctx, object_buffer_p obj_buffer) { VAStatus vaStatus = VA_STATUS_SUCCESS; VAQMatrixBufferJPEG *pBuffer; JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *) (ctx->jpeg_ctx->pMemInfoTableBlock); int i; ASSERT(obj_buffer->type == VAQMatrixBufferType); pBuffer = (VAQMatrixBufferJPEG *) obj_buffer->buffer_data; /* Zero value isn't allowed. It will cause JPEG firmware time out */ if (0 != pBuffer->load_lum_quantiser_matrix) { for (i=0; i<QUANT_TABLE_SIZE_BYTES; ++i) if (pBuffer->lum_quantiser_matrix[i] != 0) pQMatrix->aui8LumaQuantParams[i] = pBuffer->lum_quantiser_matrix[i]; } if (0 != pBuffer->load_chroma_quantiser_matrix) { for (i=0; i<QUANT_TABLE_SIZE_BYTES; ++i) if (pBuffer->chroma_quantiser_matrix[i] != 0) pQMatrix->aui8ChromaQuantParams[i] = pBuffer->chroma_quantiser_matrix[i]; } free(obj_buffer->buffer_data); obj_buffer->buffer_data = NULL; return vaStatus; } static VAStatus pnw_jpeg_RenderPicture( object_context_p obj_context, object_buffer_p *buffers, int num_buffers) { INIT_CONTEXT_JPEG; VAStatus vaStatus = VA_STATUS_SUCCESS; int i; drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture\n"); for (i = 0; i < num_buffers; i++) { object_buffer_p obj_buffer = buffers[i]; switch (obj_buffer->type) { case VAQMatrixBufferType: drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture got VAQMatrixBufferType\n"); vaStatus = pnw__jpeg_process_qmatrix_param(ctx, obj_buffer); DEBUG_FAILURE; break; case VAEncPictureParameterBufferType: drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture got VAEncPictureParameterBufferType\n"); vaStatus = pnw__jpeg_process_picture_param(ctx, obj_buffer); DEBUG_FAILURE; break; case VAEncSliceParameterBufferType: drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_RenderPicture got VAEncSliceParameterBufferJPEG\n"); drv_debug_msg(VIDEO_DEBUG_WARNING, "VAEncSliceParameterBufferJPEG is ignored on TopazSC\n"); vaStatus = VA_STATUS_SUCCESS; DEBUG_FAILURE; break; default: vaStatus = VA_STATUS_ERROR_UNKNOWN; DEBUG_FAILURE; } } return vaStatus; } /* Add Restart interval termination (RSTm)to coded buf 1 ~ NumCores-1*/ static inline VAStatus pnw_OutputResetIntervalToCB(IMG_UINT8 *pui8Buf, IMG_UINT8 ui8_marker) { if (NULL == pui8Buf) return VA_STATUS_ERROR_UNKNOWN; /*Refer to CCITT Rec. T.81 (1992 E), B.2.1*/ /*RSTm: Restart marker conditional marker which is placed between * entropy-coded segments only if restartis enabled. There are 8 unique * restart markers (m = 0 - 7) which repeat in sequence from 0 to 7, starting with * zero for each scan, to provide a modulo 8 restart interval count*/ *pui8Buf++ = 0xff; *pui8Buf = (ui8_marker | 0xd0); return 0; } static VAStatus pnw_jpeg_EndPicture( object_context_p obj_context) { INIT_CONTEXT_JPEG; IMG_UINT16 ui16BCnt; TOPAZSC_JPEG_ENCODER_CONTEXT *pContext = ctx->jpeg_ctx; IMG_UINT32 rc = 0; pnw_cmdbuf_p cmdbuf = (pnw_cmdbuf_p)ctx->obj_context->pnw_cmdbuf; VAStatus vaStatus = VA_STATUS_SUCCESS; IMG_UINT32 ui32NoMCUsToEncode; IMG_UINT32 ui32RemainMCUs; drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_jpeg_EndPicture\n"); ui32RemainMCUs = pContext->sScan_Encode_Info.ui32NumberMCUsToEncode; for (ui16BCnt = 0; ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers && pContext->sScan_Encode_Info.ui16SScan > 0; ui16BCnt++) { pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber = pContext->sScan_Encode_Info.ui16SScan--; if (pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers < 2 || pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers > PNW_JPEG_MAX_SCAN_NUM) { vaStatus = VA_STATUS_ERROR_UNKNOWN; DEBUG_FAILURE; return vaStatus; } /*i8MTXNumber is the core number.*/ pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].i8MTXNumber = (aui32_jpg_mtx_num[pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers - 1] >> ui16BCnt) & 0x1; if (pContext->sScan_Encode_Info.ui16SScan == 0) { ui32NoMCUsToEncode = ui32RemainMCUs; // Final scan, may need fewer MCUs than buffer size, calculate the remainder } else ui32NoMCUsToEncode = pContext->sScan_Encode_Info.ui32NumberMCUsToEncodePerScan; pContext->sScan_Encode_Info.ui32CurMCUsOffset = pContext->sScan_Encode_Info.ui32NumberMCUsToEncode - ui32RemainMCUs; rc = SubmitScanToMTX(pContext, ui16BCnt, pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].i8MTXNumber, ui32NoMCUsToEncode); if (rc != IMG_ERR_OK) { vaStatus = VA_STATUS_ERROR_UNKNOWN; DEBUG_FAILURE; return vaStatus; } ui32RemainMCUs -= ui32NoMCUsToEncode; } pnw_cmdbuf_insert_command_package(ctx->obj_context, 1 , MTX_CMDID_NULL, NULL, 0); psb_buffer_unmap(&cmdbuf->pic_params); cmdbuf->pic_params_p = NULL; psb_buffer_unmap(&cmdbuf->header_mem); cmdbuf->header_mem_p = NULL; /*psb_buffer_unmap(&cmdbuf->slice_params); cmdbuf->slice_params_p = NULL;*/ psb_buffer_unmap(ctx->coded_buf->psb_buffer); pContext->jpeg_coded_buf.pMemInfo = NULL; if (pnw_context_flush_cmdbuf(ctx->obj_context)) { vaStatus = VA_STATUS_ERROR_UNKNOWN; return vaStatus; } ctx->obj_context->frame_count++; return VA_STATUS_SUCCESS; } VAStatus pnw_jpeg_AppendMarkers(object_context_p obj_context, unsigned char *raw_coded_buf) { INIT_CONTEXT_JPEG; IMG_UINT16 ui16BCnt; TOPAZSC_JPEG_ENCODER_CONTEXT *pContext = ctx->jpeg_ctx; BUFFER_HEADER* pBufHeader; STREAMTYPEW s_streamW; unsigned char *pSegStart = raw_coded_buf; if (pSegStart == NULL) { return VA_STATUS_ERROR_UNKNOWN; } pBufHeader = (BUFFER_HEADER *)pSegStart; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Number of Coded buffers %d, Per Coded Buffer size : %d\n", pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers, pContext->ui32SizePerCodedBuffer); /*The first part of coded buffer contains JPEG headers*/ pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE; pContext->jpeg_coded_buf.ui32BytesWritten = 0; for (ui16BCnt = 0; ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers; ui16BCnt++) { pBufHeader = (BUFFER_HEADER *)pSegStart; pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE + pContext->ui32SizePerCodedBuffer * ui16BCnt ; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded Buffer Part %d, size %d, next part offset: %d\n", ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3); if (ui16BCnt > 0 && pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers > 1) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Append 2 bytes Reset Interval %d " "to Coded Buffer Part %d\n", ui16BCnt - 1, ui16BCnt); while(*(pSegStart +sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed - 1) == 0xff) pBufHeader->ui32BytesUsed--; pnw_OutputResetIntervalToCB( (IMG_UINT8 *)(pSegStart + sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed), ui16BCnt - 1); pBufHeader->ui32BytesUsed += 2; } pContext->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed; pSegStart = raw_coded_buf + pBufHeader->ui32Reserved3; } pBufHeader = (BUFFER_HEADER *)pSegStart; pBufHeader->ui32Reserved3 = 0; /*Last Part of Coded Buffer*/ pContext->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Coded Buffer Part %d, size %d, next part offset: %d\n", ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3); while(*(pSegStart +sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed - 1) == 0xff) pBufHeader->ui32BytesUsed--; s_streamW.Buffer = pSegStart; s_streamW.Offset = (sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed); fPutBitsToBuffer(&s_streamW, 2, END_OF_IMAGE); pBufHeader->ui32BytesUsed += 2; pContext->jpeg_coded_buf.ui32BytesWritten += 2; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Add two bytes to last part of coded buffer," " total: %d\n", pContext->jpeg_coded_buf.ui32BytesWritten); return VA_STATUS_SUCCESS; } struct format_vtable_s pnw_JPEG_vtable = { queryConfigAttributes: pnw_jpeg_QueryConfigAttributes, validateConfig: pnw_jpeg_ValidateConfig, createContext: pnw_jpeg_CreateContext, destroyContext: pnw_jpeg_DestroyContext, beginPicture: pnw_jpeg_BeginPicture, renderPicture: pnw_jpeg_RenderPicture, endPicture: pnw_jpeg_EndPicture };