Initialize Tizen 2.3
[framework/multimedia/gst-openmax.git] / mobile / omx / gstomx_mpeg4dec.c
1 /*
2  * Copyright (C) 2007-2009 Nokia Corporation.
3  *
4  * Author: Felipe Contreras <felipe.contreras@nokia.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation
9  * version 2.1 of the License.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include "gstomx_mpeg4dec.h"
23 #include "gstomx.h"
24
25 GSTOMX_BOILERPLATE (GstOmxMpeg4Dec, gst_omx_mpeg4dec, GstOmxBaseVideoDec,
26     GST_OMX_BASE_VIDEODEC_TYPE);
27
28 static gboolean init_divx_symbol (GstOmxMpeg4Dec * self)
29 {
30   GST_LOG_OBJECT (self, "mpeg4dec load_divx_symbol enter");
31
32   self->divx_handle = dlopen (DIVX_SDK_PLUGIN_NAME, RTLD_LAZY);
33   if (!self->divx_handle) {
34     GST_ERROR_OBJECT (self, "dlopen failed [%s]", dlerror());
35     goto error_exit;
36   }
37
38   self->divx_sym_table.init_decrypt = dlsym (self->divx_handle, "divx_init_decrypt");
39   if (!self->divx_sym_table.init_decrypt) {
40     GST_ERROR_OBJECT (self, "loading divx_init_decrypt failed : %s", dlerror());
41     goto error_exit;
42   }
43   self->divx_sym_table.commit = dlsym (self->divx_handle, "divx_commit");
44   if (!self->divx_sym_table.commit) {
45     GST_ERROR_OBJECT (self, "loading divx_commit failed : %s", dlerror());
46     goto error_exit;
47   }
48   self->divx_sym_table.decrypt_video = dlsym (self->divx_handle, "divx_decrypt_video");
49   if (!self->divx_sym_table.decrypt_video) {
50     GST_ERROR_OBJECT (self, "loading divx_decrypt_video failed : %s", dlerror());
51     goto error_exit;
52   }
53   self->divx_sym_table.prepare_video_bitstream = dlsym (self->divx_handle, "divx_prepare_video_bitstream");
54   if (!self->divx_sym_table.prepare_video_bitstream) {
55     GST_ERROR_OBJECT (self, "loading divx_prepare_video_bitstream failed : %s", dlerror());
56     goto error_exit;
57   }
58   self->divx_sym_table.finalize = dlsym (self->divx_handle, "divx_finalize");
59   if (!self->divx_sym_table.finalize) {
60     GST_ERROR_OBJECT (self, "loading divx_finalize failed : %s", dlerror());
61     goto error_exit;
62   }
63
64   return TRUE;
65
66 error_exit:
67
68   if (self->divx_handle) {
69     dlclose(self->divx_handle);
70     self->divx_handle = NULL;
71   }
72
73   return FALSE;
74 }
75
76 static gboolean
77 init_divx_drm (GstOmxMpeg4Dec * self)
78 {
79   int error = 0;
80
81   GST_LOG_OBJECT (self, "mpeg4dec init_divx_drm enter");
82
83   if (init_divx_symbol(self) == FALSE) {
84     GST_ERROR_OBJECT (self, "loading symbol failed....");
85     goto error_exit;
86   }
87
88   self->drmContext = self->divx_sym_table.init_decrypt (&error);
89
90   if (self->drmContext) {
91     GST_DEBUG_OBJECT (self, "%s  init success: drmContext = %p\n", __func__, self->drmContext);
92   } else {
93     GST_ERROR_OBJECT (self, "%s  failed to init... error code = %d \n", __func__, error);
94     goto error_exit;
95   }
96
97   error = self->divx_sym_table.commit (self->drmContext);
98
99   if (error == DRM_SUCCESS) {
100     GST_DEBUG_OBJECT (self, "%s  commit success: drmContext = %p\n", __func__, self->drmContext);
101   } else {
102     GST_ERROR_OBJECT (self, "%s  failed to commit... error code = %d \n", __func__, error);
103     goto error_exit;
104   }
105
106   return TRUE;
107
108 error_exit:
109
110   if (self->drmContext)
111   {
112     self->divx_sym_table.finalize (self->drmContext);
113     free(self->drmContext);
114     self->drmContext = NULL;
115   }
116
117   return FALSE;
118 }
119
120 static GstOmxReturn
121 process_input_buf (GstOmxBaseFilter * omx_base_filter, GstBuffer **buf)
122 {
123   GstOmxMpeg4Dec *self;
124
125   self = GST_OMX_MPEG4DEC (omx_base_filter);
126
127   GST_LOG_OBJECT (self, "mpeg4dec process_input_buf enter");
128
129   /* decrypt DivX DRM buffer if this is DRM */
130   if (self->drmContext) {
131     if (DRM_SUCCESS == self->divx_sym_table.decrypt_video (self->drmContext, GST_BUFFER_DATA(*buf), GST_BUFFER_SIZE(*buf))) {
132       GST_DEBUG_OBJECT (self, "##### DivX DRM Mode ##### decrypt video success : buffer = %d", GST_BUFFER_SIZE(*buf));
133     } else {
134       GST_ERROR_OBJECT (self, "##### DivX DRM Mode ##### decrypt video failed : buffer = %d", GST_BUFFER_SIZE(*buf));
135     }
136   }
137
138 /* if you want to use commonly for videodec input, use this */
139 /*  GST_OMX_BASE_FILTER_CLASS (parent_class)->process_input_buf (omx_base_filter, buf); */
140
141   return GSTOMX_RETURN_OK;
142 }
143
144 static void
145 print_tag (const GstTagList * list, const gchar * tag, gpointer data)
146 {
147   gint i, count;
148   GstOmxMpeg4Dec *self;
149
150   self = GST_OMX_MPEG4DEC (data);
151
152   count = gst_tag_list_get_tag_size (list, tag);
153
154   for (i = 0; i < count; i++) {
155     gchar *str;
156
157     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
158       if (!gst_tag_list_get_string_index (list, tag, i, &str))
159         g_assert_not_reached ();
160     } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) {
161       GstBuffer *img;
162
163       img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
164       if (img) {
165         gchar *caps_str;
166
167         caps_str = GST_BUFFER_CAPS (img) ?
168             gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
169         str = g_strdup_printf ("buffer of %u bytes, type: %s",
170             GST_BUFFER_SIZE (img), caps_str);
171         g_free (caps_str);
172       } else {
173         str = g_strdup ("NULL buffer");
174       }
175     } else {
176       str = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
177     }
178
179     if (i == 0) {
180       GST_LOG_OBJECT(self, "%16s: %s", gst_tag_get_nick (tag), str);
181
182       if (strcmp (gst_tag_get_nick(tag), "DRM DivX") == 0) {
183         if (self->drmContext == NULL) {
184           GST_LOG_OBJECT(self, "Init divx drm !!!!!!!!!!!!!!!!!!!! [%s]", str);
185           if (init_divx_drm (self)) {
186             GST_LOG_OBJECT(self, "omx_printtag_init_divx_drm() success");
187           } else {
188             GST_ERROR_OBJECT(self, "omx_printtag_init_divx_drm() failed");
189           }
190         } else {
191           GST_LOG_OBJECT(self, "Init divx drm is DONE before. so do nothing [%s]", str);
192         }
193       }
194     } else {
195       GST_LOG_OBJECT(self, "tag is not DRM Divx");
196     }
197
198     g_free (str);
199   }
200
201   GST_LOG_OBJECT(self, "print_tag End");
202 }
203
204 static gboolean
205 mpeg4_pad_event (GstPad * pad, GstEvent * event)
206 {
207   GstOmxMpeg4Dec *self;
208   gboolean ret = TRUE;
209
210   self = GST_OMX_MPEG4DEC (GST_OBJECT_PARENT (pad));
211
212   GST_LOG_OBJECT (self, "begin");
213
214   GST_INFO_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));
215
216   switch (GST_EVENT_TYPE (event)) {
217     case GST_EVENT_TAG:
218     {
219       GstTagList *taglist = NULL;
220
221       GST_LOG_OBJECT (self, "GST_EVENT_TAG");
222
223       gst_event_parse_tag (event, &taglist);
224       gst_tag_list_foreach (taglist, print_tag, self);
225       gst_event_unref (event);
226       ret= FALSE;
227       break;
228     }
229     default:
230       ret = TRUE;
231       break;
232   }
233   return ret;
234 }
235
236 static void
237 finalize (GObject * obj)
238 {
239   GstOmxMpeg4Dec *self;
240
241   self = GST_OMX_MPEG4DEC (obj);
242
243   GST_LOG_OBJECT (self, "mpeg4dec finalize enter");
244
245   if (self->drmContext)
246   {
247     self->divx_sym_table.finalize (self->drmContext);
248     free(self->drmContext);
249     self->drmContext = NULL;
250   }
251
252   if (self->divx_handle)
253   {
254     dlclose(self->divx_handle);
255     self->divx_handle = NULL;
256   }
257
258   G_OBJECT_CLASS (parent_class)->finalize (obj);
259 }
260
261 static void
262 type_base_init (gpointer g_class)
263 {
264   GstElementClass *element_class;
265
266   element_class = GST_ELEMENT_CLASS (g_class);
267
268   gst_element_class_set_details_simple (element_class,
269       "OpenMAX IL MPEG-4 video decoder",
270       "Codec/Decoder/Video",
271       "Decodes video in MPEG-4 format with OpenMAX IL", "Felipe Contreras");
272
273   gst_element_class_add_pad_template (element_class,
274       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
275           gstomx_template_caps (G_TYPE_FROM_CLASS (g_class), "sink")));
276
277   gst_element_class_add_pad_template (element_class,
278       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
279           gstomx_template_caps (G_TYPE_FROM_CLASS (g_class), "src")));
280 }
281
282 static void
283 type_class_init (gpointer g_class, gpointer class_data)
284 {
285   GObjectClass *gobject_class;
286   GstOmxBaseFilterClass *basefilter_class;
287
288   gobject_class = G_OBJECT_CLASS (g_class);
289   basefilter_class = GST_OMX_BASE_FILTER_CLASS (g_class);
290
291   gobject_class->finalize = finalize;
292   basefilter_class->process_input_buf = process_input_buf;
293 }
294
295 static void
296 type_instance_init (GTypeInstance * instance, gpointer g_class)
297 {
298   GstOmxBaseVideoDec *omx_base;
299   GstOmxBaseFilter *omx_base_filter;
300
301   omx_base = GST_OMX_BASE_VIDEODEC (instance);
302   omx_base_filter = GST_OMX_BASE_FILTER (instance);
303
304   omx_base_filter->pad_event = mpeg4_pad_event;
305   omx_base->compression_format = OMX_VIDEO_CodingMPEG4;
306 }