2 * Copyright (C) 2007-2009 Nokia Corporation.
4 * Author: Felipe Contreras <felipe.contreras@nokia.com>
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.
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.
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
22 #include "gstomx_mpeg4dec.h"
25 GSTOMX_BOILERPLATE (GstOmxMpeg4Dec, gst_omx_mpeg4dec, GstOmxBaseVideoDec,
26 GST_OMX_BASE_VIDEODEC_TYPE);
28 static gboolean init_divx_symbol (GstOmxMpeg4Dec * self)
30 GST_LOG_OBJECT (self, "mpeg4dec load_divx_symbol enter");
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());
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());
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());
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());
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());
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());
68 if (self->divx_handle) {
69 dlclose(self->divx_handle);
70 self->divx_handle = NULL;
77 init_divx_drm (GstOmxMpeg4Dec * self)
81 GST_LOG_OBJECT (self, "mpeg4dec init_divx_drm enter");
83 if (init_divx_symbol(self) == FALSE) {
84 GST_ERROR_OBJECT (self, "loading symbol failed....");
88 self->drmContext = self->divx_sym_table.init_decrypt (&error);
90 if (self->drmContext) {
91 GST_DEBUG_OBJECT (self, "%s init success: drmContext = %p\n", __func__, self->drmContext);
93 GST_ERROR_OBJECT (self, "%s failed to init... error code = %d \n", __func__, error);
97 error = self->divx_sym_table.commit (self->drmContext);
99 if (error == DRM_SUCCESS) {
100 GST_DEBUG_OBJECT (self, "%s commit success: drmContext = %p\n", __func__, self->drmContext);
102 GST_ERROR_OBJECT (self, "%s failed to commit... error code = %d \n", __func__, error);
110 if (self->drmContext)
112 self->divx_sym_table.finalize (self->drmContext);
113 free(self->drmContext);
114 self->drmContext = NULL;
121 process_input_buf (GstOmxBaseFilter * omx_base_filter, GstBuffer **buf)
123 GstOmxMpeg4Dec *self;
125 self = GST_OMX_MPEG4DEC (omx_base_filter);
127 GST_LOG_OBJECT (self, "mpeg4dec process_input_buf enter");
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));
134 GST_ERROR_OBJECT (self, "##### DivX DRM Mode ##### decrypt video failed : buffer = %d", GST_BUFFER_SIZE(*buf));
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); */
141 return GSTOMX_RETURN_OK;
145 print_tag (const GstTagList * list, const gchar * tag, gpointer data)
148 GstOmxMpeg4Dec *self;
150 self = GST_OMX_MPEG4DEC (data);
152 count = gst_tag_list_get_tag_size (list, tag);
154 for (i = 0; i < count; i++) {
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) {
163 img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
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);
173 str = g_strdup ("NULL buffer");
176 str = g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
180 GST_LOG_OBJECT(self, "%16s: %s", gst_tag_get_nick (tag), str);
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");
188 GST_ERROR_OBJECT(self, "omx_printtag_init_divx_drm() failed");
191 GST_LOG_OBJECT(self, "Init divx drm is DONE before. so do nothing [%s]", str);
195 GST_LOG_OBJECT(self, "tag is not DRM Divx");
201 GST_LOG_OBJECT(self, "print_tag End");
205 mpeg4_pad_event (GstPad * pad, GstEvent * event)
207 GstOmxMpeg4Dec *self;
210 self = GST_OMX_MPEG4DEC (GST_OBJECT_PARENT (pad));
212 GST_LOG_OBJECT (self, "begin");
214 GST_INFO_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));
216 switch (GST_EVENT_TYPE (event)) {
219 GstTagList *taglist = NULL;
221 GST_LOG_OBJECT (self, "GST_EVENT_TAG");
223 gst_event_parse_tag (event, &taglist);
224 gst_tag_list_foreach (taglist, print_tag, self);
225 gst_event_unref (event);
237 finalize (GObject * obj)
239 GstOmxMpeg4Dec *self;
241 self = GST_OMX_MPEG4DEC (obj);
243 GST_LOG_OBJECT (self, "mpeg4dec finalize enter");
245 if (self->drmContext)
247 self->divx_sym_table.finalize (self->drmContext);
248 free(self->drmContext);
249 self->drmContext = NULL;
252 if (self->divx_handle)
254 dlclose(self->divx_handle);
255 self->divx_handle = NULL;
258 G_OBJECT_CLASS (parent_class)->finalize (obj);
262 type_base_init (gpointer g_class)
264 GstElementClass *element_class;
266 element_class = GST_ELEMENT_CLASS (g_class);
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");
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")));
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")));
283 type_class_init (gpointer g_class, gpointer class_data)
285 GObjectClass *gobject_class;
286 GstOmxBaseFilterClass *basefilter_class;
288 gobject_class = G_OBJECT_CLASS (g_class);
289 basefilter_class = GST_OMX_BASE_FILTER_CLASS (g_class);
291 gobject_class->finalize = finalize;
292 basefilter_class->process_input_buf = process_input_buf;
296 type_instance_init (GTypeInstance * instance, gpointer g_class)
298 GstOmxBaseVideoDec *omx_base;
299 GstOmxBaseFilter *omx_base_filter;
301 omx_base = GST_OMX_BASE_VIDEODEC (instance);
302 omx_base_filter = GST_OMX_BASE_FILTER (instance);
304 omx_base_filter->pad_event = mpeg4_pad_event;
305 omx_base->compression_format = OMX_VIDEO_CodingMPEG4;