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