Update tizen 2.0 beta source
[framework/multimedia/gst-openmax.git] / 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 void
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   GST_OMX_BASE_FILTER_CLASS (parent_class)->process_input_buf (omx_base_filter, buf);
139 }
140
141 static void
142 print_tag (const GstTagList * list, const gchar * tag, gpointer data)
143 {
144   gint i, count;
145   GstOmxMpeg4Dec *self;
146
147   self = GST_OMX_MPEG4DEC (data);
148
149   count = gst_tag_list_get_tag_size (list, tag);
150
151   for (i = 0; i < count; i++) {
152     gchar *str;
153
154     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
155       if (!gst_tag_list_get_string_index (list, tag, i, &str))
156         g_assert_not_reached ();
157     } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) {
158       GstBuffer *img;
159
160       img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
161       if (img) {
162         gchar *caps_str;
163
164         caps_str = GST_BUFFER_CAPS (img) ?
165             gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
166         str = g_strdup_printf ("buffer of %u bytes, type: %s",
167             GST_BUFFER_SIZE (img), caps_str);
168         g_free (caps_str);
169       } else {
170         str = g_strdup ("NULL buffer");
171       }
172     } else {
173       str = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
174     }
175
176     if (i == 0) {
177       GST_LOG_OBJECT(self, "%16s: %s", gst_tag_get_nick (tag), str);
178
179       if (strcmp (gst_tag_get_nick(tag), "DRM DivX") == 0) {
180         if (self->drmContext == NULL) {
181           GST_LOG_OBJECT(self, "Init divx drm !!!!!!!!!!!!!!!!!!!! [%s]", str);
182           if (init_divx_drm (self)) {
183             GST_LOG_OBJECT(self, "omx_printtag_init_divx_drm() success");
184           } else {
185             GST_ERROR_OBJECT(self, "omx_printtag_init_divx_drm() failed");
186           }
187         } else {
188           GST_LOG_OBJECT(self, "Init divx drm is DONE before. so do nothing [%s]", str);
189         }
190       }
191     } else {
192       GST_LOG_OBJECT(self, "tag is not DRM Divx");
193     }
194
195     g_free (str);
196   }
197
198   GST_LOG_OBJECT(self, "print_tag End");
199 }
200
201 static gboolean
202 mpeg4_pad_event (GstPad * pad, GstEvent * event)
203 {
204   GstOmxMpeg4Dec *self;
205   gboolean ret = TRUE;
206
207   self = GST_OMX_MPEG4DEC (GST_OBJECT_PARENT (pad));
208
209   GST_LOG_OBJECT (self, "begin");
210
211   GST_INFO_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));
212
213   switch (GST_EVENT_TYPE (event)) {
214     case GST_EVENT_TAG:
215     {
216       GstTagList *taglist = NULL;
217
218       GST_LOG_OBJECT (self, "GST_EVENT_TAG");
219
220       gst_event_parse_tag (event, &taglist);
221       gst_tag_list_foreach (taglist, print_tag, self);
222       gst_event_unref (event);
223       ret= FALSE;
224       break;
225     }
226     default:
227       ret = TRUE;
228       break;
229   }
230   return ret;
231 }
232
233 static void
234 finalize (GObject * obj)
235 {
236   GstOmxMpeg4Dec *self;
237
238   self = GST_OMX_MPEG4DEC (obj);
239
240   GST_LOG_OBJECT (self, "mpeg4dec finalize enter");
241
242   if (self->drmContext)
243   {
244     self->divx_sym_table.finalize (self->drmContext);
245     free(self->drmContext);
246     self->drmContext = NULL;
247   }
248
249   if (self->divx_handle)
250   {
251     dlclose(self->divx_handle);
252     self->divx_handle = NULL;
253   }
254
255   G_OBJECT_CLASS (parent_class)->finalize (obj);
256 }
257
258 static void
259 type_base_init (gpointer g_class)
260 {
261   GstElementClass *element_class;
262
263   element_class = GST_ELEMENT_CLASS (g_class);
264
265   gst_element_class_set_details_simple (element_class,
266       "OpenMAX IL MPEG-4 video decoder",
267       "Codec/Decoder/Video",
268       "Decodes video in MPEG-4 format with OpenMAX IL", "Felipe Contreras");
269
270   gst_element_class_add_pad_template (element_class,
271       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
272           gstomx_template_caps (G_TYPE_FROM_CLASS (g_class), "sink")));
273
274   gst_element_class_add_pad_template (element_class,
275       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
276           gstomx_template_caps (G_TYPE_FROM_CLASS (g_class), "src")));
277 }
278
279 static void
280 type_class_init (gpointer g_class, gpointer class_data)
281 {
282   GObjectClass *gobject_class;
283   GstOmxBaseFilterClass *basefilter_class;
284
285   gobject_class = G_OBJECT_CLASS (g_class);
286   basefilter_class = GST_OMX_BASE_FILTER_CLASS (g_class);
287
288   gobject_class->finalize = finalize;
289   basefilter_class->process_input_buf = process_input_buf;
290 }
291
292 static void
293 type_instance_init (GTypeInstance * instance, gpointer g_class)
294 {
295   GstOmxBaseVideoDec *omx_base;
296   GstOmxBaseFilter *omx_base_filter;
297
298   omx_base = GST_OMX_BASE_VIDEODEC (instance);
299   omx_base_filter = GST_OMX_BASE_FILTER (instance);
300
301   omx_base_filter->pad_event = mpeg4_pad_event;
302   omx_base->compression_format = OMX_VIDEO_CodingMPEG4;
303 }