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  *    Zeng Li <zeng.li@intel.com>
28  *
29  */
30 
31 #include "psb_def.h"
32 #include "psb_surface.h"
33 #include "psb_cmdbuf.h"
34 #include "pnw_H263ES.h"
35 #include "pnw_hostcode.h"
36 #include "pnw_hostheader.h"
37 #include "psb_drv_debug.h"
38 
39 #include <stdlib.h>
40 #include <stdint.h>
41 #include <string.h>
42 
43 
44 #define TOPAZ_H263_MAX_BITRATE 16000000
45 
46 #define INIT_CONTEXT_H263ES    context_ENC_p ctx = (context_ENC_p) (obj_context->format_data)
47 #define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
48 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
49 
50 
pnw_H263ES_QueryConfigAttributes(VAProfile __maybe_unused profile,VAEntrypoint __maybe_unused entrypoint,VAConfigAttrib * attrib_list,int num_attribs)51 static void pnw_H263ES_QueryConfigAttributes(
52     VAProfile __maybe_unused profile,
53     VAEntrypoint __maybe_unused entrypoint,
54     VAConfigAttrib *attrib_list,
55     int num_attribs)
56 {
57     int i;
58     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263ES_QueryConfigAttributes\n");
59 
60     /* RateControl attributes */
61     for (i = 0; i < num_attribs; i++) {
62         switch (attrib_list[i].type) {
63         case VAConfigAttribRTFormat:
64             break;
65 
66         case VAConfigAttribRateControl:
67             attrib_list[i].value = VA_RC_NONE | VA_RC_CBR | VA_RC_VBR;
68             break;
69 
70         default:
71             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
72             break;
73         }
74     }
75 
76 }
77 
78 
pnw_H263ES_ValidateConfig(object_config_p obj_config)79 static VAStatus pnw_H263ES_ValidateConfig(
80     object_config_p obj_config)
81 {
82     int i;
83     /* Check all attributes */
84     for (i = 0; i < obj_config->attrib_count; i++) {
85         switch (obj_config->attrib_list[i].type) {
86         case VAConfigAttribRTFormat:
87             /* Ignore */
88             break;
89         case VAConfigAttribRateControl:
90             break;
91         default:
92             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
93         }
94     }
95 
96     return VA_STATUS_SUCCESS;
97 }
98 
99 
pnw_H263ES_CreateContext(object_context_p obj_context,object_config_p obj_config)100 static VAStatus pnw_H263ES_CreateContext(
101     object_context_p obj_context,
102     object_config_p obj_config)
103 {
104     VAStatus vaStatus = VA_STATUS_SUCCESS;
105     unsigned int eRCmode;
106     context_ENC_p ctx;
107     int i;
108 
109     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263ES_CreateContext\n");
110 
111     vaStatus = pnw_CreateContext(obj_context, obj_config, 0);/* alloc context_ENC_s and BO */
112 
113     if (VA_STATUS_SUCCESS != vaStatus)
114         return VA_STATUS_ERROR_ALLOCATION_FAILED;
115 
116     ctx = (context_ENC_p) obj_context->format_data;
117 
118     for (i = 0; i < obj_config->attrib_count; i++) {
119         if (obj_config->attrib_list[i].type == VAConfigAttribRateControl)
120             break;
121     }
122 
123     if (i >= obj_config->attrib_count)
124         eRCmode = VA_RC_NONE;
125     else
126         eRCmode = obj_config->attrib_list[i].value;
127 
128 
129     if (eRCmode == VA_RC_VBR) {
130         ctx->eCodec = IMG_CODEC_H263_VBR;
131         ctx->sRCParams.RCEnable = IMG_TRUE;
132     } else if (eRCmode == VA_RC_CBR) {
133         ctx->eCodec = IMG_CODEC_H263_CBR;
134         ctx->sRCParams.RCEnable = IMG_TRUE;
135     } else if (eRCmode == VA_RC_NONE) {
136         ctx->eCodec = IMG_CODEC_H263_NO_RC;
137         ctx->sRCParams.RCEnable = IMG_FALSE;
138     } else
139         return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
140     ctx->eFormat = IMG_CODEC_PL12;
141 
142     ctx->Slices = ctx->Height / 16;
143     ctx->ParallelCores = 1; /* H263 encode use only one core from DDKv186 */
144 
145     ctx->IPEControl = pnw__get_ipe_control(ctx->eCodec);
146 
147     return vaStatus;
148 
149 
150 }
151 
152 
pnw_H263ES_DestroyContext(object_context_p obj_context)153 static void pnw_H263ES_DestroyContext(
154     object_context_p obj_context)
155 {
156 
157     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263ES_DestroyContext\n");
158 
159     pnw_DestroyContext(obj_context);
160 }
161 
pnw_H263ES_BeginPicture(object_context_p obj_context)162 static VAStatus pnw_H263ES_BeginPicture(
163     object_context_p obj_context)
164 {
165     VAStatus vaStatus = VA_STATUS_SUCCESS;
166 
167     INIT_CONTEXT_H263ES;
168 
169     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263ES_BeginPicture\n");
170 
171     vaStatus = pnw_BeginPicture(ctx);
172 
173     return vaStatus;
174 }
175 
176 
pnw__H263ES_process_sequence_param(context_ENC_p ctx,object_buffer_p obj_buffer)177 static VAStatus pnw__H263ES_process_sequence_param(context_ENC_p ctx, object_buffer_p obj_buffer)
178 {
179     /*
180      * process rate control parameters
181      */
182     VAEncSequenceParameterBufferH263 *pSequenceParams;
183     int i;
184     unsigned int frame_size;
185 
186     ASSERT(obj_buffer->type == VAEncSequenceParameterBufferType);
187     ASSERT(obj_buffer->num_elements == 1);
188     ASSERT(obj_buffer->size == sizeof(VAEncSequenceParameterBufferH263));
189     //initialize the frame_rate and qp
190     ctx->sRCParams.InitialQp = 15;
191     ctx->sRCParams.MinQP = 1;
192     ctx->sRCParams.FrameRate = 30;
193 
194     if ((obj_buffer->num_elements != 1) ||
195         (obj_buffer->size != sizeof(VAEncSequenceParameterBufferH263))) {
196         return VA_STATUS_ERROR_UNKNOWN;
197     }
198 
199     pSequenceParams = (VAEncSequenceParameterBufferH263 *) obj_buffer->buffer_data;
200     obj_buffer->buffer_data = NULL;
201     obj_buffer->size = 0;
202 
203     if (pSequenceParams->bits_per_second > TOPAZ_H263_MAX_BITRATE) {
204         ctx->sRCParams.BitsPerSecond = TOPAZ_H263_MAX_BITRATE;
205         drv_debug_msg(VIDEO_DEBUG_GENERAL, " bits_per_second(%d) exceeds \
206 		the maximum bitrate, set it with %d\n",
207                                  pSequenceParams->bits_per_second,
208                                  TOPAZ_H263_MAX_BITRATE);
209     } else
210         ctx->sRCParams.BitsPerSecond = pSequenceParams->bits_per_second;
211 
212     ctx->sRCParams.FrameRate = (pSequenceParams->frame_rate < 1) ? 1 :
213         ((65535 < pSequenceParams->frame_rate) ? 65535 : pSequenceParams->frame_rate);
214     ctx->sRCParams.InitialQp = pSequenceParams->initial_qp;
215     ctx->sRCParams.MinQP = pSequenceParams->min_qp;
216     ctx->sRCParams.BUSize = 0; /* default 0, and will be set in pnw__setup_busize */
217 
218     ctx->sRCParams.BufferSize = ctx->sRCParams.BitsPerSecond;
219     frame_size = ctx->sRCParams.BitsPerSecond / ctx->sRCParams.FrameRate;
220     /*
221         IMG_UINT16 MBRows = 0;
222         if(ctx->Height <= 400)
223             MBRows = 1;
224         else if (ctx->Height < 800)
225             MBRows = 2;
226     */
227     ctx->sRCParams.Slices = ctx->Slices;
228     ctx->sRCParams.QCPOffset = 0;/* FIXME */
229     if (ctx->sRCParams.IntraFreq != pSequenceParams->intra_period
230             && ctx->raw_frame_count != 0
231             && ctx->sRCParams.IntraFreq != 0
232             && ((ctx->obj_context->frame_count + 1) % ctx->sRCParams.IntraFreq) != 0
233             && (!ctx->sRCParams.bDisableFrameSkipping)) {
234         drv_debug_msg(VIDEO_DEBUG_ERROR,
235                 "Changing intra period value in the middle of a GOP is\n"
236                 "not allowed if frame skip isn't disabled.\n"
237                 "it can cause I frame been skipped\n");
238         return VA_STATUS_ERROR_INVALID_PARAMETER;
239     }
240     else
241         ctx->sRCParams.IntraFreq = pSequenceParams->intra_period;
242 
243     ctx->sRCParams.InitialLevel = (3 * ctx->sRCParams.BufferSize) >> 4;
244     /* Aligned with target frame size */
245     ctx->sRCParams.InitialLevel += (frame_size / 2);
246     ctx->sRCParams.InitialLevel /= frame_size;
247     ctx->sRCParams.InitialLevel *= frame_size;
248     ctx->sRCParams.InitialDelay = ctx->sRCParams.BufferSize - ctx->sRCParams.InitialLevel;
249     ctx->buffer_size = ctx->sRCParams.BufferSize;
250 
251     /*if (ctx->sRCParams.BitsPerSecond < 256000)
252         ctx->sRCParams.BufferSize = (9 * ctx->sRCParams.BitsPerSecond) >> 1;
253     else
254         ctx->sRCParams.BufferSize = (5 * ctx->sRCParams.BitsPerSecond) >> 1;*/
255 
256     if (ctx->raw_frame_count == 0) { /* Add Register IO behind begin Picture */
257         for (i = (ctx->ParallelCores - 1); i >= 0; i--)
258             pnw_set_bias(ctx, i);
259     }
260 
261     free(pSequenceParams);
262     return VA_STATUS_SUCCESS;
263 }
264 
265 
266 /* Work done by the followinig funcs in testbench should be done here.
267  * IMG_C_StartPicture()
268  * IMG_C_InsertSync()
269  * APP_H263_SendPictureHeader()
270  * Frame skip must be taken into consideration
271  * */
pnw__H263ES_process_picture_param(context_ENC_p ctx,object_buffer_p obj_buffer)272 static VAStatus pnw__H263ES_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer)
273 {
274     VAStatus vaStatus = VA_STATUS_SUCCESS;
275     VAEncPictureParameterBufferH263 *pBuffer;
276     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
277     H263_SOURCE_FORMAT_TYPE SourceFormatType;
278     int i;
279 
280     ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
281 
282     if ((obj_buffer->num_elements != 1) ||
283         (obj_buffer->size != sizeof(VAEncPictureParameterBufferH263))) {
284         return VA_STATUS_ERROR_UNKNOWN;
285     }
286 
287     /* Transfer ownership of VAEncPictureParameterBufferH263 data */
288     pBuffer = (VAEncPictureParameterBufferH263 *) obj_buffer->buffer_data;
289     obj_buffer->buffer_data = NULL;
290     obj_buffer->size = 0;
291 
292     ctx->ref_surface = SURFACE(pBuffer->reference_picture);
293     ctx->dest_surface = SURFACE(pBuffer->reconstructed_picture);
294     ctx->coded_buf = BUFFER(pBuffer->coded_buf);
295 
296     ctx->RawWidth = pBuffer->picture_width;
297     ctx->RawHeight = pBuffer->picture_height;
298 
299     /* Insert do_header command here */
300 
301     if ((ctx->Width == 128) && (ctx->Height == 96))
302         SourceFormatType = _128x96_SubQCIF;
303     else if ((ctx->Width == 176) && (ctx->Height == 144))
304         SourceFormatType = _176x144_QCIF;
305     else if ((ctx->Width == 352) && (ctx->Height == 288))
306         SourceFormatType = _352x288_CIF;
307     else if ((ctx->Width == 704) && (ctx->Height == 576))
308         SourceFormatType = _704x576_4CIF;
309     else if ((ctx->Width <= 720) && (ctx->Height <= 576))
310         SourceFormatType = 7;
311     else {
312         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Unsupported resolution!\n");
313         return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
314     }
315 
316     memset(cmdbuf->header_mem_p + ctx->pic_header_ofs,
317            0,
318            HEADER_SIZE);
319     pnw__H263_prepare_picture_header(cmdbuf->header_mem_p + ctx->pic_header_ofs,
320                                      ctx->obj_context->frame_count,
321                                      pBuffer->picture_type,
322                                      SourceFormatType,
323                                      ctx->sRCParams.FrameRate,
324                                      ctx->RawWidth,
325                                      ctx->RawHeight);
326 
327     pnw_cmdbuf_insert_command_package(ctx->obj_context,
328                                       ctx->ParallelCores - 1, /* Send to the last core as this will complete first */
329                                       MTX_CMDID_DO_HEADER,
330                                       &cmdbuf->header_mem,
331                                       ctx->pic_header_ofs);
332 
333 
334     /* Prepare START_PICTURE params */
335     /* Actually H263 only use 1 core from DDKv186 */
336     for (i = (ctx->ParallelCores - 1); i >= 0; i--)
337         vaStatus = pnw_RenderPictureParameter(ctx, i);
338 
339     free(pBuffer);
340     return vaStatus;
341 }
342 
343 
pnw__H263ES_process_slice_param(context_ENC_p ctx,object_buffer_p obj_buffer)344 static VAStatus pnw__H263ES_process_slice_param(context_ENC_p ctx, object_buffer_p obj_buffer)
345 {
346     /* Prepare InParams for macros of current slice, insert slice header, insert do slice command */
347     VAEncSliceParameterBuffer *pBuffer;
348     pnw_cmdbuf_p cmdbuf = ctx->obj_context->pnw_cmdbuf;
349     PIC_PARAMS *psPicParams = (PIC_PARAMS *)(cmdbuf->pic_params_p);
350     unsigned int i;
351     int slice_param_idx;
352 
353     ASSERT(obj_buffer->type == VAEncSliceParameterBufferType);
354 
355     /* Transfer ownership of VAEncPictureParameterBufferH263 data */
356     pBuffer = (VAEncSliceParameterBuffer *) obj_buffer->buffer_data;
357     obj_buffer->size = 0;
358 
359     /*In case the slice number changes*/
360     if ((ctx->slice_param_cache != NULL) && (obj_buffer->num_elements != ctx->slice_param_num)) {
361         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Slice number changes. Previous value is %d. Now it's %d\n",
362                                  ctx->slice_param_num, obj_buffer->num_elements);
363         free(ctx->slice_param_cache);
364         ctx->slice_param_cache = NULL;
365         ctx->slice_param_num = 0;
366     }
367 
368     if (NULL == ctx->slice_param_cache) {
369         ctx->slice_param_num = obj_buffer->num_elements;
370         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate %d VAEncSliceParameterBuffer cache buffers\n", 2 * ctx->slice_param_num);
371         ctx->slice_param_cache = calloc(2 * ctx->slice_param_num, sizeof(VAEncSliceParameterBuffer));
372         if (NULL == ctx->slice_param_cache) {
373             drv_debug_msg(VIDEO_DEBUG_ERROR, "Run out of memory!\n");
374             free(obj_buffer->buffer_data);
375             return VA_STATUS_ERROR_ALLOCATION_FAILED;
376         }
377     }
378 
379     for (i = 0; i < obj_buffer->num_elements; i++) {
380         /*Todo list:
381          *1.Insert Do header command
382          *2.setup InRowParams
383          *3.setup Slice params
384          *4.Insert Do slice command
385          * */
386         unsigned char deblock_idc;
387 
388         deblock_idc = pBuffer->slice_flags.bits.disable_deblocking_filter_idc;
389 
390         /* Insert Do Header command, relocation is needed */
391         if (ctx->obj_context->slice_count) {  /*First slice of a frame need not slice header*/
392             memset(cmdbuf->header_mem_p + ctx->slice_header_ofs
393                    + ctx->obj_context->slice_count * HEADER_SIZE,
394                    0,
395                    HEADER_SIZE);
396 
397             pnw__H263_prepare_GOBslice_header(
398                 cmdbuf->header_mem_p + ctx->slice_header_ofs + ctx->obj_context->slice_count * HEADER_SIZE,
399                 ctx->obj_context->slice_count,
400                 ctx->obj_context->frame_count);
401 
402             ctx->LastSliceNum[ctx->SliceToCore] = ctx->obj_context->slice_count;
403 
404             pnw_cmdbuf_insert_command_package(ctx->obj_context,
405                                               ctx->SliceToCore,
406                                               MTX_CMDID_DO_HEADER,
407                                               &cmdbuf->header_mem,
408                                               ctx->slice_header_ofs + ctx->obj_context->slice_count * HEADER_SIZE);
409 
410             if (0 == ctx->SliceToCore) {
411                 ctx->SliceToCore = ctx->ParallelCores;
412             }
413             ctx->SliceToCore--;
414 
415         }
416 
417         if ((pBuffer->start_row_number == 0) && pBuffer->slice_flags.bits.is_intra) {
418             pnw_reset_encoder_params(ctx); /* originally do in BeginPicture, but beginpicture has no intra info */
419             ctx->BelowParamsBufIdx = (ctx->BelowParamsBufIdx + 1) & 0x1;
420         }
421 
422         slice_param_idx = (pBuffer->slice_flags.bits.is_intra ? 0 : 1) * ctx->slice_param_num + i;
423         if (VAEncSliceParameter_Equal(&ctx->slice_param_cache[slice_param_idx], pBuffer) == 0) {
424             /* cache current param parameters */
425             memcpy(&ctx->slice_param_cache[slice_param_idx],
426                    pBuffer, sizeof(VAEncSliceParameterBuffer));
427 
428             /* Setup InParams value*/
429             pnw_setup_slice_params(ctx,
430                                    pBuffer->start_row_number * 16,
431                                    pBuffer->slice_height * 16,
432                                    pBuffer->slice_flags.bits.is_intra,
433                                    ctx->obj_context->frame_count > 0,
434                                    psPicParams->sInParams.SeInitQP);
435         }
436 
437         /* Insert do slice command and setup related buffer value */
438         pnw__send_encode_slice_params(ctx,
439                                       pBuffer->slice_flags.bits.is_intra,
440                                       pBuffer->start_row_number * 16,
441                                       deblock_idc,
442                                       ctx->obj_context->frame_count,
443                                       pBuffer->slice_height * 16,
444                                       ctx->obj_context->slice_count);
445 
446         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Now frame_count/slice_count is %d/%d\n",
447                                  ctx->obj_context->frame_count, ctx->obj_context->slice_count);
448 
449         ctx->obj_context->slice_count++;
450         pBuffer++;        /*Move to the next buffer*/
451 
452         ASSERT(ctx->obj_context->slice_count < MAX_SLICES_PER_PICTURE);
453     }
454 
455     free(obj_buffer->buffer_data);
456     obj_buffer->buffer_data = NULL;
457     return VA_STATUS_SUCCESS;
458 }
459 
460 
461 
pnw_H263ES_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)462 static VAStatus pnw_H263ES_RenderPicture(
463     object_context_p obj_context,
464     object_buffer_p *buffers,
465     int num_buffers)
466 {
467     int i;
468     INIT_CONTEXT_H263ES;
469     VAStatus vaStatus = VA_STATUS_SUCCESS;
470 
471     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263ES_RenderPicture\n");
472 
473     for (i = 0; i < num_buffers; i++) {
474         object_buffer_p obj_buffer = buffers[i];
475 
476         switch (obj_buffer->type) {
477         case VAEncSequenceParameterBufferType:
478             drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263_RenderPicture got VAEncSequenceParameterBufferType\n");
479             vaStatus = pnw__H263ES_process_sequence_param(ctx, obj_buffer);
480             DEBUG_FAILURE;
481             break;
482 
483         case VAEncPictureParameterBufferType:
484             drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263_RenderPicture got VAEncPictureParameterBuffer\n");
485             vaStatus = pnw__H263ES_process_picture_param(ctx, obj_buffer);
486             DEBUG_FAILURE;
487             break;
488 
489         case VAEncSliceParameterBufferType:
490             drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263_RenderPicture got VAEncSliceParameterBufferType\n");
491             vaStatus = pnw__H263ES_process_slice_param(ctx, obj_buffer);
492             DEBUG_FAILURE;
493             break;
494 
495         default:
496             vaStatus = VA_STATUS_ERROR_UNKNOWN;
497             DEBUG_FAILURE;
498         }
499         if (vaStatus != VA_STATUS_SUCCESS) {
500             break;
501         }
502     }
503 
504 
505     return vaStatus;
506 }
507 
pnw_H263ES_EndPicture(object_context_p obj_context)508 static VAStatus pnw_H263ES_EndPicture(
509     object_context_p obj_context)
510 {
511     VAStatus vaStatus = VA_STATUS_SUCCESS;
512     INIT_CONTEXT_H263ES;
513 
514     drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_H263ES_EndPicture\n");
515 
516     vaStatus = pnw_EndPicture(ctx);
517 
518     return vaStatus;
519 }
520 
521 
522 struct format_vtable_s pnw_H263ES_vtable = {
523 queryConfigAttributes:
524     pnw_H263ES_QueryConfigAttributes,
525 validateConfig:
526     pnw_H263ES_ValidateConfig,
527 createContext:
528     pnw_H263ES_CreateContext,
529 destroyContext:
530     pnw_H263ES_DestroyContext,
531 beginPicture:
532     pnw_H263ES_BeginPicture,
533 renderPicture:
534     pnw_H263ES_RenderPicture,
535 endPicture:
536     pnw_H263ES_EndPicture
537 };
538