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