Merge branch 'tizen_3.0' into tizen 07/104307/1 accepted/tizen/common/20161214.160614 accepted/tizen/ivi/20161214.015318 accepted/tizen/mobile/20161214.014919 accepted/tizen/tv/20161214.015115 accepted/tizen/wearable/20161214.015138 submit/tizen/20161213.083228
authorEunhae Choi <eunhae1.choi@samsung.com>
Tue, 13 Dec 2016 05:14:44 +0000 (14:14 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Tue, 13 Dec 2016 05:15:29 +0000 (14:15 +0900)
Change-Id: I3905cf76c0f254efba9b0acfde1b473c50c8bcf0
Signed-off-by: Eunhae Choi <eunhae1.choi@samsung.com>
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasesrc.h
packaging/gstreamer.spec
plugins/elements/gstmultiqueue.c
plugins/elements/gstmultiqueue.h

index 31ac75e..70f48c9 100644 (file)
@@ -2503,7 +2503,17 @@ again:
   if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
     if (ret == GST_FLOW_OK) {
       if (*buf == NULL)
+      {
+#ifdef TIZEN_FEATURE_TRUSTZONE
+        /*tzappsrc patch : release handle when unref res_buf*/
+        if(bclass->tz_src_release_handle)
+        {
+          GST_INFO_OBJECT (src, "tzappsrc release the handle");
+          bclass->tz_src_release_handle(src,res_buf);
+        }
+#endif
         gst_buffer_unref (res_buf);
+      }
     }
     src->priv->forced_eos = TRUE;
     goto eos;
@@ -2562,7 +2572,18 @@ again:
        * it got unlocked because we did a state change. In any case, get rid of
        * the buffer. */
       if (*buf == NULL)
+      {
+#ifdef TIZEN_FEATURE_TRUSTZONE
+        /*tzappsrc patch : release handle when unref res_buf*/
+        GstBaseSrcClass *klass = GST_BASE_SRC_GET_CLASS(src);
+        if(klass->tz_src_release_handle)
+        {
+          GST_INFO_OBJECT (src, "tzappsrc release the handle");
+          klass->tz_src_release_handle(src,res_buf);
+        }
+#endif
         gst_buffer_unref (res_buf);
+      }
 
       if (!src->live_running) {
         /* We return FLUSHING when we are not running to stop the dataflow also
@@ -2584,7 +2605,18 @@ again:
           (_("Internal clock error.")),
           ("clock returned unexpected return value %d", status));
       if (*buf == NULL)
+      {
+#ifdef TIZEN_FEATURE_TRUSTZONE
+        /*tzappsrc patch : release handle when unref res_buf*/
+        GstBaseSrcClass *klass = GST_BASE_SRC_GET_CLASS(src);
+        if(klass->tz_src_release_handle)
+        {
+          GST_INFO_OBJECT (src, "tzappsrc release the handle");
+          klass->tz_src_release_handle(src,res_buf);
+        }
+#endif
         gst_buffer_unref (res_buf);
+      }
       ret = GST_FLOW_ERROR;
       break;
   }
@@ -2612,7 +2644,18 @@ map_failed:
         (_("Failed to map buffer.")),
         ("failed to map result buffer in WRITE mode"));
     if (*buf == NULL)
+    {
+#ifdef TIZEN_FEATURE_TRUSTZONE
+      /*tzappsrc patch : release handle when unref res_buf*/
+      GstBaseSrcClass *klass = GST_BASE_SRC_GET_CLASS(src);
+      if(klass->tz_src_release_handle)
+      {
+        GST_INFO_OBJECT (src, "tzappsrc release the handle");
+        klass->tz_src_release_handle(src,res_buf);
+      }
+#endif
       gst_buffer_unref (res_buf);
+    }
     return GST_FLOW_ERROR;
   }
 not_started:
