tizen 2.0 init
[framework/multimedia/gst-plugins-ext0.10.git] / drmsrc / src / gstdrmsrc.c
1 /*
2  * drmsrc
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the
10  * Free Software Foundation; either version 2.1 of the License, or (at your option)
11  * any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation, Inc., 51
20  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 #include "gstdrmsrc.h"
28
29 #define LOG_TRACE(message)  //g_print("DRM_SRC: %s: %d: %s - %s \n", __FILE__, __LINE__, __FUNCTION__, message);
30
31 #define GST_TAG_PLAYREADY "playready_file_path"
32
33 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);
34
35
36 GST_DEBUG_CATEGORY_STATIC (gst_drm_src_debug);
37 #define GST_CAT_DEFAULT gst_drm_src_debug
38
39 enum
40 {
41         ARG_0,
42         ARG_LOCATION,
43         ARG_FD
44 };
45 static void gst_drm_src_finalize (GObject * object);
46 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
47 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
48 static gboolean gst_drm_src_start (GstBaseSrc * basesrc);
49 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc);
50 static gboolean gst_drm_src_is_seekable (GstBaseSrc * src);
51 static gboolean gst_drm_src_get_size (GstBaseSrc * src, guint64 * size);
52 static GstFlowReturn gst_drm_src_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buffer);
53 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
54
55 /**
56  * This function does the following:
57  *  1. Initializes GstDrmSrc ( defines gst_drm_get_type)
58  *
59  * @param   drmsrc_type    [out]  GType
60  *
61  * @return  void
62  */
63 static void _do_init (GType drmsrc_type)
64 {
65        // 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
66         static const GInterfaceInfo urihandler_info = {
67                 gst_drm_src_uri_handler_init,
68                 NULL,
69                 NULL
70         };
71
72         g_type_add_interface_static (drmsrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
73         GST_DEBUG_CATEGORY_INIT (gst_drm_src_debug, "drmsrc", 0, "drmsrc element");
74 }
75 GST_BOILERPLATE_FULL (GstDrmSrc, gst_drm_src, GstBaseSrc, GST_TYPE_BASE_SRC,   _do_init);
76 /**
77  * This function does the following:
78  *  1. Sets the class details
79  *  2. Adds the source pad template
80  *
81  * @param   g_class    [out]   gpointer
82  *
83  * @return  void
84  */
85 static void gst_drm_src_base_init (gpointer g_class)
86 {
87         GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
88         // 1. Sets the class details
89         gst_element_class_set_details_simple (gstelement_class,
90                 "DRM Source",
91                 "Source/File",
92                 "Read from arbitrary point in a standard/DRM file",
93                 "Kishore Arepalli  <kishore.a@samsung.com> and Sadanand Dodawadakar <sadanand.d@samsung.com>");
94       // 2. Adds the source pad template
95         gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
96 }
97 /**
98  * This function does the following:
99  *  1. Installs the properties
100  *  2. Assigns the function pointers GObject class attributes
101  *
102  * @param   klass    [out]   GstDrmSrcClass Structure
103  *
104  * @return  void
105  */
106 static void gst_drm_src_class_init (GstDrmSrcClass * klass)
107 {
108         GObjectClass *gobject_class;
109         GstElementClass *gstelement_class;
110         GstBaseSrcClass *gstbasesrc_class;
111         gobject_class = G_OBJECT_CLASS (klass);
112         gstelement_class = GST_ELEMENT_CLASS (klass);
113         gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
114         // Assigns the function pointers GObject class attributes
115         gobject_class->set_property = gst_drm_src_set_property;
116         gobject_class->get_property = gst_drm_src_get_property;
117         //  1. Installs the properties
118         g_object_class_install_property (gobject_class, ARG_FD,
119                 g_param_spec_int ("fd", "File-descriptor",
120                 "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
121                 G_PARAM_READABLE));
122         g_object_class_install_property (gobject_class, ARG_LOCATION,
123                 g_param_spec_string ("location", "File Location",
124                 "Location of the file to read", NULL, G_PARAM_READWRITE));
125
126         // 2. Assigns the function pointers GObject class attributes
127         gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_drm_src_finalize);
128         gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_drm_src_start);
129         gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_drm_src_stop);
130         gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_drm_src_is_seekable);
131         gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_drm_src_get_size);
132         gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_drm_src_create);
133
134
135         gst_tag_register (GST_TAG_PLAYREADY, GST_TAG_FLAG_META,
136                         G_TYPE_STRING,
137                         "PlayReady File Path",
138                         "a tag that is specific to PlayReady File",
139                         NULL);
140 }
141 /**
142  * This function does the following:
143  *  1. Initilizes the parameters of GstDrmSrc
144  *
145  * @param   src    [out]   GstDrmSrc structure
146  * @param   g_class    [in]   GstDrmSrcClass structure
147  *
148  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
149  */
150 static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
151 {
152         // 1. Initilizes the parameters of GstDrmSrc
153         src->filename = NULL;
154         src->fd = 0;
155         src->uri = NULL;
156         src->is_regular = FALSE;
157         src->seekable = FALSE;
158         PROFILE_INIT;
159 }
160 /**
161  * This function does the following:
162  *  1. deallocates the filename and uri
163  *  2. calls the parent class->finalize
164  *
165  * @param   object    [in]   GObject Structure
166  *
167  * @return  void
168  */
169 static void gst_drm_src_finalize (GObject * object)
170 {
171         GstDrmSrc *src;
172
173         src = GST_DRM_SRC (object);
174         //  1. deallocates the filename and uri
175         g_free (src->filename);
176         g_free (src->uri);
177         // 2. calls the parent class->finalize
178         G_OBJECT_CLASS (parent_class)->finalize (object);
179 }
180 /**
181  * This function does the following:
182  *  1. Checks the state
183  *  2. Checks the filename
184  *  3. Sets the filename
185  *
186  * @param   src    [in]   GstDrmSrc Structure
187  * @param   location    [in]   location of the file
188  *
189  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
190  */
191 static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * location)
192 {
193         GstState state;
194
195         GST_OBJECT_LOCK (src);
196         //  1. Checks the state
197         state = GST_STATE (src);
198         if (state != GST_STATE_READY && state != GST_STATE_NULL)
199         {
200                 GST_DEBUG_OBJECT (src, "setting location in wrong state");
201                 GST_OBJECT_UNLOCK (src);
202                 return FALSE;
203         }
204         GST_OBJECT_UNLOCK (src);
205         g_free (src->filename);
206         g_free (src->uri);
207         //  2. Checks the filename
208         if (location == NULL)
209         {
210                 src->filename = NULL;
211                 src->uri = NULL;
212         }
213         else
214         {
215                 // 3. Sets the filename
216                 src->filename = g_strdup (location);
217                 src->uri = gst_uri_construct ("file", src->filename);
218         }
219         g_object_notify (G_OBJECT (src), "location");
220         gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
221         return TRUE;
222 }
223 /**
224  * This function does the following:
225  *  1. Sets the location of the file.
226  *
227  * @param   object    [in]   GObject Structure
228  * @param   prop_id    [in]   id of the property
229  * @param   value    [in]   property value
230  * @param   pspec    [in]  GParamSpec Structure
231  *
232  * @return  void
233  */
234 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
235 {
236         GstDrmSrc *src;
237
238         g_return_if_fail (GST_IS_DRM_SRC (object));
239         src = GST_DRM_SRC (object);
240         switch (prop_id)
241         {
242                 //  1. Sets the location of the file.
243                 case ARG_LOCATION:
244                         gst_drm_src_set_location (src, g_value_get_string (value));
245                         break;
246                 default:
247                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
248                         break;
249         }
250 }
251 /**
252  * This function does the following:
253  *  1. Provides the location of the file.
254  *  2. Provides the file descriptor.
255  *
256  * @param   object    [in]   GObject Structure
257  * @param   prop_id    [in]   id of the property
258  * @param   value    [out]   property value
259  * @param   pspec    [in]  GParamSpec Structure
260  *
261  * @return  void
262  */
263 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value,GParamSpec * pspec)
264 {
265         GstDrmSrc *src;
266
267         g_return_if_fail (GST_IS_DRM_SRC (object));
268         src = GST_DRM_SRC (object);
269         switch (prop_id)
270         {
271                 //  1. Provides the location of the file.
272                 case ARG_LOCATION:
273                         g_value_set_string (value, src->filename);
274                         break;
275                 // 2. Provides the file descriptor.
276                 case ARG_FD:
277                         g_value_set_int (value, src->fd);
278                         break;
279                 default:
280                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
281                         break;
282         }
283 }
284
285 /**
286  * This function does the following:
287  *  1. Seeks to the specified position.
288  *  2. Allocates a buffer to push the data
289  *  3. Reads from the file and sets the related params
290  *
291  * @param   src    [in]   GstDrmSrc Structure
292  * @param   offset    [in]   offset of the file to seek
293  * @param   length    [in]   size of the data in bytes
294  * @param   buffer    [out]   GstBuffer to hold the contents
295  *
296  * @return  GstFlowReturn   Returns GST_FLOW_OK on success and ERROR on failure
297  */
298 static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
299 {
300         int ret;
301         GstBuffer *buf;
302         // 1. Seeks to the specified position.
303         if (G_UNLIKELY (src->read_position != offset))
304         {
305                 off_t res;
306                 res = lseek (src->fd, offset, SEEK_SET);
307                 if (G_UNLIKELY (res < 0 || res != offset))
308                 {
309                         GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
310                         return GST_FLOW_ERROR;
311                 }
312                 src->read_position = offset;
313         }
314         // 2. Allocates a buffer to push the data
315         buf = gst_buffer_new_and_alloc (length);
316         GST_LOG_OBJECT (src, "Reading %d bytes", length);
317         // 3. Reads from the file and sets the related params
318         ret = read (src->fd, GST_BUFFER_DATA (buf), length);
319         if (G_UNLIKELY (ret < 0))
320         {
321                 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
322                 gst_buffer_unref (buf);
323                 return GST_FLOW_ERROR;
324         }
325         if (G_UNLIKELY ((guint) ret < length && src->seekable))
326         {
327                 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),("unexpected end of file."));
328                 gst_buffer_unref (buf);
329                 return GST_FLOW_ERROR;
330         }
331         if (G_UNLIKELY (ret == 0 && length > 0))
332         {
333                 GST_DEBUG ("non-regular file hits EOS");
334                 gst_buffer_unref (buf);
335                 return GST_FLOW_UNEXPECTED;
336         }
337         length = ret;
338         GST_BUFFER_SIZE (buf) = length;
339         GST_BUFFER_OFFSET (buf) = offset;
340         GST_BUFFER_OFFSET_END (buf) = offset + length;
341         *buffer = buf;
342         src->read_position += length;
343         return GST_FLOW_OK;
344 }
345 /**
346  * This function does the following:
347  *  1. Calls DRM file read chain method for drm files.
348  *  2. Calls normal file read chain method for standard files.
349  *
350  * @param   basesrc    [in]   BaseSrc Structure
351  * @param   size    [out]   Size of the file
352  *
353  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
354  */
355 static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
356 {
357         GstDrmSrc *src = GST_DRM_SRC (basesrc);
358
359         // 1. Calls DRM file read chain method for drm files.
360
361         // 2. Calls normal file read chain method for standard files.
362         return gst_drm_src_create_read (src, offset, length, buffer);
363 }
364 /**
365  *
366  * @param   basesrc    [in]   BaseSrc Structure
367  *
368  * @return  gboolean   Returns TRUE if the file is seekable and FALSE if the file is not seekable
369  */
370 static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
371 {
372         GstDrmSrc *src = GST_DRM_SRC (basesrc);
373         return src->seekable;
374 }
375 /**
376  * This function does the following:
377  *  1. Gets the filesize for drm file by using seek oprations
378  *  2. Gets the file size for standard file by using statistics
379  *
380  * @param   basesrc    [in]   BaseSrc Structure
381  * @param   size    [in]   Size of the file
382  *
383  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
384  */
385 static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
386 {
387         struct stat stat_results;
388         GstDrmSrc *src = GST_DRM_SRC (basesrc);
389         unsigned int offset;
390
391         //  1. Gets the filesize for drm file by using seek oprations
392
393         // 2. Gets the file size for standard file by using statistics
394         if (fstat (src->fd, &stat_results) < 0)
395                 return FALSE;
396         *size = stat_results.st_size;
397         return TRUE;
398 }
399 /**
400  * This function does the following:
401  *  1. Checks the filename
402  *  2. Opens the file and check statistics of the file
403  *  7. Checks the seeking for standard files
404  *
405  * @param   basesrc    [in]   BaseSrc Structure
406  *
407  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
408  */
409 static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
410 {
411         GstDrmSrc *src = GST_DRM_SRC (basesrc);
412         struct stat stat_results;
413         off_t ret;
414 PROFILE_FUNC_BEGIN;
415         // 1. Checks the filename
416         if (src->filename == NULL || src->filename[0] == '\0')
417         {
418                 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,("No file name specified for reading."), (NULL));
419                 return FALSE;
420         }
421         // 2. Opens the file and check statistics of the file
422         GST_INFO_OBJECT (src, "opening file %s", src->filename);
423         src->fd = open (src->filename, O_RDONLY | O_BINARY);
424         if (src->fd < 0)
425         {
426                 if(errno == ENOENT)
427                 {
428                         GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
429                         return FALSE;
430                 }
431                 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
432                 return FALSE;
433         }
434         if (fstat (src->fd, &stat_results) < 0)
435         {
436                 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not get info on \"%s\".", src->filename), (NULL));
437                 close (src->fd);
438                 return FALSE;
439         }
440         if (S_ISDIR (stat_results.st_mode))
441         {
442                 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
443                 close (src->fd);
444                 return FALSE;
445         }
446         if (S_ISSOCK (stat_results.st_mode))
447         {
448                 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
449                 close (src->fd);
450                 return FALSE;
451         }
452         src->read_position = 0;
453
454         // 7. Checks the seeking for standard files
455         if (S_ISREG (stat_results.st_mode))
456                 src->is_regular = TRUE;
457         ret = lseek (src->fd, 0, SEEK_END);
458         if (ret < 0)
459         {
460                 GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
461                         "failed: %s", g_strerror (errno));
462                 src->seekable = FALSE;
463         }
464         else
465         {
466                 src->seekable = TRUE;
467         }
468         lseek (src->fd, 0, SEEK_SET);
469         src->seekable = src->seekable && src->is_regular;
470         PROFILE_FUNC_END;
471         return TRUE;
472 }
473 /**
474  * This function does the following:
475  *  1. Closes the file desciptor and resets the flags
476  *
477  * @param   basesrc    [in]   BaseSrc Structure
478  *
479  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
480  */
481 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
482 {
483         GstDrmSrc *src = GST_DRM_SRC (basesrc);
484
485         // 1. Closes the file desciptor and resets the flags
486         if(src->fd > 0)
487                 close (src->fd);
488         src->fd = 0;
489         src->is_regular = FALSE;
490 //      PROFILE_SHOW_RESULT;
491         return TRUE;
492 }
493 /**
494  *
495  * @param   void
496  *
497  * @return  GstURIType   Returns GST_URI_SRC
498  */
499
500 static GstURIType gst_drm_src_uri_get_type (void)
501 {
502         return GST_URI_SRC;
503 }
504
505 /**
506  * This function does the following:
507  *  1. Defines the list of protocols
508  *
509  * @param   void
510  *
511  * @return  gchar **   Returns the protocol list
512  */
513
514 static gchar ** gst_drm_src_uri_get_protocols (void)
515 {
516         static gchar *protocols[] = { "file", NULL };
517         return protocols;
518 }
519 /**
520  *
521  * @param   handler [in] GstURIHandler structure
522  *
523  * @return  gchar*   Returns the uri
524  */
525 static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
526 {
527         GstDrmSrc *src = GST_DRM_SRC (handler);
528         return src->uri;
529 }
530 /**
531  * This function does the following:
532  *  1. Checks the protocol
533  *  2. Checks the whether it is absolute or not
534  *  3 sets the location
535  *
536  * @param   handler [in] GstURIHandler structure
537  * @param   uri [in] uri string
538  *
539  * @return  gboolean   Returns TRUE on success and FALSE on Error
540  */
541 static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * uri)
542 {
543         gchar *protocol, *location;
544         gboolean ret;
545         GstDrmSrc *src = GST_DRM_SRC (handler);
546         // 1. Checks the protocol
547         protocol = gst_uri_get_protocol (uri);
548         if (strcmp (protocol, "file") != 0)
549         {
550                 g_free (protocol);
551                 return FALSE;
552         }
553         g_free (protocol);
554         if (g_str_has_prefix (uri, "file://localhost/"))
555         {
556                 char *tmp;
557                 tmp = g_strconcat ("file://", uri + 16, NULL);
558                 location = gst_uri_get_location (tmp);
559                 g_free (tmp);
560         }
561         else if (strcmp (uri, "file://") == 0)
562         {
563                 gst_drm_src_set_location (src, NULL);
564                 return TRUE;
565         }
566         else
567         {
568                 location = gst_uri_get_location (uri);
569         }
570         if (!location)
571                 return FALSE;
572         // 2. Checks the whether it is absolute or not
573         if (!g_path_is_absolute (location))
574         {
575                 g_free (location);
576                 return FALSE;
577         }
578         // 3 sets the location
579         ret = gst_drm_src_set_location (src, location);
580         g_free (location);
581         return ret;
582 }
583 /**
584  * This function does the following:
585  *  1. Assignes the function pointer for URI related stuff
586  *
587  * @param   g_iface [in] an interface to URI handler
588  * @param   iface_data [in] a gpointer
589  *
590  * @return  void
591  */
592 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
593 {
594         GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
595         // 1. Assigning the function pointer for URI related stuff
596         iface->get_type = gst_drm_src_uri_get_type;
597         iface->get_protocols = gst_drm_src_uri_get_protocols;
598         iface->get_uri = gst_drm_src_uri_get_uri;
599         iface->set_uri = gst_drm_src_uri_set_uri;
600 }
601 /**
602  * This function does the following:
603  *  1. Registers an element as drmsrc
604  *
605  * @param   i_pPlugin [in] a plug-in structure
606  *
607  * @return  gboolean TRUE on SUCCESS and FALSE on Error
608  */
609 static gboolean plugin_init(GstPlugin* i_pPlugin)
610 {
611         return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);;
612 }
613 /**
614  * This function does the following:
615  *  1. plugin defination
616  *
617  */
618 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
619                                                  GST_VERSION_MINOR,
620                                                  "drmsrc",
621                                                  "Plugin to read data from standad/DRM File",
622                                                  plugin_init,
623                                                  VERSION,
624                                                  "LGPL",
625                                                  "Samsung Electronics Co",
626                                                  "http://www.samsung.com/")
627