tizen 2.3 release
[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 #include "drm_util.h"
30 #include <drm_client.h>
31 #include <drm_client_types.h>
32
33 #ifdef CONTROL_PAGECACHE
34 #include <fcntl.h>
35 #define DEFAULT_DO_FADVISE_THRESHOLD    (100 * 1024 * 1024)    /* 100 MB */
36 #endif
37
38 #define LOG_TRACE(message)  //g_print("DRM_SRC: %s: %d: %s - %s \n", __FILE__, __LINE__, __FUNCTION__, message);
39
40 #define GST_TAG_PLAYREADY "playready_file_path"
41
42 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);
43
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) \
47         do \
48         { \
49                 if (posix_fadvise64(x_fd, x_offset, x_length, POSIX_FADV_DONTNEED) != 0) \
50                 { \
51                         GST_ERROR("Set posix_fadvise with POSIX_FADV_DONTNEED failed"); \
52                 } \
53         }while (0);
54 #else
55 #define DRMSRC_FADVISE_DONT(x_fd, x_offset, x_length) \
56         do \
57         { \
58                 if (posix_fadvise(x_fd, x_offset, x_length, POSIX_FADV_DONTNEED) != 0) \
59                 { \
60                         GST_ERROR("Set posix_fadvise with POSIX_FADV_DONTNEED failed"); \
61                 } \
62         }while (0);
63 #endif
64 #endif
65
66 GST_DEBUG_CATEGORY_STATIC (gst_drm_src_debug);
67 #define GST_CAT_DEFAULT gst_drm_src_debug
68
69 enum
70 {
71   ARG_0,
72   ARG_LOCATION,
73   ARG_FD,
74   IS_DRM
75 };
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);
88 /**
89  * This function does the following:
90  *  1. Initializes GstDrmSrc ( defines gst_drm_get_type)
91  *
92  * @param   drmsrc_type    [out]  GType
93  *
94  * @return  void
95  */
96 static void _do_init (GType drmsrc_type)
97 {
98   // 1. Initializes GstDrmSrc ( defines gst_drm_get_type)
99   static const GInterfaceInfo urihandler_info = {
100     gst_drm_src_uri_handler_init,
101     NULL,
102     NULL
103   };
104
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");
107 }
108 GST_BOILERPLATE_FULL (GstDrmSrc, gst_drm_src, GstBaseSrc, GST_TYPE_BASE_SRC,   _do_init);
109 /**
110  * This function does the following:
111  *  1. Sets the class details
112  *  2. Adds the source pad template
113  *
114  * @param   g_class    [out]   gpointer
115  *
116  * @return  void
117  */
118 static void gst_drm_src_base_init (gpointer g_class)
119 {
120   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
121
122   /*Sets the class details */
123   gst_element_class_set_details_simple (gstelement_class,
124     "DRM Source",
125     "Source/File",
126     "Read from arbitrary point in a standard/DRM file",
127     "Kishore Arepalli  <kishore.a@samsung.com> and Sadanand Dodawadakar <sadanand.d@samsung.com>");
128
129   /*Adds the source pad template */
130   gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
131 }
132 /**
133  * This function does the following:
134  *  1. Installs the properties
135  *  2. Assigns the function pointers GObject class attributes
136  *
137  * @param   klass    [out]   GstDrmSrcClass Structure
138  *
139  * @return  void
140  */
141 static void gst_drm_src_class_init (GstDrmSrcClass * klass)
142 {
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;
152
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,
157       G_PARAM_READABLE));
158
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,
162       G_PARAM_READWRITE));
163
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,
167       G_PARAM_READABLE));
168
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,
179     G_TYPE_STRING,
180     "PlayReady File Path",
181     "a tag that is specific to PlayReady File",
182      NULL);
183 }
184 /**
185  * This function does the following:
186  *  1. Initilizes the parameters of GstDrmSrc
187  *
188  * @param   src    [out]   GstDrmSrc structure
189  * @param   g_class    [in]   GstDrmSrcClass structure
190  *
191  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
192  */
193 static void gst_drm_src_init (GstDrmSrc * src, GstDrmSrcClass * g_class)
194 {
195   /* Initilizes the parameters of GstDrmSrc */
196   src->filename = NULL;
197   src->fd = 0;
198   src->uri = NULL;
199   src->is_regular = FALSE;
200   src->is_oma = FALSE;
201   src->seekable = FALSE;
202   src->hfile = NULL;
203   src->event_posted = FALSE;
204   src->is_playready = FALSE;
205   src->is_drm = FALSE;
206   src->isopen = FALSE;
207 #ifdef CONTROL_PAGECACHE
208   src->accum = 0;
209 #endif
210 }
211 /**
212  * This function does the following:
213  *  1. deallocates the filename and uri
214  *  2. calls the parent class->finalize
215  *
216  * @param   object    [in]   GObject Structure
217  *
218  * @return  void
219  */
220 static void gst_drm_src_finalize (GObject * object)
221 {
222   GstDrmSrc *src;
223
224   src = GST_DRM_SRC (object);
225   /*. deallocates the filename and uri */
226   g_free (src->filename);
227   g_free (src->uri);
228   /* calls the parent class->finalize */
229   G_OBJECT_CLASS (parent_class)->finalize (object);
230 }
231 /**
232  * This function does the following:
233  *  1. Checks the state
234  *  2. Checks the filename
235  *  3. Sets the filename
236  *
237  * @param   src    [in]   GstDrmSrc Structure
238  * @param   location    [in]   location of the file
239  *
240  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
241  */
242 static gboolean gst_drm_src_set_location (GstDrmSrc * src, const gchar * location)
243 {
244   GstState state;
245
246   GST_OBJECT_LOCK (src);
247
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);
253     return FALSE;
254   }
255   GST_OBJECT_UNLOCK (src);
256
257   g_free (src->filename);
258   g_free (src->uri);
259
260   /* Checks the filename */
261   if (location == NULL) {
262     src->filename = NULL;
263     src->uri = NULL;
264   } else {
265     /*. Sets the filename */
266     src->filename = g_strdup (location);
267 #if 0
268     /*This below API is changing the filename in case of punctuation marks in filename*/
269     src->uri = gst_filename_to_uri (location, NULL);
270 #else
271     src->uri = g_strdup_printf ("%s://%s", "file", src->filename);
272
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) {
276         src->is_drm = TRUE;
277       }
278     }
279     GST_DEBUG_OBJECT (src, "is drm : %d", src->is_drm);
280 #endif
281     GST_INFO_OBJECT(src, "filename : %s", src->filename);
282     GST_INFO_OBJECT(src, "uri      : %s", src->uri);
283   }
284   g_object_notify (G_OBJECT (src), "location");
285   gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri);
286
287   return TRUE;
288 }
289 /**
290  * This function does the following:
291  *  1. Sets the location of the file.
292  *
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
297  *
298  * @return  void
299  */
300 static void gst_drm_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
301 {
302   GstDrmSrc *src;
303
304   g_return_if_fail (GST_IS_DRM_SRC (object));
305
306   src = GST_DRM_SRC (object);
307
308   switch (prop_id) {
309   //  1. Sets the location of the file.
310   case ARG_LOCATION:
311     gst_drm_src_set_location (src, g_value_get_string (value));
312     break;
313   default:
314     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
315     break;
316   }
317 }
318 /**
319  * This function does the following:
320  *  1. Provides the location of the file.
321  *  2. Provides the file descriptor.
322  *
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
327  *
328  * @return  void
329  */
330 static void gst_drm_src_get_property (GObject * object, guint prop_id, GValue * value,GParamSpec * pspec)
331 {
332   GstDrmSrc *src;
333
334   g_return_if_fail (GST_IS_DRM_SRC (object));
335   src = GST_DRM_SRC (object);
336   switch (prop_id) {
337     case ARG_LOCATION:
338     g_value_set_string (value, src->filename);
339     break;
340     case ARG_FD:
341     g_value_set_int (value, src->fd);
342     break;
343     case IS_DRM:
344     g_value_set_boolean(value, src->is_drm);
345     break;
346     default:
347     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
348     break;
349   }
350 }
351
352 static GstStateChangeReturn
353 gst_drm_src_change_state (GstElement * element, GstStateChange transition)
354 {
355
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 */
367         if (!src->isopen) {
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");
371             return FALSE;
372           }
373           src->isopen=TRUE;
374         }
375       }
376     break;
377     }
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!!");
386         } else {
387           GST_ERROR("Clean Up Failed!!, ret = 0x%x", ret);
388         }
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!!");
392         } else {
393           GST_ERROR("Clean Up Failed!!, ret = 0x%x", ret);
394         }
395       }
396       break;
397     }
398     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
399       GST_INFO_OBJECT(src,"change state from paused to playing");
400       break;
401     }
402     default:
403       break;
404   }
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");
409       break;
410     }
411     case GST_STATE_CHANGE_PAUSED_TO_READY:{
412       GST_INFO_OBJECT(src,"change state from paused to ready");
413       if (src->hfile) {
414         if (src->isopen)
415           if (drm_util_close(&src->hfile))
416             src->isopen=FALSE;
417             src->hfile = NULL;
418 #ifdef CONTROL_PAGECACHE
419             DRMSRC_FADVISE_DONT(src->hfile, 0, 0);
420             src->accum = 0;
421 #endif
422       }
423       break;
424     }
425     case GST_STATE_CHANGE_READY_TO_NULL:{
426       GST_INFO_OBJECT(src,"change state from ready to null");
427       break;
428     }
429     default:
430     break;
431
432   }
433   return result;
434 }
435
436
437
438
439 /**
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.
444  *
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
449  *
450  * @return  GstFlowReturn   Returns GST_FLOW_OK on success and ERROR on failure
451  */
452 static GstFlowReturn  gst_drm_src_create_read_drm_file (GstDrmSrc* src, guint64 i_uiOffset, guint length, GstBuffer ** o_pBbuffer)
453 {
454   GstBuffer *buf = NULL;
455   unsigned int readSize;
456
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)
460       goto FAILED;
461
462     src->read_position = i_uiOffset;
463   }
464
465   /* Allocates a buffer to push the data for DRM file. */
466   buf = gst_buffer_new_and_alloc (length);
467   if(buf == NULL) {
468     LOG_TRACE("Exit on error");
469     return GST_FLOW_ERROR;
470   }
471
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)
474     goto FAILED;
475
476   if(readSize <= 0) {
477     LOG_TRACE("Exit on error");
478     return GST_FLOW_ERROR;
479   }
480
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;
486   }
487   #endif
488
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;
493   }
494
495 #ifdef CONTROL_PAGECACHE
496         src->accum += readSize;
497         if (src->accum >= DEFAULT_DO_FADVISE_THRESHOLD) {
498                 DRMSRC_FADVISE_DONT(src->hfile, 0, 0);
499                 src->accum = 0;
500         }
501 #endif
502
503   length = readSize;
504   GST_BUFFER_SIZE (buf) = length;
505   GST_BUFFER_OFFSET (buf) = i_uiOffset;
506   GST_BUFFER_OFFSET_END (buf) = i_uiOffset + length;
507   *o_pBbuffer = buf;
508   src->read_position += length;
509
510   return GST_FLOW_OK;
511
512 FAILED:
513 {
514   GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
515   return GST_FLOW_ERROR;
516 }
517 }
518 /**
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
523  *
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
528  *
529  * @return  GstFlowReturn   Returns GST_FLOW_OK on success and ERROR on failure
530  */
531 static GstFlowReturn gst_drm_src_create_read (GstDrmSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
532 {
533   int ret;
534   GstBuffer *buf;
535
536   /* Seeks to the specified position. */
537   if (G_UNLIKELY (src->read_position != offset)) {
538     off_t res;
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;
543     }
544     src->read_position = offset;
545   }
546
547   /* Allocates a buffer to push the data */
548   buf = gst_buffer_new_and_alloc (length);
549   if (NULL == buf) {
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;
553   }
554
555   GST_LOG_OBJECT (src, "Reading %d bytes", length);
556
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;
563   }
564
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;
569   }
570
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;
575   }
576
577 #ifdef CONTROL_PAGECACHE
578         src->accum += ret;
579         if (src->accum >= DEFAULT_DO_FADVISE_THRESHOLD) {
580                 DRMSRC_FADVISE_DONT(src->fd, 0, 0);
581                 src->accum = 0;
582         }
583         //DRMSRC_FADVISE_DONT(src->fd, offset, ret);
584 #endif
585
586   length = ret;
587   GST_BUFFER_SIZE (buf) = length;
588   GST_BUFFER_OFFSET (buf) = offset;
589   GST_BUFFER_OFFSET_END (buf) = offset + length;
590   *buffer = buf;
591   src->read_position += length;
592
593   return GST_FLOW_OK;
594 }
595 /**
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.
599  *
600  * @param   basesrc    [in]   BaseSrc Structure
601  * @param   size    [out]   Size of the file
602  *
603  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
604  */
605 static GstFlowReturn gst_drm_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
606 {
607   GstDrmSrc *src = GST_DRM_SRC (basesrc);
608
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);
613     if (tags) {
614       GstPad* src_pad = gst_element_get_static_pad (src, "src");
615       if (src_pad) {
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;
620         }
621         GST_DEBUG_OBJECT (src, "posting tags returns [%d]", src->event_posted);
622         src->event_posted = TRUE;
623         gst_object_unref (src_pad);
624       }
625     }
626   }
627
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);
632 }
633
634 static gboolean
635 gst_drm_src_query (GstBaseSrc * basesrc, GstQuery * query)
636 {
637   gboolean ret = FALSE;
638   GstDrmSrc *src = GST_DRM_SRC (basesrc);
639
640   switch (GST_QUERY_TYPE (query)) {
641     case GST_QUERY_URI:
642       gst_query_set_uri (query, src->uri);
643       ret = TRUE;
644       break;
645     case GST_QUERY_CUSTOM:
646     {
647       GstStructure *s;
648       guint64 size = 0;
649       GValue v = { 0, { { 0 } } };
650       g_value_init(&v, G_TYPE_UINT64);
651
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);
658           ret = TRUE;
659         }
660       }
661       break;
662     }
663     default:
664       ret = FALSE;
665       break;
666   }
667
668   if (!ret)
669     ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
670
671   return ret;
672 }
673
674 /**
675  *
676  * @param   basesrc    [in]   BaseSrc Structure
677  *
678  * @return  gboolean   Returns TRUE if the file is seekable and FALSE if the file is not seekable
679  */
680 static gboolean gst_drm_src_is_seekable (GstBaseSrc * basesrc)
681 {
682   GstDrmSrc *src = GST_DRM_SRC (basesrc);
683   return src->seekable;
684 }
685 /**
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
689  *
690  * @param   basesrc    [in]   BaseSrc Structure
691  * @param   size    [in]   Size of the file
692  *
693  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
694  */
695 static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size)
696 {
697   struct stat stat_results;
698   GstDrmSrc *src = GST_DRM_SRC (basesrc);
699   unsigned int offset;
700
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 */
706       *size = offset;
707     }
708     drm_util_seek (src->hfile, 0, DRM_SEEK_SET);
709     src->read_position = 0;
710     return TRUE;
711   }
712
713   if (!src->seekable) {
714     GST_DEBUG_OBJECT (src, "non-seekable");
715     return FALSE;
716   }
717
718   /* Gets the file size for standard file by using statistics */
719   if (fstat (src->fd, &stat_results) < 0)
720     return FALSE;
721
722   *size = stat_results.st_size;
723   GST_DEBUG_OBJECT (src, "size : %"G_GUINT64_FORMAT, *size);
724   return TRUE;
725 }
726 /**
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
735  *
736  * @param   basesrc    [in]   BaseSrc Structure
737  *
738  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
739  */
740 static gboolean gst_drm_src_start (GstBaseSrc * basesrc)
741 {
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;
746   off_t ret;
747
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));
751     return FALSE;
752   }
753
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);
757   if (src->fd < 0) {
758     if(errno == ENOENT) {
759       GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),("No such file \"%s\"", src->filename));
760       return FALSE;
761     }
762     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("Could not open file \"%s\" for reading.", src->filename), GST_ERROR_SYSTEM);
763     return FALSE;
764   }
765
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));
768     close (src->fd);
769     return FALSE;
770   }
771
772   if (S_ISDIR (stat_results.st_mode)) {
773     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("\"%s\" is a directory.", src->filename), (NULL));
774     close (src->fd);
775     return FALSE;
776   }
777
778   if (S_ISSOCK (stat_results.st_mode)) {
779     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("File \"%s\" is a socket.", src->filename), (NULL));
780     close (src->fd);
781     return FALSE;
782   }
783
784   src->read_position = 0;
785
786
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);
791     return FALSE;
792   }
793   GST_DEBUG_OBJECT (src, "file_path = [%s], file_type = [%d]", src->filename, file_type);
794
795 #if 0
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) {
800         src->is_drm = TRUE;
801       }
802     }
803     GST_DEBUG_OBJECT (src, "is drm = [%d]", src->is_drm);
804   }
805 #endif
806
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);
812
813     src->seekable       = TRUE;
814     src->is_regular     = TRUE;
815     src->is_oma = TRUE;
816
817     LOG_TRACE("Exit");
818     return TRUE;
819   }
820
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;
824   }
825
826   /* Checks the seeking for standard files */
827   if (S_ISREG (stat_results.st_mode))
828     src->is_regular = TRUE;
829
830   ret = lseek (src->fd, 0, SEEK_END);
831   if (ret < 0) {
832     GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek failed: %s", g_strerror (errno));
833     src->seekable = FALSE;
834   } else {
835     src->seekable = TRUE;
836   }
837
838   lseek (src->fd, 0, SEEK_SET);
839   src->seekable = src->seekable && src->is_regular;
840
841
842   return TRUE;
843 }
844 /**
845  * This function does the following:
846  *  1. Closes the file desciptor and resets the flags
847  *
848  * @param   basesrc    [in]   BaseSrc Structure
849  *
850  * @return  gboolean   Returns TRUE on success and FALSE on ERROR
851  */
852 static gboolean gst_drm_src_stop (GstBaseSrc * basesrc)
853 {
854   GstDrmSrc *src = GST_DRM_SRC (basesrc);
855   // 1. Closes the file desciptor and resets the flags
856   if(src->fd > 0) {
857 #ifdef CONTROL_PAGECACHE
858         DRMSRC_FADVISE_DONT(src->fd, 0, 0);
859         src->accum = 0;
860 #endif
861     close (src->fd);
862   }
863
864   src->fd = 0;
865   src->is_regular = FALSE;
866   src->event_posted = FALSE;
867   src->is_playready = FALSE;
868
869   return TRUE;
870 }
871 /**
872  *
873  * @param   void
874  *
875  * @return  GstURIType   Returns GST_URI_SRC
876  */
877
878 static GstURIType gst_drm_src_uri_get_type (void)
879 {
880   return GST_URI_SRC;
881 }
882
883 /**
884  * This function does the following:
885  *  1. Defines the list of protocols
886  *
887  * @param   void
888  *
889  * @return  gchar **   Returns the protocol list
890  */
891
892 static gchar ** gst_drm_src_uri_get_protocols (void)
893 {
894   static gchar *protocols[] = { "file", NULL };
895   return protocols;
896 }
897 /**
898  *
899  * @param   handler [in] GstURIHandler structure
900  *
901  * @return  gchar*   Returns the uri
902  */
903 static const gchar * gst_drm_src_uri_get_uri (GstURIHandler *handler)
904 {
905   GstDrmSrc *src = GST_DRM_SRC (handler);
906   return src->uri;
907 }
908 /**
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
913  *
914  * @param   handler [in] GstURIHandler structure
915  * @param   uri [in] uri string
916  *
917  * @return  gboolean   Returns TRUE on success and FALSE on Error
918  */
919 static gboolean gst_drm_src_uri_set_uri (GstURIHandler *handler, const gchar * uri)
920 {
921   gchar *location, *hostname = NULL;
922   gboolean ret = FALSE;
923   GstDrmSrc *src = GST_DRM_SRC (handler);
924   GError *error = NULL;
925
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);
931     return TRUE;
932   }
933
934   location = g_filename_from_uri (uri, &hostname, &error);
935
936   if (!location || error) {
937     if (error) {
938       GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
939           error->message);
940       g_error_free (error);
941     } else {
942       GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc", uri);
943     }
944     goto beach;
945   }
946
947   if ((hostname) && (strcmp (hostname, "localhost"))) {
948     /* Only 'localhost' is permitted */
949     GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
950     goto beach;
951   }
952
953   ret = gst_drm_src_set_location (src, location);
954
955 beach:
956   if (location)
957     g_free (location);
958   if (hostname)
959     g_free (hostname);
960
961   return ret;
962 }
963
964
965 /**
966  * This function does the following:
967  *  1. Assignes the function pointer for URI related stuff
968  *
969  * @param   g_iface [in] an interface to URI handler
970  * @param   iface_data [in] a gpointer
971  *
972  * @return  void
973  */
974 static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
975 {
976   GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
977
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;
983 }
984 /**
985  * This function does the following:
986  *  1. Registers an element as drmsrc
987  *
988  * @param   i_pPlugin [in] a plug-in structure
989  *
990  * @return  gboolean TRUE on SUCCESS and FALSE on Error
991  */
992 static gboolean plugin_init(GstPlugin* i_pPlugin)
993 {
994   return gst_element_register(i_pPlugin, "drmsrc", GST_RANK_NONE, GST_TYPE_DRM_SRC);
995 }
996 /**
997  * This function does the following:
998  *  1. plugin defination
999  *
1000  */
1001 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1002   GST_VERSION_MINOR,
1003   "drmsrc",
1004   "Plugin to read data from standad/DRM File",
1005   plugin_init,
1006   VERSION,
1007   "LGPL",
1008   "Samsung Electronics Co",
1009   "http://www.samsung.com/")
1010