Merge the tizen patch and fix build err based on 1.12.2 30/158530/1
authorEunhae Choi <eunhae1.choi@samsung.com>
Wed, 1 Nov 2017 12:44:43 +0000 (21:44 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Wed, 1 Nov 2017 12:44:59 +0000 (21:44 +0900)
Change-Id: Ica5cd6b1a865b8367584aeb40e33ea6f3e4017e8

29 files changed:
1  2 
Makefile.am
configure.ac
ext/pulse/Makefile.am
ext/pulse/pulsesink.c
ext/pulse/pulsesrc.c
ext/soup/Makefile.am
ext/soup/gstsouphttpsrc.c
ext/soup/gstsouphttpsrc.h
gst/audioparsers/gstaacparse.c
gst/audioparsers/gstaacparse.h
gst/audioparsers/gstmpegaudioparse.c
gst/flx/gstflxdec.c
gst/flx/gstflxdec.h
gst/isomp4/fourcc.h
gst/isomp4/gstqtmux.c
gst/isomp4/gstqtmux.h
gst/isomp4/qtdemux.c
gst/isomp4/qtdemux_types.c
gst/matroska/matroska-demux.c
gst/rtpmanager/gstrtpbin.c
gst/rtsp/gstrtspsrc.c
gst/rtsp/gstrtspsrc.h
gst/videofilter/gstvideobalance.c
gst/wavparse/gstwavparse.c
packaging/common.tar.gz
packaging/gst-plugins-good.spec
sys/v4l2/gstv4l2videodec.c
sys/v4l2/v4l2_calls.c
sys/waveform/gstwaveformsink.c

diff --cc Makefile.am
@@@ -43,10 -42,12 +40,8 @@@ check-torture
  else
  check-torture:
        true
- build-checks:
-       true
  endif
  
 -win32-update:
 -      cp $(top_builddir)/win32/common/config.h-new \
 -          $(top_srcdir)/win32/common/config.h
 -
  include $(top_srcdir)/common/coverage/lcov.mak
  
  # cruft: plugins that have been merged or moved or renamed
diff --cc configure.ac
  AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes")
  AM_CONDITIONAL(HAVE_GTK_X11, test "x$HAVE_GTK_X11" = "xyes")
  
+ AC_ARG_ENABLE(pcmdump, AC_HELP_STRING([--enable-pcmdump], [pcm dump]),
+   [
+     case "${enableval}" in
+       yes) PCM_DUMP_ENABLE=yes ;;
+       no)  PCM_DUMP_ENABLE=no ;;
+       *)   AC_MSG_ERROR(bad value ${enableval} for --enable-pcmdump) ;;
+     esac
+   ],
+   [PCM_DUMP_ENABLE=no])
+ AM_CONDITIONAL([PCM_DUMP_ENABLE], [test "x$PCM_DUMP_ENABLE" = "xyes"])
+ if test "x$PCM_DUMP_ENABLE" = "xyes"; then
+ PKG_CHECK_MODULES(VCONF, vconf)
+ AC_SUBST(VCONF_CFLAGS)
+ AC_SUBST(VCONF_LIBS)
+ fi
 +dnl Check for -Bsymbolic-functions linker flag used to avoid
 +dnl intra-library PLT jumps, if available.
 +AC_ARG_ENABLE(Bsymbolic,
 +              [AS_HELP_STRING([--disable-Bsymbolic],[avoid linking with -Bsymbolic])],,
 +              [SAVED_LDFLAGS="${LDFLAGS}" SAVED_LIBS="${LIBS}"
 +               AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
 +               LDFLAGS=-Wl,-Bsymbolic-functions
 +               LIBS=
 +               AC_TRY_LINK([], [return 0],
 +                           AC_MSG_RESULT(yes)
 +                           enable_Bsymbolic=yes,
 +                           AC_MSG_RESULT(no)
 +                           enable_Bsymbolic=no)
 +               LDFLAGS="${SAVED_LDFLAGS}" LIBS="${SAVED_LIBS}"])
 +
  dnl *** set variables based on configure arguments ***
  
  dnl set license and copyright notice
@@@ -781,7 -785,7 +824,7 @@@ AG_GST_CHECK_FEATURE(SHOUT2, [Shoutcast
  dnl *** soup ***
  translit(dnm, m, l) AM_CONDITIONAL(USE_SOUP, true)
  AG_GST_CHECK_FEATURE(SOUP, [soup http client plugin (2.4)], souphttpsrc, [
-   PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.48, [HAVE_SOUP="yes"], [HAVE_SOUP="no"])
 -  PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.40, [HAVE_SOUP="yes"], [HAVE_SOUP="no"])
++  PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.46, [HAVE_SOUP="yes"], [HAVE_SOUP="no"])
    AC_SUBST(SOUP_CFLAGS)
    AC_SUBST(SOUP_LIBS)
  ])
@@@ -7,13 -7,18 +7,18 @@@ libgstpulseaudio_la_SOURCES = 
        pulsedeviceprovider.c \
        pulseutil.c
  
 -libgstpulse_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(PULSE_CFLAGS)
 -libgstpulse_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) \
 +libgstpulseaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(PULSE_CFLAGS)
 +libgstpulseaudio_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) \
        -lgstpbutils-$(GST_API_VERSION) \
        $(GST_BASE_LIBS) $(GST_LIBS) $(PULSE_LIBS)
 -libgstpulse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 -libgstpulse_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 +libgstpulseaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 +libgstpulseaudio_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
  
 -libgstpulse_la_CFLAGS += $(VCONF_CFLAGS) -DPCM_DUMP_ENABLE
 -libgstpulse_la_LIBADD += $(VCONF_LIBS)
+ if PCM_DUMP_ENABLE
++libgstpulseaudio_la_CFLAGS += $(VCONF_CFLAGS) -DPCM_DUMP_ENABLE
++libgstpulseaudio_la_LIBADD += $(VCONF_LIBS)
+ endif
  noinst_HEADERS = \
        pulsesink.h \
        pulsesrc.h \
Simple merge
@@@ -59,6 -59,9 +59,11 @@@ GST_DEBUG_CATEGORY_EXTERN (pulse_debug)
  #define DEFAULT_VOLUME          1.0
  #define DEFAULT_MUTE            FALSE
  #define MAX_VOLUME              10.0
+ #ifdef __TIZEN__
+ #define DEFAULT_AUDIO_LATENCY   "mid"
+ #endif /* __TIZEN__ */
++/* See the pulsesink code for notes on how we interact with the PA mainloop
++ * thread. */
  
  /* See the pulsesink code for notes on how we interact with the PA mainloop
   * thread. */
@@@ -1,13 -1,13 +1,13 @@@
 -plugin_LTLIBRARIES = libgstsouphttpsrc.la
 +plugin_LTLIBRARIES = libgstsoup.la
  
 -libgstsouphttpsrc_la_SOURCES = gstsouphttpsrc.c gstsouphttpclientsink.c gstsouputils.c gstsoup.c
 +libgstsoup_la_SOURCES = gstsouphttpsrc.c gstsouphttpclientsink.c gstsouputils.c gstsoup.c
  
 -libgstsouphttpsrc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
 +libgstsoup_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
        $(GST_CFLAGS) $(SOUP_CFLAGS) \
-       -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_48 \
-       -DSOUP_VERSION_MAX_ALLOWED=SOUP_DEPRECATED_IN_2_48
 -      -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_26 \
 -      -DSOUP_VERSION_MAX_ALLOWED=SOUP_DEPRECATED_IN_2_26
 -libgstsouphttpsrc_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_API_VERSION@ $(GST_BASE_LIBS) $(SOUP_LIBS)
 -libgstsouphttpsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 -libgstsouphttpsrc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
++      -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_46 \
++      -DSOUP_VERSION_MAX_ALLOWED=SOUP_DEPRECATED_IN_2_46
 +libgstsoup_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_API_VERSION@ $(GST_BASE_LIBS) $(SOUP_LIBS)
 +libgstsoup_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 +libgstsoup_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
  
  noinst_HEADERS = gstsouphttpsrc.h gstsouphttpclientsink.h gstsouputils.h
