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
77MIX_RESULT mix_video_get_version_default(MixVideo * mix, guint * major,
78		guint * minor);
79
80MIX_RESULT mix_video_initialize_default(MixVideo * mix, MixCodecMode mode,
81		MixVideoInitParams * init_params, MixDrmParams * drm_init_params);
82
83MIX_RESULT mix_video_deinitialize_default(MixVideo * mix);
84
85MIX_RESULT mix_video_configure_default(MixVideo * mix,
86		MixVideoConfigParams * config_params, MixDrmParams * drm_config_params);
87
88MIX_RESULT mix_video_get_config_default(MixVideo * mix,
89		MixVideoConfigParams ** config_params);
90
91MIX_RESULT mix_video_decode_default(MixVideo * mix, MixBuffer * bufin[],
92		gint bufincnt, MixVideoDecodeParams * decode_params);
93
94MIX_RESULT mix_video_get_frame_default(MixVideo * mix, MixVideoFrame ** frame);
95
96MIX_RESULT mix_video_release_frame_default(MixVideo * mix,
97		MixVideoFrame * frame);
98
99MIX_RESULT mix_video_render_default(MixVideo * mix,
100		MixVideoRenderParams * render_params, MixVideoFrame *frame);
101
102MIX_RESULT mix_video_encode_default(MixVideo * mix, MixBuffer * bufin[],
103		gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
104		MixVideoEncodeParams * encode_params);
105
106MIX_RESULT mix_video_flush_default(MixVideo * mix);
107
108MIX_RESULT mix_video_eos_default(MixVideo * mix);
109
110MIX_RESULT mix_video_get_state_default(MixVideo * mix, MixState * state);
111
112MIX_RESULT mix_video_get_mixbuffer_default(MixVideo * mix, MixBuffer ** buf);
113
114MIX_RESULT mix_video_release_mixbuffer_default(MixVideo * mix, MixBuffer * buf);
115
116MIX_RESULT mix_video_get_max_coded_buffer_size_default (MixVideo * mix, guint *max_size);
117
118
119static void mix_video_finalize(GObject * obj);
120MIX_RESULT mix_video_configure_decode(MixVideo * mix,
121		MixVideoConfigParamsDec * config_params_dec,
122		MixDrmParams * drm_config_params);
123
124MIX_RESULT mix_video_configure_encode(MixVideo * mix,
125		MixVideoConfigParamsEnc * config_params_enc,
126		MixDrmParams * drm_config_params);
127
128G_DEFINE_TYPE( MixVideo, mix_video, G_TYPE_OBJECT);
129
130static 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
145static 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
171MixVideo *mix_video_new(void) {
172
173	MixVideo *ret = g_object_new(MIX_TYPE_VIDEO, NULL);
174
175	return ret;
176}
177
178void mix_video_finalize(GObject * obj) {
179
180	/* clean up here. */
181
182	MixVideo *mix = MIX_VIDEO(obj);
183	mix_video_deinitialize(mix);
184}
185
186MixVideo *
187mix_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
195void 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
218void 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
268MIX_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
284MIX_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
426MIX_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
440MIX_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
720MIX_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
925MIX_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
954MIX_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
988MIX_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
1021MIX_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
1050MIX_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
1090MIX_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
1237MIX_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
1263MIX_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
1298MIX_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
1333MIX_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
1353MIX_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
1381MIX_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
1408MIX_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
1448MIX_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
1460MIX_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
1473MIX_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
1484MIX_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
1497MIX_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
1510MIX_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
1524MIX_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
1536MIX_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
1547MIX_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
1560MIX_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
1575MIX_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
1586MIX_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
1597MIX_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
1608MIX_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
1619MIX_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
1630MIX_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