pnw_jpeg.c revision 437b3eda28a4bf098efa80598cab67f190275266
1/*
2 * Copyright (c) 2007 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#include <stdlib.h>
26#include <stdint.h>
27#include <string.h>
28
29#include "psb_def.h"
30#include "psb_surface.h"
31#include "psb_cmdbuf.h"
32#include "pnw_jpeg.h"
33#include "pnw_hostcode.h"
34#include "pnw_hostheader.h"
35#include "pnw_hostjpeg.h"
36
37#define TOPAZ_MPEG4_MAX_BITRATE 16000000
38
39#define INIT_CONTEXT_JPEG	context_ENC_p ctx = (context_ENC_p) obj_context->format_data
40#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
41#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
42
43
44
45static void pnw_jpeg_QueryConfigAttributes(
46    VAProfile profile,
47    VAEntrypoint entrypoint,
48    VAConfigAttrib *attrib_list,
49    int num_attribs )
50{
51    int i;
52
53    psb__information_message("pnw_jpeg_QueryConfigAttributes\n");
54
55    /* RateControl attributes */
56    for (i = 0; i < num_attribs; i++) {
57        switch (attrib_list[i].type) {
58        case VAConfigAttribRTFormat:
59            break;
60        default:
61            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
62            break;
63        }
64    }
65
66    return;
67}
68
69
70static VAStatus pnw_jpeg_ValidateConfig(
71    object_config_p obj_config )
72{
73    VAStatus vaStatus = VA_STATUS_SUCCESS;
74    psb__information_message("pnw_jpeg_ValidateConfig\n");
75
76    return vaStatus;
77
78}
79
80/*Init JPEG context. Ported from IMG_JPEG_EncoderInitialise*/
81static VAStatus pnw_jpeg_CreateContext(
82    object_context_p obj_context,
83    object_config_p obj_config )
84{
85    VAStatus vaStatus = VA_STATUS_SUCCESS;
86    context_ENC_p ctx;
87    TOPAZSC_JPEG_ENCODER_CONTEXT *jpeg_ctx_p;
88
89    psb__information_message("pnw_jpeg_CreateContext\n");
90
91    vaStatus = pnw_CreateContext(obj_context, obj_config, 1);
92    if(VA_STATUS_SUCCESS != vaStatus)
93        return VA_STATUS_ERROR_ALLOCATION_FAILED;
94
95    ctx = (context_ENC_p) obj_context->format_data;
96
97    ctx->eCodec = IMG_CODEC_JPEG;
98    ctx->eFormat = IMG_CODEC_PL12;
99//    ctx->eFormat = IMG_CODEC_IYUV;
100
101    ctx->Slices = 2;
102    ctx->ParallelCores = 2;
103    ctx->NumCores = 2;
104    ctx->jpeg_ctx = (TOPAZSC_JPEG_ENCODER_CONTEXT * )malloc(sizeof(TOPAZSC_JPEG_ENCODER_CONTEXT));
105
106    if (NULL == ctx->jpeg_ctx)
107	return VA_STATUS_ERROR_ALLOCATION_FAILED;
108
109    jpeg_ctx_p = ctx->jpeg_ctx;
110    jpeg_ctx_p->eFormat = ctx->eFormat;
111
112    jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers = ctx->NumCores;
113
114    jpeg_ctx_p->sScan_Encode_Info.aBufferTable =
115	(TOPAZSC_JPEG_BUFFER_INFO *)malloc(sizeof(TOPAZSC_JPEG_BUFFER_INFO)
116		    * jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers);
117
118    if (NULL == jpeg_ctx_p->sScan_Encode_Info.aBufferTable)
119	return VA_STATUS_ERROR_ALLOCATION_FAILED;
120    memset(jpeg_ctx_p->sScan_Encode_Info.aBufferTable, 0,
121	sizeof(TOPAZSC_JPEG_BUFFER_INFO) * jpeg_ctx_p->sScan_Encode_Info.ui8NumberOfCodedBuffers);
122
123    jpeg_ctx_p->ui32OutputWidth = ctx->Width;
124    jpeg_ctx_p->ui32OutputHeight = ctx->Height;
125
126    jpeg_ctx_p->ui32SizePerCodedBuffer = PNW_JPEG_CODED_BUF_SIZE(ctx->Width, ctx->Height, ctx->NumCores);
127
128    psb__information_message("SizePerCodedBuffer :%d\n", jpeg_ctx_p->ui32SizePerCodedBuffer);
129    jpeg_ctx_p->ctx = ctx;
130    /*Reuse header_mem(76*4 bytes) and pic_params_size(256 bytes)
131     *  as pMemInfoMTXSetup(JPEG_MTX_DMA_SETUP 24x4 bytes) and
132     *  pMemInfoTableBlock JPEG_MTX_QUANT_TABLE(128byes)*/
133    return vaStatus;
134}
135
136
137static void pnw_jpeg_DestroyContext(
138    object_context_p obj_context)
139{
140    context_ENC_p ctx;
141
142    psb__information_message("pnw_jpeg_DestroyPicture\n");
143
144    ctx = (context_ENC_p)(obj_context->format_data);
145
146    if (ctx->jpeg_ctx)
147    {
148	if (ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable)
149	{
150	    free(ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable);
151	    ctx->jpeg_ctx->sScan_Encode_Info.aBufferTable = NULL;
152	}
153
154	free(ctx->jpeg_ctx);
155    }
156    pnw_DestroyContext(obj_context);
157
158}
159
160static VAStatus pnw_jpeg_BeginPicture(
161    object_context_p obj_context)
162{
163    INIT_CONTEXT_JPEG;
164    VAStatus vaStatus = VA_STATUS_SUCCESS;
165    int ret;
166    pnw_cmdbuf_p cmdbuf;
167
168    psb__information_message("pnw_jpeg_BeginPicture\n");
169
170    ctx->src_surface = ctx->obj_context->current_render_target;
171
172    /* Initialise the command buffer */
173    ret = pnw_context_get_next_cmdbuf(ctx->obj_context);
174    if(ret) {
175        psb__information_message("get next cmdbuf fail\n");
176        vaStatus = VA_STATUS_ERROR_UNKNOWN;
177        return vaStatus;
178    }
179    cmdbuf = ctx->obj_context->pnw_cmdbuf;
180
181    /* map start_pic param */
182    vaStatus = psb_buffer_map(&cmdbuf->pic_params, &cmdbuf->pic_params_p);
183    if(vaStatus) {
184        return vaStatus;
185    }
186    vaStatus = psb_buffer_map(&cmdbuf->header_mem, &cmdbuf->header_mem_p);
187    if (vaStatus) {
188        psb_buffer_unmap(&cmdbuf->pic_params);
189        return vaStatus;
190    }
191    /*vaStatus = psb_buffer_map(&cmdbuf->slice_params, &cmdbuf->slice_params_p);
192    if (vaStatus) {
193        psb_buffer_unmap(&cmdbuf->pic_params);
194        psb_buffer_unmap(&cmdbuf->header_mem);
195        return vaStatus;
196    }*/
197
198    /*Store the QMatrix data*/
199    ctx->jpeg_ctx->pMemInfoTableBlock = cmdbuf->pic_params_p;
200    ctx->jpeg_ctx->psTablesBlock = (JPEG_MTX_QUANT_TABLE *)ctx->jpeg_ctx->pMemInfoTableBlock;
201
202    /*Store MTX_SETUP data*/
203    ctx->jpeg_ctx->pMemInfoMTXSetup = cmdbuf->header_mem_p;
204    ctx->jpeg_ctx->pMTXSetup = (JPEG_MTX_DMA_SETUP*)ctx->jpeg_ctx->pMemInfoMTXSetup;
205
206    ctx->jpeg_ctx->pMTXSetup->ui32ComponentsInScan=PNW_JPEG_COMPONENTS_NUM;
207
208    if ( ctx->obj_context->frame_count==0) { /* first picture */
209
210        psb_driver_data_p driver_data=ctx->obj_context->driver_data;
211
212        *cmdbuf->cmd_idx++ = ((MTX_CMDID_SW_NEW_CODEC & MTX_CMDWORD_ID_MASK) << MTX_CMDWORD_ID_SHIFT) |
213                             (((driver_data->drm_context & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT));
214    	pnw_cmdbuf_insert_command_param(ctx->eCodec);
215        pnw_cmdbuf_insert_command_param((ctx->Width<<16)|ctx->Height);
216    }
217
218    pnw_jpeg_set_default_qmatix(ctx->jpeg_ctx->pMemInfoTableBlock);
219
220    InitializeJpegEncode(ctx->jpeg_ctx, ctx->src_surface);
221
222    return vaStatus;
223}
224
225static VAStatus pnw__jpeg_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer)
226{
227    VAStatus vaStatus = VA_STATUS_SUCCESS;
228    VAEncPictureParameterBufferJPEG *pBuffer;
229    pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
230    BUFFER_HEADER *pBufHeader;
231    //unsigned long *pPictureHeaderMem;
232    //MTX_HEADER_PARAMS *psPicHeader;
233    int i;
234    TOPAZSC_JPEG_ENCODER_CONTEXT *jpeg_ctx = ctx->jpeg_ctx;
235    IMG_ERRORCODE rc;
236
237    ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
238
239    if((obj_buffer->num_elements != 1) ||
240       (obj_buffer->size != sizeof(VAEncPictureParameterBufferJPEG)))
241    {
242        return VA_STATUS_ERROR_UNKNOWN;
243    }
244
245    /* Transfer ownership of VAEncPictureParameterBufferMPEG4 data */
246    pBuffer = (VAEncPictureParameterBufferJPEG *) obj_buffer->buffer_data;
247    obj_buffer->buffer_data = NULL;
248    obj_buffer->size = 0;
249
250    ASSERT(ctx->Width == pBuffer->picture_width);
251    ASSERT(ctx->Height == pBuffer->picture_height);
252
253    ctx->coded_buf = BUFFER(pBuffer->coded_buf);
254
255    free(pBuffer);
256
257    if (NULL == ctx->coded_buf)
258    {
259	psb__error_message("%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__);
260	return VA_STATUS_ERROR_INVALID_BUFFER;
261    }
262
263    psb__information_message("Set Quant Tables\n");
264    /*Set Quant Tables*/
265    for (i = ctx->NumCores - 1; i >= 0; i--)
266	pnw_cmdbuf_insert_command_package(ctx->obj_context,
267		i,
268		MTX_CMDID_SETQUANT,
269		&cmdbuf->pic_params,
270		0);
271
272    for (i = 0; i < 10 ; i++)
273	psb__information_message("Quant Table %d: %d\n", i, *((unsigned char *)cmdbuf->pic_params_p + i));
274    psb__information_message("Coded buffer total size is %d, per coded buffer size is %d\n",
275		ctx->coded_buf->size, jpeg_ctx->ui32SizePerCodedBuffer );
276
277    vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, &jpeg_ctx->jpeg_coded_buf.pMemInfo);
278    if (vaStatus)
279    {
280	psb__error_message("ERROR: Map coded_buf failed!");
281        return vaStatus;
282    }
283    jpeg_ctx->jpeg_coded_buf.ui32Size = ctx->coded_buf->size;
284    jpeg_ctx->jpeg_coded_buf.sLock = BUFFER_FREE;
285    jpeg_ctx->jpeg_coded_buf.ui32BytesWritten = 0;
286
287    psb__information_message("Setup JPEG Tables\n");
288    rc=SetupJPEGTables(ctx->jpeg_ctx, &jpeg_ctx->jpeg_coded_buf,  ctx->src_surface);
289
290    if (rc!=IMG_ERR_OK)
291	return VA_STATUS_ERROR_UNKNOWN;
292
293    psb__information_message("Write JPEG Headers to coded buf\n");
294
295    pBufHeader = (BUFFER_HEADER *)jpeg_ctx->jpeg_coded_buf.pMemInfo;
296    pBufHeader->ui32BytesUsed = 0; /* Not include BUFFER_HEADER*/
297    rc=PrepareHeader(jpeg_ctx, &jpeg_ctx->jpeg_coded_buf, sizeof(BUFFER_HEADER), IMG_TRUE);
298    if (rc!=IMG_ERR_OK)
299	return VA_STATUS_ERROR_UNKNOWN;
300
301    pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE;//Next coded buffer offset
302    pBufHeader->ui32BytesUsed = jpeg_ctx->jpeg_coded_buf.ui32BytesWritten - sizeof(BUFFER_HEADER);
303
304    psb__information_message("JPEG Buffer Header size: %d, File Header size :%d, next codef buffer offset: %d\n",
305	sizeof(BUFFER_HEADER), pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
306    return vaStatus;
307}
308
309static VAStatus pnw__jpeg_process_qmatrix_param(context_ENC_p ctx, object_buffer_p obj_buffer)
310{
311    VAStatus vaStatus = VA_STATUS_SUCCESS;
312    VAQMatrixBufferJPEG *pBuffer;
313    JPEG_MTX_QUANT_TABLE* pQMatrix = (JPEG_MTX_QUANT_TABLE *)
314	(ctx->jpeg_ctx->pMemInfoTableBlock);
315
316    ASSERT(obj_buffer->type == VAQMatrixBufferType);
317
318    pBuffer = (VAQMatrixBufferJPEG *) obj_buffer->buffer_data;
319
320    if (0 != pBuffer->load_lum_quantiser_matrix)
321    {
322	memcpy(pQMatrix->aui8LumaQuantParams,
323		pBuffer->lum_quantiser_matrix,
324		QUANT_TABLE_SIZE_BYTES);
325    }
326
327    if (0 != pBuffer->load_chroma_quantiser_matrix)
328    {
329	memcpy(pQMatrix->aui8LumaQuantParams,
330		pBuffer->chroma_quantiser_matrix,
331		QUANT_TABLE_SIZE_BYTES);
332    }
333
334    free(obj_buffer->buffer_data);
335    obj_buffer->buffer_data = NULL;
336
337    return vaStatus;
338}
339
340
341static VAStatus pnw_jpeg_RenderPicture(
342    object_context_p obj_context,
343    object_buffer_p *buffers,
344    int num_buffers)
345{
346    INIT_CONTEXT_JPEG;
347    VAStatus vaStatus = VA_STATUS_SUCCESS;
348    int i;
349
350    psb__information_message("pnw_jpeg_RenderPicture\n");
351
352    for (i=0; i<num_buffers; i++) {
353	object_buffer_p obj_buffer = buffers[i];
354
355	switch (obj_buffer->type) {
356	    case VAQMatrixBufferType:
357		psb__information_message("pnw_jpeg_RenderPicture got VAEncSliceParameterBufferType\n");
358		vaStatus = pnw__jpeg_process_qmatrix_param(ctx, obj_buffer);
359		DEBUG_FAILURE;
360		break;
361	    case VAEncPictureParameterBufferType:
362		psb__information_message("pnw_jpeg_RenderPicture got VAEncPictureParameterBufferType\n");
363		vaStatus = pnw__jpeg_process_picture_param(ctx, obj_buffer);
364		DEBUG_FAILURE;
365		break;
366	    default:
367		vaStatus = VA_STATUS_ERROR_UNKNOWN;
368		DEBUG_FAILURE;
369	}
370    }
371
372    return vaStatus;
373}
374
375/* Add Restart interval termination (RSTm)to coded buf 1 ~ NumCores-1*/
376static inline VAStatus pnw_OutputResetIntervalToCB(IMG_UINT8 *pui8Buf, IMG_UINT8 ui8_marker)
377{
378   if (NULL == pui8Buf)
379	   return VA_STATUS_ERROR_UNKNOWN;
380   /*Refer to CCITT Rec. T.81 (1992 E), B.2.1*/
381   /*RSTm: Restart marker conditional marker which is placed between
382    * entropy-coded segments only if restartis enabled. There are 8 unique
383    * restart markers (m = 0 - 7) which repeat in sequence from 0 to 7, starting with
384    * zero for each scan, to provide a modulo 8 restart interval count*/
385   *pui8Buf++ = 0xff;
386   *pui8Buf = ( ui8_marker | 0xd0 );
387   return 0;
388}
389
390
391static VAStatus pnw_jpeg_EndPicture(
392    object_context_p obj_context)
393{
394    INIT_CONTEXT_JPEG;
395    IMG_UINT16 ui16BCnt;
396    TOPAZSC_JPEG_ENCODER_CONTEXT *pContext = ctx->jpeg_ctx;
397    IMG_UINT32 rc = 0;
398    VAStatus vaStatus = VA_STATUS_SUCCESS;
399    BUFFER_HEADER* pBufHeader;
400    pnw_cmdbuf_p cmdbuf = (pnw_cmdbuf_p)ctx->obj_context->pnw_cmdbuf;
401    STREAMTYPEW s_streamW;
402    void *pCodedBufStart = NULL;
403
404    psb__information_message("pnw_jpeg_EndPicture\n");
405
406    for (ui16BCnt = 0; ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers
407	    && pContext->sScan_Encode_Info.ui16SScan >= 0; ui16BCnt++)
408    {
409	pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber = pContext->sScan_Encode_Info.ui16SScan--;
410	/*FIXME: if ui16CScan(initial value of ui16SScan) is larger than Numcores, we shuold wait for MTX idle
411	 * before sending more MTX_CMDID_ISSUEBUFF commands. This case may happen if (Width / 16)*(Height / 16)
412	 * is odd, e.x QGIF. Then we should use only one core to encode it*/
413	pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].i8MTXNumber = pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].ui16ScanNumber;
414	rc=SubmitScanToMTX(pContext, ui16BCnt, pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].i8MTXNumber);
415	if (rc != IMG_ERR_OK)
416	{
417	    vaStatus = VA_STATUS_ERROR_UNKNOWN;
418	    DEBUG_FAILURE;
419	    return vaStatus;
420	}
421    }
422
423    psb_buffer_unmap(&cmdbuf->pic_params);
424    cmdbuf->pic_params_p = NULL;
425    psb_buffer_unmap(&cmdbuf->header_mem);
426    cmdbuf->header_mem_p = NULL;
427    /*psb_buffer_unmap(&cmdbuf->slice_params);
428    cmdbuf->slice_params_p = NULL;*/
429    psb_buffer_unmap(ctx->coded_buf->psb_buffer);
430    pContext->jpeg_coded_buf.pMemInfo = NULL;
431    if (pnw_context_flush_cmdbuf(ctx->obj_context)) {
432	vaStatus = VA_STATUS_ERROR_UNKNOWN;
433	return vaStatus;
434    }
435
436 /*   vaStatus = psb_buffer_map(&cmdbuf->slice_params, &cmdbuf->slice_params_p);
437    if ( 0 != vaStatus)
438    {
439	psb__error_message("ERROR: map slice params failed\n");
440	return vaStatus;
441    }
442
443
444    for (ui16BCnt = 0; ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers; ui16BCnt++ ){
445	pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].pMemInfo = cmdbuf->slice_params_p +
446	   ui16BCnt * pContext->ui32SizePerCodedBuffer;
447	pBuffHdr =  (BUFFER_HEADER*)pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].pMemInfo;
448	psb__information_message("Coded Buffer %d, used bytes %d\n",pBuffHdr->ui32BytesUsed);
449	if (pContext->jpeg_coded_buf.ui32BytesWritten + pBuffHdr->ui32BytesUsed < pContext->jpeg_coded_buf.ui32Size )
450	{
451	    psb__error_message("ERROR: There is no enough space in codedbuf!\n");
452	    psb_buffer_unmap(ctx->coded_buf->psb_buffer);
453	    return VA_STATUS_ERROR_UNKNOWN;
454	}
455	memcpy((void *)(pContext->jpeg_coded_buf.pMemInfo + pContext->jpeg_coded_buf.ui32BytesWritten),
456		(void *)(pContext->sScan_Encode_Info.aBufferTable[ui16BCnt].pMemInfo + sizeof(BUFFER_HEADER)),
457		pBuffHdr->ui32BytesUsed);
458	pContext->jpeg_coded_buf.ui32BytesWritten += pBuffHdr->ui32BytesUsed;
459    }
460    */
461    vaStatus = psb_buffer_map(ctx->coded_buf->psb_buffer, &pContext->jpeg_coded_buf.pMemInfo);
462    if (vaStatus)
463    {
464	psb__error_message("ERROR: Map coded_buf failed!");
465        return vaStatus;
466    }
467    pCodedBufStart = pContext->jpeg_coded_buf.pMemInfo;
468    pBufHeader = (BUFFER_HEADER *)pContext->jpeg_coded_buf.pMemInfo;
469
470    psb__information_message("Number of Coded buffers %d, Per Coded Buffer size : %d\n",
471	pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers, pContext->ui32SizePerCodedBuffer);
472
473    /*The first part of coded buffer contains JPEG headers*/
474    pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE;
475
476    pContext->jpeg_coded_buf.ui32BytesWritten = 0;
477
478    for (ui16BCnt = 0; ui16BCnt < pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers; ui16BCnt++ ) {
479	pBufHeader = (BUFFER_HEADER *)pCodedBufStart;
480	pBufHeader->ui32Reserved3 = PNW_JPEG_HEADER_MAX_SIZE + pContext->ui32SizePerCodedBuffer * ui16BCnt ;
481	psb__information_message("Coded Buffer Part %d, size %d, next part offset: %d\n",
482		ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
483        if (ui16BCnt > 0 && pContext->sScan_Encode_Info.ui8NumberOfCodedBuffers > 1)
484	{
485	    pnw_OutputResetIntervalToCB(
486		(IMG_UINT8 *)(pCodedBufStart + sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed),
487		ui16BCnt - 1);
488	    pBufHeader->ui32BytesUsed += 2;
489	    psb__information_message("Append 2 bytes Reset Interval %d to Coded Buffer Part %d\n",
490		ui16BCnt - 1, ui16BCnt);
491	}
492
493	pContext->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed;
494	pCodedBufStart = pContext->jpeg_coded_buf.pMemInfo + pBufHeader->ui32Reserved3;
495    }
496    pBufHeader = (BUFFER_HEADER *)pCodedBufStart;
497    pBufHeader->ui32Reserved3 = 0; /*Last Part of Coded Buffer*/
498    pContext->jpeg_coded_buf.ui32BytesWritten += pBufHeader->ui32BytesUsed;
499
500    psb__information_message("Coded Buffer Part %d, size %d, next part offset: %d\n",
501		    ui16BCnt, pBufHeader->ui32BytesUsed, pBufHeader->ui32Reserved3);
502
503    s_streamW.Buffer = pCodedBufStart ;
504    s_streamW.Buffer += (sizeof(BUFFER_HEADER) + pBufHeader->ui32BytesUsed);
505    fPutBitsToBuffer(&s_streamW, 2, END_OF_IMAGE);
506    pBufHeader->ui32BytesUsed += 2;
507    pContext->jpeg_coded_buf.ui32BytesWritten += 2;
508
509    psb__information_message("Add two bytes to last part of coded buffer, total: %d\n", pContext->jpeg_coded_buf.ui32BytesWritten);
510    psb_buffer_unmap(ctx->coded_buf->psb_buffer);
511    return VA_STATUS_SUCCESS;
512}
513
514
515struct format_vtable_s pnw_JPEG_vtable = {
516  queryConfigAttributes: pnw_jpeg_QueryConfigAttributes,
517  validateConfig: pnw_jpeg_ValidateConfig,
518  createContext: pnw_jpeg_CreateContext,
519  destroyContext: pnw_jpeg_DestroyContext,
520  beginPicture: pnw_jpeg_BeginPicture,
521  renderPicture: pnw_jpeg_RenderPicture,
522  endPicture: pnw_jpeg_EndPicture
523};
524