1/* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * Copyright (c) Imagination Technologies Limited, UK 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Elaine Wang <elaine.wang@intel.com> 27 * 28 */ 29 30 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*/ 58static const uint32_t aui32_jpg_mtx_num[PNW_JPEG_MAX_SCAN_NUM] = {0x0, 0x1, 0x1, 0x5, 0x5, 0x15, 0x15}; 59 60static 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 107static 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*/ 129static 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 231static 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 252static 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 312static 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 458static 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 492static 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*/ 533static 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 548static 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 622VAStatus 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 696struct format_vtable_s pnw_JPEG_vtable = { 697queryConfigAttributes: 698 pnw_jpeg_QueryConfigAttributes, 699validateConfig: 700 pnw_jpeg_ValidateConfig, 701createContext: 702 pnw_jpeg_CreateContext, 703destroyContext: 704 pnw_jpeg_DestroyContext, 705beginPicture: 706 pnw_jpeg_BeginPicture, 707renderPicture: 708 pnw_jpeg_RenderPicture, 709endPicture: 710 pnw_jpeg_EndPicture 711}; 712