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 #include <va/va.h>             /* libVA */
10 #include <X11/Xlib.h>
11 #include <va/va_x11.h>
12 
13 #include "mixvideolog.h"
14 
15 #include "mixdisplayx11.h"
16 #include "mixvideoframe.h"
17 
18 #include "mixframemanager.h"
19 #include "mixvideorenderparams.h"
20 #include "mixvideorenderparams_internal.h"
21 
22 #include "mixvideoformat.h"
23 #include "mixvideoformat_vc1.h"
24 #include "mixvideoformat_h264.h"
25 #include "mixvideoformat_mp42.h"
26 
27 #include "mixvideoconfigparamsdec_vc1.h"
28 #include "mixvideoconfigparamsdec_h264.h"
29 #include "mixvideoconfigparamsdec_mp42.h"
30 
31 #include "mixvideoformatenc.h"
32 #include "mixvideoformatenc_h264.h"
33 #include "mixvideoformatenc_mpeg4.h"
34 #include "mixvideoformatenc_preview.h"
35 
36 #include "mixvideoconfigparamsenc_h264.h"
37 #include "mixvideoconfigparamsenc_mpeg4.h"
38 #include "mixvideoconfigparamsenc_preview.h"
39 
40 
41 #include "mixvideo.h"
42 #include "mixvideo_private.h"
43 
44 #define USE_OPAQUE_POINTER
45 
46 #ifdef USE_OPAQUE_POINTER
47 #define MIX_VIDEO_PRIVATE(mix) (MixVideoPrivate *)(mix->context)
48 #else
49 #define MIX_VIDEO_PRIVATE(mix) MIX_VIDEO_GET_PRIVATE(mix)
50 #endif
51 
52 #define CHECK_INIT(mix, priv) \
53 	if (!mix) { \
54 		return MIX_RESULT_NULL_PTR; \
55 	} \
56 	if (!MIX_IS_VIDEO(mix)) { \
57 		LOG_E( "Not MixVideo\n"); \
58 		return MIX_RESULT_INVALID_PARAM; \
59 	} \
60 	priv = MIX_VIDEO_PRIVATE(mix); \
61 	if (!priv->initialized) { \
62 		LOG_E( "Not initialized\n"); \
63 		return MIX_RESULT_NOT_INIT; \
64 	}
65 
66 #define CHECK_INIT_CONFIG(mix, priv) \
67 	CHECK_INIT(mix, priv); \
68 	if (!priv->configured) { \
69 		LOG_E( "Not configured\n"); \
70 		return MIX_RESULT_NOT_CONFIGURED; \
71 	}
72 
73 /*
74  * default implementation of virtual methods
75  */
76 
77 MIX_RESULT mix_video_get_version_default(MixVideo * mix, guint * major,
78 		guint * minor);
79 
80 MIX_RESULT mix_video_initialize_default(MixVideo * mix, MixCodecMode mode,
81 		MixVideoInitParams * init_params, MixDrmParams * drm_init_params);
82 
83 MIX_RESULT mix_video_deinitialize_default(MixVideo * mix);
84 
85 MIX_RESULT mix_video_configure_default(MixVideo * mix,
86 		MixVideoConfigParams * config_params, MixDrmParams * drm_config_params);
87 
88 MIX_RESULT mix_video_get_config_default(MixVideo * mix,
89 		MixVideoConfigParams ** config_params);
90 
91 MIX_RESULT mix_video_decode_default(MixVideo * mix, MixBuffer * bufin[],
92 		gint bufincnt, MixVideoDecodeParams * decode_params);
93 
94 MIX_RESULT mix_video_get_frame_default(MixVideo * mix, MixVideoFrame ** frame);
95 
96 MIX_RESULT mix_video_release_frame_default(MixVideo * mix,
97 		MixVideoFrame * frame);
98 
99 MIX_RESULT mix_video_render_default(MixVideo * mix,
100 		MixVideoRenderParams * render_params, MixVideoFrame *frame);
101 
102 MIX_RESULT mix_video_encode_default(MixVideo * mix, MixBuffer * bufin[],
103 		gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
104 		MixVideoEncodeParams * encode_params);
105 
106 MIX_RESULT mix_video_flush_default(MixVideo * mix);
107 
108 MIX_RESULT mix_video_eos_default(MixVideo * mix);
109 
110 MIX_RESULT mix_video_get_state_default(MixVideo * mix, MixState * state);
111 
112 MIX_RESULT mix_video_get_mixbuffer_default(MixVideo * mix, MixBuffer ** buf);
113 
114 MIX_RESULT mix_video_release_mixbuffer_default(MixVideo * mix, MixBuffer * buf);
115 
116 MIX_RESULT mix_video_get_max_coded_buffer_size_default (MixVideo * mix, guint *max_size);
117 
118 
119 static void mix_video_finalize(GObject * obj);
120 MIX_RESULT mix_video_configure_decode(MixVideo * mix,
121 		MixVideoConfigParamsDec * config_params_dec,
122 		MixDrmParams * drm_config_params);
123 
124 MIX_RESULT mix_video_configure_encode(MixVideo * mix,
125 		MixVideoConfigParamsEnc * config_params_enc,
126 		MixDrmParams * drm_config_params);
127 
128 G_DEFINE_TYPE( MixVideo, mix_video, G_TYPE_OBJECT);
129 
mix_video_init(MixVideo * self)130 static void mix_video_init(MixVideo * self) {
131 
132 	MixVideoPrivate *priv = MIX_VIDEO_GET_PRIVATE(self);
133 
134 #ifdef USE_OPAQUE_POINTER
135 	self->context = priv;
136 #else
137 	self->context = NULL;
138 #endif
139 
140 	/* private structure initialization */
141 
142 	mix_video_private_initialize(priv);
143 }
144 
mix_video_class_init(MixVideoClass * klass)145 static void mix_video_class_init(MixVideoClass * klass) {
146 	GObjectClass *gobject_class = (GObjectClass *) klass;
147 
148 	gobject_class->finalize = mix_video_finalize;
149 
150 	/* Register and allocate the space the private structure for this object */
151 	g_type_class_add_private(gobject_class, sizeof(MixVideoPrivate));
152 
153 	klass->get_version_func = mix_video_get_version_default;
154 	klass->initialize_func = mix_video_initialize_default;
155 	klass->deinitialize_func = mix_video_deinitialize_default;
156 	klass->configure_func = mix_video_configure_default;
157 	klass->get_config_func = mix_video_get_config_default;
158 	klass->decode_func = mix_video_decode_default;
159 	klass->get_frame_func = mix_video_get_frame_default;
160 	klass->release_frame_func = mix_video_release_frame_default;
161 	klass->render_func = mix_video_render_default;
162 	klass->encode_func = mix_video_encode_default;
163 	klass->flush_func = mix_video_flush_default;
164 	klass->eos_func = mix_video_eos_default;
165 	klass->get_state_func = mix_video_get_state_default;
166 	klass->get_mix_buffer_func = mix_video_get_mixbuffer_default;
167 	klass->release_mix_buffer_func = mix_video_release_mixbuffer_default;
168 	klass->get_max_coded_buffer_size_func = mix_video_get_max_coded_buffer_size_default;
169 }
170 
mix_video_new(void)171 MixVideo *mix_video_new(void) {
172 
173 	MixVideo *ret = g_object_new(MIX_TYPE_VIDEO, NULL);
174 
175 	return ret;
176 }
177 
mix_video_finalize(GObject * obj)178 void mix_video_finalize(GObject * obj) {
179 
180 	/* clean up here. */
181 
182 	MixVideo *mix = MIX_VIDEO(obj);
183 	mix_video_deinitialize(mix);
184 }
185 
186 MixVideo *
mix_video_ref(MixVideo * mix)187 mix_video_ref(MixVideo * mix) {
188 	return (MixVideo *) g_object_ref(G_OBJECT(mix));
189 }
190 
191 /* private methods */
192 
193 #define MIXUNREF(obj, unref) if(obj) { unref(obj); obj = NULL; }
194 
mix_video_private_initialize(MixVideoPrivate * priv)195 void mix_video_private_initialize(MixVideoPrivate* priv) {
196 	priv->objlock = NULL;
197 	priv->initialized = FALSE;
198 	priv->configured = FALSE;
199 
200 	/* libVA */
201 	priv->va_display = NULL;
202 	priv->va_major_version = -1;
203 	priv->va_major_version = -1;
204 
205 	/* mix objects */
206 	priv->frame_manager = NULL;
207 	priv->video_format = NULL;
208 	priv->video_format_enc = NULL; //for encoding
209 	priv->surface_pool = NULL;
210 	priv->buffer_pool = NULL;
211 
212 	priv->codec_mode = MIX_CODEC_MODE_DECODE;
213 	priv->init_params = NULL;
214 	priv->drm_params = NULL;
215 	priv->config_params = NULL;
216 }
217 
mix_video_private_cleanup(MixVideoPrivate * priv)218 void mix_video_private_cleanup(MixVideoPrivate* priv) {
219 
220 	VAStatus va_status;
221 
222 	if (!priv) {
223 		return;
224 	}
225 
226 	if (priv->video_format_enc) {
227 		mix_videofmtenc_deinitialize(priv->video_format_enc);
228 	}
229 
230 	MIXUNREF(priv->frame_manager, mix_framemanager_unref)
231 	MIXUNREF(priv->video_format, mix_videoformat_unref)
232 	MIXUNREF(priv->video_format_enc, mix_videoformatenc_unref)
233 	//for encoding
234 	MIXUNREF(priv->buffer_pool, mix_bufferpool_unref)
235 	MIXUNREF(priv->surface_pool, mix_surfacepool_unref)
236 /*	MIXUNREF(priv->init_params, mix_videoinitparams_unref) */
237 	MIXUNREF(priv->drm_params, mix_drmparams_unref)
238 	MIXUNREF(priv->config_params, mix_videoconfigparams_unref)
239 
240 	/* terminate libVA */
241 	if (priv->va_display) {
242 		va_status = vaTerminate(priv->va_display);
243 		LOG_V( "vaTerminate\n");
244 		if (va_status != VA_STATUS_SUCCESS) {
245 			LOG_W( "Failed vaTerminate\n");
246 		} else {
247 			priv->va_display = NULL;
248 		}
249 	}
250 
251 	MIXUNREF(priv->init_params, mix_videoinitparams_unref)
252 
253 	priv->va_major_version = -1;
254 	priv->va_major_version = -1;
255 
256 	if (priv->objlock) {
257 		g_mutex_free(priv->objlock);
258 		priv->objlock = NULL;
259 	}
260 
261 	priv->codec_mode = MIX_CODEC_MODE_DECODE;
262 	priv->initialized = FALSE;
263 	priv->configured = FALSE;
264 }
265 
266 /* The following methods are defined in MI-X API */
267 
mix_video_get_version_default(MixVideo * mix,guint * major,guint * minor)268 MIX_RESULT mix_video_get_version_default(MixVideo * mix, guint * major,
269 		guint * minor) {
270 	if (!mix || !major || !minor) {
271 		return MIX_RESULT_NULL_PTR;
272 	}
273 
274 	if (!MIX_IS_VIDEO(mix)) {
275 		return MIX_RESULT_INVALID_PARAM;
276 	}
277 
278 	*major = MIXVIDEO_CURRENT - MIXVIDEO_AGE;
279 	*minor = MIXVIDEO_AGE;
280 
281 	return MIX_RESULT_SUCCESS;
282 }
283 
mix_video_initialize_default(MixVideo * mix,MixCodecMode mode,MixVideoInitParams * init_params,MixDrmParams * drm_init_params)284 MIX_RESULT mix_video_initialize_default(MixVideo * mix, MixCodecMode mode,
285 		MixVideoInitParams * init_params, MixDrmParams * drm_init_params) {
286 
287 	MIX_RESULT ret = MIX_RESULT_FAIL;
288 	MixVideoPrivate *priv = NULL;
289 	MixDisplay *mix_display = NULL;
290 
291 	LOG_V( "Begin\n");
292 
293 	if (!mix || !init_params) {
294 		LOG_E( "!mix || !init_params\n");
295 		return MIX_RESULT_NULL_PTR;
296 	}
297 
298 	if (mode >= MIX_CODEC_MODE_LAST) {
299 		LOG_E("mode >= MIX_CODEC_MODE_LAST\n");
300 		return MIX_RESULT_INVALID_PARAM;
301 	}
302 
303 #if 0  //we have encoding support
304 	/* TODO: We need to support encoding in the future */
305 	if (mode == MIX_CODEC_MODE_ENCODE) {
306 		LOG_E("mode == MIX_CODEC_MODE_ENCODE\n");
307 		return MIX_RESULT_NOTIMPL;
308 	}
309 #endif
310 
311 	if (!MIX_IS_VIDEO(mix)) {
312 		LOG_E( "!MIX_IS_VIDEO(mix)\n");
313 		return MIX_RESULT_INVALID_PARAM;
314 	}
315 
316 	if (!MIX_IS_VIDEOINITPARAMS(init_params)) {
317 		LOG_E("!MIX_IS_VIDEOINITPARAMS(init_params\n");
318 		return MIX_RESULT_INVALID_PARAM;
319 	}
320 
321 	priv = MIX_VIDEO_PRIVATE(mix);
322 
323 	if (priv->initialized) {
324 		LOG_W( "priv->initialized\n");
325 		return MIX_RESULT_ALREADY_INIT;
326 	}
327 
328 	/*
329 	 * Init thread before any threads/sync object are used.
330 	 * TODO: If thread is not supported, what we do?
331 	 */
332 
333 	if (!g_thread_supported()) {
334 		LOG_W("!g_thread_supported()\n");
335 		g_thread_init(NULL);
336 	}
337 
338 	/* create object lock */
339 	priv->objlock = g_mutex_new();
340 	if (!priv->objlock) {
341 		ret = MIX_RESULT_NO_MEMORY;
342 		LOG_E( "!priv->objlock\n");
343 		goto cleanup;
344 	}
345 
346 	/* clone mode */
347 	priv->codec_mode = mode;
348 
349 	/* ref init_params */
350 	priv->init_params = (MixVideoInitParams *) mix_params_ref(MIX_PARAMS(
351 			init_params));
352 	if (!priv->init_params) {
353 		ret = MIX_RESULT_NO_MEMORY;
354 		LOG_E( "!priv->init_params\n");
355 		goto cleanup;
356 	}
357 
358 	/* NOTE: we don't do anything with drm_init_params */
359 
360 	/* libVA initialization */
361 
362 	{
363 		VAStatus va_status;
364 		Display *display = NULL;
365 		ret = mix_videoinitparams_get_display(priv->init_params, &mix_display);
366 		if (ret != MIX_RESULT_SUCCESS) {
367 			LOG_E("Failed to get display 1\n");
368 			goto cleanup;
369 		}
370 
371 		if (MIX_IS_DISPLAYX11(mix_display)) {
372 			MixDisplayX11 *mix_displayx11 = MIX_DISPLAYX11(mix_display);
373 			ret = mix_displayx11_get_display(mix_displayx11, &display);
374 			if (ret != MIX_RESULT_SUCCESS) {
375 				LOG_E("Failed to get display 2\n");
376 				goto cleanup;
377 			}
378 		} else {
379 
380 			/* TODO: add support to other MixDisplay type. For now, just return error!*/
381 			LOG_E("It is not display x11\n");
382 			ret = MIX_RESULT_FAIL;
383 			goto cleanup;
384 		}
385 
386 		/* Now, we can initialize libVA */
387 		priv->va_display = vaGetDisplay(display);
388 
389 		/* Oops! Fail to get VADisplay */
390 		if (!priv->va_display) {
391 			ret = MIX_RESULT_FAIL;
392 			LOG_E("Fail to get VADisplay\n");
393 			goto cleanup;
394 		}
395 
396 		/* Initialize libVA */
397 		va_status = vaInitialize(priv->va_display, &priv->va_major_version,
398 				&priv->va_minor_version);
399 
400 		/* Oops! Fail to initialize libVA */
401 		if (va_status != VA_STATUS_SUCCESS) {
402 			ret = MIX_RESULT_FAIL;
403 			LOG_E("Fail to initialize libVA\n");
404 			goto cleanup;
405 		}
406 
407 		/* TODO: check the version numbers of libVA */
408 
409 		priv->initialized = TRUE;
410 		ret = MIX_RESULT_SUCCESS;
411 	}
412 
413 	cleanup:
414 
415 	if (ret != MIX_RESULT_SUCCESS) {
416 		mix_video_private_cleanup(priv);
417 	}
418 
419 	MIXUNREF(mix_display, mix_display_unref);
420 
421 	LOG_V( "End\n");
422 
423 	return ret;
424 }
425 
mix_video_deinitialize_default(MixVideo * mix)426 MIX_RESULT mix_video_deinitialize_default(MixVideo * mix) {
427 
428 	MixVideoPrivate *priv = NULL;
429 
430 	LOG_V( "Begin\n");
431 
432 	CHECK_INIT(mix, priv);
433 
434 	mix_video_private_cleanup(priv);
435 
436 	LOG_V( "End\n");
437 	return MIX_RESULT_SUCCESS;
438 }
439 
mix_video_configure_decode(MixVideo * mix,MixVideoConfigParamsDec * config_params_dec,MixDrmParams * drm_config_params)440 MIX_RESULT mix_video_configure_decode(MixVideo * mix,
441 		MixVideoConfigParamsDec * config_params_dec, MixDrmParams * drm_config_params) {
442 
443 	MIX_RESULT ret = MIX_RESULT_FAIL;
444 	MixVideoPrivate *priv = NULL;
445 	MixVideoConfigParamsDec *priv_config_params_dec = NULL;
446 
447 	gchar *mime_type = NULL;
448 	guint fps_n, fps_d;
449 	guint bufpoolsize = 0;
450 
451 	MixFrameOrderMode frame_order_mode = MIX_FRAMEORDER_MODE_DISPLAYORDER;
452 
453 	LOG_V( "Begin\n");
454 
455 	CHECK_INIT(mix, priv);
456 
457 	if (!config_params_dec) {
458 		LOG_E( "!config_params_dec\n");
459 		return MIX_RESULT_NULL_PTR;
460 	}
461 
462 	if (!MIX_IS_VIDEOCONFIGPARAMSDEC(config_params_dec)) {
463 		LOG_E("Not a MixVideoConfigParamsDec\n");
464 		return MIX_RESULT_INVALID_PARAM;
465 	}
466 
467 	/* ---------------------- begin lock --------------------- */
468 	g_mutex_lock(priv->objlock);
469 
470 	/*
471 	 * MixVideo has already been configured, it should be
472 	 * re-configured.
473 	 *
474 	 * TODO: Allow MixVideo re-configuration
475 	 */
476 	if (priv->configured) {
477 		ret = MIX_RESULT_SUCCESS;
478 		LOG_W( "Already configured\n");
479 		goto cleanup;
480 	}
481 
482 	/* Make a copy of config_params */
483 	priv->config_params = (MixVideoConfigParams *) mix_params_dup(MIX_PARAMS(
484 			config_params_dec));
485 	if (!priv->config_params) {
486 		ret = MIX_RESULT_NO_MEMORY;
487 		LOG_E("Fail to duplicate config_params\n");
488 		goto cleanup;
489 	}
490 
491 	priv_config_params_dec = (MixVideoConfigParamsDec *)priv->config_params;
492 
493 	/* Get fps, frame order mode and mime type from config_params */
494 	ret = mix_videoconfigparamsdec_get_mime_type(priv_config_params_dec, &mime_type);
495 	if (ret != MIX_RESULT_SUCCESS) {
496 		LOG_E("Failed to get mime type\n");
497 		goto cleanup;
498 	}
499 
500 	LOG_I( "mime : %s\n", mime_type);
501 
502 #ifdef MIX_LOG_ENABLE
503 	if (g_strcmp0(mime_type, "video/x-wmv") == 0) {
504 
505 		LOG_I( "mime : video/x-wmv\n");
506 		if (MIX_IS_VIDEOCONFIGPARAMSDEC_VC1(priv_config_params_dec)) {
507 			LOG_I( "VC1 config_param\n");
508 		} else {
509 			LOG_E("Not VC1 config_param\n");
510 		}
511 	}
512 #endif
513 
514 	ret = mix_videoconfigparamsdec_get_frame_order_mode(priv_config_params_dec,
515 			&frame_order_mode);
516 	if (ret != MIX_RESULT_SUCCESS) {
517 		LOG_E("Failed to frame order mode\n");
518 		goto cleanup;
519 	}
520 
521 	ret = mix_videoconfigparamsdec_get_frame_rate(priv_config_params_dec, &fps_n,
522 			&fps_d);
523 	if (ret != MIX_RESULT_SUCCESS) {
524 		LOG_E("Failed to get frame rate\n");
525 		goto cleanup;
526 	}
527 
528 	if (!fps_n) {
529 		ret = MIX_RESULT_FAIL;
530 		LOG_E( "fps_n is 0\n");
531 		goto cleanup;
532 	}
533 
534 	ret = mix_videoconfigparamsdec_get_buffer_pool_size(priv_config_params_dec,
535 			&bufpoolsize);
536 	if (ret != MIX_RESULT_SUCCESS) {
537 		LOG_E("Failed to get buffer pool size\n");
538 		goto cleanup;
539 	}
540 
541 	/* create frame manager */
542 	priv->frame_manager = mix_framemanager_new();
543 	if (!priv->frame_manager) {
544 		ret = MIX_RESULT_NO_MEMORY;
545 		LOG_E("Failed to create frame manager\n");
546 		goto cleanup;
547 	}
548 
549 	/* initialize frame manager */
550 
551 	if (g_strcmp0(mime_type, "video/x-wmv") == 0 || g_strcmp0(mime_type,
552 			"video/mpeg") == 0 || g_strcmp0(mime_type, "video/x-divx") == 0) {
553 		ret = mix_framemanager_initialize(priv->frame_manager,
554 				frame_order_mode, fps_n, fps_d, FALSE);
555 	} else {
556 		ret = mix_framemanager_initialize(priv->frame_manager,
557 				frame_order_mode, fps_n, fps_d, TRUE);
558 	}
559 
560 	if (ret != MIX_RESULT_SUCCESS) {
561 		LOG_E("Failed to initialize frame manager\n");
562 		goto cleanup;
563 	}
564 
565 	/* create buffer pool */
566 	priv->buffer_pool = mix_bufferpool_new();
567 	if (!priv->buffer_pool) {
568 		ret = MIX_RESULT_NO_MEMORY;
569 		LOG_E("Failed to create buffer pool\n");
570 		goto cleanup;
571 	}
572 
573 	ret = mix_bufferpool_initialize(priv->buffer_pool, bufpoolsize);
574 	if (ret != MIX_RESULT_SUCCESS) {
575 		LOG_E("Failed to initialize buffer pool\n");
576 		goto cleanup;
577 	}
578 
579 	/* Finally, we can create MixVideoFormat */
580 	/* What type of MixVideoFormat we need create? */
581 
582 	if (g_strcmp0(mime_type, "video/x-wmv") == 0
583 			&& MIX_IS_VIDEOCONFIGPARAMSDEC_VC1(priv_config_params_dec)) {
584 
585 		MixVideoFormat_VC1 *video_format = mix_videoformat_vc1_new();
586 		if (!video_format) {
587 			ret = MIX_RESULT_NO_MEMORY;
588 			LOG_E("Failed to create VC-1 video format\n");
589 			goto cleanup;
590 		}
591 
592 		/* TODO: work specific to VC-1 */
593 
594 		priv->video_format = MIX_VIDEOFORMAT(video_format);
595 
596 	} else if (g_strcmp0(mime_type, "video/x-h264") == 0
597 			&& MIX_IS_VIDEOCONFIGPARAMSDEC_H264(priv_config_params_dec)) {
598 
599 		MixVideoFormat_H264 *video_format = mix_videoformat_h264_new();
600 		if (!video_format) {
601 			ret = MIX_RESULT_NO_MEMORY;
602 			LOG_E("Failed to create H.264 video format\n");
603 			goto cleanup;
604 		}
605 
606 		/* TODO: work specific to H.264 */
607 
608 		priv->video_format = MIX_VIDEOFORMAT(video_format);
609 
610 	} else if (g_strcmp0(mime_type, "video/mpeg") == 0 || g_strcmp0(mime_type,
611 			"video/x-divx") == 0) {
612 
613 		guint version = 0;
614 
615 		/* Is this mpeg4:2 ? */
616 		if (g_strcmp0(mime_type, "video/mpeg") == 0) {
617 
618 			/*
619 			 *  we don't support mpeg other than mpeg verion 4
620 			 */
621 			if (!MIX_IS_VIDEOCONFIGPARAMSDEC_MP42(priv_config_params_dec)) {
622 				ret = MIX_RESULT_NOT_SUPPORTED;
623 				goto cleanup;
624 			}
625 
626 			/* what is the mpeg version ? */
627 			ret = mix_videoconfigparamsdec_mp42_get_mpegversion(
628 					MIX_VIDEOCONFIGPARAMSDEC_MP42(priv_config_params_dec), &version);
629 			if (ret != MIX_RESULT_SUCCESS) {
630 				LOG_E("Failed to get mpeg version\n");
631 				goto cleanup;
632 			}
633 
634 			/* if it is not MPEG4 */
635 			if (version != 4) {
636 				ret = MIX_RESULT_NOT_SUPPORTED;
637 				goto cleanup;
638 			}
639 
640 		} else {
641 
642 			/* config_param shall be MixVideoConfigParamsDecMP42 */
643 			if (!MIX_IS_VIDEOCONFIGPARAMSDEC_MP42(priv_config_params_dec)) {
644 				ret = MIX_RESULT_NOT_SUPPORTED;
645 				goto cleanup;
646 			}
647 
648 			/* what is the divx version ? */
649 			ret = mix_videoconfigparamsdec_mp42_get_divxversion(
650 					MIX_VIDEOCONFIGPARAMSDEC_MP42(priv_config_params_dec), &version);
651 			if (ret != MIX_RESULT_SUCCESS) {
652 				LOG_E("Failed to get divx version\n");
653 				goto cleanup;
654 			}
655 
656 			/* if it is not divx 4 or 5 */
657 			if (version != 4 && version != 5) {
658 				ret = MIX_RESULT_NOT_SUPPORTED;
659 				goto cleanup;
660 			}
661 		}
662 
663 		MixVideoFormat_MP42 *video_format = mix_videoformat_mp42_new();
664 		if (!video_format) {
665 			ret = MIX_RESULT_NO_MEMORY;
666 			LOG_E("Failed to create MPEG-4:2 video format\n");
667 			goto cleanup;
668 		}
669 
670 		/* TODO: work specific to MPEG-4:2 */
671 		priv->video_format = MIX_VIDEOFORMAT(video_format);
672 
673 	} else {
674 
675 		/* Oops! A format we don't know */
676 
677 		ret = MIX_RESULT_FAIL;
678 		LOG_E("Unknown format, we can't handle it\n");
679 		goto cleanup;
680 	}
681 
682 	/* initialize MixVideoFormat */
683 	ret = mix_videofmt_initialize(priv->video_format, priv_config_params_dec,
684 			priv->frame_manager, priv->buffer_pool, &priv->surface_pool,
685 			priv->va_display);
686 
687 	if (ret != MIX_RESULT_SUCCESS) {
688 		LOG_E("Failed initialize video format\n");
689 		goto cleanup;
690 	}
691 
692 	mix_surfacepool_ref(priv->surface_pool);
693 
694 	/* decide MixVideoFormat from mime_type*/
695 
696 	priv->configured = TRUE;
697 	ret = MIX_RESULT_SUCCESS;
698 
699 	cleanup:
700 
701 	if (ret != MIX_RESULT_SUCCESS) {
702 		MIXUNREF(priv->config_params, mix_videoconfigparams_unref);
703 		MIXUNREF(priv->frame_manager, mix_framemanager_unref);
704 		MIXUNREF(priv->buffer_pool, mix_bufferpool_unref);
705 		MIXUNREF(priv->video_format, mix_videoformat_unref);
706 	}
707 
708 	if (mime_type) {
709 		g_free(mime_type);
710 	}
711 
712 	g_mutex_unlock(priv->objlock);
713 	/* ---------------------- end lock --------------------- */
714 
715 	LOG_V( "End\n");
716 
717 	return ret;
718 }
719 
mix_video_configure_encode(MixVideo * mix,MixVideoConfigParamsEnc * config_params_enc,MixDrmParams * drm_config_params)720 MIX_RESULT mix_video_configure_encode(MixVideo * mix,
721 		MixVideoConfigParamsEnc * config_params_enc,
722 		MixDrmParams * drm_config_params) {
723 
724 	MIX_RESULT ret = MIX_RESULT_FAIL;
725 	MixVideoPrivate *priv = NULL;
726 	MixVideoConfigParamsEnc *priv_config_params_enc = NULL;
727 
728 
729 	gchar *mime_type = NULL;
730 	MixEncodeTargetFormat encode_format = MIX_ENCODE_TARGET_FORMAT_H264;
731 	guint bufpoolsize = 0;
732 
733 	MixFrameOrderMode frame_order_mode = MIX_FRAMEORDER_MODE_DECODEORDER;
734 
735 
736 	LOG_V( "Begin\n");
737 
738 	CHECK_INIT(mix, priv);
739 
740 	if (!config_params_enc) {
741 		LOG_E("!config_params_enc\n");
742 		return MIX_RESULT_NULL_PTR;
743 	}
744 	if (!MIX_IS_VIDEOCONFIGPARAMSENC(config_params_enc)) {
745 		LOG_E("Not a MixVideoConfigParams\n");
746 		return MIX_RESULT_INVALID_PARAM;
747 	}
748 
749 	/* ---------------------- begin lock --------------------- */
750 	g_mutex_lock(priv->objlock);
751 
752 	/*
753 	 * MixVideo has already been configured, it should be
754 	 * re-configured.
755 	 *
756 	 * TODO: Allow MixVideo re-configuration
757 	 */
758 	if (priv->configured) {
759 		ret = MIX_RESULT_SUCCESS;
760 		LOG_E( "Already configured\n");
761 		goto cleanup;
762 	}
763 
764 	/* Make a copy of config_params */
765 	priv->config_params = (MixVideoConfigParams *) mix_params_dup(
766 			MIX_PARAMS(config_params_enc));
767 	if (!priv->config_params) {
768 		ret = MIX_RESULT_NO_MEMORY;
769 		LOG_E("Fail to duplicate config_params\n");
770 		goto cleanup;
771 	}
772 
773 	priv_config_params_enc = (MixVideoConfigParamsEnc *)priv->config_params;
774 
775 	/* Get fps, frame order mode and mime type from config_params */
776 	ret = mix_videoconfigparamsenc_get_mime_type(priv_config_params_enc,
777 			&mime_type);
778 	if (ret != MIX_RESULT_SUCCESS) {
779 		LOG_E("Failed to get mime type\n");
780 		goto cleanup;
781 	}
782 
783 	LOG_I( "mime : %s\n", mime_type);
784 
785 	ret = mix_videoconfigparamsenc_get_encode_format(priv_config_params_enc,
786 			&encode_format);
787 	if (ret != MIX_RESULT_SUCCESS) {
788 		LOG_E("Failed to get target format\n");
789 		goto cleanup;
790 	}
791 
792 	LOG_I( "encode_format : %d\n",
793 			encode_format);
794 
795 	ret = mix_videoconfigparamsenc_get_buffer_pool_size(
796 			priv_config_params_enc, &bufpoolsize);
797 	if (ret != MIX_RESULT_SUCCESS) {
798 		LOG_E("Failed to get buffer pool size\n");
799 		goto cleanup;
800 	}
801 
802 	/* create frame manager */
803 	priv->frame_manager = mix_framemanager_new();
804 	if (!priv->frame_manager) {
805 		ret = MIX_RESULT_NO_MEMORY;
806 		LOG_E("Failed to create frame manager\n");
807 		goto cleanup;
808 	}
809 
810 	/* initialize frame manager */
811 	/* frame rate can be any value for encoding. */
812 	ret = mix_framemanager_initialize(priv->frame_manager, frame_order_mode,
813 			1, 1, FALSE);
814 
815 	if (ret != MIX_RESULT_SUCCESS) {
816 		LOG_E("Failed to initialize frame manager\n");
817 		goto cleanup;
818 	}
819 
820 	/* create buffer pool */
821 	priv->buffer_pool = mix_bufferpool_new();
822 	if (!priv->buffer_pool) {
823 		ret = MIX_RESULT_NO_MEMORY;
824 		LOG_E("Failed to create buffer pool\n");
825 		goto cleanup;
826 	}
827 
828 	ret = mix_bufferpool_initialize(priv->buffer_pool, bufpoolsize);
829 	if (ret != MIX_RESULT_SUCCESS) {
830 		LOG_E("Failed to initialize buffer pool\n");
831 		goto cleanup;
832 	}
833 
834 	/* Finally, we can create MixVideoFormatEnc */
835 	/* What type of MixVideoFormatEnc we need create? */
836 
837 	if (encode_format == MIX_ENCODE_TARGET_FORMAT_H264
838 			&& MIX_IS_VIDEOCONFIGPARAMSENC_H264(priv_config_params_enc)) {
839 
840 		MixVideoFormatEnc_H264 *video_format_enc =
841 				mix_videoformatenc_h264_new();
842 		if (!video_format_enc) {
843 			ret = MIX_RESULT_NO_MEMORY;
844 			LOG_E("mix_video_configure_encode: Failed to create h264 video enc format\n");
845 			goto cleanup;
846 		}
847 
848 		/* TODO: work specific to h264 encode */
849 
850 		priv->video_format_enc = MIX_VIDEOFORMATENC(video_format_enc);
851 
852 	}
853     else if (encode_format == MIX_ENCODE_TARGET_FORMAT_MPEG4
854             && MIX_IS_VIDEOCONFIGPARAMSENC_MPEG4(priv_config_params_enc)) {
855 
856         MixVideoFormatEnc_MPEG4 *video_format_enc = mix_videoformatenc_mpeg4_new();
857         if (!video_format_enc) {
858             ret = MIX_RESULT_NO_MEMORY;
859             LOG_E("mix_video_configure_encode: Failed to create mpeg-4:2 video format\n");
860             goto cleanup;
861         }
862 
863 		/* TODO: work specific to mpeg4 */
864 
865 		priv->video_format_enc = MIX_VIDEOFORMATENC(video_format_enc);
866 
867 	}
868     else if (encode_format == MIX_ENCODE_TARGET_FORMAT_PREVIEW
869             && MIX_IS_VIDEOCONFIGPARAMSENC_PREVIEW(priv_config_params_enc)) {
870 
871         MixVideoFormatEnc_Preview *video_format_enc = mix_videoformatenc_preview_new();
872         if (!video_format_enc) {
873             ret = MIX_RESULT_NO_MEMORY;
874             LOG_E( "mix_video_configure_encode: Failed to create preview video format\n");
875             goto cleanup;
876         }
877 
878 		priv->video_format_enc = MIX_VIDEOFORMATENC(video_format_enc);
879 
880 	}
881 	else {
882 
883 		/*unsupported format */
884 		ret = MIX_RESULT_NOT_SUPPORTED;
885 		LOG_E("Unknown format, we can't handle it\n");
886 		goto cleanup;
887 	}
888 
889 	/* initialize MixVideoEncFormat */
890 	ret = mix_videofmtenc_initialize(priv->video_format_enc,
891             priv_config_params_enc, priv->frame_manager, NULL, &priv->surface_pool,
892             priv->va_display);
893 
894 	if (ret != MIX_RESULT_SUCCESS) {
895 		LOG_E("Failed initialize video format\n");
896 		goto cleanup;
897 	}
898 
899 	mix_surfacepool_ref(priv->surface_pool);
900 
901 	priv->configured = TRUE;
902 	ret = MIX_RESULT_SUCCESS;
903 
904 	cleanup:
905 
906 	if (ret != MIX_RESULT_SUCCESS) {
907 		MIXUNREF(priv->frame_manager, mix_framemanager_unref);
908 		MIXUNREF(priv->config_params, mix_videoconfigparams_unref);
909 		MIXUNREF(priv->buffer_pool, mix_bufferpool_unref);
910 		MIXUNREF(priv->video_format_enc, mix_videoformatenc_unref);
911 	}
912 
913 	if (mime_type) {
914 		g_free(mime_type);
915 	}
916 
917 	g_mutex_unlock(priv->objlock);
918 	/* ---------------------- end lock --------------------- */
919 
920 	LOG_V( "End\n");
921 
922 	return ret;
923 }
924 
mix_video_configure_default(MixVideo * mix,MixVideoConfigParams * config_params,MixDrmParams * drm_config_params)925 MIX_RESULT mix_video_configure_default(MixVideo * mix,
926 		MixVideoConfigParams * config_params,
927 		MixDrmParams * drm_config_params) {
928 
929 	MIX_RESULT ret = MIX_RESULT_FAIL;
930 	MixVideoPrivate *priv = NULL;
931 
932 	LOG_V( "Begin\n");
933 
934 	CHECK_INIT(mix, priv);
935 	if(!config_params) {
936 		LOG_E("!config_params\n");
937 		return MIX_RESULT_NULL_PTR;
938 	}
939 
940 	/*Decoder mode or Encoder mode*/
941 	if (priv->codec_mode == MIX_CODEC_MODE_DECODE && MIX_IS_VIDEOCONFIGPARAMSDEC(config_params)) {
942 		ret = mix_video_configure_decode(mix, (MixVideoConfigParamsDec*)config_params, NULL);
943 	} else if (priv->codec_mode == MIX_CODEC_MODE_ENCODE && MIX_IS_VIDEOCONFIGPARAMSENC(config_params)) {
944 		ret = mix_video_configure_encode(mix, (MixVideoConfigParamsEnc*)config_params, NULL);
945 	} else {
946 		LOG_E("Codec mode not supported\n");
947 	}
948 
949 	LOG_V( "end\n");
950 
951 	return ret;
952 }
953 
mix_video_get_config_default(MixVideo * mix,MixVideoConfigParams ** config_params)954 MIX_RESULT mix_video_get_config_default(MixVideo * mix,
955 		MixVideoConfigParams ** config_params) {
956 
957 	MIX_RESULT ret = MIX_RESULT_FAIL;
958 	MixVideoPrivate *priv = NULL;
959 
960 	CHECK_INIT_CONFIG(mix, priv);
961 
962 	if (!config_params) {
963 		LOG_E( "!config_params\n");
964 		return MIX_RESULT_NULL_PTR;
965 	}
966 
967 	/* ---------------------- begin lock --------------------- */
968 	g_mutex_lock(priv->objlock);
969 
970 	*config_params = MIX_VIDEOCONFIGPARAMS(mix_params_dup(MIX_PARAMS(priv->config_params)));
971 	if(!*config_params) {
972 		ret = MIX_RESULT_NO_MEMORY;
973 		LOG_E("Failed to duplicate MixVideoConfigParams\n");
974 		goto cleanup;
975 	}
976 
977 	cleanup:
978 
979 	/* ---------------------- end lock --------------------- */
980 	g_mutex_unlock(priv->objlock);
981 
982 	LOG_V( "End\n");
983 
984 	return ret;
985 
986 }
987 
mix_video_decode_default(MixVideo * mix,MixBuffer * bufin[],gint bufincnt,MixVideoDecodeParams * decode_params)988 MIX_RESULT mix_video_decode_default(MixVideo * mix, MixBuffer * bufin[],
989 		gint bufincnt, MixVideoDecodeParams * decode_params) {
990 
991 	MIX_RESULT ret = MIX_RESULT_FAIL;
992 	MixVideoPrivate *priv = NULL;
993 
994 	LOG_V( "Begin\n");
995 
996 	CHECK_INIT_CONFIG(mix, priv);
997 	if(!bufin || !bufincnt || !decode_params) {
998 		LOG_E( "!bufin || !bufincnt || !decode_params\n");
999 		return MIX_RESULT_NULL_PTR;
1000 	}
1001 
1002 	//First check that we have surfaces available for decode
1003 	ret = mix_surfacepool_check_available(priv->surface_pool);
1004 
1005 	if (ret == MIX_RESULT_POOLEMPTY) {
1006 		LOG_I( "Out of surface\n");
1007 		return MIX_RESULT_OUTOFSURFACES;
1008 	}
1009 
1010 	g_mutex_lock(priv->objlock);
1011 
1012 	ret = mix_videofmt_decode(priv->video_format, bufin, bufincnt, decode_params);
1013 
1014 	g_mutex_unlock(priv->objlock);
1015 
1016 	LOG_V( "End\n");
1017 
1018 	return ret;
1019 }
1020 
mix_video_get_frame_default(MixVideo * mix,MixVideoFrame ** frame)1021 MIX_RESULT mix_video_get_frame_default(MixVideo * mix, MixVideoFrame ** frame) {
1022 
1023 	LOG_V( "Begin\n");
1024 
1025 	MIX_RESULT ret = MIX_RESULT_FAIL;
1026 	MixVideoPrivate *priv = NULL;
1027 
1028 	CHECK_INIT_CONFIG(mix, priv);
1029 
1030 	if (!frame) {
1031 		LOG_E( "!frame\n");
1032 		return MIX_RESULT_NULL_PTR;
1033 	}
1034 
1035 	/* ---------------------- begin lock --------------------- */
1036 	g_mutex_lock(priv->objlock);
1037 
1038 	LOG_V("Calling frame manager dequeue\n");
1039 
1040 	ret = mix_framemanager_dequeue(priv->frame_manager, frame);
1041 
1042 	/* ---------------------- end lock --------------------- */
1043 	g_mutex_unlock(priv->objlock);
1044 
1045 	LOG_V( "End\n");
1046 
1047 	return ret;
1048 }
1049 
mix_video_release_frame_default(MixVideo * mix,MixVideoFrame * frame)1050 MIX_RESULT mix_video_release_frame_default(MixVideo * mix,
1051 		MixVideoFrame * frame) {
1052 
1053 	LOG_V( "Begin\n");
1054 
1055 	MIX_RESULT ret = MIX_RESULT_FAIL;
1056 	MixVideoPrivate *priv = NULL;
1057 
1058 	CHECK_INIT_CONFIG(mix, priv);
1059 
1060 	if (!frame) {
1061 		LOG_E( "!frame\n");
1062 		return MIX_RESULT_NULL_PTR;
1063 	}
1064 
1065 	/*
1066 	 * We don't need lock here. MixVideoFrame has lock to
1067 	 * protect itself.
1068 	 */
1069 #if 0
1070 	/* ---------------------- begin lock --------------------- */
1071 	g_mutex_lock(priv->objlock);
1072 #endif
1073 
1074 	LOG_I("Releasing reference frame %x\n", (guint) frame);
1075 	mix_videoframe_unref(frame);
1076 
1077 	ret = MIX_RESULT_SUCCESS;
1078 
1079 #if 0
1080 	/* ---------------------- end lock --------------------- */
1081 	g_mutex_unlock(priv->objlock);
1082 #endif
1083 
1084 	LOG_V( "End\n");
1085 
1086 	return ret;
1087 
1088 }
1089 
mix_video_render_default(MixVideo * mix,MixVideoRenderParams * render_params,MixVideoFrame * frame)1090 MIX_RESULT mix_video_render_default(MixVideo * mix,
1091 		MixVideoRenderParams * render_params, MixVideoFrame *frame) {
1092 
1093 	LOG_V( "Begin\n");
1094 
1095 	MIX_RESULT ret = MIX_RESULT_FAIL;
1096 	MixVideoPrivate *priv = NULL;
1097 
1098 	MixDisplay *mix_display = NULL;
1099 	MixDisplayX11 *mix_display_x11 = NULL;
1100 
1101 	Display *display = NULL;
1102 	Drawable drawable = 0;
1103 
1104 	MixRect src_rect, dst_rect;
1105 
1106 	VARectangle *va_cliprects = NULL;
1107 	guint number_of_cliprects = 0;
1108 
1109 	/* VASurfaceID va_surface_id; */
1110 	gulong va_surface_id;
1111 	VAStatus va_status;
1112 
1113 	CHECK_INIT_CONFIG(mix, priv);
1114 
1115 	if (!render_params || !frame) {
1116 		LOG_E( "!render_params || !frame\n");
1117 		return MIX_RESULT_NULL_PTR;
1118 	}
1119 
1120 	/* Is this render param valid? */
1121 	if (!MIX_IS_VIDEORENDERPARAMS(render_params)) {
1122 		LOG_E("Not MixVideoRenderParams\n");
1123 		return MIX_RESULT_INVALID_PARAM;
1124 	}
1125 
1126 	/*
1127 	 * We don't need lock here. priv->va_display may be the only variable
1128 	 * seems need to be protected. But, priv->va_display is initialized
1129 	 * when mixvideo object is initialized, and it keeps
1130 	 * the same value thoughout the life of mixvideo.
1131 	 */
1132 #if 0
1133 	/* ---------------------- begin lock --------------------- */
1134 	g_mutex_lock(priv->objlock);
1135 #endif
1136 
1137 	/* get MixDisplay prop from render param */
1138 	ret = mix_videorenderparams_get_display(render_params, &mix_display);
1139 	if (ret != MIX_RESULT_SUCCESS) {
1140 		LOG_E("Failed to get mix_display\n");
1141 		goto cleanup;
1142 	}
1143 
1144 	/* Is this MixDisplayX11 ? */
1145 	/* TODO: we shall also support MixDisplay other than MixDisplayX11 */
1146 	if (!MIX_IS_DISPLAYX11(mix_display)) {
1147 		ret = MIX_RESULT_INVALID_PARAM;
1148 		LOG_E( "Not MixDisplayX11\n");
1149 		goto cleanup;
1150 	}
1151 
1152 	/* cast MixDisplay to MixDisplayX11 */
1153 	mix_display_x11 = MIX_DISPLAYX11(mix_display);
1154 
1155 	/* Get Drawable */
1156 	ret = mix_displayx11_get_drawable(mix_display_x11, &drawable);
1157 	if (ret != MIX_RESULT_SUCCESS) {
1158 		LOG_E( "Failed to get drawable\n");
1159 		goto cleanup;
1160 	}
1161 
1162 	/* Get Display */
1163 	ret = mix_displayx11_get_display(mix_display_x11, &display);
1164 	if (ret != MIX_RESULT_SUCCESS) {
1165 		LOG_E( "Failed to get display\n");
1166 		goto cleanup;
1167 	}
1168 
1169 	/* get src_rect */
1170 	ret = mix_videorenderparams_get_src_rect(render_params, &src_rect);
1171 	if (ret != MIX_RESULT_SUCCESS) {
1172 		LOG_E("Failed to get SOURCE src_rect\n");
1173 		goto cleanup;
1174 	}
1175 
1176 	/* get dst_rect */
1177 	ret = mix_videorenderparams_get_dest_rect(render_params, &dst_rect);
1178 	if (ret != MIX_RESULT_SUCCESS) {
1179 		LOG_E( "Failed to get dst_rect\n");
1180 		goto cleanup;
1181 	}
1182 
1183 	/* get va_cliprects */
1184 	ret = mix_videorenderparams_get_cliprects_internal(render_params,
1185 			&va_cliprects, &number_of_cliprects);
1186 	if (ret != MIX_RESULT_SUCCESS) {
1187 		LOG_E("Failed to get va_cliprects\n");
1188 		goto cleanup;
1189 	}
1190 
1191 	/* get surface id from frame */
1192 	ret = mix_videoframe_get_frame_id(frame, &va_surface_id);
1193 	if (ret != MIX_RESULT_SUCCESS) {
1194 		LOG_E("Failed to get va_surface_id\n");
1195 		goto cleanup;
1196 	}
1197 	guint64 timestamp = 0;
1198 	mix_videoframe_get_timestamp(frame, &timestamp);
1199 	LOG_V( "Displaying surface ID %d, timestamp %"G_GINT64_FORMAT"\n", (int)va_surface_id, timestamp);
1200 
1201 	guint32 frame_structure = 0;
1202 	mix_videoframe_get_frame_structure(frame, &frame_structure);
1203 	/* TODO: the last param of vaPutSurface is de-interlacing flags,
1204 	 what is value shall be*/
1205 	va_status = vaPutSurface(priv->va_display, (VASurfaceID) va_surface_id,
1206 			drawable, src_rect.x, src_rect.y, src_rect.width, src_rect.height,
1207 			dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height,
1208 			va_cliprects, number_of_cliprects, frame_structure);
1209 
1210 	if (va_status != VA_STATUS_SUCCESS) {
1211 		ret = MIX_RESULT_FAIL;
1212 		LOG_E("Failed vaPutSurface() : va_status = %d\n", va_status);
1213 		goto cleanup;
1214 	}
1215 
1216 	/* TODO: Is this only for X11? */
1217 	XSync(display, FALSE);
1218 
1219 	ret = MIX_RESULT_SUCCESS;
1220 
1221 	cleanup:
1222 
1223 	MIXUNREF(mix_display, mix_display_unref)
1224 	/*	MIXUNREF(render_params, mix_videorenderparams_unref)*/
1225 
1226 #if 0
1227 	/* ---------------------- end lock --------------------- */
1228 	g_mutex_unlock(priv->objlock);
1229 #endif
1230 
1231 	LOG_V( "End\n");
1232 
1233 	return ret;
1234 
1235 }
1236 
mix_video_encode_default(MixVideo * mix,MixBuffer * bufin[],gint bufincnt,MixIOVec * iovout[],gint iovoutcnt,MixVideoEncodeParams * encode_params)1237 MIX_RESULT mix_video_encode_default(MixVideo * mix, MixBuffer * bufin[],
1238 		gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
1239 		MixVideoEncodeParams * encode_params) {
1240 
1241 	MIX_RESULT ret = MIX_RESULT_FAIL;
1242 	MixVideoPrivate *priv = NULL;
1243 
1244 	LOG_V( "Begin\n");
1245 
1246 	CHECK_INIT_CONFIG(mix, priv);
1247 	if(!bufin || !bufincnt) { //we won't check encode_params here, it's just a placeholder
1248 		LOG_E( "!bufin || !bufincnt\n");
1249 		return MIX_RESULT_NULL_PTR;
1250 	}
1251 
1252 	g_mutex_lock(priv->objlock);
1253 
1254 	ret = mix_videofmtenc_encode(priv->video_format_enc, bufin, bufincnt,
1255 			iovout, iovoutcnt, encode_params);
1256 
1257 	g_mutex_unlock(priv->objlock);
1258 
1259 	LOG_V( "End\n");
1260 	return ret;
1261 }
1262 
mix_video_flush_default(MixVideo * mix)1263 MIX_RESULT mix_video_flush_default(MixVideo * mix) {
1264 
1265 	MIX_RESULT ret = MIX_RESULT_FAIL;
1266 	MixVideoPrivate *priv = NULL;
1267 
1268 	LOG_V( "Begin\n");
1269 
1270 	CHECK_INIT_CONFIG(mix, priv);
1271 
1272 	/* ---------------------- begin lock --------------------- */
1273 	g_mutex_lock(priv->objlock);
1274 
1275 	if (priv->codec_mode == MIX_CODEC_MODE_DECODE && priv->video_format != NULL) {
1276 		ret = mix_videofmt_flush(priv->video_format);
1277 
1278 		ret = mix_framemanager_flush(priv->frame_manager);
1279 	} else if (priv->codec_mode == MIX_CODEC_MODE_ENCODE
1280 			&& priv->video_format_enc != NULL) {
1281 		/*No framemanager for encoder now*/
1282 		ret = mix_videofmtenc_flush(priv->video_format_enc);
1283 	} else {
1284 		g_mutex_unlock(priv->objlock);
1285 		LOG_E("Invalid video_format/video_format_enc Pointer\n");
1286 		return MIX_RESULT_NULL_PTR;
1287 	}
1288 
1289 	/* ---------------------- end lock --------------------- */
1290 	g_mutex_unlock(priv->objlock);
1291 
1292 	LOG_V( "End\n");
1293 
1294 	return ret;
1295 
1296 }
1297 
mix_video_eos_default(MixVideo * mix)1298 MIX_RESULT mix_video_eos_default(MixVideo * mix) {
1299 
1300 	MIX_RESULT ret = MIX_RESULT_FAIL;
1301 	MixVideoPrivate *priv = NULL;
1302 
1303 	LOG_V( "Begin\n");
1304 
1305 	CHECK_INIT_CONFIG(mix, priv);
1306 
1307 	/* ---------------------- begin lock --------------------- */
1308 	g_mutex_lock(priv->objlock);
1309 
1310 	if (priv->codec_mode == MIX_CODEC_MODE_DECODE && priv->video_format != NULL) {
1311 		ret = mix_videofmt_eos(priv->video_format);
1312 
1313 		/* frame manager will set EOS flag to be TRUE */
1314 		ret = mix_framemanager_eos(priv->frame_manager);
1315 	} else if (priv->codec_mode == MIX_CODEC_MODE_ENCODE
1316 			&& priv->video_format_enc != NULL) {
1317 		/*No framemanager now*/
1318 		ret = mix_videofmtenc_eos(priv->video_format_enc);
1319 	} else {
1320 		g_mutex_unlock(priv->objlock);
1321 		LOG_E("Invalid video_format/video_format_enc Pointer\n");
1322 		return MIX_RESULT_NULL_PTR;
1323 	}
1324 
1325 	/* ---------------------- end lock --------------------- */
1326 	g_mutex_unlock(priv->objlock);
1327 
1328 	LOG_V( "End\n");
1329 
1330 	return ret;
1331 }
1332 
mix_video_get_state_default(MixVideo * mix,MixState * state)1333 MIX_RESULT mix_video_get_state_default(MixVideo * mix, MixState * state) {
1334 
1335 	MixVideoPrivate *priv = NULL;
1336 
1337 	LOG_V( "Begin\n");
1338 
1339 	CHECK_INIT_CONFIG(mix, priv);
1340 
1341 	if (!state) {
1342 		LOG_E( "!state\n");
1343 		return MIX_RESULT_NULL_PTR;
1344 	}
1345 
1346 	*state = MIX_STATE_CONFIGURED;
1347 
1348 	LOG_V( "End\n");
1349 
1350 	return MIX_RESULT_SUCCESS;
1351 }
1352 
mix_video_get_mixbuffer_default(MixVideo * mix,MixBuffer ** buf)1353 MIX_RESULT mix_video_get_mixbuffer_default(MixVideo * mix, MixBuffer ** buf) {
1354 
1355 	MIX_RESULT ret = MIX_RESULT_FAIL;
1356 	MixVideoPrivate *priv = NULL;
1357 
1358 	LOG_V( "Begin\n");
1359 
1360 	CHECK_INIT_CONFIG(mix, priv);
1361 
1362 	if (!buf) {
1363 		LOG_E( "!buf\n");
1364 		return MIX_RESULT_INVALID_PARAM;
1365 	}
1366 
1367 	/* ---------------------- begin lock --------------------- */
1368 	g_mutex_lock(priv->objlock);
1369 
1370 	ret = mix_bufferpool_get(priv->buffer_pool, buf);
1371 
1372 	/* ---------------------- end lock --------------------- */
1373 	g_mutex_unlock(priv->objlock);
1374 
1375 	LOG_V( "End ret = 0x%x\n", ret);
1376 
1377 	return ret;
1378 
1379 }
1380 
mix_video_release_mixbuffer_default(MixVideo * mix,MixBuffer * buf)1381 MIX_RESULT mix_video_release_mixbuffer_default(MixVideo * mix, MixBuffer * buf) {
1382 
1383 	MIX_RESULT ret = MIX_RESULT_FAIL;
1384 	MixVideoPrivate *priv = NULL;
1385 
1386 	LOG_V( "Begin\n");
1387 
1388 	CHECK_INIT_CONFIG(mix, priv);
1389 
1390 	if (!buf) {
1391 		LOG_E( "!buf\n");
1392 		return MIX_RESULT_INVALID_PARAM;
1393 	}
1394 
1395 	/* ---------------------- begin lock --------------------- */
1396 	g_mutex_lock(priv->objlock);
1397 
1398 	mix_buffer_unref(buf);
1399 
1400 	/* ---------------------- end lock --------------------- */
1401 	g_mutex_unlock(priv->objlock);
1402 
1403 	LOG_V( "End\n");
1404 	return ret;
1405 
1406 }
1407 
mix_video_get_max_coded_buffer_size_default(MixVideo * mix,guint * max_size)1408 MIX_RESULT mix_video_get_max_coded_buffer_size_default (MixVideo * mix, guint *max_size)
1409 {
1410       MIX_RESULT ret = MIX_RESULT_FAIL;
1411 	MixVideoPrivate *priv = NULL;
1412 
1413 	LOG_V( "Begin\n");
1414 
1415 	if (!mix || !max_size) /* TODO: add other parameter NULL checking */
1416 	{
1417 		LOG_E( "!mix || !bufsize\n");
1418 		return MIX_RESULT_NULL_PTR;
1419 	}
1420 
1421 	CHECK_INIT_CONFIG(mix, priv);
1422 
1423 	g_mutex_lock(priv->objlock);
1424 
1425 	ret = mix_videofmtenc_get_max_coded_buffer_size(priv->video_format_enc, max_size);
1426 
1427 	g_mutex_unlock(priv->objlock);
1428 
1429 	LOG_V( "End\n");
1430 	return ret;
1431 }
1432 
1433 /*
1434  * API functions
1435  */
1436 
1437 #define CHECK_AND_GET_MIX_CLASS(mix, klass) \
1438 	if (!mix) { \
1439 		return MIX_RESULT_NULL_PTR; \
1440 	} \
1441 	if (!MIX_IS_VIDEO(mix)) { \
1442 		LOG_E( "Not MixVideo\n"); \
1443 		return MIX_RESULT_INVALID_PARAM; \
1444 	} \
1445 	klass = MIX_VIDEO_GET_CLASS(mix);
1446 
1447 
mix_video_get_version(MixVideo * mix,guint * major,guint * minor)1448 MIX_RESULT mix_video_get_version(MixVideo * mix, guint * major, guint * minor) {
1449 
1450 	MixVideoClass *klass = NULL;
1451 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1452 
1453 	if (klass->get_version_func) {
1454 		return klass->get_version_func(mix, major, minor);
1455 	}
1456 	return MIX_RESULT_NOTIMPL;
1457 
1458 }
1459 
mix_video_initialize(MixVideo * mix,MixCodecMode mode,MixVideoInitParams * init_params,MixDrmParams * drm_init_params)1460 MIX_RESULT mix_video_initialize(MixVideo * mix, MixCodecMode mode,
1461 		MixVideoInitParams * init_params, MixDrmParams * drm_init_params) {
1462 
1463 	MixVideoClass *klass = NULL;
1464 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1465 
1466 	if (klass->initialize_func) {
1467 		return klass->initialize_func(mix, mode, init_params, drm_init_params);
1468 	}
1469 	return MIX_RESULT_NOTIMPL;
1470 
1471 }
1472 
mix_video_deinitialize(MixVideo * mix)1473 MIX_RESULT mix_video_deinitialize(MixVideo * mix) {
1474 
1475 	MixVideoClass *klass = NULL;
1476 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1477 
1478 	if (klass->deinitialize_func) {
1479 		return klass->deinitialize_func(mix);
1480 	}
1481 	return MIX_RESULT_NOTIMPL;
1482 }
1483 
mix_video_configure(MixVideo * mix,MixVideoConfigParams * config_params,MixDrmParams * drm_config_params)1484 MIX_RESULT mix_video_configure(MixVideo * mix,
1485 		MixVideoConfigParams * config_params,
1486 		MixDrmParams * drm_config_params) {
1487 
1488 	MixVideoClass *klass = NULL;
1489 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1490 
1491 	if (klass->configure_func) {
1492 		return klass->configure_func(mix, config_params, drm_config_params);
1493 	}
1494 	return MIX_RESULT_NOTIMPL;
1495 }
1496 
mix_video_get_config(MixVideo * mix,MixVideoConfigParams ** config_params_dec)1497 MIX_RESULT mix_video_get_config(MixVideo * mix,
1498 		MixVideoConfigParams ** config_params_dec) {
1499 
1500 	MixVideoClass *klass = NULL;
1501 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1502 
1503 	if (klass->get_config_func) {
1504 		return klass->get_config_func(mix, config_params_dec);
1505 	}
1506 	return MIX_RESULT_NOTIMPL;
1507 
1508 }
1509 
mix_video_decode(MixVideo * mix,MixBuffer * bufin[],gint bufincnt,MixVideoDecodeParams * decode_params)1510 MIX_RESULT mix_video_decode(MixVideo * mix, MixBuffer * bufin[], gint bufincnt,
1511 		MixVideoDecodeParams * decode_params) {
1512 
1513 	MixVideoClass *klass = NULL;
1514 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1515 
1516 	if (klass->decode_func) {
1517 		return klass->decode_func(mix, bufin, bufincnt,
1518 				decode_params);
1519 	}
1520 	return MIX_RESULT_NOTIMPL;
1521 
1522 }
1523 
mix_video_get_frame(MixVideo * mix,MixVideoFrame ** frame)1524 MIX_RESULT mix_video_get_frame(MixVideo * mix, MixVideoFrame ** frame) {
1525 
1526 	MixVideoClass *klass = NULL;
1527 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1528 
1529 	if (klass->get_frame_func) {
1530 		return klass->get_frame_func(mix, frame);
1531 	}
1532 	return MIX_RESULT_NOTIMPL;
1533 
1534 }
1535 
mix_video_release_frame(MixVideo * mix,MixVideoFrame * frame)1536 MIX_RESULT mix_video_release_frame(MixVideo * mix, MixVideoFrame * frame) {
1537 
1538 	MixVideoClass *klass = NULL;
1539 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1540 
1541 	if (klass->release_frame_func) {
1542 		return klass->release_frame_func(mix, frame);
1543 	}
1544 	return MIX_RESULT_NOTIMPL;
1545 }
1546 
mix_video_render(MixVideo * mix,MixVideoRenderParams * render_params,MixVideoFrame * frame)1547 MIX_RESULT mix_video_render(MixVideo * mix,
1548 		MixVideoRenderParams * render_params, MixVideoFrame *frame) {
1549 
1550 	MixVideoClass *klass = NULL;
1551 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1552 
1553 	if (klass->render_func) {
1554 		return klass->render_func(mix, render_params, frame);
1555 	}
1556 	return MIX_RESULT_NOTIMPL;
1557 
1558 }
1559 
mix_video_encode(MixVideo * mix,MixBuffer * bufin[],gint bufincnt,MixIOVec * iovout[],gint iovoutcnt,MixVideoEncodeParams * encode_params)1560 MIX_RESULT mix_video_encode(MixVideo * mix, MixBuffer * bufin[], gint bufincnt,
1561 		MixIOVec * iovout[], gint iovoutcnt,
1562 		MixVideoEncodeParams * encode_params) {
1563 
1564 	MixVideoClass *klass = NULL;
1565 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1566 
1567 	if (klass->encode_func) {
1568 		return klass->encode_func(mix, bufin, bufincnt, iovout, iovoutcnt,
1569 				encode_params);
1570 	}
1571 	return MIX_RESULT_NOTIMPL;
1572 
1573 }
1574 
mix_video_flush(MixVideo * mix)1575 MIX_RESULT mix_video_flush(MixVideo * mix) {
1576 
1577 	MixVideoClass *klass = NULL;
1578 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1579 
1580 	if (klass->flush_func) {
1581 		return klass->flush_func(mix);
1582 	}
1583 	return MIX_RESULT_NOTIMPL;
1584 }
1585 
mix_video_eos(MixVideo * mix)1586 MIX_RESULT mix_video_eos(MixVideo * mix) {
1587 
1588 	MixVideoClass *klass = NULL;
1589 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1590 
1591 	if (klass->eos_func) {
1592 		return klass->eos_func(mix);
1593 	}
1594 	return MIX_RESULT_NOTIMPL;
1595 }
1596 
mix_video_get_state(MixVideo * mix,MixState * state)1597 MIX_RESULT mix_video_get_state(MixVideo * mix, MixState * state) {
1598 
1599 	MixVideoClass *klass = NULL;
1600 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1601 
1602 	if (klass->get_state_func) {
1603 		return klass->get_state_func(mix, state);
1604 	}
1605 	return MIX_RESULT_NOTIMPL;
1606 }
1607 
mix_video_get_mixbuffer(MixVideo * mix,MixBuffer ** buf)1608 MIX_RESULT mix_video_get_mixbuffer(MixVideo * mix, MixBuffer ** buf) {
1609 
1610 	MixVideoClass *klass = NULL;
1611 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1612 
1613 	if (klass->get_mix_buffer_func) {
1614 		return klass->get_mix_buffer_func(mix, buf);
1615 	}
1616 	return MIX_RESULT_NOTIMPL;
1617 }
1618 
mix_video_release_mixbuffer(MixVideo * mix,MixBuffer * buf)1619 MIX_RESULT mix_video_release_mixbuffer(MixVideo * mix, MixBuffer * buf) {
1620 
1621 	MixVideoClass *klass = NULL;
1622 	CHECK_AND_GET_MIX_CLASS(mix, klass);
1623 
1624 	if (klass->release_mix_buffer_func) {
1625 		return klass->release_mix_buffer_func(mix, buf);
1626 	}
1627 	return MIX_RESULT_NOTIMPL;
1628 }
1629 
mix_video_get_max_coded_buffer_size(MixVideo * mix,guint * bufsize)1630 MIX_RESULT mix_video_get_max_coded_buffer_size(MixVideo * mix, guint *bufsize) {
1631 
1632 	MixVideoClass *klass = MIX_VIDEO_GET_CLASS(mix);
1633 
1634 	if (klass->get_max_coded_buffer_size_func) {
1635 		return klass->get_max_coded_buffer_size_func(mix, bufsize);
1636 	}
1637 	return MIX_RESULT_NOTIMPL;
1638 }
1639