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 <va/va_x11.h>
     10 
     11 #include "mixvideolog.h"
     12 #include "mixvideoformat_h264.h"
     13 
     14 #ifdef MIX_LOG_ENABLE
     15 static int mix_video_h264_counter = 0;
     16 #endif /* MIX_LOG_ENABLE */
     17 
     18 /* The parent class. The pointer will be saved
     19  * in this class's initialization. The pointer
     20  * can be used for chaining method call if needed.
     21  */
     22 static MixVideoFormatClass *parent_class = NULL;
     23 
     24 static void mix_videoformat_h264_finalize(GObject * obj);
     25 
     26 /*
     27  * Please note that the type we pass to G_DEFINE_TYPE is MIX_TYPE_VIDEOFORMAT
     28  */
     29 G_DEFINE_TYPE (MixVideoFormat_H264, mix_videoformat_h264, MIX_TYPE_VIDEOFORMAT);
     30 
     31 static void mix_videoformat_h264_init(MixVideoFormat_H264 * self) {
     32 	MixVideoFormat *parent = MIX_VIDEOFORMAT(self);
     33 
     34 	/* public member initialization */
     35 	/* These are all public because MixVideoFormat objects are completely internal to MixVideo,
     36 		no need for private members  */
     37 	self->dpb_surface_table = NULL;
     38 
     39 	/* NOTE: we don't need to do this here.
     40 	 * This just demostrates how to access
     41 	 * member varibles beloned to parent
     42 	 */
     43 	parent->initialized = FALSE;
     44 }
     45 
     46 static void mix_videoformat_h264_class_init(
     47 		MixVideoFormat_H264Class * klass) {
     48 
     49 	/* root class */
     50 	GObjectClass *gobject_class = (GObjectClass *) klass;
     51 
     52 	/* direct parent class */
     53 	MixVideoFormatClass *video_format_class =
     54 			MIX_VIDEOFORMAT_CLASS(klass);
     55 
     56 	/* parent class for later use */
     57 	parent_class = g_type_class_peek_parent(klass);
     58 
     59 	/* setup finializer */
     60 	gobject_class->finalize = mix_videoformat_h264_finalize;
     61 
     62 	/* setup vmethods with base implementation */
     63 	/* This is where we can override base class methods if needed */
     64 	video_format_class->getcaps = mix_videofmt_h264_getcaps;
     65 	video_format_class->initialize = mix_videofmt_h264_initialize;
     66 	video_format_class->decode = mix_videofmt_h264_decode;
     67 	video_format_class->flush = mix_videofmt_h264_flush;
     68 	video_format_class->eos = mix_videofmt_h264_eos;
     69 	video_format_class->deinitialize = mix_videofmt_h264_deinitialize;
     70 }
     71 
     72 MixVideoFormat_H264 *
     73 mix_videoformat_h264_new(void) {
     74 	MixVideoFormat_H264 *ret =
     75 			g_object_new(MIX_TYPE_VIDEOFORMAT_H264, NULL);
     76 
     77 	return ret;
     78 }
     79 
     80 void mix_videoformat_h264_finalize(GObject * obj) {
     81 	gint32 pret = VBP_OK;
     82 
     83 	/* clean up here. */
     84 
     85 	MixVideoFormat *parent = NULL;
     86 	MixVideoFormat_H264 *self = MIX_VIDEOFORMAT_H264(obj);
     87 	GObjectClass *root_class = (GObjectClass *) parent_class;
     88 
     89 	parent = MIX_VIDEOFORMAT(self);
     90 
     91 	//surfacepool is deallocated by parent
     92 	//inputbufqueue is deallocated by parent
     93 	//parent calls vaDestroyConfig, vaDestroyContext and vaDestroySurfaces
     94 
     95 	//Free the DPB surface table
     96 	//First remove all the entries (frames will be unrefed)
     97 	g_hash_table_remove_all(self->dpb_surface_table);
     98 	//Then unref the table
     99 	g_hash_table_unref(self->dpb_surface_table);
    100 	self->dpb_surface_table = NULL;
    101 
    102 	g_mutex_lock(parent->objectlock);
    103 	parent->initialized = TRUE;
    104 	parent->parse_in_progress = FALSE;
    105 	parent->current_timestamp = 0;
    106 
    107 	//Close the parser
    108         pret = vbp_close(parent->parser_handle);
    109 	parent->parser_handle = NULL;
    110 	if (pret != VBP_OK)
    111 	{
    112 		LOG_E( "Error closing parser\n");
    113 	}
    114 
    115 	g_mutex_unlock(parent->objectlock);
    116 
    117 	/* Chain up parent */
    118 	if (root_class->finalize) {
    119 		root_class->finalize(obj);
    120 	}
    121 }
    122 
    123 MixVideoFormat_H264 *
    124 mix_videoformat_h264_ref(MixVideoFormat_H264 * mix) {
    125 	return (MixVideoFormat_H264 *) g_object_ref(G_OBJECT(mix));
    126 }
    127 
    128 /*  H.264 vmethods implementation */
    129 MIX_RESULT mix_videofmt_h264_getcaps(MixVideoFormat *mix, GString *msg) {
    130 
    131 MIX_RESULT ret = MIX_RESULT_SUCCESS;
    132 
    133 	if (mix == NULL || msg == NULL)
    134 	{
    135 		LOG_E( "NUll pointer passed in\n");
    136 		return MIX_RESULT_NULL_PTR;
    137 	}
    138 
    139 	LOG_V( "Begin\n");
    140 
    141 	/* Chainup parent method.
    142 	 */
    143 
    144 	if (parent_class->getcaps) {
    145 		ret = parent_class->getcaps(mix, msg);
    146 	}
    147 
    148 	LOG_V( "End\n");
    149 
    150 	return ret;
    151 }
    152 
    153 MIX_RESULT mix_videofmt_h264_initialize(MixVideoFormat *mix,
    154 		MixVideoConfigParamsDec * config_params,
    155                 MixFrameManager * frame_mgr,
    156 		MixBufferPool * input_buf_pool,
    157 		MixSurfacePool ** surface_pool,
    158 		VADisplay va_display ) {
    159 
    160 	uint32 pret = 0;
    161 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
    162 	enum _vbp_parser_type ptype = VBP_H264;
    163 	vbp_data_h264 *data = NULL;
    164 	MixVideoFormat *parent = NULL;
    165 	MixIOVec *header = NULL;
    166 	gint numprofs = 0, numactualprofs = 0;
    167 	gint numentrypts = 0, numactualentrypts = 0;
    168 	VADisplay vadisplay = NULL;
    169 	VAProfile *profiles = NULL;
    170 	VAEntrypoint *entrypts = NULL;
    171 	VAConfigAttrib attrib;
    172 	VAStatus vret = VA_STATUS_SUCCESS;
    173 	guint extra_surfaces = 0;
    174 	VASurfaceID *surfaces = NULL;
    175 	guint numSurfaces = 0;
    176 
    177 	//TODO Partition this method into smaller methods
    178 
    179 	if (mix == NULL || config_params == NULL || frame_mgr == NULL || input_buf_pool == NULL || va_display == NULL)
    180 	{
    181 		LOG_E( "NUll pointer passed in\n");
    182 		return MIX_RESULT_NULL_PTR;
    183 	}
    184 
    185 	LOG_V( "Begin\n");
    186 
    187 	/* Chainup parent method. */
    188 
    189 	if (parent_class->initialize) {
    190 		ret = parent_class->initialize(mix, config_params,
    191 				frame_mgr, input_buf_pool, surface_pool,
    192 				va_display);
    193 	}
    194 
    195 	if (ret != MIX_RESULT_SUCCESS)
    196 	{
    197 		LOG_E( "Error initializing\n");
    198 		return ret;
    199 	}
    200 
    201 	if (!MIX_IS_VIDEOFORMAT_H264(mix))
    202 		return MIX_RESULT_INVALID_PARAM;
    203 
    204 	parent = MIX_VIDEOFORMAT(mix);
    205 	MixVideoFormat_H264 *self = MIX_VIDEOFORMAT_H264(mix);
    206 
    207 	LOG_V( "Locking\n");
    208 	//From now on, we exit this function through cleanup:
    209 	g_mutex_lock(parent->objectlock);
    210 
    211 	LOG_V( "Before vbp_open\n");
    212 	//Load the bitstream parser
    213 	pret = vbp_open(ptype, &(parent->parser_handle));
    214 
    215 	LOG_V( "After vbp_open\n");
    216         if (!(pret == VBP_OK))
    217 	{
    218 		ret = MIX_RESULT_FAIL;
    219 		LOG_E( "Error opening parser\n");
    220 		goto cleanup;
    221 	}
    222 	LOG_V( "Opened parser\n");
    223 
    224 	ret = mix_videoconfigparamsdec_get_header(config_params,
    225 		&header);
    226 
    227         if ((ret != MIX_RESULT_SUCCESS) || (header == NULL))
    228         {
    229 		ret = MIX_RESULT_FAIL;
    230 		LOG_E( "Cannot get header data\n");
    231 		goto cleanup;
    232         }
    233 
    234         ret = mix_videoconfigparamsdec_get_extra_surface_allocation(config_params,
    235                 &extra_surfaces);
    236 
    237         if (ret != MIX_RESULT_SUCCESS)
    238         {
    239 		ret = MIX_RESULT_FAIL;
    240 		LOG_E( "Cannot get extra surface allocation setting\n");
    241 		goto cleanup;
    242         }
    243 
    244         LOG_V( "Calling parse on header data, handle %d\n", (int)parent->parser_handle);
    245 
    246 	pret = vbp_parse(parent->parser_handle, header->data,
    247 			header->data_size, TRUE);
    248 
    249         if (!((pret == VBP_OK) || (pret == VBP_DONE)))
    250         {
    251 		ret = MIX_RESULT_FAIL;
    252 		LOG_E( "Error parsing header data\n");
    253 		goto cleanup;
    254         }
    255 
    256         LOG_V( "Parsed header\n");
    257 
    258        //Get the header data and save
    259         pret = vbp_query(parent->parser_handle, (void *)&data);
    260 
    261 	if ((pret != VBP_OK) || (data == NULL))
    262 	{
    263 		ret = MIX_RESULT_FAIL;
    264 		LOG_E( "Error reading parsed header data\n");
    265 		goto cleanup;
    266 	}
    267 
    268 	LOG_V( "Queried parser for header data\n");
    269 
    270 	//Time for libva initialization
    271 
    272 	vadisplay = parent->va_display;
    273 
    274 	numprofs = vaMaxNumProfiles(vadisplay);
    275 	profiles = g_malloc(numprofs*sizeof(VAProfile));
    276 
    277 	if (!profiles)
    278 	{
    279 		ret = MIX_RESULT_NO_MEMORY;
    280 		LOG_E( "Error allocating memory\n");
    281 		goto cleanup;
    282 	}
    283 
    284 	vret = vaQueryConfigProfiles(vadisplay, profiles,
    285 		&numactualprofs);
    286 	if (!(vret == VA_STATUS_SUCCESS))
    287 	{
    288 		ret = MIX_RESULT_FAIL;
    289 		LOG_E( "Error initializing video driver\n");
    290 		goto cleanup;
    291 	}
    292 
    293         //check the desired profile support
    294         gint vaprof = 0;
    295 
    296 	//TODO Need to cover more cases
    297 	switch (data->codec_data->profile_idc)
    298 	{
    299 #if 1
    300 //TODO Reinstate this once constraint_set1 flag has been added to codec_data
    301 	case 66: //Baseline profile
    302 
    303 	LOG_V( "mix_videofmt_h264_initialize:  Baseline profile\n");
    304 		if (data->codec_data->constraint_set1_flag == 0)
    305 		{
    306         		for (; vaprof < numactualprofs; vaprof++)
    307         		{
    308                			if (profiles[vaprof] == VAProfileH264Baseline)
    309                	       	 	break;
    310         		}
    311 		} else
    312 		{
    313         		for (; vaprof < numactualprofs; vaprof++)
    314         		{
    315                			if (profiles[vaprof] == VAProfileH264High)
    316                	       	 	break;
    317         		}
    318 		}
    319 		if ((vaprof >= numprofs) || ((profiles[vaprof] != VAProfileH264Baseline) && (profiles[vaprof] != VAProfileH264High)))
    320 		//Did not get the profile we wanted
    321 		{
    322 			ret = MIX_RESULT_FAIL;
    323 			LOG_E( "Profile not supported by driver\n");
    324 			goto cleanup;
    325 		}
    326 		break;
    327 #endif
    328 
    329 #if 0
    330 //Code left in place in case bug is fixed in libva
    331 	case 77: //Main profile (need to set to High for libva bug)
    332 	LOG_V( "mix_videofmt_h264_initialize:  Main profile\n");
    333 
    334         	for (; vaprof < numactualprofs; vaprof++)
    335         	{
    336                		if (profiles[vaprof] == VAProfileH264Main)
    337                	        	break;
    338         	}
    339 		if (vaprof >= numprofs || profiles[vaprof] != VAProfileH264Main)
    340 		//Did not get the profile we wanted
    341 		{
    342 			ret = MIX_RESULT_FAIL;
    343 			LOG_E( "Profile not supported by driver\n");
    344 			goto cleanup;
    345 		}
    346 		break;
    347 #endif
    348 
    349 	case 100: //High profile
    350 	default:  //Set to High as default
    351 
    352 	LOG_V( "High profile\n");
    353 
    354         	for (; vaprof < numactualprofs; vaprof++)
    355         	{
    356                		if (profiles[vaprof] == VAProfileH264High)
    357                	        	break;
    358         	}
    359 		if (vaprof >= numprofs || profiles[vaprof] != VAProfileH264High)
    360 		//Did not get the profile we wanted
    361 		{
    362 			ret = MIX_RESULT_FAIL;
    363 			LOG_E( "Profile not supported by driver\n");
    364 			goto cleanup;
    365 		}
    366 		break;
    367 
    368 
    369 	}
    370 
    371 	numentrypts = vaMaxNumEntrypoints(vadisplay);
    372 	entrypts = g_malloc(numentrypts*sizeof(VAEntrypoint));
    373 
    374 	if (!entrypts)
    375 	{
    376 		ret = MIX_RESULT_NO_MEMORY;
    377 		LOG_E( "Error allocating memory\n");
    378 		goto cleanup;
    379 	}
    380 
    381 	vret = vaQueryConfigEntrypoints(vadisplay, profiles[vaprof],
    382 		entrypts, &numactualentrypts);
    383 	if (!(vret == VA_STATUS_SUCCESS))
    384 	{
    385 		ret = MIX_RESULT_FAIL;
    386 		LOG_E( "Error initializing driver\n");
    387 		goto cleanup;
    388 	}
    389 
    390 	gint vaentrypt = 0;
    391 	for (; vaentrypt < numactualentrypts; vaentrypt++)
    392 	{
    393 		if (entrypts[vaentrypt] == VAEntrypointVLD)
    394 			break;
    395 	}
    396 	if (vaentrypt >= numentrypts || entrypts[vaentrypt] != VAEntrypointVLD)
    397 	//Did not get the entrypt we wanted
    398 	{
    399 		ret = MIX_RESULT_FAIL;
    400 		LOG_E( "Entry point not supported by driver\n");
    401 		goto cleanup;
    402 	}
    403 
    404 	//We are requesting RT attributes
    405 	attrib.type = VAConfigAttribRTFormat;
    406 
    407 	vret = vaGetConfigAttributes(vadisplay, profiles[vaprof],
    408 		entrypts[vaentrypt], &attrib, 1);
    409 
    410         //TODO Handle other values returned for RT format
    411         // and check with requested format provided in config params
    412         //Right now only YUV 4:2:0 is supported by libva
    413         // and this is our default
    414         if (((attrib.value & VA_RT_FORMAT_YUV420) == 0) ||
    415                 vret != VA_STATUS_SUCCESS)
    416         {
    417 		ret = MIX_RESULT_FAIL;
    418 		LOG_E( "Error initializing driver\n");
    419 		goto cleanup;
    420         }
    421 
    422 	//Initialize and save the VA config ID
    423 	vret = vaCreateConfig(vadisplay, profiles[vaprof],
    424 		entrypts[vaentrypt], &attrib, 1, &(parent->va_config));
    425 
    426 	if (!(vret == VA_STATUS_SUCCESS))
    427 	{
    428 		ret = MIX_RESULT_FAIL;
    429 		LOG_E( "Error initializing driver\n");
    430 		goto cleanup;
    431 	}
    432 
    433 	LOG_V( "Created libva config with profile %d\n", vaprof);
    434 
    435 
    436 	//Initialize the surface pool
    437 
    438 	LOG_V( "Codec data says num_ref_frames is %d\n", data->codec_data->num_ref_frames);
    439 
    440 
    441 	// handle both frame and field coding for interlaced content
    442 	int num_ref_pictures = data->codec_data->num_ref_frames;
    443 	if (!data->codec_data->frame_mbs_only_flag &&
    444 		!data->codec_data->mb_adaptive_frame_field_flag)
    445 	{
    446 
    447 		// field coding, two fields share the same surface.
    448 		//num_ref_pictures *= 2;
    449 	}
    450 
    451 	//Adding 1 to work around VBLANK issue
    452 	parent->va_num_surfaces = 1 + extra_surfaces + (((num_ref_pictures + 3) <
    453 		MIX_VIDEO_H264_SURFACE_NUM) ?
    454 		(num_ref_pictures + 3)
    455 		: MIX_VIDEO_H264_SURFACE_NUM);
    456 
    457 	numSurfaces = parent->va_num_surfaces;
    458 
    459 	parent->va_surfaces = g_malloc(sizeof(VASurfaceID)*numSurfaces);
    460 
    461 	surfaces = parent->va_surfaces;
    462 
    463 	if (surfaces == NULL)
    464 	{
    465 		ret = MIX_RESULT_FAIL;
    466 		LOG_E( "Cannot allocate temporary data\n");
    467 		goto cleanup;
    468 	}
    469 
    470 	LOG_V( "Codec data says picture size is %d x %d\n", (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) * 16, (data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) * 16);
    471 	LOG_V( "getcaps says picture size is %d x %d\n", parent->picture_width, parent->picture_height);
    472 
    473 	vret = vaCreateSurfaces(vadisplay, (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) * 16,
    474 		(data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) * 16, entrypts[vaentrypt],
    475 		numSurfaces, surfaces);
    476 
    477 	if (!(vret == VA_STATUS_SUCCESS))
    478 	{
    479 		ret = MIX_RESULT_FAIL;
    480 		LOG_E( "Error allocating surfaces\n");
    481 		goto cleanup;
    482 	}
    483 
    484 	parent->surfacepool = mix_surfacepool_new();
    485 	*surface_pool = parent->surfacepool;
    486 
    487 	if (parent->surfacepool == NULL)
    488 	{
    489 		ret = MIX_RESULT_FAIL;
    490 		LOG_E( "Error initializing surface pool\n");
    491 		goto cleanup;
    492 	}
    493 
    494 
    495 	ret = mix_surfacepool_initialize(parent->surfacepool,
    496 		surfaces, numSurfaces);
    497 
    498 	switch (ret)
    499 	{
    500 		case MIX_RESULT_SUCCESS:
    501 			break;
    502 		case MIX_RESULT_ALREADY_INIT:  //This case is for future use when we can be  initialized multiple times.  It is to detect when we have not been reset before re-initializing.
    503 		default:
    504 			ret = MIX_RESULT_ALREADY_INIT;
    505 			LOG_E( "Error init failure\n");
    506 			goto cleanup;
    507                         break;
    508 	}
    509 
    510 	LOG_V( "Created %d libva surfaces\n", numSurfaces);
    511 
    512         //Initialize and save the VA context ID
    513         //Note: VA_PROGRESSIVE libva flag is only relevant to MPEG2
    514         vret = vaCreateContext(vadisplay, parent->va_config,
    515                 parent->picture_width, parent->picture_height,
    516                 0, surfaces, numSurfaces,
    517                 &(parent->va_context));
    518 	if (!(vret == VA_STATUS_SUCCESS))
    519 	{
    520 		ret = MIX_RESULT_FAIL;
    521 		LOG_E( "Error initializing video driver\n");
    522 		goto cleanup;
    523 	}
    524 
    525 	LOG_V( "Created libva context width %d, height %d\n", parent->picture_width, parent->picture_height);
    526 
    527 	//Create our table of Decoded Picture Buffer "in use" surfaces
    528 	self->dpb_surface_table = g_hash_table_new_full(NULL, NULL, mix_videofmt_h264_destroy_DPB_key, mix_videofmt_h264_destroy_DPB_value);
    529 
    530 	if (self->dpb_surface_table == NULL)
    531 	{
    532 		ret = MIX_RESULT_NO_MEMORY;
    533 		LOG_E( "Error allocating dbp surface table\n");
    534 		goto cleanup;  //leave this goto here in case other code is added between here and cleanup label
    535 	}
    536 
    537 	cleanup:
    538 	if (ret != MIX_RESULT_SUCCESS) {
    539 		pret = vbp_close(parent->parser_handle);
    540 		parent->parser_handle = NULL;
    541        		parent->initialized = FALSE;
    542 
    543 	} else {
    544 	         parent->initialized = TRUE;
    545 	}
    546 
    547 	if (header != NULL)
    548 	{
    549 		if (header->data != NULL)
    550 			g_free(header->data);
    551 		g_free(header);
    552 		header = NULL;
    553 	}
    554 
    555 	g_free(profiles);
    556         g_free(entrypts);
    557 
    558 	LOG_V( "Unlocking\n");
    559         g_mutex_unlock(parent->objectlock);
    560 
    561 
    562 	return ret;
    563 }
    564 
    565 MIX_RESULT mix_videofmt_h264_decode(MixVideoFormat *mix, MixBuffer * bufin[],
    566                 gint bufincnt, MixVideoDecodeParams * decode_params) {
    567 
    568         uint32 pret = 0;
    569 	int i = 0;
    570         MixVideoFormat *parent = NULL;
    571 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
    572 	guint64 ts = 0;
    573 	vbp_data_h264 *data = NULL;
    574 	gboolean discontinuity = FALSE;
    575 	MixInputBufferEntry *bufentry = NULL;
    576 
    577         LOG_V( "Begin\n");
    578 
    579         if (mix == NULL || bufin == NULL || decode_params == NULL )
    580 	{
    581 		LOG_E( "NUll pointer passed in\n");
    582                 return MIX_RESULT_NULL_PTR;
    583 	}
    584 
    585 	/* Chainup parent method.
    586 		We are not chaining up to parent method for now.
    587 	 */
    588 
    589 #if 0
    590         if (parent_class->decode) {
    591                 return parent_class->decode(mix, bufin, bufincnt,
    592                                         decode_params);
    593 	}
    594 #endif
    595 
    596 	if (!MIX_IS_VIDEOFORMAT_H264(mix))
    597 		return MIX_RESULT_INVALID_PARAM;
    598 
    599 	parent = MIX_VIDEOFORMAT(mix);
    600 
    601 
    602 	ret = mix_videodecodeparams_get_timestamp(decode_params,
    603 			&ts);
    604 	if (ret != MIX_RESULT_SUCCESS)
    605 	{
    606 		return MIX_RESULT_FAIL;
    607 	}
    608 
    609 	ret = mix_videodecodeparams_get_discontinuity(decode_params,
    610 			&discontinuity);
    611 	if (ret != MIX_RESULT_SUCCESS)
    612 	{
    613 		return MIX_RESULT_FAIL;
    614 	}
    615 
    616 	//From now on, we exit this function through cleanup:
    617 
    618 	LOG_V( "Locking\n");
    619         g_mutex_lock(parent->objectlock);
    620 
    621 	LOG_V( "parse in progress is %d\n", parent->parse_in_progress);
    622 	//If this is a new frame and we haven't retrieved parser
    623 	//  workload data from previous frame yet, do so
    624 	if ((ts != parent->current_timestamp) &&
    625 			(parent->parse_in_progress))
    626 	{
    627 
    628 		//query for data
    629 		pret = vbp_query(parent->parser_handle,
    630 			(void *) &data);
    631 
    632 		if ((pret != VBP_OK) || (data == NULL))
    633         	{
    634 			ret = MIX_RESULT_FAIL;
    635 			LOG_E( "Error initializing parser\n");
    636                		goto cleanup;
    637         	}
    638 
    639 		LOG_V( "Queried for last frame data\n");
    640 
    641 		//process and decode data
    642 		ret = mix_videofmt_h264_process_decode(mix,
    643 			data, parent->current_timestamp,
    644 			parent->discontinuity_frame_in_progress);
    645 
    646 		if (ret != MIX_RESULT_SUCCESS)
    647         	{
    648 			//We log this but need to process the new frame data, so do not return
    649 			LOG_E( "Process_decode failed.\n");
    650         	}
    651 
    652 		LOG_V( "Called process and decode for last frame\n");
    653 
    654 		parent->parse_in_progress = FALSE;
    655 
    656 	}
    657 
    658 	parent->current_timestamp = ts;
    659 	parent->discontinuity_frame_in_progress = discontinuity;
    660 
    661 	LOG_V( "Starting current frame %d, timestamp %"G_GINT64_FORMAT"\n", mix_video_h264_counter++, ts);
    662 
    663 	for (i = 0; i < bufincnt; i++)
    664 	{
    665 
    666 		LOG_V( "Calling parse for current frame, parse handle %d, buf %x, size %d\n", (int)parent->parser_handle, (guint)bufin[i]->data, bufin[i]->size);
    667 
    668 		pret = vbp_parse(parent->parser_handle,
    669 			bufin[i]->data,
    670 			bufin[i]->size,
    671 			FALSE);
    672 
    673 		LOG_V( "Called parse for current frame\n");
    674 
    675 		if ((pret == VBP_DONE) || (pret == VBP_OK))
    676 		{
    677 			//query for data
    678 			pret = vbp_query(parent->parser_handle,
    679 				(void *) &data);
    680 
    681 			if ((pret != VBP_OK) || (data == NULL))
    682         		{
    683 				ret = MIX_RESULT_FAIL;
    684 				LOG_E( "Error getting parser data\n");
    685                			goto cleanup;
    686         		}
    687 
    688 			LOG_V( "Called query for current frame\n");
    689 
    690 			//Increase the ref count of this input buffer
    691 			mix_buffer_ref(bufin[i]);
    692 
    693 			//Create a new MixInputBufferEntry
    694 			//TODO make this from a pool to optimize
    695 			bufentry = g_malloc(sizeof(
    696 				MixInputBufferEntry));
    697 			if (bufentry == NULL)
    698         		{
    699 				ret = MIX_RESULT_NO_MEMORY;
    700 				LOG_E( "Error allocating bufentry\n");
    701                			goto cleanup;
    702         		}
    703 
    704 			bufentry->buf = bufin[i];
    705 	LOG_V( "Setting bufentry %x for mixbuffer %x ts to %"G_GINT64_FORMAT"\n", (guint)bufentry, (guint)bufentry->buf, ts);
    706 			bufentry->timestamp = ts;
    707 
    708 			LOG_V( "Enqueue this input buffer for current frame\n");
    709 			LOG_V( "bufentry->timestamp %"G_GINT64_FORMAT"\n", bufentry->timestamp);
    710 
    711 			//Enqueue this input buffer
    712 			g_queue_push_tail(parent->inputbufqueue,
    713 				(gpointer)bufentry);
    714 
    715 			//process and decode data
    716 			ret = mix_videofmt_h264_process_decode(mix,
    717 				data, ts, discontinuity);
    718 
    719 			if (ret != MIX_RESULT_SUCCESS)
    720                 	{
    721 				//We log this but continue since we need to complete our processing of input buffers
    722 				LOG_E( "Process_decode failed.\n");
    723                 	}
    724 
    725 			LOG_V( "Called process and decode for current frame\n");
    726 
    727 			parent->parse_in_progress = FALSE;
    728 		}
    729 		else if (pret != VBP_OK)
    730         	{
    731 			//We log this but continue since we need to complete our processing of input buffers
    732 			LOG_E( "Parsing failed.\n");
    733 			ret = MIX_RESULT_FAIL;
    734         	}
    735 		else
    736 		{
    737 
    738 			LOG_V( "Enqueuing buffer and going on to next (if any) for this frame\n");
    739 
    740 			//Increase the ref count of this input buffer
    741 			mix_buffer_ref(bufin[i]);
    742 
    743 			//Create a new MixInputBufferEntry
    744 			//TODO make this from a pool to optimize
    745 			bufentry = g_malloc(sizeof
    746 				(MixInputBufferEntry));
    747 			if (bufentry == NULL)
    748         		{
    749 				ret = MIX_RESULT_NO_MEMORY;
    750 				LOG_E( "Error allocating bufentry\n");
    751                			goto cleanup;
    752         		}
    753 			bufentry->buf = bufin[i];
    754 	LOG_V( "Setting bufentry %x for mixbuffer %x ts to %"G_GINT64_FORMAT"\n", (guint)bufentry, (guint)bufentry->buf, ts);
    755 			bufentry->timestamp = ts;
    756 
    757 			LOG_V( "Enqueue this input buffer for current frame\n");
    758 			LOG_V( "bufentry->timestamp %"G_GINT64_FORMAT"\n", bufentry->timestamp);
    759 
    760 			//Enqueue this input buffer
    761 			g_queue_push_tail(parent->inputbufqueue,
    762 				(gpointer)bufentry);
    763 	LOG_V( "Setting parse_in_progress to TRUE\n");
    764 			parent->parse_in_progress = TRUE;
    765 		}
    766 
    767 	}
    768 
    769 
    770 	cleanup:
    771 
    772 	LOG_V( "Unlocking\n");
    773  	g_mutex_unlock(parent->objectlock);
    774 
    775         LOG_V( "End\n");
    776 
    777 	return ret;
    778 }
    779 
    780 MIX_RESULT mix_videofmt_h264_flush(MixVideoFormat *mix) {
    781 
    782 MIX_RESULT ret = MIX_RESULT_SUCCESS;
    783 
    784 	LOG_V( "Begin\n");
    785 
    786 	if (mix == NULL)
    787 	{
    788 		LOG_E( "Null pointer passed in\n");
    789 		return MIX_RESULT_NULL_PTR;
    790 	}
    791 
    792         uint32 pret = 0;
    793 	MixInputBufferEntry *bufentry = NULL;
    794 
    795 
    796 	/* Chainup parent method.
    797 		We are not chaining up to parent method for now.
    798 	 */
    799 
    800 #if 0
    801 	if (parent_class->flush) {
    802 		return parent_class->flush(mix, msg);
    803 	}
    804 #endif
    805 
    806 	MixVideoFormat_H264 *self = MIX_VIDEOFORMAT_H264(mix);
    807 
    808         g_mutex_lock(mix->objectlock);
    809 
    810 	//Clear the contents of inputbufqueue
    811 	while (!g_queue_is_empty(mix->inputbufqueue))
    812 	{
    813 		bufentry = (MixInputBufferEntry *) g_queue_pop_head(
    814 				mix->inputbufqueue);
    815 		if (bufentry == NULL) continue;
    816 
    817 		mix_buffer_unref(bufentry->buf);
    818 		g_free(bufentry);
    819 	}
    820 
    821 	//Clear parse_in_progress flag and current timestamp
    822         mix->parse_in_progress = FALSE;
    823 	mix->discontinuity_frame_in_progress = FALSE;
    824 	mix->current_timestamp = 0;
    825 
    826 	//Clear the DPB surface table
    827 	g_hash_table_remove_all(self->dpb_surface_table);
    828 
    829 	//Call parser flush
    830 	pret = vbp_flush(mix->parser_handle);
    831 	if (pret != VBP_OK)
    832 		ret = MIX_RESULT_FAIL;
    833 
    834         g_mutex_unlock(mix->objectlock);
    835 
    836 	LOG_V( "End\n");
    837 
    838 	return ret;
    839 }
    840 
    841 MIX_RESULT mix_videofmt_h264_eos(MixVideoFormat *mix) {
    842 
    843 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
    844 	vbp_data_h264 *data = NULL;
    845         uint32 pret = 0;
    846 
    847         LOG_V( "Begin\n");
    848 
    849 	if (mix == NULL)
    850 	{
    851 		LOG_E( "Null pointer passed in\n");
    852 		return MIX_RESULT_NULL_PTR;
    853 	}
    854 
    855 	/* Chainup parent method.
    856 		We are not chaining up to parent method for now.
    857 	 */
    858 
    859 #if 0
    860 	if (parent_class->eos) {
    861 		return parent_class->eos(mix, msg);
    862 	}
    863 #endif
    864 
    865         g_mutex_lock(mix->objectlock);
    866 
    867 	//if a frame is in progress, process the frame
    868 	if (mix->parse_in_progress)
    869 	{
    870 		//query for data
    871 		pret = vbp_query(mix->parser_handle,
    872 			(void *) &data);
    873 
    874 		if ((pret != VBP_OK) || (data == NULL))
    875                	{
    876                		ret = MIX_RESULT_FAIL;
    877  			LOG_E( "Error getting last parse data\n");
    878 			goto cleanup;
    879                	}
    880 
    881 		//process and decode data
    882 		ret = mix_videofmt_h264_process_decode(mix,
    883 			data, mix->current_timestamp,
    884 			mix->discontinuity_frame_in_progress);
    885 		mix->parse_in_progress = FALSE;
    886 		if (ret != MIX_RESULT_SUCCESS)
    887 		{
    888  			LOG_E( "Error processing last frame\n");
    889 			goto cleanup;
    890 		}
    891 
    892 	}
    893 
    894 cleanup:
    895 
    896         g_mutex_unlock(mix->objectlock);
    897 
    898 	//Call Frame Manager with _eos()
    899 	ret = mix_framemanager_eos(mix->framemgr);
    900 
    901 	LOG_V( "End\n");
    902 
    903 	return ret;
    904 
    905 
    906 }
    907 
    908 MIX_RESULT mix_videofmt_h264_deinitialize(MixVideoFormat *mix) {
    909 
    910 //Note this method is not called; may remove in future
    911 
    912 	LOG_V( "Begin\n");
    913 
    914 	if (mix == NULL)
    915 	{
    916 		LOG_E( "Null pointer passed in\n");
    917 		return MIX_RESULT_NULL_PTR;
    918 	}
    919 
    920 	/* Chainup parent method.
    921 	 */
    922 
    923 	if (parent_class->deinitialize) {
    924 		return parent_class->deinitialize(mix);
    925 	}
    926 
    927         //Most stuff is cleaned up in parent_class->finalize() and in _finalize
    928 
    929         LOG_V( "End\n");
    930 
    931 	return MIX_RESULT_SUCCESS;
    932 }
    933 #define HACK_DPB
    934 #ifdef HACK_DPB
    935 static inline void mix_videofmt_h264_hack_dpb(MixVideoFormat *mix,
    936 					vbp_picture_data_h264* pic_data
    937 					)
    938 {
    939 
    940 	gboolean found = FALSE;
    941 	guint tflags = 0;
    942 	VAPictureParameterBufferH264 *pic_params = pic_data->pic_parms;
    943 	VAPictureH264 *pRefList = NULL;
    944 	int i = 0, j = 0, k = 0, list = 0;
    945 
    946 	MixVideoFormat_H264 *self = MIX_VIDEOFORMAT_H264(mix);
    947 
    948 	//Set the surface ID for everything in the parser DPB to INVALID
    949 	for (i = 0; i < 16; i++)
    950 	{
    951 		pic_params->ReferenceFrames[i].picture_id = VA_INVALID_SURFACE;
    952 		pic_params->ReferenceFrames[i].frame_idx = -1;
    953 		pic_params->ReferenceFrames[i].TopFieldOrderCnt = -1;
    954 		pic_params->ReferenceFrames[i].BottomFieldOrderCnt = -1;
    955 		pic_params->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;  //assuming we don't need to OR with existing flags
    956 	}
    957 
    958 	pic_params->num_ref_frames = 0;
    959 
    960 	for (i = 0; i < pic_data->num_slices; i++)
    961 	{
    962 
    963 		//Copy from the List0 and List1 surface IDs
    964 		pRefList = pic_data->slc_data[i].slc_parms.RefPicList0;
    965 		for (list = 0; list < 2; list++)
    966 		{
    967 			for (j = 0; j < 32; j++)
    968 			{
    969 				if (pRefList[j].flags & VA_PICTURE_H264_INVALID)
    970 				{
    971 					break;  //no more valid reference frames in this list
    972 				}
    973 				found = FALSE;
    974 				for (k = 0; k < pic_params->num_ref_frames; k++)
    975 				{
    976 					if (pic_params->ReferenceFrames[k].TopFieldOrderCnt == pRefList[j].TopFieldOrderCnt)
    977 					{
    978 						///check for complementary field
    979 						tflags = pic_params->ReferenceFrames[k].flags | pRefList[j].flags;
    980 						//If both TOP and BOTTOM are set, we'll clear those flags
    981 						if ((tflags & VA_PICTURE_H264_TOP_FIELD) &&
    982 							(tflags & VA_PICTURE_H264_TOP_FIELD))
    983 							pic_params->ReferenceFrames[k].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
    984 						found = TRUE;  //already in the DPB; will not add this one
    985 						break;
    986 					}
    987 				}
    988 				if (!found)
    989 				{
    990 					guint poc = mix_videofmt_h264_get_poc(&(pRefList[j]));
    991 					gpointer video_frame = g_hash_table_lookup(self->dpb_surface_table, (gpointer)poc);
    992 					pic_params->ReferenceFrames[pic_params->num_ref_frames].picture_id =
    993 						((MixVideoFrame *)video_frame)->frame_id;
    994 
    995         				LOG_V( "Inserting frame id %d into DPB\n", pic_params->ReferenceFrames[pic_params->num_ref_frames].picture_id);
    996 
    997 					pic_params->ReferenceFrames[pic_params->num_ref_frames].flags =
    998 						pRefList[j].flags;
    999 					pic_params->ReferenceFrames[pic_params->num_ref_frames].frame_idx =
   1000 						pRefList[j].frame_idx;
   1001 					pic_params->ReferenceFrames[pic_params->num_ref_frames].TopFieldOrderCnt =
   1002 						pRefList[j].TopFieldOrderCnt;
   1003 					pic_params->ReferenceFrames[pic_params->num_ref_frames++].BottomFieldOrderCnt =
   1004 						pRefList[j].BottomFieldOrderCnt;
   1005 				}
   1006 
   1007 			}
   1008 		pRefList = pic_data->slc_data[i].slc_parms.RefPicList1;
   1009 		}
   1010 
   1011 	}
   1012 }
   1013 #endif
   1014 
   1015 
   1016 MIX_RESULT mix_videofmt_h264_process_decode_picture(MixVideoFormat *mix,
   1017 					vbp_data_h264 *data,
   1018 					guint64 timestamp,
   1019 					gboolean discontinuity,
   1020 					int pic_index,
   1021 					MixVideoFrame *frame)
   1022 {
   1023 
   1024 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
   1025 	VAStatus vret = VA_STATUS_SUCCESS;
   1026 	VADisplay vadisplay = NULL;
   1027 	VAContextID vacontext;
   1028 	guint buffer_id_cnt = 0;
   1029 	VABufferID *buffer_ids = NULL;
   1030 
   1031 	//TODO Partition this method into smaller methods
   1032 
   1033 	LOG_V( "Begin\n");
   1034 
   1035 	if ((mix == NULL) || (data == NULL) || (data->pic_data == NULL) || (frame == NULL))
   1036 	{
   1037 		LOG_E( "Null pointer passed in\n");
   1038 		return MIX_RESULT_NULL_PTR;
   1039 	}
   1040 
   1041 	vbp_picture_data_h264* pic_data = &(data->pic_data[pic_index]);
   1042 
   1043 
   1044 	//After this point, all exits from this function are through cleanup:
   1045 
   1046 	if (!MIX_IS_VIDEOFORMAT_H264(mix))
   1047 		return MIX_RESULT_INVALID_PARAM;
   1048 
   1049 	MixVideoFormat_H264 *self = MIX_VIDEOFORMAT_H264(mix);
   1050 
   1051 	VAPictureParameterBufferH264 *pic_params = pic_data->pic_parms;
   1052 
   1053 	if (pic_params == NULL)
   1054 	{
   1055 		ret = MIX_RESULT_NULL_PTR;
   1056 		LOG_E( "Error reading parser data\n");
   1057 		goto cleanup;
   1058 	}
   1059 
   1060 	//TODO
   1061 	//Check for frame gaps and repeat frames if necessary
   1062 
   1063 	LOG_V( "num_slices is %d, allocating %d buffer_ids\n", pic_data->num_slices, (pic_data->num_slices * 2) + 2);
   1064 
   1065 	buffer_ids = g_malloc(sizeof(VABufferID) *
   1066 					((pic_data->num_slices * 2) + 2));
   1067 
   1068 	if (buffer_ids == NULL)
   1069 	{
   1070 		LOG_E( "Cannot allocate buffer IDs\n");
   1071 		ret = MIX_RESULT_NO_MEMORY;
   1072 		goto cleanup;
   1073 	}
   1074 
   1075 	//Set up reference frames for the picture parameter buffer
   1076 
   1077 	//Set the picture type (I, B or P frame)
   1078 	//For H.264 we use the first encountered slice type for this (check - may need to change later to search all slices for B type)
   1079 	MixFrameType frame_type = TYPE_INVALID;
   1080 
   1081 	switch (pic_data->slc_data->slc_parms.slice_type)
   1082 	{
   1083 		case 0:
   1084 		case 3:
   1085 		case 5:
   1086 		case 8:
   1087 			frame_type = TYPE_P;
   1088 			break;
   1089 		case 1:
   1090 		case 6:
   1091 			frame_type = TYPE_B;
   1092 			break;
   1093 		case 2:
   1094 		case 4:
   1095 		case 7:
   1096 		case 9:
   1097 			frame_type = TYPE_I;
   1098 			break;
   1099 		default:
   1100 			break;
   1101 	}
   1102 
   1103 	//Do not have to check for B frames after a seek
   1104 	//Note:  Demux should seek to IDR (instantaneous decoding refresh) frame, otherwise
   1105 	//  DPB will not be correct and frames may come in with invalid references
   1106 	//  This will be detected when DPB is checked for valid mapped surfaces and
   1107 	//  error returned from there.
   1108 
   1109 	LOG_V( "Getting a new surface for frame_num %d\n", pic_params->frame_num);
   1110 	LOG_V( "frame type is %d\n", frame_type);
   1111 
   1112 
   1113 
   1114 	//Set the frame type for the frame object (used in reordering by frame manager)
   1115 	ret = mix_videoframe_set_frame_type(frame, frame_type);
   1116 
   1117 	if (ret != MIX_RESULT_SUCCESS)
   1118 	{
   1119 		LOG_E( "Error setting frame type on frame\n");
   1120 		goto cleanup;
   1121 	}
   1122 
   1123 	LOG_V( "Updating DPB for libva\n");
   1124 
   1125 	//Now handle the reference frames and surface IDs for DPB and current frame
   1126 	mix_videofmt_h264_handle_ref_frames(mix, pic_params, frame);
   1127 
   1128 #ifdef HACK_DPB
   1129 	//We have to provide a hacked DPB rather than complete DPB for libva as workaround
   1130 	mix_videofmt_h264_hack_dpb(mix, pic_data);
   1131 #endif
   1132 
   1133 	//Libva buffer set up
   1134 
   1135 	vadisplay = mix->va_display;
   1136 	vacontext = mix->va_context;
   1137 
   1138 	LOG_V( "Creating libva picture parameter buffer\n");
   1139 	LOG_V( "picture parameter buffer shows num_ref_frames is %d\n", pic_params->num_ref_frames);
   1140 
   1141 	//First the picture parameter buffer
   1142 	vret = vaCreateBuffer(vadisplay, vacontext,
   1143 			VAPictureParameterBufferType,
   1144 			sizeof(VAPictureParameterBufferH264),
   1145 			1,
   1146 			pic_params,
   1147 			&buffer_ids[buffer_id_cnt]);
   1148 	buffer_id_cnt++;
   1149 
   1150 	if (vret != VA_STATUS_SUCCESS)
   1151 	{
   1152 		ret = MIX_RESULT_FAIL;
   1153 		LOG_E( "Video driver returned error from vaCreateBuffer\n");
   1154 		goto cleanup;
   1155 	}
   1156 
   1157 	LOG_V( "Creating libva IQMatrix buffer\n");
   1158 
   1159 
   1160 	//Then the IQ matrix buffer
   1161     	vret = vaCreateBuffer(vadisplay, vacontext,
   1162                     VAIQMatrixBufferType,
   1163                     sizeof(VAIQMatrixBufferH264),
   1164                     1,
   1165                     data->IQ_matrix_buf,
   1166                     &buffer_ids[buffer_id_cnt]);
   1167 	buffer_id_cnt++;
   1168 
   1169 	if (vret != VA_STATUS_SUCCESS)
   1170 	{
   1171 		ret = MIX_RESULT_FAIL;
   1172 		LOG_E( "Video driver returned error from vaCreateBuffer\n");
   1173 		goto cleanup;
   1174 	}
   1175 
   1176 
   1177 	//Now for slices
   1178 	int i = 0;
   1179 	gpointer video_frame;
   1180 	for (;i < pic_data->num_slices; i++)
   1181 	{
   1182 
   1183 		LOG_V( "Creating libva slice parameter buffer, for slice %d\n", i);
   1184 
   1185 		//Do slice parameters
   1186 
   1187 		//First patch up the List0 and List1 surface IDs
   1188 		int j = 0;
   1189 		guint poc = 0;
   1190 		for (; j <= pic_data->slc_data[i].slc_parms.num_ref_idx_l0_active_minus1; j++)
   1191 		{
   1192 			if (!(pic_data->slc_data[i].slc_parms.RefPicList0[j].flags & VA_PICTURE_H264_INVALID))
   1193 			{
   1194 				poc = mix_videofmt_h264_get_poc(&(pic_data->slc_data[i].slc_parms.RefPicList0[j]));
   1195 				video_frame = g_hash_table_lookup(self->dpb_surface_table, (gpointer)poc);
   1196 				if (video_frame == NULL)
   1197 				{
   1198 					LOG_E(  "unable to find surface of picture %d (current picture %d).", poc, mix_videofmt_h264_get_poc(&pic_params->CurrPic));
   1199 					ret = MIX_RESULT_FAIL;
   1200 					goto cleanup;
   1201 				}
   1202 				else
   1203 				{
   1204 					pic_data->slc_data[i].slc_parms.RefPicList0[j].picture_id =
   1205 						((MixVideoFrame *)video_frame)->frame_id;
   1206 				}
   1207 			}
   1208 
   1209 		}
   1210 
   1211 		if ((pic_data->slc_data->slc_parms.slice_type == 1) || (pic_data->slc_data->slc_parms.slice_type == 6))
   1212 		{
   1213 			for (j = 0; j <= pic_data->slc_data[i].slc_parms.num_ref_idx_l1_active_minus1; j++)
   1214 			{
   1215 				if (!(pic_data->slc_data[i].slc_parms.RefPicList1[j].flags & VA_PICTURE_H264_INVALID))
   1216 				{
   1217 					poc = mix_videofmt_h264_get_poc(&(pic_data->slc_data[i].slc_parms.RefPicList1[j]));
   1218 					video_frame = g_hash_table_lookup(self->dpb_surface_table, (gpointer)poc);
   1219 					if (video_frame == NULL)
   1220 					{
   1221 						LOG_E(  "unable to find surface of picture %d (current picture %d).", poc, mix_videofmt_h264_get_poc(&pic_params->CurrPic));
   1222 						ret = MIX_RESULT_FAIL;
   1223 						goto cleanup;
   1224 					}
   1225 					else
   1226 					{
   1227 						pic_data->slc_data[i].slc_parms.RefPicList1[j].picture_id =
   1228 							((MixVideoFrame *)video_frame)->frame_id;
   1229 					}
   1230 				}
   1231 			}
   1232 		}
   1233 
   1234 
   1235 		//Then do the libva setup
   1236 
   1237 	       	vret = vaCreateBuffer(vadisplay, vacontext,
   1238 			 VASliceParameterBufferType,
   1239 			 sizeof(VASliceParameterBufferH264),
   1240 			 1,
   1241 	       	         &(pic_data->slc_data[i].slc_parms),
   1242 	       	         &buffer_ids[buffer_id_cnt]);
   1243 
   1244 		if (vret != VA_STATUS_SUCCESS)
   1245 		{
   1246 			ret = MIX_RESULT_FAIL;
   1247 			LOG_E( "Video driver returned error from vaCreateBuffer\n");
   1248 			goto cleanup;
   1249 		}
   1250 
   1251 	    	buffer_id_cnt++;
   1252 
   1253 
   1254 		LOG_V( "Creating libva slice data buffer for slice %d, using slice address %x, with offset %d and size %u\n", i, (guint)pic_data->slc_data[i].buffer_addr, pic_data->slc_data[i].slc_parms.slice_data_offset, pic_data->slc_data[i].slice_size);
   1255 
   1256 
   1257 		//Do slice data
   1258 
   1259       		vret = vaCreateBuffer(vadisplay, vacontext,
   1260        	       	  VASliceDataBufferType,
   1261 		  //size
   1262 		  pic_data->slc_data[i].slice_size,
   1263 		  //num_elements
   1264        	       	  1,
   1265 		  //slice data buffer pointer
   1266 		  //Note that this is the original data buffer ptr;
   1267 		  // offset to the actual slice data is provided in
   1268 		  // slice_data_offset in VASliceParameterBufferH264
   1269 		  pic_data->slc_data[i].buffer_addr + pic_data->slc_data[i].slice_offset,
   1270       	       	  &buffer_ids[buffer_id_cnt]);
   1271 
   1272        	 	buffer_id_cnt++;
   1273 
   1274        	 	if (vret != VA_STATUS_SUCCESS)
   1275 		{
   1276 			ret = MIX_RESULT_FAIL;
   1277  			LOG_E( "Video driver returned error from vaCreateBuffer\n");
   1278 			goto cleanup;
   1279 		}
   1280 
   1281 	}
   1282 
   1283 	gulong surface = 0;
   1284 
   1285 	//Get our surface ID from the frame object
   1286 	ret = mix_videoframe_get_frame_id(frame, &surface);
   1287 
   1288 	if (ret != MIX_RESULT_SUCCESS)
   1289 	{
   1290 		LOG_E( "Error getting surface ID from frame object\n");
   1291 		goto cleanup;
   1292 	}
   1293 
   1294 	LOG_V( "Calling vaBeginPicture\n");
   1295 
   1296 	//Now we can begin the picture
   1297       	vret = vaBeginPicture(vadisplay, vacontext, surface);
   1298 
   1299        	if (vret != VA_STATUS_SUCCESS)
   1300 	{
   1301 		ret = MIX_RESULT_FAIL;
   1302 		LOG_E( "Video driver returned error from vaBeginPicture\n");
   1303 		goto cleanup;
   1304 	}
   1305 
   1306 	LOG_V( "Calling vaRenderPicture\n");
   1307 
   1308 	//Render the picture
   1309       	vret = vaRenderPicture(vadisplay, vacontext,
   1310       	     		buffer_ids,
   1311 			buffer_id_cnt);
   1312 
   1313 
   1314        	if (vret != VA_STATUS_SUCCESS)
   1315 	{
   1316 		ret = MIX_RESULT_FAIL;
   1317 		LOG_E( "Video driver returned error from vaRenderPicture\n");
   1318 		goto cleanup;
   1319 	}
   1320 
   1321 	LOG_V( "Calling vaEndPicture\n");
   1322 
   1323 	//End picture
   1324 	vret = vaEndPicture(vadisplay, vacontext);
   1325 
   1326        	if (vret != VA_STATUS_SUCCESS)
   1327 	{
   1328 		ret = MIX_RESULT_FAIL;
   1329 		LOG_E( "Video driver returned error from vaEndPicture\n");
   1330 		goto cleanup;
   1331 	}
   1332 
   1333 	LOG_V( "Calling vaSyncSurface\n");
   1334 
   1335 	//Decode the picture
   1336       	vret = vaSyncSurface(vadisplay, surface);
   1337 
   1338        	if (vret != VA_STATUS_SUCCESS)
   1339 	{
   1340 		ret = MIX_RESULT_FAIL;
   1341 		LOG_E( "Video driver returned error from vaSyncSurface\n");
   1342 		goto cleanup;
   1343 	}
   1344 
   1345 
   1346 	if (pic_index == 0)
   1347 	{
   1348 		//Set the discontinuity flag
   1349 		mix_videoframe_set_discontinuity(frame, discontinuity);
   1350 
   1351 		//Set the timestamp
   1352 		mix_videoframe_set_timestamp(frame, timestamp);
   1353 
   1354 		guint32 frame_structure = VA_FRAME_PICTURE;
   1355 		if (pic_params->CurrPic.flags & VA_PICTURE_H264_TOP_FIELD)
   1356 		{
   1357 			frame_structure =  VA_TOP_FIELD;
   1358 		}
   1359 		else if (pic_params->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD)
   1360 		{
   1361 			frame_structure = VA_BOTTOM_FIELD;
   1362 		}
   1363 		mix_videoframe_set_frame_structure(frame, frame_structure);
   1364 	}
   1365 	else
   1366 	{
   1367 		// frame must be field-coded, no need to set
   1368 		// discontinuity falg and time stamp again
   1369 		mix_videoframe_set_frame_structure(frame, VA_BOTTOM_FIELD | VA_TOP_FIELD);
   1370 	}
   1371 
   1372 	//TODO need to save off frame when handling is added for repeat frames?
   1373 
   1374 //TODO Complete YUVDUMP code and move into base class
   1375 #ifdef YUVDUMP
   1376 	if (mix_video_h264_counter < 10)
   1377 		ret = GetImageFromSurface (mix, frame);
   1378 //		g_usleep(5000000);
   1379 #endif  /* YUVDUMP */
   1380 
   1381 	LOG_V( "Enqueueing the frame with frame manager, timestamp %"G_GINT64_FORMAT"\n", timestamp);
   1382 
   1383 
   1384 	cleanup:
   1385 
   1386 	if (NULL != buffer_ids)
   1387 		g_free(buffer_ids);
   1388 
   1389 
   1390 	LOG_V( "End\n");
   1391 
   1392 	return ret;
   1393 
   1394 }
   1395 
   1396 
   1397 MIX_RESULT mix_videofmt_h264_process_decode(MixVideoFormat *mix,
   1398 					vbp_data_h264 *data,
   1399 					guint64 timestamp,
   1400 					gboolean discontinuity)
   1401 {
   1402 	MIX_RESULT ret = MIX_RESULT_SUCCESS;
   1403 	int i = 0;
   1404 
   1405 	if ((mix == NULL) || (data == NULL))
   1406 	{
   1407 		LOG_E( "Null pointer passed in\n");
   1408 		return MIX_RESULT_NULL_PTR;
   1409 	}
   1410 
   1411 	//Get a frame from the surface pool
   1412 	MixVideoFrame *frame = NULL;
   1413 
   1414 	ret = mix_surfacepool_get(mix->surfacepool, &frame);
   1415 
   1416 	if (ret != MIX_RESULT_SUCCESS)
   1417 	{
   1418 		LOG_E( "Error getting frame from surfacepool\n");
   1419 		return MIX_RESULT_FAIL;
   1420 	}
   1421 
   1422 
   1423 	for (i = 0; i < data->num_pictures; i++)
   1424 	{
   1425 		ret = mix_videofmt_h264_process_decode_picture(mix, data, timestamp, discontinuity, i, frame);
   1426 		if (ret != 	MIX_RESULT_SUCCESS)
   1427 		{
   1428 			LOG_E( "Failed to process decode picture %d, error =  %#X.", data->buf_number, ret);
   1429 			break;
   1430 		}
   1431 	}
   1432 
   1433 	if (ret == MIX_RESULT_SUCCESS)
   1434 	{
   1435 		//Enqueue the decoded frame using frame manager
   1436 		ret = mix_framemanager_enqueue(mix->framemgr, frame);
   1437 		if (ret != MIX_RESULT_SUCCESS)
   1438                	{
   1439  			LOG_E( "Error enqueuing frame object\n");
   1440 			mix_videoframe_unref(frame);
   1441                	}
   1442 
   1443 	}
   1444 	else
   1445 	{
   1446 		mix_videoframe_unref(frame);
   1447 	}
   1448 	mix_videofmt_h264_release_input_buffers(mix, timestamp);
   1449 
   1450 	return ret;
   1451 }
   1452 
   1453 MIX_RESULT mix_videofmt_h264_handle_ref_frames(MixVideoFormat *mix,
   1454 					VAPictureParameterBufferH264* pic_params,
   1455 					MixVideoFrame * current_frame
   1456 					) {
   1457 
   1458 	guint poc = 0;
   1459 
   1460 	LOG_V( "Begin\n");
   1461 
   1462         if (mix == NULL || current_frame == NULL || pic_params == NULL)
   1463 	{
   1464 		LOG_E( "Null pointer passed in\n");
   1465 		return MIX_RESULT_NULL_PTR;
   1466 	}
   1467 
   1468 
   1469 	LOG_V( "Pic_params has flags %d, topfieldcnt %d, bottomfieldcnt %d.  Surface ID is %d\n", pic_params->CurrPic.flags, pic_params->CurrPic.TopFieldOrderCnt, pic_params->CurrPic.BottomFieldOrderCnt, (gint) current_frame->frame_id);
   1470 
   1471 #ifdef MIX_LOG_ENABLE
   1472 	if (pic_params->CurrPic.flags & VA_PICTURE_H264_INVALID)
   1473 		LOG_V( "Flags show VA_PICTURE_H264_INVALID\n");
   1474 
   1475 	if (pic_params->CurrPic.flags & VA_PICTURE_H264_TOP_FIELD)
   1476 		LOG_V( "Flags show VA_PICTURE_H264_TOP_FIELD\n");
   1477 
   1478 	if (pic_params->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD)
   1479 		LOG_V( "Flags show VA_PICTURE_H264_BOTTOM_FIELD\n");
   1480 
   1481 	if (pic_params->CurrPic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE)
   1482 		LOG_V( "Flags show VA_PICTURE_H264_SHORT_TERM_REFERENCE\n");
   1483 
   1484 	if (pic_params->CurrPic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)
   1485 		LOG_V( "Flags show VA_PICTURE_H264_LONG_TERM_REFERENCE\n");
   1486 #endif
   1487 
   1488         MixVideoFormat_H264 *self = MIX_VIDEOFORMAT_H264(mix);
   1489 
   1490 
   1491 	//First we need to check the parser DBP against our DPB table
   1492 	//So for each item in our DBP table, we look to see if it is in the parser DPB
   1493 	//If it is not, it gets unrefed and removed
   1494 #ifdef MIX_LOG_ENABLE
   1495 	guint num_removed =
   1496 #endif
   1497 	g_hash_table_foreach_remove(self->dpb_surface_table, mix_videofmt_h264_check_in_DPB, pic_params);
   1498 
   1499 		LOG_V( "%d entries removed from DPB surface table at this frame\n", num_removed);
   1500 
   1501 
   1502 	MixVideoFrame *mvf = NULL;
   1503 	gboolean found = FALSE;
   1504 	//Set the surface ID for everything in the parser DPB
   1505 	int i = 0;
   1506 	for (; i < 16; i++)
   1507 	{
   1508 		if (!(pic_params->ReferenceFrames[i].flags & VA_PICTURE_H264_INVALID))
   1509 		{
   1510 
   1511 			poc = mix_videofmt_h264_get_poc(&(pic_params->ReferenceFrames[i]));
   1512 		LOG_V( "Looking up poc %d in dpb table\n", poc);
   1513 			found = g_hash_table_lookup_extended(self->dpb_surface_table, (gpointer)poc, NULL, (gpointer)&mvf);
   1514 
   1515 			if (found)
   1516 			{
   1517 				pic_params->ReferenceFrames[i].picture_id = mvf->frame_id;
   1518 		LOG_V( "Looked up poc %d in dpb table found frame ID %d\n", poc, (gint)mvf->frame_id);
   1519 			} else {
   1520 		LOG_V( "Looking up poc %d in dpb table did not find value\n", poc);
   1521 			}
   1522 		LOG_V( "For poc %d, set surface id for DPB index %d to %d\n", poc, i, (gint)pic_params->ReferenceFrames[i].picture_id);
   1523 		}
   1524 
   1525 	}
   1526 
   1527 
   1528 	//Set picture_id for current picture
   1529 	pic_params->CurrPic.picture_id = current_frame->frame_id;
   1530 
   1531 	//Check to see if current frame is a reference frame
   1532 	if ((pic_params->CurrPic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) || (pic_params->CurrPic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE))
   1533 	{
   1534 		//Get current frame's POC
   1535 		poc = mix_videofmt_h264_get_poc(&(pic_params->CurrPic));
   1536 
   1537 		//Increment the reference count for this frame
   1538 		mix_videoframe_ref(current_frame);
   1539 
   1540 		LOG_V( "Inserting poc %d, surfaceID %d\n", poc, (gint)current_frame->frame_id);
   1541 		//Add this frame to the DPB surface table
   1542 		g_hash_table_insert(self->dpb_surface_table, (gpointer)poc, current_frame);
   1543 	}
   1544 
   1545 
   1546 
   1547 	LOG_V( "End\n");
   1548 
   1549 	return MIX_RESULT_SUCCESS;
   1550 }
   1551 
   1552 guint mix_videofmt_h264_get_poc(VAPictureH264 *pic)
   1553 {
   1554 
   1555         if (pic == NULL)
   1556                 return 0;
   1557 
   1558 	if (pic->flags & VA_PICTURE_H264_BOTTOM_FIELD)
   1559 		return pic->BottomFieldOrderCnt;
   1560 
   1561 
   1562 	if (pic->flags & VA_PICTURE_H264_TOP_FIELD)
   1563 		return pic->TopFieldOrderCnt;
   1564 
   1565 	return pic->TopFieldOrderCnt;
   1566 
   1567 }
   1568 
   1569 
   1570 gboolean mix_videofmt_h264_check_in_DPB(gpointer key, gpointer value, gpointer user_data)
   1571 {
   1572 	gboolean ret = TRUE;
   1573 
   1574         if ((value == NULL) || (user_data == NULL))  //Note that 0 is valid value for key
   1575                 return FALSE;
   1576 
   1577 	VAPictureH264* vaPic = NULL;
   1578 	int i = 0;
   1579 	for (; i < 16; i++)
   1580 	{
   1581 		vaPic = &(((VAPictureParameterBufferH264*)user_data)->ReferenceFrames[i]);
   1582 		if (vaPic->flags & VA_PICTURE_H264_INVALID)
   1583 			continue;
   1584 
   1585 		if ((guint)key == vaPic->TopFieldOrderCnt ||
   1586 			(guint)key == vaPic->BottomFieldOrderCnt)
   1587 		{
   1588 			ret = FALSE;
   1589 			break;
   1590 		}
   1591 	}
   1592 
   1593 	return ret;
   1594 }
   1595 
   1596 void mix_videofmt_h264_destroy_DPB_key(gpointer data)
   1597 {
   1598 //TODO remove this method and don't register it with the hash table foreach call; it is no longer needed
   1599 	LOG_V( "Begin, poc of %d\n", (guint)data);
   1600 	LOG_V( "End\n");
   1601 
   1602 	return;
   1603 }
   1604 
   1605 void mix_videofmt_h264_destroy_DPB_value(gpointer data)
   1606 {
   1607 	LOG_V( "Begin\n");
   1608         if (data == NULL)
   1609         	return ;
   1610 	mix_videoframe_unref((MixVideoFrame *)data);
   1611 
   1612 	return;
   1613 }
   1614 
   1615 
   1616 MIX_RESULT mix_videofmt_h264_release_input_buffers(MixVideoFormat *mix,
   1617 					guint64 timestamp
   1618 					) {
   1619 
   1620 	MixInputBufferEntry *bufentry = NULL;
   1621 	gboolean done = FALSE;
   1622 
   1623 	LOG_V( "Begin\n");
   1624 
   1625         if (mix == NULL)
   1626                 return MIX_RESULT_NULL_PTR;
   1627 
   1628 	//Dequeue and release all input buffers for this frame
   1629 
   1630 	LOG_V( "Releasing all the MixBuffers for this frame\n");
   1631 
   1632 	//While the head of the queue has timestamp == current ts
   1633 	//dequeue the entry, unref the MixBuffer, and free the struct
   1634 	done = FALSE;
   1635 	while (!done)
   1636 	{
   1637 		bufentry = (MixInputBufferEntry *) g_queue_peek_head(
   1638 				mix->inputbufqueue);
   1639 		if (bufentry == NULL) break;
   1640 	LOG_V( "head of queue buf %x, timestamp %"G_GINT64_FORMAT", buffer timestamp %"G_GINT64_FORMAT"\n", (guint)bufentry->buf, timestamp, bufentry->timestamp);
   1641 
   1642 		if (bufentry->timestamp != timestamp)
   1643 		{
   1644 	LOG_V( "buf %x, timestamp %"G_GINT64_FORMAT", buffer timestamp %"G_GINT64_FORMAT"\n", (guint)bufentry->buf, timestamp, bufentry->timestamp);
   1645 			done = TRUE;
   1646 			break;
   1647 		}
   1648 
   1649 		bufentry = (MixInputBufferEntry *) g_queue_pop_head(
   1650 				mix->inputbufqueue);
   1651 		LOG_V( "Unref this MixBuffers %x\n", (guint)bufentry->buf);
   1652 		mix_buffer_unref(bufentry->buf);
   1653 		g_free(bufentry);
   1654 	}
   1655 
   1656 
   1657 	LOG_V( "End\n");
   1658 
   1659 	return MIX_RESULT_SUCCESS;
   1660 }
   1661 
   1662 
   1663 
   1664