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