Home | History | Annotate | Download | only in src
      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 (at) intel.com>
     27  *    Zeng Li <zeng.li (at) 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 
     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 
     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 
    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 
    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 
    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 
    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  * */
    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 
    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 
    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 
    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