@@@ -444,14 -447,17 +444,25 @@@ gst_soup_http_src_reset (GstSoupHTTPSr
    src->content_size = 0;
    src->have_body = FALSE;
  
 -  src->ret = GST_FLOW_OK;
 +  src->reduce_blocksize_count = 0;
 +  src->increase_blocksize_count = 0;
 +
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+   if (src->dash_oldest_segment) {
+     g_free (src->dash_oldest_segment);
+     src->dash_oldest_segment = NULL;
+   }
+   if (src->dash_newest_segment) {
+     g_free (src->dash_newest_segment);
+     src->dash_newest_segment = NULL;
+   }
+ #endif
++
 +  g_cancellable_reset (src->cancellable);
 +  if (src->input_stream) {
 +    g_object_unref (src->input_stream);
 +    src->input_stream = NULL;
 +  }
  
    gst_caps_replace (&src->src_caps, NULL);
    g_free (src->iradio_name);
@@@ -487,10 -494,12 +498,14 @@@ gst_soup_http_src_init (GstSoupHTTPSrc 
    src->ssl_strict = DEFAULT_SSL_STRICT;
    src->ssl_use_system_ca_file = DEFAULT_SSL_USE_SYSTEM_CA_FILE;
    src->tls_database = DEFAULT_TLS_DATABASE;
 +  src->tls_interaction = DEFAULT_TLS_INTERACTION;
    src->max_retries = DEFAULT_RETRIES;
    src->method = DEFAULT_SOUP_METHOD;
 +  src->minimum_blocksize = gst_base_src_get_blocksize (GST_BASE_SRC_CAST (src));
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+   src->dash_oldest_segment = NULL;
+   src->dash_newest_segment = NULL;
+ #endif
    proxy = g_getenv ("http_proxy");
    if (!gst_soup_http_src_set_proxy (src, proxy)) {
      GST_WARNING_OBJECT (src,
@@@ -789,16 -850,21 +846,23 @@@ gst_soup_http_src_add_range_header (Gst
    gint rc;
  
    soup_message_headers_remove (src->msg->request_headers, "Range");
-   if (offset || stop_offset != -1) {
+ /* This changes are needed to enable Seekable Contents from server.
+    We have observed that , for few specific networks ( VODAFONE ) , without theabove headers ,
+    Youtube is sending non-seekable contents to the Client. */
+ #ifndef TIZEN_FEATURE_SOUP_MODIFICATION
+   if (offset || stop_offset != -1)
+ #endif
+   {
      if (stop_offset != -1) {
 +      g_assert (offset != stop_offset);
 +
        rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-%"
 -                G_GUINT64_FORMAT, offset, stop_offset);
 +          G_GUINT64_FORMAT, offset, (stop_offset > 0) ? stop_offset - 1 :
 +          stop_offset);
      } else {
        rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-",
-           offset);
+                 offset);
      }
      if (rc > sizeof (buf) || rc < 0)
        return FALSE;
@@@ -901,17 -1022,19 +995,17 @@@ gst_soup_http_src_session_open (GstSoup
      GST_DEBUG_OBJECT (src, "Creating session");
      if (src->proxy == NULL) {
        src->session =
 -          soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
 -          src->context, SOUP_SESSION_USER_AGENT, src->user_agent,
 -          SOUP_SESSION_TIMEOUT, src->timeout,
 -          SOUP_SESSION_SSL_STRICT, src->ssl_strict,
 -          SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
 -          NULL);
 +          soup_session_new_with_options (SOUP_SESSION_USER_AGENT,
 +          src->user_agent, SOUP_SESSION_TIMEOUT, src->timeout,
-           SOUP_SESSION_SSL_STRICT, src->ssl_strict,
-           SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
++          SOUP_SESSION_SSL_STRICT, src->ssl_strict, NULL);
++//          SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
      } else {
        src->session =
 -          soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
 -          src->context, SOUP_SESSION_PROXY_URI, src->proxy,
 +          soup_session_new_with_options (SOUP_SESSION_PROXY_URI, src->proxy,
            SOUP_SESSION_TIMEOUT, src->timeout,
            SOUP_SESSION_SSL_STRICT, src->ssl_strict,
-           SOUP_SESSION_USER_AGENT, src->user_agent,
-           SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
+           SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
++//          SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
      }
  
      if (!src->session) {
@@@ -950,17 -1103,50 +1066,25 @@@ gst_soup_http_src_session_close (GstSou
  {
    GST_DEBUG_OBJECT (src, "Closing session");
  
 -  if (src->loop)
 -    g_main_loop_quit (src->loop);
 -
    g_mutex_lock (&src->mutex);
 +  if (src->msg) {
 +    soup_session_cancel_message (src->session, src->msg, SOUP_STATUS_CANCELLED);
 +    g_object_unref (src->msg);
 +    src->msg = NULL;
 +  }
 +
    if (src->session) {
 -    soup_session_abort (src->session);  /* This unrefs the message. */
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+ /* When Playback is ongoing and Browser is moved to background ( Pressing Menu or Home Key ), The Session gets destroyed.
+    But the cookie_jar property remains unfreed. This results in garbage pointer and causes crash.
+    Removing the cookie_jar feature during close session of browser to handle the issue. */
+     GST_DEBUG_OBJECT (src, "Removing Cookie Jar instance");
+     soup_session_remove_feature_by_type(src->session, SOUP_TYPE_COOKIE_JAR);
+     src->cookie_jar = NULL;
+ #endif
 +    soup_session_abort (src->session);
      g_object_unref (src->session);
      src->session = NULL;
 -    src->msg = NULL;
 -  }
 -  if (src->loop) {
 -#ifdef LIBSOUP_DOES_NOT_STEAL_OUR_CONTEXT
 -    GSource *idle_source;
 -
 -    /* Iterating the main context to give GIO cancellables a chance
 -     * to initiate cleanups. Wihout this, resources allocated by
 -     * libsoup for the connection are not released and socket fd is
 -     * leaked. */
 -    idle_source = g_idle_source_new ();
 -    /* Suppressing "idle souce without callback" warning */
 -    g_source_set_callback (idle_source, dummy_idle_cb, NULL, NULL);
 -    g_source_set_priority (idle_source, G_PRIORITY_LOW);
 -    g_source_attach (idle_source, src->context);
 -    /* Acquiring the context. Idle source guarantees that we'll not block. */
 -    g_main_context_push_thread_default (src->context);
 -    g_main_context_iteration (src->context, TRUE);
 -    /* Ensuring that there's no unhandled pending events left. */
 -    while (g_main_context_iteration (src->context, FALSE));
 -    g_main_context_pop_thread_default (src->context);
 -    g_source_unref (idle_source);
 -#endif
 -
 -    g_main_loop_unref (src->loop);
 -    g_main_context_unref (src->context);
 -    src->loop = NULL;
 -    src->context = NULL;
    }
    g_mutex_unlock (&src->mutex);
  }
@@@ -1018,8 -1201,58 +1142,58 @@@ insert_http_header (const gchar * name
    }
  }
  
 -static void
 -gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+ static void
+ gst_soup_http_src_headers_foreach (const gchar * name, const gchar * val,
+     gpointer src)
+ {
+   GST_INFO_OBJECT (src, " %s: %s", name, val);
+   if (g_ascii_strcasecmp (name, "Set-Cookie") == 0)
+   {
+     if (val)
+     {
+       gboolean bret = FALSE;
+       GstStructure *s = NULL;
+       GstSoupHTTPSrc * tmp = src;
+       SoupURI *uri;
+       uri =  soup_uri_new (tmp->location);
+       /* post current bandwith & uri to application */
+       s = gst_structure_new ("cookies",
+             "updated-cookie", G_TYPE_STRING, val,
+             "updated-url", G_TYPE_STRING, tmp->location, NULL);
+       bret = gst_element_post_message (GST_ELEMENT_CAST (src), gst_message_new_element (GST_OBJECT_CAST (src), s));
+       soup_cookie_jar_set_cookie (tmp->cookie_jar,  uri, val);
+       soup_uri_free (uri);
+       GST_INFO_OBJECT (src, "request url [%s], posted cookies [%s] msg and returned = %d", tmp->location, val, bret);
+     }
+   }
+   else if (g_ascii_strcasecmp (name, "Dash-Oldest-Segment") == 0)
+   {
+     if (val)
+     {
+       GstSoupHTTPSrc * tmp = src;
+       tmp->dash_oldest_segment = g_strdup (val);
+       GST_INFO_OBJECT (src, "Dash-Oldest-Segment set as %s ", tmp->dash_oldest_segment);
+     }
+   }
+   else if (g_ascii_strcasecmp (name, "Dash-Newest-Segment") == 0)
+   {
+     if (val)
+     {
+       GstSoupHTTPSrc * tmp = src;
+       tmp->dash_newest_segment = g_strdup (val);
+       GST_INFO_OBJECT (src, "Dash-Newest-Segment set as %s ", tmp->dash_newest_segment);
+     }
+   }
+ }
+ #endif
 +static GstFlowReturn
 +gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
  {
    const char *value;
    GstTagList *tag_list;
    GstEvent *http_headers_event;
    GstStructure *http_headers, *headers;
    const gchar *accept_ranges;
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+   gint64 start = 0, stop = 0, total = 0;
+ #endif
  
-   GST_INFO_OBJECT (src, "got headers");
+   GST_INFO_OBJECT (src, "got headers : %d", msg->status_code);
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+   soup_message_headers_foreach (msg->response_headers,
+       gst_soup_http_src_headers_foreach, src);
+ #endif
    if (msg->status_code == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED &&
 -      src->proxy_id && src->proxy_pw)
 -    return;
 -
 -  if (src->automatic_redirect && SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
 -    src->redirection_uri = g_strdup (soup_message_headers_get_one
 -        (msg->response_headers, "Location"));
 -    src->redirection_permanent =
 -        (msg->status_code == SOUP_STATUS_MOVED_PERMANENTLY);
 -    GST_DEBUG_OBJECT (src, "%u redirect to \"%s\" (permanent %d)",
 -        msg->status_code, src->redirection_uri, src->redirection_permanent);
 -    return;
 +      src->proxy_id && src->proxy_pw) {
 +    /* wait for authenticate callback */
 +    return GST_FLOW_OK;
    }
  
 -  if (msg->status_code == SOUP_STATUS_UNAUTHORIZED)
 -    return;
 +  if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
 +    /* force an error */
 +    return gst_soup_http_src_parse_status (msg, src);
 +  }
  
 -  src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING;
    src->got_headers = TRUE;
 +  g_cond_broadcast (&src->have_headers_cond);
  
    http_headers = gst_structure_new_empty ("http-headers");
    gst_structure_set (http_headers, "uri", G_TYPE_STRING, src->location, NULL);
@@@ -1312,12 -1799,24 +1520,22 @@@ gst_soup_http_src_parse_status (SoupMes
      /* when content_size is unknown and we have just finished receiving
       * a body message, requests that go beyond the content limits will result
       * in an error. Here we convert those to EOS */
 -      src->ret = GST_FLOW_EOS;
 -      return;
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+     if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE &&
+         ((src->have_body && !src->have_size) ||
+          (src->have_size && src->request_position >= src->content_size))) {
+       GST_DEBUG_OBJECT (src, "Requested range out of limits and received full "
+           "body, returning EOS");
++      return GST_FLOW_EOS;
+     }
+ #else
      if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE &&
          src->have_body && !src->have_size) {
        GST_DEBUG_OBJECT (src, "Requested range out of limits and received full "
            "body, returning EOS");
 -      src->ret = GST_FLOW_EOS;
 -      return;
 +      return GST_FLOW_EOS;
      }
+ #endif
  
      /* FIXME: reason_phrase is not translated and not suitable for user
       * error dialog according to libsoup documentation.
@@@ -1378,15 -1903,22 +1625,16 @@@ gst_soup_http_src_build_message (GstSou
            *cookie);
      }
    }
+ #endif
  
 -  src->retry = FALSE;
 -
 -  g_signal_connect (src->msg, "got_headers",
 -      G_CALLBACK (gst_soup_http_src_got_headers_cb), src);
 -  g_signal_connect (src->msg, "got_body",
 -      G_CALLBACK (gst_soup_http_src_got_body_cb), src);
 -  g_signal_connect (src->msg, "finished",
 -      G_CALLBACK (gst_soup_http_src_finished_cb), src);
 -  g_signal_connect (src->msg, "got_chunk",
 -      G_CALLBACK (gst_soup_http_src_got_chunk_cb), src);
    soup_message_set_flags (src->msg, SOUP_MESSAGE_OVERWRITE_CHUNKS |
        (src->automatic_redirect ? 0 : SOUP_MESSAGE_NO_REDIRECT));
 -  soup_message_set_chunk_allocator (src->msg,
 -      gst_soup_http_src_chunk_allocator, src, NULL);
 +
 +  if (src->automatic_redirect) {
 +    g_signal_connect (src->msg, "restarted",
 +        G_CALLBACK (gst_soup_http_src_restarted_cb), src);
 +  }
 +
    gst_soup_http_src_add_range_header (src, src->request_position,
        src->stop_position);
  
@@@ -1462,181 -1959,84 +1715,187 @@@ gst_soup_http_src_do_request (GstSoupHT
      if (!gst_soup_http_src_build_message (src, method)) {
        return GST_FLOW_ERROR;
      }
 +  }
  
 -  src->ret = GST_FLOW_CUSTOM_ERROR;
 -  src->outbuf = outbuf;
 -  do {
 -    if (src->interrupted) {
 -      GST_INFO_OBJECT (src, "interrupted");
 -      src->ret = GST_FLOW_FLUSHING;
 -      break;
 -    }
 -    if (src->retry) {
 -      GST_INFO_OBJECT (src, "Reconnecting");
 -      if (!gst_soup_http_src_build_message (src, method)) {
 -        return GST_FLOW_ERROR;
 -      }
 -      src->retry = FALSE;
 -      continue;
 +  if (g_cancellable_is_cancelled (src->cancellable)) {
 +    GST_INFO_OBJECT (src, "interrupted");
 +    return GST_FLOW_FLUSHING;
 +  }
 +
 +  ret = gst_soup_http_src_send_message (src);
 +
 +  /* Check if Range header was respected. */
++#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
++  if (ret == GST_FLOW_OK && src->request_position > 0 &&
++      (src->msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) &&
++        (src->request_position < src->content_size)) {
++#else
 +  if (ret == GST_FLOW_OK && src->request_position > 0 &&
 +      src->msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) {
++#endif
 +    src->seekable = FALSE;
 +    GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, SEEK,
 +        (_("Server does not support seeking.")),
 +        ("Server does not accept Range HTTP header, URL: %s, Redirect to: %s",
 +            src->location, GST_STR_NULL (src->redirection_uri)),
 +        ("http-status-code", G_TYPE_UINT, src->msg->status_code,
 +            "http-redirection-uri", G_TYPE_STRING,
 +            GST_STR_NULL (src->redirection_uri), NULL));
 +    ret = GST_FLOW_ERROR;
 +  }
 +
 +  return ret;
 +}
 +
 +/*
 + * Check if the bytes_read is above a certain threshold of the blocksize, if
 + * that happens a few times in a row, increase the blocksize; Do the same in
 + * the opposite direction to reduce the blocksize.
 + */
 +static void
 +gst_soup_http_src_check_update_blocksize (GstSoupHTTPSrc * src,
 +    gint64 bytes_read)
 +{
 +  guint blocksize = gst_base_src_get_blocksize (GST_BASE_SRC_CAST (src));
 +
 +  GST_LOG_OBJECT (src, "Checking to update blocksize. Read:%" G_GINT64_FORMAT
 +      " blocksize:%u", bytes_read, blocksize);
 +
 +  if (bytes_read >= blocksize * GROW_BLOCKSIZE_LIMIT) {
 +    src->reduce_blocksize_count = 0;
 +    src->increase_blocksize_count++;
 +
 +    if (src->increase_blocksize_count >= GROW_BLOCKSIZE_COUNT) {
 +      blocksize *= GROW_BLOCKSIZE_FACTOR;
 +      GST_DEBUG_OBJECT (src, "Increased blocksize to %u", blocksize);
 +      gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src), blocksize);
 +      src->increase_blocksize_count = 0;
      }
 -    if (!src->msg) {
 -      GST_DEBUG_OBJECT (src, "EOS reached");
 -      break;
 +  } else if (bytes_read < blocksize * REDUCE_BLOCKSIZE_LIMIT) {
 +    src->reduce_blocksize_count++;
 +    src->increase_blocksize_count = 0;
 +
 +    if (src->reduce_blocksize_count >= REDUCE_BLOCKSIZE_COUNT) {
 +      blocksize *= REDUCE_BLOCKSIZE_FACTOR;
 +      blocksize = MAX (blocksize, src->minimum_blocksize);
 +      GST_DEBUG_OBJECT (src, "Decreased blocksize to %u", blocksize);
 +      gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src), blocksize);
 +      src->reduce_blocksize_count = 0;
      }
 +  } else {
 +    src->reduce_blocksize_count = src->increase_blocksize_count = 0;
 +  }
 +}
  
 -    switch (src->session_io_status) {
 -      case GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_IDLE:
 -        GST_INFO_OBJECT (src, "Queueing connection request");
 -        gst_soup_http_src_queue_message (src);
 -        break;
 -      case GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_QUEUED:
 -        break;
 -      case GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING:
 -        gst_soup_http_src_session_unpause_message (src);
 -        break;
 -      case GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_CANCELLED:
 -        /* Impossible. */
 -        break;
 -    }
 +static void
 +gst_soup_http_src_update_position (GstSoupHTTPSrc * src, gint64 bytes_read)
 +{
 +  GstBaseSrc *basesrc = GST_BASE_SRC_CAST (src);
 +  guint64 new_position;
  
 -    if (src->ret == GST_FLOW_CUSTOM_ERROR) {
 -      g_main_context_push_thread_default (src->context);
 -      g_main_loop_run (src->loop);
 -      g_main_context_pop_thread_default (src->context);
 +  new_position = src->read_position + bytes_read;
 +  if (G_LIKELY (src->request_position == src->read_position))
 +    src->request_position = new_position;
 +  src->read_position = new_position;
 +
 +  if (src->have_size) {
 +    if (new_position > src->content_size) {
 +      GST_DEBUG_OBJECT (src, "Got position previous estimated content size "
 +          "(%" G_GINT64_FORMAT " > %" G_GINT64_FORMAT ")", new_position,
 +          src->content_size);
 +      src->content_size = new_position;
 +      basesrc->segment.duration = src->content_size;
 +      gst_element_post_message (GST_ELEMENT (src),
 +          gst_message_new_duration_changed (GST_OBJECT (src)));
 +    } else if (new_position == src->content_size) {
 +      GST_DEBUG_OBJECT (src, "We're EOS now");
      }
 +  }
 +}
  
 -  } while (src->ret == GST_FLOW_CUSTOM_ERROR);
 -
 -  /* Let the request finish if we had a stop position and are there */
 -  if (src->ret == GST_FLOW_OK && src->stop_position != -1
 -      && src->read_position >= src->stop_position) {
 -    src->outbuf = NULL;
 -    gst_soup_http_src_session_unpause_message (src);
 -    g_main_context_push_thread_default (src->context);
 -    g_main_loop_run (src->loop);
 -    g_main_context_pop_thread_default (src->context);
 -
 -    g_cond_signal (&src->request_finished_cond);
 -    /* Return OK unconditionally here, src->ret will
 -     * be most likely be EOS now but we want to
 -     * consume the buffer we got above */
 -    return GST_FLOW_OK;
 +static GstFlowReturn
 +gst_soup_http_src_read_buffer (GstSoupHTTPSrc * src, GstBuffer ** outbuf)
 +{
 +  gssize read_bytes;
 +  GstMapInfo mapinfo;
 +  GstBaseSrc *bsrc;
 +  GstFlowReturn ret;
 +
 +  bsrc = GST_BASE_SRC_CAST (src);
 +
 +  *outbuf = gst_soup_http_src_alloc_buffer (src);
 +  if (!*outbuf) {
 +    GST_WARNING_OBJECT (src, "Failed to allocate buffer");
 +    return GST_FLOW_ERROR;
    }
  
 -  if (src->ret == GST_FLOW_CUSTOM_ERROR)
 -    src->ret = GST_FLOW_EOS;
 -  g_cond_signal (&src->request_finished_cond);
 +  if (!gst_buffer_map (*outbuf, &mapinfo, GST_MAP_WRITE)) {
 +    GST_WARNING_OBJECT (src, "Failed to map buffer");
 +    return GST_FLOW_ERROR;
 +  }
  
 -  /* basesrc assumes that we don't return a buffer if
 -   * something else than OK is returned. It will just
 -   * leak any buffer we might accidentially provide
 -   * here.
 -   *
 -   * This can potentially happen during flushing.
 -   */
 -  if (src->ret != GST_FLOW_OK && outbuf && *outbuf) {
 +  read_bytes =
 +      g_input_stream_read (src->input_stream, mapinfo.data, mapinfo.size,
 +      src->cancellable, NULL);
 +  GST_DEBUG_OBJECT (src, "Read %" G_GSSIZE_FORMAT " bytes from http input",
 +      read_bytes);
 +
 +  g_mutex_lock (&src->mutex);
 +  if (g_cancellable_is_cancelled (src->cancellable)) {
 +    gst_buffer_unmap (*outbuf, &mapinfo);
      gst_buffer_unref (*outbuf);
 -    *outbuf = NULL;
 +    g_mutex_unlock (&src->mutex);
 +    return GST_FLOW_FLUSHING;
 +  }
 +
 +  gst_buffer_unmap (*outbuf, &mapinfo);
 +  if (read_bytes > 0) {
 +    gst_buffer_set_size (*outbuf, read_bytes);
 +    GST_BUFFER_OFFSET (*outbuf) = bsrc->segment.position;
 +    ret = GST_FLOW_OK;
 +    gst_soup_http_src_update_position (src, read_bytes);
 +
 +    /* Got some data, reset retry counter */
 +    src->retry_count = 0;
 +
 +    gst_soup_http_src_check_update_blocksize (src, read_bytes);
 +
 +    /* If we're at the end of a range request, read again to let libsoup
 +     * finalize the request. This allows to reuse the connection again later,
 +     * otherwise we would have to cancel the message and close the connection
 +     */
 +    if (bsrc->segment.stop != -1
 +        && bsrc->segment.position + read_bytes >= bsrc->segment.stop) {
 +      guint8 tmp[128];
 +
 +      g_object_unref (src->msg);
 +      src->msg = NULL;
 +      src->have_body = TRUE;
 +
 +      /* This should return immediately as we're at the end of the range */
 +      read_bytes =
 +          g_input_stream_read (src->input_stream, tmp, sizeof (tmp),
 +          src->cancellable, NULL);
 +      if (read_bytes > 0)
 +        GST_ERROR_OBJECT (src,
 +            "Read %" G_GSIZE_FORMAT " bytes after end of range", read_bytes);
 +    }
 +  } else {
 +    gst_buffer_unref (*outbuf);
 +    if (read_bytes < 0 ||
 +        (src->have_size && src->read_position < src->content_size)) {
 +      /* Maybe the server disconnected, retry */
 +      ret = GST_FLOW_CUSTOM_ERROR;
 +    } else {
 +      g_object_unref (src->msg);
 +      src->msg = NULL;
 +      ret = GST_FLOW_EOS;
 +      src->have_body = TRUE;
 +    }
    }
 +  g_mutex_unlock (&src->mutex);
  
 -  return src->ret;
 +  return ret;
  }
  
  static GstFlowReturn
@@@ -109,9 -111,13 +111,13 @@@ struct _GstSoupHTTPSrc 
    guint timeout;
  
    GMutex mutex;
 -  GCond request_finished_cond;
 +  GCond have_headers_cond;
  
    GstEvent *http_headers_event;
+ #ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+   gchar *dash_oldest_segment;
+   gchar *dash_newest_segment;
+ #endif
  };
  
  struct _GstSoupHTTPSrcClass {
@@@ -73,9 -73,18 +73,18 @@@ GST_DEBUG_CATEGORY_STATIC (aacparse_deb
                                     headers prepended during raw to ADTS
                                     conversion */
  
+ #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION      /* to get more accurate duration */
+ #define AAC_MAX_ESTIMATE_DURATION_BUF (1024 * 1024)     /* use first 1 Mbyte */
+ #define AAC_SAMPLE_PER_FRAME 1024
+ #define AAC_MAX_PULL_RANGE_BUF  (1 * 1024 * 1024)       /* 1 MByte */
+ #define AAC_LARGE_FILE_SIZE     (2 * 1024 * 1024)       /* 2 MByte */
+ #define gst_aac_parse_parent_class parent_class
+ #endif
  #define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
  
 -static const gint loas_sample_rate_table[32] = {
 +static const gint loas_sample_rate_table[16] = {
    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
    16000, 12000, 11025, 8000, 7350, 0, 0, 0
  };
@@@ -97,17 -106,35 +106,42 @@@ static GstFlowReturn gst_aac_parse_hand
      GstBaseParseFrame * frame, gint * skipsize);
  static GstFlowReturn gst_aac_parse_pre_push_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame);
 +static gboolean gst_aac_parse_src_event (GstBaseParse * parse,
 +    GstEvent * event);
 +
 +static gboolean gst_aac_parse_read_audio_specific_config (GstAacParse *
 +    aacparse, GstBitReader * br, gint * object_type, gint * sample_rate,
 +    gint * channels, gint * frame_samples);
  
+ #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
+ static guint gst_aac_parse_adts_get_fast_frame_len (const guint8 * data);
+ static gboolean gst_aac_parse_src_eventfunc (GstBaseParse * parse,
+     GstEvent * event);
+ /* make full aac(adts) index table when seek */
+ static gboolean gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse,
+     GstEvent * event);
+ int get_aac_parse_get_adts_frame_length (const unsigned char *data,
+     gint64 offset);
+ static gboolean gst_aac_parse_estimate_duration (GstBaseParse * parse);
+ #endif
  
 +#define gst_aac_parse_parent_class parent_class
  G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE);
  
