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_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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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