diff --git a/gstreamer-0.10.21/plugins/elements/gstfilesrc.c b/gstreamer-0.10.21/plugins/elements/gstfilesrc.c
index cf3d5aa..a90ab67 100644
--- a/gstreamer-0.10.21/plugins/elements/gstfilesrc.c
+++ b/gstreamer-0.10.21/plugins/elements/gstfilesrc.c
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *               2000,2005 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2008 Motorola 
  *
  * gstfilesrc.c:
  *
@@ -23,7 +24,7 @@
  * SECTION:element-filesrc
  * @see_also: #GstFileSrc
  *
- * Read data from a file in the local file system.
+ * Read data from a file in the local file system, or a progressive downloading file.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -155,6 +156,16 @@ gst_open (const gchar * filename, int flags, int mode)
 GST_DEBUG_CATEGORY_STATIC (gst_file_src_debug);
 #define GST_CAT_DEFAULT gst_file_src_debug
 
+#ifndef GST_DISABLE_FILESRC_PD
+#define GST_FILE_GET_LOCK(elem)     (GST_FILE_SRC_CAST(elem)->pd_lock)
+#define GST_FILE_LOCK(elem)         g_mutex_lock(GST_FILE_GET_LOCK(elem))
+#define GST_FILE_TRYLOCK(elem)      g_mutex_trylock(GST_FILE_GET_LOCK(elem))
+#define GST_FILE_UNLOCK(elem)       g_mutex_unlock(GST_FILE_GET_LOCK(elem))
+#define GST_FILE_GET_COND(elem)     (GST_FILE_SRC_CAST(elem)->pd_cond)
+#define GST_FILE_WAIT(elem)         g_cond_wait (GST_FILE_GET_COND (elem), GST_FILE_GET_LOCK (elem))
+#define GST_FILE_SIGNAL(elem)       g_cond_signal (GST_FILE_GET_COND (elem));
+#endif
+
 /* FileSrc signals and args */
 enum
 {
@@ -167,6 +178,11 @@ enum
 #define DEFAULT_TOUCH           TRUE
 #define DEFAULT_USEMMAP         FALSE
 #define DEFAULT_SEQUENTIAL      FALSE
+#define DEFAULT_PD_FILESIZE        -1  /* Unknown file size, will support in the future */
+#define DEFAULT_PD_DOWNLOADEDSIZE  0
+#define DEFAULT_PD_SET             FALSE  
+/* number of milliseconds to try for reading download file  */
+#define PD_TRY_TIME                200
 
 enum
 {
@@ -176,7 +192,10 @@ enum
   ARG_MMAPSIZE,
   ARG_SEQUENTIAL,
   ARG_TOUCH,
-  ARG_USEMMAP
+  ARG_USEMMAP,
+  ARG_PD_SET,
+  ARG_PD_FILESIZE,
+  ARG_PD_DOWNLOADEDSIZE
 };
 
 static void gst_file_src_finalize (GObject * object);
@@ -197,6 +216,12 @@ static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset,
 static void gst_file_src_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
 
+#ifndef GST_DISABLE_FILESRC_PD
+static gboolean gst_file_src_get_pd_downloadedsize (GstFileSrc * src);
+static gboolean gst_file_src_pd_unlock (GstBaseSrc * basesrc);
+static gboolean gst_file_src_pd_on_timeout(GstFileSrc * src);
+#endif
+
 static void
 _do_init (GType filesrc_type)
 {
@@ -286,6 +311,21 @@ gst_file_src_class_init (GstFileSrcClass * klass)
           "mmap pages will be sequential",
           DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+#ifndef GST_DISABLE_FILESRC_PD
+  g_object_class_install_property (gobject_class, ARG_PD_SET,
+      g_param_spec_boolean ("is-pd", "Set PD mode", 
+          "Whether to use PD mode",
+          DEFAULT_PD_SET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, ARG_PD_FILESIZE,
+      g_param_spec_int64("pd-filesize", "PD File Size", 
+          "Indicate the predefined file size in byte while progressive downloading", -1, G_MAXINT64,
+          DEFAULT_PD_FILESIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, ARG_PD_DOWNLOADEDSIZE,
+      g_param_spec_uint64("pd-downloadedsize", "PD Downloaded Size",
+          "Incremental downloaded size, which may be less than or equal to file size", 0, G_MAXUINT64,
+          DEFAULT_PD_DOWNLOADEDSIZE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+#endif
+
   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_file_src_finalize);
 
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_file_src_start);
@@ -293,6 +333,9 @@ gst_file_src_class_init (GstFileSrcClass * klass)
   gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
   gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create);
+#ifndef GST_DISABLE_FILESRC_PD
+  gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_file_src_pd_unlock);
+#endif
 
   if (sizeof (off_t) < 8) {
     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
@@ -319,6 +362,20 @@ gst_file_src_init (GstFileSrc * src, GstFileSrcClass * g_class)
   src->sequential = DEFAULT_SEQUENTIAL;
 
   src->is_regular = FALSE;
+
+#ifndef GST_DISABLE_FILESRC_PD
+  src->pd_lock = g_mutex_new ();
+  src->pd_cond = g_cond_new ();
+
+  src->pd_filesize = DEFAULT_PD_FILESIZE;
+  src->pd_downloadedsize = DEFAULT_PD_DOWNLOADEDSIZE;
+  src->requestlen = 0;
+  src->is_pd = FALSE;
+  src->pd_sent_downloadcomplete_event = FALSE;
+  src->pd_blocked = FALSE;
+  src->pd_bunlock = FALSE;
+  src->pd_timer_id  = 0;
+#endif
 }
 
 static void
@@ -331,6 +388,11 @@ gst_file_src_finalize (GObject * object)
   g_free (src->filename);
   g_free (src->uri);
 
+#ifndef GST_DISABLE_FILESRC_PD
+  g_mutex_free (src->pd_lock);
+  g_cond_free (src->pd_cond);
+#endif
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -405,6 +467,16 @@ gst_file_src_set_property (GObject * object, guint prop_id,
     case ARG_USEMMAP:
       src->use_mmap = g_value_get_boolean (value);
       break;
+#ifndef GST_DISABLE_FILESRC_PD
+    case ARG_PD_SET:
+      src->is_pd = g_value_get_boolean (value);
+      break;
+    case ARG_PD_FILESIZE:
+      /*If user sets filesize, then works as PD mode*/
+      src->is_pd = TRUE;
+      src->pd_filesize = g_value_get_int64 (value);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -440,6 +512,18 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value,
     case ARG_USEMMAP:
       g_value_set_boolean (value, src->use_mmap);
       break;
+#ifndef GST_DISABLE_FILESRC_PD
+    case ARG_PD_SET:
+      g_value_set_boolean (value, src->is_pd);
+      break;
+    case ARG_PD_FILESIZE:
+      g_value_set_int64 (value, src->pd_filesize);
+      break;
+    case ARG_PD_DOWNLOADEDSIZE:
+      gst_file_src_get_pd_downloadedsize (src);
+      g_value_set_uint64 (value, src->pd_downloadedsize);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -811,9 +895,12 @@ gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
 {
   int ret;
   GstBuffer *buf;
+  off_t res;
+#ifndef GST_DISABLE_FILESRC_PD
+  src->pd_bunlock = FALSE;  
+#endif
 
   if (G_UNLIKELY (src->read_position != offset)) {
-    off_t res;
 
     res = lseek (src->fd, offset, SEEK_SET);
     if (G_UNLIKELY (res < 0 || res != offset))
@@ -824,14 +911,61 @@ gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
 
   buf = gst_buffer_new_and_alloc (length);
 
-  GST_LOG_OBJECT (src, "Reading %d bytes", length);
+  GST_LOG_OBJECT (src, "Reading %d bytes at %" G_GUINT64_FORMAT " bytes !!", length,offset);
   ret = read (src->fd, GST_BUFFER_DATA (buf), length);
+
   if (G_UNLIKELY (ret < 0))
     goto could_not_read;
 
   /* seekable regular files should have given us what we expected */
+#ifdef GST_DISABLE_FILESRC_PD
   if (G_UNLIKELY ((guint) ret < length && src->seekable))
-    goto unexpected_eos;
+  {
+#else
+  if (G_UNLIKELY ((guint) ret < length))
+  {
+    /* Design like this is to consider the efficiency. If get downloaded size by
+    fstat, and then judge downloaded size, the efficiency is lower */
+    if (src->is_pd)/*blocked*/
+    {
+      src->requestlen = offset + length;
+      src->pd_timer_id = g_timeout_add(PD_TRY_TIME, (GSourceFunc)gst_file_src_pd_on_timeout, src);
+      GST_LOG_OBJECT (src, "filesrc adds a timer, id=%u", src->pd_timer_id);
+    
+      GST_FILE_LOCK (src);
+    
+      src->pd_blocked = TRUE;
+      GST_FILE_WAIT (src);
+      GST_FILE_UNLOCK (src);
+    
+      src->pd_blocked = FALSE;
+      if (src->pd_bunlock)
+      {
+        GST_DEBUG_OBJECT (src, "stop called");
+        gst_buffer_unref (buf);
+        return GST_FLOW_WRONG_STATE;
+      }
+    
+      res = lseek (src->fd, offset, SEEK_SET);
+      if (res < 0 || res != offset)
+      {
+        gst_buffer_unref (buf);
+        goto seek_failed;
+      }
+      
+      GST_LOG_OBJECT (src, "Reading %d bytes", length);
+      ret = read (src->fd, GST_BUFFER_DATA (buf), length);
+      if (G_UNLIKELY ((guint) ret < length))
+        goto unexpected_eos;
+      if (G_UNLIKELY (ret < 0))
+        goto could_not_read;
+    }
+    else if G_UNLIKELY ((src->seekable))
+#endif
+    {
+      goto unexpected_eos;
+    }
+  }
 
   /* other files should eos if they read 0 and more was requested */
   if (G_UNLIKELY (ret == 0 && length > 0))
@@ -847,6 +981,17 @@ gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
 
   src->read_position += length;
 
+#ifndef GST_DISABLE_FILESRC_PD
+  if ((!src->pd_sent_downloadcomplete_event)&&(src->pd_downloadedsize >= src->pd_filesize))
+     {
+      GST_INFO_OBJECT (src, "downloaded size = %" G_GUINT64_FORMAT " bytes,filesize= %" G_GINT64_FORMAT " bytes.\n", src->pd_downloadedsize,src->pd_filesize);
+      gst_element_post_message(GST_ELEMENT(src),
+                               gst_message_new_element(GST_OBJECT(src),
+                               gst_structure_new ("application/x-download-completed", NULL)));
+      GST_LOG_OBJECT (src, "download completed,PD have send the message application/x-download-completed");
+      src->pd_sent_downloadcomplete_event = TRUE;
+     }
+#endif
   return GST_FLOW_OK;
 
   /* ERROR */
@@ -885,6 +1030,26 @@ gst_file_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
 
   src = GST_FILE_SRC (basesrc);
 
+  /*GstActivateMode activate_mode;
+
+  GST_OBJECT_LOCK (basesrc->srcpad);
+  activate_mode = GST_PAD_ACTIVATE_MODE (basesrc->srcpad);
+  GST_OBJECT_UNLOCK (basesrc->srcpad);
+ 
+  switch(activate_mode) {
+    case GST_ACTIVATE_PULL: 
+      GST_INFO_OBJECT (src, "filesrc is runing in PULL mode.\n");
+      break;
+ 
+    case GST_ACTIVATE_PUSH:
+      GST_INFO_OBJECT (src, "filesrc is runing in PUSH mode.\n");
+      break;
+    default:
+      GST_ERROR_OBJECT (src, "filesrc is not runing in PUSH/PULL mode.\n");
+      break;
+  }*/
+
+
 #ifdef HAVE_MMAP
   if (src->using_mmap) {
     ret = gst_file_src_create_mmap (src, offset, length, buffer);
@@ -914,26 +1079,61 @@ gst_file_src_get_size (GstBaseSrc * basesrc, guint64 * size)
 
   src = GST_FILE_SRC (basesrc);
 
-  if (!src->seekable) {
-    /* If it isn't seekable, we won't know the length (but fstat will still
-     * succeed, and wrongly say our length is zero. */
-    return FALSE;
+#ifndef GST_DISABLE_FILESRC_PD
+  if(src->is_pd)
+  {
+      if (src->pd_filesize < 0)
+       return FALSE;
+      *size =src->pd_filesize;
+  }
+  else
+#endif
+  {
+      if (!src->seekable) {
+        /* If it isn't seekable, we won't know the length (but fstat will still
+         * succeed, and wrongly say our length is zero. */
+        return FALSE;
+      }
+    
+      if (fstat (src->fd, &stat_results) < 0)
+        goto could_not_stat;
+    
+      *size = stat_results.st_size;
   }
-
-  if (fstat (src->fd, &stat_results) < 0)
-    goto could_not_stat;
-
-  *size = stat_results.st_size;
 
   return TRUE;
 
   /* ERROR */
 could_not_stat:
   {
+    GST_ERROR_OBJECT (src, "could_not_stat: %s", src->filename);
     return FALSE;
   }
 }
 
+#ifndef GST_DISABLE_FILESRC_PD
+static gboolean
+gst_file_src_get_pd_downloadedsize (GstFileSrc * src)
+{
+  struct stat stat_results;
+  gboolean ret = FALSE;
+
+  if (fstat (src->fd, &stat_results) < 0)
+  {
+      /* ERROR */
+      GST_ERROR_OBJECT (src, "could_not_stat: %s", src->filename);
+  }
+  else
+  {
+      src->pd_downloadedsize = stat_results.st_size;
+      GST_INFO_OBJECT (src, "downloaded size = %" G_GUINT64_FORMAT " bytes\n", src->pd_downloadedsize);
+      ret = TRUE;
+  }
+
+  return ret;
+}
+#endif
+
 /* open the file and mmap it, necessary to go to READY state */
 static gboolean
 gst_file_src_start (GstBaseSrc * basesrc)
@@ -985,16 +1185,25 @@ gst_file_src_start (GstBaseSrc * basesrc)
   {
     /* If not in mmap mode, we need to check if the underlying file is
      * seekable. */
-    off_t res = lseek (src->fd, 0, SEEK_END);
-
-    if (res < 0) {
-      GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
-          "failed: %s", g_strerror (errno));
-      src->seekable = FALSE;
-    } else {
-      src->seekable = TRUE;
+#ifndef GST_DISABLE_FILESRC_PD
+    if(src->is_pd)
+    {
+      src->seekable = FALSE; /* only support push mode while enable PD */
+    }
+    else
+#endif
+    {
+      off_t res = lseek (src->fd, 0, SEEK_END);
+  
+      if (res < 0) {
+        GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
+            "failed: %s", g_strerror (errno));
+        src->seekable = FALSE;
+      } else {
+        src->seekable = TRUE;
+      }
+      lseek (src->fd, 0, SEEK_SET);
     }
-    lseek (src->fd, 0, SEEK_SET);
   }
 
   /* We can only really do seeking on regular files - for other file types, we
@@ -1079,7 +1288,11 @@ gst_file_src_uri_get_type (void)
 static gchar **
 gst_file_src_uri_get_protocols (void)
 {
+#ifndef GST_DISABLE_FILESRC_PD
+  static gchar *protocols[] = { "file", "pd" };
+#else
   static gchar *protocols[] = { "file", NULL };
+#endif
 
   return protocols;
 }
@@ -1099,7 +1312,11 @@ gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
   GstFileSrc *src = GST_FILE_SRC (handler);
 
   protocol = gst_uri_get_protocol (uri);
+#ifndef GST_DISABLE_FILESRC_PD
+  if ((strcmp (protocol, "file") != 0) && (strcmp (protocol, "pd") != 0)) {
+#else
   if (strcmp (protocol, "file") != 0) {
+#endif
     g_free (protocol);
     return FALSE;
   }
@@ -1122,6 +1339,20 @@ gst_file_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
      *  that supports the URI protocol. */
     gst_file_src_set_location (src, NULL);
     return TRUE;
+#ifndef GST_DISABLE_FILESRC_PD
+  } else if (g_str_has_prefix (uri, "pd://")) {
+    char *tmp_uri;
+    char *tmp_filesize;
+
+    tmp_filesize = strstr (uri, "?pd-filesize=");
+    src->is_pd = TRUE;
+    src->pd_filesize = g_ascii_strtoll (tmp_filesize + 13, NULL, 10);
+    GST_INFO_OBJECT (src, "filesize= %" G_GINT64_FORMAT " bytes.\n", src->pd_filesize);
+
+    tmp_uri = g_strndup (uri, tmp_filesize - uri);
+    location = gst_uri_get_location (tmp_uri);
+    g_free (tmp_uri);
+#endif
   } else {
     location = gst_uri_get_location (uri);
     GST_LOG_OBJECT (src, "Location '%s' found from uri '%s'", location, uri);
@@ -1150,3 +1381,64 @@ gst_file_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
   iface->get_uri = gst_file_src_uri_get_uri;
   iface->set_uri = gst_file_src_uri_set_uri;
 }
+
+#ifndef GST_DISABLE_FILESRC_PD
+static gboolean
+gst_file_src_pd_unlock (GstBaseSrc * basesrc)
+{
+  GstFileSrc *src;
+
+  src = GST_FILE_SRC (basesrc);
+
+  GST_DEBUG_OBJECT (src, "sending stop command");
+  if (src->pd_blocked )
+  {
+    GST_FILE_LOCK (src);
+    GST_WARNING_OBJECT (src, "signal block object");
+    src->pd_bunlock = TRUE;
+    if (src->pd_timer_id > 0)
+    {
+       g_source_remove(src->pd_timer_id);
+       src->pd_timer_id = 0;
+    }
+
+    GST_FILE_SIGNAL (src);
+    GST_FILE_UNLOCK (src);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_file_src_pd_on_timeout(GstFileSrc * src)
+{
+  guint64 size;
+  struct stat stat_results;
+
+  fstat (src->fd, &stat_results);
+
+  size = stat_results.st_size;
+  src->pd_downloadedsize = size;
+
+  if (src->requestlen > src->pd_filesize )
+      src->requestlen = src->pd_filesize;
+  
+  GST_INFO_OBJECT (src, "trying to unblock ......, size = %" G_GINT64_FORMAT ", req = %" G_GINT64_FORMAT ", downloaded size = %" G_GUINT64_FORMAT "\n", size, src->requestlen, src->pd_downloadedsize);
+  if ((src->pd_blocked ) && (size >= src->requestlen))
+  {
+    GST_FILE_LOCK (src);
+    GST_FILE_SIGNAL (src);
+    GST_FILE_UNLOCK (src);
+    GST_DEBUG_OBJECT (src, "unblocking ......\n");
+
+    src->pd_timer_id = 0;
+
+    return FALSE;
+  }
+  else
+  {
+    GST_INFO_OBJECT (src, "blocking ......\n");
+    return TRUE;
+  }
+}
+#endif
