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 *    Zeng Li <zeng.li@intel.com>
27 *    Shengquan Yuan  <shengquan.yuan@intel.com>
28 *    Binglin Chen <binglin.chen@intel.com>
29 *
30 */
31
32#include "psb_def.h"
33#include "psb_surface.h"
34#include "psb_cmdbuf.h"
35#include "lnc_MPEG4ES.h"
36#include "lnc_hostcode.h"
37#include "lnc_hostheader.h"
38#include "psb_drv_debug.h"
39
40#include <stdlib.h>
41#include <stdint.h>
42#include <string.h>
43
44
45#define TOPAZ_MPEG4_MAX_BITRATE 16000000
46
47#define INIT_CONTEXT_MPEG4ES    context_ENC_p ctx = (context_ENC_p) obj_context->format_data
48#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
49#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
50
51
52
53static void lnc_MPEG4ES_QueryConfigAttributes(
54    VAProfile profile,
55    VAEntrypoint entrypoint,
56    VAConfigAttrib *attrib_list,
57    int num_attribs)
58{
59    int i;
60
61    drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_QueryConfigAttributes\n");
62
63    /* RateControl attributes */
64    for (i = 0; i < num_attribs; i++) {
65        switch (attrib_list[i].type) {
66        case VAConfigAttribRTFormat:
67            break;
68
69        case VAConfigAttribRateControl:
70            attrib_list[i].value = VA_RC_NONE | VA_RC_CBR | VA_RC_VBR;
71            break;
72#if 0
73        case VAConfigAttribEncMaxSliceSize:
74            attrib_list[i].value = 0;
75            break;
76#endif
77        default:
78            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
79            break;
80        }
81    }
82
83    return;
84}
85
86
87static VAStatus lnc_MPEG4ES_ValidateConfig(
88    object_config_p obj_config)
89{
90    int i;
91    /* Check all attributes */
92    for (i = 0; i < obj_config->attrib_count; i++) {
93        switch (obj_config->attrib_list[i].type) {
94        case VAConfigAttribRTFormat:
95            /* Ignore */
96            break;
97        case VAConfigAttribRateControl:
98            break;
99        default:
100            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
101        }
102    }
103
104    return VA_STATUS_SUCCESS;
105}
106
107
108static VAStatus lnc_MPEG4ES_CreateContext(
109    object_context_p obj_context,
110    object_config_p obj_config)
111{
112    VAStatus vaStatus = VA_STATUS_SUCCESS;
113    context_ENC_p ctx;
114    int i;
115    unsigned int eRCmode;
116
117    drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_CreateContext\n");
118
119    vaStatus = lnc_CreateContext(obj_context, obj_config);
120    if (VA_STATUS_SUCCESS != vaStatus)
121        return VA_STATUS_ERROR_ALLOCATION_FAILED;
122
123    ctx = (context_ENC_p) obj_context->format_data;
124    ctx->FCode = 3;
125
126    ctx->max_slice_size = 0;
127    eRCmode = VA_RC_NONE;
128
129    for (i = 0; i < obj_config->attrib_count; i++) {
130#if 0
131        if (obj_config->attrib_list[i].type == VAConfigAttribEncMaxSliceSize)
132            ctx->max_slice_size = obj_config->attrib_list[i].value;
133        else if (obj_config->attrib_list[i].type == VAConfigAttribRateControl)
134            eRCmode = obj_config->attrib_list[i].value;
135
136#else
137        if (obj_config->attrib_list[i].type == VAConfigAttribRateControl)
138            eRCmode = obj_config->attrib_list[i].value;
139#endif
140    }
141
142    if (eRCmode == VA_RC_VBR) {
143        ctx->eCodec = IMG_CODEC_MPEG4_VBR;
144        ctx->sRCParams.RCEnable = IMG_TRUE;
145    } else if (eRCmode == VA_RC_CBR) {
146        ctx->eCodec = IMG_CODEC_MPEG4_CBR;
147        ctx->sRCParams.RCEnable = IMG_TRUE;
148    } else if (eRCmode == VA_RC_NONE) {
149        ctx->eCodec = IMG_CODEC_MPEG4_NO_RC;
150        ctx->sRCParams.RCEnable = IMG_FALSE;
151    } else
152        return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
153    ctx->eFormat = IMG_CODEC_PL12;
154
155    ctx->IPEControl = lnc__get_ipe_control(ctx->eCodec);
156
157    switch (obj_config->profile) {
158    case VAProfileMPEG4Simple:
159        ctx->profile_idc = 2;
160        break;
161    case VAProfileMPEG4AdvancedSimple:
162        ctx->profile_idc = 3;
163        break;
164    default:
165        ctx->profile_idc = 2;
166        break;
167    }
168
169    return vaStatus;
170}
171
172
173static void lnc_MPEG4ES_DestroyContext(
174    object_context_p obj_context)
175{
176    drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_DestroyPicture\n");
177
178    lnc_DestroyContext(obj_context);
179}
180
181static VAStatus lnc_MPEG4ES_BeginPicture(
182    object_context_p obj_context)
183{
184    INIT_CONTEXT_MPEG4ES;
185    VAStatus vaStatus = VA_STATUS_SUCCESS;
186
187    drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_BeginPicture\n");
188
189    vaStatus = lnc_BeginPicture(ctx);
190
191    return vaStatus;
192}
193
194static VAStatus lnc__MPEG4ES_process_sequence_param(context_ENC_p ctx, object_buffer_p obj_buffer)
195{
196    VAStatus vaStatus = VA_STATUS_SUCCESS;
197    VAEncSequenceParameterBufferMPEG4 *seq_params;
198    lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
199    MPEG4_PROFILE_TYPE profile;
200
201    ASSERT(obj_buffer->type == VAEncSequenceParameterBufferType);
202    ASSERT(obj_buffer->num_elements == 1);
203    ASSERT(obj_buffer->size == sizeof(VAEncSequenceParameterBufferMPEG4));
204
205    if ((obj_buffer->num_elements != 1) ||
206        (obj_buffer->size != sizeof(VAEncSequenceParameterBufferMPEG4))) {
207        return VA_STATUS_ERROR_UNKNOWN;
208    }
209
210    seq_params = (VAEncSequenceParameterBufferMPEG4 *) obj_buffer->buffer_data;
211    obj_buffer->buffer_data = NULL;
212    obj_buffer->size = 0;
213
214    if ((ctx->obj_context->frame_count != 0) &&
215        (ctx->sRCParams.BitsPerSecond != seq_params->bits_per_second))
216        ctx->update_rc_control = 1;
217
218    if (seq_params->bits_per_second > TOPAZ_MPEG4_MAX_BITRATE) {
219        ctx->sRCParams.BitsPerSecond = TOPAZ_MPEG4_MAX_BITRATE;
220        drv_debug_msg(VIDEO_DEBUG_GENERAL, " bits_per_second(%d) exceeds \
221		the maximum bitrate, set it with %d\n",
222                                 seq_params->bits_per_second,
223                                 TOPAZ_MPEG4_MAX_BITRATE);
224    } else
225        ctx->sRCParams.BitsPerSecond = seq_params->bits_per_second;
226
227    if (seq_params->initial_qp < 3)
228        seq_params->initial_qp = 3;
229
230    ctx->sRCParams.FrameRate = seq_params->frame_rate;
231    ctx->sRCParams.InitialQp = seq_params->initial_qp;
232    ctx->sRCParams.MinQP = seq_params->min_qp;
233    ctx->sRCParams.BUSize = 0;  /* default 0, and will be set in lnc__setup_busize */
234
235    ctx->sRCParams.Slices = 1;
236    ctx->sRCParams.IntraFreq = seq_params->intra_period;
237
238    cmdbuf = ctx->obj_context->lnc_cmdbuf;
239
240    switch (ctx->profile_idc) {
241    case 2:
242        profile = SP;
243        break;
244    case 3:
245        profile = ASP;
246        break;
247    default:
248        profile = SP;
249        break;
250    }
251
252    lnc__MPEG4_prepare_sequence_header(
253        (IMG_UINT32 *)(cmdbuf->header_mem_p + ctx->seq_header_ofs),
254        0, /* BFrame? */
255        profile, /* sProfile */
256        seq_params->profile_and_level_indication, /* */
257        seq_params->fixed_vop_time_increment, /*3,*/  /* sFixed_vop_time_increment */
258        seq_params->video_object_layer_width,/* Picture_Width_Pixels */
259        seq_params->video_object_layer_height, /* Picture_Height_Pixels */
260        0, /*   bVBVPresent  */
261        0, /*   First_half_bit_rate   */
262        0, /*   Latter_half_bit_rate */
263        0, /*   First_half_vbv_buffer_size */
264        0, /*   Latter_half_vbv_buffer_size  */
265        0, /*   First_half_vbv_occupancy */
266        0, /*   Latter_half_vbv_occupancy */
267        seq_params->vop_time_increment_resolution); /* VopTimeResolution */
268
269    ctx->MPEG4_vop_time_increment_resolution = seq_params->vop_time_increment_resolution;
270
271    lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_DO_HEADER, 2, 0);
272    RELOC_CMDBUF(cmdbuf->cmd_idx++, ctx->seq_header_ofs, &cmdbuf->header_mem);
273
274    free(seq_params);
275    return vaStatus;
276}
277
278
279static VAStatus lnc__MPEG4ES_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer)
280{
281    VAStatus vaStatus = VA_STATUS_SUCCESS;
282    VAEncPictureParameterBufferMPEG4 *pBuffer;
283    lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
284    IMG_BOOL bIsVOPCoded = IMG_TRUE;
285
286    ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
287
288    if ((obj_buffer->num_elements != 1) ||
289        (obj_buffer->size != sizeof(VAEncPictureParameterBufferMPEG4))) {
290        return VA_STATUS_ERROR_UNKNOWN;
291    }
292
293    /* Transfer ownership of VAEncPictureParameterBufferMPEG4 data */
294    pBuffer = (VAEncPictureParameterBufferMPEG4 *) obj_buffer->buffer_data;
295    obj_buffer->buffer_data = NULL;
296    obj_buffer->size = 0;
297
298    ctx->ref_surface = SURFACE(pBuffer->reference_picture);
299    ctx->dest_surface = SURFACE(pBuffer->reconstructed_picture);
300    ctx->coded_buf = BUFFER(pBuffer->coded_buf);
301
302    ASSERT(ctx->Width == pBuffer->picture_width);
303    ASSERT(ctx->Height == pBuffer->picture_height);
304
305    if (ctx->sRCParams.RCEnable && ctx->sRCParams.FrameSkip)
306        bIsVOPCoded = IMG_FALSE;
307
308    /* save current cmdbuf write pointer for MPEG4 frameskip redo
309     * MPEG4 picture header need re-patch, and no slice header needed
310     * for a skipped frame
311     */
312    cmdbuf->cmd_idx_saved_frameskip = cmdbuf->cmd_idx;
313
314    lnc__MPEG4_prepare_vop_header((IMG_UINT32 *)(cmdbuf->header_mem_p + ctx->pic_header_ofs),
315                                  bIsVOPCoded,
316                                  pBuffer->vop_time_increment, /* In testbench, this should be FrameNum */
317                                  4,/* default value is 4,search range */
318                                  pBuffer->picture_type,
319                                  ctx->MPEG4_vop_time_increment_resolution/* defaule value */);
320
321    lnc_cmdbuf_insert_command(cmdbuf, MTX_CMDID_DO_HEADER, 2, 1);
322    RELOC_CMDBUF(cmdbuf->cmd_idx++, ctx->pic_header_ofs, &cmdbuf->header_mem);
323
324    vaStatus = lnc_RenderPictureParameter(ctx);
325
326    free(pBuffer);
327    return vaStatus;
328}
329
330static VAStatus lnc__MPEG4ES_process_slice_param(context_ENC_p ctx, object_buffer_p obj_buffer)
331{
332    VAStatus vaStatus = VA_STATUS_SUCCESS;
333    VAEncSliceParameterBuffer *pBuffer;
334    lnc_cmdbuf_p cmdbuf = ctx->obj_context->lnc_cmdbuf;
335    PIC_PARAMS *psPicParams = (PIC_PARAMS *)(cmdbuf->pic_params_p);
336    unsigned int i;
337    int slice_param_idx;
338
339    ASSERT(obj_buffer->type == VAEncSliceParameterBufferType);
340
341    pBuffer = (VAEncSliceParameterBuffer *) obj_buffer->buffer_data;
342
343    if (0 == pBuffer->start_row_number) {
344        if (pBuffer->slice_flags.bits.is_intra)
345            RELOC_PIC_PARAMS(&psPicParams->InParamsBase, ctx->in_params_ofs, cmdbuf->topaz_in_params_I);
346        else
347            RELOC_PIC_PARAMS(&psPicParams->InParamsBase, ctx->in_params_ofs, cmdbuf->topaz_in_params_P);
348    }
349
350    /*In case the slice number changes*/
351    if ((ctx->slice_param_cache != NULL) && (obj_buffer->num_elements != ctx->slice_param_num)) {
352        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Slice number changes. Previous value is %d. Now it's %d\n",
353                                 ctx->slice_param_num, obj_buffer->num_elements);
354        free(ctx->slice_param_cache);
355        ctx->slice_param_cache = NULL;
356        ctx->slice_param_num = 0;
357    }
358
359    if (NULL == ctx->slice_param_cache) {
360        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate %d VAEncSliceParameterBuffer cache buffers\n", 2 * ctx->slice_param_num);
361        ctx->slice_param_num = obj_buffer->num_elements;
362        ctx->slice_param_cache = calloc(2 * ctx->slice_param_num, sizeof(VAEncSliceParameterBuffer));
363        if (NULL == ctx->slice_param_cache) {
364            drv_debug_msg(VIDEO_DEBUG_ERROR, "Run out of memory!\n");
365            free(obj_buffer->buffer_data);
366            return VA_STATUS_ERROR_ALLOCATION_FAILED;
367        }
368    }
369
370    for (i = 0; i < obj_buffer->num_elements; i++) {
371        if (!(ctx->sRCParams.RCEnable && ctx->sRCParams.FrameSkip)) {
372            if ((ctx->obj_context->frame_count == 0) && (pBuffer->start_row_number == 0) && pBuffer->slice_flags.bits.is_intra)
373                lnc_reset_encoder_params(ctx);
374
375            /*The corresponding slice buffer cache*/
376            slice_param_idx = (pBuffer->slice_flags.bits.is_intra ? 0 : 1) * ctx->slice_param_num + i;
377
378            if (VAEncSliceParameter_Equal(&ctx->slice_param_cache[slice_param_idx], pBuffer) == 0) {
379                /* cache current param parameters */
380                memcpy(&ctx->slice_param_cache[slice_param_idx],
381                       pBuffer, sizeof(VAEncSliceParameterBuffer));
382
383                /* Setup InParams value*/
384                lnc_setup_slice_params(ctx,
385                                       pBuffer->start_row_number * 16,
386                                       pBuffer->slice_height * 16,
387                                       pBuffer->slice_flags.bits.is_intra,
388                                       ctx->obj_context->frame_count > 0,
389                                       psPicParams->sInParams.SeInitQP);
390            }
391
392            lnc__send_encode_slice_params(ctx,
393                                          pBuffer->slice_flags.bits.is_intra,
394                                          pBuffer->start_row_number * 16,
395                                          IMG_FALSE,    /* Deblock is off for MPEG4*/
396                                          ctx->obj_context->frame_count,
397                                          pBuffer->slice_height * 16,
398                                          ctx->obj_context->slice_count,
399                                          ctx->max_slice_size);
400
401            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Now frame_count/slice_count is %d/%d\n",
402                                     ctx->obj_context->frame_count, ctx->obj_context->slice_count);
403        }
404        ctx->obj_context->slice_count++;
405        pBuffer++;
406
407        ASSERT(ctx->obj_context->slice_count < MAX_SLICES_PER_PICTURE);
408    }
409
410    free(obj_buffer->buffer_data);
411    obj_buffer->buffer_data = NULL;
412
413    return vaStatus;
414}
415
416static VAStatus lnc__MPEG4ES_process_misc_param(context_ENC_p ctx, object_buffer_p obj_buffer)
417{
418    /* Prepare InParams for macros of current slice, insert slice header, insert do slice command */
419    VAEncMiscParameterBuffer *pBuffer;
420    VAEncMiscParameterRateControl *rate_control_param;
421    VAEncMiscParameterAIR *air_param;
422    VAEncMiscParameterMaxSliceSize *max_slice_size_param;
423    VAEncMiscParameterFrameRate *frame_rate_param;
424
425    VAStatus vaStatus = VA_STATUS_SUCCESS;
426
427    ASSERT(obj_buffer->type == VAEncMiscParameterBufferType);
428
429    pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
430    obj_buffer->size = 0;
431
432    switch (pBuffer->type) {
433    case VAEncMiscParameterTypeFrameRate:
434        frame_rate_param = (VAEncMiscParameterFrameRate *)pBuffer->data;
435        drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: frame rate changed to %d\n",
436                                 frame_rate_param->framerate);
437        break;
438
439    case VAEncMiscParameterTypeRateControl:
440        rate_control_param = (VAEncMiscParameterRateControl *)pBuffer->data;
441
442        drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: bit rate changed to %d\n",
443                                 rate_control_param->bits_per_second);
444
445        if (rate_control_param->bits_per_second == ctx->sRCParams.BitsPerSecond)
446            break;
447        else
448            ctx->update_rc_control = 1;
449
450        if (rate_control_param->bits_per_second > TOPAZ_MPEG4_MAX_BITRATE) {
451            ctx->sRCParams.BitsPerSecond = TOPAZ_MPEG4_MAX_BITRATE;
452            drv_debug_msg(VIDEO_DEBUG_GENERAL, " bits_per_second(%d) exceeds \
453		the maximum bitrate, set it with %d\n",
454                                     rate_control_param->bits_per_second,
455                                     TOPAZ_MPEG4_MAX_BITRATE);
456        } else
457            ctx->sRCParams.BitsPerSecond = rate_control_param->bits_per_second;
458
459        break;
460
461    case VAEncMiscParameterTypeMaxSliceSize:
462        max_slice_size_param = (VAEncMiscParameterMaxSliceSize *)pBuffer->data;
463
464        if (ctx->max_slice_size == max_slice_size_param->max_slice_size)
465            break;
466
467        drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: max slice size changed to %d\n",
468                                 max_slice_size_param->max_slice_size);
469
470        ctx->max_slice_size = max_slice_size_param->max_slice_size;
471
472        break;
473
474    case VAEncMiscParameterTypeAIR:
475        air_param = (VAEncMiscParameterAIR *)pBuffer->data;
476
477        drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: air slice size changed to num_air_mbs %d "
478                                 "air_threshold %d, air_auto %d\n",
479                                 air_param->air_num_mbs, air_param->air_threshold,
480                                 air_param->air_auto);
481
482        ctx->num_air_mbs = air_param->air_num_mbs;
483        ctx->air_threshold = air_param->air_threshold;
484        ctx->autotune_air_flag = air_param->air_auto;
485
486        break;
487
488    default:
489        vaStatus = VA_STATUS_ERROR_UNKNOWN;
490        DEBUG_FAILURE;
491        break;
492    }
493
494    free(obj_buffer->buffer_data);
495    obj_buffer->buffer_data = NULL;
496
497    return VA_STATUS_SUCCESS;
498}
499
500static VAStatus lnc_MPEG4ES_RenderPicture(
501    object_context_p obj_context,
502    object_buffer_p *buffers,
503    int num_buffers)
504{
505    INIT_CONTEXT_MPEG4ES;
506    VAStatus vaStatus = VA_STATUS_SUCCESS;
507    int i;
508
509    drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_RenderPicture\n");
510
511    for (i = 0; i < num_buffers; i++) {
512        object_buffer_p obj_buffer = buffers[i];
513
514        switch (obj_buffer->type) {
515        case VAEncSequenceParameterBufferType:
516            drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_RenderPicture got VAEncSequenceParameterBufferType\n");
517            vaStatus = lnc__MPEG4ES_process_sequence_param(ctx, obj_buffer);
518            DEBUG_FAILURE;
519            break;
520
521        case VAEncPictureParameterBufferType:
522            drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_RenderPicture got VAEncPictureParameterBufferType\n");
523            vaStatus = lnc__MPEG4ES_process_picture_param(ctx, obj_buffer);
524            DEBUG_FAILURE;
525            break;
526
527        case VAEncSliceParameterBufferType:
528            drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_RenderPicture got VAEncSliceParameterBufferType\n");
529            vaStatus = lnc__MPEG4ES_process_slice_param(ctx, obj_buffer);
530            DEBUG_FAILURE;
531            break;
532
533        case VAEncMiscParameterBufferType:
534            drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_RenderPicture got VAEncMiscParameterBufferType\n");
535            vaStatus = lnc__MPEG4ES_process_misc_param(ctx, obj_buffer);
536            DEBUG_FAILURE;
537            break;
538
539        default:
540            vaStatus = VA_STATUS_ERROR_UNKNOWN;
541            DEBUG_FAILURE;
542        }
543    }
544
545    return vaStatus;
546}
547
548static VAStatus lnc_MPEG4ES_EndPicture(
549    object_context_p obj_context)
550{
551    INIT_CONTEXT_MPEG4ES;
552
553    drv_debug_msg(VIDEO_DEBUG_GENERAL, "lnc_MPEG4ES_EndPicture\n");
554    return lnc_EndPicture(ctx);
555}
556
557
558struct format_vtable_s lnc_MPEG4ES_vtable = {
559queryConfigAttributes:
560    lnc_MPEG4ES_QueryConfigAttributes,
561validateConfig:
562    lnc_MPEG4ES_ValidateConfig,
563createContext:
564    lnc_MPEG4ES_CreateContext,
565destroyContext:
566    lnc_MPEG4ES_DestroyContext,
567beginPicture:
568    lnc_MPEG4ES_BeginPicture,
569renderPicture:
570    lnc_MPEG4ES_RenderPicture,
571endPicture:
572    lnc_MPEG4ES_EndPicture
573};
574