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