@@ -2640,7 +2683,18 @@ flushing:
   {
     GST_DEBUG_OBJECT (src, "we are flushing");
     if (*buf == NULL)
+    {
+#ifdef TIZEN_FEATURE_TRUSTZONE
+      /*tzappsrc patch : release handle when unref res_buf*/
+      GstBaseSrcClass *klass = GST_BASE_SRC_GET_CLASS(src);
+      if(klass->tz_src_release_handle)
+      {
+        GST_INFO_OBJECT (src, "tzappsrc release the handle");
+        klass->tz_src_release_handle(src,res_buf);
+      }
+#endif
       gst_buffer_unref (res_buf);
+    }
     return GST_FLOW_FLUSHING;
   }
 eos:
@@ -2887,6 +2941,15 @@ gst_base_src_loop (GstPad * pad)
 
   ret = gst_pad_push (pad, buf);
   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+#ifdef TIZEN_FEATURE_TRUSTZONE
+    /*tzappsrc patch : release handle when unref res_buf*/
+    GstBaseSrcClass *klass = GST_BASE_SRC_GET_CLASS(src);
+    if(klass->tz_src_release_handle)
+    {
+      GST_INFO_OBJECT (src, "tzappsrc release the handle");
+      klass->tz_src_release_handle(src,buf);
+    }
+#endif
     if (ret == GST_FLOW_NOT_NEGOTIATED) {
       goto not_negotiated;
     }
index 1167cd3..190dc48 100644 (file)
@@ -231,6 +231,12 @@ struct _GstBaseSrcClass {
 
   /*< private >*/
   gpointer       _gst_reserved[GST_PADDING_LARGE];
+#ifdef TIZEN_FEATURE_TRUSTZONE
+  /*tzappsrc patch*/
+  int (*tz_flush) (GstBaseSrc *src, unsigned int handle);
+  int (*tz_src_flush) (GstBaseSrc *src);
+  int (*tz_src_release_handle) (GstBaseSrc *src, GstBuffer *buf);
+#endif
 };
 
 GType gst_base_src_get_type (void);
index 99a1852..2e2b702 100644 (file)
@@ -73,6 +73,8 @@ export CFLAGS="%{optflags} \
        -DTIZEN_FEATURE_QUEUE_MODIFICATION\
 %if "%{?profile}" == "tv"
        -DTIZEN_PROFILE_TV\
+        -DRVU_LIVESTREAMING_OPTIMIZATION\
+       -DTIZEN_FEATURE_TRUSTZONE\
 %endif
        -DTIZEN_FEATURE_RTSPSRC_MODIFICATION\
        -fno-strict-aliasing"
index 84e87b5..425654c 100644 (file)
  */
 typedef struct _GstSingleQueue GstSingleQueue;
 
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch*/
+enum
+{
+  SQ_VIDEO_STREAM = 0,
+  SQ_AUDIO_STREAM,
+  SQ_OTHER_STREAM
+};
+#endif
+
 struct _GstSingleQueue
 {
   /* unique identifier of the queue */
@@ -172,6 +182,11 @@ struct _GstSingleQueue
   GCond query_handled;
   gboolean last_query;
   GstQuery *last_handled_query;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : update buffering percent*/
+  gint sq_stream_type;
+  GstClockTime cur_time_of_begin_buffering;
+#endif
 };
 
 
@@ -189,6 +204,10 @@ struct _GstMultiQueueItem
   guint32 posid;
 
   gboolean is_query;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+  /*RVU patch : for update single queue buffering percent*/
+  GstSingleQueue *sq;
+#endif
 };
 
 static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue, guint id);
