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 GstBaseSrcClass *gstbasesrc_class;
110 gobject_class = G_OBJECT_CLASS (klass);
111 gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
112 // Assigns the function pointers GObject class attributes
113 gobject_class->set_property = gst_drm_src_set_property;
114 gobject_class->get_property = gst_drm_src_get_property;
115 // 1. Installs the properties
116 g_object_class_install_property (gobject_class, ARG_FD,
117 g_param_spec_int ("fd", "File-descriptor",
118 "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
120 g_object_class_install_property (gobject_class, ARG_LOCATION,
121 g_param_spec_string ("location", "File Location",
122 "Location of the file to read", NULL, G_PARAM_READWRITE));
124 // 2. Assigns the function pointers GObject class attributes
125 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_drm_src_finalize);
126 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_drm_src_start);
127 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_drm_src_stop);
128 gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_drm_src_is_seekable);
129 gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_drm_src_get_size);
130 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_drm_src_create);
133 gst_tag_register (GST_TAG_PLAYREADY, GST_TAG_FLAG_META,
135 "PlayReady File Path",
136 "a tag that is specific to PlayReady File",
140 * This function does the following:
141 * 1. Initilizes the parameters of GstDrmSrc
143 * @param src [out] GstDrmSrc structure
144 * @param g_class [in] GstDrmSrcClass structure
146 * @return gboolean Returns TRUE on success and FALSE on ERROR
148 static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
150 // 1. Initilizes the parameters of GstDrmSrc
151 src->filename = NULL;
154 src->is_regular = FALSE;
155 src->seekable = FALSE;
159 * This function does the following:
160 * 1. deallocates the filename and uri
161 * 2. calls the parent class->finalize
163 * @param object [in] GObject Structure
167 static void gst_drm_src_finalize (GObject * object)
171 src = GST_DRM_SRC (object);
172 // 1. deallocates the filename and uri
173 g_free (src->filename);
175 // 2. calls the parent class->finalize
176 G_OBJECT_CLASS (parent_class)->finalize (object);
179 * This function does the following:
180 * 1. Checks the state
181 * 2. Checks the filename
182 * 3. Sets the filename
184 * @param src [in] GstDrmSrc Structure
185 * @param location [in] location of the file
187 * @return gboolean Returns TRUE on success and FALSE on ERROR
189 static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * location)
193 GST_OBJECT_LOCK (src);
194 // 1. Checks the state
195 state = GST_STATE (src);
196 if (state != GST_STATE_READY && state != GST_STATE_NULL)
198 GST_DEBUG_OBJECT (src, "setting location in wrong state");
199 GST_OBJECT_UNLOCK (src);
202 GST_OBJECT_UNLOCK (src);
203 g_free (src->filename);
205 // 2. Checks the filename
206 if (location == NULL)
208 src->filename = NULL;
213 // 3. Sets the filename
214 src->filename = g_strdup (location);
215 src->uri = gst_uri_construct ("file", src->filename);
217 g_object_notify (G_OBJECT (src), "location");
218 gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
222 * This function does the following:
223 * 1. Sets the location of the file.
225 * @param object [in] GObject Structure
226 * @param prop_id [in] id of the property
227 * @param value [in] property value
228 * @param pspec [in] GParamSpec Structure
232 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
236 g_return_if_fail (GST_IS_DRM_SRC (object));
237 src = GST_DRM_SRC (object);
240 // 1. Sets the location of the file.
242 gst_drm_src_set_location (src, g_value_get_string (value));
245 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
250 * This function does the following:
251 * 1. Provides the location of the file.
252 * 2. Provides the file descriptor.
254 * @param object [in] GObject Structure
255 * @param prop_id [in] id of the property
256 * @param value [out] property value
257 * @param pspec [in] GParamSpec Structure
261 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value,GParamSpec * pspec)
265 g_return_if_fail (GST_IS_DRM_SRC (object));
266 src = GST_DRM_SRC (object);
269 // 1. Provides the location of the file.
271 g_value_set_string (value, src->filename);
273 // 2. Provides the file descriptor.
275 g_value_set_int (value, src->fd);
278 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
284 * This function does the following:
285 * 1. Seeks to the specified position.
286 * 2. Allocates a buffer to push the data
287 * 3. Reads from the file and sets the related params
289 * @param src [in] GstDrmSrc Structure
290 * @param offset [in] offset of the file to seek
291 * @param length [in] size of the data in bytes
292 * @param buffer [out] GstBuffer to hold the contents
294 * @return GstFlowReturn Returns GST_FLOW_OK on success and ERROR on failure
296 static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
300 // 1. Seeks to the specified position.
301 if (G_UNLIKELY (src->read_position != offset))
304 res = lseek (src->fd, offset, SEEK_SET);
305 if (G_UNLIKELY (res < 0 || res != offset))
307 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
308 return GST_FLOW_ERROR;
310 src->read_position = offset;
312 // 2. Allocates a buffer to push the data
313 buf = gst_buffer_new_and_alloc (length);
314 GST_LOG_OBJECT (src, "Reading %d bytes", length);
315 // 3. Reads from the file and sets the related params
316 ret = read (src->fd, GST_BUFFER_DATA (buf), length);
317 if (G_UNLIKELY (ret < 0))
319 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
320 gst_buffer_unref (buf);
321 return GST_FLOW_ERROR;
323 if (G_UNLIKELY ((guint) ret < length && src->seekable))
325 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),("unexpected end of file."));
326 gst_buffer_unref (buf);
327 return GST_FLOW_ERROR;
329 if (G_UNLIKELY (ret == 0 && length > 0))
331 GST_DEBUG ("non-regular file hits EOS");
332 gst_buffer_unref (buf);
333 return GST_FLOW_UNEXPECTED;
336 GST_BUFFER_SIZE (buf) = length;
337 GST_BUFFER_OFFSET (buf) = offset;
338 GST_BUFFER_OFFSET_END (buf) = offset + length;
340 src->read_position += length;
344 * This function does the following:
345 * 1. Calls DRM file read chain method for drm files.
346 * 2. Calls normal file read chain method for standard files.
348 * @param basesrc [in] BaseSrc Structure
349 * @param size [out] Size of the file
351 * @return gboolean Returns TRUE on success and FALSE on ERROR
353 static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
355 GstDrmSrc *src = GST_DRM_SRC (basesrc);
357 // 1. Calls DRM file read chain method for drm files.
359 // 2. Calls normal file read chain method for standard files.
360 return gst_drm_src_create_read (src, offset, length, buffer);
364 * @param basesrc [in] BaseSrc Structure
366 * @return gboolean Returns TRUE if the file is seekable and FALSE if the file is not seekable
368 static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
370 GstDrmSrc *src = GST_DRM_SRC (basesrc);
371 return src->seekable;
374 * This function does the following:
375 * 1. Gets the filesize for drm file by using seek oprations
376 * 2. Gets the file size for standard file by using statistics
378 * @param basesrc [in] BaseSrc Structure
379 * @param size [in] Size of the file
381 * @return gboolean Returns TRUE on success and FALSE on ERROR
383 static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
385 struct stat stat_results;
386 GstDrmSrc *src = GST_DRM_SRC (basesrc);
389 // 1. Gets the filesize for drm file by using seek oprations
391 // 2. Gets the file size for standard file by using statistics
392 if (fstat (src->fd, &stat_results) < 0)
394 *size = stat_results.st_size;
398 * This function does the following:
399 * 1. Checks the filename
400 * 2. Opens the file and check statistics of the file
401 * 7. Checks the seeking for standard files
403 * @param basesrc [in] BaseSrc Structure
405 * @return gboolean Returns TRUE on success and FALSE on ERROR
407 static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
409 GstDrmSrc *src = GST_DRM_SRC (basesrc);
410 struct stat stat_results;
413 // 1. Checks the filename
414 if (src->filename == NULL || src->filename[0] == '\0')
416 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,("No file name specified for reading."), (NULL));
419 // 2. Opens the file and check statistics of the file
420 GST_INFO_OBJECT (src, "opening file %s", src->filename);
421 src->fd = open (src->filename, O_RDONLY | O_BINARY);
426 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
429 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
432 if (fstat (src->fd, &stat_results) < 0)
434 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not get info on \"%s\".", src->filename), (NULL));
438 if (S_ISDIR (stat_results.st_mode))
440 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
444 if (S_ISSOCK (stat_results.st_mode))
446 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
450 src->read_position = 0;
452 // 7. Checks the seeking for standard files
453 if (S_ISREG (stat_results.st_mode))
454 src->is_regular = TRUE;
455 ret = lseek (src->fd, 0, SEEK_END);
458 GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
459 "failed: %s", g_strerror (errno));
460 src->seekable = FALSE;
464 src->seekable = TRUE;
466 lseek (src->fd, 0, SEEK_SET);
467 src->seekable = src->seekable && src->is_regular;
472 * This function does the following:
473 * 1. Closes the file desciptor and resets the flags
475 * @param basesrc [in] BaseSrc Structure
477 * @return gboolean Returns TRUE on success and FALSE on ERROR
479 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
481 GstDrmSrc *src = GST_DRM_SRC (basesrc);
483 // 1. Closes the file desciptor and resets the flags
487 src->is_regular = FALSE;
488 // PROFILE_SHOW_RESULT;
495 * @return GstURIType Returns GST_URI_SRC
498 static GstURIType gst_drm_src_uri_get_type (void)
504 * This function does the following:
505 * 1. Defines the list of protocols
509 * @return gchar ** Returns the protocol list
512 static gchar ** gst_drm_src_uri_get_protocols (void)
514 static gchar *protocols[] = { "file", NULL };
519 * @param handler [in] GstURIHandler structure
521 * @return gchar* Returns the uri
523 static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
525 GstDrmSrc *src = GST_DRM_SRC (handler);
529 * This function does the following:
530 * 1. Checks the protocol
531 * 2. Checks the whether it is absolute or not
532 * 3 sets the location
534 * @param handler [in] GstURIHandler structure
535 * @param uri [in] uri string
537 * @return gboolean Returns TRUE on success and FALSE on Error
539 static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * uri)
541 gchar *protocol, *location;
543 GstDrmSrc *src = GST_DRM_SRC (handler);
544 // 1. Checks the protocol
545 protocol = gst_uri_get_protocol (uri);
546 if (strcmp (protocol, "file") != 0)
552 if (g_str_has_prefix (uri, "file://localhost/"))
555 tmp = g_strconcat ("file://", uri + 16, NULL);
556 location = gst_uri_get_location (tmp);
559 else if (strcmp (uri, "file://") == 0)
561 gst_drm_src_set_location (src, NULL);
566 location = gst_uri_get_location (uri);
570 // 2. Checks the whether it is absolute or not
571 if (!g_path_is_absolute (location))
576 // 3 sets the location
577 ret = gst_drm_src_set_location (src, location);
582 * This function does the following:
583 * 1. Assignes the function pointer for URI related stuff
585 * @param g_iface [in] an interface to URI handler
586 * @param iface_data [in] a gpointer
590 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
592 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
593 // 1. Assigning the function pointer for URI related stuff
594 iface->get_type = gst_drm_src_uri_get_type;
595 iface->get_protocols = gst_drm_src_uri_get_protocols;
596 iface->get_uri = gst_drm_src_uri_get_uri;
597 iface->set_uri = gst_drm_src_uri_set_uri;
600 * This function does the following:
601 * 1. Registers an element as drmsrc
603 * @param i_pPlugin [in] a plug-in structure
605 * @return gboolean TRUE on SUCCESS and FALSE on Error
607 static gboolean plugin_init(GstPlugin* i_pPlugin)
609 return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);;
612 * This function does the following:
613 * 1. plugin defination
616 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
619 "Plugin to read data from standad/DRM File",
623 "Samsung Electronics Co",
624 "http://www.samsung.com/")