Home | History | Annotate | Download | only in src
      1 /*
      2  INTEL CONFIDENTIAL
      3  Copyright 2009 Intel Corporation All Rights Reserved.
      4  The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intels prior express written permission.
      5 
      6  No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
      7  */
      8 #include <glib.h>
      9 #include <string.h>
     10 #include "mixvideolog.h"
     11 #include "mixvideoformat_mp42.h"
     12 
     13 enum {
     14 	MP4_VOP_TYPE_I = 0,
     15 	MP4_VOP_TYPE_P = 1,
     16 	MP4_VOP_TYPE_B = 2,
     17 	MP4_VOP_TYPE_S = 3,
     18 };
     19 
     20 /*
     21  * This is for divx packed stream
     22  */
     23 typedef struct _PackedStream PackedStream;
     24 struct _PackedStream {
     25 	vbp_picture_data_mp42 *picture_data;
     26 	MixBuffer *mix_buffer;
     27 };
     28 
     29 /*
     30  * Clone and destroy vbp_picture_data_mp42
     31  */
     32 static vbp_picture_data_mp42 *mix_videoformat_mp42_clone_picture_data(
     33 		vbp_picture_data_mp42 *picture_data);
     34 static void mix_videoformat_mp42_free_picture_data(
     35 		vbp_picture_data_mp42 *picture_data);
     36 static void mix_videoformat_mp42_flush_packed_stream_queue(
     37 		GQueue *packed_stream_queue);
     38 
     39 /* The parent class. The pointer will be saved
     40  * in this class's initialization. The pointer
     41  * can be used for chaining method call if needed.
     42  */
     43 static MixVideoFormatClass *parent_class = NULL;
     44 
     45 static void mix_videoformat_mp42_finalize(GObject * obj);
     46 
     47 /*
     48  * Please note that the type we pass to G_DEFINE_TYPE is MIX_TYPE_VIDEOFORMAT
     49  */
     50 G_DEFINE_TYPE( MixVideoFormat_MP42, mix_videoformat_mp42, MIX_TYPE_VIDEOFORMAT);
     51 
     52 static void mix_videoformat_mp42_init(MixVideoFormat_MP42 * self) {
     53 	MixVideoFormat *parent = MIX_VIDEOFORMAT(self);
     54 
     55 	self->reference_frames[0] = NULL;
     56 	self->reference_frames[1] = NULL;
     57 
     58 	self->last_frame = NULL;
     59 	self->last_vop_coding_type = -1;
     60 
     61 	self->packed_stream_queue = NULL;
     62 
     63 	/* NOTE: we don't need to do this here.
     64 	 * This just demostrates how to access
     65 	 * member varibles beloned to parent
     66 	 */
     67 	parent->initialized = FALSE;
     68 }
     69 
     70 static void mix_videoformat_mp42_class_init(MixVideoFormat_MP42Class * klass) {
     71 
     72 	/* root class */
     73 	GObjectClass *gobject_class = (GObjectClass *) klass;
     74 
     75 	/* direct parent class */
     76 	MixVideoFormatClass *video_format_class = MIX_VIDEOFORMAT_CLASS(klass);
     77 
     78 	/* parent class for later use */
     79 	parent_class = g_type_class_peek_parent(klass);
     80 
     81 	/* setup finializer */
     82 	gobject_class->finalize = mix_videoformat_mp42_finalize;
     83 
     84 	/* setup vmethods with base implementation */
     85 	video_format_class->getcaps = mix_videofmt_mp42_getcaps;
     86 	video_format_class->initialize = mix_videofmt_mp42_initialize;
     87 	video_format_class->decode = mix_videofmt_mp42_decode;
     88 	video_format_class->flush = mix_videofmt_mp42_flush;
     89 	video_format_class->eos = mix_videofmt_mp42_eos;
     90 	video_format_class->deinitialize = mix_videofmt_mp42_deinitialize;
     91 }
     92 
     93 MixVideoFormat_MP42 *mix_videoformat_mp42_new(void) {
     94 	MixVideoFormat_MP42 *ret = g_object_new(MIX_TYPE_VIDEOFORMAT_MP42, NULL);
     95 
     96 	return ret;
     97 }
     98 
     99 void mix_videoformat_mp42_finalize(GObject * obj) {
    100 	/* clean up here. */
    101 
    102 	/*	MixVideoFormat_MP42 *mix = MIX_VIDEOFORMAT_MP42(obj); */
    103 	GObjectClass *root_class = (GObjectClass *) parent_class;
    104 	MixVideoFormat *parent = NULL;
    105 	gint32 vbp_ret = VBP_OK;
    106 	MixVideoFormat_MP42 *self = NULL;
    107 
    108 	LOG_V("Begin\n");
    109 
    110 	if (obj == NULL) {
    111 		LOG_E("obj is NULL\n");
    112 		return;
    113 	}
    114 
    115 	if (!MIX_IS_VIDEOFORMAT_MP42(obj)) {
    116 		LOG_E("obj is not mixvideoformat_mp42\n");
    117 		return;
    118 	}
    119 
    120 	self = MIX_VIDEOFORMAT_MP42(obj);
    121 	parent = MIX_VIDEOFORMAT(self);
    122 
    123 	//surfacepool is deallocated by parent
    124 	//inputbufqueue is deallocated by parent
    125 	//parent calls vaDestroyConfig, vaDestroyContext and vaDestroySurfaces
    126 
    127 	g_mutex_lock(parent->objectlock);
    128 
    129 	/* unref reference frames */
    130 	{
    131 		gint idx = 0;
    132 		for (idx = 0; idx < 2; idx++) {
    133 			if (self->reference_frames[idx] != NULL) {
    134 				mix_videoframe_unref(self->reference_frames[idx]);
    135 				self->reference_frames[idx] = NULL;
    136 			}
    137 		}
    138 	}
    139 
    140 
    141 	/* Reset state */
    142 	parent->initialized = TRUE;
    143 	parent->parse_in_progress = FALSE;
    144 	parent->discontinuity_frame_in_progress = FALSE;
    145 	parent->current_timestamp = 0;
    146 
    147 	/* Close the parser */
    148 	vbp_ret = vbp_close(parent->parser_handle);
    149 	parent->parser_handle = NULL;
    150 
    151 	if (self->packed_stream_queue) {
    152 		mix_videoformat_mp42_flush_packed_stream_queue(self->packed_stream_queue);
    153 		g_queue_free(self->packed_stream_queue);
    154 	}
    155 	self->packed_stream_queue = NULL;
    156 
    157 	g_mutex_unlock(parent->objectlock);
    158 
    159 	/* Chain up parent */
    160 	if (root_class->finalize) {
    161 		root_class->finalize(obj);
    162 	}
    163 
    164 	LOG_V("End\n");
    165 }
    166 
    167 MixVideoFormat_MP42 *
    168 mix_videoformat_mp42_ref(MixVideoFormat_MP42 * mix) {
    169 	return (MixVideoFormat_MP42 *) g_object_ref(G_OBJECT(mix));
    170 }
    171 
    172 /*  MP42 vmethods implementation */
    173 MIX_RESULT mix_videofmt_mp42_getcaps(MixVideoFormat *mix, GString *msg) {
    174 
    175 //This method is reserved for future use
    176 
    177 	LOG_V("Begin\n");
    178 	if (parent_class->getcaps) {
    179 		return parent_class->getcaps(mix, msg);
    180 	}
    181 
    182 	LOG_V("End\n");
    183 	return MIX_RESULT_NOTIMPL;
    184 }
    185 
    186 MIX_RESULT mix_videofmt_mp42_initialize(MixVideoFormat *mix,
    187 		MixVideoConfigParamsDec * config_params, MixFrameManager * frame_mgr,
    188 		MixBufferPool * input_buf_pool, MixSurfacePool ** surface_pool,
    189 		VADisplay va_display) {
    190 	uint32 vbp_ret = 0;
    191 	MIX_RESULT ret = MIX_RESULT_FAIL;
    192 
    193 	vbp_data_mp42 *data = NULL;
    194 	MixVideoFormat *parent = NULL;
    195 	MixIOVec *header = NULL;
    196 
    197 	VAProfile va_profile = VAProfileMPEG4AdvancedSimple;
    198 	VAConfigAttrib attrib;
    199 
    200 	VAStatus va_ret = VA_STATUS_SUCCESS;
    201 	guint number_extra_surfaces = 0;
    202 	VASurfaceID *surfaces = NULL;
    203 	guint numSurfaces = 0;
    204 
    205 	MixVideoFormat_MP42 *self = MIX_VIDEOFORMAT_MP42(mix);
    206 
    207 	if (mix == NULL || config_params == NULL || frame_mgr == NULL) {
    208 		return MIX_RESULT_NULL_PTR;
    209 	}
    210 
    211 	if (!MIX_IS_VIDEOFORMAT_MP42(mix)) {
    212 		return MIX_RESULT_INVALID_PARAM;
    213 	}
    214 
    215 	LOG_V("begin\n");
    216 
    217 	if (parent_class->initialize) {
    218 		ret = parent_class->initialize(mix, config_params, frame_mgr,
    219 				input_buf_pool, surface_pool, va_display);
    220 		if (ret != MIX_RESULT_SUCCESS) {
    221 			LOG_E("Failed to initialize parent!\n");
    222 			return ret;
    223 		}
    224 	}
    225 
    226 	parent = MIX_VIDEOFORMAT(mix);
    227 
    228 	g_mutex_lock(parent->objectlock);
    229 
    230 	parent->initialized = FALSE;
    231 
    232 	vbp_ret = vbp_open(VBP_MPEG4, &(parent->parser_handle));
    233 
    234 	if (vbp_ret != VBP_OK) {
    235 		LOG_E("Failed to call vbp_open()\n");
    236 		ret = MIX_RESULT_FAIL;
    237 		goto cleanup;
    238 	}
    239 
    240 	/*
    241 	 * avidemux doesn't pass codec_data, we need handle this.
    242 	 */
    243 
    244 	LOG_V("Try to get header data from config_param\n");
    245 
    246 	ret = mix_videoconfigparamsdec_get_header(config_params, &header);
    247 	if (ret == MIX_RESULT_SUCCESS && header != NULL) {
    248 
    249 		LOG_V("Found header data from config_param\n");
    250 		vbp_ret = vbp_parse(parent->parser_handle, header->data, header->data_size,
    251 				TRUE);
    252 
    253 		LOG_V("vbp_parse() returns 0x%x\n", vbp_ret);
    254 
    255 		g_free(header->data);
    256 		g_free(header);
    257 
    258 		if (!((vbp_ret == VBP_OK) || (vbp_ret == VBP_DONE))) {
    259 			LOG_E("Failed to call vbp_parse() to parse header data!\n");
    260 			goto cleanup;
    261 		}
    262 
    263 		/* Get the header data and save */
    264 
    265 		LOG_V("Call vbp_query()\n");
    266 		vbp_ret = vbp_query(parent->parser_handle, (void *) &data);
    267 		LOG_V("vbp_query() returns 0x%x\n", vbp_ret);
    268 
    269 		if ((vbp_ret != VBP_OK) || (data == NULL)) {
    270 			LOG_E("Failed to call vbp_query() to query header data parsing result\n");
    271 			goto cleanup;
    272 		}
    273 
    274 		if ((data->codec_data.profile_and_level_indication & 0xF8) == 0xF0) {
    275 			va_profile = VAProfileMPEG4AdvancedSimple;
    276 			LOG_V("The profile is VAProfileMPEG4AdvancedSimple from header data\n");
    277 		} else {
    278 			va_profile = VAProfileMPEG4Simple;
    279 			LOG_V("The profile is VAProfileMPEG4Simple from header data\n");
    280 		}
    281 	}
    282 
    283 	va_display = parent->va_display;
    284 
    285 	/* We are requesting RT attributes */
    286 	attrib.type = VAConfigAttribRTFormat;
    287 
    288 	va_ret = vaGetConfigAttributes(va_display, va_profile, VAEntrypointVLD,
    289 			&attrib, 1);
    290 	if (va_ret != VA_STATUS_SUCCESS) {
    291 		LOG_E("Failed to call vaGetConfigAttributes()\n");
    292 		goto cleanup;
    293 	}
    294 
    295 	if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
    296 		LOG_E("The attrib.value is wrong!\n");
    297 		goto cleanup;
    298 	}
    299 
    300 	va_ret = vaCreateConfig(va_display, va_profile, VAEntrypointVLD, &attrib,
    301 			1, &(parent->va_config));
    302 
    303 	if (va_ret != VA_STATUS_SUCCESS) {
    304 		LOG_E("Failed to call vaCreateConfig()!\n");
    305 		goto cleanup;
    306 	}
    307 
    308 	ret = mix_videoconfigparamsdec_get_extra_surface_allocation(config_params,
    309 			&number_extra_surfaces);
    310 
    311 	if (ret != MIX_RESULT_SUCCESS) {
    312 		LOG_E("Failed to call mix_videoconfigparams_get_extra_surface_allocation()!\n");
    313 		goto cleanup;
    314 	}
    315 
    316 	parent->va_num_surfaces = number_extra_surfaces + 4;
    317 	if (parent->va_num_surfaces > MIX_VIDEO_MP42_SURFACE_NUM) {
    318 		parent->va_num_surfaces = MIX_VIDEO_MP42_SURFACE_NUM;
    319 	}
    320 
    321 	numSurfaces = parent->va_num_surfaces;
    322 
    323 	parent->va_surfaces = g_malloc(sizeof(VASurfaceID) * numSurfaces);
    324 	if (!parent->va_surfaces) {
    325 		LOG_E("Not enough memory to allocate surfaces!\n");
    326 		ret = MIX_RESULT_NO_MEMORY;
    327 		goto cleanup;
    328 	}
    329 
    330 	surfaces = parent->va_surfaces;
    331 
    332 	va_ret = vaCreateSurfaces(va_display, parent->picture_width,
    333 			parent->picture_height, VA_RT_FORMAT_YUV420, numSurfaces,
    334 			surfaces);
    335 	if (va_ret != VA_STATUS_SUCCESS) {
    336 		LOG_E("Failed to call vaCreateSurfaces()!\n");
    337 		goto cleanup;
    338 	}
    339 
    340 	parent->surfacepool = mix_surfacepool_new();
    341 	if (parent->surfacepool == NULL) {
    342 		LOG_E("Not enough memory to create surface pool!\n");
    343 		ret = MIX_RESULT_NO_MEMORY;
    344 		goto cleanup;
    345 	}
    346 
    347 	*surface_pool = parent->surfacepool;
    348 
    349 	ret = mix_surfacepool_initialize(parent->surfacepool, surfaces,
    350 			numSurfaces);
    351 
    352 	/* Initialize and save the VA context ID
    353 	 * Note: VA_PROGRESSIVE libva flag is only relevant to MPEG2
    354 	 */
    355 	va_ret = vaCreateContext(va_display, parent->va_config,
    356 			parent->picture_width, parent->picture_height, 0, surfaces,
    357 			numSurfaces, &(parent->va_context));
    358 
    359 	if (va_ret != VA_STATUS_SUCCESS) {
    360 		LOG_E("Failed to call vaCreateContext()!\n");
    361 		ret = MIX_RESULT_FAIL;
    362 		goto cleanup;
    363 	}
    364 
    365 	/*
    366 	 * Packed stream queue
    367 	 */
    368 
    369 	self->packed_stream_queue = g_queue_new();
    370 	if (!self->packed_stream_queue) {
    371 		LOG_E("Failed to crate packed stream queue!\n");
    372 		ret = MIX_RESULT_NO_MEMORY;
    373 		goto cleanup;
    374 	}
    375 
    376 	self->last_frame = NULL;
    377 	self->last_vop_coding_type = -1;
    378 	parent->initialized = FALSE;
    379 	ret = MIX_RESULT_SUCCESS;
    380 
    381 	cleanup:
    382 
    383 	g_mutex_unlock(parent->objectlock);
    384 
    385 	LOG_V("End\n");
    386 
    387 	return ret;
    388 }
    389 
    390 MIX_RESULT mix_videofmt_mp42_decode(MixVideoFormat *mix, MixBuffer * bufin[],
    391 		gint bufincnt, MixVideoDecodeParams * decode_params) {
    392 	uint32 vbp_ret = 0;
    393 	MixVideoFormat *parent = NULL;
    394 	MIX_RESULT ret = MIX_RESULT_FAIL;
    395 	guint64 ts = 0;
    396 	vbp_data_mp42 *data = NULL;
    397 	gboolean discontinuity = FALSE;
    398 	MixInputBufferEntry *bufentry = NULL;
    399 	gint i = 0;
    400 
    401 	LOG_V("Begin\n");
    402 
    403 	if (mix == NULL || bufin == NULL || decode_params == NULL) {
    404 		return MIX_RESULT_NULL_PTR;
    405 	}
    406 
    407 	if (!MIX_IS_VIDEOFORMAT_MP42(mix)) {
    408 		return MIX_RESULT_INVALID_PARAM;
    409 	}
    410 
    411 	parent = MIX_VIDEOFORMAT(mix);
    412 
    413 	g_mutex_lock(parent->objectlock);
    414 
    415 	ret = mix_videodecodeparams_get_timestamp(decode_params, &ts);
    416 	if (ret != MIX_RESULT_SUCCESS) {
    417 		LOG_E("Failed to get timestamp\n");
    418 		goto cleanup;
    419 	}
    420 
    421 	LOG_I("ts after mix_videodecodeparams_get_timestamp() = %"G_GINT64_FORMAT"\n", ts);
    422 
    423 	ret
    424 			= mix_videodecodeparams_get_discontinuity(decode_params,
    425 					&discontinuity);
    426 	if (ret != MIX_RESULT_SUCCESS) {
    427 		LOG_E("Failed to get discontinuity\n");
    428 		goto cleanup;
    429 	}
    430 
    431 	/*  If this is a new frame and we haven't retrieved parser
    432 	 *	workload data from previous frame yet, do so
    433 	 */
    434 
    435 	if ((ts != parent->current_timestamp) && (parent->parse_in_progress)) {
    436 
    437 		LOG_V("timestamp changed and parsing is still in progress\n");
    438 
    439 		/* this is new data and the old data parsing is not complete, continue
    440 		 * to parse the old data
    441 		 */
    442 		vbp_ret = vbp_query(parent->parser_handle, (void *) &data);
    443 		LOG_V("vbp_query() returns 0x%x\n", vbp_ret);
    444 
    445 		if ((vbp_ret != VBP_OK) || (data == NULL)) {
    446 			ret = MIX_RESULT_FAIL;
    447 			LOG_E("vbp_ret != VBP_OK || data == NULL\n");
    448 			goto cleanup;
    449 		}
    450 
    451 		ret = mix_videofmt_mp42_process_decode(mix, data,
    452 				parent->current_timestamp,
    453 				parent->discontinuity_frame_in_progress);
    454 
    455 		if (ret != MIX_RESULT_SUCCESS) {
    456 			/* We log this but need to process
    457 			 * the new frame data, so do not return
    458 			 */
    459 			LOG_W("process_decode failed.\n");
    460 		}
    461 
    462 		/* we are done parsing for old data */
    463 		parent->parse_in_progress = FALSE;
    464 	}
    465 
    466 	parent->current_timestamp = ts;
    467 	parent->discontinuity_frame_in_progress = discontinuity;
    468 
    469 	/* we parse data buffer one by one */
    470 	for (i = 0; i < bufincnt; i++) {
    471 
    472 		LOG_V(
    473 				"Calling parse for current frame, parse handle %d, buf %x, size %d\n",
    474 				(int) parent->parser_handle, (guint) bufin[i]->data,
    475 				bufin[i]->size);
    476 
    477 		vbp_ret = vbp_parse(parent->parser_handle, bufin[i]->data,
    478 				bufin[i]->size, FALSE);
    479 
    480 		LOG_V("vbp_parse() returns 0x%x\n", vbp_ret);
    481 
    482 		/* The parser failed to parse */
    483 		if (vbp_ret != VBP_DONE && vbp_ret != VBP_OK) {
    484 			LOG_E("vbp_parse() ret = %d\n", vbp_ret);
    485 			ret = MIX_RESULT_FAIL;
    486 			goto cleanup;
    487 		}
    488 
    489 		LOG_V("vbp_parse() ret = %d\n", vbp_ret);
    490 
    491 		if (vbp_ret == VBP_OK || vbp_ret == VBP_DONE) {
    492 
    493 			LOG_V("Now, parsing is done (VBP_DONE)!\n");
    494 
    495 			vbp_ret = vbp_query(parent->parser_handle, (void *) &data);
    496 			LOG_V("vbp_query() returns 0x%x\n", vbp_ret);
    497 
    498 			if ((vbp_ret != VBP_OK) || (data == NULL)) {
    499 				ret = MIX_RESULT_FAIL;
    500 				goto cleanup;
    501 			}
    502 
    503 			/* Increase the ref count of this input buffer */
    504 			mix_buffer_ref(bufin[i]);
    505 
    506 			/* Create a new MixInputBufferEntry
    507 			 * TODO: make this from a pool later
    508 			 */
    509 			bufentry = g_malloc(sizeof(MixInputBufferEntry));
    510 			if (bufentry == NULL) {
    511 				ret = MIX_RESULT_NO_MEMORY;
    512 				goto cleanup;
    513 			}
    514 
    515 			bufentry->buf = bufin[i];
    516 			bufentry->timestamp = ts;
    517 
    518 			LOG_I("bufentry->buf = %x bufentry->timestamp FOR VBP_DONE = %"G_GINT64_FORMAT"\n", bufentry->buf, bufentry->timestamp);
    519 
    520 			/* Enqueue this input buffer */
    521 			g_queue_push_tail(parent->inputbufqueue, (gpointer) bufentry);
    522 
    523 			/* process and decode data */
    524 			ret
    525 					= mix_videofmt_mp42_process_decode(mix, data, ts,
    526 							discontinuity);
    527 
    528 			if (ret != MIX_RESULT_SUCCESS) {
    529 				/* We log this but continue since we need
    530 				 * to complete our processing
    531 				 */
    532 				LOG_W("process_decode failed.\n");
    533 			}
    534 
    535 			LOG_V("Called process and decode for current frame\n");
    536 
    537 			parent->parse_in_progress = FALSE;
    538 
    539 		}
    540 #if 0
    541 		/*
    542 		 * The DHG parser checks for next_sc, if next_sc is a start code, it thinks the current parsing is done: VBP_DONE.
    543 		 * For our situtation, this not the case. The start code is always begin with the gstbuffer. At the end of frame,
    544 		 * the start code is never found.
    545 		 */
    546 
    547 		else if (vbp_ret == VBP_OK) {
    548 
    549 			LOG_V("Now, parsing is not done (VBP_OK)!\n");
    550 
    551 			LOG_V(
    552 					"Enqueuing buffer and going on to next (if any) for this frame\n");
    553 
    554 			/* Increase the ref count of this input buffer */
    555 			mix_buffer_ref(bufin[i]);
    556 
    557 			/* Create a new MixInputBufferEntry
    558 			 * TODO make this from a pool later
    559 			 */
    560 			bufentry = g_malloc(sizeof(MixInputBufferEntry));
    561 			if (bufentry == NULL) {
    562 				ret = MIX_RESULT_FAIL;
    563 				goto cleanup;
    564 			}
    565 
    566 			bufentry->buf = bufin[i];
    567 			bufentry->timestamp = ts;
    568 			LOG_I("bufentry->buf = %x bufentry->timestamp FOR VBP_OK = %"G_GINT64_FORMAT"\n", bufentry->buf, bufentry->timestamp);
    569 
    570 			/* Enqueue this input buffer */
    571 			g_queue_push_tail(parent->inputbufqueue, (gpointer) bufentry);
    572 			parent->parse_in_progress = TRUE;
    573 		}
    574 #endif
    575 	}
    576 
    577 	cleanup:
    578 
    579 	g_mutex_unlock(parent->objectlock);
    580 
    581 	LOG_V("End\n");
    582 
    583 	return ret;
    584 }
    585 
    586 MIX_RESULT mix_videofmt_mp42_process_decode(MixVideoFormat *mix,
    587 		vbp_data_mp42 *data, guint64 timestamp, gboolean discontinuity) {
    588 
    589 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
    590 	VAStatus va_ret = VA_STATUS_SUCCESS;
    591 	VADisplay va_display = NULL;
    592 	VAContextID va_context;
    593 
    594 	MixVideoFormat_MP42 *self = NULL;
    595 	vbp_picture_data_mp42 *picture_data = NULL;
    596 	VAPictureParameterBufferMPEG4 *picture_param = NULL;
    597 	VAIQMatrixBufferMPEG4 *iq_matrix_buffer = NULL;
    598 	vbp_slice_data_mp42 *slice_data = NULL;
    599 	VASliceParameterBufferMPEG4 *slice_param = NULL;
    600 
    601 	gint frame_type = -1;
    602 	guint buffer_id_number = 0;
    603 	guint buffer_id_cnt = 0;
    604 	VABufferID *buffer_ids = NULL;
    605 	MixVideoFrame *frame = NULL;
    606 
    607 	gint idx = 0, jdx = 0;
    608 	gulong surface = 0;
    609 
    610 	MixBuffer *mix_buffer = NULL;
    611 	gboolean is_from_queued_data = FALSE;
    612 
    613 	LOG_V("Begin\n");
    614 
    615 	if ((mix == NULL) || (data == NULL)) {
    616 		return MIX_RESULT_NULL_PTR;
    617 	}
    618 
    619 	if (!MIX_IS_VIDEOFORMAT_MP42(mix)) {
    620 		return MIX_RESULT_INVALID_PARAM;
    621 	}
    622 
    623 	self = MIX_VIDEOFORMAT_MP42(mix);
    624 
    625 	LOG_V("data->number_pictures = %d\n", data->number_pictures);
    626 
    627 	if (data->number_pictures == 0) {
    628 		LOG_W("data->number_pictures == 0\n");
    629 		mix_videofmt_mp42_release_input_buffers(mix, timestamp);
    630 		return ret;
    631 	}
    632 
    633 	is_from_queued_data = FALSE;
    634 
    635 	/* Do we have packed frames? */
    636 	if (data->number_pictures > 1) {
    637 
    638 		/*
    639 
    640 		 Assumption:
    641 
    642 		 1. In one packed frame, there's only one P or I frame and the
    643 		 reference frame will be the first one in the packed frame
    644 		 2. In packed frame, there's no skipped frame(vop_coded = 0)
    645 		 3. In one packed frame, if there're n B frames, there will be
    646 		 n N-VOP frames to follow the packed frame.
    647 		 The timestamp of each N-VOP frame will be used for each B frames
    648 		 in the packed frame
    649 		 4. N-VOP frame is the frame with vop_coded = 0.
    650 
    651 		 {P, B, B, B }, N, N, N, P, P, P, I, ...
    652 
    653 		 */
    654 
    655 		MixInputBufferEntry *bufentry = NULL;
    656 		PackedStream *packed_stream = NULL;
    657 		vbp_picture_data_mp42 *cloned_picture_data = NULL;
    658 
    659 		LOG_V("This is packed frame\n");
    660 
    661 		/*
    662 		 * Is the packed_frame_queue empty? If not, how come
    663 		 * a packed frame can follow another packed frame without
    664 		 * necessary number of N-VOP between them?
    665 		 */
    666 
    667 		if (!g_queue_is_empty(self->packed_stream_queue)) {
    668 			ret = MIX_RESULT_FAIL;
    669 			LOG_E("The previous packed frame is not fully processed yet!\n");
    670 			goto cleanup;
    671 		}
    672 
    673 		/* Packed frame shall be something like this {P, B, B, B, ... B } */
    674 		for (idx = 0; idx < data->number_pictures; idx++) {
    675 			picture_data = &(data->picture_data[idx]);
    676 			picture_param = &(picture_data->picture_param);
    677 			frame_type = picture_param->vop_fields.bits.vop_coding_type;
    678 
    679 			/* Is the first frame in the packed frames a reference frame? */
    680 			if (idx == 0 && frame_type != MP4_VOP_TYPE_I && frame_type
    681 					!= MP4_VOP_TYPE_P) {
    682 				ret = MIX_RESULT_FAIL;
    683 				LOG_E("The first frame in packed frame is not I or B\n");
    684 				goto cleanup;
    685 			}
    686 
    687 			if (idx != 0 && frame_type != MP4_VOP_TYPE_B) {
    688 				ret = MIX_RESULT_FAIL;
    689 				LOG_E("The frame other than the first one in packed frame is not B\n");
    690 				goto cleanup;
    691 			}
    692 
    693 			if (picture_data->vop_coded == 0) {
    694 				ret = MIX_RESULT_FAIL;
    695 				LOG_E("In packed frame, there's unexpected skipped frame\n");
    696 				goto cleanup;
    697 			}
    698 		}
    699 
    700 		LOG_V("The packed frame looks valid\n");
    701 
    702 		/* Okay, the packed-frame looks ok. Now, we enqueue all the B frames */
    703 		bufentry
    704 				= (MixInputBufferEntry *) g_queue_peek_head(mix->inputbufqueue);
    705 		if (bufentry == NULL) {
    706 			ret = MIX_RESULT_FAIL;
    707 			LOG_E("There's data in in inputbufqueue\n");
    708 			goto cleanup;
    709 		}
    710 
    711 		LOG_V("Enqueue all B frames in the packed frame\n");
    712 
    713 		mix_buffer = bufentry->buf;
    714 		for (idx = 1; idx < data->number_pictures; idx++) {
    715 			picture_data = &(data->picture_data[idx]);
    716 			cloned_picture_data = mix_videoformat_mp42_clone_picture_data(
    717 					picture_data);
    718 			if (!cloned_picture_data) {
    719 				ret = MIX_RESULT_NO_MEMORY;
    720 				LOG_E("Failed to allocate memory for cloned picture_data\n");
    721 				goto cleanup;
    722 			}
    723 
    724 			packed_stream = g_malloc(sizeof(PackedStream));
    725 			if (packed_stream == NULL) {
    726 				ret = MIX_RESULT_NO_MEMORY;
    727 				LOG_E("Failed to allocate memory for packed_stream\n");
    728 				goto cleanup;
    729 			}
    730 
    731 			packed_stream->mix_buffer = mix_buffer_ref(mix_buffer);
    732 			packed_stream->picture_data = cloned_picture_data;
    733 
    734 			g_queue_push_tail(self->packed_stream_queue,
    735 					(gpointer) packed_stream);
    736 		}
    737 
    738 		LOG_V("Prepare to decode the first frame in the packed frame\n");
    739 
    740 		/* we are going to process the firs frame */
    741 		picture_data = &(data->picture_data[0]);
    742 
    743 	} else {
    744 
    745 		LOG_V("This is a single frame\n");
    746 
    747 		/* Okay, we only have one frame */
    748 		if (g_queue_is_empty(self->packed_stream_queue)) {
    749 			/* If the packed_stream_queue is empty, everything is fine */
    750 			picture_data = &(data->picture_data[0]);
    751 
    752 			LOG_V("There's no packed frame not processed yet\n");
    753 
    754 		} else {
    755 			/*	The packed_stream_queue is not empty, is this frame N-VOP? */
    756 			picture_data = &(data->picture_data[0]);
    757 			if (picture_data->vop_coded != 0) {
    758 
    759 				LOG_V("The packed frame queue is not empty, we will flush it\n");
    760 
    761 				/*
    762 				 * Unexpected! We flush the packed_stream_queue and begin to process the
    763 				 * current frame if it is not a B frame
    764 				 */
    765 				mix_videoformat_mp42_flush_packed_stream_queue(
    766 						self->packed_stream_queue);
    767 
    768 				picture_param = &(picture_data->picture_param);
    769 				frame_type = picture_param->vop_fields.bits.vop_coding_type;
    770 
    771 				if (frame_type == MP4_VOP_TYPE_B) {
    772 					ret = MIX_RESULT_FAIL;
    773 					LOG_E("The frame right after packed frame is B frame!\n");
    774 					goto cleanup;
    775 				}
    776 
    777 			} else {
    778 				/*	This is N-VOP, process B frame from the packed_stream_queue */
    779 				PackedStream *packed_stream = NULL;
    780 
    781 				LOG_V("N-VOP found, we ignore it and start to process the B frame from the packed frame queue\n");
    782 
    783 				packed_stream = (PackedStream *) g_queue_pop_head(
    784 						self->packed_stream_queue);
    785 				picture_data = packed_stream->picture_data;
    786 				mix_buffer = packed_stream->mix_buffer;
    787 				g_free(packed_stream);
    788 				is_from_queued_data = TRUE;
    789 			}
    790 		}
    791 	}
    792 
    793 	picture_param = &(picture_data->picture_param);
    794 	iq_matrix_buffer = &(picture_data->iq_matrix_buffer);
    795 
    796 	if (picture_param == NULL) {
    797 		ret = MIX_RESULT_NULL_PTR;
    798 		LOG_E("picture_param == NULL\n");
    799 		goto cleanup;
    800 	}
    801 
    802 	/* If the frame type is not I, P or B */
    803 	frame_type = picture_param->vop_fields.bits.vop_coding_type;
    804 	if (frame_type != MP4_VOP_TYPE_I && frame_type != MP4_VOP_TYPE_P
    805 			&& frame_type != MP4_VOP_TYPE_B) {
    806 		ret = MIX_RESULT_FAIL;
    807 		LOG_E("frame_type is not I, P or B. frame_type = %d\n", frame_type);
    808 		goto cleanup;
    809 	}
    810 
    811 	/*
    812 	 * This is a skipped frame (vop_coded = 0)
    813 	 * Please note that this is not a N-VOP (DivX).
    814 	 */
    815 	if (picture_data->vop_coded == 0) {
    816 
    817 		MixVideoFrame *skip_frame = NULL;
    818 		gulong frame_id = VA_INVALID_SURFACE;
    819 
    820 		LOG_V("vop_coded == 0\n");
    821 		if (self->last_frame == NULL) {
    822 			LOG_W("Previous frame is NULL\n");
    823 
    824 			/*
    825 			 * We shouldn't get a skipped frame
    826 			 * before we are able to get a real frame
    827 			 */
    828 			ret = MIX_RESULT_DROPFRAME;
    829 			goto cleanup;
    830 		}
    831 
    832 		skip_frame = mix_videoframe_new();
    833 		ret = mix_videoframe_set_is_skipped(skip_frame, TRUE);
    834 		mix_videoframe_ref(self->last_frame);
    835 
    836 		ret = mix_videoframe_get_frame_id(self->last_frame, &frame_id);
    837 		ret = mix_videoframe_set_frame_id(skip_frame, frame_id);
    838 		ret = mix_videoframe_set_frame_type(skip_frame, MP4_VOP_TYPE_P);
    839 		ret = mix_videoframe_set_real_frame(skip_frame, self->last_frame);
    840 		ret = mix_videoframe_set_timestamp(skip_frame, timestamp);
    841 		ret = mix_videoframe_set_discontinuity(skip_frame, FALSE);
    842 
    843 		LOG_V("Processing skipped frame %x, frame_id set to %d, ts %"G_GINT64_FORMAT"\n",
    844 				(guint)skip_frame, (guint)frame_id, timestamp);
    845 
    846 		/* Release our input buffers */
    847 		ret = mix_videofmt_mp42_release_input_buffers(mix, timestamp);
    848 
    849 		/* Enqueue the skipped frame using frame manager */
    850 		ret = mix_framemanager_enqueue(mix->framemgr, skip_frame);
    851 		goto cleanup;
    852 	}
    853 
    854 	/*
    855 	 * Decide the number of buffer to use
    856 	 */
    857 
    858 	buffer_id_number = picture_data->number_slices * 2 + 2;
    859 	LOG_V("number_slices is %d, allocating %d buffer_ids\n",
    860 			picture_data->number_slices, buffer_id_number);
    861 
    862 	/*
    863 	 * Check for B frames after a seek
    864 	 * We need to have both reference frames in hand before we can decode a B frame
    865 	 * If we don't have both reference frames, we must return MIX_RESULT_DROPFRAME
    866 	 */
    867 	if (frame_type == MP4_VOP_TYPE_B) {
    868 
    869 		if (self->reference_frames[1] == NULL) {
    870 			LOG_W("Insufficient reference frames for B frame\n");
    871 			ret = MIX_RESULT_DROPFRAME;
    872 			goto cleanup;
    873 		}
    874 	}
    875 
    876 	buffer_ids = g_malloc(sizeof(VABufferID) * buffer_id_number);
    877 	if (buffer_ids == NULL) {
    878 		ret = MIX_RESULT_NO_MEMORY;
    879 		LOG_E("Failed to allocate buffer_ids!\n");
    880 		goto cleanup;
    881 	}
    882 
    883 	LOG_V("Getting a new surface\n");LOG_V("frame type is %d\n", frame_type);
    884 
    885 	/* Get a frame from the surface pool */
    886 	ret = mix_surfacepool_get(mix->surfacepool, &frame);
    887 	if (ret != MIX_RESULT_SUCCESS) {
    888 		LOG_E("Failed to get frame from surface pool!\n");
    889 		goto cleanup;
    890 	}
    891 
    892 	/*
    893 	 * Set the frame type for the frame object (used in reordering by frame manager)
    894 	 */
    895 	ret = mix_videoframe_set_frame_type(frame, frame_type);
    896 	if (ret != MIX_RESULT_SUCCESS) {
    897 		LOG_E("Failed to set frame type!\n");
    898 		goto cleanup;
    899 	}
    900 
    901 	/* If I or P frame, update the reference array */
    902 	if ((frame_type == MP4_VOP_TYPE_I) || (frame_type == MP4_VOP_TYPE_P)) {
    903 		LOG_V("Updating forward/backward references for libva\n");
    904 
    905 		self->last_vop_coding_type = frame_type;
    906 		mix_videofmt_mp42_handle_ref_frames(mix, frame_type, frame);
    907 	}
    908 
    909 	LOG_V("Setting reference frames in picparams, frame_type = %d\n",
    910 			frame_type);
    911 
    912 	switch (frame_type) {
    913 	case MP4_VOP_TYPE_I:
    914 		picture_param->forward_reference_picture = VA_INVALID_SURFACE;
    915 		picture_param->backward_reference_picture = VA_INVALID_SURFACE;
    916 		LOG_V("I frame, surface ID %u\n", (guint) frame->frame_id);
    917 		break;
    918 	case MP4_VOP_TYPE_P:
    919 		picture_param-> forward_reference_picture
    920 				= self->reference_frames[0]->frame_id;
    921 		picture_param-> backward_reference_picture = VA_INVALID_SURFACE;
    922 
    923 		LOG_V("P frame, surface ID %u, forw ref frame is %u\n",
    924 				(guint) frame->frame_id,
    925 				(guint) self->reference_frames[0]->frame_id);
    926 		break;
    927 	case MP4_VOP_TYPE_B:
    928 
    929 		picture_param->vop_fields.bits.backward_reference_vop_coding_type
    930 				= self->last_vop_coding_type;
    931 
    932 		picture_param->forward_reference_picture
    933 				= self->reference_frames[1]->frame_id;
    934 		picture_param->backward_reference_picture
    935 				= self->reference_frames[0]->frame_id;
    936 
    937 		LOG_V("B frame, surface ID %u, forw ref %d, back ref %d\n",
    938 				(guint) frame->frame_id,
    939 				(guint) picture_param->forward_reference_picture,
    940 				(guint) picture_param->backward_reference_picture);
    941 		break;
    942 	case MP4_VOP_TYPE_S:
    943 		LOG_W("MP4_VOP_TYPE_S, Will never reach here\n");
    944 		break;
    945 
    946 	default:
    947 		LOG_W("default, Will never reach here\n");
    948 		break;
    949 
    950 	}
    951 
    952 	/* Libva buffer set up */
    953 	va_display = mix->va_display;
    954 	va_context = mix->va_context;
    955 
    956 	LOG_V("Creating libva picture parameter buffer\n");
    957 
    958 	/* First the picture parameter buffer */
    959 	buffer_id_cnt = 0;
    960 	va_ret = vaCreateBuffer(va_display, va_context,
    961 			VAPictureParameterBufferType,
    962 			sizeof(VAPictureParameterBufferMPEG4), 1, picture_param,
    963 			&buffer_ids[buffer_id_cnt]);
    964 	buffer_id_cnt++;
    965 
    966 	if (va_ret != VA_STATUS_SUCCESS) {
    967 		ret = MIX_RESULT_FAIL;
    968 		LOG_E("Failed to create va buffer of type VAPictureParameterBufferMPEG4!\n");
    969 		goto cleanup;
    970 	}
    971 
    972 	LOG_V("Creating libva VAIQMatrixBufferMPEG4 buffer\n");
    973 
    974 	if (picture_param->vol_fields.bits.quant_type) {
    975 		va_ret = vaCreateBuffer(va_display, va_context, VAIQMatrixBufferType,
    976 				sizeof(VAIQMatrixBufferMPEG4), 1, iq_matrix_buffer,
    977 				&buffer_ids[buffer_id_cnt]);
    978 
    979 		if (va_ret != VA_STATUS_SUCCESS) {
    980 			ret = MIX_RESULT_FAIL;
    981 			LOG_E("Failed to create va buffer of type VAIQMatrixBufferType!\n");
    982 			goto cleanup;
    983 		}
    984 		buffer_id_cnt++;
    985 	}
    986 
    987 	/* Now for slices */
    988 	for (jdx = 0; jdx < picture_data->number_slices; jdx++) {
    989 
    990 		slice_data = &(picture_data->slice_data[jdx]);
    991 		slice_param = &(slice_data->slice_param);
    992 
    993 		LOG_V(
    994 				"Creating libva slice parameter buffer, for slice %d\n",
    995 				jdx);
    996 
    997 		/* Do slice parameters */
    998 		va_ret = vaCreateBuffer(va_display, va_context,
    999 				VASliceParameterBufferType,
   1000 				sizeof(VASliceParameterBufferMPEG4), 1, slice_param,
   1001 				&buffer_ids[buffer_id_cnt]);
   1002 		if (va_ret != VA_STATUS_SUCCESS) {
   1003 			ret = MIX_RESULT_FAIL;
   1004 			LOG_E("Failed to create va buffer of type VASliceParameterBufferMPEG4!\n");
   1005 			goto cleanup;
   1006 		}
   1007 		buffer_id_cnt++;
   1008 
   1009 		/* Do slice data */
   1010 		va_ret = vaCreateBuffer(va_display, va_context, VASliceDataBufferType,
   1011 				slice_data->slice_size, 1, slice_data->buffer_addr
   1012 						+ slice_data->slice_offset, &buffer_ids[buffer_id_cnt]);
   1013 		if (va_ret != VA_STATUS_SUCCESS) {
   1014 			ret = MIX_RESULT_FAIL;
   1015 			LOG_E("Failed to create va buffer of type VASliceDataBufferType!\n");
   1016 			goto cleanup;
   1017 		}
   1018 		buffer_id_cnt++;
   1019 	}
   1020 
   1021 	/* Get our surface ID from the frame object */
   1022 	ret = mix_videoframe_get_frame_id(frame, &surface);
   1023 	if (ret != MIX_RESULT_SUCCESS) {
   1024 		LOG_E("Failed to get frame id: ret = 0x%x\n", ret);
   1025 		goto cleanup;
   1026 	}
   1027 
   1028 	LOG_V("Calling vaBeginPicture\n");
   1029 
   1030 	/* Now we can begin the picture */
   1031 	va_ret = vaBeginPicture(va_display, va_context, surface);
   1032 	if (va_ret != VA_STATUS_SUCCESS) {
   1033 		ret = MIX_RESULT_FAIL;
   1034 		LOG_E("Failed to vaBeginPicture(): va_ret = 0x%x\n", va_ret);
   1035 		goto cleanup;
   1036 	}
   1037 
   1038 	LOG_V("Calling vaRenderPicture\n");
   1039 
   1040 	/* Render the picture */
   1041 	va_ret = vaRenderPicture(va_display, va_context, buffer_ids, buffer_id_cnt);
   1042 	if (va_ret != VA_STATUS_SUCCESS) {
   1043 		ret = MIX_RESULT_FAIL;
   1044 		LOG_E("Failed to vaRenderPicture(): va_ret = 0x%x\n", va_ret);
   1045 		goto cleanup;
   1046 	}
   1047 
   1048 	LOG_V("Calling vaEndPicture\n");
   1049 
   1050 	/* End picture */
   1051 	va_ret = vaEndPicture(va_display, va_context);
   1052 	if (va_ret != VA_STATUS_SUCCESS) {
   1053 		ret = MIX_RESULT_FAIL;
   1054 		LOG_E("Failed to vaEndPicture(): va_ret = 0x%x\n", va_ret);
   1055 		goto cleanup;
   1056 	}
   1057 
   1058 	LOG_V("Calling vaSyncSurface\n");
   1059 
   1060 	/* Decode the picture */
   1061 	va_ret = vaSyncSurface(va_display, surface);
   1062 	if (va_ret != VA_STATUS_SUCCESS) {
   1063 		ret = MIX_RESULT_FAIL;
   1064 		LOG_E("Failed to vaSyncSurface(): va_ret = 0x%x\n", va_ret);
   1065 		goto cleanup;
   1066 	}
   1067 
   1068 	/* Set the discontinuity flag */
   1069 	mix_videoframe_set_discontinuity(frame, discontinuity);
   1070 
   1071 	/* Set the timestamp */
   1072 	mix_videoframe_set_timestamp(frame, timestamp);
   1073 
   1074 	LOG_V("Enqueueing the frame with frame manager, timestamp %"G_GINT64_FORMAT"\n", timestamp);
   1075 
   1076 	/* Enqueue the decoded frame using frame manager */
   1077 	ret = mix_framemanager_enqueue(mix->framemgr, frame);
   1078 	if (ret != MIX_RESULT_SUCCESS) {
   1079 		LOG_E("Failed to mix_framemanager_enqueue()!\n");
   1080 		goto cleanup;
   1081 	}
   1082 
   1083 	/* For I or P frames, save this frame off for skipped frame handling */
   1084 	if ((frame_type == MP4_VOP_TYPE_I) || (frame_type == MP4_VOP_TYPE_P)) {
   1085 		if (self->last_frame != NULL) {
   1086 			mix_videoframe_unref(self->last_frame);
   1087 		}
   1088 		self->last_frame = frame;
   1089 		mix_videoframe_ref(frame);
   1090 	}
   1091 
   1092 	ret = MIX_RESULT_SUCCESS;
   1093 
   1094 	cleanup:
   1095 
   1096 	if (ret != MIX_RESULT_SUCCESS && frame != NULL) {
   1097 		mix_videoframe_unref(frame);
   1098 	}
   1099 
   1100 	if (ret != MIX_RESULT_SUCCESS) {
   1101 		mix_videoformat_mp42_flush_packed_stream_queue(
   1102 				self->packed_stream_queue);
   1103 	}
   1104 
   1105 	g_free(buffer_ids);
   1106 	mix_videofmt_mp42_release_input_buffers(mix, timestamp);
   1107 
   1108 	if (is_from_queued_data) {
   1109 		if (mix_buffer) {
   1110 			mix_buffer_unref(mix_buffer);
   1111 		}
   1112 		mix_videoformat_mp42_free_picture_data(picture_data);
   1113 	}
   1114 
   1115 	LOG_V("End\n");
   1116 
   1117 	return ret;
   1118 }
   1119 
   1120 MIX_RESULT mix_videofmt_mp42_flush(MixVideoFormat *mix) {
   1121 
   1122 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
   1123 	MixVideoFormat_MP42 *self = MIX_VIDEOFORMAT_MP42(mix);
   1124 	MixInputBufferEntry *bufentry = NULL;
   1125 
   1126 	LOG_V("Begin\n");
   1127 
   1128 	g_mutex_lock(mix->objectlock);
   1129 
   1130 	mix_videoformat_mp42_flush_packed_stream_queue(self->packed_stream_queue);
   1131 
   1132 	/*
   1133 	 * Clear the contents of inputbufqueue
   1134 	 */
   1135 	while (!g_queue_is_empty(mix->inputbufqueue)) {
   1136 		bufentry = (MixInputBufferEntry *) g_queue_pop_head(mix->inputbufqueue);
   1137 		if (bufentry == NULL) {
   1138 			continue;
   1139 		}
   1140 
   1141 		mix_buffer_unref(bufentry->buf);
   1142 		g_free(bufentry);
   1143 	}
   1144 
   1145 	/*
   1146 	 * Clear parse_in_progress flag and current timestamp
   1147 	 */
   1148 	mix->parse_in_progress = FALSE;
   1149 	mix->discontinuity_frame_in_progress = FALSE;
   1150 	mix->current_timestamp = 0;
   1151 
   1152 	{
   1153 		gint idx = 0;
   1154 		for (idx = 0; idx < 2; idx++) {
   1155 			if (self->reference_frames[idx] != NULL) {
   1156 				mix_videoframe_unref(self->reference_frames[idx]);
   1157 				self->reference_frames[idx] = NULL;
   1158 			}
   1159 		}
   1160 	}
   1161 
   1162 	/* Call parser flush */
   1163 	vbp_flush(mix->parser_handle);
   1164 
   1165 	g_mutex_unlock(mix->objectlock);
   1166 
   1167 	LOG_V("End\n");
   1168 
   1169 	return ret;
   1170 }
   1171 
   1172 MIX_RESULT mix_videofmt_mp42_eos(MixVideoFormat *mix) {
   1173 
   1174 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
   1175 	vbp_data_mp42 *data = NULL;
   1176 	uint32 vbp_ret = 0;
   1177 
   1178 	LOG_V("Begin\n");
   1179 
   1180 	if (mix == NULL) {
   1181 		return MIX_RESULT_NULL_PTR;
   1182 	}
   1183 
   1184 	if (!MIX_IS_VIDEOFORMAT_MP42(mix)) {
   1185 		return MIX_RESULT_INVALID_PARAM;
   1186 	}
   1187 
   1188 	g_mutex_lock(mix->objectlock);
   1189 
   1190 	/* if a frame is in progress, process the frame */
   1191 	if (mix->parse_in_progress) {
   1192 		/* query for data */
   1193 		vbp_ret = vbp_query(mix->parser_handle, (void *) &data);
   1194 		LOG_V("vbp_query() returns 0x%x\n", vbp_ret);
   1195 
   1196 		if ((vbp_ret != VBP_OK) || (data == NULL)) {
   1197 			ret = MIX_RESULT_FAIL;
   1198 			LOG_E("vbp_ret != VBP_OK || data == NULL\n");
   1199 			goto cleanup;
   1200 		}
   1201 
   1202 		/* process and decode data */
   1203 		ret = mix_videofmt_mp42_process_decode(mix, data,
   1204 				mix->current_timestamp, mix->discontinuity_frame_in_progress);
   1205 		mix->parse_in_progress = FALSE;
   1206 
   1207 	}
   1208 
   1209 	ret = mix_framemanager_eos(mix->framemgr);
   1210 
   1211 	cleanup:
   1212 
   1213 	g_mutex_unlock(mix->objectlock);
   1214 
   1215 	LOG_V("End\n");
   1216 
   1217 	return ret;
   1218 }
   1219 
   1220 MIX_RESULT mix_videofmt_mp42_deinitialize(MixVideoFormat *mix) {
   1221 
   1222 	/*
   1223 	 * We do the all the cleanup in _finalize
   1224 	 */
   1225 
   1226 	MIX_RESULT ret = MIX_RESULT_FAIL;
   1227 
   1228 	LOG_V("Begin\n");
   1229 
   1230 	if (mix == NULL) {
   1231 		LOG_V("mix is NULL\n");
   1232 		return MIX_RESULT_NULL_PTR;
   1233 	}
   1234 
   1235 	if (!MIX_IS_VIDEOFORMAT_MP42(mix)) {
   1236 		LOG_V("mix is not mixvideoformat_mp42\n");
   1237 		return MIX_RESULT_INVALID_PARAM;
   1238 	}
   1239 
   1240 	if (parent_class->deinitialize) {
   1241 		ret = parent_class->deinitialize(mix);
   1242 	}
   1243 
   1244 	LOG_V("End\n");
   1245 	return ret;
   1246 }
   1247 
   1248 MIX_RESULT mix_videofmt_mp42_handle_ref_frames(MixVideoFormat *mix,
   1249 		enum _picture_type frame_type, MixVideoFrame * current_frame) {
   1250 
   1251 	MixVideoFormat_MP42 *self = MIX_VIDEOFORMAT_MP42(mix);
   1252 
   1253 	LOG_V("Begin\n");
   1254 
   1255 	if (mix == NULL || current_frame == NULL) {
   1256 		return MIX_RESULT_NULL_PTR;
   1257 	}
   1258 
   1259 	switch (frame_type) {
   1260 	case MP4_VOP_TYPE_I:
   1261 	case MP4_VOP_TYPE_P:
   1262 		LOG_V("Refing reference frame %x\n", (guint) current_frame);
   1263 
   1264 		mix_videoframe_ref(current_frame);
   1265 
   1266 		/* should only happen on first frame */
   1267 		if (self->reference_frames[0] == NULL) {
   1268 			self->reference_frames[0] = current_frame;
   1269 			/* should only happen on second frame */
   1270 		} else if (self->reference_frames[1] == NULL) {
   1271 			self->reference_frames[1] = current_frame;
   1272 		} else {
   1273 			LOG_V("Releasing reference frame %x\n",
   1274 					(guint) self->reference_frames[0]);
   1275 			mix_videoframe_unref(self->reference_frames[0]);
   1276 			self->reference_frames[0] = self->reference_frames[1];
   1277 			self->reference_frames[1] = current_frame;
   1278 		}
   1279 		break;
   1280 	case MP4_VOP_TYPE_B:
   1281 	case MP4_VOP_TYPE_S:
   1282 	default:
   1283 		break;
   1284 
   1285 	}
   1286 
   1287 	LOG_V("End\n");
   1288 
   1289 	return MIX_RESULT_SUCCESS;
   1290 }
   1291 
   1292 MIX_RESULT mix_videofmt_mp42_release_input_buffers(MixVideoFormat *mix,
   1293 		guint64 timestamp) {
   1294 
   1295 	MixInputBufferEntry *bufentry = NULL;
   1296 	gboolean done = FALSE;
   1297 
   1298 	LOG_V("Begin\n");
   1299 
   1300 	if (mix == NULL) {
   1301 		return MIX_RESULT_NULL_PTR;
   1302 	}
   1303 
   1304 	/* Dequeue and release all input buffers for this frame */
   1305 	LOG_V("Releasing all the MixBuffers for this frame\n");
   1306 
   1307 	/*
   1308 	 * While the head of the queue has timestamp == current ts
   1309 	 * dequeue the entry, unref the MixBuffer, and free the struct
   1310 	 */
   1311 	done = FALSE;
   1312 	while (!done) {
   1313 		bufentry
   1314 				= (MixInputBufferEntry *) g_queue_peek_head(mix->inputbufqueue);
   1315 		if (bufentry == NULL) {
   1316 			break;
   1317 		}
   1318 
   1319 		LOG_V("head of queue buf %x, timestamp %"G_GINT64_FORMAT", buffer timestamp %"G_GINT64_FORMAT"\n",
   1320 				(guint)bufentry->buf, timestamp, bufentry->timestamp);
   1321 
   1322 		if (bufentry->timestamp != timestamp) {
   1323 			LOG_V("buf %x, timestamp %"G_GINT64_FORMAT", buffer timestamp %"G_GINT64_FORMAT"\n",
   1324 					(guint)bufentry->buf, timestamp, bufentry->timestamp);
   1325 
   1326 			done = TRUE;
   1327 			break;
   1328 		}
   1329 
   1330 		bufentry = (MixInputBufferEntry *) g_queue_pop_head(mix->inputbufqueue);
   1331 		LOG_V("Unref this MixBuffers %x\n", (guint) bufentry->buf);
   1332 
   1333 		mix_buffer_unref(bufentry->buf);
   1334 		g_free(bufentry);
   1335 	}
   1336 
   1337 	LOG_V("End\n");
   1338 
   1339 	return MIX_RESULT_SUCCESS;
   1340 }
   1341 
   1342 vbp_picture_data_mp42 *mix_videoformat_mp42_clone_picture_data(
   1343 		vbp_picture_data_mp42 *picture_data) {
   1344 
   1345 	gboolean succ = FALSE;
   1346 
   1347 	if (!picture_data) {
   1348 		return NULL;
   1349 	}
   1350 
   1351 	if (picture_data->number_slices == 0) {
   1352 		return NULL;
   1353 	}
   1354 
   1355 	vbp_picture_data_mp42 *cloned_picture_data = g_try_new0(
   1356 			vbp_picture_data_mp42, 1);
   1357 	if (cloned_picture_data == NULL) {
   1358 		goto cleanup;
   1359 	}
   1360 
   1361 	memcpy(cloned_picture_data, picture_data, sizeof(vbp_picture_data_mp42));
   1362 
   1363 	cloned_picture_data->number_slices = picture_data->number_slices;
   1364 	cloned_picture_data->slice_data = g_try_new0(vbp_slice_data_mp42,
   1365 			picture_data->number_slices);
   1366 	if (cloned_picture_data->slice_data == NULL) {
   1367 		goto cleanup;
   1368 	}
   1369 
   1370 	memcpy(cloned_picture_data->slice_data, picture_data->slice_data,
   1371 			sizeof(vbp_slice_data_mp42) * (picture_data->number_slices));
   1372 
   1373 	succ = TRUE;
   1374 
   1375 	cleanup:
   1376 
   1377 	if (!succ) {
   1378 		mix_videoformat_mp42_free_picture_data(cloned_picture_data);
   1379 		return NULL;
   1380 	}
   1381 
   1382 	return cloned_picture_data;
   1383 }
   1384 
   1385 void mix_videoformat_mp42_free_picture_data(vbp_picture_data_mp42 *picture_data) {
   1386 	if (picture_data) {
   1387 		if (picture_data->slice_data) {
   1388 			g_free(picture_data->slice_data);
   1389 		}
   1390 		g_free(picture_data);
   1391 	}
   1392 }
   1393 
   1394 void mix_videoformat_mp42_flush_packed_stream_queue(GQueue *packed_stream_queue) {
   1395 
   1396 	PackedStream *packed_stream = NULL;
   1397 
   1398 	if (packed_stream_queue == NULL) {
   1399 		return;
   1400 	}
   1401 	while (!g_queue_is_empty(packed_stream_queue)) {
   1402 		packed_stream = (PackedStream *) g_queue_pop_head(packed_stream_queue);
   1403 		if (packed_stream == NULL) {
   1404 			continue;
   1405 		}
   1406 
   1407 		if (packed_stream->picture_data) {
   1408 			mix_videoformat_mp42_free_picture_data(packed_stream->picture_data);
   1409 		}
   1410 
   1411 		if (packed_stream->mix_buffer) {
   1412 			mix_buffer_unref(packed_stream->mix_buffer);
   1413 		}
   1414 		g_free(packed_stream);
   1415 	}
   1416 }
   1417