+ #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
+ static inline gint
+ gst_aac_parse_get_sample_rate_from_index (guint sr_idx)
+ {
+   static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
+     32000, 24000, 22050, 16000, 12000, 11025, 8000
+   };
+   if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
+     return aac_sample_rates[sr_idx];
+   GST_WARNING ("Invalid sample rate index %u", sr_idx);
+   return 0;
+ }
+ #endif
  /**
   * gst_aac_parse_class_init:
   * @klass: #GstAacParseClass.
@@@ -136,7 -165,10 +170,12 @@@ gst_aac_parse_class_init (GstAacParseCl
    parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_handle_frame);
    parse_class->pre_push_frame =
        GST_DEBUG_FUNCPTR (gst_aac_parse_pre_push_frame);
 -#ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
 +  parse_class->src_event = GST_DEBUG_FUNCPTR (gst_aac_parse_src_event);
++
++//#ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION // FIXME
+   /* make full aac(adts) index table when seek */
 -  parse_class->src_event = GST_DEBUG_FUNCPTR (gst_aac_parse_src_eventfunc);
 -#endif
++//  parse_class->src_event = GST_DEBUG_FUNCPTR (gst_aac_parse_src_eventfunc);
++//#endif
  }
  
  
@@@ -152,9 -184,10 +191,13 @@@ gst_aac_parse_init (GstAacParse * aacpa
    GST_DEBUG ("initialized");
    GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (aacparse));
    GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (aacparse));
 +
 +  aacparse->last_parsed_sample_rate = 0;
 +  aacparse->last_parsed_channels = 0;
+ #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
+   /* to get more correct duration */
+   aacparse->first_frame = TRUE;
+ #endif
  }
  
  
@@@ -1653,15 -1632,600 +1721,613 @@@ gst_aac_parse_sink_getcaps (GstBasePars
    return res;
  }
  
 +static gboolean
 +gst_aac_parse_src_event (GstBaseParse * parse, GstEvent * event)
 +{
 +  GstAacParse *aacparse = GST_AAC_PARSE (parse);
 +
 +  if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
 +    aacparse->last_parsed_channels = 0;
 +    aacparse->last_parsed_sample_rate = 0;
 +  }
 +
 +  return GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
 +}
