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 "mixvideolog.h"
     10 
     11 #include "mixvideoformat.h"
     12 
     13 #define MIXUNREF(obj, unref) if(obj) { unref(obj); obj = NULL; }
     14 
     15 
     16 /* Default vmethods implementation */
     17 static MIX_RESULT mix_videofmt_getcaps_default(MixVideoFormat *mix,
     18 		GString *msg);
     19 static MIX_RESULT mix_videofmt_initialize_default(MixVideoFormat *mix,
     20 		MixVideoConfigParamsDec * config_params,
     21                 MixFrameManager * frame_mgr,
     22 		MixBufferPool * input_buf_pool,
     23 		MixSurfacePool ** surface_pool,
     24                 VADisplay vadisplay);
     25 static MIX_RESULT
     26 		mix_videofmt_decode_default(MixVideoFormat *mix,
     27 		MixBuffer * bufin[], gint bufincnt,
     28                 MixVideoDecodeParams * decode_params);
     29 static MIX_RESULT mix_videofmt_flush_default(MixVideoFormat *mix);
     30 static MIX_RESULT mix_videofmt_eos_default(MixVideoFormat *mix);
     31 static MIX_RESULT mix_videofmt_deinitialize_default(MixVideoFormat *mix);
     32 
     33 static GObjectClass *parent_class = NULL;
     34 
     35 static void mix_videoformat_finalize(GObject * obj);
     36 G_DEFINE_TYPE (MixVideoFormat, mix_videoformat, G_TYPE_OBJECT);
     37 
     38 static void mix_videoformat_init(MixVideoFormat * self) {
     39 
     40 	/* public member initialization */
     41 	/* These are all public because MixVideoFormat objects are completely internal to MixVideo,
     42 		no need for private members  */
     43 
     44 	self->initialized = FALSE;
     45 	self->framemgr = NULL;
     46 	self->surfacepool = NULL;
     47 	self->inputbufpool = NULL;
     48 	self->inputbufqueue = NULL;
     49 	self->va_display = NULL;
     50 	self->va_context = VA_INVALID_ID;
     51 	self->va_config = VA_INVALID_ID;
     52 	self->va_surfaces = NULL;
     53 	self->va_num_surfaces = 0;
     54 	self->mime_type = NULL;
     55 	self->frame_rate_num = 0;
     56 	self->frame_rate_denom = 0;
     57 	self->picture_width = 0;
     58 	self->picture_height = 0;
     59 	self->parse_in_progress = FALSE;
     60 	self->current_timestamp = 0;
     61 }
     62 
     63 static void mix_videoformat_class_init(MixVideoFormatClass * klass) {
     64 	GObjectClass *gobject_class = (GObjectClass *) klass;
     65 
     66 	/* parent class for later use */
     67 	parent_class = g_type_class_peek_parent(klass);
     68 
     69 	gobject_class->finalize = mix_videoformat_finalize;
     70 
     71 	/* setup vmethods with base implementation */
     72 	klass->getcaps = mix_videofmt_getcaps_default;
     73 	klass->initialize = mix_videofmt_initialize_default;
     74 	klass->decode = mix_videofmt_decode_default;
     75 	klass->flush = mix_videofmt_flush_default;
     76 	klass->eos = mix_videofmt_eos_default;
     77 	klass->deinitialize = mix_videofmt_deinitialize_default;
     78 }
     79 
     80 MixVideoFormat *
     81 mix_videoformat_new(void) {
     82 	MixVideoFormat *ret = g_object_new(MIX_TYPE_VIDEOFORMAT, NULL);
     83 
     84 	return ret;
     85 }
     86 
     87 void mix_videoformat_finalize(GObject * obj) {
     88 	/* clean up here. */
     89 	VAStatus va_status;
     90 
     91 	MixVideoFormat *mix = MIX_VIDEOFORMAT(obj);
     92 	MixInputBufferEntry *buf_entry = NULL;
     93 
     94         if(mix->objectlock) {
     95                 g_mutex_free(mix->objectlock);
     96                 mix->objectlock = NULL;
     97         }
     98 
     99 	if (mix->mime_type)
    100 	{
    101 		if (mix->mime_type->str)
    102 			g_string_free(mix->mime_type, TRUE);
    103 		else
    104 			g_string_free(mix->mime_type, FALSE);
    105 	}
    106 
    107 	//MiVideo object calls the _deinitialize() for frame manager
    108 	MIXUNREF(mix->framemgr, mix_framemanager_unref);
    109 
    110 	if (mix->surfacepool)
    111 	{
    112 	  mix_surfacepool_deinitialize(mix->surfacepool);
    113 	  MIXUNREF(mix->surfacepool, mix_surfacepool_unref);
    114 	}
    115 
    116 	//libVA cleanup (vaTerminate is called from MixVideo object)
    117 	if (mix->va_display) {
    118 		if (mix->va_context != VA_INVALID_ID)
    119 		{
    120 			va_status = vaDestroyConfig(mix->va_display, mix->va_config);
    121 			if (va_status != VA_STATUS_SUCCESS) {
    122 			LOG_W( "Failed vaDestroyConfig\n");
    123 			}
    124 			mix->va_config = VA_INVALID_ID;
    125 		}
    126 		if (mix->va_context != VA_INVALID_ID)
    127 		{
    128 			va_status = vaDestroyContext(mix->va_display, mix->va_context);
    129 			if (va_status != VA_STATUS_SUCCESS) {
    130 				LOG_W( "Failed vaDestroyContext\n");
    131 			}
    132 			mix->va_context = VA_INVALID_ID;
    133 		}
    134 		if (mix->va_surfaces)
    135 		{
    136 			va_status = vaDestroySurfaces(mix->va_display, mix->va_surfaces, mix->va_num_surfaces);
    137 			if (va_status != VA_STATUS_SUCCESS) {
    138 				LOG_W( "Failed vaDestroySurfaces\n");
    139 			}
    140 			g_free(mix->va_surfaces);
    141 			mix->va_surfaces = NULL;
    142 			mix->va_num_surfaces = 0;
    143 		}
    144 	}
    145 
    146 
    147 	//Deinit input buffer queue
    148 
    149 	while (!g_queue_is_empty(mix->inputbufqueue))
    150 	{
    151 		buf_entry = g_queue_pop_head(mix->inputbufqueue);
    152 		mix_buffer_unref(buf_entry->buf);
    153 		g_free(buf_entry);
    154 	}
    155 
    156 	g_queue_free(mix->inputbufqueue);
    157 
    158 	//MixBuffer pool is deallocated in MixVideo object
    159 	mix->inputbufpool = NULL;
    160 
    161 	/* Chain up parent */
    162 	if (parent_class->finalize) {
    163 		parent_class->finalize(obj);
    164 	}
    165 }
    166 
    167 MixVideoFormat *
    168 mix_videoformat_ref(MixVideoFormat * mix) {
    169 	return (MixVideoFormat *) g_object_ref(G_OBJECT(mix));
    170 }
    171 
    172 /* Default vmethods implementation */
    173 static MIX_RESULT mix_videofmt_getcaps_default(MixVideoFormat *mix,
    174 		GString *msg) {
    175 	g_print("mix_videofmt_getcaps_default\n");
    176 	return MIX_RESULT_SUCCESS;
    177 }
    178 
    179 static MIX_RESULT mix_videofmt_initialize_default(MixVideoFormat *mix,
    180 		MixVideoConfigParamsDec * config_params,
    181                 MixFrameManager * frame_mgr,
    182 		MixBufferPool * input_buf_pool,
    183 		MixSurfacePool ** surface_pool,
    184                 VADisplay va_display) {
    185 
    186 	LOG_V(	"Begin\n");
    187 
    188 	MIX_RESULT res = MIX_RESULT_SUCCESS;
    189 	MixInputBufferEntry *buf_entry = NULL;
    190 
    191 	if (!mix || !config_params || !frame_mgr || !input_buf_pool || !surface_pool || !va_display)
    192 	{
    193 		LOG_E( "NUll pointer passed in\n");
    194 		return (MIX_RESULT_NULL_PTR);
    195 	}
    196 
    197 	// Create object lock
    198 	// Note that g_thread_init() has already been called by mix_video_init()
    199 	if (mix->objectlock)  //If already exists, then deallocate old one (we are being re-initialized)
    200 	{
    201                 g_mutex_free(mix->objectlock);
    202                 mix->objectlock = NULL;
    203 	}
    204 	mix->objectlock = g_mutex_new();
    205 	if (!mix->objectlock) {
    206 		LOG_E( "!mix->objectlock\n");
    207 		return (MIX_RESULT_NO_MEMORY);
    208 	}
    209 
    210 	g_mutex_lock(mix->objectlock);
    211 
    212 	//Clean up any previous framemgr
    213 	MIXUNREF(mix->framemgr, mix_framemanager_unref);
    214 	mix->framemgr = frame_mgr;
    215 	mix_framemanager_ref(mix->framemgr);
    216 
    217 	mix->va_display = va_display;
    218 
    219 	if (mix->mime_type)  //Clean up any previous mime_type
    220 	{
    221 		if (mix->mime_type->str)
    222 			g_string_free(mix->mime_type, TRUE);
    223 		else
    224 			g_string_free(mix->mime_type, FALSE);
    225 	}
    226 	gchar *mime_tmp = NULL;
    227 	res = mix_videoconfigparamsdec_get_mime_type(config_params, &mime_tmp);
    228 	if (mime_tmp)
    229 	{
    230 		mix->mime_type = g_string_new(mime_tmp);
    231 		g_free(mime_tmp);
    232 		if (!mix->mime_type) //new failed
    233 		{
    234 			res = MIX_RESULT_NO_MEMORY;
    235 			LOG_E( "Could not duplicate mime_type\n");
    236 			goto cleanup;
    237 		}
    238 	}  //else there is no mime_type; leave as NULL
    239 
    240 	res = mix_videoconfigparamsdec_get_frame_rate(config_params, &(mix->frame_rate_num), &(mix->frame_rate_denom));
    241 	if (res != MIX_RESULT_SUCCESS)
    242 	{
    243 		LOG_E( "Error getting frame_rate\n");
    244 		goto cleanup;
    245 	}
    246 	res = mix_videoconfigparamsdec_get_picture_res(config_params, &(mix->picture_width), &(mix->picture_height));
    247 	if (res != MIX_RESULT_SUCCESS)
    248 	{
    249 		LOG_E( "Error getting picture_res\n");
    250 		goto cleanup;
    251 	}
    252 
    253 	if (mix->inputbufqueue)
    254 	{
    255 		//Deinit previous input buffer queue
    256 
    257 		while (!g_queue_is_empty(mix->inputbufqueue))
    258 		{
    259 			buf_entry = g_queue_pop_head(mix->inputbufqueue);
    260 			mix_buffer_unref(buf_entry->buf);
    261 			g_free(buf_entry);
    262 		}
    263 
    264 		g_queue_free(mix->inputbufqueue);
    265 	}
    266 
    267 	//MixBuffer pool is cleaned up in MixVideo object
    268 	mix->inputbufpool = NULL;
    269 
    270 	mix->inputbufpool = input_buf_pool;
    271 	mix->inputbufqueue = g_queue_new();
    272 	if (!mix->inputbufqueue)  //New failed
    273 	{
    274 		res = MIX_RESULT_NO_MEMORY;
    275 		LOG_E( "Could not duplicate mime_type\n");
    276 		goto cleanup;
    277 	}
    278 
    279 	// surface pool, VA context/config and parser handle are initialized by
    280 	// derived classes
    281 
    282 
    283 	cleanup:
    284 	if (res != MIX_RESULT_SUCCESS) {
    285 
    286 		MIXUNREF(mix->framemgr, mix_framemanager_unref);
    287 		if (mix->mime_type)
    288 		{
    289 			if (mix->mime_type->str)
    290 				g_string_free(mix->mime_type, TRUE);
    291 			else
    292 				g_string_free(mix->mime_type, FALSE);
    293 			mix->mime_type = NULL;
    294 		}
    295 
    296 		if (mix->objectlock)
    297 			g_mutex_unlock(mix->objectlock);
    298                 g_mutex_free(mix->objectlock);
    299                 mix->objectlock = NULL;
    300 		mix->frame_rate_num = 0;
    301 		mix->frame_rate_denom = 1;
    302 		mix->picture_width = 0;
    303 		mix->picture_height = 0;
    304 
    305 	} else {
    306 	//Normal unlock
    307 		if (mix->objectlock)
    308 			g_mutex_unlock(mix->objectlock);
    309 	}
    310 
    311 	LOG_V( "End\n");
    312 
    313 	return res;
    314 }
    315 
    316 static MIX_RESULT mix_videofmt_decode_default(MixVideoFormat *mix,
    317 		MixBuffer * bufin[], gint bufincnt,
    318                 MixVideoDecodeParams * decode_params) {
    319 	return MIX_RESULT_SUCCESS;
    320 }
    321 
    322 static MIX_RESULT mix_videofmt_flush_default(MixVideoFormat *mix) {
    323 	return MIX_RESULT_SUCCESS;
    324 }
    325 
    326 static MIX_RESULT mix_videofmt_eos_default(MixVideoFormat *mix) {
    327 	return MIX_RESULT_SUCCESS;
    328 }
    329 
    330 static MIX_RESULT mix_videofmt_deinitialize_default(MixVideoFormat *mix) {
    331 
    332 	//All teardown is being done in _finalize()
    333 
    334 	return MIX_RESULT_SUCCESS;
    335 }
    336 
    337 /* mixvideoformat class methods implementation */
    338 
    339 MIX_RESULT mix_videofmt_getcaps(MixVideoFormat *mix, GString *msg) {
    340 	MixVideoFormatClass *klass = MIX_VIDEOFORMAT_GET_CLASS(mix);
    341 	g_print("mix_videofmt_getcaps\n");
    342 	if (klass->getcaps) {
    343 		return klass->getcaps(mix, msg);
    344 	}
    345 	return MIX_RESULT_NOTIMPL;
    346 }
    347 
    348 MIX_RESULT mix_videofmt_initialize(MixVideoFormat *mix,
    349 		MixVideoConfigParamsDec * config_params,
    350                 MixFrameManager * frame_mgr,
    351 		MixBufferPool * input_buf_pool,
    352 		MixSurfacePool ** surface_pool,
    353 		VADisplay va_display) {
    354 	MixVideoFormatClass *klass = MIX_VIDEOFORMAT_GET_CLASS(mix);
    355 
    356 	if (klass->initialize) {
    357 		return klass->initialize(mix, config_params, frame_mgr,
    358 					input_buf_pool, surface_pool, va_display);
    359 	}
    360 
    361 	return MIX_RESULT_FAIL;
    362 
    363 }
    364 
    365 MIX_RESULT mix_videofmt_decode(MixVideoFormat *mix, MixBuffer * bufin[],
    366                 gint bufincnt, MixVideoDecodeParams * decode_params) {
    367 
    368 	MixVideoFormatClass *klass = MIX_VIDEOFORMAT_GET_CLASS(mix);
    369 	if (klass->decode) {
    370 		return klass->decode(mix, bufin, bufincnt, decode_params);
    371 	}
    372 
    373 	return MIX_RESULT_FAIL;
    374 }
    375 
    376 MIX_RESULT mix_videofmt_flush(MixVideoFormat *mix) {
    377 	MixVideoFormatClass *klass = MIX_VIDEOFORMAT_GET_CLASS(mix);
    378 	if (klass->flush) {
    379 		return klass->flush(mix);
    380 	}
    381 
    382 	return MIX_RESULT_FAIL;
    383 }
    384 
    385 MIX_RESULT mix_videofmt_eos(MixVideoFormat *mix) {
    386 	MixVideoFormatClass *klass = MIX_VIDEOFORMAT_GET_CLASS(mix);
    387 	if (klass->eos) {
    388 		return klass->eos(mix);
    389 	}
    390 
    391 	return MIX_RESULT_FAIL;
    392 }
    393 
    394 MIX_RESULT mix_videofmt_deinitialize(MixVideoFormat *mix) {
    395 	MixVideoFormatClass *klass = MIX_VIDEOFORMAT_GET_CLASS(mix);
    396 	if (klass->deinitialize) {
    397 		return klass->deinitialize(mix);
    398 	}
    399 
    400 	return MIX_RESULT_FAIL;
    401 }
    402