1/*
2 INTEL CONFIDENTIAL
3 Copyright 2009 Intel Corporation All Rights Reserved.
4 The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
5
6 No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
7 */
8#include <glib.h>
9#include "mixvideolog.h"
10#include "mixvideoformatenc.h"
11
12//#define MDEBUG
13
14/* Default vmethods implementation */
15static MIX_RESULT mix_videofmtenc_getcaps_default(MixVideoFormatEnc *mix,
16        GString *msg);
17static MIX_RESULT mix_videofmtenc_initialize_default(MixVideoFormatEnc *mix,
18        MixVideoConfigParamsEnc * config_params_enc,
19        MixFrameManager * frame_mgr,
20        MixBufferPool * input_buf_pool,
21        MixSurfacePool ** surface_pool,
22        VADisplay vadisplay);
23
24static MIX_RESULT
25mix_videofmtenc_encode_default(MixVideoFormatEnc *mix, MixBuffer * bufin[],
26        gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
27        MixVideoEncodeParams * encode_params);
28static MIX_RESULT mix_videofmtenc_flush_default(MixVideoFormatEnc *mix);
29static MIX_RESULT mix_videofmtenc_eos_default(MixVideoFormatEnc *mix);
30static MIX_RESULT mix_videofmtenc_deinitialize_default(MixVideoFormatEnc *mix);
31static MIX_RESULT mix_videofmtenc_get_max_coded_buffer_size_default(
32	MixVideoFormatEnc *mix, guint *max_size);
33
34
35static GObjectClass *parent_class = NULL;
36
37static void mix_videoformatenc_finalize(GObject * obj);
38G_DEFINE_TYPE (MixVideoFormatEnc, mix_videoformatenc, G_TYPE_OBJECT);
39
40static void mix_videoformatenc_init(MixVideoFormatEnc * self) {
41	/* TODO: public member initialization */
42
43	/* TODO: private member initialization */
44
45	self->objectlock = g_mutex_new();
46
47	self->initialized = FALSE;
48	self->framemgr = NULL;
49	self->surfacepool = NULL;
50	self->inputbufpool = NULL;
51	self->inputbufqueue = NULL;
52	self->va_display = NULL;
53	self->va_context = 0;
54	self->va_config = 0;
55	self->mime_type = NULL;
56	self->frame_rate_num= 0;
57	self->frame_rate_denom = 1;
58	self->picture_width = 0;
59	self->picture_height = 0;
60	self->initial_qp = 0;
61	self->min_qp = 0;
62	self->intra_period = 0;
63	self->bitrate = 0;
64	self->share_buf_mode = FALSE;
65	self->ci_frame_id = NULL;
66	self->ci_frame_num = 0;
67       self->drawable = 0x0;
68       self->need_display = TRUE;
69
70      self->va_rcmode = VA_RC_NONE;
71      self->va_format = VA_RT_FORMAT_YUV420;
72      self->va_entrypoint = VAEntrypointEncSlice;
73      self->va_profile = VAProfileH264Baseline;
74
75	//add more properties here
76}
77
78static void mix_videoformatenc_class_init(MixVideoFormatEncClass * klass) {
79	GObjectClass *gobject_class = (GObjectClass *) klass;
80
81	/* parent class for later use */
82	parent_class = g_type_class_peek_parent(klass);
83
84	gobject_class->finalize = mix_videoformatenc_finalize;
85
86	/* setup vmethods with base implementation */
87	klass->getcaps = mix_videofmtenc_getcaps_default;
88	klass->initialize = mix_videofmtenc_initialize_default;
89	klass->encode = mix_videofmtenc_encode_default;
90	klass->flush = mix_videofmtenc_flush_default;
91	klass->eos = mix_videofmtenc_eos_default;
92	klass->deinitialize = mix_videofmtenc_deinitialize_default;
93	klass->getmaxencodedbufsize = mix_videofmtenc_get_max_coded_buffer_size_default;
94}
95
96MixVideoFormatEnc *
97mix_videoformatenc_new(void) {
98	MixVideoFormatEnc *ret = g_object_new(MIX_TYPE_VIDEOFORMATENC, NULL);
99
100	return ret;
101}
102
103void mix_videoformatenc_finalize(GObject * obj) {
104	/* clean up here. */
105
106    if (obj == NULL) {
107        LOG_E( "obj == NULL\n");
108        return;
109    }
110
111    MixVideoFormatEnc *mix = MIX_VIDEOFORMATENC(obj);
112
113    LOG_V( "\n");
114
115    if(mix->objectlock) {
116        g_mutex_free(mix->objectlock);
117        mix->objectlock = NULL;
118    }
119
120	//MiVideo object calls the _deinitialize() for frame manager
121	if (mix->framemgr)
122	{
123	  mix_framemanager_unref(mix->framemgr);
124	  mix->framemgr = NULL;
125	}
126
127	if (mix->mime_type)
128    {
129        if (mix->mime_type->str)
130            g_string_free(mix->mime_type, TRUE);
131        else
132            g_string_free(mix->mime_type, FALSE);
133    }
134
135	if (mix->ci_frame_id)
136        g_free (mix->ci_frame_id);
137
138
139	if (mix->surfacepool)
140	{
141        mix_surfacepool_deinitialize(mix->surfacepool);
142        mix_surfacepool_unref(mix->surfacepool);
143        mix->surfacepool = NULL;
144    }
145
146
147	/* TODO: cleanup here */
148
149	/* Chain up parent */
150	if (parent_class->finalize) {
151		parent_class->finalize(obj);
152	}
153}
154
155MixVideoFormatEnc *
156mix_videoformatenc_ref(MixVideoFormatEnc * mix) {
157	return (MixVideoFormatEnc *) g_object_ref(G_OBJECT(mix));
158}
159
160/* Default vmethods implementation */
161static MIX_RESULT mix_videofmtenc_getcaps_default(MixVideoFormatEnc *mix,
162        GString *msg) {
163    LOG_V( "Begin\n");
164    return MIX_RESULT_SUCCESS;
165}
166
167static MIX_RESULT mix_videofmtenc_initialize_default(MixVideoFormatEnc *mix,
168        MixVideoConfigParamsEnc * config_params_enc,
169        MixFrameManager * frame_mgr,
170        MixBufferPool * input_buf_pool,
171        MixSurfacePool ** surface_pool,
172        VADisplay va_display) {
173
174    LOG_V( "Begin\n");
175
176    if (mix == NULL ||config_params_enc == NULL) {
177        LOG_E(
178                "!mix || config_params_enc == NULL\n");
179        return MIX_RESULT_NULL_PTR;
180    }
181
182
183    MIX_RESULT ret = MIX_RESULT_SUCCESS;
184
185	//TODO check return values of getter fns for config_params
186
187	g_mutex_lock(mix->objectlock);
188
189	mix->framemgr = frame_mgr;
190	mix_framemanager_ref(mix->framemgr);
191
192	mix->va_display = va_display;
193
194    LOG_V(
195            "Start to get properities from parent params\n");
196
197    /* get properties from param (parent) Object*/
198    ret = mix_videoconfigparamsenc_get_bit_rate (config_params_enc,
199            &(mix->bitrate));
200    if (ret != MIX_RESULT_SUCCESS) {
201        //TODO cleanup
202        LOG_E(
203                "Failed to mix_videoconfigparamsenc_get_bps\n");
204        g_mutex_unlock(mix->objectlock);
205        return MIX_RESULT_FAIL;
206    }
207
208    ret = mix_videoconfigparamsenc_get_frame_rate (config_params_enc,
209            &(mix->frame_rate_num), &(mix->frame_rate_denom));
210
211    if (ret != MIX_RESULT_SUCCESS) {
212        //TODO cleanup
213        LOG_E(
214                "Failed to mix_videoconfigparamsenc_get_frame_rate\n");
215        g_mutex_unlock(mix->objectlock);
216        return MIX_RESULT_FAIL;
217    }
218
219    ret = mix_videoconfigparamsenc_get_init_qp (config_params_enc,
220            &(mix->initial_qp));
221
222    if (ret != MIX_RESULT_SUCCESS) {
223        //TODO cleanup
224
225        LOG_E(
226                "Failed to mix_videoconfigparamsenc_get_init_qp\n");
227        g_mutex_unlock(mix->objectlock);
228        return MIX_RESULT_FAIL;
229    }
230
231
232    ret = mix_videoconfigparamsenc_get_min_qp (config_params_enc,
233            &(mix->min_qp));
234
235    if (ret != MIX_RESULT_SUCCESS) {
236        //TODO cleanup
237
238        LOG_E(
239                "Failed to mix_videoconfigparamsenc_get_min_qp\n");
240        g_mutex_unlock(mix->objectlock);
241        return MIX_RESULT_FAIL;
242    }
243
244    ret = mix_videoconfigparamsenc_get_intra_period (config_params_enc,
245            &(mix->intra_period));
246
247    if (ret != MIX_RESULT_SUCCESS) {
248        //TODO cleanup
249
250        LOG_E(
251                "Failed to mix_videoconfigparamsenc_get_intra_period\n");
252        g_mutex_unlock(mix->objectlock);
253        return MIX_RESULT_FAIL;
254    }
255
256    ret = mix_videoconfigparamsenc_get_picture_res (config_params_enc,
257            &(mix->picture_width), &(mix->picture_height));
258
259    if (ret != MIX_RESULT_SUCCESS) {
260        //TODO cleanup
261
262        LOG_E(
263                "Failed to mix_videoconfigparamsenc_get_picture_res\n");
264        g_mutex_unlock(mix->objectlock);
265        return MIX_RESULT_FAIL;
266    }
267
268    ret = mix_videoconfigparamsenc_get_share_buf_mode (config_params_enc,
269            &(mix->share_buf_mode));
270
271    if (ret != MIX_RESULT_SUCCESS) {
272        //TODO cleanup
273
274        LOG_E(
275                "Failed to mix_videoconfigparamsenc_get_share_buf_mode\n");
276        g_mutex_unlock(mix->objectlock);
277        return MIX_RESULT_FAIL;
278    }
279
280
281    ret = mix_videoconfigparamsenc_get_ci_frame_info (config_params_enc,
282            &(mix->ci_frame_id),  &(mix->ci_frame_num));
283
284    if (ret != MIX_RESULT_SUCCESS) {
285        //TODO cleanup
286
287        LOG_E(
288                "Failed to mix_videoconfigparamsenc_get_ci_frame_info\n");
289        g_mutex_unlock(mix->objectlock);
290        return MIX_RESULT_FAIL;
291    }
292
293
294    ret = mix_videoconfigparamsenc_get_drawable (config_params_enc,
295            &(mix->drawable));
296
297    if (ret != MIX_RESULT_SUCCESS) {
298        //TODO cleanup
299
300        LOG_E(
301                "Failed to mix_videoconfigparamsenc_get_drawable\n");
302        g_mutex_unlock(mix->objectlock);
303        return MIX_RESULT_FAIL;
304    }
305
306    ret = mix_videoconfigparamsenc_get_need_display (config_params_enc,
307            &(mix->need_display));
308
309    if (ret != MIX_RESULT_SUCCESS) {
310        //TODO cleanup
311
312        LOG_E(
313                "Failed to mix_videoconfigparamsenc_get_drawable\n");
314        g_mutex_unlock(mix->objectlock);
315        return MIX_RESULT_FAIL;
316    }
317
318    ret = mix_videoconfigparamsenc_get_rate_control (config_params_enc,
319            &(mix->va_rcmode));
320
321    if (ret != MIX_RESULT_SUCCESS) {
322        //TODO cleanup
323
324        LOG_E(
325                "Failed to mix_videoconfigparamsenc_get_rc_mode\n");
326        g_mutex_unlock(mix->objectlock);
327        return MIX_RESULT_FAIL;
328    }
329
330    ret = mix_videoconfigparamsenc_get_raw_format (config_params_enc,
331            &(mix->va_format));
332
333    if (ret != MIX_RESULT_SUCCESS) {
334        //TODO cleanup
335
336        LOG_E(
337                "Failed to mix_videoconfigparamsenc_get_format\n");
338        g_mutex_unlock(mix->objectlock);
339        return MIX_RESULT_FAIL;
340    }
341
342    ret = mix_videoconfigparamsenc_get_profile (config_params_enc,
343            (MixProfile *) &(mix->va_profile));
344
345    if (ret != MIX_RESULT_SUCCESS) {
346        //TODO cleanup
347
348        LOG_E(
349                "Failed to mix_videoconfigparamsenc_get_profile\n");
350        g_mutex_unlock(mix->objectlock);
351        return MIX_RESULT_FAIL;
352    }
353
354
355    LOG_V(
356            "======Video Encode Parent Object properities======:\n");
357
358    LOG_I( "mix->bitrate = %d\n",
359            mix->bitrate);
360    LOG_I( "mix->frame_rate = %d\n",
361            mix->frame_rate_denom / mix->frame_rate_denom);
362    LOG_I( "mix->initial_qp = %d\n",
363            mix->initial_qp);
364    LOG_I( "mix->min_qp = %d\n",
365            mix->min_qp);
366    LOG_I( "mix->intra_period = %d\n",
367            mix->intra_period);
368    LOG_I( "mix->picture_width = %d\n",
369            mix->picture_width);
370    LOG_I( "mix->picture_height = %d\n",
371            mix->picture_height);
372    LOG_I( "mix->share_buf_mode = %d\n",
373            mix->share_buf_mode);
374    LOG_I( "mix->ci_frame_id = 0x%08x\n",
375            mix->ci_frame_id);
376    LOG_I( "mix->ci_frame_num = %d\n",
377            mix->ci_frame_num);
378    LOG_I( "mix->drawable = 0x%08x\n",
379            mix->drawable);
380    LOG_I( "mix->need_display = %d\n",
381            mix->need_display);
382    LOG_I( "mix->va_format = %d\n",
383            mix->va_format);
384    LOG_I( "mix->va_profile = %d\n",
385            mix->va_profile);
386    LOG_I( "mix->va_rcmode = %d\n\n",
387            mix->va_rcmode);
388
389    g_mutex_unlock(mix->objectlock);
390
391    LOG_V( "end\n");
392
393    return MIX_RESULT_SUCCESS;
394}
395
396static MIX_RESULT mix_videofmtenc_encode_default (MixVideoFormatEnc *mix, MixBuffer * bufin[],
397        gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
398        MixVideoEncodeParams * encode_params) {
399    return MIX_RESULT_SUCCESS;
400}
401
402static MIX_RESULT mix_videofmtenc_flush_default(MixVideoFormatEnc *mix) {
403    return MIX_RESULT_SUCCESS;
404}
405
406static MIX_RESULT mix_videofmtenc_eos_default(MixVideoFormatEnc *mix) {
407	return MIX_RESULT_SUCCESS;
408}
409
410static MIX_RESULT mix_videofmtenc_deinitialize_default(MixVideoFormatEnc *mix) {
411
412	//TODO decide whether to put any of the teardown from _finalize() here
413
414	return MIX_RESULT_SUCCESS;
415}
416
417static MIX_RESULT mix_videofmtenc_get_max_coded_buffer_size_default(
418	MixVideoFormatEnc *mix, guint *max_size) {
419
420
421	return MIX_RESULT_SUCCESS;
422}
423
424/* mixvideoformatenc class methods implementation */
425
426MIX_RESULT mix_videofmtenc_getcaps(MixVideoFormatEnc *mix, GString *msg) {
427    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
428
429    LOG_V( "Begin\n");
430
431    if (klass->getcaps) {
432        return klass->getcaps(mix, msg);
433    }
434    return MIX_RESULT_NOTIMPL;
435}
436
437MIX_RESULT mix_videofmtenc_initialize(MixVideoFormatEnc *mix,
438        MixVideoConfigParamsEnc * config_params_enc,
439        MixFrameManager * frame_mgr,
440        MixBufferPool * input_buf_pool,
441        MixSurfacePool ** surface_pool,
442        VADisplay va_display) {
443    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
444
445    /*frame_mgr and input_buf_pool is reserved for future use*/
446	if (klass->initialize) {
447        return klass->initialize(mix, config_params_enc, frame_mgr,
448                input_buf_pool, surface_pool, va_display);
449    }
450
451    return MIX_RESULT_FAIL;
452
453}
454
455MIX_RESULT mix_videofmtenc_encode(MixVideoFormatEnc *mix, MixBuffer * bufin[],
456        gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
457        MixVideoEncodeParams * encode_params) {
458
459    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
460    if (klass->encode) {
461        return klass->encode(mix, bufin, bufincnt, iovout, iovoutcnt, encode_params);
462    }
463
464    return MIX_RESULT_FAIL;
465}
466
467MIX_RESULT mix_videofmtenc_flush(MixVideoFormatEnc *mix) {
468    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
469    if (klass->flush) {
470        return klass->flush(mix);
471    }
472
473    return MIX_RESULT_FAIL;
474}
475
476MIX_RESULT mix_videofmtenc_eos(MixVideoFormatEnc *mix) {
477    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
478    if (klass->eos) {
479        return klass->eos(mix);
480    }
481
482    return MIX_RESULT_FAIL;
483}
484
485MIX_RESULT mix_videofmtenc_deinitialize(MixVideoFormatEnc *mix) {
486    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
487    if (klass->deinitialize) {
488        return klass->deinitialize(mix);
489    }
490
491    return MIX_RESULT_FAIL;
492}
493
494MIX_RESULT mix_videofmtenc_get_max_coded_buffer_size(MixVideoFormatEnc *mix, guint * max_size) {
495
496    MixVideoFormatEncClass *klass = MIX_VIDEOFORMATENC_GET_CLASS(mix);
497    if (klass->encode) {
498        return klass->getmaxencodedbufsize(mix, max_size);
499    }
500
501    return MIX_RESULT_FAIL;
502}
503