++
+ #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
+ /**
+  * get_aac_parse_get_adts_framelength:
+  * @data: #GstBufferData.
+  * @offset: #GstBufferData offset
+  *
+  * Implementation to get adts framelength by using first some frame.
+  *
+  * Returns: frame size
+  */
+ int
+ get_aac_parse_get_adts_frame_length (const unsigned char *data, gint64 offset)
+ {
+   const gint adts_header_length_no_crc = 7;
+   const gint adts_header_length_with_crc = 9;
+   gint frame_size = 0;
+   gint protection_absent;
+   gint head_size;
+   /* check of syncword */
+   if ((data[offset + 0] != 0xff) || ((data[offset + 1] & 0xf6) != 0xf0)) {
+     GST_ERROR ("check sync word is fail\n");
+     return -1;
+   }
+   /* check of protection absent */
+   protection_absent = (data[offset + 1] & 0x01);
+   /*check of frame length */
+   frame_size =
+       (data[offset + 3] & 0x3) << 11 | data[offset + 4] << 3 | data[offset +
+       5] >> 5;
+   /* check of header size */
+   /* protectionAbsent is 0 if there is CRC */
+   head_size =
+       protection_absent ? adts_header_length_no_crc :
+       adts_header_length_with_crc;
+   if (head_size > frame_size) {
+     GST_ERROR ("return frame length as 0 (frameSize %u < headSize %u)",
+         frame_size, head_size);
+     return 0;
+   }
+   return frame_size;
+ }
+ /**
+  * gst_aac_parse_estimate_duration:
+  * @parse: #GstBaseParse.
+  *
+  * Implementation to get estimated total duration by using first some frame.
+  *
+  * Returns: TRUE if we can get estimated total duraion
+  */
+ static gboolean
+ gst_aac_parse_estimate_duration (GstBaseParse * parse)
+ {
+   gboolean ret = FALSE;
+   GstFlowReturn res = GST_FLOW_OK;
+   gint64 pull_size = 0, file_size = 0, offset = 0, num_frames = 0, duration = 0;
+   guint sample_rate_index = 0, sample_rate = 0, channel = 0;
+   guint frame_size = 0, frame_duration_us = 0, estimated_bitrate = 0;
+   guint lost_sync_count = 0;
+   GstClockTime estimated_duration = GST_CLOCK_TIME_NONE;
+   GstBuffer *buffer = NULL;
+   guint8 *buf = NULL;
+   gint i = 0;
+   GstPadMode pad_mode = GST_PAD_MODE_NONE;
+   GstAacParse *aacparse;
+   gint64 buffer_size = 0;
+   GstMapInfo map;
+   aacparse = GST_AAC_PARSE (parse);
+   GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
+   /* check baseparse define these fuction */
+   gst_base_parse_get_pad_mode (parse, &pad_mode);
+   if (pad_mode != GST_PAD_MODE_PULL) {
+     GST_INFO_OBJECT (aacparse,
+         "aac parser is not pull mode. can not estimate duration");
+     return FALSE;
+   }
+   gst_base_parse_get_upstream_size (parse, &file_size);
+   if (file_size < ADIF_MAX_SIZE) {
+     GST_ERROR_OBJECT (aacparse, "file size is too short");
+     return FALSE;
+   }
+   pull_size = MIN (file_size, AAC_MAX_ESTIMATE_DURATION_BUF);
+   res = gst_pad_pull_range (parse->sinkpad, 0, pull_size, &buffer);
+   if (res != GST_FLOW_OK) {
+     GST_ERROR_OBJECT (aacparse, "gst_pad_pull_range failed!");
+     return FALSE;
+   }
+   gst_buffer_map (buffer, &map, GST_MAP_READ);
+   buf = map.data;
+   buffer_size = map.size;
+   if (buffer_size != pull_size) {
+     GST_ERROR_OBJECT (aacparse,
+         "We got different buffer_size(%" G_GINT64_FORMAT ") with pull_size(%"
+         G_GINT64_FORMAT ").", buffer_size, pull_size);
+   }
+   /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
+   for (i = 0; i < buffer_size; i++) {
+     if ((buf[i] == 0xff) && ((buf[i + 1] & 0xf6) == 0xf0)) {    /* aac sync word */
+       //guint profile = (buf[i+2] >> 6) & 0x3;
+       sample_rate_index = (buf[i + 2] >> 2) & 0xf;
+       sample_rate =
+           gst_aac_parse_get_sample_rate_from_index (sample_rate_index);
+       if (sample_rate == 0) {
+         GST_WARNING_OBJECT (aacparse, "Invalid sample rate index (0)");
+         goto EXIT;
+       }
+       channel = (buf[i + 2] & 0x1) << 2 | (buf[i + 3] >> 6);
+       GST_INFO_OBJECT (aacparse, "found sync. aac fs=%d, ch=%d", sample_rate,
+           channel);
+       /* count number of frames */
+       /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
+       //while (offset < pull_size) {
+       while (offset < buffer_size) {
+         frame_size = get_aac_parse_get_adts_frame_length (buf, i + offset);
+         if (frame_size == 0) {
+           GST_ERROR_OBJECT (aacparse,
+               "framesize error at offset %" G_GINT64_FORMAT, offset);
+           break;
+         } else if (frame_size == -1) {
+           offset++;
+           lost_sync_count++;    //  lost sync count limmitation 2K Bytes
+           if (lost_sync_count > (1024 * 2)) {
+             GST_WARNING_OBJECT (aacparse,
+                 "lost_sync_count is larger than 2048");
+             goto EXIT;
+           }
+         } else {
+           offset += frame_size;
+           num_frames++;
+           lost_sync_count = 0;
+         }
+       }                         /* while */
+       /* if we can got full file, we can calculate the accurate duration */
+       /* MODIFICATION : add defence codes for real buffer_size is different with pull_size */
+       //if (pull_size == file_size) {
+       if (buffer_size == file_size) {
+         gfloat duration_for_one_frame = 0;
+         GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
+         GST_INFO_OBJECT (aacparse,
+             "we got total file (%" G_GINT64_FORMAT
+             " bytes). do not estimate but make Accurate total duration.",
+             pull_size);
+         duration_for_one_frame =
+             (gfloat) AAC_SAMPLE_PER_FRAME / (gfloat) sample_rate;
+         calculated_duration =
+             num_frames * duration_for_one_frame * 1000 * 1000 * 1000;
+         GST_INFO_OBJECT (aacparse, "duration_for_one_frame %f ms",
+             duration_for_one_frame);
+         GST_INFO_OBJECT (aacparse, "calculated duration = %" GST_TIME_FORMAT,
+             GST_TIME_ARGS (calculated_duration));
+         /* 0 means disable estimate */
+         gst_base_parse_set_duration (parse, GST_FORMAT_TIME,
+             calculated_duration, 0);
+       } else {
+         GST_INFO_OBJECT (aacparse,
+             "we got %" G_GUINT64_FORMAT " bytes in total file (%"
+             G_GINT64_FORMAT "). can not make accurate duration but Estimate.",
+             pull_size, file_size);
+         frame_duration_us =
+             (1024 * 1000000ll + (sample_rate - 1)) / sample_rate;
+         duration = num_frames * frame_duration_us;
+         if (duration == 0) {
+           GST_WARNING_OBJECT (aacparse, "Invalid duration");
+           goto EXIT;
+         }
+         estimated_bitrate =
+             (gint) ((gfloat) (offset * 8) / (gfloat) (duration / 1000));
+         if (estimated_bitrate == 0) {
+           GST_WARNING_OBJECT (aacparse, "Invalid estimated_bitrate");
+           goto EXIT;
+         }
+         estimated_duration =
+             (GstClockTime) ((file_size * 8) / (estimated_bitrate * 1000)) *
+             GST_SECOND;
+         GST_INFO_OBJECT (aacparse, "number of frame = %" G_GINT64_FORMAT,
+             num_frames);
+         GST_INFO_OBJECT (aacparse, "duration = %" G_GINT64_FORMAT,
+             duration / 1000000);
+         GST_INFO_OBJECT (aacparse, "byte = %" G_GINT64_FORMAT, offset);
+         GST_INFO_OBJECT (aacparse, "estimated bitrate = %d bps",
+             estimated_bitrate);
+         GST_INFO_OBJECT (aacparse, "estimated duration = %" GST_TIME_FORMAT,
+             GST_TIME_ARGS (estimated_duration));
+         gst_base_parse_set_average_bitrate (parse, estimated_bitrate * 1000);
+         /* set update_interval as duration(sec)/2 */
+         gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration,
+             (gint) (duration / 2));
+       }
+       break;
+     }
+   }
+   ret = TRUE;
+ EXIT:
+   gst_buffer_unmap (buffer, &map);
+   gst_buffer_unref (buffer);
+   return ret;
+ }
+ /* perform seek in push based mode:
+    find BYTE position to move to based on time and delegate to upstream
+ */
+ static gboolean
+ gst_aac_audio_parse_do_push_seek (GstBaseParse * parse,
+     GstPad * pad, GstEvent * event)
+ {
+   GstAacParse *aacparse = GST_AAC_PARSE (parse);
+   gdouble rate;
+   GstFormat format;
+   GstSeekFlags flags;
+   GstSeekType cur_type, stop_type;
+   gint64 cur, stop;
+   gboolean res;
+   gint64 byte_cur;
+   gint64 esimate_byte;
+   gint32 frame_dur;
+   gint64 upstream_total_bytes = 0;
+   GstFormat fmt = GST_FORMAT_BYTES;
+   GST_INFO_OBJECT (parse, "doing aac push-based seek");
+   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
+       &stop_type, &stop);
+   /* FIXME, always play to the end */
+   stop = -1;
+   /* only forward streaming and seeking is possible */
+   if (rate <= 0)
+     goto unsupported_seek;
+   if (cur == 0) {
+     /* handle rewind only */
+     cur_type = GST_SEEK_TYPE_SET;
+     byte_cur = 0;
+     stop_type = GST_SEEK_TYPE_NONE;
+     stop = -1;
+     flags |= GST_SEEK_FLAG_FLUSH;
+   } else {
+     /* handle normal seek */
+     cur_type = GST_SEEK_TYPE_SET;
+     stop_type = GST_SEEK_TYPE_NONE;
+     stop = -1;
+     flags |= GST_SEEK_FLAG_FLUSH;
+     esimate_byte = (cur / (1000 * 1000)) * aacparse->frame_byte;
+     if (aacparse->sample_rate > 0)
+       frame_dur = (aacparse->spf * 1000) / aacparse->sample_rate;
+     else
+       goto unsupported_seek;
+     if (frame_dur > 0)
+       byte_cur = esimate_byte / (frame_dur);
+     else
+       goto unsupported_seek;
+     GST_INFO_OBJECT (parse, "frame_byte(%d) spf(%d)  rate (%d) ",
+         aacparse->frame_byte, aacparse->spf, aacparse->sample_rate);
+     GST_INFO_OBJECT (parse,
+         "seek cur (%" G_GINT64_FORMAT ") = (%" GST_TIME_FORMAT ") ", cur,
+         GST_TIME_ARGS (cur));
+     GST_INFO_OBJECT (parse,
+         "esimate_byte(%" G_GINT64_FORMAT ")  esimate_byte (%d)", esimate_byte,
+         frame_dur);
+   }
+   /* obtain real upstream total bytes */
+   if (!gst_pad_peer_query_duration (parse->sinkpad, fmt, &upstream_total_bytes))
+     upstream_total_bytes = 0;
+   GST_INFO_OBJECT (aacparse,
+       "gst_pad_query_peer_duration -upstream_total_bytes (%" G_GUINT64_FORMAT
+       ")", upstream_total_bytes);
+   aacparse->file_size = upstream_total_bytes;
+   if ((byte_cur == -1) || (byte_cur > aacparse->file_size)) {
+     GST_INFO_OBJECT (parse,
+         "[WEB-ERROR] seek cur (%" G_GINT64_FORMAT ") > file_size (%"
+         G_GINT64_FORMAT ") ", cur, aacparse->file_size);
+     goto abort_seek;
+   }
+   GST_INFO_OBJECT (parse,
+       "Pushing BYTE seek rate %g, " "start %" G_GINT64_FORMAT ", stop %"
+       G_GINT64_FORMAT, rate, byte_cur, stop);
+   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
+     GST_INFO_OBJECT (parse,
+         "Requested seek time: %" GST_TIME_FORMAT ", calculated seek offset: %"
+         G_GUINT64_FORMAT, GST_TIME_ARGS (cur), byte_cur);
+   }
+   /* BYTE seek event */
+   event =
+       gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
+       stop_type, stop);
+   res = gst_pad_push_event (parse->sinkpad, event);
+   return res;
+   /* ERRORS */
+ abort_seek:
+   {
+     GST_DEBUG_OBJECT (parse,
+         "could not determine byte position to seek to, " "seek aborted.");
+     return FALSE;
+   }
+ unsupported_seek:
+   {
+     GST_DEBUG_OBJECT (parse, "unsupported seek, seek aborted.");
+     return FALSE;
+   }
+ }
+ static guint
+ gst_aac_parse_adts_get_fast_frame_len (const guint8 * data)
+ {
+   int length;
+   if ((data[0] == 0xff) && ((data[1] & 0xf6) == 0xf0)) {
+     length =
+         ((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] & 0xe0) >> 5);
+   } else {
+     length = 0;
+   }
+   return length;
+ }
+ static gboolean
+ gst_aac_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+ {
+   gboolean handled = FALSE;
+   GstAacParse *aacparse;
+   aacparse = GST_AAC_PARSE (parse);
+   GST_DEBUG ("Entering gst_aac_parse_src_eventfunc header type = %d",
+       aacparse->header_type);
+   if (aacparse->header_type == DSPAAC_HEADER_ADTS)
+     return gst_aac_parse_adts_src_eventfunc (parse, event);
+   else
+     goto aac_seek_null_exit;
+ aac_seek_null_exit:
+   /* call baseparse src_event function to handle event */
+   handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
+   return handled;
+ }
+ /**
+  * gst_aac_parse_adts_src_eventfunc:
+  * @parse: #GstBaseParse. #event
+  *
+  * before baseparse handles seek event, make full amr index table.
+  *
+  * Returns: TRUE on success.
+  */
+ static gboolean
+ gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+ {
+   gboolean handled = FALSE;
+   GstAacParse *aacparse = GST_AAC_PARSE (parse);
+   switch (GST_EVENT_TYPE (event)) {
+     case GST_EVENT_SEEK:
+     {
+       GstFlowReturn res = GST_FLOW_OK;
+       gint64 base_offset = 0, cur = 0;
+       gint32 frame_count = 1;   /* do not add first frame because it is already in index table */
+       gint64 second_count = 0;  /* initial 1 second */
+       gint64 total_file_size = 0, start_offset = 0;
+       GstClockTime current_ts = GST_CLOCK_TIME_NONE;
+       GstPadMode pad_mode = GST_PAD_MODE_NONE;
+       /* check baseparse define these fuction */
+       gst_base_parse_get_pad_mode (parse, &pad_mode);
+       if (pad_mode != GST_PAD_MODE_PULL) {
+         gboolean ret = FALSE;
+         GstPad *srcpad = parse->srcpad;
+         GST_INFO_OBJECT (aacparse, "aac parser is PUSH MODE.");
+         /* check NULL */
+         ret = gst_aac_audio_parse_do_push_seek (parse, srcpad, event);
+         gst_object_unref (srcpad);
+         return ret;
+       }
+       gst_base_parse_get_upstream_size (parse, &total_file_size);
+       gst_base_parse_get_index_last_offset (parse, &start_offset);
+       gst_base_parse_get_index_last_ts (parse, &current_ts);
+       if (total_file_size > AAC_LARGE_FILE_SIZE) {
+         gst_base_parse_set_seek_mode (parse, 0);
+         GST_INFO_OBJECT (aacparse, "larger than big size (2MB).");
+         goto aac_seek_null_exit;
+       }
+       GST_DEBUG ("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK enter");
+       if (total_file_size == 0 || start_offset >= total_file_size) {
+         GST_ERROR ("last index offset %" G_GINT64_FORMAT
+             " is larger than file size %" G_GINT64_FORMAT, start_offset,
+             total_file_size);
+         break;
+       }
+       gst_event_parse_seek (event, NULL, NULL, NULL, NULL, &cur, NULL, NULL);
+       if (cur <= current_ts) {
+         GST_INFO ("seek to %" GST_TIME_FORMAT " within index table %"
+             GST_TIME_FORMAT ". do not make index table", GST_TIME_ARGS (cur),
+             GST_TIME_ARGS (current_ts));
+         break;
+       } else {
+         GST_INFO ("seek to %" GST_TIME_FORMAT " without index table %"
+             GST_TIME_FORMAT ". make index table", GST_TIME_ARGS (cur),
+             GST_TIME_ARGS (current_ts));
+       }
+       GST_INFO ("make AAC(ADTS) Index Table. file_size  = %" G_GINT64_FORMAT
+           " last idx offset=%" G_GINT64_FORMAT ", last idx ts=%"
+           GST_TIME_FORMAT, total_file_size, start_offset,
+           GST_TIME_ARGS (current_ts));
+       base_offset = start_offset;       /* set base by start offset */
+       second_count = current_ts + GST_SECOND;   /* 1sec */
+       /************************************/
+       /* STEP 0: Setting parse information */
+       /************************************/
+       aacparse->spf = aacparse->frame_samples;
+       aacparse->frame_duration = (aacparse->spf * 1000 * 100) / aacparse->sample_rate;  /* duration per frame (msec) */
+       aacparse->frame_per_sec = (aacparse->sample_rate) / aacparse->spf;        /* frames per second (ea) */
+       /************************************/
+       /* STEP 1: MAX_PULL_RANGE_BUF cycle */
+       /************************************/
+       while (total_file_size - base_offset >= AAC_MAX_PULL_RANGE_BUF) {
+         gint64 offset = 0;
+         GstBuffer *buffer = NULL;
+         guint8 *buf = NULL;
+         GstMapInfo map;
+         GST_INFO ("gst_pad_pull_range %d bytes (from %" G_GINT64_FORMAT
+             ") use max size", AAC_MAX_PULL_RANGE_BUF, base_offset);
+         res =
+             gst_pad_pull_range (parse->sinkpad, base_offset,
+             base_offset + AAC_MAX_PULL_RANGE_BUF, &buffer);
+         if (res != GST_FLOW_OK) {
+           GST_ERROR ("gst_pad_pull_range failed!");
+           break;
+         }
+         gst_buffer_map (buffer, &map, GST_MAP_READ);
+         buf = map.data;
+         if (buf == NULL) {
+           gst_buffer_unmap (buffer, &map);
+           GST_WARNING ("buffer is NULL in make aac seek table's STEP1");
+           gst_buffer_unref (buffer);
+           goto aac_seek_null_exit;
+         }
+         while (offset <= AAC_MAX_PULL_RANGE_BUF) {
+           gint frame_size = 0;
+           /* make sure the values in the frame header look sane */
+           frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
+           if ((frame_size > 0)
+               && (frame_size < (AAC_MAX_PULL_RANGE_BUF - offset))) {
+             if (current_ts > second_count) {    /* 1 sec == xx frames. we make idx per sec */
+               gst_base_parse_add_index_entry (parse, base_offset + offset, current_ts, TRUE, TRUE);     /* force */
+               GST_DEBUG ("Adding  index ts=%" GST_TIME_FORMAT " offset %"
+                   G_GINT64_FORMAT, GST_TIME_ARGS (current_ts),
+                   base_offset + offset);
+               second_count += GST_SECOND;       /* 1sec */
+             }
+             current_ts += (aacparse->frame_duration * GST_MSECOND) / 100;       /* each frame is (frame_duration) ms */
+             offset += frame_size;
+             buf += frame_size;
+             frame_count++;
+           } else if (frame_size >= (AAC_MAX_PULL_RANGE_BUF - offset)) {
+             GST_DEBUG ("we need refill buffer");
+             break;
+           } else {
+             GST_WARNING ("we lost sync");
+             buf++;
+             offset++;
+           }
+         }                       /* while */
+         base_offset = base_offset + offset;
+         gst_buffer_unmap (buffer, &map);
+         gst_buffer_unref (buffer);
+       }                         /* end MAX buffer cycle */
+       /*******************************/
+       /* STEP 2: Remain Buffer cycle */
+       /*******************************/
+       if (total_file_size - base_offset > 0) {
+         gint64 offset = 0;
+         GstBuffer *buffer = NULL;
+         guint8 *buf = NULL;
+         GstMapInfo map;
+         GST_INFO ("gst_pad_pull_range %" G_GINT64_FORMAT " bytes (from %"
+             G_GINT64_FORMAT ") use remain_buf size",
+             total_file_size - base_offset, base_offset);
+         res =
+             gst_pad_pull_range (parse->sinkpad, base_offset, total_file_size,
+             &buffer);
+         if (res != GST_FLOW_OK) {
+           GST_ERROR ("gst_pad_pull_range failed!");
+           break;
+         }
+         gst_buffer_map (buffer, &map, GST_MAP_READ);
+         buf = map.data;
+         if (buf == NULL) {
+           gst_buffer_unmap (buffer, &map);
+           GST_WARNING ("buffer is NULL in make aac seek table's STEP2");
+           gst_buffer_unref (buffer);
+           goto aac_seek_null_exit;
+         }
+         while (base_offset + offset < total_file_size) {
+           gint frame_size = 0;
+           /* make sure the values in the frame header look sane */
+           frame_size = gst_aac_parse_adts_get_fast_frame_len (buf);
+           if ((frame_size > 0)
+               && (frame_size <= (total_file_size - (base_offset + offset)))) {
+             if (current_ts > second_count) {    /* 1 sec == xx frames. we make idx per sec */
+               gst_base_parse_add_index_entry (parse, base_offset + offset, current_ts, TRUE, TRUE);     /* force */
+               GST_DEBUG ("Adding  index ts=%" GST_TIME_FORMAT " offset %"
+                   G_GINT64_FORMAT, GST_TIME_ARGS (current_ts),
+                   base_offset + offset);
+               second_count += GST_SECOND;       /* 1sec */
+             }
+             current_ts += (aacparse->frame_duration * GST_MSECOND) / 100;       /* each frame is (frame_duration) ms */
+             offset += frame_size;
+             buf += frame_size;
+             frame_count++;
+           } else if (frame_size == 0) {
+             GST_DEBUG ("Frame size is 0 so, Decoding end..");
+             break;
+           } else {
+             GST_WARNING ("we lost sync");
+             buf++;
+             offset++;
+           }
+         }                       /* while */
+         gst_buffer_unmap (buffer, &map);
+         gst_buffer_unref (buffer);
+       }
+       /* end remain_buf buffer cycle */
+       GST_DEBUG ("gst_aac_parse_adts_src_eventfunc GST_EVENT_SEEK leave");
+     }
+       break;
+     default:
+       break;
+   }
+ aac_seek_null_exit:
+   /* call baseparse src_event function to handle event */
+   handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
+   return handled;
+ }
+ #endif //end of #ifdef TIZEN_FEATURE_AACPARSE_MODIFICATION
Simple merge
Simple merge
index 37d552a,aa1bed5..37d552a
mode 100644,100755..100755
Simple merge
Simple merge
@@@ -268,8 -267,9 +268,11 @@@ enu
    PROP_DTS_METHOD,
  #endif
    PROP_DO_CTTS,
 +  PROP_INTERLEAVE_BYTES,
 +  PROP_INTERLEAVE_TIME,
