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 
      9 /**
     10  * SECTION:mixvideoframe
     11  * @short_description: VideoConfig parameters
     12  *
     13  * A data object which stores videoconfig specific parameters.
     14  */
     15 
     16 
     17 #include <va/va.h>
     18 #include <va/va_x11.h>
     19 #include "mixvideolog.h"
     20 #include "mixvideoframe.h"
     21 #include "mixvideoframe_private.h"
     22 
     23 #define SAFE_FREE(p) if(p) { g_free(p); p = NULL; }
     24 
     25 static GType _mix_videoframe_type = 0;
     26 static MixParamsClass *parent_class = NULL;
     27 
     28 #define _do_init { _mix_videoframe_type = g_define_type_id; }
     29 
     30 gboolean mix_videoframe_copy(MixParams * target, const MixParams * src);
     31 MixParams *mix_videoframe_dup(const MixParams * obj);
     32 gboolean mix_videoframe_equal(MixParams * first, MixParams * second);
     33 static void mix_videoframe_finalize(MixParams * obj);
     34 
     35 G_DEFINE_TYPE_WITH_CODE (MixVideoFrame, mix_videoframe, MIX_TYPE_PARAMS,
     36 		_do_init);
     37 
     38 #define VIDEOFRAME_PRIVATE(self) ((MixVideoFramePrivate *)((self)->reserved1))
     39 static void mix_videoframe_init(MixVideoFrame * self) {
     40 	/* initialize properties here */
     41 	self->frame_id = VA_INVALID_SURFACE;
     42 	self->timestamp = 0;
     43 	self->discontinuity = FALSE;
     44 	self->frame_structure = VA_FRAME_PICTURE;
     45 
     46 	MixVideoFramePrivate *priv = MIX_VIDEOFRAME_GET_PRIVATE(self);
     47 	self->reserved1 = priv;
     48 	self->reserved2 = NULL;
     49 	self->reserved3 = NULL;
     50 	self->reserved4 = NULL;
     51 
     52 	/* set pool pointer in private structure to NULL */
     53 	priv -> pool = NULL;
     54 
     55 	/* set stuff for skipped frames */
     56 	priv -> is_skipped = FALSE;
     57 	priv -> real_frame = NULL;
     58 
     59 	g_static_rec_mutex_init (&priv -> lock);
     60 
     61 }
     62 
     63 static void mix_videoframe_class_init(MixVideoFrameClass * klass) {
     64 	MixParamsClass *mixparams_class = MIX_PARAMS_CLASS(klass);
     65 
     66 	/* setup static parent class */
     67 	parent_class = (MixParamsClass *) g_type_class_peek_parent(klass);
     68 
     69 	mixparams_class->finalize = mix_videoframe_finalize;
     70 	mixparams_class->copy = (MixParamsCopyFunction) mix_videoframe_copy;
     71 	mixparams_class->dup = (MixParamsDupFunction) mix_videoframe_dup;
     72 	mixparams_class->equal = (MixParamsEqualFunction) mix_videoframe_equal;
     73 
     74 	/* Register and allocate the space the private structure for this object */
     75 	g_type_class_add_private(mixparams_class, sizeof(MixVideoFramePrivate));
     76 
     77 }
     78 
     79 MixVideoFrame *
     80 mix_videoframe_new(void) {
     81 	MixVideoFrame *ret = (MixVideoFrame *) g_type_create_instance(
     82 			MIX_TYPE_VIDEOFRAME);
     83 	return ret;
     84 }
     85 
     86 void mix_videoframe_finalize(MixParams * obj) {
     87 	/* clean up here. */
     88 	MixVideoFrame *self = MIX_VIDEOFRAME (obj);
     89 	MixVideoFramePrivate *priv = VIDEOFRAME_PRIVATE(self);
     90 
     91 	g_static_rec_mutex_free (&priv->lock);
     92 
     93 	/* Chain up parent */
     94 	if (parent_class->finalize) {
     95 		parent_class->finalize(obj);
     96 	}
     97 }
     98 
     99 MixVideoFrame *
    100 mix_videoframe_ref(MixVideoFrame * obj) {
    101 
    102 	MixVideoFrame *ret = NULL;
    103 	MixVideoFramePrivate *priv = VIDEOFRAME_PRIVATE(obj);
    104 	g_static_rec_mutex_lock(&priv->lock);
    105 	LOG_I("obj %x, new refcount is %d\n", (guint) obj,
    106 			MIX_PARAMS(obj)->refcount + 1);
    107 
    108 	ret = (MixVideoFrame *) mix_params_ref(MIX_PARAMS(obj));
    109 	g_static_rec_mutex_unlock (&priv->lock);
    110 	return ret;
    111 }
    112 
    113 void mix_videoframe_unref(MixVideoFrame * obj) {
    114 
    115 	if(obj == NULL) {
    116 		LOG_E("obj is NULL\n");
    117 		return;
    118 	}
    119 
    120 	MixVideoFramePrivate *priv = VIDEOFRAME_PRIVATE(obj);
    121 	g_static_rec_mutex_lock(&priv->lock);
    122 
    123 	LOG_I("obj %x, frame id %d, new refcount is %d\n", (guint) obj,
    124 			(guint) obj->frame_id, MIX_PARAMS(obj)->refcount - 1);
    125 
    126 	// Check if we have reduced to 1, in which case we add ourselves to free pool
    127 	// but only do this for real frames, not skipped frames
    128 	if (((MIX_PARAMS(obj)->refcount - 1) == 1) && (!(priv -> is_skipped))) {
    129 
    130 		LOG_I("Adding obj %x, frame id %d back to pool\n", (guint) obj,
    131 				(guint) obj->frame_id);
    132 
    133 		MixSurfacePool *pool = NULL;
    134 		pool = priv -> pool;
    135 		if(pool == NULL) {
    136 			LOG_E("pool is NULL\n");
    137 			g_static_rec_mutex_unlock (&priv->lock);
    138 			return;
    139 		}
    140 		mix_surfacepool_put(pool, obj);
    141 	}
    142 
    143 	//If this is a skipped frame that is being deleted, release the real frame
    144 	if (((MIX_PARAMS(obj)->refcount - 1) == 0) && (priv -> is_skipped)) {
    145 
    146 		LOG_I("skipped frame obj %x, releasing real frame %x \n",
    147 				(guint) obj, (guint) priv->real_frame);
    148 
    149 		mix_videoframe_unref(priv -> real_frame);
    150 	}
    151 
    152 	// Unref through base class
    153 	mix_params_unref(MIX_PARAMS(obj));
    154 	g_static_rec_mutex_unlock (&priv->lock);
    155 }
    156 
    157 /**
    158  * mix_videoframe_dup:
    159  * @obj: a #MixVideoFrame object
    160  * @returns: a newly allocated duplicate of the object.
    161  *
    162  * Copy duplicate of the object.
    163  */
    164 MixParams *
    165 mix_videoframe_dup(const MixParams * obj) {
    166 	MixParams *ret = NULL;
    167 
    168 	if (MIX_IS_VIDEOFRAME(obj)) {
    169 		MixVideoFrame *duplicate = mix_videoframe_new();
    170 		if (mix_videoframe_copy(MIX_PARAMS(duplicate), MIX_PARAMS(obj))) {
    171 			ret = MIX_PARAMS(duplicate);
    172 		} else {
    173 			mix_videoframe_unref(duplicate);
    174 		}
    175 	}
    176 	return ret;
    177 }
    178 
    179 /**
    180  * mix_videoframe_copy:
    181  * @target: copy to target
    182  * @src: copy from src
    183  * @returns: boolean indicates if copy is successful.
    184  *
    185  * Copy instance data from @src to @target.
    186  */
    187 gboolean mix_videoframe_copy(MixParams * target, const MixParams * src) {
    188 	MixVideoFrame *this_target, *this_src;
    189 
    190 	if (MIX_IS_VIDEOFRAME(target) && MIX_IS_VIDEOFRAME(src)) {
    191 		// Cast the base object to this child object
    192 		this_target = MIX_VIDEOFRAME(target);
    193 		this_src = MIX_VIDEOFRAME(src);
    194 
    195 		// Free the existing properties
    196 
    197 		// Duplicate string
    198 		this_target->frame_id = this_src->frame_id;
    199 		this_target->timestamp = this_src->timestamp;
    200 		this_target->discontinuity = this_src->discontinuity;
    201 		this_target->frame_structure = this_src->frame_structure;
    202 
    203 		// Now chainup base class
    204 		if (parent_class->copy) {
    205 			return parent_class->copy(MIX_PARAMS_CAST(target), MIX_PARAMS_CAST(
    206 					src));
    207 		} else {
    208 			return TRUE;
    209 		}
    210 	}
    211 	return FALSE;
    212 }
    213 
    214 /**
    215  * mix_videoframe_equal:
    216  * @first: first object to compare
    217  * @second: seond object to compare
    218  * @returns: boolean indicates if instance are equal.
    219  *
    220  * Copy instance data from @src to @target.
    221  */
    222 gboolean mix_videoframe_equal(MixParams * first, MixParams * second) {
    223 	gboolean ret = FALSE;
    224 	MixVideoFrame *this_first, *this_second;
    225 
    226 	if (MIX_IS_VIDEOFRAME(first) && MIX_IS_VIDEOFRAME(second)) {
    227 		// Deep compare
    228 		// Cast the base object to this child object
    229 
    230 		this_first = MIX_VIDEOFRAME(first);
    231 		this_second = MIX_VIDEOFRAME(second);
    232 
    233 		/* TODO: add comparison for other properties */
    234 		if (this_first->frame_id == this_second->frame_id
    235 				&& this_first->timestamp == this_second->timestamp
    236 				&& this_first->discontinuity == this_second->discontinuity
    237 				&& this_first->frame_structure == this_second->frame_structure) {
    238 			// members within this scope equal. chaining up.
    239 			MixParamsClass *klass = MIX_PARAMS_CLASS(parent_class);
    240 			if (klass->equal)
    241 				ret = klass->equal(first, second);
    242 			else
    243 				ret = TRUE;
    244 		}
    245 	}
    246 
    247 	return ret;
    248 }
    249 
    250 #define MIX_VIDEOFRAME_SETTER_CHECK_INPUT(obj) \
    251 	if(!obj) return MIX_RESULT_NULL_PTR; \
    252 	if(!MIX_IS_VIDEOFRAME(obj)) return MIX_RESULT_FAIL; \
    253 
    254 #define MIX_VIDEOFRAME_GETTER_CHECK_INPUT(obj, prop) \
    255 	if(!obj || !prop) return MIX_RESULT_NULL_PTR; \
    256 	if(!MIX_IS_VIDEOFRAME(obj)) return MIX_RESULT_FAIL; \
    257 
    258 
    259 /* TODO: Add getters and setters for other properties. The following is just an exmaple, not implemented yet. */
    260 MIX_RESULT mix_videoframe_set_frame_id(MixVideoFrame * obj, gulong frame_id) {
    261 	MIX_VIDEOFRAME_SETTER_CHECK_INPUT (obj);
    262 	obj->frame_id = frame_id;
    263 
    264 	return MIX_RESULT_SUCCESS;
    265 }
    266 
    267 MIX_RESULT mix_videoframe_get_frame_id(MixVideoFrame * obj, gulong * frame_id) {
    268 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT (obj, frame_id);
    269 	*frame_id = obj->frame_id;
    270 	return MIX_RESULT_SUCCESS;
    271 }
    272 
    273 MIX_RESULT mix_videoframe_set_ci_frame_idx (MixVideoFrame * obj, guint ci_frame_idx) {
    274 	MIX_VIDEOFRAME_SETTER_CHECK_INPUT (obj);
    275 	obj->ci_frame_idx = ci_frame_idx;
    276 
    277 	return MIX_RESULT_SUCCESS;
    278 }
    279 
    280 MIX_RESULT mix_videoframe_get_ci_frame_idx (MixVideoFrame * obj, guint * ci_frame_idx) {
    281 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT (obj, ci_frame_idx);
    282 	*ci_frame_idx = obj->ci_frame_idx;
    283 	return MIX_RESULT_SUCCESS;
    284 }
    285 
    286 MIX_RESULT mix_videoframe_set_timestamp(MixVideoFrame * obj, guint64 timestamp) {
    287 	MIX_VIDEOFRAME_SETTER_CHECK_INPUT (obj);
    288 
    289 	obj->timestamp = timestamp;
    290 
    291 	return MIX_RESULT_SUCCESS;
    292 }
    293 
    294 MIX_RESULT mix_videoframe_get_timestamp(MixVideoFrame * obj,
    295 		guint64 * timestamp) {
    296 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT (obj, timestamp);
    297 	*timestamp = obj->timestamp;
    298 	return MIX_RESULT_SUCCESS;
    299 }
    300 
    301 MIX_RESULT mix_videoframe_set_discontinuity(MixVideoFrame * obj,
    302 		gboolean discontinuity) {
    303 	MIX_VIDEOFRAME_SETTER_CHECK_INPUT (obj);
    304 	obj->discontinuity = discontinuity;
    305 	return MIX_RESULT_SUCCESS;
    306 }
    307 
    308 MIX_RESULT mix_videoframe_get_discontinuity(MixVideoFrame * obj,
    309 		gboolean * discontinuity) {
    310 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT (obj, discontinuity);
    311 	*discontinuity = obj->discontinuity;
    312 	return MIX_RESULT_SUCCESS;
    313 }
    314 
    315 MIX_RESULT mix_videoframe_set_frame_structure(MixVideoFrame * obj,
    316 		guint32 frame_structure) {
    317 	MIX_VIDEOFRAME_SETTER_CHECK_INPUT (obj);
    318 	obj->frame_structure = frame_structure;
    319 	return MIX_RESULT_SUCCESS;
    320 }
    321 
    322 MIX_RESULT mix_videoframe_get_frame_structure(MixVideoFrame * obj,
    323 		guint32* frame_structure) {
    324 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT (obj, frame_structure);
    325 	*frame_structure = obj->frame_structure;
    326 	return MIX_RESULT_SUCCESS;
    327 }
    328 
    329 MIX_RESULT mix_videoframe_set_pool(MixVideoFrame * obj, MixSurfacePool * pool) {
    330 
    331 	/* set pool pointer in private structure */
    332 	VIDEOFRAME_PRIVATE(obj) -> pool = pool;
    333 
    334 	return MIX_RESULT_SUCCESS;
    335 }
    336 
    337 MIX_RESULT mix_videoframe_set_frame_type(MixVideoFrame *obj,
    338 		MixFrameType frame_type) {
    339 
    340 	VIDEOFRAME_PRIVATE(obj) -> frame_type = frame_type;
    341 
    342 	return MIX_RESULT_SUCCESS;
    343 }
    344 
    345 MIX_RESULT mix_videoframe_get_frame_type(MixVideoFrame *obj,
    346 		MixFrameType *frame_type) {
    347 
    348 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT(obj, frame_type);
    349 
    350 	*frame_type = VIDEOFRAME_PRIVATE(obj) -> frame_type;
    351 
    352 	return MIX_RESULT_SUCCESS;
    353 
    354 }
    355 
    356 MIX_RESULT mix_videoframe_set_is_skipped(MixVideoFrame *obj,
    357 		gboolean is_skipped) {
    358 
    359 	VIDEOFRAME_PRIVATE(obj) -> is_skipped = is_skipped;
    360 
    361 	return MIX_RESULT_SUCCESS;
    362 }
    363 
    364 MIX_RESULT mix_videoframe_get_is_skipped(MixVideoFrame *obj,
    365 		gboolean *is_skipped) {
    366 
    367 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT(obj, is_skipped);
    368 
    369 	*is_skipped = VIDEOFRAME_PRIVATE(obj) -> is_skipped;
    370 
    371 	return MIX_RESULT_SUCCESS;
    372 }
    373 
    374 MIX_RESULT mix_videoframe_set_real_frame(MixVideoFrame *obj,
    375 		MixVideoFrame *real) {
    376 
    377 	VIDEOFRAME_PRIVATE(obj) -> real_frame = real;
    378 
    379 	return MIX_RESULT_SUCCESS;
    380 }
    381 
    382 MIX_RESULT mix_videoframe_get_real_frame(MixVideoFrame *obj,
    383 		MixVideoFrame **real) {
    384 
    385 	MIX_VIDEOFRAME_GETTER_CHECK_INPUT(obj, real);
    386 
    387 	*real = VIDEOFRAME_PRIVATE(obj) -> real_frame;
    388 
    389 	return MIX_RESULT_SUCCESS;
    390 }
    391 
    392