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 #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
mix_videoformat_init(MixVideoFormat * self)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
mix_videoformat_class_init(MixVideoFormatClass * klass)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 *
mix_videoformat_new(void)81 mix_videoformat_new(void) {
82 MixVideoFormat *ret = g_object_new(MIX_TYPE_VIDEOFORMAT, NULL);
83
84 return ret;
85 }
86
mix_videoformat_finalize(GObject * obj)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 *
mix_videoformat_ref(MixVideoFormat * mix)168 mix_videoformat_ref(MixVideoFormat * mix) {
169 return (MixVideoFormat *) g_object_ref(G_OBJECT(mix));
170 }
171
172 /* Default vmethods implementation */
mix_videofmt_getcaps_default(MixVideoFormat * mix,GString * msg)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
mix_videofmt_initialize_default(MixVideoFormat * mix,MixVideoConfigParamsDec * config_params,MixFrameManager * frame_mgr,MixBufferPool * input_buf_pool,MixSurfacePool ** surface_pool,VADisplay va_display)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
mix_videofmt_decode_default(MixVideoFormat * mix,MixBuffer * bufin[],gint bufincnt,MixVideoDecodeParams * decode_params)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
mix_videofmt_flush_default(MixVideoFormat * mix)322 static MIX_RESULT mix_videofmt_flush_default(MixVideoFormat *mix) {
323 return MIX_RESULT_SUCCESS;
324 }
325
mix_videofmt_eos_default(MixVideoFormat * mix)326 static MIX_RESULT mix_videofmt_eos_default(MixVideoFormat *mix) {
327 return MIX_RESULT_SUCCESS;
328 }
329
mix_videofmt_deinitialize_default(MixVideoFormat * mix)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
mix_videofmt_getcaps(MixVideoFormat * mix,GString * msg)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
mix_videofmt_initialize(MixVideoFormat * mix,MixVideoConfigParamsDec * config_params,MixFrameManager * frame_mgr,MixBufferPool * input_buf_pool,MixSurfacePool ** surface_pool,VADisplay va_display)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
mix_videofmt_decode(MixVideoFormat * mix,MixBuffer * bufin[],gint bufincnt,MixVideoDecodeParams * decode_params)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
mix_videofmt_flush(MixVideoFormat * mix)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
mix_videofmt_eos(MixVideoFormat * mix)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
mix_videofmt_deinitialize(MixVideoFormat * mix)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