+ #ifdef TIZEN_FEATURE_GST_MUX_ENHANCEMENT
+   PROP_EXPECTED_TRAILER_SIZE,
+ #endif /* TIZEN_FEATURE_GST_MUX_ENHANCEMENT */
  };
  
  /* some spare for header size as well */
@@@ -483,17 -705,17 +710,27 @@@ gst_qt_mux_class_init (GstQTMuxClass * 
            "Multiplier for converting reserved-max-duration into bytes of header to reserve, per second, per track",
            0, 10000, DEFAULT_RESERVED_BYTES_PER_SEC_PER_TRAK,
            G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 +  g_object_class_install_property (gobject_class, PROP_INTERLEAVE_BYTES,
 +      g_param_spec_uint64 ("interleave-bytes", "Interleave (bytes)",
 +          "Interleave between streams in bytes",
 +          0, G_MAXUINT64, DEFAULT_INTERLEAVE_BYTES,
 +          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 +  g_object_class_install_property (gobject_class, PROP_INTERLEAVE_TIME,
 +      g_param_spec_uint64 ("interleave-time", "Interleave (time)",
 +          "Interleave between streams in nanoseconds",
 +          0, G_MAXUINT64, DEFAULT_INTERLEAVE_TIME,
 +          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
+ #ifdef TIZEN_FEATURE_GST_MUX_ENHANCEMENT
+   tspec = g_param_spec_uint("expected-trailer-size", "Expected Trailer Size",
+     "Expected trailer size (bytes)",
+     0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+   if (tspec)
+     g_object_class_install_property(gobject_class, PROP_EXPECTED_TRAILER_SIZE, tspec);
+   else
+     GST_ERROR("g_param_spec failed for \"expected-trailer-size\"");
+ #endif /* TIZEN_FEATURE_GST_MUX_ENHANCEMENT */
    gstelement_class->request_new_pad =
        GST_DEBUG_FUNCPTR (gst_qt_mux_request_new_pad);
    gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qt_mux_change_state);
@@@ -3465,6 -3487,13 +3708,10 @@@ gst_qt_mux_add_buffer (GstQTMux * qtmux
      }
    }
  
 -  if (buf)
 -    gst_buffer_unref (buf);
 -
+ #ifdef TIZEN_FEATURE_GST_MUX_ENHANCEMENT
+   gst_qt_mux_update_expected_trailer_size(qtmux, pad);
+ #endif /* TIZEN_FEATURE_GST_MUX_ENHANCEMENT */
  exit:
  
    return ret;
@@@ -4925,12 -4664,11 +5172,17 @@@ gst_qt_mux_get_property (GObject * obje
      case PROP_RESERVED_BYTES_PER_SEC:
        g_value_set_uint (value, qtmux->reserved_bytes_per_sec_per_trak);
        break;
 +    case PROP_INTERLEAVE_BYTES:
 +      g_value_set_uint64 (value, qtmux->interleave_bytes);
 +      break;
 +    case PROP_INTERLEAVE_TIME:
 +      g_value_set_uint64 (value, qtmux->interleave_time);
 +      break;
+ #ifdef TIZEN_FEATURE_GST_MUX_ENHANCEMENT
+     case PROP_EXPECTED_TRAILER_SIZE:
+       g_value_set_uint(value, qtmux->expected_trailer_size);
+       break;
+ #endif /* TIZEN_FEATURE_GST_MUX_ENHANCEMENT */
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
Simple merge
@@@ -576,14 -556,13 +605,18 @@@ static void gst_qtdemux_send_gap_for_se
  static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
  static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
  
 +static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
 +
 +static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
 +    QtDemuxStream * stream, guint sample_index);
  static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
      const gchar * id);
 +static void qtdemux_gst_structure_free (GstStructure * gststructure);
  
+ #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
+ static void gst_tag_register_spherical_tags (void);
+ #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
  static void
  gst_qtdemux_class_init (GstQTDemuxClass * klass)
  {
  
    gst_tag_register_musicbrainz_tags ();
  
 -  gst_element_class_add_pad_template (gstelement_class,
 -      gst_static_pad_template_get (&gst_qtdemux_sink_template));
 -  gst_element_class_add_pad_template (gstelement_class,
 -      gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
 -  gst_element_class_add_pad_template (gstelement_class,
 -      gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
 -  gst_element_class_add_pad_template (gstelement_class,
 -      gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
+ #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
+   gst_tag_register_spherical_tags ();
+ #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
 +  gst_element_class_add_static_pad_template (gstelement_class,
 +      &gst_qtdemux_sink_template);
 +  gst_element_class_add_static_pad_template (gstelement_class,
 +      &gst_qtdemux_videosrc_template);
 +  gst_element_class_add_static_pad_template (gstelement_class,
 +      &gst_qtdemux_audiosrc_template);
 +  gst_element_class_add_static_pad_template (gstelement_class,
 +      &gst_qtdemux_subsrc_template);
    gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
        "Codec/Demuxer",
        "Demultiplex a QuickTime file into audio and video streams",
@@@ -662,10 -642,35 +699,37 @@@ gst_qtdemux_init (GstQTDemux * qtdemux
    qtdemux->protection_system_ids = NULL;
    g_queue_init (&qtdemux->protection_event_queue);
    gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
 +  qtdemux->tag_list = gst_tag_list_new_empty ();
 +  gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
    qtdemux->flowcombiner = gst_flow_combiner_new ();
  
+ #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
+   spherical_metadata = (QtDemuxSphericalMetadata *)
+       malloc (sizeof (QtDemuxSphericalMetadata));
+   if (spherical_metadata) {
+     spherical_metadata->is_spherical = FALSE;
+     spherical_metadata->is_stitched = FALSE;
+     spherical_metadata->stitching_software = NULL;
+     spherical_metadata->projection_type = NULL;
+     spherical_metadata->stereo_mode = NULL;
+     spherical_metadata->source_count = 0;
+     spherical_metadata->init_view_heading = 0;
+     spherical_metadata->init_view_pitch = 0;
+     spherical_metadata->init_view_roll = 0;
+     spherical_metadata->timestamp = 0;
+     spherical_metadata->full_pano_width_pixels = 0;
+     spherical_metadata->full_pano_height_pixels = 0;
+     spherical_metadata->cropped_area_image_width = 0;
+     spherical_metadata->cropped_area_image_height = 0;
+     spherical_metadata->cropped_area_left = 0;
+     spherical_metadata->cropped_area_top = 0;
+     spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_UNKNOWN;
+     spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_TYPE_UNKNOWN;
+     spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_UNKNOWN;
+   }
+ #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
    GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
  }
  
@@@ -982,14 -988,21 +1057,20 @@@ gst_qtdemux_push_tags (GstQTDemux * qtd
      GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
          GST_DEBUG_PAD_NAME (stream->pad));
  
 -    if (G_UNLIKELY (stream->pending_tags)) {
 +    if (!gst_tag_list_is_empty (stream->stream_tags)) {
        GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
 -          stream->pending_tags);
 +          stream->stream_tags);
        gst_pad_push_event (stream->pad,
 -          gst_event_new_tag (stream->pending_tags));
 +          gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
+ #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
+       /* post message qtdemux tag (for early recive application) */
+       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
+             gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
 -                  gst_tag_list_copy (stream->pending_tags)));
++                  gst_tag_list_copy (stream->stream_tags)));
+ #endif
 -      stream->pending_tags = NULL;
      }
  
 -    if (G_UNLIKELY (stream->send_global_tags && qtdemux->tag_list)) {
 +    if (G_UNLIKELY (stream->send_global_tags)) {
        GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
            qtdemux->tag_list);
        gst_pad_push_event (stream->pad,
@@@ -2631,30 -2463,510 +2712,505 @@@ qtdemux_handle_xmp_taglist (GstQTDemux 
    }
  }
  
+ #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
+ static void
+ _get_int_value_from_xml_string (GstQTDemux * qtdemux,
+     const char *xml_str, const char *param_name, int *value)
+ {
+   char *value_start, *value_end, *endptr;
+   const short value_length_max = 12;
+   char init_view_ret[12];
+   int value_length = 0;
+   int i = 0;
+   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
+   if (!value_start) {
+     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
+         param_name);
+     return;
+   }
+   value_start += strlen (param_name);
+   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
+     value_start++;
+   value_end = strchr (value_start, '<');
+   if (!value_end) {
+     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
+     return;
+   }
+   value_length = value_end - value_start;
+   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
+           || (value_start[value_length - 1] == '\t')))
+     value_length--;
+   if (value_start[i] == '+' || value_start[i] == '-')
+     i++;
+   while (i < value_length) {
+     if (value_start[i] < '0' || value_start[i] > '9') {
+       GST_ERROR_OBJECT (qtdemux,
+           "error: incorrect value, integer was expected\n");
+       return;
+     }
+     i++;
+   }
+   if (value_length >= value_length_max || value_length < 1) {
+     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
+     return;
+   }
+   strncpy (init_view_ret, value_start, value_length_max);
+   init_view_ret[value_length] = '\0';
+   *value = strtol (init_view_ret, &endptr, 10);
+   if (endptr == init_view_ret) {
+     GST_ERROR_OBJECT (qtdemux, "error: no digits were found\n");
+     return;
+   }
+   return;
+ }
+ static void
+ _get_string_value_from_xml_string (GstQTDemux * qtdemux,
+     const char *xml_str, const char *param_name, char **value)
+ {
+   char *value_start, *value_end;
+   const short value_length_max = 256;
+   int value_length = 0;
+   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
+   if (!value_start) {
+     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
+         param_name);
+     return;
+   }
+   value_start += strlen (param_name);
+   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
+     value_start++;
+   value_end = strchr (value_start, '<');
+   if (!value_end) {
+     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
+     return;
+   }
+   value_length = value_end - value_start;
+   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
+           || (value_start[value_length - 1] == '\t')))
+     value_length--;
+   if (value_length >= value_length_max || value_length < 1) {
+     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
+     return;
+   }
+   *value = (char *) malloc (value_length);
+   if (*value == NULL) {
+     GST_ERROR_OBJECT (qtdemux, "error: malloc failed\n");
+     return;
+   }
+   strncpy (*value, value_start, value_length);
+   return;
+ }
+ static void
+ _get_bool_value_from_xml_string (GstQTDemux * qtdemux,
+     const char *xml_str, const char *param_name, gboolean * value)
+ {
+   char *value_start, *value_end;
+   int value_length = 0;
+   value_start = (xml_str && param_name) ? strstr (xml_str, param_name) : NULL;
+   if (!value_start) {
+     GST_WARNING_OBJECT (qtdemux, "error: parameter does not exist: %s\n",
+         param_name);
+     return;
+   }
+   value_start += strlen (param_name);
+   while ((value_start[0] == ' ') || (value_start[0] == '\t'))
+     value_start++;
+   value_end = strchr (value_start, '<');
+   if (!value_end) {
+     GST_ERROR_OBJECT (qtdemux, "error: incorrect XML\n");
+     return;
+   }
+   value_length = value_end - value_start;
+   while ((value_length >= 1) && ((value_start[value_length - 1] == ' ')
+           || (value_start[value_length - 1] == '\t')))
+     value_length--;
+   if (value_length < 1) {
+     GST_ERROR_OBJECT (qtdemux, "error: empty XML value or incorrect range\n");
+     return;
+   }
+   *value = strstr (value_start, "true") ? TRUE : FALSE;
+   return;
+ }
+ static void
+ _parse_spatial_video_metadata_from_xml_string (GstQTDemux * qtdemux,
+     const char *xmlStr, QtDemuxSphericalMetadata * spherical_metadata)
+ {
+   const char is_spherical_str[] = "<GSpherical:Spherical>";
+   const char is_stitched_str[] = "<GSpherical:Stitched>";
+   const char stitching_software_str[] = "<GSpherical:StitchingSoftware>";
+   const char projection_type_str[] = "<GSpherical:ProjectionType>";
+   const char stereo_mode_str[] = "<GSpherical:StereoMode>";
+   const char source_count_str[] = "<GSpherical:SourceCount>";
+   const char init_view_heading_str[] = "<GSpherical:InitialViewHeadingDegrees>";
+   const char init_view_pitch_str[] = "<GSpherical:InitialViewPitchDegrees>";
+   const char init_view_roll_str[] = "<GSpherical:InitialViewRollDegrees>";
+   const char timestamp_str[] = "<GSpherical:Timestamp>";
+   const char full_pano_width_str[] = "<GSpherical:FullPanoWidthPixels>";
+   const char full_pano_height_str[] = "<GSpherical:FullPanoHeightPixels>";
+   const char cropped_area_image_width_str[] =
+       "<GSpherical:CroppedAreaImageWidthPixels>";
+   const char cropped_area_image_height_str[] =
+       "<GSpherical:CroppedAreaImageHeightPixels>";
+   const char cropped_area_left_str[] = "<GSpherical:CroppedAreaLeftPixels>";
+   const char cropped_area_top_str[] = "<GSpherical:CroppedAreaTopPixels>";
+   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_spherical_str,
+       (gboolean *) & spherical_metadata->is_spherical);
+   _get_bool_value_from_xml_string (qtdemux, xmlStr, is_stitched_str,
+       (gboolean *) & spherical_metadata->is_stitched);
+   if (spherical_metadata->is_spherical && spherical_metadata->is_stitched) {
+     _get_string_value_from_xml_string (qtdemux, xmlStr,
+         stitching_software_str, &spherical_metadata->stitching_software);
+     _get_string_value_from_xml_string (qtdemux, xmlStr,
+         projection_type_str, &spherical_metadata->projection_type);
+     _get_string_value_from_xml_string (qtdemux, xmlStr, stereo_mode_str,
+         &spherical_metadata->stereo_mode);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, source_count_str,
+         &spherical_metadata->source_count);
+     _get_int_value_from_xml_string (qtdemux, xmlStr,
+         init_view_heading_str, &spherical_metadata->init_view_heading);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_pitch_str,
+         &spherical_metadata->init_view_pitch);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, init_view_roll_str,
+         &spherical_metadata->init_view_roll);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, timestamp_str,
+         &spherical_metadata->timestamp);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, full_pano_width_str,
+         &spherical_metadata->full_pano_width_pixels);
+     _get_int_value_from_xml_string (qtdemux, xmlStr,
+         full_pano_height_str, &spherical_metadata->full_pano_height_pixels);
+     _get_int_value_from_xml_string (qtdemux, xmlStr,
+         cropped_area_image_width_str,
+         &spherical_metadata->cropped_area_image_width);
+     _get_int_value_from_xml_string (qtdemux, xmlStr,
+         cropped_area_image_height_str,
+         &spherical_metadata->cropped_area_image_height);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_left_str,
+         &spherical_metadata->cropped_area_left);
+     _get_int_value_from_xml_string (qtdemux, xmlStr, cropped_area_top_str,
+         &spherical_metadata->cropped_area_top);
+   }
+   return;
+ }
+ static void
+ gst_tag_register_spherical_tags (void) {
+   gst_tag_register ("is_spherical", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-spherical"),
+       _("Flag indicating if the video is a spherical video"),
+       NULL);
+   gst_tag_register ("is_stitched", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-stitched"),
+       _("Flag indicating if the video is stitched"),
+       NULL);
+   gst_tag_register ("stitching_software", GST_TAG_FLAG_META,
+       G_TYPE_STRING,
+       _("tag-stitching-software"),
+       _("Software used to stitch the spherical video"),
+       NULL);
+   gst_tag_register ("projection_type", GST_TAG_FLAG_META,
+       G_TYPE_STRING,
+       _("tag-projection-type"),
+       _("Projection type used in the video frames"),
+       NULL);
+   gst_tag_register ("stereo_mode", GST_TAG_FLAG_META,
+       G_TYPE_STRING,
+       _("tag-stereo-mode"),
+       _("Description of stereoscopic 3D layout"),
+       NULL);
+   gst_tag_register ("source_count", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-source-count"),
+       _("Number of cameras used to create the spherical video"),
+       NULL);
+   gst_tag_register ("init_view_heading", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-init-view-heading"),
+       _("The heading angle of the initial view in degrees"),
+       NULL);
+   gst_tag_register ("init_view_pitch", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-init-view-pitch"),
+       _("The pitch angle of the initial view in degrees"),
+       NULL);
+   gst_tag_register ("init_view_roll", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-init-view-roll"),
+       _("The roll angle of the initial view in degrees"),
+       NULL);
+   gst_tag_register ("timestamp", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-timestamp"),
+       _("Epoch timestamp of when the first frame in the video was recorded"),
+       NULL);
+   gst_tag_register ("full_pano_width_pixels", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-full-pano-width"),
+       _("Width of the encoded video frame in pixels"),
+       NULL);
+   gst_tag_register ("full_pano_height_pixels", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-full-pano-height"),
+       _("Height of the encoded video frame in pixels"),
+       NULL);
+   gst_tag_register ("cropped_area_image_width", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-cropped-area-image-width"),
+       _("Width of the video frame to display (e.g. cropping)"),
+       NULL);
+   gst_tag_register ("cropped_area_image_height", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-cropped-area-image-height"),
+       _("Height of the video frame to display (e.g. cropping)"),
+       NULL);
+   gst_tag_register ("cropped_area_left", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-cropped-area-left"),
+       _("Column where the left edge of the image was cropped from the"
+           " full sized panorama"),
+       NULL);
+   gst_tag_register ("cropped_area_top", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-cropped-area-top"),
+       _("Row where the top edge of the image was cropped from the"
+           " full sized panorama"),
+       NULL);
+   gst_tag_register ("ambisonic_type", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-ambisonic-type"),
+       _("Specifies the type of ambisonic audio represented"),
+       NULL);
+   gst_tag_register ("ambisonic_format", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-ambisonic-format"),
+       _("Specifies the ambisonic audio format"),
+       NULL);
+   gst_tag_register ("ambisonic_order", GST_TAG_FLAG_META,
+       G_TYPE_INT,
+       _("tag-ambisonic-order"),
+       _("Specifies the ambisonic audio channel order"),
+       NULL);
+   return;
+ }
+ static void
+ _send_message_to_bus (GstQTDemux * qtdemux,
+     QtDemuxSphericalMetadata * spherical_metadata)
+ {
+   GstTagList *taglist;
+   GST_DEBUG_OBJECT (qtdemux, "is_spherical = %d",
+       spherical_metadata->is_spherical);
+   GST_DEBUG_OBJECT (qtdemux, "is_stitched = %d",
+       spherical_metadata->is_stitched);
+   GST_DEBUG_OBJECT (qtdemux, "stitching_software = %s",
+       spherical_metadata->stitching_software);
+   GST_DEBUG_OBJECT (qtdemux, "projection_type = %s",
+       spherical_metadata->projection_type);
+   GST_DEBUG_OBJECT (qtdemux, "stereo_mode = %s",
+       spherical_metadata->stereo_mode);
+   GST_DEBUG_OBJECT (qtdemux, "source_count %d",
+       spherical_metadata->source_count);
+   GST_DEBUG_OBJECT (qtdemux, "init_view_heading = %d",
+       spherical_metadata->init_view_heading);
+   GST_DEBUG_OBJECT (qtdemux, "init_view_pitch = %d",
+       spherical_metadata->init_view_pitch);
+   GST_DEBUG_OBJECT (qtdemux, "init_view_roll = %d",
+       spherical_metadata->init_view_roll);
+   GST_DEBUG_OBJECT (qtdemux, "timestamp = %d", spherical_metadata->timestamp);
+   GST_DEBUG_OBJECT (qtdemux, "full_pano_width_pixels = %d",
+       spherical_metadata->full_pano_width_pixels);
+   GST_DEBUG_OBJECT (qtdemux, "full_pano_height_pixels = %d",
+       spherical_metadata->full_pano_height_pixels);
+   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_width = %d",
+       spherical_metadata->cropped_area_image_width);
+   GST_DEBUG_OBJECT (qtdemux, "cropped_area_image_height = %d",
+       spherical_metadata->cropped_area_image_height);
+   GST_DEBUG_OBJECT (qtdemux, "cropped_area_left = %d",
+       spherical_metadata->cropped_area_left);
+   GST_DEBUG_OBJECT (qtdemux, "cropped_area_top = %d",
+       spherical_metadata->cropped_area_top);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type = %d",
+       spherical_metadata->ambisonic_type);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order = %d",
+       spherical_metadata->ambisonic_order);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_format = %d",
+       spherical_metadata->ambisonic_format);
+   taglist = gst_tag_list_new_empty ();
+   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+       "is_spherical", spherical_metadata->is_spherical,
+       "is_stitched", spherical_metadata->is_stitched,
+       "source_count", spherical_metadata->source_count,
+       "init_view_heading", spherical_metadata->init_view_heading,
+       "init_view_pitch", spherical_metadata->init_view_pitch,
+       "init_view_roll", spherical_metadata->init_view_roll,
+       "timestamp", spherical_metadata->timestamp,
+       "full_pano_width_pixels", spherical_metadata->full_pano_width_pixels,
+       "full_pano_height_pixels", spherical_metadata->full_pano_height_pixels,
+       "cropped_area_image_width", spherical_metadata->cropped_area_image_width,
+       "cropped_area_image_height", spherical_metadata->cropped_area_image_height,
+       "cropped_area_left", spherical_metadata->cropped_area_left,
+       "cropped_area_top", spherical_metadata->cropped_area_top,
+       "ambisonic_type", spherical_metadata->ambisonic_type,
+       "ambisonic_format", spherical_metadata->ambisonic_format,
+       "ambisonic_order", spherical_metadata->ambisonic_order,
+       NULL);
+   if (spherical_metadata->stitching_software)
+     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+         "stitching_software", spherical_metadata->stitching_software,
+         NULL);
+   if (spherical_metadata->projection_type)
+     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+         "projection_type", spherical_metadata->projection_type,
+         NULL);
+   if (spherical_metadata->stereo_mode)
+     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+         "stereo_mode", spherical_metadata->stereo_mode,
+         NULL);
+   gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
+           gst_message_new_tag (GST_OBJECT_CAST (qtdemux),
+                   gst_tag_list_copy (taglist)));
+   gst_tag_list_unref(taglist);
+   return;
+ }
+ static void
+ qtdemux_parse_SA3D (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
+ {
+   guint offset = 0;
+   guint8 version = 0;
+   guint8 ambisonic_type  = 0;
+   guint32 ambisonic_order = 0;
+   guint8 ambisonic_channel_ordering = 0;
+   guint8 ambisonic_normalization = 0;
+   guint32 num_channels = 0;
+   guint32 channel_map[49] = { 0 };      /* Up to 6th order */
+   int i;
+   GST_DEBUG_OBJECT (qtdemux, "qtdemux_parse_SA3D");
+   qtdemux->header_size += length;
+   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
+   if (length <= offset + 16) {
+     GST_DEBUG_OBJECT (qtdemux, "SA3D atom is too short, skipping");
+     return;
+   }
+   version = QT_UINT8 (buffer + offset);
+   ambisonic_type = QT_UINT8 (buffer + offset + 1);
+   ambisonic_order = QT_UINT32 (buffer + offset + 2);
+   ambisonic_channel_ordering = QT_UINT8 (buffer + offset + 6);
+   ambisonic_normalization = QT_UINT8 (buffer + offset + 7);
+   num_channels = QT_UINT32 (buffer + offset + 8);
+   for (i = 0; i < num_channels; ++i)
+     channel_map[i] = QT_UINT32 (buffer + offset + 12 + i * 4);
+   GST_DEBUG_OBJECT (qtdemux, "version: %d", version);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_type: %d", ambisonic_type);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_order: %d", ambisonic_order);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_channel_ordering: %d",
+       ambisonic_channel_ordering);
+   GST_DEBUG_OBJECT (qtdemux, "ambisonic_normalization: %d",
+       ambisonic_normalization);
+   GST_DEBUG_OBJECT (qtdemux, "num_channels: %d", num_channels);
+   for (i = 0; i < num_channels; ++i)
+     GST_DEBUG_OBJECT (qtdemux, "channel_map: %d", channel_map[i]);
+   if (version == RFC_AMBISONIC_SA3DBOX_VERSION_SUPPORTED) {
+     if (ambisonic_type == RFC_AMBISONIC_TYPE_PERIPHONIC)
+       spherical_metadata->ambisonic_type = QTDEMUX_AMBISONIC_TYPE_PERIPHONIC;
+     if (ambisonic_order == RFC_AMBISONIC_ORDER_FOA) {
+       if (num_channels == 4) {
+         spherical_metadata->ambisonic_order = QTDEMUX_AMBISONIC_ORDER_FOA;
+         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN)
+             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D)
+             && (channel_map[0] == 0) && (channel_map[1] == 1)
+             && (channel_map[2] == 2) && (channel_map[3] == 3))
+           spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMBIX;
+         if ((ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA)
+             && (ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA)
+             && (channel_map[0] == 0) && (channel_map[1] == 3)
+             && (channel_map[2] == 1) && (channel_map[3] == 2))
+           spherical_metadata->ambisonic_format = QTDEMUX_AMBISONIC_FORMAT_AMB;
+       }
+     }
+   }
+   return;
+ }
+ #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
  static void
 -qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
 +qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
 +    guint offset)
  {
 -  static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
 -    0x97, 0xA9, 0x42, 0xE8,
 -    0x9C, 0x71, 0x99, 0x94,
 -    0x91, 0xE3, 0xAF, 0xAC
 -  };
 -  static const guint8 playready_uuid[] = {
 -    0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
 -    0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
 -  };
 -
 -#ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
 -  static const guint8 spherical_uuid[] = {
 -    0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
 -    0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd
 -  };
 -#endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
 -
 -  guint offset;
 +  GstByteReader br;
 +  guint8 version;
 +  guint32 flags = 0;
 +  guint i;
 +  guint8 iv_size = 8;
 +  QtDemuxStream *stream;
 +  GstStructure *structure;
 +  QtDemuxCencSampleSetInfo *ss_info = NULL;
 +  const gchar *system_id;
 +  gboolean uses_sub_sample_encryption = FALSE;
  
 -  /* counts as header data */
 -  qtdemux->header_size += length;
 +  if (qtdemux->n_streams == 0)
 +    return;
  
 -  offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
 +  stream = qtdemux->streams[0];
  
 -  if (length <= offset + 16) {
 -    GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
 +  structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
 +  if (!gst_structure_has_name (structure, "application/x-cenc")) {
 +    GST_WARNING_OBJECT (qtdemux,
 +        "Attempting PIFF box parsing on an unencrypted stream.");
      return;
    }
  
@@@ -207,7 -201,9 +207,10 @@@ static const QtNodeType qt_node_types[
    {FOURCC_schi, "scheme information", QT_FLAG_CONTAINER},
    {FOURCC_pssh, "protection system specific header", 0},
    {FOURCC_tenc, "track encryption", 0},
 +  {FOURCC_stpp, "XML subtitle sample entry", 0},
+ #ifdef TIZEN_FEATURE_QTDEMUX_MODIFICATION
+   {FOURCC_SA3D, "spatial sound", 0,},
+ #endif /* TIZEN_FEATURE_QTDEMUX_MODIFICATION */
    {0, "unknown", 0,},
  };
  
Simple merge
@@@ -1751,12 -1561,16 +1763,21 @@@ create_stream (GstRtpBinSession * sessi
    g_object_set (buffer, "do-lost", rtpbin->do_lost, NULL);
    g_object_set (buffer, "mode", rtpbin->buffer_mode, NULL);
    g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL);
 +  g_object_set (buffer, "max-rtcp-rtp-time-diff",
 +      rtpbin->max_rtcp_rtp_time_diff, NULL);
 +  g_object_set (buffer, "max-dropout-time", rtpbin->max_dropout_time,
 +      "max-misorder-time", rtpbin->max_misorder_time, NULL);
 +  g_object_set (buffer, "rfc7273-sync", rtpbin->rfc7273_sync, NULL);
  
+ #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
+   /* configure queue2 to use live buffering */
+   if (queue2) {
+     g_object_set_data (G_OBJECT (queue2), "GstRTPBin.stream", stream);
+     g_object_set (queue2, "use-buffering", TRUE, NULL);
+     g_object_set (queue2, "buffer-mode", GST_BUFFERING_LIVE, NULL);
+   }
+ #endif
    g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER], 0,
        buffer, session->id, ssrc);
  
