4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
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)
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.
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
27 #include "gstdrmsrc.h"
29 #define LOG_TRACE(message) //g_print("DRM_SRC: %s: %d: %s - %s \n", __FILE__, __LINE__, __FUNCTION__, message);
31 #define GST_TAG_PLAYREADY "playready_file_path"
33 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);
36 GST_DEBUG_CATEGORY_STATIC (gst_drm_src_debug);
37 #define GST_CAT_DEFAULT gst_drm_src_debug
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);
56 * This function does the following:
57 * 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
59 * @param drmsrc_type [out] GType
63 static void _do_init (GType drmsrc_type)
65 // 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
66 static const GInterfaceInfo urihandler_info = {
67 gst_drm_src_uri_handler_init,
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");
75 GST_BOILERPLATE_FULL (GstDrmSrc, gst_drm_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init);
77 * This function does the following:
78 * 1. Sets the class details
79 * 2. Adds the source pad template
81 * @param g_class [out] gpointer
85 static void gst_drm_src_base_init (gpointer g_class)
87 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
88 // 1. Sets the class details
89 gst_element_class_set_details_simple (gstelement_class,
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));
98 * This function does the following:
99 * 1. Installs the properties
100 * 2. Assigns the function pointers GObject class attributes
102 * @param klass [out] GstDrmSrcClass Structure
106 static void gst_drm_src_class_init (GstDrmSrcClass * klass)
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,
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));
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);
135 gst_tag_register (GST_TAG_PLAYREADY, GST_TAG_FLAG_META,
137 "PlayReady File Path",
138 "a tag that is specific to PlayReady File",
142 * This function does the following:
143 * 1. Initilizes the parameters of GstDrmSrc
145 * @param src [out] GstDrmSrc structure
146 * @param g_class [in] GstDrmSrcClass structure
148 * @return gboolean Returns TRUE on success and FALSE on ERROR
150 static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
152 // 1. Initilizes the parameters of GstDrmSrc
153 src->filename = NULL;
156 src->is_regular = FALSE;
157 src->seekable = FALSE;
161 * This function does the following:
162 * 1. deallocates the filename and uri
163 * 2. calls the parent class->finalize
165 * @param object [in] GObject Structure
169 static void gst_drm_src_finalize (GObject * object)
173 src = GST_DRM_SRC (object);
174 // 1. deallocates the filename and uri
175 g_free (src->filename);
177 // 2. calls the parent class->finalize
178 G_OBJECT_CLASS (parent_class)->finalize (object);
181 * This function does the following:
182 * 1. Checks the state
183 * 2. Checks the filename
184 * 3. Sets the filename
186 * @param src [in] GstDrmSrc Structure
187 * @param location [in] location of the file
189 * @return gboolean Returns TRUE on success and FALSE on ERROR
191 static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * location)
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)
200 GST_DEBUG_OBJECT (src, "setting location in wrong state");
201 GST_OBJECT_UNLOCK (src);
204 GST_OBJECT_UNLOCK (src);
205 g_free (src->filename);
207 // 2. Checks the filename
208 if (location == NULL)
210 src->filename = NULL;
215 // 3. Sets the filename
216 src->filename = g_strdup (location);
217 src->uri = gst_uri_construct ("file", src->filename);
219 g_object_notify (G_OBJECT (src), "location");
220 gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
224 * This function does the following:
225 * 1. Sets the location of the file.
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
234 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
238 g_return_if_fail (GST_IS_DRM_SRC (object));
239 src = GST_DRM_SRC (object);
242 // 1. Sets the location of the file.
244 gst_drm_src_set_location (src, g_value_get_string (value));
247 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
252 * This function does the following:
253 * 1. Provides the location of the file.
254 * 2. Provides the file descriptor.
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
263 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value,GParamSpec * pspec)
267 g_return_if_fail (GST_IS_DRM_SRC (object));
268 src = GST_DRM_SRC (object);
271 // 1. Provides the location of the file.
273 g_value_set_string (value, src->filename);
275 // 2. Provides the file descriptor.
277 g_value_set_int (value, src->fd);
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
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
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
296 * @return GstFlowReturn Returns GST_FLOW_OK on success and ERROR on failure
298 static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
302 // 1. Seeks to the specified position.
303 if (G_UNLIKELY (src->read_position != offset))
306 res = lseek (src->fd, offset, SEEK_SET);
307 if (G_UNLIKELY (res < 0 || res != offset))
309 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
310 return GST_FLOW_ERROR;
312 src->read_position = offset;
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))
321 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
322 gst_buffer_unref (buf);
323 return GST_FLOW_ERROR;
325 if (G_UNLIKELY ((guint) ret < length && src->seekable))
327 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),("unexpected end of file."));
328 gst_buffer_unref (buf);
329 return GST_FLOW_ERROR;
331 if (G_UNLIKELY (ret == 0 && length > 0))
333 GST_DEBUG ("non-regular file hits EOS");
334 gst_buffer_unref (buf);
335 return GST_FLOW_UNEXPECTED;
338 GST_BUFFER_SIZE (buf) = length;
339 GST_BUFFER_OFFSET (buf) = offset;
340 GST_BUFFER_OFFSET_END (buf) = offset + length;
342 src->read_position += length;
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.
350 * @param basesrc [in] BaseSrc Structure
351 * @param size [out] Size of the file
353 * @return gboolean Returns TRUE on success and FALSE on ERROR
355 static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
357 GstDrmSrc *src = GST_DRM_SRC (basesrc);
359 // 1. Calls DRM file read chain method for drm files.
361 // 2. Calls normal file read chain method for standard files.
362 return gst_drm_src_create_read (src, offset, length, buffer);
366 * @param basesrc [in] BaseSrc Structure
368 * @return gboolean Returns TRUE if the file is seekable and FALSE if the file is not seekable
370 static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
372 GstDrmSrc *src = GST_DRM_SRC (basesrc);
373 return src->seekable;
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
380 * @param basesrc [in] BaseSrc Structure
381 * @param size [in] Size of the file
383 * @return gboolean Returns TRUE on success and FALSE on ERROR
385 static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
387 struct stat stat_results;
388 GstDrmSrc *src = GST_DRM_SRC (basesrc);
391 // 1. Gets the filesize for drm file by using seek oprations
393 // 2. Gets the file size for standard file by using statistics
394 if (fstat (src->fd, &stat_results) < 0)
396 *size = stat_results.st_size;
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
405 * @param basesrc [in] BaseSrc Structure
407 * @return gboolean Returns TRUE on success and FALSE on ERROR
409 static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
411 GstDrmSrc *src = GST_DRM_SRC (basesrc);
412 struct stat stat_results;
415 // 1. Checks the filename
416 if (src->filename == NULL || src->filename[0] == '\0')
418 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,("No file name specified for reading."), (NULL));
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);
428 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
431 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
434 if (fstat (src->fd, &stat_results) < 0)
436 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not get info on \"%s\".", src->filename), (NULL));
440 if (S_ISDIR (stat_results.st_mode))
442 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
446 if (S_ISSOCK (stat_results.st_mode))
448 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
452 src->read_position = 0;
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);
460 GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
461 "failed: %s", g_strerror (errno));
462 src->seekable = FALSE;
466 src->seekable = TRUE;
468 lseek (src->fd, 0, SEEK_SET);
469 src->seekable = src->seekable && src->is_regular;
474 * This function does the following:
475 * 1. Closes the file desciptor and resets the flags
477 * @param basesrc [in] BaseSrc Structure
479 * @return gboolean Returns TRUE on success and FALSE on ERROR
481 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
483 GstDrmSrc *src = GST_DRM_SRC (basesrc);
485 // 1. Closes the file desciptor and resets the flags
489 src->is_regular = FALSE;
490 // PROFILE_SHOW_RESULT;
497 * @return GstURIType Returns GST_URI_SRC
500 static GstURIType gst_drm_src_uri_get_type (void)
506 * This function does the following:
507 * 1. Defines the list of protocols
511 * @return gchar ** Returns the protocol list
514 static gchar ** gst_drm_src_uri_get_protocols (void)
516 static gchar *protocols[] = { "file", NULL };
521 * @param handler [in] GstURIHandler structure
523 * @return gchar* Returns the uri
525 static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
527 GstDrmSrc *src = GST_DRM_SRC (handler);
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
536 * @param handler [in] GstURIHandler structure
537 * @param uri [in] uri string
539 * @return gboolean Returns TRUE on success and FALSE on Error
541 static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * uri)
543 gchar *protocol, *location;
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)
554 if (g_str_has_prefix (uri, "file://localhost/"))
557 tmp = g_strconcat ("file://", uri + 16, NULL);
558 location = gst_uri_get_location (tmp);
561 else if (strcmp (uri, "file://") == 0)
563 gst_drm_src_set_location (src, NULL);
568 location = gst_uri_get_location (uri);
572 // 2. Checks the whether it is absolute or not
573 if (!g_path_is_absolute (location))
578 // 3 sets the location
579 ret = gst_drm_src_set_location (src, location);
584 * This function does the following:
585 * 1. Assignes the function pointer for URI related stuff
587 * @param g_iface [in] an interface to URI handler
588 * @param iface_data [in] a gpointer
592 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
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;
602 * This function does the following:
603 * 1. Registers an element as drmsrc
605 * @param i_pPlugin [in] a plug-in structure
607 * @return gboolean TRUE on SUCCESS and FALSE on Error
609 static gboolean plugin_init(GstPlugin* i_pPlugin)
611 return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);;
614 * This function does the following:
615 * 1. plugin defination
618 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
621 "Plugin to read data from standad/DRM File",
625 "Samsung Electronics Co",
626 "http://www.samsung.com/")