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