@@@ -226,9 -232,11 +226,13 @@@ gst_rtsp_src_ntp_time_source_get_type (
  #define DEFAULT_DO_RETRANSMISSION        TRUE
  #define DEFAULT_NTP_TIME_SOURCE  NTP_TIME_SOURCE_NTP
  #define DEFAULT_USER_AGENT       "GStreamer/" PACKAGE_VERSION
 +#define DEFAULT_MAX_RTCP_RTP_TIME_DIFF 1000
 +#define DEFAULT_RFC7273_SYNC         FALSE
  
+ #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
+ #define DEFAULT_START_POSITION   0
+ #endif
  enum
  {
    PROP_0,
@@@ -894,9 -932,11 +947,13 @@@ gst_rtspsrc_init (GstRTSPSrc * src
    src->do_retransmission = DEFAULT_DO_RETRANSMISSION;
    src->ntp_time_source = DEFAULT_NTP_TIME_SOURCE;
    src->user_agent = g_strdup (DEFAULT_USER_AGENT);
 +  src->max_rtcp_rtp_time_diff = DEFAULT_MAX_RTCP_RTP_TIME_DIFF;
 +  src->rfc7273_sync = DEFAULT_RFC7273_SYNC;
  
+ #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
+   g_mutex_init (&(src)->pause_lock);
+   g_cond_init (&(src)->open_end);
+ #endif
    /* get a list of all extensions */
    src->extensions = gst_rtsp_ext_list_get ();
  
@@@ -4954,7 -5455,8 +5130,8 @@@ no_protocols
      GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
          ("Could not receive any UDP packets for %.4f seconds, maybe your "
              "firewall is blocking it. No other protocols to try.",
 -            gst_guint64_to_gdouble (src->udp_timeout / 1000000.0)));
 +            gst_guint64_to_gdouble (src->udp_timeout) / 1000000.0));
