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 Intel’s 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))
mix_videoframe_init(MixVideoFrame * self)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
mix_videoframe_class_init(MixVideoFrameClass * klass)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 *
mix_videoframe_new(void)80 mix_videoframe_new(void) {
81 MixVideoFrame *ret = (MixVideoFrame *) g_type_create_instance(
82 MIX_TYPE_VIDEOFRAME);
83 return ret;
84 }
85
mix_videoframe_finalize(MixParams * obj)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 *
mix_videoframe_ref(MixVideoFrame * obj)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
mix_videoframe_unref(MixVideoFrame * obj)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 *
mix_videoframe_dup(const MixParams * obj)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 */
mix_videoframe_copy(MixParams * target,const MixParams * src)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 */
mix_videoframe_equal(MixParams * first,MixParams * second)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. */
mix_videoframe_set_frame_id(MixVideoFrame * obj,gulong frame_id)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
mix_videoframe_get_frame_id(MixVideoFrame * obj,gulong * frame_id)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
mix_videoframe_set_ci_frame_idx(MixVideoFrame * obj,guint ci_frame_idx)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
mix_videoframe_get_ci_frame_idx(MixVideoFrame * obj,guint * ci_frame_idx)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
mix_videoframe_set_timestamp(MixVideoFrame * obj,guint64 timestamp)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
mix_videoframe_get_timestamp(MixVideoFrame * obj,guint64 * timestamp)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
mix_videoframe_set_discontinuity(MixVideoFrame * obj,gboolean discontinuity)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
mix_videoframe_get_discontinuity(MixVideoFrame * obj,gboolean * discontinuity)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
mix_videoframe_set_frame_structure(MixVideoFrame * obj,guint32 frame_structure)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
mix_videoframe_get_frame_structure(MixVideoFrame * obj,guint32 * frame_structure)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
mix_videoframe_set_pool(MixVideoFrame * obj,MixSurfacePool * pool)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
mix_videoframe_set_frame_type(MixVideoFrame * obj,MixFrameType frame_type)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
mix_videoframe_get_frame_type(MixVideoFrame * obj,MixFrameType * frame_type)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
mix_videoframe_set_is_skipped(MixVideoFrame * obj,gboolean is_skipped)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
mix_videoframe_get_is_skipped(MixVideoFrame * obj,gboolean * is_skipped)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
mix_videoframe_set_real_frame(MixVideoFrame * obj,MixVideoFrame * real)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
mix_videoframe_get_real_frame(MixVideoFrame * obj,MixVideoFrame ** real)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