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"
30 #include <drm_client.h>
31 #include <drm_client_types.h>
33 #ifdef CONTROL_PAGECACHE
35 #define DEFAULT_DO_FADVISE_THRESHOLD (100 * 1024 * 1024) /* 100 MB */
38 #define LOG_TRACE(message) //g_print("DRM_SRC: %s: %d: %s - %s \n", __FILE__, __LINE__, __FUNCTION__, message);
40 #define GST_TAG_PLAYREADY "playready_file_path"
42 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);
44 #ifdef CONTROL_PAGECACHE
45 #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
46 #define DRMSRC_FADVISE_DONT(x_fd, x_offset, x_length) \
49 if (posix_fadvise64(x_fd, x_offset, x_length, POSIX_FADV_DONTNEED) != 0) \
51 GST_ERROR("Set posix_fadvise with POSIX_FADV_DONTNEED failed"); \
55 #define DRMSRC_FADVISE_DONT(x_fd, x_offset, x_length) \
58 if (posix_fadvise(x_fd, x_offset, x_length, POSIX_FADV_DONTNEED) != 0) \
60 GST_ERROR("Set posix_fadvise with POSIX_FADV_DONTNEED failed"); \
66 GST_DEBUG_CATEGORY_STATIC (gst_drm_src_debug);
67 #define GST_CAT_DEFAULT gst_drm_src_debug
76 static void gst_drm_src_finalize (GObject * object);
77 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
78 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
79 static gboolean gst_drm_src_start (GstBaseSrc * basesrc);
80 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc);
81 static gboolean gst_drm_src_is_seekable (GstBaseSrc * src);
82 static gboolean gst_drm_src_get_size (GstBaseSrc * src, guint64 * size);
83 static GstFlowReturn gst_drm_src_create (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buffer);
84 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
85 static gboolean gst_drm_src_query (GstBaseSrc * src, GstQuery * query);
86 static GstStateChangeReturn gst_drm_src_change_state (GstElement * element,
87 GstStateChange transition);
89 * This function does the following:
90 * 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
92 * @param drmsrc_type [out] GType
96 static void _do_init (GType drmsrc_type)
98 // 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
99 static const GInterfaceInfo urihandler_info = {
100 gst_drm_src_uri_handler_init,
105 g_type_add_interface_static (drmsrc_type, GST_TYPE_URI_HANDLER, &urihandler_info);
106 GST_DEBUG_CATEGORY_INIT (gst_drm_src_debug, "drmsrc", 0, "drmsrc element");
108 GST_BOILERPLATE_FULL (GstDrmSrc, gst_drm_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init);
110 * This function does the following:
111 * 1. Sets the class details
112 * 2. Adds the source pad template
114 * @param g_class [out] gpointer
118 static void gst_drm_src_base_init (gpointer g_class)
120 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
122 /*Sets the class details */
123 gst_element_class_set_details_simple (gstelement_class,
126 "Read from arbitrary point in a standard/DRM file",
127 "Kishore Arepalli <kishore.a@samsung.com> and Sadanand Dodawadakar <sadanand.d@samsung.com>");
129 /*Adds the source pad template */
130 gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
133 * This function does the following:
134 * 1. Installs the properties
135 * 2. Assigns the function pointers GObject class attributes
137 * @param klass [out] GstDrmSrcClass Structure
141 static void gst_drm_src_class_init (GstDrmSrcClass * klass)
143 GObjectClass *gobject_class;
144 GstBaseSrcClass *gstbasesrc_class;
145 gobject_class = G_OBJECT_CLASS (klass);
146 gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
147 GstElementClass *gstelement_class;
148 gstelement_class = (GstElementClass *) klass;
149 /* Assigns the function pointers GObject class attributes */
150 gobject_class->set_property = gst_drm_src_set_property;
151 gobject_class->get_property = gst_drm_src_get_property;
153 /* Installs the properties*/
154 g_object_class_install_property (gobject_class, ARG_FD,
155 g_param_spec_int ("fd", "File-descriptor",
156 "File-descriptor for the file being mmap()d", 0, G_MAXINT, 0,
159 g_object_class_install_property (gobject_class, ARG_LOCATION,
160 g_param_spec_string ("location", "File Location",
161 "Location of the file to read", NULL,
164 g_object_class_install_property (gobject_class, IS_DRM,
165 g_param_spec_boolean ("is-drm", "whether selected file type is drm or not",
166 "true, false", FALSE,
169 /*Assigns the function pointers GObject class attributes */
170 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_drm_src_finalize);
171 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_drm_src_start);
172 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_drm_src_stop);
173 gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_drm_src_is_seekable);
174 gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_drm_src_get_size);
175 gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_drm_src_create);
176 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_drm_src_query);
177 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_drm_src_change_state);
178 gst_tag_register (GST_TAG_PLAYREADY, GST_TAG_FLAG_META,
180 "PlayReady File Path",
181 "a tag that is specific to PlayReady File",
185 * This function does the following:
186 * 1. Initilizes the parameters of GstDrmSrc
188 * @param src [out] GstDrmSrc structure
189 * @param g_class [in] GstDrmSrcClass structure
191 * @return gboolean Returns TRUE on success and FALSE on ERROR
193 static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
195 /* Initilizes the parameters of GstDrmSrc */
196 src->filename = NULL;
199 src->is_regular = FALSE;
201 src->seekable = FALSE;
203 src->event_posted = FALSE;
204 src->is_playready = FALSE;
207 #ifdef CONTROL_PAGECACHE
212 * This function does the following:
213 * 1. deallocates the filename and uri
214 * 2. calls the parent class->finalize
216 * @param object [in] GObject Structure
220 static void gst_drm_src_finalize (GObject * object)
224 src = GST_DRM_SRC (object);
225 /*. deallocates the filename and uri */
226 g_free (src->filename);
228 /* calls the parent class->finalize */
229 G_OBJECT_CLASS (parent_class)->finalize (object);
232 * This function does the following:
233 * 1. Checks the state
234 * 2. Checks the filename
235 * 3. Sets the filename
237 * @param src [in] GstDrmSrc Structure
238 * @param location [in] location of the file
240 * @return gboolean Returns TRUE on success and FALSE on ERROR
242 static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * location)
246 GST_OBJECT_LOCK (src);
248 /* Checks the state */
249 state = GST_STATE (src);
250 if (state != GST_STATE_READY && state != GST_STATE_NULL) {
251 GST_DEBUG_OBJECT (src, "setting location in wrong state");
252 GST_OBJECT_UNLOCK (src);
255 GST_OBJECT_UNLOCK (src);
257 g_free (src->filename);
260 /* Checks the filename */
261 if (location == NULL) {
262 src->filename = NULL;
265 /*. Sets the filename */
266 src->filename = g_strdup (location);
268 /*This below API is changing the filename in case of punctuation marks in filename*/
269 src->uri = gst_filename_to_uri (location, NULL);
271 src->uri = g_strdup_printf ("%s://%s", "file", src->filename);
273 drm_bool_type_e is_drm = DRM_FALSE;
274 if (drm_is_drm_file(src->filename, &is_drm) == DRM_RETURN_SUCCESS) {
275 if (is_drm == DRM_TRUE) {
279 GST_DEBUG_OBJECT (src, "is drm : %d", src->is_drm);
281 GST_INFO_OBJECT(src, "filename : %s", src->filename);
282 GST_INFO_OBJECT(src, "uri : %s", src->uri);
284 g_object_notify (G_OBJECT (src), "location");
285 gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
290 * This function does the following:
291 * 1. Sets the location of the file.
293 * @param object [in] GObject Structure
294 * @param prop_id [in] id of the property
295 * @param value [in] property value
296 * @param pspec [in] GParamSpec Structure
300 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
304 g_return_if_fail (GST_IS_DRM_SRC (object));
306 src = GST_DRM_SRC (object);
309 // 1. Sets the location of the file.
311 gst_drm_src_set_location (src, g_value_get_string (value));
314 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
319 * This function does the following:
320 * 1. Provides the location of the file.
321 * 2. Provides the file descriptor.
323 * @param object [in] GObject Structure
324 * @param prop_id [in] id of the property
325 * @param value [out] property value
326 * @param pspec [in] GParamSpec Structure
330 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value,GParamSpec * pspec)
334 g_return_if_fail (GST_IS_DRM_SRC (object));
335 src = GST_DRM_SRC (object);
338 g_value_set_string (value, src->filename);
341 g_value_set_int (value, src->fd);
344 g_value_set_boolean(value, src->is_drm);
347 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
352 static GstStateChangeReturn
353 gst_drm_src_change_state (GstElement * element, GstStateChange transition)
356 GstDrmSrc *src = GST_DRM_SRC (element);
357 GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
358 gboolean ret = FALSE;
359 drm_file_type_e file_type = DRM_TYPE_UNDEFINED;
360 switch (transition) {
361 case GST_STATE_CHANGE_NULL_TO_READY:{
362 GST_INFO_OBJECT(src,"change state from NULL to ready");
363 drm_result_e drm_result;
364 drm_result = drm_get_file_type (src->filename, &file_type);
365 if (file_type == DRM_TYPE_OMA_V1) {
366 /* Opens the DRM file if it is DRM */
368 GST_DEBUG_OBJECT (src, "trying to open drm util");
369 if (drm_util_open (&src->hfile, src->filename, file_type) == FALSE) {
370 GST_ERROR_OBJECT (src, "failed to open drm util");
378 case GST_STATE_CHANGE_READY_TO_PAUSED:{
379 GST_INFO_OBJECT(src,"change state from ready to paused");
380 drm_result_e drm_result;
381 drm_result = drm_get_file_type (src->filename, &file_type);
382 if (file_type == DRM_TYPE_OMA_V1){
383 ret = drm_process_request(DRM_REQUEST_TYPE_CLIENT_CLEAN_UP, NULL, NULL);
384 if (DRM_RETURN_SUCCESS == ret) {
385 GST_INFO("Clean Up successful!!");
387 GST_ERROR("Clean Up Failed!!, ret = 0x%x", ret);
389 ret = drm_trusted_handle_request(DRM_TRUSTED_REQ_TYPE_CLIENT_CLEAN_UP, NULL, NULL);
390 if (DRM_RETURN_SUCCESS == ret) {
391 GST_INFO("Clean Up successful!!");
393 GST_ERROR("Clean Up Failed!!, ret = 0x%x", ret);
398 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
399 GST_INFO_OBJECT(src,"change state from paused to playing");
405 result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
406 switch (transition) {
407 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
408 GST_INFO_OBJECT(src,"change state from playing to paused");
411 case GST_STATE_CHANGE_PAUSED_TO_READY:{
412 GST_INFO_OBJECT(src,"change state from paused to ready");
415 if (drm_util_close(&src->hfile))
418 #ifdef CONTROL_PAGECACHE
419 DRMSRC_FADVISE_DONT(src->hfile, 0, 0);
425 case GST_STATE_CHANGE_READY_TO_NULL:{
426 GST_INFO_OBJECT(src,"change state from ready to null");
440 * This function does the following:
441 * 1. Seeks to the specified position for DRM file.
442 * 2. Allocates a buffer to push the data for DRM file.
443 * 3. Reads from the file and sets the related params for DRM file.
445 * @param i_pDrmSrc [in] GstDrmSrc Structure
446 * @param i_uiOffset [in] offset of the file to seek
447 * @param length [in] size of the data in bytes
448 * @param o_pBbuffer [out] GstBuffer to hold the contents
450 * @return GstFlowReturn Returns GST_FLOW_OK on success and ERROR on failure
452 static GstFlowReturn gst_drm_src_create_read_drm_file (GstDrmSrc* src, guint64 i_uiOffset, guint length, GstBuffer ** o_pBbuffer)
454 GstBuffer *buf = NULL;
455 unsigned int readSize;
457 /* Seeks to the specified position for DRM file. */
458 if (G_UNLIKELY (src->read_position != i_uiOffset)) {
459 if (drm_util_seek (src->hfile, i_uiOffset, DRM_SEEK_SET) == FALSE)
462 src->read_position = i_uiOffset;
465 /* Allocates a buffer to push the data for DRM file. */
466 buf = gst_buffer_new_and_alloc (length);
468 LOG_TRACE("Exit on error");
469 return GST_FLOW_ERROR;
472 /*. Reads from the file and sets the related params for DRM file. */
473 if (drm_util_read (src->hfile, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf), &readSize) == FALSE)
477 LOG_TRACE("Exit on error");
478 return GST_FLOW_ERROR;
481 #if 0 // Drm service can give lesser size block than requested thing.
482 if (G_UNLIKELY ((guint) readSize < length && i_pDrmSrc->seekable)) {
483 GST_ELEMENT_ERROR (i_pDrmSrc, RESOURCE, READ, (NULL),("unexpected end of file."));
484 gst_buffer_unref (buf);
485 return GST_FLOW_ERROR;
489 if (G_UNLIKELY (readSize == 0 && length > 0)) {
490 GST_DEBUG ("non-regular file hits EOS");
491 gst_buffer_unref (buf);
492 return GST_FLOW_UNEXPECTED;
495 #ifdef CONTROL_PAGECACHE
496 src->accum += readSize;
497 if (src->accum >= DEFAULT_DO_FADVISE_THRESHOLD) {
498 DRMSRC_FADVISE_DONT(src->hfile, 0, 0);
504 GST_BUFFER_SIZE (buf) = length;
505 GST_BUFFER_OFFSET (buf) = i_uiOffset;
506 GST_BUFFER_OFFSET_END (buf) = i_uiOffset + length;
508 src->read_position += length;
514 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
515 return GST_FLOW_ERROR;
519 * This function does the following:
520 * 1. Seeks to the specified position.
521 * 2. Allocates a buffer to push the data
522 * 3. Reads from the file and sets the related params
524 * @param src [in] GstDrmSrc Structure
525 * @param offset [in] offset of the file to seek
526 * @param length [in] size of the data in bytes
527 * @param buffer [out] GstBuffer to hold the contents
529 * @return GstFlowReturn Returns GST_FLOW_OK on success and ERROR on failure
531 static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
536 /* Seeks to the specified position. */
537 if (G_UNLIKELY (src->read_position != offset)) {
539 res = lseek (src->fd, offset, SEEK_SET);
540 if (G_UNLIKELY (res < 0 || res != offset)) {
541 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
542 return GST_FLOW_ERROR;
544 src->read_position = offset;
547 /* Allocates a buffer to push the data */
548 buf = gst_buffer_new_and_alloc (length);
550 GST_ERROR_OBJECT (src, "failed to allocate memory..");
551 GST_ELEMENT_ERROR (src, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
552 return GST_FLOW_ERROR;
555 GST_LOG_OBJECT (src, "Reading %d bytes", length);
557 /* Reads from the file and sets the related params */
558 ret = read (src->fd, GST_BUFFER_DATA (buf), length);
559 if (G_UNLIKELY (ret < 0)) {
560 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
561 gst_buffer_unref (buf);
562 return GST_FLOW_ERROR;
565 if (G_UNLIKELY ((guint) ret < length && src->seekable)) {
566 GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),("unexpected end of file."));
567 gst_buffer_unref (buf);
568 return GST_FLOW_ERROR;
571 if (G_UNLIKELY (ret == 0 && length > 0)) {
572 GST_DEBUG ("non-regular file hits EOS");
573 gst_buffer_unref (buf);
574 return GST_FLOW_UNEXPECTED;
577 #ifdef CONTROL_PAGECACHE
579 if (src->accum >= DEFAULT_DO_FADVISE_THRESHOLD) {
580 DRMSRC_FADVISE_DONT(src->fd, 0, 0);
583 //DRMSRC_FADVISE_DONT(src->fd, offset, ret);
587 GST_BUFFER_SIZE (buf) = length;
588 GST_BUFFER_OFFSET (buf) = offset;
589 GST_BUFFER_OFFSET_END (buf) = offset + length;
591 src->read_position += length;
596 * This function does the following:
597 * 1. Calls DRM file read chain method for drm files.
598 * 2. Calls normal file read chain method for standard files.
600 * @param basesrc [in] BaseSrc Structure
601 * @param size [out] Size of the file
603 * @return gboolean Returns TRUE on success and FALSE on ERROR
605 static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
607 GstDrmSrc *src = GST_DRM_SRC (basesrc);
609 if (src->is_playready && src->event_posted == FALSE) {
610 GstTagList *tags = NULL;
611 GST_DEBUG_OBJECT (src, "posting playready tags");
612 tags = gst_tag_list_new_full (GST_TAG_PLAYREADY, src->filename, NULL);
614 GstPad* src_pad = gst_element_get_static_pad (src, "src");
616 if(!gst_pad_push_event (src_pad, gst_event_new_tag (tags))) {
617 GST_ERROR_OBJECT (src, "failed to push tags..");
618 gst_object_unref (src_pad);
619 return GST_FLOW_ERROR;
621 GST_DEBUG_OBJECT (src, "posting tags returns [%d]", src->event_posted);
622 src->event_posted = TRUE;
623 gst_object_unref (src_pad);
628 if(src->is_oma == TRUE) /* Calls DRM file read chain method for drm files. */
629 return gst_drm_src_create_read_drm_file (src, offset, length, buffer);
630 else /* Calls normal file read chain method for standard files. */
631 return gst_drm_src_create_read (src, offset, length, buffer);
635 gst_drm_src_query (GstBaseSrc * basesrc, GstQuery * query)
637 gboolean ret = FALSE;
638 GstDrmSrc *src = GST_DRM_SRC (basesrc);
640 switch (GST_QUERY_TYPE (query)) {
642 gst_query_set_uri (query, src->uri);
645 case GST_QUERY_CUSTOM:
649 GValue v = { 0, { { 0 } } };
650 g_value_init(&v, G_TYPE_UINT64);
652 s = gst_query_get_structure (query);
653 if (gst_structure_has_name (s, "dynamic-size")) {
654 if (gst_drm_src_get_size (basesrc, &size)){
655 /* succedded. take size */
656 g_value_set_uint64 (&v, size);
657 gst_structure_set_value(s, "size", &v);
669 ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
676 * @param basesrc [in] BaseSrc Structure
678 * @return gboolean Returns TRUE if the file is seekable and FALSE if the file is not seekable
680 static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
682 GstDrmSrc *src = GST_DRM_SRC (basesrc);
683 return src->seekable;
686 * This function does the following:
687 * 1. Gets the filesize for drm file by using seek oprations
688 * 2. Gets the file size for standard file by using statistics
690 * @param basesrc [in] BaseSrc Structure
691 * @param size [in] Size of the file
693 * @return gboolean Returns TRUE on success and FALSE on ERROR
695 static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
697 struct stat stat_results;
698 GstDrmSrc *src = GST_DRM_SRC (basesrc);
701 /* Gets the filesize for drm file by using seek oprations */
702 if(src->is_oma==TRUE) {
703 drm_util_seek (src->hfile, 0, DRM_SEEK_END);
704 if (drm_util_tell(src->hfile, &offset) == TRUE) {
705 /* FIXME : drm doesn't support 64 */
708 drm_util_seek (src->hfile, 0, DRM_SEEK_SET);
709 src->read_position = 0;
713 if (!src->seekable) {
714 GST_DEBUG_OBJECT (src, "non-seekable");
718 /* Gets the file size for standard file by using statistics */
719 if (fstat (src->fd, &stat_results) < 0)
722 *size = stat_results.st_size;
723 GST_DEBUG_OBJECT (src, "size : %"G_GUINT64_FORMAT, *size);
727 * This function does the following:
728 * 1. Checks the filename
729 * 2. Opens the file and check statistics of the file
730 * 3. Checks whether DRM file or not.
731 * 4. Checks the DRM file type (supports only for OMA) if it is DRM
732 * 5. Opens the DRM file if it is DRM
733 * 6. Gets the DRM_FILE_HANDLE and sets the drm, seekable and regular flag.
734 * 7. Checks the seeking for standard files
736 * @param basesrc [in] BaseSrc Structure
738 * @return gboolean Returns TRUE on success and FALSE on ERROR
740 static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
742 GstDrmSrc *src = GST_DRM_SRC (basesrc);
743 struct stat stat_results;
744 drm_result_e drm_result;
745 drm_file_type_e file_type;
748 /* Checks the filename */
749 if (src->filename == NULL || src->filename[0] == '\0') {
750 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,("No file name specified for reading."), (NULL));
754 /* Opens the file and check statistics of the file */
755 GST_INFO_OBJECT (src, "opening file %s", src->filename);
756 src->fd = open (src->filename, O_RDONLY | O_BINARY);
758 if(errno == ENOENT) {
759 GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
762 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
766 if (fstat (src->fd, &stat_results) < 0) {
767 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not get info on \"%s\".", src->filename), (NULL));
772 if (S_ISDIR (stat_results.st_mode)) {
773 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
778 if (S_ISSOCK (stat_results.st_mode)) {
779 GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
784 src->read_position = 0;
787 /* Checks whether DRM file or not.*/
788 drm_result = drm_get_file_type (src->filename, &file_type);
789 if (drm_result != DRM_RETURN_SUCCESS) {
790 GST_ERROR_OBJECT (src,"Error in drm_get_file_type(), error=%d", drm_result);
793 GST_DEBUG_OBJECT (src, "file_path = [%s], file_type = [%d]", src->filename, file_type);
796 if (DRM_TYPE_UNDEFINED != file_type) {
797 drm_bool_type_e is_drm = DRM_FALSE;
798 if (drm_is_drm_file(src->filename, &is_drm) == DRM_RETURN_SUCCESS) {
799 if (is_drm == DRM_TRUE) {
803 GST_DEBUG_OBJECT (src, "is drm = [%d]", src->is_drm);
807 /* We handles as DRM file if it is drm with OMA type */
808 if (file_type == DRM_TYPE_OMA_V1) { /* FIMXE: what about DRM_TYPE_OMA_V2 */
809 // Gets the DRM_FILE_HANDLE and sets the drm, seekable and regular flags.
810 drm_util_seek (src->hfile, 0, DRM_SEEK_END);
811 drm_util_seek (src->hfile, 0, DRM_SEEK_SET);
813 src->seekable = TRUE;
814 src->is_regular = TRUE;
821 if (file_type == DRM_TYPE_PLAYREADY || file_type == DRM_TYPE_PLAYREADY_ENVELOPE) { /* FIXME: what is envelope?? */
822 src->is_playready = TRUE;
823 src->event_posted = FALSE;
826 /* Checks the seeking for standard files */
827 if (S_ISREG (stat_results.st_mode))
828 src->is_regular = TRUE;
830 ret = lseek (src->fd, 0, SEEK_END);
832 GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek failed: %s", g_strerror (errno));
833 src->seekable = FALSE;
835 src->seekable = TRUE;
838 lseek (src->fd, 0, SEEK_SET);
839 src->seekable = src->seekable && src->is_regular;
845 * This function does the following:
846 * 1. Closes the file desciptor and resets the flags
848 * @param basesrc [in] BaseSrc Structure
850 * @return gboolean Returns TRUE on success and FALSE on ERROR
852 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
854 GstDrmSrc *src = GST_DRM_SRC (basesrc);
855 // 1. Closes the file desciptor and resets the flags
857 #ifdef CONTROL_PAGECACHE
858 DRMSRC_FADVISE_DONT(src->fd, 0, 0);
865 src->is_regular = FALSE;
866 src->event_posted = FALSE;
867 src->is_playready = FALSE;
875 * @return GstURIType Returns GST_URI_SRC
878 static GstURIType gst_drm_src_uri_get_type (void)
884 * This function does the following:
885 * 1. Defines the list of protocols
889 * @return gchar ** Returns the protocol list
892 static gchar ** gst_drm_src_uri_get_protocols (void)
894 static gchar *protocols[] = { "file", NULL };
899 * @param handler [in] GstURIHandler structure
901 * @return gchar* Returns the uri
903 static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
905 GstDrmSrc *src = GST_DRM_SRC (handler);
909 * This function does the following:
910 * 1. Checks the protocol
911 * 2. Checks the whether it is absolute or not
912 * 3 sets the location
914 * @param handler [in] GstURIHandler structure
915 * @param uri [in] uri string
917 * @return gboolean Returns TRUE on success and FALSE on Error
919 static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * uri)
921 gchar *location, *hostname = NULL;
922 gboolean ret = FALSE;
923 GstDrmSrc *src = GST_DRM_SRC (handler);
924 GError *error = NULL;
926 if (strcmp (uri, "file://") == 0) {
927 /* Special case for "file://" as this is used by some applications
928 * to test with gst_element_make_from_uri if there's an element
929 * that supports the URI protocol. */
930 gst_drm_src_set_location (src, NULL);
934 location = g_filename_from_uri (uri, &hostname, &error);
936 if (!location || error) {
938 GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
940 g_error_free (error);
942 GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
947 if ((hostname) && (strcmp (hostname, "localhost"))) {
948 /* Only 'localhost' is permitted */
949 GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
953 ret = gst_drm_src_set_location (src, location);
966 * This function does the following:
967 * 1. Assignes the function pointer for URI related stuff
969 * @param g_iface [in] an interface to URI handler
970 * @param iface_data [in] a gpointer
974 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
976 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
978 /* Assigning the function pointer for URI related stuff */
979 iface->get_type = gst_drm_src_uri_get_type;
980 iface->get_protocols = gst_drm_src_uri_get_protocols;
981 iface->get_uri = gst_drm_src_uri_get_uri;
982 iface->set_uri = gst_drm_src_uri_set_uri;
985 * This function does the following:
986 * 1. Registers an element as drmsrc
988 * @param i_pPlugin [in] a plug-in structure
990 * @return gboolean TRUE on SUCCESS and FALSE on Error
992 static gboolean plugin_init(GstPlugin* i_pPlugin)
994 return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);
997 * This function does the following:
998 * 1. plugin defination
1001 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1004 "Plugin to read data from standad/DRM File",
1008 "Samsung Electronics Co",
1009 "http://www.samsung.com/")