+ #endif
      return GST_RTSP_ERROR;
    }
  open_failed:
@@@ -5572,12 -6226,22 +5802,22 @@@ error_response
  
      switch (response->type_data.response.code) {
        case GST_RTSP_STS_NOT_FOUND:
 -        GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), ("%s",
 -                response->type_data.response.reason));
+ #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
+         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_BAD_REQUEST,
+             "STS NOT FOUND");
+ #else
 +        RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, NOT_FOUND,
 +            "Not found");
+ #endif
          break;
        case GST_RTSP_STS_UNAUTHORIZED:
 -        GST_ELEMENT_ERROR (src, RESOURCE, NOT_AUTHORIZED, (NULL), ("%s",
 -                response->type_data.response.reason));
+ #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
+         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_NOT_AUTHORIZED,
+             "STS NOT AUTHORIZED");
+ #else
 +        RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, NOT_AUTHORIZED,
 +            "Unauthorized");
+ #endif
          break;
        case GST_RTSP_STS_MOVED_PERMANENTLY:
        case GST_RTSP_STS_MOVE_TEMPORARILY:
          res = GST_RTSP_OK;
          break;
        default:
 -        GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
 -            ("Got error response: %d (%s).", response->type_data.response.code,
 -                response->type_data.response.reason));
+ #ifdef TIZEN_FEATURE_RTSP_MODIFICATION
+         gst_rtspsrc_post_error_message (src, GST_RTSPSRC_ERROR_UNEXPECTED_MSG,
+             "Got error response from Server");
+ #else
 +        RTSP_SRC_RESPONSE_ERROR (src, response, RESOURCE, READ,
 +            "Unhandled error");