@@ -205,6 +224,13 @@ static void gst_multi_queue_post_buffering (GstMultiQueue * mq);
 
 static void gst_single_queue_flush_queue (GstSingleQueue * sq, gboolean full);
 
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : work for get stream type to set single queue buffering params*/
+static void single_queue_set_stream_type (GstSingleQueue * squeue,
+    GstBuffer * buffer);
+static void early_exit_buffering (GstMultiQueue * mq);
+#endif
+
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
@@ -265,6 +291,20 @@ enum
   PROP_LOW_PERCENT,
   PROP_HIGH_PERCENT,
   PROP_SYNC_BY_RUNNING_TIME,
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : buffering params*/
+  PROP_MAX_AUDIO_SIZE_BYTES,
+  PROP_MAX_AUDIO_SIZE_BUFFERS,
+  PROP_MAX_AUDIO_SIZE_TIME,
+  PROP_MAX_VIDEO_SIZE_BYTES,
+  PROP_MAX_VIDEO_SIZE_BUFFERS,
+  PROP_MAX_VIDEO_SIZE_TIME,
+  PROP_ENABLE_BUFFERING_OPT,
+/*RVU patch : rvu reset, disable audio buffering and adaptive buffering property*/
+  PROP_RESET_FLAG,
+  PROP_DISABLE_AUDIO_BUFFERING,
+  PROP_BUFFERING_ENHANCEMENT,
+#endif
   PROP_LAST
 };
 
@@ -348,7 +388,6 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
   /* PROPERTIES */
-
   g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES,
       g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
           "Max. amount of data in the queue (bytes, 0=disable)",
@@ -436,6 +475,59 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
           "Synchronize deactivated or not-linked streams by running time",
           DEFAULT_SYNC_BY_RUNNING_TIME,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : buffering params property*/
