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