+ #endif
          break;
      }
      /* if we return ERROR we should unset the response ourselves */
Simple merge
Simple merge
Simple merge
index 0000000,f3d1043..c3aef17
mode 000000,100644..100644
Binary files differ
index 0000000,520cac0..d7679cc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,211 +1,212 @@@
 -Version:        1.6.1
 -Release:        17
+ %bcond_with x
+ %define gst_branch 1.0
+ Name:           gst-plugins-good
 -%{_libdir}/gstreamer-%{gst_branch}/libgstpulse.so
++Version:        1.12.2
++Release:        0
+ License:        LGPL-2.1+
+ Summary:        GStreamer Streaming-Media Framework Plug-Ins
+ Url:            http://gstreamer.freedesktop.org/
+ Group:          Multimedia/Framework
+ Source:         http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-%{version}.tar.xz
+ Source100:      common.tar.gz
+ BuildRequires:  gcc-c++
+ BuildRequires:  gettext-tools
+ BuildRequires:  pkgconfig(glib-2.0) >= 2.32
+ BuildRequires:  pkgconfig(gstreamer-1.0)
+ BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
+ BuildRequires:  libjpeg-devel
+ BuildRequires:  orc >= 0.4.16
+ BuildRequires:  python
+ BuildRequires:  xsltproc
+ BuildRequires:  pkgconfig(bzip2)
+ #BuildRequires:  pkgconfig(libpng) >= 1.2
+ BuildRequires:  pkgconfig(libpulse) >= 1.0
+ BuildRequires:  pkgconfig(libsoup-2.4)
+ BuildRequires:  pkgconfig(libxml-2.0) >= 2.4.9
+ # TODO find where process.h comes from, not kernel-devel and not wxWidgets so far.
+ %if %{with x}
+ BuildRequires:  pkgconfig(ice)
+ BuildRequires:  pkgconfig(sm)
+ BuildRequires:  pkgconfig(xdamage)
+ BuildRequires:  pkgconfig(xfixes)
+ # used by libgstvideo4linux2.so
+ BuildRequires:  pkgconfig(xv)
+ %endif
+ BuildRequires:  pkgconfig(zlib)
+ %if "%{TIZEN_PRODUCT_TV}" != "1"
+ BuildRequires:  pkgconfig(libv4l2)
+ %endif
+ BuildRequires:  pkgconfig(vconf)
+ Requires:       gst-plugins-base >= 1.0.0
+ Requires:       gstreamer >= 1.0.5
+ %description
+ GStreamer is a streaming media framework based on graphs of filters
+ that operate on media data. Applications using this library can do
+ anything media-related, from real-time sound processing to playing
+ videos. Its plug-in-based architecture means that new data types or
+ processing capabilities can be added simply by installing new plug-ins.
+ %package extra
+ Summary:        Complementary plugins for %{name}
+ Group:          Productivity/Multimedia/Other
+ Requires:       %{name} = %{version}
+ Enhances:       gst-plugins-good
+ %description extra
+ This package provides complementary plugins for
+ %{name}.
+ %prep
+ %setup -q -n gst-plugins-good-%{version}
+ %setup -q -T -D -a 100
+ %build
+ # FIXME:
+ # warning: failed to load external entity "xml/element-v4l2src-details.xml"
+ # warning: failed to load external entity "xml/plugin-video4linux2.xml"
+ export V=1
+ NOCONFIGURE=1 ./autogen.sh
+ export CFLAGS+=" -DTIZEN_FEATURE_V4L2SRC_MODIFICATION\
+               -DTIZEN_FEATURE_WAVPARSE_MODIFICATION\
+               -DTIZEN_FEATURE_MP3PARSE_MODIFICATION\
+               -DTIZEN_FEATURE_AACPARSE_MODIFICATION\
+               -DTIZEN_FEATURE_QTDEMUX_MODIFICATION\
+               -DTIZEN_FEATURE_FLVDEMUX_MODIFICATION\
+               -DTIZEN_FEATURE_GST_UPSTREAM\
+                 -DTIZEN_FEATURE_RTSP_MODIFICATION\
+               -DTIZEN_FEATURE_GST_MUX_ENHANCEMENT\
+               -DTIZEN_FEATURE_SOUP_MODIFICATION\
+               -DTIZEN_FEATURE_BASEPARSE_MODIFICATION"
+ %configure\
+ %if ! 0%{?ENABLE_AALIB}
+       --disable-aalib\
+ %endif
+ %if "%{TIZEN_PRODUCT_TV}" != "1"
+       --with-libv4l2 \
+ %endif
+       --disable-gtk-doc\
+       --with-gtk=3.0\
+       --disable-monoscope\
+       --disable-y4m\
+       --disable-taglib\
+       --disable-wavpack\
+       --enable-experimental\
+ %if "%{TIZEN_PRODUCT_TV}" == "1"
+       --disable-equalizer\
+       --disable-flv\
+       --disable-videobox\
+       --disable-videomixer\
+ %endif
+       --disable-effectv\
+       --disable-alpha\
+       --disable-auparse\
+       --disable-effectv\
+       --disable-flx\
+       --disable-goom\
+       --disable-goom2k1\
+       --disable-level\
+       --disable-multipart\
+       --disable-replaygain\
+       --disable-smpte\
+       --disable-spectrum\
+       --disable-cutter\
+       --disable-dtmf\
+       --disable-imagefreeze\
+       --disable-oss4\
+       --disable-oss\
+       --disable-shapewipe
+ make %{?_smp_mflags} CFLAGS+="-Wno-error" CXXFLAGS+="-Wno-error"
+ %install
+ %make_install
+ %find_lang %{name}-%{gst_branch}
+ %lang_package -f %{name}-%{gst_branch}
+ %files
+ %manifest %{name}.manifest
+ %defattr(-, root, root)
+ %license COPYING
+ %{_libdir}/gstreamer-%{gst_branch}/libgstalaw.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstalpha.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstalphacolor.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstapetag.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstaudiofx.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstaudioparsers.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstauparse.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstautodetect.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstavi.so
+ # Not yet ported
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstcutter.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstdebug.so
+ # Not yet ported
+ %{_libdir}/gstreamer-%{gst_branch}/libgstdeinterlace.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgsteffectv.so
+ #%{_datadir}/gstreamer-%{gst_branch}/presets/GstVP8Enc.prs
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstflxdec.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstgoom.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstgoom2k1.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgsticydemux.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstid3demux.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstimagefreeze.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstinterleave.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstisomp4.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstjpeg.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstlevel.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstmatroska.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstmonoscope.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstmulaw.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstmultifile.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstmultipart.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstnavigationtest.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstoss4audio.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstossaudio.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstpng.so
 -%{_libdir}/gstreamer-%{gst_branch}/libgstsouphttpsrc.so
++%{_libdir}/gstreamer-%{gst_branch}/libgstpulseaudio.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstreplaygain.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstrtp.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstrtpmanager.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstrtsp.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstshapewipe.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstsmpte.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstspectrum.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstspeex.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstudp.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstvideo4linux2.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstvideocrop.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstvideofilter.so
+ %if "%{TIZEN_PRODUCT_TV}" != "1"
+ %{_libdir}/gstreamer-%{gst_branch}/libgstflv.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstequalizer.so
+ %{_datadir}/gstreamer-%{gst_branch}/presets/GstIirEqualizer10Bands.prs
+ %{_datadir}/gstreamer-%{gst_branch}/presets/GstIirEqualizer3Bands.prs
++%{_datadir}/gstreamer-%{gst_branch}/presets/GstQTMux.prs
+ %{_libdir}/gstreamer-%{gst_branch}/libgstvideobox.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstvideomixer.so
+ %endif
+ %{_libdir}/gstreamer-%{gst_branch}/libgstwavenc.so
+ %{_libdir}/gstreamer-%{gst_branch}/libgstwavparse.so
+ %if %{with x}
+ %{_libdir}/gstreamer-%{gst_branch}/libgstximagesrc.so
+ %endif
+ #%{_libdir}/gstreamer-%{gst_branch}/libgsty4menc.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstcairo.so
++%{_libdir}/gstreamer-%{gst_branch}/libgstsoup.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstflac.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstvpx.so
+ #%{_libdir}/gstreamer-%{gst_branch}/libgstdtmf.so
+ %if 0%{?ENABLE_AALIB}
+ %files extra
+ %manifest %{name}.manifest
+ %defattr(-, root, root)
+ %{_libdir}/gstreamer-%{gst_branch}/libgstaasink.so
+ %endif
Simple merge
@@@ -556,19 -606,45 +611,45 @@@ CHECK_AGAIN
      v4l2object->video_fd = libv4l2_fd;
  
    /* get capabilities, error will be posted */
+ #ifdef TIZEN_FEATURE_V4L2SRC_MODIFICATION
+   if (!gst_v4l2_get_capabilities (v4l2object)) {
+     error_type = V4L2_OPEN_ERROR;
+     goto pre_error_check;
+   }
+ #else /* TIZEN_FEATURE_V4L2SRC_MODIFICATION */
    if (!gst_v4l2_get_capabilities (v4l2object))
      goto error;
+ #endif /* TIZEN_FEATURE_V4L2SRC_MODIFICATION */
  
    /* do we need to be a capture device? */
 -  GST_INFO_OBJECT(v4l2object->element, "capabilities 0x%x", v4l2object->vcap.capabilities);
+ #ifdef TIZEN_FEATURE_V4L2SRC_MODIFICATION
 -      (!(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) ||
 -       (v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE)))) {
++  GST_INFO_OBJECT(v4l2object->element, "device_caps 0x%x", v4l2object->device_caps);
+   if (GST_IS_V4L2SRC (v4l2object->element) &&
++      (!(v4l2object->device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) ||
++       (v4l2object->device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE)))) {
+     error_type = V4L2_OPEN_ERROR_NOT_CAPTURE;
+     goto pre_error_check;
+   }
+ #else /* TIZEN_FEATURE_V4L2SRC_MODIFICATION */
    if (GST_IS_V4L2SRC (v4l2object->element) &&
 -      !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_CAPTURE |
 +      !(v4l2object->device_caps & (V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_VIDEO_CAPTURE_MPLANE)))
      goto not_capture;
+ #endif /* TIZEN_FEATURE_V4L2SRC_MODIFICATION */
  
 -      !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_OUTPUT |
+ #ifdef TIZEN_FEATURE_V4L2SRC_MODIFICATION
+   if (GST_IS_V4L2SINK (v4l2object->element) &&
++      !(v4l2object->device_caps & (V4L2_CAP_VIDEO_OUTPUT |
+               V4L2_CAP_VIDEO_OUTPUT_MPLANE))) {
+     error_type = V4L2_OPEN_ERROR_NOT_OUTPUT;
+     goto pre_error_check;
+   }
+ #else /* TIZEN_FEATURE_V4L2SRC_MODIFICATION */
    if (GST_IS_V4L2SINK (v4l2object->element) &&
 -      !(v4l2object->vcap.capabilities & (V4L2_CAP_VIDEO_OUTPUT |
 +      !(v4l2object->device_caps & (V4L2_CAP_VIDEO_OUTPUT |
                V4L2_CAP_VIDEO_OUTPUT_MPLANE)))
      goto not_output;
+ #endif /* TIZEN_FEATURE_V4L2SRC_MODIFICATION */
  
    if (GST_IS_V4L2_VIDEO_DEC (v4l2object->element) &&
        /* Today's M2M device only expose M2M */
Simple merge