+  g_object_class_install_property (gobject_class, PROP_MAX_AUDIO_SIZE_BYTES,
+      g_param_spec_uint ("max-size-audio-bytes", "Max. size (kB)",
+          "Max. amount of data in the audio queue (bytes, 0=disable)", 0,
+          G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MAX_AUDIO_SIZE_BUFFERS,
+      g_param_spec_uint ("max-size-audio-buffers", "Max. size (buffers)",
+          "Max. number of buffers in the audio queue (0=disable)", 0, G_MAXUINT,
+          DEFAULT_MAX_SIZE_BUFFERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MAX_AUDIO_SIZE_TIME,
+      g_param_spec_uint64 ("max-size-audio-time", "Max. size (ns)",
+          "Max. amount of data in the audio queue (in ns, 0=disable)", 0,
+          G_MAXUINT64, DEFAULT_MAX_SIZE_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MAX_VIDEO_SIZE_BYTES,
+      g_param_spec_uint ("max-size-video-bytes", "Max. size (kB)",
+          "Max. amount of data in the video queue (bytes, 0=disable)",
+          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MAX_VIDEO_SIZE_BUFFERS,
+      g_param_spec_uint ("max-size-video-buffers", "Max. size (buffers)",
+          "Max. number of buffers in the video queue (0=disable)", 0, G_MAXUINT,
+          DEFAULT_MAX_SIZE_BUFFERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_MAX_VIDEO_SIZE_TIME,
+      g_param_spec_uint64 ("max-size-video-time", "Max. size (ns)",
+          "Max. amount of data in the video queue (in ns, 0=disable)", 0,
+          G_MAXUINT64, DEFAULT_MAX_SIZE_TIME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_ENABLE_BUFFERING_OPT,
+      g_param_spec_boolean ("enable-buffering-opt",
+          "make buffering optimize enable",
+          "enable to control the buffering queue size and time.", FALSE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+/*RVU patch : rvu reset, disable audio buffering and adaptive buffering property*/
+  g_object_class_install_property (gobject_class, PROP_RESET_FLAG,
+      g_param_spec_int ("buffering-reset-flag", "reset flag",
+          "reset buffering flag", 0, 1, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_DISABLE_AUDIO_BUFFERING,
+      g_param_spec_boolean ("disable-audio-buffering",
+          "disable audio stream buffering", "disable audio buffering solution",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_BUFFERING_ENHANCEMENT,
+      g_param_spec_boolean ("enhancement-buffering", "enhancement buffering solution",
+          "enhancement buffering solution",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
 
   gobject_class->finalize = gst_multi_queue_finalize;
 
@@ -478,6 +570,21 @@ gst_multi_queue_init (GstMultiQueue * mqueue)
   mqueue->counter = 1;
   mqueue->highid = -1;
   mqueue->high_time = GST_CLOCK_TIME_NONE;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : buffering params init*/
+  mqueue->audio_max_size.bytes = DEFAULT_MAX_SIZE_BYTES;
+  mqueue->audio_max_size.visible = DEFAULT_MAX_SIZE_BUFFERS;
+  mqueue->audio_max_size.time = DEFAULT_MAX_SIZE_TIME;
+  mqueue->video_max_size.bytes = DEFAULT_MAX_SIZE_BYTES;
+  mqueue->video_max_size.visible = DEFAULT_MAX_SIZE_BUFFERS;
+  mqueue->video_max_size.time = DEFAULT_MAX_SIZE_TIME;
+  mqueue->buffering_start_time = 0;
+  mqueue->stream_duration = 0;
+/*RVU patch : rvu reset flag, disable audio buffering flag and adaptive buffering flag*/
+  mqueue->buffering_reset = FALSE;
+  mqueue->disable_audio_buffering = FALSE;
+  mqueue->enhancement_buffering = FALSE;
+#endif
 
   g_mutex_init (&mqueue->qlock);
   g_mutex_init (&mqueue->buffering_post_lock);
@@ -570,6 +677,45 @@ gst_multi_queue_set_property (GObject * object, guint prop_id,
       GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
       gst_multi_queue_post_buffering (mq);
       break;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : buffering params property*/
+    case PROP_MAX_AUDIO_SIZE_BYTES:
+      GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+      mq->audio_max_size.bytes = g_value_get_uint (value);
+      SET_CHILD_PROPERTY (mq, bytes);
+      GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+      break;
+    case PROP_MAX_AUDIO_SIZE_BUFFERS:
+      GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+      mq->audio_max_size.visible = g_value_get_uint (value);
+      SET_CHILD_PROPERTY (mq, visible);
+      GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+      break;
+    case PROP_MAX_AUDIO_SIZE_TIME:
+      GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+      mq->audio_max_size.time = g_value_get_uint64 (value);
+      SET_CHILD_PROPERTY (mq, time);
+      GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+      break;
+    case PROP_MAX_VIDEO_SIZE_BYTES:
+      GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+      mq->video_max_size.bytes = g_value_get_uint (value);
+      SET_CHILD_PROPERTY (mq, bytes);
+      GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+      break;
+    case PROP_MAX_VIDEO_SIZE_BUFFERS:
+      GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+      mq->video_max_size.visible = g_value_get_uint (value);
+      SET_CHILD_PROPERTY (mq, visible);
+      GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+      break;
+    case PROP_MAX_VIDEO_SIZE_TIME:
+      GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+      mq->video_max_size.time = g_value_get_uint64 (value);
+      SET_CHILD_PROPERTY (mq, time);
+      GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+      break;
+#endif
     case PROP_EXTRA_SIZE_BYTES:
       mq->extra_size.bytes = g_value_get_uint (value);
       break;
@@ -622,6 +768,29 @@ gst_multi_queue_set_property (GObject * object, guint prop_id,
     case PROP_SYNC_BY_RUNNING_TIME:
       mq->sync_by_running_time = g_value_get_boolean (value);
       break;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : rvu reset buffering, disable audio buffering and adaptive buffering property*/
+    case PROP_RESET_FLAG:
+      mq->buffering = FALSE;
+      mq->percent = 0;
+      mq->buffering_reset = TRUE;
+      GST_DEBUG_OBJECT (mq, "MQ RESET FLAG!\n");
+      break;
+    case PROP_DISABLE_AUDIO_BUFFERING:
+    {
+      mq->disable_audio_buffering = g_value_get_boolean (value);
+      GST_LOG_OBJECT (mq, "disable-audio-buffering %d\n",
+          mq->disable_audio_buffering);
+    }
+      break;
+    case PROP_BUFFERING_ENHANCEMENT:
+    {
+      mq->enhancement_buffering = g_value_get_boolean (value);
+      GST_LOG_OBJECT (mq, "mq->enhancement_buffering %d\n",
+          mq->enhancement_buffering);
+    }
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -701,6 +870,15 @@ gst_multi_queue_get_property (GObject * object, guint prop_id,
     case PROP_SYNC_BY_RUNNING_TIME:
       g_value_set_boolean (value, mq->sync_by_running_time);
       break;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : rvu disable audio buffering and adaptive buffering property*/
+    case PROP_DISABLE_AUDIO_BUFFERING:
+      g_value_set_boolean (value, mq->disable_audio_buffering);
+      break;
+    case PROP_BUFFERING_ENHANCEMENT:
+      g_value_set_boolean (value, mq->enhancement_buffering);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -956,10 +1134,26 @@ get_percentage (GstSingleQueue * sq)
       tmp = (sq->cur_time * 100) / sq->max_size.time;
       percent = MAX (percent, tmp);
     }
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+    /*RVU patch : rvu adaptive buffering */
+    if (sq->mqueue->enhancement_buffering == TRUE)
+      GST_LOG_OBJECT (sq->mqueue,
+          "MULTIQUEUE ENHANCEMENT BUFFERING SOLUTION ENABLE!\n");
+
+    if (sq->mqueue->enhancement_buffering == FALSE) {
+      if (sq->max_size.bytes > 0) {
+        tmp = (size.bytes * 100) / sq->max_size.bytes;
+        percent = MAX (percent, tmp);
+      }
+    } else {
+      GST_LOG_OBJECT (sq->mqueue, "disable bytes buffering profile!\n");
+    }
+#else
     if (sq->max_size.bytes > 0) {
       tmp = (size.bytes * 100) / sq->max_size.bytes;
       percent = MAX (percent, tmp);
     }
+#endif
   }
 
   return percent;
@@ -970,21 +1164,97 @@ static void
 update_buffering (GstMultiQueue * mq, GstSingleQueue * sq)
 {
   gint percent;
-
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+  /*RVU patch : disable mq audio buffering solution */
+  GstPad *audio_pad = NULL;
+  GstCaps *audio_caps = NULL;
+  GstStructure *audio_caps_str = NULL;
+  const char *audio_mime = NULL;
+  const char *audio_stream_type = NULL;
+#endif
   /* nothing to dowhen we are not in buffering mode */
   if (!mq->use_buffering)
     return;
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+  /*RVU patch : disable mq audio buffering solution */
+  if ((sq != NULL) && (mq->disable_audio_buffering == TRUE)) {
+    GST_LOG_OBJECT (mq, "disable audio buffering solution start!\n");
+    audio_pad = GST_PAD_PEER (sq->sinkpad);
+    audio_caps = gst_pad_get_current_caps (audio_pad);
+    if (NULL == audio_caps) {
+      GST_LOG_OBJECT (mq, "audio caps is null!\n");
+      goto NEXT_STEP;
+    }
 
+    audio_caps_str = gst_caps_get_structure (audio_caps, 0);
+    if (NULL == audio_caps_str) {
+      GST_LOG_OBJECT (mq, "audio caps string is NULL!\n");
+      goto NEXT_STEP;
+    }
+
+    audio_mime = gst_structure_get_name (audio_caps_str);
+    if (NULL == audio_mime) {
+      GST_LOG_OBJECT (mq, "audio caps string mime is NULL!\n");
+      goto NEXT_STEP;
+    }
+
+    GST_LOG_OBJECT (mq, "audio_mime:[%s]\n", audio_mime);
+    if (g_strrstr (audio_mime, "audio")) {
+      GST_LOG_OBJECT (mq,
+          "non-drm audio single queue!, skip audio buffering\n");
+      goto LAST_POS;
+    } else if (g_strrstr (audio_mime, "drm")) {
+      audio_stream_type =
+          gst_structure_get_string (audio_caps_str, "stream-type");
+      if (NULL == audio_stream_type) {
+        GST_LOG_OBJECT (mq, "drm audio single queue can not get stream-type\n");
+        goto NEXT_STEP;
+      }
+      if (g_strrstr (audio_stream_type, "audio")) {
+        GST_LOG_OBJECT (mq, "drm audio single queue!, skip audio buffering!\n");
+        goto LAST_POS;
+      }
+    }
+    GST_LOG_OBJECT (mq, "disable audio buffering solution end!\n");
+  }
+
+NEXT_STEP:
+  if (audio_caps != NULL) {
+    GST_LOG_OBJECT (mq,
+        "audio caps release for disable audio buffering solution!\n");
+    gst_caps_unref (audio_caps);
+    audio_caps = NULL;
+  }
+#endif
   percent = get_percentage (sq);
 
   if (mq->buffering) {
     if (percent >= mq->high_percent) {
       mq->buffering = FALSE;
     }
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : rvu reset buffering */
+    if (mq->buffering_reset) {
+      if (percent < mq->low_percent) {
+        mq->buffering = TRUE;
+        mq->percent = percent;
+        mq->percent_changed = TRUE;
+      }
+    }
+#endif
     /* make sure it increases */
     percent = MAX (mq->percent, percent);
 
     SET_PERCENT (mq, percent);
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : adaptive buffering solution*/
+    if (mq->enhancement_buffering == TRUE) {
+      if (percent >= mq->high_percent) {
+        mq->percent_changed = TRUE;
+        GST_LOG_OBJECT (mq, "MULTIQUEUE ENHANCEMENT BUFFERING!\n");
+      }
+    }
+#endif
   } else {
     GList *iter;
     gboolean is_buffering = TRUE;
@@ -1004,6 +1274,109 @@ update_buffering (GstMultiQueue * mq, GstSingleQueue * sq)
       SET_PERCENT (mq, percent);
     }
   }
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*common update buffering */
+/*while starts buffering, need restore start time */
+  if (mq->enable_buffering_opt) {
+    if (percent < mq->low_percent && mq->buffering == TRUE) {
+      struct timeval tv = { 0 };
+      GList *iter = NULL;
+      gettimeofday (&tv, NULL);
+
+      mq->buffering_start_time =
+          GST_SECOND * (guint64) tv.tv_sec + (guint64) tv.tv_usec * GST_USECOND;
+      /*update all single queue */
+      for (iter = mq->queues; iter; iter = g_list_next (iter)) {
+        GstSingleQueue *oq = (GstSingleQueue *) iter->data;
+        oq->cur_time_of_begin_buffering = oq->cur_time;
+      }
+      GST_DEBUG_OBJECT (mq,
+          "update buffering start time, cur_time is : %" G_GUINT64_FORMAT,
+          sq->cur_time_of_begin_buffering);
+    } else if (mq->buffering == TRUE) {
+      struct timeval tv = { 0 };
+      gettimeofday (&tv, NULL);
+      GstClockTime buffering_duration = sq->cur_time;
+      guint64 tmp_time =
+          GST_SECOND * (guint64) tv.tv_sec + (guint64) tv.tv_usec * GST_USECOND;
+      guint64 elapsed_time = 0;
+
+      /*caculate elapsed time */
+      tmp_time -= mq->buffering_start_time;
+      elapsed_time = tmp_time;
+      /*buffering percentage increase until its src pad is blocked,  */
+      if (sq->cur_time > sq->cur_time_of_begin_buffering)
+        buffering_duration = sq->cur_time - sq->cur_time_of_begin_buffering;
+
+      GST_DEBUG_OBJECT (mq,
+          "%s, elapsed time is: %" G_GUINT64_FORMAT " cur_time is: %"
+          G_GUINT64_FORMAT, sq->sq_stream_type == SQ_VIDEO_STREAM ? "vq" : "aq",
+          elapsed_time, buffering_duration);
+      tmp_time /= GST_SECOND;
+
+      /*demuxer speed is lower than decoder */
+      if (tmp_time > 0 && (tmp_time % 3 == 0)
+          && buffering_duration < elapsed_time
+          && sq->sq_stream_type == SQ_VIDEO_STREAM) {
+        GstFormat format = GST_FORMAT_TIME;
+        guint64 cur_position = sq->srctime;
+        GstCaps *video_caps = NULL;
+        GstStructure *caps_structure = NULL;
+        gint rnum = 0, rdenom = 1;
+        gint r_framerate = 0, remaining_frame = 0, instant_throughput =
+            0, estimated_video_frame_count = 0;
+        GstDataQueueSize size;
+
+        if (cur_position <= 0 || mq->stream_duration <= 0) {
+          GST_DEBUG_OBJECT (mq, "no duration or position");
+          return;
+        }
+        gst_data_queue_get_level (sq->queue, &size);
+
+        video_caps = gst_pad_get_current_caps (sq->sinkpad);
+        GST_DEBUG_OBJECT (mq, "stream caps: %" GST_PTR_FORMAT, video_caps);
+
+        if (video_caps != NULL) {
+          caps_structure = gst_caps_get_structure (video_caps, 0);
+
+          if (caps_structure != NULL)
+            gst_structure_get_fraction (caps_structure, "r_framerate", &rnum,
+                &rdenom);
+
+          gst_caps_unref (video_caps);
+        }
+
+        else
+          return;
+
+        if (rdenom != 0)
+          r_framerate = rnum / rdenom;
+
+        GST_DEBUG_OBJECT (mq, "r_framerate is %d ", r_framerate);
+
+        remaining_frame = (mq->stream_duration - cur_position) * r_framerate / GST_SECOND - size.visible;       // packets num in video queue;     
+        instant_throughput = size.visible * GST_SECOND / elapsed_time;  // packets num / per seconds
+        GST_DEBUG_OBJECT (mq, "remaining_fram is %d, instant_throughput is %d",
+            remaining_frame, instant_throughput);
+        if (remaining_frame != 0)
+          estimated_video_frame_count =
+              (int) ((remaining_frame * r_framerate) / (r_framerate +
+                  instant_throughput));
+      }
+    }
+  }
+#endif
+#ifdef TIZEN_PROFILE_TV
+/*RVU patch : rvu case disable audio buffering */
+  return;
+LAST_POS:
+  if (audio_caps != NULL) {
+    gst_caps_unref (audio_caps);
+    audio_caps = NULL;
+  }
+  GST_LOG_OBJECT (mq, "DISABLE AUDIO BUFFERING MESSAGE HANDLE!\n");
+  return;
+#endif
 }
 
 static void
@@ -1439,7 +1812,18 @@ next:
 
   if (sq->flushing)
     goto out_flushing;
-
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+  if (mq->stream_duration == 0) {
+    GstPad *peer = NULL;
+    peer = gst_pad_get_peer (sq->sinkpad);
+    if (peer) {
+      if (!gst_pad_query_duration (peer, GST_FORMAT_TIME,
+              &(mq->stream_duration)))
+        GST_WARNING_OBJECT (mq, "Could not query upstream length!");
+      gst_object_unref (peer);
+    }
+  }
+#endif
   /* Get something from the queue, blocking until that happens, or we get
    * flushed */
   if (!(gst_data_queue_pop (sq->queue, &sitem)))
@@ -1692,6 +2076,70 @@ out_flushing:
   }
 }
 
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+/*RVU patch : set buffering params*/
+static void
+single_queue_set_stream_type (GstSingleQueue * squeue, GstBuffer * buffer)
+{
+  if (squeue->sq_stream_type == -1 && buffer) {
+    GstCaps *buffer_caps = NULL;
+    GstStructure *caps_str = NULL;
+    const gchar *mime_type = NULL;
+    const gchar *drm_stream_type = NULL;
+    struct timeval tv = { 0 };
+
+    do {
+      buffer_caps = gst_pad_get_current_caps (squeue->sinkpad); //GST_BUFFER_CAPS(buffer);
+      if (NULL == buffer_caps) {
+        GST_DEBUG_OBJECT (squeue->mqueue, "cannot get caps from single queue.");
+        break;
+      }
+
+      GST_DEBUG_OBJECT (squeue->mqueue, "single queue caps  %" GST_PTR_FORMAT,
+          buffer_caps);
+
+      caps_str = gst_caps_get_structure (buffer_caps, 0);
+      if (NULL == caps_str) {
+        GST_DEBUG_OBJECT (squeue->mqueue, "cannot get structure from capse.");
+        break;
+      }
+
+      mime_type = gst_structure_get_name (caps_str);
+      if (NULL == mime_type) {
+        GST_DEBUG_OBJECT (squeue->mqueue,
+            "cannot get mimetype from structure.");
+        break;
+      }
+
+      drm_stream_type = gst_structure_get_string (caps_str, "stream-type");
+
+      if (g_strrstr (mime_type, "video/") || (drm_stream_type
+              && g_strrstr (drm_stream_type, "video/"))) {
+        squeue->sq_stream_type = SQ_VIDEO_STREAM;
+        /*subtitle stream */
+        if (g_strrstr (mime_type, "video/x-dvb-subpicture"))
+          squeue->sq_stream_type = SQ_OTHER_STREAM;
+
+        gettimeofday (&tv, NULL);
+        if (squeue->mqueue->buffering_start_time == 0)
+          squeue->mqueue->buffering_start_time =
+              GST_SECOND * (guint64) tv.tv_sec +
+              (guint64) tv.tv_usec * GST_USECOND;
+      } else if (g_strrstr (mime_type, "audio/") || (drm_stream_type
+              && g_strrstr (drm_stream_type, "audio/"))) {
+        squeue->sq_stream_type = SQ_AUDIO_STREAM;
+        gettimeofday (&tv, NULL);
+        if (squeue->mqueue->buffering_start_time == 0)
+          squeue->mqueue->buffering_start_time =
+              GST_SECOND * (guint64) tv.tv_sec +
+              (guint64) tv.tv_usec * GST_USECOND;
+      } else {
+        squeue->sq_stream_type = SQ_OTHER_STREAM;
+      }
+    } while (0);
+  }
+}
+#endif
 /**
  * gst_multi_queue_chain:
  *
@@ -1711,6 +2159,11 @@ gst_multi_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   sq = gst_pad_get_element_private (pad);
   mq = sq->mqueue;
 
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+  if (mq->enable_buffering_opt) {
+    single_queue_set_stream_type (sq, buffer);
+  }
+#endif
   /* if eos, we are always full, so avoid hanging incoming indefinitely */
   if (sq->is_eos)
     goto was_eos;
@@ -2463,6 +2916,9 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
   sq->sink_tainted = TRUE;
   sq->src_tainted = TRUE;
 
+#ifdef TIZEN_FEATURE_TRUSTZONE
+  sq->sq_stream_type = -1;
+#endif
   name = g_strdup_printf ("sink_%u", sq->id);
   sq->sinkpad = gst_pad_new_from_static_template (&sinktemplate, name);
   g_free (name);
index d63eda5..28fd7e0 100644 (file)
@@ -77,6 +77,16 @@ struct _GstMultiQueue {
 
   gboolean percent_changed;
   GMutex buffering_post_lock; /* assures only one posted at a time */
+#ifdef RVU_LIVESTREAMING_OPTIMIZATION
+  /*RVU patch - reset functionality & buffering optimization*/
+  gboolean enable_buffering_opt;
+  guint64 buffering_start_time;
+  guint64 stream_duration;
+  GstDataQueueSize video_max_size, audio_max_size;
+  gboolean buffering_reset;
+  gboolean disable_audio_buffering;
+  gboolean enhancement_buffering;
+#endif
 };
 
 struct _GstMultiQueueClass {