tizen 2.3.1 release tizen_2.3.1 submit/tizen_2.3.1/20150915.081250 tizen_2.3.1_release
authorjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:28:02 +0000 (22:28 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:28:02 +0000 (22:28 +0900)
51 files changed:
configure.ac
debian/changelog [deleted file]
debian/compat [deleted file]
debian/control [deleted file]
debian/copyright [deleted file]
debian/gstreamer0.10-plugins-good.install.in [deleted file]
debian/rules [deleted file]
debian/rules.old [deleted file]
ext/pulse/Makefile.am
ext/pulse/pulsesink.c [changed mode: 0644->0755]
ext/pulse/pulsesink.h
ext/pulse/pulsesrc.c
ext/soup/gstsouphttpsrc.c [changed mode: 0644->0755]
ext/soup/gstsouphttpsrc.h [changed mode: 0644->0755]
gst-plugins-good.manifest [new file with mode: 0755]
gst-plugins-good.spec.in
gst/audioparsers/gstaacparse.c
gst/audioparsers/gstaacparse.h
gst/audioparsers/gstamrparse.c
gst/audioparsers/gstamrparse.h
gst/audioparsers/gstflacparse.c [changed mode: 0644->0755]
gst/audioparsers/gstmpegaudioparse.c
gst/audioparsers/gstmpegaudioparse.h
gst/audioparsers/plugin.c
gst/avi/gstavidemux.c [changed mode: 0644->0755]
gst/avi/gstavidemux.h [changed mode: 0644->0755]
gst/flv/gstflvdemux.c [changed mode: 0644->0755]
gst/flv/gstflvdemux.h [changed mode: 0644->0755]
gst/isomp4/Makefile.am
gst/isomp4/fourcc.h [changed mode: 0644->0755]
gst/isomp4/qtdemux.c [changed mode: 0644->0755]
gst/isomp4/qtdemux.h [changed mode: 0644->0755]
gst/isomp4/qtdemux_dump.c
gst/isomp4/qtdemux_dump.h
gst/isomp4/qtdemux_fourcc.h [changed mode: 0644->0755]
gst/isomp4/qtdemux_types.c [changed mode: 0644->0755]
gst/matroska/matroska-demux.c [changed mode: 0644->0755]
gst/matroska/matroska-demux.h [changed mode: 0644->0755]
gst/matroska/matroska-ids.h
gst/matroska/matroska-read-common.c
gst/multipart/multipartmux.c
gst/rtp/gstrtpdepay.c [changed mode: 0644->0755]
gst/rtp/gstrtpmp2tpay.c
gst/rtp/gstrtpmp2tpay.h
gst/rtsp/gstrtspsrc.c
gst/rtsp/gstrtspsrc.h
gst/udp/gstmultiudpsink.c [changed mode: 0644->0755]
gst/wavparse/gstwavparse.c
packaging/gst-plugins-good.spec [changed mode: 0644->0755]
sys/v4l2/gstv4l2bufferpool.c
sys/v4l2/v4l2_calls.c

index 13a6745..54f8438 100644 (file)
@@ -280,6 +280,23 @@ AG_GST_CHECK_FEATURE(GCONFTOOL, [GConf schemas], , [
   AC_SUBST(HAVE_GCONFTOOL)
 ])
 
+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 use divx drm --------------------------------------------------------------------------
 AC_ARG_ENABLE(divx-drm, AC_HELP_STRING([--enable-divx-drm], [using divx drm]),
   [
@@ -385,6 +402,17 @@ AG_GST_CHECK_PLUGIN(wavenc)
 AG_GST_CHECK_PLUGIN(wavparse)
 AG_GST_CHECK_PLUGIN(y4m)
 
+#PKG_CHECK_MODULES(DRM_CLIENT, drm-client)
+#AC_SUBST(DRM_CLIENT_CFLAGS)
+#AC_SUBST(DRM_CLIENT_LIBS)
+#PKG_CHECK_MODULES(DRM_TRUSTED, drm-trusted)
+#AC_SUBST(DRM_TRUSTED_CFLAGS)
+#AC_SUBST(DRM_TRUSTED_LIBS)
+
+PKG_CHECK_MODULES(INIPARSER, iniparser)
+AC_SUBST(INIPARSER_CFLAGS)
+AC_SUBST(INIPARSER_LIBS)
+
 dnl *** checks for socket and nsl libraries ***
 AC_CHECK_FUNC(socket,,[AC_CHECK_LIB(socket,socket)])
 
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100755 (executable)
index 066f9ad..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-gst-plugins-good0.10 (0.10.31-1slp2+1) unstable; urgency=low
-
-  * Upgrade 0.10.29 to 0.10.31
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.31-1slp2+1
-
- -- Hyunseok Lee <hs7388.lee@samsung.com>  Wed, 27 Jun 2012 21:17:50 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+21) unstable; urgency=low
-
-  * Adding unified trickplay of matroska demuxer
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+21
-
- -- Naveen Ch <naveen.ch@samsung.com>  Tue, 17 Apr 2012 22:30:17 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+20) unstable; urgency=low
-
-  * enable mutipart to use getUserMedia in webkit
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+20
-
- -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 12 Apr 2012 20:16:17 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+19) unstable; urgency=low
-
-  * Adding unified trickplay of QT & AVI demuxers
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+19
-
- -- Naveen Ch <naveen.ch@samsung.com>  Fri, 30 Mar 2012 07:30:08 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+18) unstable; urgency=low
-
-  * Add null check after gst_pad_pull_range in avidemux
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+18
-
- -- Sunghyun Eum <sunghyun.eum@samsung.com>  Wed, 15 Feb 2012 07:09:08 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+17) unstable; urgency=low
-
-  * Modify souphttpsrc plugin : adding Range field to request header at very first time with offset 0
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+17
-
- -- YeJin Cho <cho.yejin@samsung.com>  Tue, 07 Feb 2012 15:46:44 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+16) unstable; urgency=low
-
-  * update debian/control for libjpeg(7to8)
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+16
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Thu, 12 Jan 2012 13:23:16 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+15) unstable; urgency=low
-
-  * Enable interleave for WebAudio API
-  * Git: slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+15
-
- -- Hyunseok Lee <hs7388.lee@samsung.com>  Fri, 16 Dec 2011 18:46:33 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+14) unstable; urgency=low
-
-  * Code cleanup for source open
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+14
-
- -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 06 Dec 2011 16:18:21 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+13) unstable; urgency=low
-
-  * Modify scale function for fast forward
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+13
-
- -- Sunghyun Eum <sunghyun.eum@samsung.com>  Fri, 25 Nov 2011 19:11:24 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+12) unstable; urgency=low
-
-  * Update gst_qtdemux_find_index function to latest version.
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+12
-
- -- Dowan Kim <dowan2171.kim@samsung.com>  Mon, 07 Nov 2011 10:30:51 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+11) unstable; urgency=low
-
-  * Check the possiblity of H263 in case of mp4v fourCC and correct it.
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+11
-
- -- Hyunseok Lee <hs7388.lee@samsung.com>  Wed, 12 Oct 2011 10:31:26 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+10) unstable; urgency=low
-
-  * Add dependancy for bz2
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+10
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Fri, 30 Sep 2011 11:38:17 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+9) unstable; urgency=low
-
-  * Fix divx drm commit fails
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+9
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Tue, 06 Sep 2011 21:24:19 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+8) unstable; urgency=low
-
-  * Remove GTK dependancy
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+8
-
- -- Seungbae Shin <seungbae.shin@samsung.com>>  Tue, 06 Sep 2011 19:36:28 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+7) unstable; urgency=low
-
-  * Increase version (already previous version exists)
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+7
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Thu, 25 Aug 2011 13:56:03 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+6) unstable; urgency=low
-
-  * Remove divxsdk depedancy and use libmm-divxsdk plugin
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+6
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Thu, 25 Aug 2011 13:25:41 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+5) unstable; urgency=low
-
-  * enable wavenc
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+5
-
- -- Jeongmo Yang <jm80.yang@samsung.com>  Wed, 22 Jun 2011 11:52:03 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+4) unstable; urgency=low
-
-  * [avi] merge unmerged divx drm related code
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+4
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Fri, 10 Jun 2011 19:27:03 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+3) unstable; urgency=low
-
-  * remove old files
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+3
-
- -- Younghwan Ahn <younghwan_.an@samsung.com>  Wed, 08 Jun 2011 17:01:37 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+2) unstable; urgency=low
-
-  * update changelog
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+2
-
- -- Younghwan Ahn <younghwan_.an@samsung.com>  Tue, 07 Jun 2011 20:41:03 +0900
-
-gst-plugins-good0.10 (0.10.29-18slp2+1) lucid; urgency=low
-
-  * upgrade 17 to 29
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.29-18slp2+1
-
- -- Younghwan Ahn <younghwan_.an@samsung.com>  Thu, 12 May 2011 19:44:48 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+12) unstable; urgency=low
-
-  * [avidemux] Fix to get duration from avih in case of push-mode
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+12
-
- -- YeJin Cho <cho.yejin@samsung.com>  Wed, 16 Mar 2011 17:25:51 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+11) unstable; urgency=low
-
-  * [avidemux] Return GST_FLOW_ERROR when avidemux fail to parse stream
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+11
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Thu, 10 Mar 2011 14:07:20 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+10) unstable; urgency=low
-
-  * [avidemux] Post error when DivX DRM init fails
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+10
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Mon, 07 Mar 2011 19:05:09 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+9) unstable; urgency=low
-
-  * Revert Disable matroska plugin
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+9
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Wed, 16 Feb 2011 10:50:15 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+8) unstable; urgency=low
-
-  * Disable matroska plugin
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+8
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Wed, 09 Feb 2011 15:25:55 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+7) unstable; urgency=low
-
-  * Support DivX JIT DRM
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+7
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Wed, 05 Jan 2011 12:09:11 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+6) unstable; urgency=low
-
-  * Modified AVI demux to solved DIVX issues
-  * Git: 165.213.180.234:slp/pkgs/g/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+6
- -- Naveen Ch <naveen.ch@samsung.com>  Tue, 07 Dec 2010 13:09:22 +0530
-
-gst-plugins-good0.10 (0.10.17-18slp2+5) unstable; urgency=low
-
-  * Skip indexing when dd chunk
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+5
-
- -- Seungbae.shin <seungbae.shin@samsung.com>  Fri, 03 Dec 2010 16:28:06 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+4) unstable; urgency=low
-
-  * Merge max/avg bitrate from latest qtdemux 
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+4
-
- -- Seungbae.shin <seungbae.shin@samsung.com>  Wed, 01 Dec 2010 16:59:38 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+3) unstable; urgency=low
-
-  * Fix for as-needed
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+3
-
- -- Seungbae.shin <seungbae.shin@samsung.com>  Wed, 24 Nov 2010 21:04:10 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+2) unstable; urgency=low
-
-  * Add dbg package, PIC, as-needed
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+2
-
- -- Seungbae.shin <seungbae.shin@samsung.com>  Fri, 19 Nov 2010 10:55:49 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+1) unstable; urgency=low
-
-  * fix h264 rtph264payloader not to check sps/pps info (by yoserb.yi)
-  * enable mulaw,alaw enc/dec to support VoIP via Farsight (by yoserb.yi)
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+1
-
- -- Seungbae.shin <seungbae.shin@samsung.com>  Wed, 10 Nov 2010 21:30:23 +0900
-
-gst-plugins-good0.10 (0.10.17-18slp2+0) unstable; urgency=low
-
-  * Enable FLV demuxer
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-18slp2+0
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Fri, 05 Nov 2010 20:26:27 +0900
-
-gst-plugins-good0.10 (0.10.17-17slp2+8) unstable; urgency=low
-
-  * Rollback v4l2src to original src except for setting input index
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+8
-
- -- Wonhyung Cho <wh01.cho@samsung.com>  Tue, 21 Sep 2010 20:14:45 +0900
-
-gst-plugins-good0.10 (0.10.17-17slp2+7) unstable; urgency=low
-
-  * Repackaging for pulse (basesink updated)
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+7
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Wed, 01 Sep 2010 13:41:03 +0900
-
-gst-plugins-good0.10 (0.10.17-17slp2+6) unstable; urgency=low
-
-  * Replace libsoup2.4-1 with libsoup2.4 in debian/control
-  * Git: 165.213.180.234:/git/slp/pkgs/gst-plugins-good0.10
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+6
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Wed, 25 Aug 2010 11:12:53 +0900
-
-gst-plugins-good0.10 (0.10.17-17slp2+5) unstable; urgency=low
-
-  * No change in source code
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+5
-
- -- Naveen Ch <naveen.ch@samsung.com>  Thu, 24 Jun 2010 08:48:53 +0530
-
-gst-plugins-good0.10 (0.10.17-17slp2+4) unstable; urgency=low
-
-  * Matroska Demux: Added WebM support in matroska demuxer
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+4
-
- -- Naveen Ch <naveen.ch@samsung.com>  Thu, 17 Jun 2010 16:45:27 +0530
-
-gst-plugins-good0.10 (0.10.17-17slp2+3) unstable; urgency=low
-
-  * Matroska Demux: Added reverse trick play functionality
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+3
-
- -- Naveen Ch <naveen.ch@samsung.com>  Wed, 02 Jun 2010 13:01:47 +0530
-
-gst-plugins-good0.10 (0.10.17-17slp2+2) unstable; urgency=low
-
-  * AVI Demux: Modified the created mp3 caps to avoid selecting "mp3parse" element
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+2
-
- -- Prashanth Kumar D <prashanth.kd@samsung.com>  Mon, 17 May 2010 18:21:49 +0530
-
-gst-plugins-good0.10 (0.10.17-17slp2+1) unstable; urgency=low
-
-  * AVI Demux: Added "framed" field in the caps for AC3 content to avoid selecting ac3parse
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+1
-
- -- Prashanth Kumar D <prashanth.kd@samsung.com>  Fri, 30 Apr 2010 18:08:54 +0530
-
-gst-plugins-good0.10 (0.10.17-17slp2+0) unstable; urgency=low
-
-  * Add pulseaudio dependancy
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-17slp2+0
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Mon, 12 Apr 2010 15:52:54 +0900
-
-gst-plugins-good0.10 (0.10.17-16slp+1) unstable; urgency=low
-
-  * enable matroska demuxer/muxer
-  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/gst-plugins-good-0.10.17
-  * Tag: gst-plugins-good0.10_0.10.17-16slp+1
-
- -- Heungsoon Rim <hs06.rim@samsung.com>  Fri, 09 Apr 2010 13:32:52 +0900
-
-gst-plugins-good0.10 (0.10.17-16slp+0) unstable; urgency=low
-
-  * Change package naming rule
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Thu, 25 Mar 2010 15:13:04 +0900
-
-gst-plugins-good0.10 (0.10.17-16) unstable; urgency=low
-
-  * Add uploader list
-
- -- Wonhyung Cho <wh01.cho@samsung.com>  Mon, 22 Mar 2010 14:56:25 +0900
-
-gst-plugins-good0.10 (0.10.17-15) unstable; urgency=low
-
-  * Because gstbasesrc.h was changed, I build and upload this package again.
-
- -- Wonhyung Cho <wh01.cho@samsung.com>  Mon, 22 Mar 2010 14:31:02 +0900
-
-gst-plugins-good0.10 (0.10.17-14) unstable; urgency=low
-
-  * Remove taglib dependancy
-
- -- Seungbae Shin <seungbae.shin@samsung.com>  Tue, 09 Mar 2010 18:05:52 +0900
-
-gst-plugins-good0.10 (0.10.17-13) unstable; urgency=low
-
-  * Added support for generating index table with key frames as an alternate approach to CQ issue H0100083573 
-
- -- Naveen Ch <naveen.ch@samsung.com>  Mon, 08 Mar 2010 16:58:36 +0530
-
-gst-plugins-good0.10 (0.10.17-12) unstable; urgency=low
-
-  * Repacking by kishore
-
- -- YoungHwan Ahn <younghwan_.an@samsung.com>  Wed, 24 Feb 2010 21:13:22 +0900
-
-gst-plugins-good0.10 (0.10.17-11) unstable; urgency=low
-
-  * avi audio handling for < 4x by kishore
-
- -- YoungHwan Ahn <younghwan_.an@samsung.com>  Tue, 23 Feb 2010 22:33:34 +0900
-
-gst-plugins-good0.10 (0.10.17-10) unstable; urgency=low
-
-  * avi fixes added for trick play
-
- -- Kishore Arepalli <kishore.a@samsung.com>  Tue, 23 Feb 2010 12:39:42 +0530
-
-gst-plugins-good0.10 (0.10.17-9) unstable; urgency=low
-
-  * Trick play added for avidemux by kishore 
-
- -- younghwan ahn <younghwan_.an@samsung.com>  Thu, 18 Feb 2010 13:47:03 +0900
-
-gst-plugins-good0.10 (0.10.17-8) unstable; urgency=low
-
-  * Repacking due to the build failed
-
- -- younghwan ahn <younghwan_.an@samsung.com>  Sat, 06 Feb 2010 01:42:14 +0900
-
-gst-plugins-good0.10 (0.10.17-7) unstable; urgency=low
-
-  * jump to keyframe removed for trick play.. & modified number of lines reduced for trickplay 
-
- -- younghwan ahn <younghwan_.an@samsung.com>  Sat, 06 Feb 2010 01:26:15 +0900
-
-gst-plugins-good0.10 (0.10.17-6) unstable; urgency=low
-
-  * trick play implementation
-
- -- younghwan ahn <younghwan_.an@samsung.com>  Wed, 02 Dec 2009 10:35:21 +0900
-
-gst-plugins-good0.10 (0.10.17-5) unstable; urgency=low
-
-  * check duplicated timestamp after binary sesearch in qtdemux
-
- -- jongmin lee <jm105.lee@samsung.com>  Wed, 02 Dec 2009 10:35:21 +0900
-
-gst-plugins-good0.10 (0.10.17-4) unstable; urgency=low
-
-  * force revision up
-
- -- sangho park <sangho.g.park@samsung.com>  Mon, 30 Nov 2009 11:07:21 +0900
-
-gst-plugins-good0.10 (0.10.17-3) unstable; urgency=low
-
-  * change timeout to 3 sec 
-
- -- sangho park <sangho.g.park@samsung.com>  Mon, 30 Nov 2009 10:44:16 +0900
-
-gst-plugins-good0.10 (0.10.17-2) unstable; urgency=low
-
-  * resolve dependency break 
-
- -- jongmin lee <jm105.lee@samsung.com>  Tue, 17 Nov 2009 17:56:42 +0900
-
-gst-plugins-good0.10 (0.10.17-1) unstable; urgency=low
-
-  * Initial release.
-
- -- jongmin lee <jm105.lee@samsung.com>  The, 17 Nov 2009 12:50:00 +0900
diff --git a/debian/compat b/debian/compat
deleted file mode 100644 (file)
index 7ed6ff8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-5
diff --git a/debian/control b/debian/control
deleted file mode 100755 (executable)
index 17b5600..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-Source: gst-plugins-good0.10
-Section: libs
-Priority: optional
-Maintainer: Shin Seung Bae <seungbae.shin@samsung.com>, JongHyuk Choi <jhchoi.choi@samsung.com>
-Uploaders: younghwan ahn <younghwan_.an@samsung.com>, Naveen Ch <naveen.ch@samsung.com>, Hyunseok Lee <hs7388.lee@samsung.com>, Jeongmo Yang <jm80.yang@samsung.com>
-Build-Depends: libglib2.0-dev (>= 2.16),
-               liboil0.3-dev (>= 0.3.8),
-               libgstreamer0.10-dev (>= 0.10.25),
-               libgstreamer-plugins-base0.10-dev (>= 0.10.25),
-               libjpeg8-dev,
-               libpng12-dev,
-               libsoup2.4-dev,
-               libpulse-dev,
-               libbz2-dev
-Standards-Version: 3.8.0
-
-Package: gstreamer0.10-plugins-good
-Architecture: any
-Section: libs
-Depends: ${misc:Depends}, ${shlibs:Depends}, 
-         libglib2.0-0 (>= 2.16),
-         liboil0.3 (>= 0.3.8),
-         libgstreamer0.10-0 (>= 0.10.25),
-         libgstreamer-plugins-base0.10-0 (>= 0.10.25),
-         libjpeg8,
-         libpng12-0,
-         libsoup2.4,
-         libpulse0,
-         libbz2-1.0
-Description: GStreamer plugins from the "good" set
- GStreamer is a streaming media framework, based on graphs of filters
- which operate on media data.  Applications using this library can do
- anything from real-time sound processing to playing videos, and just
- about anything else media-related.  Its plugin-based architecture means
- that new data types or processing capabilities can be added simply by
- installing new plug-ins.
- .
- This package contains the GStreamer plugins from the "good" set, a set
- of good-quality plug-ins under the LGPL license.
-
-Package: gstreamer0.10-plugins-good-dbg
-Section: debug
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, gstreamer0.10-plugins-good (= ${Source-Version})
-Description: GStreamer plugins from the "good" set (unstripped)
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644 (file)
index e3e9f94..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-This package was debianized by David I. Lehn <dlehn@debian.org> on
-Mon, 15 Jan 2001 18:21:37 -0500.
-
-It was downloaded from http://gstreamer.net/
-
-Upstream Authors:
-
-    Erik Walthinsen <omegahacker@users.sourceforge.net>
-    Wim Taymans <wim.taymans@chello.be>
-    Richard Boulton <richard@tartarus.org>
-    and many more...
-
-Copyright:
-
-    This package is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This package is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this package; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
-
-On Debian GNU/Linux systems, the complete text of the GNU Lesser General
-Public License can be found in `/usr/share/common-licenses/LGPL'.
-
diff --git a/debian/gstreamer0.10-plugins-good.install.in b/debian/gstreamer0.10-plugins-good.install.in
deleted file mode 100644 (file)
index a32767e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-@PREFIX@/lib/gstreamer-0.10/libgst*.so*
diff --git a/debian/rules b/debian/rules
deleted file mode 100755 (executable)
index 0cd87f0..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/usr/bin/make -f
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-CFLAGS ?= -Wall -g -fPIC
-LDFLAGS ?= 
-PREFIX ?= /usr
-DATADIR ?= /opt
-
-CONFIGURE_OPTION += --disable-static           \
-               --disable-nls                   \
-               --with-html-dir=/tmp/dump       \
-               --disable-examples              \
-               --disable-gconftool             \
-               --disable-alpha                 \
-               --disable-apetag                \
-               --disable-audiofx               \
-               --disable-auparse               \
-               --disable-cutter                \
-               --disable-debugutils            \
-               --disable-deinterlace           \
-               --disable-effectv               \
-               --disable-equalizer             \
-               --disable-icydemux              \
-               --disable-flx                   \
-               --disable-goom                  \
-               --disable-goom2k1               \
-               --disable-level                 \
-               --disable-monoscope             \
-               --disable-replaygain            \
-               --disable-smpte                 \
-               --disable-spectrum              \
-               --disable-videobox              \
-               --disable-videomixer            \
-               --disable-y4m                   \
-               --disable-directsound           \
-               --disable-oss                   \
-               --disable-sunaudio              \
-               --disable-osx_aidio             \
-               --disable-osx_video             \
-               --disable-aalib                 \
-               --disable-aalibtest             \
-               --disable-annodex               \
-               --disable-cairo                 \
-               --disable-esd                   \
-               --disable-esdtest               \
-               --disable-flac                  \
-               --disable-gconf                 \
-               --disable-hal                   \
-               --disable-libcaca               \
-               --disable-libdv                 \
-               --disable-dv1394                \
-               --disable-shout2                \
-               --disable-shout2test            \
-               --disable-speex                 \
-               --disable-taglib
-
-#--disable-wavenc   \
-#--disable-bz2 \
-#--disable-jpeg \
-#--disable-autodetext \
-#--disable-wavpack \
-#--disable-avi \
-#--disable-soup \
-#--disable-id3demux \
-#--disable-qtdemux \
-#--disable-rtp \
-#--disable-rtpmanager \
-#--disable-udp \
-#--disable-gst_v4l2 \
-#--disable-taglib \
-#--disable-zlib \
-#--disable-wavparse \
-#--disable-videofilter \
-#--disable-libpng \
-#--disable-x \
-#--disable-xshm \
-#--disable-xvideo \
-#--disable-videocrop \
-
-CFLAGS += -DGST_EXT_SOUP_MODIFICATION
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
-       CFLAGS += -O0
-else
-       CFLAGS += -O2
-endif
-
-#ifneq (,$(findstring arm, $(DEB_HOST_GNU_TYPE)))
-#endif
-
-# architecture is not arm
-ifneq (, $(findstring arm, $(DEB_HOST_ARCH)))
-        # ARM
-       CONFIGURE_OPTION += --enable-divx-drm
-else
-       # OTHER
-endif
-
-LDFLAGS += -Wl,--hash-style=both -Wl,--as-needed
-
-config.status: configure
-       dh_testdir
-       ./autogen.sh
-       # Add here commands to configure the package.
-       ./configure $(CONFIGURE_OPTION) --prefix=$(PREFIX) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
-
-#configure:
-#      dh_testdir
-#      ./autogen.sh
-
-build: build-stamp
-build-stamp:  config.status
-       dh_testdir
-
-       # Add here commands to compile the package.
-       $(MAKE)
-
-       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
-               cat $$f > $${f%.in}; \
-               sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
-               sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
-       done
-
-       touch $@
-
-clean::
-       dh_testdir
-       dh_testroot
-       rm -f build-stamp stamp-h1
-       # Add here commands to clean up after the build process.
-       -$(MAKE) clean
-
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
-       cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
-       cp -f /usr/share/misc/config.guess config.guess
-endif
-
-       find ./ -depth -name "Makefile" -exec rm {} -f \;
-       find ./ -depth -name ".deps" -exec rm {} -rf \;
-       rm -f common/shave
-       rm -f common/shave-libtool
-       rm -f docs/version.entities
-       rm -f gconf/gstreamer.schemas
-       rm -f pkgconfig/gstreamer-plugins-good-uninstalled.pc
-       rm -f po/Makefile.in
-       rm -f po/POTFILES
-       rm -f tests/check/elements/.dirstamp
-       rm -f win32/common/config.h-new
-       rm -f _stdint.h
-       rm -f config.h
-       rm -f config.log
-       rm -f config.status
-       rm -f libtool
-
-       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
-               rm -f $${f%.in}; \
-       done
-
-       dh_clean 
-
-install: build
-       dh_testdir
-       dh_testroot
-       dh_clean -k 
-       dh_installdirs
-
-       # Add here commands to install the package into debian/tmp
-       $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
-       dh_testdir
-       dh_testroot
-       dh_installchangelogs
-       dh_installdocs
-       dh_installexamples
-       dh_install --sourcedir debian/tmp --list-missing
-#      dh_installmenu
-#      dh_installdebconf       
-#      dh_installlogrotate
-#      dh_installemacsen
-#      dh_installpam
-#      dh_installmime
-#      dh_python
-#      dh_installinit
-#      dh_installcron
-#      dh_installinfo
-       dh_installman
-       dh_link
-       dh_strip --dbg-package=gstreamer0.10-plugins-good-dbg
-       dh_compress
-       dh_fixperms
-       dh_perl
-       dh_makeshlibs
-       dh_installdeb
-       dh_shlibdeps 
-       dh_gencontrol
-       dh_md5sums
-       dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install 
diff --git a/debian/rules.old b/debian/rules.old
deleted file mode 100755 (executable)
index b2be11f..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-#!/usr/bin/make -f
-
-include /usr/share/cdbs/1/rules/simple-patchsys.mk
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-# These are used for cross-compiling and for saving the configure script
-# from having to guess our platform (since we know it already)
-DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-CFLAGS ?= -Wall -g
-LDFLAGS ?= 
-PREFIX ?= /usr
-DATADIR ?= /opt
-
-CONFIGURE_OPTION= --disable-static \
---disable-nls \
---with-html-dir=/tmp/dump \
---disable-examples \
---disable-gconftool    \
---disable-alpha    \
---disable-apetag   \
---disable-audiofx  \
---disable-auparse  \
---disable-cutter   \
---disable-debugutils    \
---disable-deinterlace  \
---disable-effectv  \
---disable-equalizer    \
---disable-flv \
---disable-icydemux \
---disable-interleave   \
---disable-flx  \
---disable-goom \
---disable-goom2k1  \
---disable-law  \
---disable-level    \
---disable-matroska \
---disable-monoscope    \
---disable-multifile    \
---disable-multipart    \
---disable-replaygain   \
---disable-smpte    \
---disable-spectrum \
---disable-videobox \
---disable-videomixer   \
---disable-wavenc   \
---disable-y4m  \
---disable-directsound  \
---disable-oss  \
---disable-sunaudio \
---disable-osx_aidio    \
---disable-osx_video    \
---disable-aalib    \
---disable-aalibtest    \
---disable-annodex  \
---disable-cairo    \
---disable-esd  \
---disable-esdtest  \
---disable-flac \
---disable-gconf    \
---disable-gdk_pixbuf   \
---disable-hal  \
---disable-libcaca  \
---disable-libdv    \
---disable-pulse    \
---disable-dv1394   \
---disable-shout2   \
---disable-shout2test   \
---disable-speex
-
-#--disable-bz2 \
-#--disable-jpeg \
-#--disable-autodetext \
-#--disable-wavpack \
-#--disable-avi \
-#--disable-soup \
-#--disable-id3demux \
-#--disable-qtdemux \
-#--disable-rtp \
-#--disable-rtpmanager \
-#--disable-udp \
-#--disable-gst_v4l2 \
-#--disable-taglib \
-#--disable-zlib \
-#--disable-wavparse \
-#--disable-videofilter \
-#--disable-libpng \
-#--disable-x \
-#--disable-xshm \
-#--disable-xvideo \
-#--disable-videocrop \
-
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
-       CFLAGS += -O0
-else
-       CFLAGS += -O2
-endif
-
-#ifneq (,$(findstring arm, $(DEB_HOST_GNU_TYPE)))
-#endif
-
-CFLAGS += -DMODEL_AQUILA
-
-config.status: configure
-       dh_testdir
-       # Add here commands to configure the package.
-       ./configure $(CONFIGURE_OPTION) --prefix=$(PREFIX) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
-
-#configure:
-#      dh_testdir
-#      ./autogen.sh
-
-build: build-stamp
-build-stamp:  config.status
-       dh_testdir
-
-       # Add here commands to compile the package.
-       $(MAKE)
-
-       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
-               cat $$f > $${f%.in}; \
-               sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
-               sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
-       done
-
-       touch $@
-
-clean::
-       dh_testdir
-       dh_testroot
-       rm -f build-stamp stamp-h1
-       # Add here commands to clean up after the build process.
-       -$(MAKE) clean
-
-ifneq "$(wildcard /usr/share/misc/config.sub)" ""
-       cp -f /usr/share/misc/config.sub config.sub
-endif
-ifneq "$(wildcard /usr/share/misc/config.guess)" ""
-       cp -f /usr/share/misc/config.guess config.guess
-endif
-
-       find ./ -depth -name "Makefile" -exec rm {} -f \;
-       find ./ -depth -name ".deps" -exec rm {} -rf \;
-       rm -f common/shave
-       rm -f common/shave-libtool
-       rm -f docs/version.entities
-       rm -f gconf/gstreamer.schemas
-       rm -f pkgconfig/gstreamer-plugins-good-uninstalled.pc
-       rm -f po/Makefile.in
-       rm -f po/POTFILES
-       rm -f tests/check/elements/.dirstamp
-       rm -f win32/common/config.h-new
-       rm -f _stdint.h
-       rm -f config.h
-       rm -f config.log
-       rm -f config.status
-       rm -f libtool
-
-       for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
-               rm -f $${f%.in}; \
-       done
-
-       dh_clean 
-
-install: build
-       dh_testdir
-       dh_testroot
-       dh_clean -k 
-       dh_installdirs
-
-       # Add here commands to install the package into debian/tmp
-       $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
-       dh_testdir
-       dh_testroot
-       dh_installchangelogs
-       dh_installdocs
-       dh_installexamples
-       dh_install --sourcedir debian/tmp --list-missing
-#      dh_installmenu
-#      dh_installdebconf       
-#      dh_installlogrotate
-#      dh_installemacsen
-#      dh_installpam
-#      dh_installmime
-#      dh_python
-#      dh_installinit
-#      dh_installcron
-#      dh_installinfo
-       dh_installman
-       dh_link
-       dh_strip
-       dh_compress
-       dh_fixperms
-       dh_perl
-       dh_makeshlibs
-       dh_installdeb
-       dh_shlibdeps 
-       dh_gencontrol
-       dh_md5sums
-       dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install 
index 2438f5e..0196b45 100644 (file)
@@ -11,13 +11,18 @@ libgstpulse_la_SOURCES = \
        pulsesrc.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_MAJORMINOR) \
+libgstpulse_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(PULSE_CFLAGS) $(INIPARSER_CFLAGS)
+libgstpulse_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(INIPARSER_LIBS) \
        -lgstinterfaces-$(GST_MAJORMINOR) -lgstpbutils-$(GST_MAJORMINOR) \
        $(GST_BASE_LIBS) $(GST_LIBS) $(PULSE_LIBS)
 libgstpulse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstpulse_la_LIBTOOLFLAGS = --tag=disable-static
 
+if PCM_DUMP_ENABLE
+libgstpulse_la_CFLAGS += $(VCONF_CFLAGS) -DPCM_DUMP_ENABLE
+libgstpulse_la_LIBADD += $(VCONF_LIBS)
+endif
+
 noinst_HEADERS = \
        pulsemixerctrl.h \
        pulsemixer.h \
old mode 100644 (file)
new mode 100755 (executable)
index 11e9c89..a9bb341
 #include <gst/pbutils/pbutils.h>        /* only used for GST_PLUGINS_BASE_VERSION_* */
 
 #include <gst/glib-compat-private.h>
-
+#ifdef __TIZEN__
+#include <pulse/ext-policy.h>
+#ifdef PCM_DUMP_ENABLE
+#include <vconf.h>
+#endif
+#include <iniparser.h>
+#endif
 #include "pulsesink.h"
 #include "pulseutil.h"
 
@@ -83,9 +89,83 @@ enum
   PROP_MUTE,
   PROP_CLIENT,
   PROP_STREAM_PROPERTIES,
+#ifdef __TIZEN__
+  PROP_AUDIO_VOLUME_TYPE,
+  PROP_AUDIO_ROUTE_POLICY,
+  PROP_AUDIO_PRIORITY,
+  PROP_AUDIO_USER_ROUTE,
+  PROP_AUDIO_LATENCY,
+  PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE,
+  PROP_AUDIO_SUPPORT_TYPE,
+  PROP_AUDIO_FADE_DURATION,
+#endif
   PROP_LAST
 };
 
+#ifdef __TIZEN__
+#define MEDIA_POLICY_AUTO                   "auto"
+#define MEDIA_POLICY_PHONE                  "phone"
+#define MEDIA_POLICY_ALL                    "all"
+
+#define PULSESINK_MID_LATENCY               150000
+#define PULSESINK_HIGH_LATENCY              400000
+#define PULSESINK_VERY_HIGH_LATENCY         2000000
+#define PULSESINK_WAIT_TIME_FADING          25000
+
+#ifdef PCM_DUMP_ENABLE
+#define GST_PULSESINK_DUMP_VCONF_KEY            "memory/private/sound/pcm_dump"
+#define GST_PULSESINK_DUMP_INPUT_PATH_PREFIX    "/tmp/dump_pulsesink_in_"
+#define GST_PULSESINK_DUMP_OUTPUT_PATH_PREFIX   "/tmp/dump_pulsesink_out_"
+#define GST_PULSESINK_DUMP_INPUT_FLAG           0x00000400
+#define GST_PULSESINK_DUMP_OUTPUT_FLAG          0x00000800
+#endif
+
+typedef enum  {
+       PULSESINK_AUDIOROUTE_USE_EXTERNAL_SETTING = -1,
+       PULSESINK_AUDIOROUTE_PLAYBACK_NORMAL,
+       PULSESINK_AUDIOROUTE_PLAYBACK_ALERT,
+       PULSESINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY
+}GstPulseSinkAudioRoutePolicy;
+
+typedef enum  {
+    PULSESINK_USERROUTE_DEFAULT = 0,
+       PULSESINK_USERROUTE_AUTO = 0,
+       PULSESINK_USERROUTE_PHONE,
+       PULSESINK_USERROUTE_ALL
+}GstPulseSinkUserRoutePolicy;
+
+typedef enum {
+       PULSESINK_LATENCY_LOW,
+       PULSESINK_LATENCY_MID,
+       PULSESINK_LATENCY_HIGH,
+       PULSESINK_LATENCY_VERY_HIGH,
+} GstPulseSinkLatency;
+
+typedef enum  {
+       PULSESINK_AUDIO_UNMUTE = 0,
+       PULSESINK_AUDIO_MUTE,
+#ifdef FADE_FEATURE
+       PULSESINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT,
+#endif
+}GstPulseSinkAudioMute;
+
+typedef enum {
+       PULSESINK_VOLUME_TYPE_SYSTEM,
+       PULSESINK_VOLUME_TYPE_NOTIFICATION,
+       PULSESINK_VOLUME_TYPE_ALARM,
+       PULSESINK_VOLUME_TYPE_RINGTONE,
+       PULSESINK_VOLUME_TYPE_MEDIA,
+       PULSESINK_VOLUME_TYPE_CALL,
+       PULSESINK_VOLUME_TYPE_VOIP,
+       PULSESINK_VOLUME_TYPE_SVOICE,
+       PULSESINK_VOLUME_TYPE_FIXED,
+       PULSESINK_VOLUME_TYPE_EXT_SYSTEM_JAVA,
+       PULSESINK_VOLUME_TYPE_NUM,
+       PULSESINK_VOLUME_TYPE_MAX = PULSESINK_VOLUME_TYPE_NUM
+}GstPulseSinkVolumeType;
+
+#endif
+
 #define GST_TYPE_PULSERING_BUFFER        \
         (gst_pulseringbuffer_get_type())
 #define GST_PULSERING_BUFFER(obj)        \
@@ -588,6 +668,15 @@ gst_pulseringbuffer_close_device (GstRingBuffer * buf)
   gst_pulsering_destroy_context (pbuf);
   pa_threaded_mainloop_unlock (mainloop);
 
+#ifdef __TIZEN__
+#ifdef PCM_DUMP_ENABLE
+  if (psink->dump_fd_input) {
+    fclose(psink->dump_fd_input);
+    psink->dump_fd_input = NULL;
+  }
+#endif
+#endif
+
   GST_LOG_OBJECT (psink, "closed device");
 
   return TRUE;
@@ -809,7 +898,7 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 #endif
   pa_cvolume *pv = NULL;
   pa_stream_flags_t flags;
-  const gchar *name;
+  const gchar *name = NULL;
   GstAudioClock *clock;
 #ifdef HAVE_PULSE_1_0
   pa_format_info *formats[1];
@@ -818,6 +907,13 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 #endif
 #endif
 
+#ifdef __TIZEN__
+  int vol,gain;
+  const char *policy_str = NULL;
+  const char *cur_policy = NULL;
+  pa_sample_spec ss;
+#endif
+
   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
   pbuf = GST_PULSERING_BUFFER_CAST (buf);
 
@@ -848,8 +944,10 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 
   /* initialize the channel map */
 #ifdef HAVE_PULSE_1_0
-  if (pbuf->is_pcm && gst_pulse_gst_to_channel_map (&channel_map, spec))
-    pa_format_info_set_channel_map (pbuf->format, &channel_map);
+  if (pbuf->is_pcm && gst_pulse_gst_to_channel_map (&channel_map, spec)) {
+  /* FIXME:smart switch is not working */
+  /* pa_format_info_set_channel_map (pbuf->format, &channel_map); */
+  }
 #else
   gst_pulse_gst_to_channel_map (&channel_map, spec);
 #endif
@@ -858,7 +956,83 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
   if (psink->stream_name)
     name = psink->stream_name;
   else
+#ifdef __TIZEN__
+    name = psink->latency == PULSESINK_LATENCY_HIGH ? "HIGH LATENCY Playback" : "MID LATENCY Playback";
+#else
     name = "Playback Stream";
+#endif
+
+#ifdef __TIZEN__
+#ifdef PCM_DUMP_ENABLE
+  if (psink->need_dump_input == TRUE && psink->dump_fd_input == NULL) {
+    char *suffix , *dump_path;
+    GDateTime *time = g_date_time_new_now_local();
+
+    suffix = g_date_time_format(time, "%m%d_%H%M%S");
+    dump_path = g_strdup_printf("%s_%s_%dch_%dhz_%s.pcm", GST_PULSESINK_DUMP_INPUT_PATH_PREFIX,
+      (psink->latency == PULSESINK_LATENCY_HIGH) ? "high" : "mid", pbuf->channels, spec->rate, suffix);
+
+    psink->dump_fd_input = fopen(dump_path, "w+");
+
+    g_free(suffix);
+    g_free(dump_path);
+    g_date_time_unref(time);
+  }
+#endif
+
+  if (!psink->proplist)
+    psink->proplist = pa_proplist_new();
+
+  // add gain and volume to proplist
+  vol = psink->volume_type & 0x000000FF;
+  gain = (psink->volume_type >> 8) & 0x000000FF;
+  GST_INFO(">>>>>>>>>> vol(%d), gain(%d), nvalue(%x)", vol, gain, psink->volume_type);
+  pa_proplist_setf(psink->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, "%d", vol);
+  pa_proplist_setf(psink->proplist, PA_PROP_MEDIA_TIZEN_GAIN_TYPE, "%d", gain);
+
+  /* set media policy */
+  cur_policy = pa_proplist_gets(psink->proplist, PA_PROP_MEDIA_POLICY);
+  GST_INFO(" : current media policy = [%s]", cur_policy);
+
+  if (cur_policy == NULL || (cur_policy && strlen(cur_policy) == 0)) {
+#ifdef HAVE_PULSE_1_0
+      /* FIXME : this code will moved to HAL later */
+      GST_WARNING_OBJECT (psink, "latency=%d, format=%d, width=%d, rate=%d, policy(%s)",
+                   psink->latency, spec->format, spec->width, spec->rate, cur_policy);
+      if (psink->latency >= PULSESINK_LATENCY_HIGH) {
+        if (spec->format == GST_S24_LE && spec->width == 32 && spec->rate >= 44100) {
+          pa_proplist_sets(psink->proplist, PA_PROP_MEDIA_POLICY, "auto");
+        } else {
+          pa_proplist_sets(psink->proplist, PA_PROP_MEDIA_POLICY, "high-latency");
+        }
+      } else { /* low or mid */
+#endif
+          if(PULSESINK_USERROUTE_AUTO == psink->user_route) {
+              if (vol == PULSESINK_VOLUME_TYPE_NOTIFICATION
+               || vol == PULSESINK_VOLUME_TYPE_ALARM) {
+                  policy_str = MEDIA_POLICY_ALL;
+              } else if (vol == PULSESINK_VOLUME_TYPE_CALL
+                      || vol == PULSESINK_VOLUME_TYPE_RINGTONE
+                      || vol == PULSESINK_VOLUME_TYPE_FIXED) {
+                  policy_str = MEDIA_POLICY_PHONE;
+              } else {
+                  policy_str = MEDIA_POLICY_AUTO;
+              }
+          } else if(PULSESINK_USERROUTE_PHONE == psink->user_route) {
+              policy_str = MEDIA_POLICY_PHONE;
+          } else if(PULSESINK_USERROUTE_ALL == psink->user_route) {
+              policy_str = MEDIA_POLICY_ALL;
+          }
+
+          pa_proplist_sets(psink->proplist, PA_PROP_MEDIA_POLICY, policy_str);
+
+          GST_ERROR(" ==> set property user-route : (%s)", policy_str);
+      }
+  } else {
+      GST_ERROR_OBJECT (psink, " : proplist exists : [%s]", pa_proplist_to_string(psink->proplist));
+  }
+
+#endif
 
   /* create a stream */
 #ifdef HAVE_PULSE_1_0
@@ -894,10 +1068,27 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
   /* buffering requirements. When setting prebuf to 0, the stream will not pause
    * when we cause an underrun, which causes time to continue. */
   memset (&wanted, 0, sizeof (wanted));
+#ifdef __TIZEN__
+  if (cur_policy && strcmp (cur_policy, "voip") == 0) {
+    ss.format = PA_SAMPLE_S16LE;
+    ss.rate = spec->rate;
+    ss.channels = pbuf->channels;
+    wanted.minreq = pa_usec_to_bytes(20*PA_USEC_PER_MSEC, &ss);
+    wanted.tlength = pa_usec_to_bytes(100*PA_USEC_PER_MSEC, &ss);
+    wanted.maxlength = -1;
+    wanted.prebuf = -1;
+  } else {
+    wanted.tlength = spec->segtotal * spec->segsize;
+    wanted.maxlength = -1;
+    wanted.prebuf = 0;
+    wanted.minreq = spec->segsize;
+  }
+#else
   wanted.tlength = spec->segtotal * spec->segsize;
   wanted.maxlength = -1;
   wanted.prebuf = 0;
   wanted.minreq = spec->segsize;
+#endif
 
   GST_INFO_OBJECT (psink, "tlength:   %d", wanted.tlength);
   GST_INFO_OBJECT (psink, "maxlength: %d", wanted.maxlength);
@@ -1176,7 +1367,6 @@ gst_pulseringbuffer_start (GstRingBuffer * buf)
       g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->abidata.
           ABI.eos_rendering))
     gst_pulsering_set_corked (pbuf, FALSE, FALSE);
-
   pa_threaded_mainloop_unlock (mainloop);
 
   return TRUE;
@@ -1198,6 +1388,7 @@ gst_pulseringbuffer_pause (GstRingBuffer * buf)
   /* make sure the commit method stops writing */
   pbuf->paused = TRUE;
   res = gst_pulsering_set_corked (pbuf, TRUE, TRUE);
+
   if (pbuf->in_commit) {
     /* we are waiting in a commit, signal */
     GST_DEBUG_OBJECT (psink, "signal commit");
@@ -1860,6 +2051,99 @@ gst_pulsesink_payload (GstBaseAudioSink * sink, GstBuffer * buf)
   }
 }
 
+#ifdef __TIZEN__
+
+GType
+gst_pulsesink_audio_route_get_type (void)
+{
+       static GType playback_audio_route_type = 0;
+       static const GEnumValue playback_audio_route[] = {
+               {PULSESINK_AUDIOROUTE_USE_EXTERNAL_SETTING, "Use external sound path", "external"},
+               {PULSESINK_AUDIOROUTE_PLAYBACK_NORMAL, "Auto change between speaker & earphone", "normal"},
+               {PULSESINK_AUDIOROUTE_PLAYBACK_ALERT, "Play via both speaker & earphone", "alert"},
+               {PULSESINK_AUDIOROUTE_PLAYBACK_HEADSET_ONLY, "Play via earphone only", "headset"},
+               {0, NULL, NULL},
+       };
+
+       if (!playback_audio_route_type) {
+               playback_audio_route_type =
+                       g_enum_register_static ("GstPulseSinkAudioRoutePolicy", playback_audio_route);
+       }
+       return playback_audio_route_type;
+}
+
+GType
+gst_pulsesink_user_route_get_type (void)
+{
+       static GType user_route_type = 0;
+       static const GEnumValue user_route[] = {
+               {PULSESINK_USERROUTE_AUTO, "Route automatically", "auto"},
+               {PULSESINK_USERROUTE_PHONE, "Route to phone only", "phone"},
+               {PULSESINK_USERROUTE_ALL, "Route to all", "all"},
+               {0, NULL, NULL},
+       };
+
+       if (!user_route_type) {
+               user_route_type =
+                       g_enum_register_static ("GstPulseSinkUserRoutePolicy",user_route);
+       }
+       return user_route_type;
+}
+
+GType
+gst_pulsesink_latency_get_type (void)
+{
+       static GType avsysaudio_latency_type = 0;
+       static const GEnumValue avsysaudio_latency[] = {
+               {PULSESINK_LATENCY_LOW, "Low latency", "low"},
+               {PULSESINK_LATENCY_MID, "Mid latency", "mid"},
+               {PULSESINK_LATENCY_HIGH, "High latency", "high"},
+               {PULSESINK_LATENCY_VERY_HIGH, "Very High latency", "very-high"},
+               {0, NULL, NULL},
+       };
+
+       if (!avsysaudio_latency_type) {
+               avsysaudio_latency_type =
+                       g_enum_register_static ("GstPulseSinkLatency", avsysaudio_latency);
+       }
+       return avsysaudio_latency_type;
+}
+
+GType
+gst_pulsesink_audio_mute_get_type (void)
+{
+       static GType avaudio_mute_type = 0;
+       static const GEnumValue avaudio_mute[] = {
+               {PULSESINK_AUDIO_UNMUTE, "Unmute", "unmute"},
+               {PULSESINK_AUDIO_MUTE, "Mute immediately", "mute"},
+#ifdef FADE_FEATURE
+               {PULSESINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT, "Mute with fadedown effect", "fadedown"},
+#endif
+               {0, NULL, NULL},
+       };
+
+       if (!avaudio_mute_type) {
+               avaudio_mute_type =
+                       g_enum_register_static ("GstPulseSinkAudioMute", avaudio_mute);
+       }
+       return avaudio_mute_type;
+}
+
+#ifdef PCM_DUMP_ENABLE
+static gboolean
+gst_pulsesink_pad_dump_handler (GstPad *pad, GstBuffer *buffer, gpointer data)
+{
+  GstPulseSink *psink = GST_PULSESINK_CAST (data);
+  int ret = -1;
+
+  if (psink->dump_fd_input)
+    ret = fwrite(GST_BUFFER_DATA(buffer), 1, GST_BUFFER_SIZE(buffer), psink->dump_fd_input);
+
+  return !!ret;
+}
+#endif
+#endif
+
 static void
 gst_pulsesink_class_init (GstPulseSinkClass * klass)
 {
@@ -1910,11 +2194,20 @@ gst_pulsesink_class_init (GstPulseSinkClass * klass)
       g_param_spec_double ("volume", "Volume",
           "Linear volume of this stream, 1.0=100%", 0.0, MAX_VOLUME,
           DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+#ifdef __TIZEN__
+  g_object_class_install_property (gobject_class,
+      PROP_MUTE,
+      g_param_spec_enum("mute", "Tizen Audio Mute",
+          "Mute state of this stream", gst_pulsesink_audio_mute_get_type(), PULSESINK_AUDIO_UNMUTE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
+#else
   g_object_class_install_property (gobject_class,
       PROP_MUTE,
       g_param_spec_boolean ("mute", "Mute",
           "Mute state of this stream", DEFAULT_MUTE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
 
   /**
    * GstPulseSink:client
@@ -1954,6 +2247,54 @@ gst_pulsesink_class_init (GstPulseSinkClass * klass)
       g_param_spec_boxed ("stream-properties", "stream properties",
           "list of pulseaudio stream properties",
           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+#ifdef __TIZEN__
+  g_object_class_install_property (gobject_class,
+      PROP_AUDIO_VOLUME_TYPE,
+      g_param_spec_int ("volumetype", "Avsystem Volume Type",
+          "Select tizen audio software volume type", 0, G_MAXINT, 4,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+      PROP_AUDIO_ROUTE_POLICY,
+      g_param_spec_enum("audio-route", "Audio Route Policy",
+          "Audio route policy of system", gst_pulsesink_audio_route_get_type(), PULSESINK_AUDIOROUTE_USE_EXTERNAL_SETTING,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
+
+  g_object_class_install_property (gobject_class,
+      PROP_AUDIO_PRIORITY,
+      g_param_spec_int ("priority", "Avsystem Sound Priority",
+          "Avsystem sound priority", 0, G_MAXINT, 0,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+      PROP_AUDIO_USER_ROUTE,
+      g_param_spec_enum("user-route", "User Route Policy",
+          "Select tizen user route policy", gst_pulsesink_user_route_get_type(), PULSESINK_USERROUTE_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class,
+      PROP_AUDIO_LATENCY,
+      g_param_spec_enum("latency", "Audio Backend Latency",
+          "Audio backend latency", gst_pulsesink_latency_get_type(), PULSESINK_LATENCY_MID,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
+
+  g_object_class_install_property (gobject_class, PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE,
+      g_param_spec_boolean ("close-handle-on-prepare", "Close Handle on Prepare",
+          "deprecated interface",
+          FALSE, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_AUDIO_SUPPORT_TYPE,
+      g_param_spec_int ("supporttype", "supporttype Type",
+          "Select avsystem audio support type", 0, G_MAXINT,
+          0, G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_AUDIO_FADE_DURATION,
+      g_param_spec_int ("fade_duration", "fade duration time",
+          "Set fade duration time(msec)", 0, G_MAXINT,
+          20, G_PARAM_READWRITE));
+#endif
+
 }
 
 /* returns the current time of the sink ringbuffer */
@@ -2183,9 +2524,41 @@ info_failed:
 }
 #endif
 
+#ifdef __TIZEN__
+static void
+gst_pulsesink_get_configuation(GstPulseSink * pulsesink)
+{
+    dictionary * dict = NULL;
+    const char* path = "/usr/etc/mmfw_audio_config.ini";
+
+    dict = iniparser_load(path);
+    if (!dict) {
+        GST_WARNING_OBJECT(pulsesink, "open failed. path(%s). use default latency", path);
+        pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_MID] = PULSESINK_MID_LATENCY;
+        pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_HIGH] = PULSESINK_HIGH_LATENCY;
+        pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_VERY_HIGH] = PULSESINK_VERY_HIGH_LATENCY;
+    } else {
+        pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_MID] = iniparser_getint(dict, "pulsesink:mid_buffer_time", PULSESINK_MID_LATENCY);
+        pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_MID] = iniparser_getint(dict, "pulsesink:mid_latency_time", 0);
+        pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_HIGH] = iniparser_getint(dict, "pulsesink:high_buffer_time", PULSESINK_HIGH_LATENCY);
+        pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_HIGH] = iniparser_getint(dict, "pulsesink:high_latency_time", 0);
+        pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_VERY_HIGH] = iniparser_getint(dict, "pulsesink:vhigh_buffer_time", PULSESINK_VERY_HIGH_LATENCY);
+        pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_VERY_HIGH] = iniparser_getint(dict, "pulsesink:vhigh_latency_time", 0);
+    }
+    iniparser_freedict(dict);
+}
+#endif
+
 static void
 gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
 {
+#ifdef __TIZEN__
+#ifdef PCM_DUMP_ENABLE
+  GstPad *sinkpad = NULL;
+  int vconf_dump = 0;
+#endif
+#endif
+
   pulsesink->server = NULL;
   pulsesink->device = NULL;
   pulsesink->device_description = NULL;
@@ -2203,6 +2576,27 @@ gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
   pulsesink->mute_set = FALSE;
 
   pulsesink->notify = 0;
+#ifdef __TIZEN__
+  /* default volume is media because webkit use pulsesink without player. */
+  pulsesink->volume_type = 4;
+  pulsesink->fade_stat = PULSESINK_AUDIO_UNMUTE;
+  pulsesink->fade_duration = 20;
+  pulsesink->support_type = 0;
+#ifdef PCM_DUMP_ENABLE
+  if (vconf_get_int(GST_PULSESINK_DUMP_VCONF_KEY, &vconf_dump)) {
+    GST_WARNING("vconf_get_int %s failed", GST_PULSESINK_DUMP_VCONF_KEY);
+  }
+  pulsesink->need_dump_input = vconf_dump & GST_PULSESINK_DUMP_INPUT_FLAG ? TRUE : FALSE;
+  pulsesink->dump_fd_input = NULL;
+  if (pulsesink->need_dump_input) {
+    sinkpad = gst_element_get_static_pad((GstElement *)pulsesink, "sink");
+    gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (gst_pulsesink_pad_dump_handler), pulsesink);
+  }
+#endif
+  memset(pulsesink->buffer_time, 0, sizeof(pulsesink->buffer_time));
+  memset(pulsesink->latency_time, 0, sizeof(pulsesink->latency_time));
+  gst_pulsesink_get_configuation(pulsesink);
+#endif
 
 #ifdef HAVE_PULSE_1_0
   g_atomic_int_set (&pulsesink->format_lost, FALSE);
@@ -2221,6 +2615,7 @@ gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
       (GstAudioClockGetTimeFunc) gst_pulsesink_get_time, pulsesink);
 
 #ifdef HAVE_PULSE_1_0
+  /* FIXME: disable this which causes delay in VT call */
   gst_pad_set_acceptcaps_function (GST_BASE_SINK (pulsesink)->sinkpad,
       GST_DEBUG_FUNCPTR (gst_pulsesink_pad_acceptcaps));
 #endif
@@ -2382,7 +2777,80 @@ unlock:
 no_mainloop:
   {
     psink->mute = mute;
-    psink->mute_set = TRUE;
+    psink->mute_set = FALSE;
+
+    GST_DEBUG_OBJECT (psink, "we have no mainloop");
+    return;
+  }
+no_buffer:
+  {
+    psink->mute = mute;
+    psink->mute_set = FALSE;
+
+    GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
+    goto unlock;
+  }
+no_index:
+  {
+    GST_DEBUG_OBJECT (psink, "we don't have a stream index");
+    goto unlock;
+  }
+mute_failed:
+  {
+    GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
+        ("pa_stream_set_sink_input_mute() failed: %s",
+            pa_strerror (pa_context_errno (pbuf->context))), (NULL));
+    goto unlock;
+  }
+}
+
+#ifdef __TIZEN__
+static void success_context_cb(pa_context *c, int success, void *userdata) {
+    pa_threaded_mainloop_signal(mainloop, 0);
+}
+
+static void
+gst_pulsesink_set_mute_sync (GstPulseSink * psink, gboolean mute)
+{
+  pa_operation *o = NULL;
+  GstPulseRingBuffer *pbuf;
+  uint32_t idx;
+
+  GST_WARNING_OBJECT (psink, "setting mute state to mute(%d)", mute);
+
+  pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
+  if (pbuf == NULL || pbuf->stream == NULL)
+    goto no_buffer;
+
+  if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
+    goto no_index;
+
+  if (!(o = pa_context_set_sink_input_mute (pbuf->context, idx,
+              mute, success_context_cb, NULL)))
+    goto mute_failed;
+
+  while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
+    pa_threaded_mainloop_wait (mainloop);
+    if (gst_pulsering_is_dead (psink, pbuf, TRUE))
+      goto mute_failed;
+  }
+
+  /* We don't really care about the result of this call */
+unlock:
+
+  if (o)
+    pa_operation_unref (o);
+
+  /* wait for fading time */
+  usleep(PULSESINK_WAIT_TIME_FADING);
+
+  return;
+
+  /* ERRORS */
+no_mainloop:
+  {
+    psink->mute = mute;
+    psink->mute_set = FALSE;
 
     GST_DEBUG_OBJECT (psink, "we have no mainloop");
     return;
@@ -2390,7 +2858,7 @@ no_mainloop:
 no_buffer:
   {
     psink->mute = mute;
-    psink->mute_set = TRUE;
+    psink->mute_set = FALSE;
 
     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
     goto unlock;
@@ -2409,6 +2877,79 @@ mute_failed:
   }
 }
 
+#ifdef FADE_FEATURE
+static void
+gst_pulsesink_set_mute_with_fade (GstPulseSink * psink, int fade)
+{
+  pa_operation *o = NULL;
+  GstPulseRingBuffer *pbuf;
+  uint32_t idx;
+
+  if (!mainloop)
+    goto no_mainloop;
+
+  pa_threaded_mainloop_lock (mainloop);
+
+  GST_WARNING_OBJECT(psink, "mute(fade) is comming mute(%d), fade_stat(%d), fade_duration(%d msec)",
+            fade, psink->fade_stat, psink->fade_duration);
+
+  pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
+  if (pbuf == NULL || pbuf->stream == NULL)
+    goto no_buffer;
+
+  if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
+    goto no_index;
+
+  GST_INFO_OBJECT(psink, "context(%p) idx(%d)", pbuf->context, idx);
+  if (!(o = pa_ext_policy_volume_fade (pbuf->context, idx,
+    fade==PULSESINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT ? PA_TIZEN_FADEDOWN_REQUEST : PA_TIZEN_FADEUP_REQUEST, psink->fade_duration, NULL, NULL))) {
+    GST_ERROR_OBJECT(psink, "pa_ext_policy_volume_fade failed. stream(%d), fade(%d)", idx, fade);
+    goto mute_failed;
+  } else {
+    psink->fade_stat = fade;
+  }
+  GST_INFO_OBJECT(psink, "end (%d)", psink->fade_stat);
+
+  /* We don't really care about the result of this call */
+unlock:
+
+  if (o)
+    pa_operation_unref (o);
+
+  pa_threaded_mainloop_unlock (mainloop);
+
+  /* should be returned quickly. */
+  //sleep(duration);
+
+  return;
+
+  /* ERRORS */
+no_mainloop:
+  {
+    GST_DEBUG_OBJECT (psink, "we have no mainloop");
+    return;
+  }
+no_buffer:
+  {
+    GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
+    goto unlock;
+  }
+no_index:
+  {
+    GST_DEBUG_OBJECT (psink, "we don't have a stream index");
+    goto unlock;
+  }
+mute_failed:
+  {
+    GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
+        ("pa_ext_policy_volume_fade() failed: %s",
+            pa_strerror (pa_context_errno (pbuf->context))), (NULL));
+    goto unlock;
+  }
+}
+#endif
+#endif
+
 static void
 gst_pulsesink_sink_input_info_cb (pa_context * c, const pa_sink_input_info * i,
     int eol, void *userdata)
@@ -2647,9 +3188,24 @@ gst_pulsesink_set_property (GObject * object,
     case PROP_VOLUME:
       gst_pulsesink_set_volume (pulsesink, g_value_get_double (value));
       break;
+#ifdef __TIZEN__
+    case PROP_MUTE: {
+        int nvalue = g_value_get_enum(value);
+#ifdef FADE_FEATURE
+        if(nvalue == PULSESINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT && pulsesink->fade_stat == PULSESINK_AUDIO_UNMUTE)
+            gst_pulsesink_set_mute_with_fade(pulsesink, PULSESINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT);
+        else
+#endif
+            gst_pulsesink_set_mute(pulsesink, nvalue==TRUE ? 1 : 0);
+
+        GST_WARNING_OBJECT(pulsesink, "mute end");
+        break;
+    }
+#else
     case PROP_MUTE:
       gst_pulsesink_set_mute (pulsesink, g_value_get_boolean (value));
       break;
+#endif
     case PROP_CLIENT:
       g_free (pulsesink->client_name);
       if (!g_value_get_string (value)) {
@@ -2668,6 +3224,69 @@ gst_pulsesink_set_property (GObject * object,
         pa_proplist_free (pulsesink->proplist);
       pulsesink->proplist = gst_pulse_make_proplist (pulsesink->properties);
       break;
+
+#ifdef __TIZEN__
+    case PROP_AUDIO_VOLUME_TYPE: {
+        char vol = 0;
+        char gain = 0;
+        gint nvalue = g_value_get_int(value);
+
+        pulsesink->volume_type = nvalue;
+        break;
+    }
+    case PROP_AUDIO_ROUTE_POLICY:
+        break;
+    case PROP_AUDIO_PRIORITY:
+        break;
+    case PROP_AUDIO_USER_ROUTE: {
+        gint nvalue = g_value_get_enum(value);
+        pulsesink->user_route = nvalue;
+        break;
+    }
+    case PROP_AUDIO_LATENCY: {
+        gint nvalue = 0;
+        char policy[32] = { '\0', };
+
+        if (!pulsesink->proplist)
+            pulsesink->proplist = pa_proplist_new();
+
+        nvalue = g_value_get_enum(value);
+
+        if(nvalue >= PULSESINK_LATENCY_HIGH) {
+            sprintf(policy, "%s", "high-latency");
+            pa_proplist_sets(pulsesink->proplist, PA_PROP_MEDIA_POLICY, policy);
+
+            if(pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_HIGH])
+                GST_BASE_AUDIO_SINK (pulsesink)->buffer_time = pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_HIGH];
+            if(pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_HIGH])
+                GST_BASE_AUDIO_SINK (pulsesink)->latency_time = pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_HIGH];
+        } else {
+            if(pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_MID])
+                GST_BASE_AUDIO_SINK (pulsesink)->buffer_time = pulsesink->buffer_time[PULSESINK_LOCAL_CONFIGURATION_MID];
+            if(pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_MID])
+                GST_BASE_AUDIO_SINK (pulsesink)->latency_time = pulsesink->latency_time[PULSESINK_LOCAL_CONFIGURATION_MID];
+        }
+
+        GST_WARNING_OBJECT(pulsesink,"buffer information : latency(%d), buffer_time(%lld), latency_time(%lld)", nvalue,
+                GST_BASE_AUDIO_SINK (pulsesink)->buffer_time, GST_BASE_AUDIO_SINK (pulsesink)->latency_time);
+
+        pulsesink->latency = nvalue;
+        break;
+    }
+    case PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE:
+        // deprecated.
+        break;
+    case PROP_AUDIO_SUPPORT_TYPE:
+        pulsesink->support_type = g_value_get_int(value);
+        if(pulsesink->support_type == 4) { // FIXME: call volume (VT call)
+            pa_proplist_sets(pulsesink->proplist, PA_PROP_MEDIA_POLICY, "voip");
+            GST_WARNING_OBJECT(pulsesink, "support type(%d), use voip(videocall) policy", pulsesink->support_type);
+        }
+        break;
+    case PROP_AUDIO_FADE_DURATION:
+        pulsesink->fade_duration = g_value_get_int(value);
+        break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2695,7 +3314,11 @@ gst_pulsesink_get_property (GObject * object,
       g_value_set_double (value, gst_pulsesink_get_volume (pulsesink));
       break;
     case PROP_MUTE:
+#ifdef __TIZEN__
+      g_value_set_enum(value, pulsesink->mute);
+#else
       g_value_set_boolean (value, gst_pulsesink_get_mute (pulsesink));
+#endif
       break;
     case PROP_CLIENT:
       g_value_set_string (value, pulsesink->client_name);
@@ -2703,6 +3326,33 @@ gst_pulsesink_get_property (GObject * object,
     case PROP_STREAM_PROPERTIES:
       gst_value_set_structure (value, pulsesink->properties);
       break;
+
+#ifdef __TIZEN__
+    case PROP_AUDIO_VOLUME_TYPE:
+        g_value_set_int (value, pulsesink->volume_type);
+        break;
+    case PROP_AUDIO_ROUTE_POLICY:
+        break;
+    case PROP_AUDIO_PRIORITY:
+        break;
+    case PROP_AUDIO_USER_ROUTE:
+        GST_ERROR("get property user rouyte");
+        g_value_set_enum (value, pulsesink->user_route);
+        break;
+    case PROP_AUDIO_LATENCY:
+        g_value_set_enum (value, pulsesink->latency);
+        break;
+    case PROP_AUDIO_CLOSE_HANDLE_ON_PREPARE:
+        g_value_set_boolean(value, FALSE);
+        break;
+        case PROP_AUDIO_SUPPORT_TYPE:
+        g_value_set_int(value, pulsesink->support_type);
+        break;
+    case PROP_AUDIO_FADE_DURATION:
+        g_value_set_int(value, pulsesink->fade_duration);
+        break;
+#endif
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2972,7 +3622,6 @@ gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
           gst_message_new_clock_provide (GST_OBJECT_CAST (element),
               GST_BASE_AUDIO_SINK (pulsesink)->provided_clock, TRUE));
       break;
-
     default:
       break;
   }
@@ -2981,6 +3630,16 @@ gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
   if (ret == GST_STATE_CHANGE_FAILURE)
     goto state_failure;
 
+#ifdef __TIZEN__
+  if(transition == GST_STATE_CHANGE_PAUSED_TO_PLAYING) {
+#ifdef FADE_FEATURE
+    if(pulsesink->fade_stat == PULSESINK_AUDIO_MUTE_WITH_FADEDOWN_EFFECT) {
+      gst_pulsesink_set_mute_with_fade(pulsesink, PULSESINK_AUDIO_UNMUTE);
+    }
+#endif
+  }
+#endif
+
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       /* format_lost is reset in release() in baseaudiosink */
index 340b481..01859a2 100644 (file)
@@ -51,6 +51,16 @@ G_BEGIN_DECLS
 #define GST_PULSESINK_CAST(obj) \
   ((GstPulseSink *)(obj))
 
+#ifdef __TIZEN__
+enum {
+       PULSESINK_LOCAL_CONFIGURATION_LOW,
+       PULSESINK_LOCAL_CONFIGURATION_MID,
+       PULSESINK_LOCAL_CONFIGURATION_HIGH,
+       PULSESINK_LOCAL_CONFIGURATION_VERY_HIGH,
+       PULSESINK_LOCAL_CONFIGURATION_MAX,
+};
+#endif
+
 typedef struct _GstPulseSink GstPulseSink;
 typedef struct _GstPulseSinkClass GstPulseSinkClass;
 
@@ -61,17 +71,37 @@ struct _GstPulseSink
   gchar *server, *device, *stream_name, *client_name;
   gchar *device_description;
 
+  gint volume_type;
+  gint latency;
+  gint user_route;
+
   GstPulseProbe *probe;
 
   gdouble volume;
   gboolean volume_set:1;
+#ifdef __TIZEN__
+  gint mute;
+#else
   gboolean mute:1;
+#endif
   gboolean mute_set:1;
 
   guint defer_pending;
 
   gint notify; /* atomic */
 
+#ifdef __TIZEN__
+  gint fade_stat;
+  gint fade_duration;
+  gint support_type;
+  gint buffer_time[PULSESINK_LOCAL_CONFIGURATION_MAX];
+  gint latency_time[PULSESINK_LOCAL_CONFIGURATION_MAX];
+#ifdef PCM_DUMP_ENABLE
+  gint need_dump_input;
+  FILE *dump_fd_input;
+#endif
+#endif
+
   const gchar *pa_version;
 
   GstStructure *properties;
index 12e5282..adeb31a 100644 (file)
@@ -214,6 +214,13 @@ gst_pulsesrc_base_init (gpointer g_class)
           "depth = (int) 8, "
           "rate = (int) [ 1, MAX ], "
           "channels = (int) [ 1, 32 ];"
+          "audio/x-lpcm, "
+          "endianness = (int) { " ENDIANNESS " }, "
+          "signed = (boolean) TRUE, "
+          "width = (int) 16, "
+          "depth = (int) 16, "
+          "rate = (int) [ 1, MAX ], "
+          "channels = (int) [ 1, 32 ];"
           "audio/x-alaw, "
           "rate = (int) [ 1, MAX], "
           "channels = (int) [ 1, 32 ];"
old mode 100644 (file)
new mode 100755 (executable)
index 158eac2..9fa5727
@@ -17,7 +17,7 @@
  *
  * This plugin reads data from a remote location specified by a URI.
  * Supported protocols are 'http', 'https'.
- * 
+ *
  * An HTTP proxy must be specified by its URL.
  * If the "http_proxy" environment variable is set, its value is used.
  * If built with libsoup's GNOME integration features, the GNOME proxy
@@ -87,6 +87,7 @@
 #include <gst/tag/tag.h>
 
 #define SEEK_CHANGES
+
 GST_DEBUG_CATEGORY_STATIC (souphttpsrc_debug);
 #define GST_CAT_DEFAULT souphttpsrc_debug
 
@@ -114,15 +115,29 @@ enum
   PROP_IRADIO_URL,
   PROP_IRADIO_TITLE,
   PROP_TIMEOUT,
+#ifdef GST_EXT_SOUP_MODIFICATION
+  PROP_CONTENT_SIZE,
+  PROP_AHS_STREAMING,
+#endif
 #ifdef SEEK_CHANGES
   PROP_EXTRA_HEADERS,
-  PROP_BLOCKSIZE,
+  PROP_RANGESIZE,
 #else
-  PROP_EXTRA_HEADERS
+  PROP_EXTRA_HEADERS,
 #endif
+  PROP_SOUPCOOKIES
 };
 
-#define DEFAULT_USER_AGENT           "GStreamer souphttpsrc "
+#define DEFAULT_USER_AGENT           "Gstreamer souphttpsrc "
+
+#ifdef GST_EXT_SOUP_MODIFICATION
+#define DEFAULT_RETRY_TIMEOUT -1
+#define DEFAULT_SESSION_TIMEOUT 20
+#define MIN_SESSION_TIMEOUT 5
+
+#define DLNA_OP_TIMED_SEEK  0x02
+#define DLNA_OP_BYTE_SEEK   0x01
+#endif
 
 static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
@@ -142,6 +157,10 @@ static gboolean gst_soup_http_src_is_seekable (GstBaseSrc * bsrc);
 static gboolean gst_soup_http_src_do_seek (GstBaseSrc * bsrc,
     GstSegment * segment);
 static gboolean gst_soup_http_src_query (GstBaseSrc * bsrc, GstQuery * query);
+#ifdef USE_SAMSUNG_LINK
+static gboolean gst_soup_http_src_event (GstBaseSrc * bsrc, GstEvent *event);
+#endif
+
 static gboolean gst_soup_http_src_unlock (GstBaseSrc * bsrc);
 static gboolean gst_soup_http_src_unlock_stop (GstBaseSrc * bsrc);
 static gboolean gst_soup_http_src_set_location (GstSoupHTTPSrc * src,
@@ -152,8 +171,13 @@ static char *gst_soup_http_src_unicodify (const char *str);
 static gboolean gst_soup_http_src_build_message (GstSoupHTTPSrc * src);
 static void gst_soup_http_src_cancel_message (GstSoupHTTPSrc * src);
 static void gst_soup_http_src_queue_message (GstSoupHTTPSrc * src);
+#ifdef GST_EXT_SOUP_MODIFICATION
 static gboolean gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src,
-    guint64 offset);
+    guint64 offset , gchar *range);
+#else
+static gboolean gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src,
+    guint64 offset)
+#endif
 static void gst_soup_http_src_session_unpause_message (GstSoupHTTPSrc * src);
 static void gst_soup_http_src_session_pause_message (GstSoupHTTPSrc * src);
 static void gst_soup_http_src_session_close (GstSoupHTTPSrc * src);
@@ -260,26 +284,50 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
           "HTTP proxy URI user password for authentication", "",
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_COOKIES,
-      g_param_spec_boxed ("cookies", "Cookies", "HTTP request cookies",
+      g_param_spec_boxed("cookies", "Cookies", "HTTP request cookies",
           G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SOUPCOOKIES,
+      g_param_spec_pointer("soupcookies", "soupcookies", "web HTTP request cookies",
+          G_PARAM_WRITABLE));
   g_object_class_install_property (gobject_class, PROP_IS_LIVE,
       g_param_spec_boolean ("is-live", "is-live", "Act like a live source",
           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#ifdef GST_EXT_SOUP_MODIFICATION
+  g_object_class_install_property (gobject_class, PROP_TIMEOUT,
+      g_param_spec_int ("timeout", "timeout",
+          "Value in seconds to timeout (0 = No timeout, -1 = default timeout + infinite retry).", -1,
+          G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#else
   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
       g_param_spec_uint ("timeout", "timeout",
           "Value in seconds to timeout a blocking I/O (0 = No timeout).", 0,
           3600, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
   g_object_class_install_property (gobject_class, PROP_EXTRA_HEADERS,
       g_param_spec_boxed ("extra-headers", "Extra Headers",
           "Extra headers to append to the HTTP request",
           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
 #ifdef SEEK_CHANGES
-  g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
-      g_param_spec_int64 ("blocksize", "blocksize",
+  g_object_class_install_property (gobject_class, PROP_RANGESIZE,
+      g_param_spec_int64 ("rangesize", "rangesize",
           "Size of each buffer downloaded from libsoup",
           -1, G_MAXUINT, 4096, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 #endif
+
+#ifdef GST_EXT_SOUP_MODIFICATION
+  g_object_class_install_property (gobject_class, PROP_CONTENT_SIZE,
+      g_param_spec_uint64 ("content-size", "contentsize",
+          "Total size of the content under download",
+          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class,
+      PROP_AHS_STREAMING,
+      g_param_spec_boolean ("ahs-streaming", "adaptive HTTP Streaming",
+          "set whether adaptive HTTP streaming(HLS/SS/DASH) or not ",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
+
   /* icecast stuff */
   g_object_class_install_property (gobject_class,
       PROP_IRADIO_MODE,
@@ -318,6 +366,9 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
   gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_soup_http_src_get_size);
   gstbasesrc_class->is_seekable =
       GST_DEBUG_FUNCPTR (gst_soup_http_src_is_seekable);
+#ifdef USE_SAMSUNG_LINK
+  gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_soup_http_src_event);
+#endif
   gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_soup_http_src_do_seek);
   gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_soup_http_src_query);
 
@@ -334,7 +385,13 @@ gst_soup_http_src_reset (GstSoupHTTPSrc * src)
   src->read_position = 0;
   src->request_position = 0;
   src->content_size = 0;
-
+  src->have_body = FALSE;
+#ifdef GST_EXT_SOUP_MODIFICATION
+  src->content_len = 0;
+  src->timeout = DEFAULT_RETRY_TIMEOUT;
+  src->session_timeout = DEFAULT_SESSION_TIMEOUT;
+  src->op_code = 0;
+#endif
 #ifdef SEEK_CHANGES
   src->file_size = 0;
 #endif
@@ -377,6 +434,12 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src, GstSoupHTTPSrcClass * g_class)
         "The proxy in the http_proxy env var (\"%s\") cannot be parsed.",
         proxy);
   }
+#ifdef GST_EXT_SOUP_MODIFICATION
+  src->is_ahs_streaming = FALSE;
+  src->cookie_jar  = NULL;
+  src->cookie_list = NULL;
+  src->op_code = 0;
+#endif
 
   gst_soup_http_src_reset (src);
 }
@@ -397,6 +460,11 @@ gst_soup_http_src_finalize (GObject * gobject)
   g_free (src->user_pw);
   g_free (src->proxy_id);
   g_free (src->proxy_pw);
+  if (src->cookie_list != NULL) {
+    g_slist_free (src->cookie_list);
+    src->cookie_list = NULL;
+  }
+
   g_strfreev (src->cookies);
 
   G_OBJECT_CLASS (parent_class)->finalize (gobject);
@@ -456,19 +524,80 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
     {
 #ifdef GST_EXT_SOUP_MODIFICATION
       char **array;
+      SoupURI *base_uri;
+
 #endif
       g_strfreev (src->cookies);
       src->cookies = g_strdupv (g_value_get_boxed (value));
 #ifdef GST_EXT_SOUP_MODIFICATION
-      if ((array = src->cookies) != NULL) {
+      if (src->cookie_jar && ((array = src->cookies) != NULL)) {
+               base_uri = soup_uri_new (src->location);
+        GST_INFO_OBJECT (src, "request to set cookies...");
         while (*array != NULL) {
           soup_cookie_jar_add_cookie (src->cookie_jar,
-              soup_cookie_parse (*array++, NULL));
+              soup_cookie_parse (*array++, base_uri));
         }
+        soup_uri_free (base_uri);
+      } else {
+        GST_INFO_OBJECT (src, "set cookies after session creation");
       }
 #endif
       break;
     }
+#ifdef GST_EXT_SOUP_MODIFICATION
+    case PROP_SOUPCOOKIES:
+    {
+      GSList *walk, *new_cookies;
+      SoupCookie* cookie;
+
+      new_cookies = (GSList*)g_value_get_pointer(value);
+
+      /* remove old list and alloc new */
+      if (src->cookie_list)
+      {
+        g_slist_free (src->cookie_list);
+      }
+      src->cookie_list = g_slist_alloc();
+
+      if ( new_cookies )
+      {
+        walk = new_cookies;
+
+        /* check if cookie_jar is created */
+        if ( src->cookie_jar )
+        {
+          GST_INFO_OBJECT (src, "cookie jar exist. adding it to jar");
+          for ( ; walk; walk = walk->next)
+          {
+            cookie = (SoupCookie*)walk->data;
+            if ( cookie )
+            {
+              GST_INFO_OBJECT (src, "adding cookie to jar : %s - %s",
+              cookie->name, cookie->value);
+              soup_cookie_jar_add_cookie (src->cookie_jar, cookie);
+            }
+          }
+        }
+        else
+        /* cooke jar not created yet. new cookies will be stored in temporal list
+        * and will be added to jar when start() has called */
+        {
+          GST_INFO_OBJECT (src, "cookie jar not yet created. adding to temporal list");
+          for ( ; walk; walk = walk->next )
+          {
+            src->cookie_list = g_slist_prepend(src->cookie_list,
+            soup_cookie_copy(walk->data));
+          }
+        }
+      }
+      break;
+    }
+#endif
+#ifdef GST_EXT_SOUP_MODIFICATION
+    case PROP_AHS_STREAMING:
+      src->is_ahs_streaming = g_value_get_boolean (value);
+      break;
+#endif
     case PROP_IS_LIVE:
       gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
       break;
@@ -493,7 +622,11 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
       src->proxy_pw = g_value_dup_string (value);
       break;
     case PROP_TIMEOUT:
+#ifdef GST_EXT_SOUP_MODIFICATION
+      src->timeout = g_value_get_int (value);
+#else
       src->timeout = g_value_get_uint (value);
+#endif
       break;
     case PROP_EXTRA_HEADERS:{
       const GstStructure *s = gst_value_get_structure (value);
@@ -505,11 +638,12 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
       break;
     }
 #ifdef SEEK_CHANGES
-       case PROP_BLOCKSIZE:{
-         src->range_size = g_value_get_int64 (value);
-         break;
-       }
+    case PROP_RANGESIZE:{
+      src->range_size = g_value_get_int64 (value);
+      break;
+    }
 #endif
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -571,6 +705,11 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id,
     case PROP_IRADIO_MODE:
       g_value_set_boolean (value, src->iradio_mode);
       break;
+#ifdef GST_EXT_SOUP_MODIFICATION
+    case PROP_AHS_STREAMING:
+      g_value_set_boolean (value, src->is_ahs_streaming);
+      break;
+#endif
     case PROP_IRADIO_NAME:
       g_value_set_string (value, src->iradio_name);
       break;
@@ -596,16 +735,25 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id,
       g_value_set_string (value, src->proxy_pw);
       break;
     case PROP_TIMEOUT:
+#ifdef GST_EXT_SOUP_MODIFICATION
+      g_value_set_int (value, src->timeout);
+#else
       g_value_set_uint (value, src->timeout);
+#endif
       break;
     case PROP_EXTRA_HEADERS:
       gst_value_set_structure (value, src->extra_headers);
       break;
 #ifdef SEEK_CHANGES
-    case PROP_BLOCKSIZE:
+    case PROP_RANGESIZE:
          g_value_set_int64 (value, src->range_size);
          break;
 #endif
+#ifdef GST_EXT_SOUP_MODIFICATION
+    case PROP_CONTENT_SIZE:
+      g_value_set_uint64 (value, src->content_len);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -636,13 +784,19 @@ gst_soup_http_src_cancel_message (GstSoupHTTPSrc * src)
 static void
 gst_soup_http_src_queue_message (GstSoupHTTPSrc * src)
 {
+
   soup_session_queue_message (src->session, src->msg,
       (SoupSessionCallback) gst_soup_http_src_response_cb, src);
   src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_QUEUED;
 }
 
+#ifdef GST_EXT_SOUP_MODIFICATION
+static gboolean
+gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src, guint64 offset ,gchar *range)
+#else
 static gboolean
 gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src, guint64 offset)
+#endif
 {
   gchar buf[64];
 
@@ -651,13 +805,66 @@ gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src, guint64 offset)
   soup_message_headers_remove (src->msg->request_headers, "Range");
 
 #ifdef GST_EXT_SOUP_MODIFICATION
-  /* Note : Some http server could not handle Range header in the middle of playing.
-   *    Need to add Range header at first for seeking properly.
-   */
-  rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-", offset);
-  if (rc > sizeof (buf) || rc < 0)
-    return FALSE;
-  soup_message_headers_append (src->msg->request_headers, "Range", buf);
+
+  if ((range != NULL) && src->is_ahs_streaming) {
+    guint len, pos;
+    gchar *str = NULL;
+    guint64 first_byte_pos = 0, last_byte_pos = 0;
+
+    str = range +6 ;//remove 'range='
+    len = strlen(range);
+    GST_DEBUG(" mediaRange : %s", str);
+
+    /* read "-" */
+    pos = strcspn (str, "-");
+    if (pos >= len) {
+      GST_TRACE ("pos %d >= len %d", pos, len);
+      GST_WARNING ("pos >= len !");
+      return FALSE;
+    }
+    /* read first_byte_pos */
+    if (pos != 0) {
+      if (sscanf (str, "%llu", &first_byte_pos) != 1) {
+        GST_WARNING ("can not get first_byte_pos");
+        return FALSE;
+      }
+    }
+    /* read last_byte_pos */
+    if (pos < (len - 1)) {
+      if (sscanf (str + pos + 1, "%llu", &last_byte_pos) != 1) {
+        GST_WARNING ("can not get last_byte_pos");
+        return FALSE;
+      }
+    }
+
+    GST_DEBUG_OBJECT(src,"- requestRange: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT,
+        first_byte_pos, last_byte_pos);
+
+    rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT, first_byte_pos, last_byte_pos);
+      if (rc > sizeof (buf) || rc < 0)
+          return FALSE;
+    soup_message_headers_append (src->msg->request_headers, "Range", buf);
+       }
+
+ else {
+
+  if (!src->is_ahs_streaming) {
+    /* Note : Some http server could not handle Range header in the middle of playing.
+     *    Need to add Range header at first for seeking properly.
+     */
+    rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-", offset);
+    if (rc > sizeof (buf) || rc < 0)
+      return FALSE;
+    soup_message_headers_append (src->msg->request_headers, "Range", buf);
+  } else {
+    if (offset) {
+      rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-", offset);
+      if (rc > sizeof (buf) || rc < 0)
+        return FALSE;
+      soup_message_headers_append (src->msg->request_headers, "Range", buf);
+    }
+  }
+}
 #else
   if (offset) {
     rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-", offset);
@@ -698,6 +905,33 @@ _append_extra_header (GQuark field_id, const GValue * value, gpointer user_data)
       field_content);
   soup_message_headers_append (src->msg->request_headers, field_name,
       field_content);
+#ifdef GST_EXT_SOUP_MODIFICATION
+  if (!g_ascii_strcasecmp(field_name, "Cookie")) {
+    SoupURI *uri = NULL;
+    SoupCookie *cookie_parsed = NULL;
+
+    if (strlen(field_content) > 0) {
+      gchar *tmp_field = NULL;
+
+      uri = soup_uri_new (src->location);
+
+      tmp_field = strtok (field_content, ";");
+
+      while (tmp_field != NULL) {
+        GST_DEBUG_OBJECT (src, "field_content = %s", tmp_field);
+
+        cookie_parsed = soup_cookie_parse(tmp_field, uri);
+        GST_DEBUG_OBJECT (src, "cookie parsed = %p", cookie_parsed);
+
+        if (src->cookie_jar)
+          soup_cookie_jar_add_cookie (src->cookie_jar, cookie_parsed);
+
+        tmp_field = strtok (NULL, ";");
+      }
+      soup_uri_free (uri);
+    }
+  }
+#endif
 
   g_free (field_content);
 
@@ -790,6 +1024,31 @@ gst_soup_http_src_headers_foreach (const gchar * name, const gchar * val,
     gpointer src)
 {
   GST_DEBUG_OBJECT (src, " %s: %s", name, val);
+
+#ifdef GST_EXT_SOUP_MODIFICATION
+  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);
+    }
+  }
+#endif
 }
 
 static void
@@ -805,6 +1064,11 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
   GHashTable *params = NULL;
 
   GST_DEBUG_OBJECT (src, "got headers:");
+
+#ifdef GST_EXT_SOUP_MODIFICATION
+  src->retry_timestamp = 0;
+#endif
+
   soup_message_headers_foreach (msg->response_headers,
       gst_soup_http_src_headers_foreach, src);
 
@@ -828,6 +1092,52 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
 
   src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING;
 
+#ifdef GST_EXT_SOUP_MODIFICATION
+  if ((value =
+          soup_message_headers_get (msg->response_headers,
+              "contentFeatures.dlna.org")) != NULL) {
+    gchar **token = NULL;
+    gchar **ptr = NULL;
+
+    token = g_strsplit (value, ";", 0);
+
+    for (ptr = token ; *ptr ; ptr++)
+    {
+      if (strlen(*ptr) > 0)
+      {
+        if (strstr(g_ascii_strup(*ptr, strlen(*ptr)), "DLNA.ORG_OP") != NULL)
+        {
+          gchar *op_code = NULL;
+
+          op_code = strchr(*ptr, '=');
+          if (op_code)
+          {
+            op_code++;
+
+            src->op_code = (atoi(op_code)/10 <<1) | (atoi(op_code)%10);
+            GST_DEBUG_OBJECT (src, "dlna op code: %s (0x%X)", op_code, src->op_code);
+          }
+        }
+      }
+    }
+    g_strfreev (token);
+  }
+
+  if ((value = soup_message_headers_get (msg->response_headers, "Content-Duration")) != NULL) {
+    src->duration = atoi(value) * G_GINT64_CONSTANT (1000000);
+    GST_DEBUG_OBJECT (src, "Content Duration is %"GST_TIME_FORMAT, GST_TIME_ARGS (src->duration));
+  }
+
+#endif
+
+#ifdef USE_SAMSUNG_LINK
+  if ((value = soup_message_headers_get (msg->response_headers, "X-ASP-DURATION-TIME")) != NULL) {
+    src->is_x_asp = TRUE;
+    src->duration = atoi(value) * G_GINT64_CONSTANT (1000000);
+    GST_DEBUG_OBJECT (src, "X-ASP-DURATION-TIME is %"GST_TIME_FORMAT, GST_TIME_ARGS (src->duration));
+  }
+#endif
+
   /* Parse Content-Length. */
   if (soup_message_headers_get_encoding (msg->response_headers) ==
       SOUP_ENCODING_CONTENT_LENGTH) {
@@ -841,8 +1151,10 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
 #endif
       src->have_size = TRUE;
       src->seekable = TRUE;
-      GST_DEBUG_OBJECT (src, "size = %" G_GUINT64_FORMAT, src->content_size);
-
+      GST_DEBUG_OBJECT (src, "content size = %" G_GUINT64_FORMAT, src->content_size);
+#ifdef GST_EXT_SOUP_MODIFICATION
+      src->content_len = src->content_size;
+#endif
       basesrc = GST_BASE_SRC_CAST (src);
       gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES,
           src->content_size);
@@ -855,7 +1167,7 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
     if(total_length > 0)
     {
       src->file_size = total_length;
-      GST_DEBUG_OBJECT (src, "size = %" G_GUINT64_FORMAT, src->file_size);
+      GST_DEBUG_OBJECT (src, "total size = %" G_GUINT64_FORMAT, src->file_size);
       basesrc = GST_BASE_SRC_CAST (src);
       gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES,
           src->file_size);
@@ -865,6 +1177,27 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
     }
 #endif
   }
+#ifdef GST_EXT_SOUP_MODIFICATION
+  else if ((soup_message_headers_get_encoding (msg->response_headers) ==
+            SOUP_ENCODING_CHUNKED) && (src->op_code & DLNA_OP_BYTE_SEEK)) {
+    soup_message_headers_get_content_range(msg->response_headers, &start, &end, &total_length);
+    if(total_length > 0)
+    {
+      src->have_size = TRUE;
+      src->seekable = TRUE;
+
+      src->content_size = src->content_len = src->file_size = total_length;
+
+      GST_DEBUG_OBJECT (src, "total size = %" G_GUINT64_FORMAT, src->file_size);
+      basesrc = GST_BASE_SRC_CAST (src);
+      gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES,
+          src->file_size);
+      gst_element_post_message (GST_ELEMENT (src),
+          gst_message_new_duration (GST_OBJECT (src), GST_FORMAT_BYTES,
+              src->file_size));
+    }
+  }
+#endif
 
   /* Icecast stuff */
   tag_list = gst_tag_list_new ();
@@ -883,10 +1216,26 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
           "metadata-interval", G_TYPE_INT, icy_metaint, NULL);
     }
   }
+#ifdef SEEK_CHANGES
+  if ((msg->status_code == 200) && (value=soup_message_headers_get (msg->response_headers,"Accept-Ranges")) != NULL) {
+    GST_DEBUG_OBJECT (src, "Accept-ranges: %s ", value);
+    if(strstr(value,"none")!=NULL) {
+      src->seekable=FALSE;
+      GST_DEBUG_OBJECT (src, "server is not seekable");
+    }
+    else
+      src->seekable=TRUE;
+  }
+  else if(msg->status_code == 200) {
+    src->seekable=FALSE;
+    GST_DEBUG_OBJECT (src, "server is not seekable");
+  }
+#endif
   if ((value =
           soup_message_headers_get_content_type (msg->response_headers,
               &params)) != NULL) {
     GST_DEBUG_OBJECT (src, "Content-Type: %s", value);
+
     if (g_ascii_strcasecmp (value, "audio/L16") == 0) {
       gint channels = 2;
       gint rate = 44100;
@@ -964,6 +1313,12 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
   /* Handle HTTP errors. */
   gst_soup_http_src_parse_status (msg, src);
 
+#ifdef GST_EXT_SOUP_MODIFICATION
+  if(src->is_ahs_streaming && msg->status_code == 404){
+    GST_WARNING_OBJECT (src,"Received 404 error while HLS streaming.");
+    src->content_len = 0;
+  }
+#endif
   /* Check if Range header was respected. */
   if (src->ret == GST_FLOW_CUSTOM_ERROR &&
       src->read_position && msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) {
@@ -990,9 +1345,14 @@ gst_soup_http_src_got_body_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
   }
   GST_DEBUG_OBJECT (src, "got body");
   src->ret = GST_FLOW_UNEXPECTED;
-  if (src->loop)
-    g_main_loop_quit (src->loop);
-  gst_soup_http_src_session_pause_message (src);
+  src->have_body = TRUE;
+
+  /* no need to interrupt the message here, we do it on the
+   * finished_cb anyway if needed. And getting the body might mean
+   * that the connection was hang up before finished. This happens when
+   * the pipeline is stalled for too long (long pauses during playback).
+   * Best to let it continue from here and pause because it reached the
+   * final bytes based on content_size or received an out of range error */
 }
 
 /* Finished. Signal EOS. */
@@ -1003,24 +1363,83 @@ gst_soup_http_src_finished_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
     GST_DEBUG_OBJECT (src, "finished, but not for current message");
     return;
   }
-  GST_DEBUG_OBJECT (src, "finished");
+
+  GST_WARNING_OBJECT (src, "finished : %d", src->session_io_status);
   src->ret = GST_FLOW_UNEXPECTED;
   if (src->session_io_status == GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_CANCELLED) {
     /* gst_soup_http_src_cancel_message() triggered this; probably a seek
      * that occurred in the QUEUEING state; i.e. before the connection setup
      * was complete. Do nothing */
   } else if (src->session_io_status ==
-      GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING && src->read_position > 0) {
+      GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING && src->read_position > 0 &&
+      (src->have_size || src->read_position < src->content_size)) {
     /* The server disconnected while streaming. Reconnect and seeking to the
      * last location. */
     src->retry = TRUE;
     src->ret = GST_FLOW_CUSTOM_ERROR;
   } else if (G_UNLIKELY (src->session_io_status !=
           GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING)) {
-    /* FIXME: reason_phrase is not translated, add proper error message */
-    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
-        ("%s", msg->reason_phrase),
-        ("libsoup status code %d", msg->status_code));
+#ifdef GST_EXT_SOUP_MODIFICATION
+    if (msg->status_code != SOUP_STATUS_OK) {
+      if ((src->read_position <= 0) || (src->timeout == 0)) {
+        /* FIXME: reason_phrase is not translated, add proper error message */
+        GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
+            ("%s", msg->reason_phrase),
+            ("libsoup status code %d", msg->status_code));
+      } else {
+        GstClockTime current = 0, elapsed = 0;
+
+        GST_WARNING_OBJECT(src, "session timout:%d, timeout:%d", src->session_timeout, src->timeout);
+
+        /* Assumption : soup error will be occurred after session timeout. */
+        if (src->retry_timestamp == 0) {
+          GstClockTime retry_timestamp = 0;
+          retry_timestamp = gst_util_get_timestamp();
+          if (retry_timestamp > (src->session_timeout*GST_SECOND))
+            src->retry_timestamp = gst_util_get_timestamp() - (src->session_timeout*GST_SECOND);
+          else
+            src->retry_timestamp = 0;
+        }
+
+        current = gst_util_get_timestamp ();
+        elapsed = GST_CLOCK_DIFF (src->retry_timestamp, current);
+
+        if ((src->timeout == DEFAULT_RETRY_TIMEOUT) || (elapsed <= (src->timeout*GST_SECOND))) {
+
+          if (src->timeout != DEFAULT_RETRY_TIMEOUT) {
+            guint new_session_timeout = src->timeout - (elapsed/GST_SECOND);
+
+            if (new_session_timeout < MIN_SESSION_TIMEOUT)
+              new_session_timeout = MIN_SESSION_TIMEOUT;
+            else if (new_session_timeout > DEFAULT_SESSION_TIMEOUT)
+              new_session_timeout = DEFAULT_SESSION_TIMEOUT;
+
+            if (new_session_timeout != src->session_timeout) {
+              src->session_timeout = new_session_timeout;
+              g_object_set(src->session, SOUP_SESSION_TIMEOUT, src->session_timeout, NULL);
+            }
+          }
+
+          GST_WARNING_OBJECT(src, "retry. session timeout : %d", src->session_timeout);
+
+          src->retry = TRUE;
+          src->ret = GST_FLOW_CUSTOM_ERROR;
+        } else {
+          src->timeout = 0;
+          GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
+              ("%s", msg->reason_phrase),
+              ("libsoup status code %d", msg->status_code));
+        }
+      }
+    }
+#else
+    if (msg->status_code != SOUP_STATUS_OK){
+      /* FIXME: reason_phrase is not translated, add proper error message */
+      GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
+          ("%s", msg->reason_phrase),
+          ("libsoup status code %d", msg->status_code));
+    }
+#endif
   }
   if (src->loop)
     g_main_loop_quit (src->loop);
@@ -1103,6 +1522,8 @@ gst_soup_http_src_got_chunk_cb (SoupMessage * msg, SoupBuffer * chunk,
     GST_DEBUG_OBJECT (src, "got chunk, but not for current message");
     return;
   }
+
+  src->have_body = FALSE;
   if (G_UNLIKELY (src->session_io_status !=
           GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING)) {
     /* Probably a redirect. */
@@ -1149,7 +1570,7 @@ gst_soup_http_src_response_cb (SoupSession * session, SoupMessage * msg,
     /* Ignore redirections. */
     return;
   }
-  GST_DEBUG_OBJECT (src, "got response %d: %s", msg->status_code,
+  GST_WARNING_OBJECT (src, "got response %d: %s", msg->status_code,
       msg->reason_phrase);
   if (src->session_io_status == GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING &&
       src->read_position > 0) {
@@ -1175,15 +1596,25 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
     switch (msg->status_code) {
       case SOUP_STATUS_CANT_RESOLVE:
       case SOUP_STATUS_CANT_RESOLVE_PROXY:
-        SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, NOT_FOUND,
-            _("Could not resolve server name."));
-        src->ret = GST_FLOW_ERROR;
+#ifdef GST_EXT_SOUP_MODIFICATION
+        if (src->retry != TRUE)
+#endif
+        {
+          SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, NOT_FOUND,
+              _("Could not resolve server name."));
+          src->ret = GST_FLOW_ERROR;
+        }
         break;
       case SOUP_STATUS_CANT_CONNECT:
       case SOUP_STATUS_CANT_CONNECT_PROXY:
-        SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, OPEN_READ,
-            _("Could not establish connection to server."));
-        src->ret = GST_FLOW_ERROR;
+#ifdef GST_EXT_SOUP_MODIFICATION
+        if (src->retry != TRUE)
+#endif
+        {
+          SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, OPEN_READ,
+              _("Could not establish connection to server."));
+          src->ret = GST_FLOW_ERROR;
+        }
         break;
       case SOUP_STATUS_SSL_FAILED:
         SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, OPEN_READ,
@@ -1191,10 +1622,15 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
         src->ret = GST_FLOW_ERROR;
         break;
       case SOUP_STATUS_IO_ERROR:
-        SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, READ,
-            _("A network error occured, or the server closed the connection "
-                "unexpectedly."));
-        src->ret = GST_FLOW_ERROR;
+#ifdef GST_EXT_SOUP_MODIFICATION
+        if (src->retry != TRUE)
+#endif
+        {
+          SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, READ,
+              _("A network error occured, or the server closed the connection "
+                  "unexpectedly."));
+          src->ret = GST_FLOW_ERROR;
+        }
         break;
       case SOUP_STATUS_MALFORMED:
         SOUP_HTTP_SRC_ERROR (src, msg, RESOURCE, READ,
@@ -1209,6 +1645,17 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
       SOUP_STATUS_IS_REDIRECTION (msg->status_code) ||
       SOUP_STATUS_IS_SERVER_ERROR (msg->status_code)) {
     /* Report HTTP error. */
+    /* 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 */
+    if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE &&
+        src->have_body && src->have_size) {
+      GST_WARNING_OBJECT (src, "Requested range out of limits and received full "
+          "body, returning EOS");
+      src->ret = GST_FLOW_UNEXPECTED;
+      return;
+    }
+
     /* FIXME: reason_phrase is not translated and not suitable for user
      * error dialog according to libsoup documentation.
      * FIXME: error code (OPEN_READ vs. READ) should depend on http status? */
@@ -1223,6 +1670,8 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
 static gboolean
 gst_soup_http_src_build_message (GstSoupHTTPSrc * src)
 {
+  gchar *user_agent = DEFAULT_USER_AGENT;
+
   src->msg = soup_message_new (SOUP_METHOD_GET, src->location);
   if (!src->msg) {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
@@ -1236,31 +1685,54 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src)
     soup_message_headers_append (src->msg->request_headers, "icy-metadata",
         "1");
   }
-  if (src->cookies) {
-    gchar **cookie;
+
+  if (src->user_agent) {
+    user_agent = src->user_agent;
+    GST_DEBUG_OBJECT(src, "Set User-Agent = %s", user_agent);
+  }
+
+  soup_message_headers_append (src->msg->request_headers, "User-Agent",
+        user_agent);
+
+#ifdef SEEK_CHANGES
+  soup_message_headers_append (src->msg->request_headers, "Accept-Ranges","bytes");
+#endif
+
+
 #ifdef GST_EXT_SOUP_MODIFICATION
-    SoupURI *uri;
-    SoupCookie *cookie_parsed;
+  if (src->cookie_jar) {
+    GSList *cookie_list, *c;
+    gchar **cookies;
     gchar *header;
 
+    SoupURI *uri = NULL;
+    SoupCookie *cookie;
     uri = soup_uri_new (src->location);
-    for (cookie = src->cookies; *cookie != NULL; cookie++) {
-      if ((cookie_parsed = soup_cookie_parse (*cookie, uri)) != NULL) {
-        header = soup_cookie_to_cookie_header (cookie_parsed);
-        soup_message_headers_append (src->msg->request_headers, "Cookie",
+
+    if ((cookie_list = soup_cookie_jar_all_cookies (src->cookie_jar)) != NULL) {
+      cookies = g_new0 (gchar *, g_slist_length(cookie_list) + 1);
+      for (c = cookie_list; c; c = c->next) {
+        cookie = (SoupCookie *)c->data;
+        if (soup_cookie_applies_to_uri(cookie, uri)) {
+          header = soup_cookie_to_cookie_header (cookie);
+          soup_message_headers_append (src->msg->request_headers, "Cookie",
           header);
-        g_free (header);
-        soup_cookie_free (cookie_parsed);
+          g_free (header);
+        }
       }
     }
-    soup_uri_free (uri);
+    soup_cookies_free (cookie_list);
+  }
 #else
+  gchar **cookie;
+  if (src->cookies) {
     for (cookie = src->cookies; *cookie != NULL; cookie++) {
       soup_message_headers_append (src->msg->request_headers, "Cookie",
-          *cookie);
+        *cookie);
     }
-#endif
   }
+#endif
+
   soup_message_headers_append (src->msg->request_headers,
       "transferMode.dlna.org", "Streaming");
   src->retry = FALSE;
@@ -1277,18 +1749,48 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src)
       (src->automatic_redirect ? 0 : SOUP_MESSAGE_NO_REDIRECT));
   soup_message_set_chunk_allocator (src->msg,
       gst_soup_http_src_chunk_allocator, src, NULL);
+
+#ifdef USE_SAMSUNG_LINK
+  if(src->is_x_asp && src->seek_time_position >= 0)
+  {
+    gchar seek_time[64];
+    gint rc = 0;
+    rc = g_snprintf(seek_time, 64,  "%"G_GINT64_FORMAT, src->seek_time_position);
+    if (rc > 0)
+    {
+      soup_message_headers_append (src->msg->request_headers,
+      "X-ASP-SEEK-TIME", seek_time);
+    }
+    src->seek_time_position = (gint64)-1;
+  }
+#endif
+
 #ifdef SEEK_CHANGES
   //gst_soup_http_src_add_range_header (src, src->request_position);
   if(src->range_size > 0)
     soup_message_headers_set_range(src->msg->request_headers, src->request_position, (src->request_position+src->range_size-1));
   else {
-    gst_soup_http_src_add_range_header (src, src->request_position);
+#ifdef GST_EXT_SOUP_MODIFICATION
+    gchar *dash_mediaRange = NULL;
+    dash_mediaRange = strstr (src->location, "range=");
+      if (dash_mediaRange)
+        gst_soup_http_src_add_range_header (src, src->request_position,dash_mediaRange);
+      else
+        gst_soup_http_src_add_range_header (src, src->request_position,NULL);
+#else
+        gst_soup_http_src_add_range_header (src, src->request_position);
+#endif
     gst_soup_http_src_add_extra_headers (src);
     GST_DEBUG_OBJECT (src, "request headers:");
     soup_message_headers_foreach (src->msg->request_headers,gst_soup_http_src_headers_foreach, src);
   }
 #else
+
+#ifdef GST_EXT_SOUP_MODIFICATION
+  gst_soup_http_src_add_range_header (src, src->request_position,NULL);
+#else
   gst_soup_http_src_add_range_header (src, src->request_position);
+#endif
 
   gst_soup_http_src_add_extra_headers (src);
 
@@ -1317,7 +1819,11 @@ gst_soup_http_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
       return GST_FLOW_UNEXPECTED;
     } else if (src->session_io_status ==
         GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_IDLE) {
+      #ifdef GST_EXT_SOUP_MODIFICATION
+      gst_soup_http_src_add_range_header (src, src->request_position,NULL);
+         #else
       gst_soup_http_src_add_range_header (src, src->request_position);
+         #endif
     } else {
       GST_DEBUG_OBJECT (src, "Seek from position %" G_GUINT64_FORMAT
           " to %" G_GUINT64_FORMAT ": requeueing connection request",
@@ -1356,7 +1862,10 @@ gst_soup_http_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
       break;
     }
     if (src->retry) {
-      GST_DEBUG_OBJECT (src, "Reconnecting");
+      GST_WARNING_OBJECT (src, "Reconnecting");
+#ifdef GST_EXT_SOUP_MODIFICATION
+      g_usleep (1000000);
+#endif
       if (!gst_soup_http_src_build_message (src))
         return GST_FLOW_ERROR;
       src->retry = FALSE;
@@ -1395,9 +1904,38 @@ static gboolean
 gst_soup_http_src_start (GstBaseSrc * bsrc)
 {
   GstSoupHTTPSrc *src = GST_SOUP_HTTP_SRC (bsrc);
+#ifdef GST_EXT_SOUP_MODIFICATION
+  char **array = NULL;
+  SoupURI *base_uri;
+#endif
 
   GST_DEBUG_OBJECT (src, "start(\"%s\")", src->location);
 
+#ifdef GST_EXT_SOUP_MODIFICATION
+/* For videohub DRM dash uri which has custom data */
+  gchar *has_custom_data = strstr(src->location,"[]<>");
+  gchar *has_mpd= strstr(src->location,".mpd");
+
+  if (src->videohub_dash_uri){
+    g_free(src->videohub_dash_uri);
+    src->videohub_dash_uri = NULL;
+  }
+
+  if ( has_custom_data !=NULL && has_mpd !=NULL ) {
+    GST_DEBUG_OBJECT(src,"The uri has custom data..");
+
+    /* keep uri which includes custom data for forwarding it to qtdemux */
+    src->videohub_dash_uri = g_strdup(src->location);
+
+    /* make normal uri without custom data for requesting to server */
+    gchar *videohub_dash_normal_uri = NULL;
+    videohub_dash_normal_uri = strtok(src->location,"[]<>");
+    src->location = NULL;
+    src->location = videohub_dash_normal_uri;
+    GST_DEBUG_OBJECT (src, "Videohub normal uri(\"%s\")", src->location);
+  }
+#endif
+
   if (!src->location) {
     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("No URL set.")),
         ("Missing location property"));
@@ -1414,11 +1952,26 @@ gst_soup_http_src_start (GstBaseSrc * bsrc)
     return FALSE;
   }
 
+#ifdef GST_EXT_SOUP_MODIFICATION
+  if (src->timeout == 0)
+    src->session_timeout = 0;
+  else if ((src->timeout > 0) && (src->timeout < DEFAULT_SESSION_TIMEOUT))
+    src->session_timeout = src->timeout;
+
+  GST_DEBUG_OBJECT (src, "session timeout: %d", src->session_timeout);
+
+  src->duration = GST_CLOCK_TIME_NONE;
+#endif
+
   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,
+#ifdef GST_EXT_SOUP_MODIFICATION
+        SOUP_SESSION_TIMEOUT, src->session_timeout,
+#else
         SOUP_SESSION_TIMEOUT, src->timeout,
+#endif
 #ifdef HAVE_LIBSOUP_GNOME
         SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_GNOME,
 #endif
@@ -1427,7 +1980,11 @@ gst_soup_http_src_start (GstBaseSrc * bsrc)
     src->session =
         soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
         src->context, SOUP_SESSION_PROXY_URI, src->proxy,
+#ifdef GST_EXT_SOUP_MODIFICATION
+        SOUP_SESSION_TIMEOUT, src->session_timeout,
+#else
         SOUP_SESSION_TIMEOUT, src->timeout,
+#endif
         SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
   }
 
@@ -1438,8 +1995,38 @@ gst_soup_http_src_start (GstBaseSrc * bsrc)
   }
 
 #ifdef GST_EXT_SOUP_MODIFICATION
+  SoupCookie *soup_cookie = NULL;
+  GSList *c_list = NULL;
+
   soup_session_add_feature_by_type (src->session, SOUP_TYPE_COOKIE_JAR);
   src->cookie_jar = SOUP_COOKIE_JAR (soup_session_get_feature (src->session, SOUP_TYPE_COOKIE_JAR));
+  if ((array = src->cookies) != NULL) {
+    base_uri = soup_uri_new (src->location);
+    while (*array != NULL) {
+      soup_cookie = soup_cookie_parse (*array++, base_uri);
+      if (soup_cookie != NULL) {
+        GST_INFO_OBJECT (src, "adding cookies..");
+        soup_cookie_jar_add_cookie (src->cookie_jar, soup_cookie);
+      }
+    }
+    soup_uri_free (base_uri);
+  }
+
+  /* check if temporal cookie store exist. add them to jar */
+  if ( src->cookie_list ) {
+    for ( c_list = src->cookie_list; c_list; c_list = c_list->next) {
+      soup_cookie = (SoupCookie *)c_list->data;
+      if ( soup_cookie ) {
+        soup_cookie_jar_add_cookie (src->cookie_jar, soup_cookie);
+        c_list->data = NULL;
+        GST_INFO_OBJECT (src, "adding cookies..");
+      }
+    }
+    /* freeing list since all cookies are stolen by jar */
+    g_slist_free(src->cookie_list);
+    src->cookie_list = NULL;
+  }
+
 #endif
 
   g_signal_connect (src->session, "authenticate",
@@ -1541,6 +2128,11 @@ gst_soup_http_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
 #endif
   if (src->read_position == segment->start) {
     GST_DEBUG_OBJECT (src, "Seeking to current read position");
+
+#ifdef SEEK_CHANGES
+  if (src->request_position >= src->file_size)
+    src->request_position = segment->start;
+#endif
     return TRUE;
   }
 
@@ -1575,9 +2167,92 @@ gst_soup_http_src_query (GstBaseSrc * bsrc, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_URI:
+#ifdef GST_EXT_SOUP_MODIFICATION
+    if(src->videohub_dash_uri)
+      gst_query_set_uri (query, src->videohub_dash_uri);
+    else
+#endif
       gst_query_set_uri (query, src->location);
       ret = TRUE;
       break;
+#ifdef GST_EXT_SOUP_MODIFICATION
+    case GST_QUERY_CUSTOM: {
+        GstStructure *s;
+        s = gst_query_get_structure (query);
+        if (gst_structure_has_name (s, "HTTPCookies")) {
+          GSList *cookie_list, *c;
+          gchar **cookies, **array;
+          GValue value = { 0, { { 0 } } };
+
+          g_value_init (&value, G_TYPE_STRV);
+          cookies = NULL;
+          if ((cookie_list = soup_cookie_jar_all_cookies (src->cookie_jar)) != NULL) {
+            cookies = g_new0 (gchar *, g_slist_length(cookie_list) + 1);
+            array = cookies;
+            for (c = cookie_list; c; c = c->next) {
+              *array++ = soup_cookie_to_set_cookie_header ((SoupCookie *)(c->data));
+            }
+            soup_cookies_free (cookie_list);
+          }
+          g_value_set_boxed (&value, cookies);
+
+          GST_INFO_OBJECT (src, "Received supported custom query");
+          gst_structure_set_value (s, "cookies", &value);
+          ret = TRUE;
+        }
+#ifdef USE_SAMSUNG_LINK
+        else if (gst_structure_has_name (s, "X-ASP")){
+          GST_INFO_OBJECT (src, "Received X-ASP custom query, X-ASP is %d", src->is_x_asp);
+          GValue value = { 0, };
+          g_value_init (&value, G_TYPE_BOOLEAN);
+          g_value_set_boolean (&value, src->is_x_asp);
+          gst_structure_set_value (s, "x-asp", &value);
+          ret = TRUE;
+        }
+#endif
+        else if (gst_structure_has_name(s, "HTTPUserAgent")) {
+          GValue value = { 0, };
+          g_value_init (&value, G_TYPE_STRING);
+          g_value_set_string (&value, src->user_agent);
+          GST_INFO_OBJECT (src, "Received HTTPUserAgent custom query");
+          gst_structure_set_value (s, "user-agent", &value);
+          ret = TRUE;
+        }
+        else {
+          GST_WARNING_OBJECT (src,"Unsupported query");
+          ret = FALSE;
+        }
+      }
+      break;
+    case GST_QUERY_DURATION: {
+
+      GstFormat format;
+
+      gst_query_parse_duration (query, &format, NULL);
+
+      if (format == GST_FORMAT_TIME) {
+        if (src->duration != GST_CLOCK_TIME_NONE) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, src->duration);
+          GST_DEBUG_OBJECT (src,"query duration time is %" GST_TIME_FORMAT,
+          GST_TIME_ARGS(src->duration));
+          ret = TRUE;
+        } else {
+          GST_WARNING_OBJECT (src,"Unsupported query");
+          ret = FALSE;
+        }
+
+      } else if (format == GST_FORMAT_BYTES) {
+        gst_query_set_duration (query, GST_FORMAT_BYTES, src->file_size);
+        GST_DEBUG_OBJECT (src,"query duration bytes is %" G_GUINT64_FORMAT, src->file_size);
+        ret = TRUE;
+      } else {
+        GST_WARNING_OBJECT (src,"Unsupported query");
+        ret = FALSE;
+      }
+    }
+      break;
+#endif
+
     default:
       ret = FALSE;
       break;
@@ -1589,6 +2264,43 @@ gst_soup_http_src_query (GstBaseSrc * bsrc, GstQuery * query)
   return ret;
 }
 
+#ifdef USE_SAMSUNG_LINK
+static gboolean
+gst_soup_http_src_event (GstBaseSrc * bsrc, GstEvent *event)
+{
+  GstSoupHTTPSrc *src = GST_SOUP_HTTP_SRC (bsrc);
+  gboolean ret;
+
+  GST_DEBUG_OBJECT (src, "handling %s event", GST_EVENT_TYPE_NAME (event));
+
+  switch (GST_EVENT_TYPE (event)){
+    case GST_EVENT_SEEK:
+      if (src->is_x_asp) {
+        gdouble rate;
+        GstFormat format;
+        GstSeekFlags flags;
+        GstSeekType start_type, stop_type;
+        gint64 start, stop;
+
+        gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+                                     &stop_type, &stop);
+        if (format == GST_FORMAT_TIME) {
+          src->seek_time_position = start / G_GINT64_CONSTANT (1000000);
+          GST_DEBUG_OBJECT (src,"seek position time is %" G_GINT64_FORMAT"(ms)", src->seek_time_position);
+        }
+      }
+      ret = GST_BASE_SRC_CLASS (parent_class)->event (bsrc, event);
+      break;
+    default:
+      ret = GST_BASE_SRC_CLASS (parent_class)->event (bsrc, event);
+      break;
+  }
+
+  return ret;
+}
+#endif
+
+
 static gboolean
 gst_soup_http_src_set_location (GstSoupHTTPSrc * src, const gchar * uri)
 {
old mode 100644 (file)
new mode 100755 (executable)
index 95bbc0c..14f1044
@@ -9,7 +9,7 @@
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more 
+ * Library General Public License for more
  */
 
 #ifndef __GST_SOUP_HTTP_SRC_H__
@@ -34,9 +34,13 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SOUP_HTTP_SRC))
 #define GST_IS_SOUP_HTTP_SRC_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SOUP_HTTP_SRC))
+#define        USE_SAMSUNG_LINK
 
 typedef struct _GstSoupHTTPSrc GstSoupHTTPSrc;
 typedef struct _GstSoupHTTPSrcClass GstSoupHTTPSrcClass;
+#ifdef GST_EXT_SOUP_MODIFICATION
+typedef struct _GstSoupHTTPSrcRequestRange GstSoupHTTPSrcRequestRange;
+#endif
 
 typedef enum {
   GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_IDLE,
@@ -68,6 +72,10 @@ struct _GstSoupHTTPSrc {
   gboolean interrupted;        /* Signal unlock(). */
   gboolean retry;              /* Should attempt to reconnect. */
 
+#ifdef GST_EXT_SOUP_MODIFICATION
+  guint op_code;               /* DLNA server seek setting */
+#endif
+
   gboolean have_size;          /* Received and parsed Content-Length
                                   header. */
   guint64 file_size;
@@ -78,6 +86,11 @@ struct _GstSoupHTTPSrc {
                                   Range. */
   guint64 request_position;    /* Seek to this position. */
   gboolean seeked;
+  gboolean have_body;          /* Indicates if it has just been signaled the
+                                * end of the message body. This is used to
+                                * decide if an out of range request should be
+                                * handled as an error or EOS when the content
+                                * size is unknown */
 
   /* Shoutcast/icecast metadata extraction handling. */
   gboolean iradio_mode;
@@ -89,10 +102,27 @@ struct _GstSoupHTTPSrc {
 
   GstStructure *extra_headers;
 
-  guint timeout;
 #ifdef GST_EXT_SOUP_MODIFICATION
   SoupCookieJar *cookie_jar;
+  guint64 content_len;
+  gboolean is_ahs_streaming; /* adaptive HTTP Streaming : HLS/SS/DASH */
+  gchar *videohub_dash_uri;/* includes custom data */
+  GSList *cookie_list;
+
+  gint timeout;
+  guint session_timeout;
+  GstClockTime retry_timestamp;
+
+  GstClockTime duration;
+#else
+  guint timeout;
 #endif
+
+#ifdef USE_SAMSUNG_LINK
+  gint64 seek_time_position;
+  gboolean is_x_asp;
+#endif
+
 };
 
 struct _GstSoupHTTPSrcClass {
diff --git a/gst-plugins-good.manifest b/gst-plugins-good.manifest
new file mode 100755 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
index 2dfc0eb..8ed8950 100644 (file)
@@ -27,7 +27,7 @@ BuildRequires:  gcc-c++
 @USE_ESD_TRUE@Provides:                gstreamer-audiosink
 @USE_FLAC_TRUE@BuildRequires: flac-devel >= 1.0.3
 @USE_GCONF_TRUE@BuildRequires:         GConf2-devel
-@USE_JPEG_TRUE@BuildRequires: libjpeg-devel
+@USE_JPEG_TRUE@BuildRequires: libjpeg-turbo-devel
 @USE_LIBCACA_TRUE@BuildRequires: libcaca-devel
 @USE_LIBDV_TRUE@BuildRequires: libdv-devel
 @USE_LIBPNG_TRUE@BuildRequires: libpng-devel >= 1.2.0
index d8c0995..cb984da 100644 (file)
@@ -66,6 +66,10 @@ GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
 #define ADIF_MAX_SIZE 40        /* Should be enough */
 #define ADTS_MAX_SIZE 10        /* Should be enough */
 
+#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more accurate duration */
+#define AAC_MAX_ESTIMATE_DURATION_BUF (1024 * 1024) /* use first 1 Mbyte */
+#define AAC_SAMPLE_PER_FRAME 1024
+#endif
 
 #define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
 
@@ -82,6 +86,15 @@ static gboolean gst_aac_parse_check_valid_frame (GstBaseParse * parse,
 static GstFlowReturn gst_aac_parse_parse_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame);
 
+#ifdef GST_EXT_AACPARSER_MODIFICATION /* make full aac(adts) index table when seek */
+  static guint gst_aac_parse_adts_get_fast_frame_len (const guint8 * data);
+  static gboolean gst_aac_parse_src_eventfunc(GstBaseParse * parse, GstEvent * event); // evil
+  static gboolean gst_aac_parse_adts_src_eventfunc (GstBaseParse * parse, GstEvent * event);
+  static gboolean gst_aac_parse_adif_src_eventfunc (GstBaseParse * parse, GstEvent * event); // evil 
+  #define AAC_MAX_PULL_RANGE_BUF  (1 * 1024 * 1024)   /* 1 MByte */
+  #define AAC_LARGE_FILE_SIZE             (2 * 1024 * 1024)    /* 2 MByte */
+#endif
+
 #define _do_init(bla) \
     GST_DEBUG_CATEGORY_INIT (aacparse_debug, "aacparse", 0, \
     "AAC audio stream parser");
@@ -139,6 +152,10 @@ gst_aac_parse_class_init (GstAacParseClass * klass)
   parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_parse_frame);
   parse_class->check_valid_frame =
       GST_DEBUG_FUNCPTR (gst_aac_parse_check_valid_frame);
+
+#ifdef GST_EXT_AACPARSER_MODIFICATION /* make full aac(adts) index table when seek */
+  parse_class->src_event = GST_DEBUG_FUNCPTR (gst_aac_parse_src_eventfunc);
+#endif
 }
 
 
@@ -152,6 +169,9 @@ static void
 gst_aac_parse_init (GstAacParse * aacparse, GstAacParseClass * klass)
 {
   GST_DEBUG ("initialized");
+#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
+  aacparse->first_frame = TRUE;
+#endif
 }
 
 
@@ -356,6 +376,7 @@ gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
     if ((data[*framesize] == 0xff) && ((data[*framesize + 1] & 0xf6) == 0xf0)) {
       guint nextlen = gst_aac_parse_adts_get_frame_len (data + (*framesize));
 
+      aacparse->frame_byte = ((*framesize) + nextlen) / 2;
       GST_LOG ("ADTS frame found, len: %d bytes", *framesize);
       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
           nextlen + ADTS_MAX_SIZE);
@@ -384,7 +405,206 @@ gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
   if (object)
     *object = (data[2] & 0xc0) >> 6;
 }
+static inline guint aac_get_bits(guint8* data, guint* bit_pos, guint num)
+{
+    guint ret_val;
+    guint byte_pos = (*bit_pos) >> 3;
+    guint cur_bit = (*bit_pos) & 0x7;
+    guint bit_buffer = ((guint)(data[byte_pos]) << 8) | data[byte_pos + 1];
+    guint r_shift_val = 16 + cur_bit;
+    guint l_shift_val = 32 - num;
+
+    (*bit_pos) = (*bit_pos) + num;
+    ret_val = ((bit_buffer << r_shift_val) >> l_shift_val);
+
+    GST_INFO("curr byte %i, bit %i :", byte_pos, cur_bit);
+    GST_INFO("getbits num %i, ret %i\n", num, ret_val);
+    return ret_val;
+}
+
+static inline void aac_skip_bits(guint* bit_pos, guint num)
+{
+    guint byte_pos = (*bit_pos) >> 3;
+    guint cur_bit = (*bit_pos) & 0x7;
+
+    GST_INFO("curr byte %i, bit %i :", byte_pos, cur_bit);
+    GST_INFO("skipbits num %i\n", num);
+    (*bit_pos) = (*bit_pos) + num;
+}
+
+static inline void aac_byte_alignment(guint* bit_pos)
+{
+    guint byte_pos = (*bit_pos) >> 3;
+    guint cur_bit = (*bit_pos) & 0x7;
+
+    GST_INFO("curr byte %i, bit %i :", byte_pos, cur_bit);
+    GST_INFO("byte_alignment\n");
+    (*bit_pos) = (*bit_pos) + 7;
+    (*bit_pos) = (*bit_pos) & 0xFFffFFf8;
+}
+
+static guint skip_aac_read_adif_header(guint8* data)
+{
+    guint val, num_pce;
+    guint bit_pos = 0;
+    guint read_bytes;
+
+    /* adif_id; 32 bslbf */
+    aac_skip_bits(&bit_pos, 32);
+
+    /* copyright_id_present; 1 bslbf */
+    val = aac_get_bits(data, &bit_pos, 1);
+    if(val)
+    {
+        /* copyright_id; 72 bslbf */
+        aac_skip_bits(&bit_pos, 72);
+    }
+
+    /* original_copy; 1 bslbf */
+    aac_skip_bits(&bit_pos, 1);
 
+    /* home; 1 bslbf */
+    aac_skip_bits(&bit_pos, 1);
+
+    /* bitstream_type; 1 bslbf */
+    val = aac_get_bits(data, &bit_pos, 1);
+
+    /* bitrate; 23 uimsbf */
+    aac_get_bits(data, &bit_pos, 23);
+
+    /* num_program_config_elements; 4 bslbf */
+    num_pce = aac_get_bits(data, &bit_pos, 4) + 1;
+
+    if(val == 0)
+    {
+        /* adif_buffer_fullness; 20 uimsbf */
+        aac_skip_bits(&bit_pos, 20);
+    }
+
+    for(; num_pce; num_pce--)
+    {
+        gint sr_index;
+        guint num_fce, num_sce, num_bce, num_lce, num_ade, num_vce, i;
+
+        /* element_instance_tag; 4 uimsbf */
+        aac_skip_bits(&bit_pos, 4);
+
+        /* profile; 2 uimsbf */
+        aac_skip_bits(&bit_pos, 2);
+
+        /* sampling_frequency_index; 4 uimsbf */
+        sr_index = aac_get_bits(data, &bit_pos, 4);
+
+        /* num_front_channel_elements; 4 uimsbf */
+        num_fce = aac_get_bits(data, &bit_pos, 4);
+
+        /* num_side_channel_elements; 4 uimsbf */
+        num_sce = aac_get_bits(data, &bit_pos, 4);
+
+        /* num_back_channel_elements; 4 uimsbf */
+        num_bce = aac_get_bits(data, &bit_pos, 4);
+
+        /* num_lfe_channel_elements; 2 uimsbf */
+        num_lce = aac_get_bits(data, &bit_pos, 2);
+
+        /* num_assoc_data_elements; 3 uimsbf */
+        num_ade = aac_get_bits(data, &bit_pos, 3);
+
+        /* num_valid_cc_elements; 4 uimsbf */
+        num_vce = aac_get_bits(data, &bit_pos, 4);
+
+        /* mono_mixdown_present; 1 uimsbf */
+        val = aac_get_bits(data, &bit_pos, 1);
+        if(val == 1)
+        {
+            /* mono_mixdown_element_number; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        /* stereo_mixdown_present; 1 uimsbf */
+        val = aac_get_bits(data, &bit_pos, 1);
+        if(val == 1)
+        {
+            /* stereo_mixdown_element_number; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        /* matrix_mixdown_idx_present; 1 uimsbf */
+        val = aac_get_bits(data, &bit_pos, 1);
+        if(val == 1)
+        {
+            /* matrix_mixdown_idx ; 2 uimsbf */
+            aac_skip_bits(&bit_pos, 2);
+
+            /* pseudo_surround_enable; 1 uimsbf */
+            aac_skip_bits(&bit_pos, 1);
+        }
+
+        for(i = 0; i < num_fce; i++)
+        {
+            /* front_element_is_cpe[i]; 1 bslbf */
+            aac_skip_bits(&bit_pos, 1);
+
+            /* front_element_tag_select[i]; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        for(i = 0; i < num_sce; i++)
+        {
+            /* side_element_is_cpe[i]; 1 bslbf */
+            aac_skip_bits(&bit_pos, 1);
+
+            /* side_element_tag_select[i]; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        for(i = 0; i < num_bce; i++)
+        {
+            /* back_element_is_cpe[i]; 1 bslbf */
+            aac_skip_bits(&bit_pos, 1);
+
+            /* back_element_tag_select[i]; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        for(i = 0; i < num_lce; i++)
+        {
+            /* lfe_element_tag_select[i]; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        for(i = 0; i < num_ade; i++)
+        {
+            /* assoc_data_element_tag_select[i]; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        for(i = 0; i < num_vce; i++)
+        {
+            /* cc_element_is_ind_sw[i]; 1 uimsbf */
+            aac_skip_bits(&bit_pos, 1);
+
+            /* valid_cc_element_tag_select[i]; 4 uimsbf */
+            aac_skip_bits(&bit_pos, 4);
+        }
+
+        aac_byte_alignment(&bit_pos);
+
+        /* comment_field_bytes; 8 uimsbf */
+        val = aac_get_bits(data, &bit_pos, 8);
+        for(i = 0; i < val; i++)
+        {
+            /* comment_field_data[i]; 8 uimsbf */
+            aac_skip_bits(&bit_pos, 8);
+        }
+    }
+
+    /* aac_byte_alignment(&bit_pos); */
+    read_bytes = bit_pos >> 3;
+
+    GST_DEBUG("bytes_read %i", read_bytes);
+    return read_bytes;
+}
 /**
  * gst_aac_parse_detect_stream:
  * @aacparse: #GstAacParse.
@@ -472,10 +692,11 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     return FALSE;
 
   if (memcmp (data + i, "ADIF", 4) == 0) {
-    const guint8 *adif;
+    const guint8 *adif, *tmp_data;
     int skip_size = 0;
     int bitstream_type;
     int sr_idx;
+   GstBuffer* buffer;
 
     aacparse->header_type = DSPAAC_HEADER_ADIF;
     aacparse->mpegversion = 4;
@@ -487,7 +708,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     if (adif[0] & 0x80)
       skip_size += 9;           /* skip 9 bytes */
 
-    bitstream_type = adif[0 + skip_size] & 0x10;
+    aacparse->bitstream_type =  bitstream_type = adif[0 + skip_size] & 0x10; // Added bitstream_type to the struct.
     aacparse->bitrate =
         ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
         ((unsigned int) adif[1 + skip_size] << 11) |
@@ -541,12 +762,15 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     gst_aac_parse_set_src_caps (aacparse,
         GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
 
-    /* not syncable, not easily seekable (unless we push data from start */
-    gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
-    gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
-    gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
+    gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), TRUE);
+    gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), FALSE);
+    gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), aacparse->bitrate);
 
-    *framesize = avail;
+    aacparse->read_bytes = skip_aac_read_adif_header(data);
+
+    tmp_data = data + aacparse->read_bytes;
+
+    *framesize = ((int)tmp_data [2] << 8) + tmp_data [3] + 4;
     return TRUE;
   }
 
@@ -585,8 +809,7 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
 
   if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
       aacparse->header_type == DSPAAC_HEADER_NONE) {
-    /* There is nothing to parse */
-    *framesize = GST_BUFFER_SIZE (buffer);
+    *framesize = ((int)data [2] << 8) + data [3] + 4;
     ret = TRUE;
 
   } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
@@ -617,6 +840,176 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
 }
 
 
+#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
+/**
+ * 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)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+  gint64 pull_size = 0, file_size = 0, offset = 0, num_frames=0, duration=0;
+  guint profile = 0, 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;
+  GstActivateMode pad_mode = GST_ACTIVATE_NONE;
+  GstAacParse *aacparse;
+
+  aacparse = GST_AAC_PARSE (parse);
+  GST_LOG_OBJECT (aacparse, "gst_aac_parse_estimate_duration enter");
+
+#ifdef GST_EXT_BASEPARSER_MODIFICATION /* check baseparse define these fuction */
+  gst_base_parse_get_pad_mode(parse, &pad_mode);
+  if (pad_mode != GST_ACTIVATE_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);
+#else
+  GST_WARNING_OBJECT (aacparse, "baseparser does not define get private param functions");
+  return FALSE;
+#endif
+
+  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;
+  }
+
+  buf = GST_BUFFER_DATA(buffer);
+
+  for (i = 0; i < pull_size; i ++) {
+    if ((buf[i] == 0xff) && ((buf[i+1] & 0xf6) == 0xf0)) { /* aac sync word */
+      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)");
+          return FALSE;
+      }
+      channel = (buf[i+2] & 0x1) << 2 | (buf[i+3] >> 6);
+
+      GST_INFO_OBJECT (aacparse, "found sync. aac sample_rate=%d, channel=%d", sample_rate, channel);
+
+      /* count number of frames */
+      while (offset < pull_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))
+            return FALSE;
+        } else {
+          offset += frame_size;
+          num_frames++;
+          lost_sync_count=0;
+        }
+      } /* while */
+
+      /* if we can got full file, we can calculate the accurate duration */
+      if (pull_size == file_size) {
+        gfloat duration_for_one_frame = 0;
+        GstClockTime calculated_duration = GST_CLOCK_TIME_NONE;
+
+        GST_INFO_OBJECT (aacparse, "we got total file (%d 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));
+        gst_base_parse_set_duration (parse, GST_FORMAT_TIME, calculated_duration, 0); /* 0 means disable estimate */
+
+      } else {
+        GST_INFO_OBJECT (aacparse, "we got %d 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;
+
+        estimated_bitrate = (gint)((gfloat)(offset * 8) / (gfloat)(duration / 1000));
+        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;
+    }
+  }
+
+  gst_buffer_unref (buffer);
+  return TRUE;
+}
+#endif
+
+
 /**
  * gst_aac_parse_parse_frame:
  * @parse: #GstBaseParse.
@@ -651,11 +1044,10 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   aacparse = GST_AAC_PARSE (parse);
   buffer = frame->buffer;
 
-  if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
-    return ret;
-
-  /* see above */
-  frame->overhead = 7;
+  if(aacparse->header_type == DSPAAC_HEADER_ADTS)
+  {
+         /* see above */
+         frame->overhead = 7;
 
   gst_aac_parse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
       &rate, &channels, NULL, NULL);
@@ -676,6 +1068,44 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
         aacparse->sample_rate, aacparse->frame_samples, 2, 2);
   }
 
+#ifdef GST_EXT_AACPARSER_MODIFICATION /* to get more correct duration */
+  if (aacparse->first_frame == TRUE) {
+    gboolean ret = FALSE;
+    aacparse->first_frame = FALSE;
+
+    ret = gst_aac_parse_estimate_duration(parse);
+    if (!ret) {
+      GST_WARNING_OBJECT (aacparse, "can not estimate total duration");
+      ret = GST_FLOW_NOT_SUPPORTED;
+    }
+  }
+#endif
+  }
+  else if(aacparse->header_type == DSPAAC_HEADER_ADIF /* DSPAAC_HEADER_NOT_PARSED */)
+  {
+    int file_size = 0;
+    float estimated_duration = 0;
+    GstBuffer *buffer = NULL;
+    gint64 total_file_size;
+    const guint8 *data;
+    data = GST_BUFFER_DATA (buffer);
+         if (G_UNLIKELY (rate != aacparse->sample_rate || channels != aacparse->channels)) {
+      GST_DEBUG("ADIF: Sampling Rate = %d", aacparse->sample_rate);
+      if (!gst_aac_parse_set_src_caps (aacparse, GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
+        /* If linking fails, we need to return appropriate error */
+        ret = GST_FLOW_NOT_LINKED;
+      }
+    }
+    gst_base_parse_get_upstream_size(parse, &total_file_size);
+
+    estimated_duration = ((total_file_size * 8) / (float)(aacparse->bitrate * 1000))* GST_SECOND;
+    aacparse->file_size = total_file_size;
+
+    gst_base_parse_set_average_bitrate (parse, aacparse->bitrate);
+    gst_base_parse_set_duration (parse, GST_FORMAT_TIME, estimated_duration * 1000, 0);
+
+    return GST_FLOW_OK;
+  }
   return ret;
 }
 
@@ -748,3 +1178,423 @@ gst_aac_parse_sink_getcaps (GstBaseParse * parse)
 
   return res;
 }
+
+
+#ifdef GST_EXT_AACPARSER_MODIFICATION
+/* 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;
+  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_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
+              (aacparse)), &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;
+}
+
+// evil
+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_ADIF)
+    return gst_aac_parse_adif_src_eventfunc(parse, event);
+  else 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;
+  aacparse = GST_AAC_PARSE (parse);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+      {
+        GstFlowReturn res = GST_FLOW_OK;
+        gint64 base_offset = 0, sync_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;
+        GstActivateMode pad_mode = GST_ACTIVATE_NONE;
+       gboolean large_file_flag = FALSE;
+
+#ifdef GST_EXT_BASEPARSER_MODIFICATION /* check baseparse define these fuction */
+        gst_base_parse_get_pad_mode(parse, &pad_mode);
+        if (pad_mode != GST_ACTIVATE_PULL) {
+          gboolean ret = FALSE;
+          GST_INFO_OBJECT (aacparse, "aac parser is PUSH MODE.");
+          GstPad* srcpad = gst_element_get_pad(parse, "src");
+          /* 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);
+#else
+        GST_ERROR("baseparser does not define get private param functions. can not make index table here.");
+        break;
+#endif
+
+        if (total_file_size > AAC_LARGE_FILE_SIZE ) {
+           large_file_flag = TRUE;
+          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 %d is larger than file size %d", 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;
+
+         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;
+          }
+
+          buf = GST_BUFFER_DATA(buffer);
+          if (buf == NULL) {
+            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;
+            guint32 header;
+
+            /* 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_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;
+
+          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;
+          }
+
+          buf = GST_BUFFER_DATA(buffer);
+          if (buf == NULL) {
+            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;
+            guint32 header;
+
+            /* 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_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;
+}
+
+// evil (ADIF SEEK)
+// Enter this function if the detected format is adif.
+static gboolean
+gst_aac_parse_adif_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+{
+       // Case 1: Constant bit rate => Find the byte boundary using bit rate. Add these values as indices using gst_base_parse_add_index_entry.
+       // Case 2: Variable bit rate => Need to parse the whole file here itself to find frame boundaries.
+       //gboolean handled = FALSE;
+       gint64 cur = 0;
+       int offset = 0;
+       gboolean handled = FALSE;
+       GstBuffer* buffer;
+       const guint8 * data;
+
+       GstAacParse *aacparse;
+       aacparse = GST_AAC_PARSE(parse);
+
+       GST_DEBUG("gst_aac_parse_adif_src_eventfunc enter");
+
+       aacparse->frame_duration = (aacparse->frame_samples* 1000 * 100) / aacparse->sample_rate;  /* duration per frame (msec) */
+
+       switch (GST_EVENT_TYPE (event)) {
+               case GST_EVENT_SEEK:
+               {
+                       int base_offset = aacparse->read_bytes;
+                       int framesize = 0, frame_duration_us = 0, duration = 0, estimated_bitrate, estimated_duration;
+                       GstFlowReturn res = GST_FLOW_OK;
+                       static int framecount = 0;
+                      GstClockTime current_ts = GST_CLOCK_TIME_NONE;
+
+                       GST_LOG_OBJECT(aacparse, "ADIF: Let us Handle seek event");
+
+                       // Parse the event and get the timestamp where to seek.
+                       //gst_event_parse_seek (event, NULL, NULL, NULL, NULL, &cur, NULL, NULL);
+
+                       res = gst_pad_pull_range (parse->sinkpad, base_offset, aacparse->file_size, &buffer);
+
+                       if (res != GST_FLOW_OK) {
+                               GST_ERROR ("gst_pad_pull_range failed!");
+                               break;
+                       }       
+
+                       data = GST_BUFFER_DATA(buffer);
+                      if (data == NULL) {
+                        GST_WARNING("buffer is NULL in make aac seek table's STEP2");
+                        gst_buffer_unref (buffer);
+                        goto aac_seek_null_exit;
+                      }
+                       offset = base_offset;
+                       while(offset <= aacparse->file_size) {
+                               gst_base_parse_add_index_entry (parse, offset, current_ts, TRUE, TRUE); /* force */
+                               framesize = ((int)data[2] << 8) + data[3] + 4;
+                               offset += framesize;
+                               data += framesize;
+                               framecount++;
+                               current_ts += (aacparse->frame_duration * GST_MSECOND) / 100; /* each frame is (frame_duration) ms */
+                       }
+                 gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), aacparse->sample_rate, 1024, 2, 2);
+                       gst_buffer_unref (buffer);
+                       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 GST_EXT_AACPARSER_MODIFICATION
index 1907c2e..21949a3 100644 (file)
@@ -38,6 +38,19 @@ G_BEGIN_DECLS
 #define GST_IS_AAC_PARSE_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AAC_PARSE))
 
+typedef enum
+{
+    DECAAC_RET_SUCCESS           = 0,
+    DECAAC_RET_ERR_NOT_SUFF_MEM  = -2,
+    DECAAC_RET_ERR_NOT_SUPPORT   = -3,
+    DECAAC_RET_ERR_INVALID_ARG   = -4,
+    DECAAC_RET_ERR_INVALID_BS    = -5,
+    DECAAC_RET_ERR_NOT_EXPECTED  = -8,
+    DECAAC_RET_ERR_NOT_SUFF_BS   = -9,
+    DECAAC_RET_ERR_BAD_CRC       = -10,
+    DECAAC_RET_ERR_INVALID_HCB   = -11,
+    DECAAC_RET_ERR_UNKNOWN       = -0xFF,
+} eDECAACRET;
 
 /**
  * GstAacHeaderType:
@@ -77,6 +90,20 @@ struct _GstAacParse {
   gint           mpegversion;
   gint           frame_samples;
 
+#ifdef GST_EXT_AACPARSER_MODIFICATION
+  gboolean   first_frame; /* estimate duration once at the first time */
+
+  guint           hdr_bitrate;    /* added - estimated bitrate (bps) */
+  guint           spf;            /* added - samples per frame = frame_samples */
+  guint           frame_duration; /* added - duration per frame (msec) */
+  guint           frame_per_sec; /* added - frames per second (ea) */
+  guint           bitstream_type; /* added- bitstream type - constant or variable */ //evil
+  guint           adif_header_length;
+  guint           num_program_config_elements;
+  guint           read_bytes;
+  gint64         file_size;
+  guint           frame_byte;
+#endif
   GstAacHeaderType header_type;
 };
 
index 8f6ef94..6c5bb6d 100644 (file)
@@ -69,7 +69,7 @@ static const gint block_size_wb[16] =
 /* AMR has a "hardcoded" framerate of 50fps */
 #define AMR_FRAMES_PER_SECOND 50
 #define AMR_FRAME_DURATION (GST_SECOND/AMR_FRAMES_PER_SECOND)
-#define AMR_MIME_HEADER_SIZE 9
+#define AMR_MIME_HEADER_SIZE 6
 
 static gboolean gst_amr_parse_start (GstBaseParse * parse);
 static gboolean gst_amr_parse_stop (GstBaseParse * parse);
@@ -84,6 +84,11 @@ static gboolean gst_amr_parse_check_valid_frame (GstBaseParse * parse,
 static GstFlowReturn gst_amr_parse_parse_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame);
 
+#ifdef GST_EXT_AMRPARSER_MODIFICATION /* make full amr index table when seek */
+  #define AMR_MAX_PULL_RANGE_BUF (5 * 1024 * 1024) /* 5 mbyte */
+  static gboolean gst_amr_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event);
+#endif
+
 #define _do_init(bla) \
     GST_DEBUG_CATEGORY_INIT (amrparse_debug, "amrparse", 0, \
                              "AMR-NB audio stream parser");
@@ -129,6 +134,10 @@ gst_amr_parse_class_init (GstAmrParseClass * klass)
   parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_amr_parse_parse_frame);
   parse_class->check_valid_frame =
       GST_DEBUG_FUNCPTR (gst_amr_parse_check_valid_frame);
+
+#ifdef GST_EXT_AMRPARSER_MODIFICATION /* make full amr index table when seek */
+  parse_class->src_event = gst_amr_parse_src_eventfunc;
+#endif
 }
 
 
@@ -213,7 +222,11 @@ gst_amr_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
     return FALSE;
   }
 
-  amrparse->need_header = FALSE;
+#ifdef GST_EXT_AMRPARSER_MODIFICATION
+  if (amrparse->pad_mode != GST_ACTIVATE_PULL)
+    amrparse->need_header = FALSE;
+#endif
+
   gst_base_parse_set_frame_rate (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
   gst_amr_parse_set_src_caps (amrparse);
   return TRUE;
@@ -236,17 +249,24 @@ gst_amr_parse_parse_header (GstAmrParse * amrparse,
   GST_DEBUG_OBJECT (amrparse, "Parsing header data");
 
   if (!memcmp (data, "#!AMR-WB\n", 9)) {
-    GST_DEBUG_OBJECT (amrparse, "AMR-WB detected");
+    GST_WARNING_OBJECT (amrparse, "AMR-WB detected");
     amrparse->block_size = block_size_wb;
     amrparse->wide = TRUE;
     *skipsize = amrparse->header = 9;
   } else if (!memcmp (data, "#!AMR\n", 6)) {
-    GST_DEBUG_OBJECT (amrparse, "AMR-NB detected");
+    GST_WARNING_OBJECT (amrparse, "AMR-NB detected");
     amrparse->block_size = block_size_nb;
     amrparse->wide = FALSE;
     *skipsize = amrparse->header = 6;
+#ifdef GST_EXT_AMRPARSER_MODIFICATION
+  } else {
+    GST_ERROR_OBJECT (amrparse, "AMR HEADER don't detected");
+    return FALSE;
+  }
+#else
   } else
     return FALSE;
+#endif
 
   gst_amr_parse_set_src_caps (amrparse);
   return TRUE;
@@ -288,6 +308,15 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
       gst_base_parse_set_frame_rate (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
     } else {
       GST_WARNING ("media doesn't look like a AMR format");
+#ifdef GST_EXT_AMRPARSER_MODIFICATION
+      if (amrparse->pad_mode == GST_ACTIVATE_PULL) {
+        amrparse->need_header = FALSE;
+        *framesize = 0;
+        *skipsize = -2;
+        GST_ERROR_OBJECT (amrparse, "Invalid AMR Header Format");
+        return FALSE;
+      }
+#endif
     }
     /* We return FALSE, so this frame won't get pushed forward. Instead,
        the "skip" value is set, so next time we will receive a valid frame. */
@@ -300,6 +329,31 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
     mode = (data[0] >> 3) & 0x0F;
     fsize = amrparse->block_size[mode] + 1;     /* +1 for the header byte */
 
+#ifdef GST_EXT_AMRPARSER_MODIFICATION
+    if (amrparse->pad_mode == GST_ACTIVATE_PULL) {
+      if (amrparse->sync_check) {
+        GST_DEBUG_OBJECT (amrparse, "AMR Next sync check : fsize (%d)", fsize);
+        amrparse->sync_check = FALSE;
+        if ((fsize > 0) && ((data[fsize] & 0x83) == 0)) {
+          gint next_fsize,next_mode;
+          next_mode = (data[fsize] >> 3) & 0x0F;
+          next_fsize = amrparse->block_size[next_mode] + 1;
+          if(fsize != next_fsize) {
+            *framesize = 0;
+            *skipsize = -2;
+            GST_ERROR_OBJECT (amrparse, "Invalid mode bit");
+            return FALSE;
+          }
+        } else {
+          *framesize = 0;
+          *skipsize = -2;
+          GST_ERROR_OBJECT (amrparse, "Invalid mode bit");
+          return FALSE;
+        }
+      }
+    }
+#endif
+
     /* We recognize this data as a valid frame when:
      *     - We are in sync. There is no need for extra checks then
      *     - We are in EOS. There might not be enough data to check next frame
@@ -370,6 +424,16 @@ gst_amr_parse_start (GstBaseParse * parse)
   GST_DEBUG ("start");
   amrparse->need_header = TRUE;
   amrparse->header = 0;
+#ifdef GST_EXT_AMRPARSER_MODIFICATION
+  amrparse->sync_check = TRUE;
+  gst_base_parse_get_pad_mode(parse, &amrparse->pad_mode);
+  if (amrparse->pad_mode == GST_ACTIVATE_PULL) {
+    GST_WARNING_OBJECT (amrparse, "pad_mode : GST_ACTIVATE_PULL MODE.");
+  } else if (amrparse->pad_mode == GST_ACTIVATE_PUSH) {
+    GST_WARNING_OBJECT (amrparse, " pad_mode : GST_ACTIVATE_PUSH MODE.");
+  } else
+    GST_WARNING_OBJECT (amrparse, "pad_mode : GST_ACTIVATE_NONE MODE.");
+#endif
   return TRUE;
 }
 
@@ -429,3 +493,190 @@ gst_amr_parse_sink_getcaps (GstBaseParse * parse)
 
   return res;
 }
+
+
+#ifdef GST_EXT_AMRPARSER_MODIFICATION /* make full amr index table when seek */
+/**
+ * gst_amr_parse_src_eventfunc:
+ * @parse: #GstBaseParse. #event
+ *
+ * before baseparse handles seek event, make full amr index table.
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_amr_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+{
+  gboolean handled = FALSE;
+  GstAmrParse *amrparse;
+  amrparse = GST_AMR_PARSE (parse);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+      {
+        GstFlowReturn res = GST_FLOW_OK;
+        gint64 base_offset = 0, sync_offset = 0, cur = 0;
+        gint32 frame_count = 1; /* do not add first frame because it is already in index table */
+        gint64 total_file_size = 0, start_offset = 0;
+        GstClockTime current_ts = GST_CLOCK_TIME_NONE;
+        GstActivateMode pad_mode = GST_ACTIVATE_NONE;
+
+#ifdef GST_EXT_BASEPARSER_MODIFICATION /* check baseparse define these fuction */
+        gst_base_parse_get_pad_mode(parse, &pad_mode);
+        if (pad_mode != GST_ACTIVATE_PULL) {
+          GST_INFO_OBJECT (amrparse, "arm parser is not pull mode. amr parser can not make index table.");
+          return FALSE;
+        }
+        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);
+#else
+        GST_WARNING_OBJECT (amrparse, "baseparser does not define get private param functions. can not make index table here.");
+        break;
+#endif
+
+        GST_LOG_OBJECT (amrparse, "gst_amr_parse_src_eventfunc GST_EVENT_SEEK enter");
+
+        if (total_file_size == 0 || start_offset >= total_file_size) {
+          GST_ERROR("last index offset %d is larger than file size %d", start_offset, total_file_size);
+          break;
+        }
+
+        gst_event_parse_seek (event, NULL, NULL, NULL, NULL, &cur, NULL, NULL);
+        if (cur <= current_ts) {
+          GST_INFO_OBJECT (amrparse, "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_OBJECT (amrparse, "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_OBJECT (amrparse, "make AMR 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 */
+
+
+        /************************************/
+        /* STEP 1: MAX_PULL_RANGE_BUF cycle */
+        /************************************/
+        while (total_file_size - base_offset >= AMR_MAX_PULL_RANGE_BUF) {
+          gint64 offset = 0;
+          GstBuffer *buffer = NULL;
+          guint8 *buf = NULL;
+
+         GST_INFO_OBJECT (amrparse, "gst_pad_pull_range %d bytes (from %"G_GINT64_FORMAT") use max size", AMR_MAX_PULL_RANGE_BUF, base_offset);
+          res = gst_pad_pull_range (parse->sinkpad, base_offset,
+              base_offset + AMR_MAX_PULL_RANGE_BUF, &buffer);
+          if (res != GST_FLOW_OK) {
+            GST_ERROR_OBJECT (amrparse, "gst_pad_pull_range failed!");
+            break;
+          }
+
+          buf = GST_BUFFER_DATA(buffer);
+          if (buf == NULL) {
+            GST_WARNING("buffer is NULL in make amr seek table's STEP1");
+            gst_buffer_unref (buffer);
+            goto amr_seek_null_exit;
+          }
+
+          while (offset <= AMR_MAX_PULL_RANGE_BUF) {
+            gint mode = 0,  frame_size = 0;
+
+            if ((buf[offset] & 0x83) == 0) {
+              mode = (buf[offset] >> 3) & 0x0F;
+              frame_size = amrparse->block_size[mode] + 1; /* +1 for the header byte */
+              if (frame_size < 13) {
+                GST_WARNING_OBJECT (amrparse, "frame_size is Invalid (%d) - seek event END at offset %"G_GINT64_FORMAT"", frame_size, base_offset + offset);
+                break;
+              }
+
+              if (frame_count % 50 == 0) { /* 1 sec == 50 frames. we make idx per sec */
+                gst_base_parse_add_index_entry (parse, base_offset +offset, current_ts, TRUE, TRUE); /* force */
+                GST_DEBUG_OBJECT (amrparse, "Adding  index ts=%"GST_TIME_FORMAT" offset %"G_GINT64_FORMAT,
+                    GST_TIME_ARGS(current_ts), base_offset + offset);
+              }
+
+              current_ts += 20 * 1000 * 1000; /* each frame is 20ms */
+              offset += frame_size;
+              frame_count++;
+            } else {
+              GST_WARNING_OBJECT (amrparse, "we lost sync");
+              offset++;
+            }
+          } /* while */
+        base_offset = base_offset + offset;
+        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;
+
+          GST_INFO_OBJECT (amrparse, "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;
+          }
+
+          buf = GST_BUFFER_DATA(buffer);
+          if (buf == NULL) {
+             GST_WARNING("buffer is NULL in make amr seek table's STEP2");
+             gst_buffer_unref (buffer);
+             goto amr_seek_null_exit;
+           }
+
+          while (base_offset + offset < total_file_size) {
+            gint mode = 0, frame_size = 0;
+
+            if ((buf[offset] & 0x83) == 0) {
+              mode = (buf[offset] >> 3) & 0x0F;
+              frame_size = amrparse->block_size[mode] + 1; /* +1 for the header byte */
+              if (frame_size < 13) {
+                GST_WARNING_OBJECT (amrparse, "frame_size is Invalid (%d) - seek event END at offset %"G_GINT64_FORMAT"", frame_size, base_offset + offset);
+                break;
+              }
+
+              if (frame_count % 50 == 0) { /* 1 sec == 50 frames. we make idx per sec */
+                gst_base_parse_add_index_entry (parse, base_offset +offset, current_ts, TRUE, TRUE); /* force */
+                GST_DEBUG_OBJECT (amrparse, "Adding  index ts=%"GST_TIME_FORMAT" offset %"G_GINT64_FORMAT,
+                    GST_TIME_ARGS(current_ts), base_offset + offset);
+              }
+
+              current_ts += 20 * 1000 * 1000; /* each frame is 20ms */
+              offset += frame_size;
+              frame_count++;
+            } else {
+              GST_WARNING_OBJECT (amrparse, "we lost sync");
+              offset++;
+            }
+          } /* while */
+
+        gst_buffer_unref (buffer);
+        } /* end remain_buf buffer cycle */
+
+        GST_LOG_OBJECT (amrparse, "gst_amr_parse_src_eventfunc GST_EVENT_SEEK leave");
+      }
+     break;
+
+    default:
+      break;
+  }
+
+amr_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
index 86a26e0..f9c6f12 100644 (file)
@@ -63,6 +63,10 @@ struct _GstAmrParse {
   gboolean need_header;
   gint header;
   gboolean wide;
+#ifdef GST_EXT_AMRPARSER_MODIFICATION
+  gboolean sync_check;
+  GstActivateMode pad_mode;
+#endif
 };
 
 /**
old mode 100644 (file)
new mode 100755 (executable)
index 9cfdb98..f85e964
@@ -202,6 +202,8 @@ static gboolean gst_flac_parse_convert (GstBaseParse * parse,
     GstFormat src_format, gint64 src_value, GstFormat dest_format,
     gint64 * dest_value);
 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse);
+static gboolean gst_flac_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event);
+static gboolean gst_flac_parse_do_seek (GstBaseParse * parse, GstPad * pad, GstEvent * event);
 
 GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
     GST_TYPE_BASE_PARSE);
@@ -249,6 +251,7 @@ gst_flac_parse_class_init (GstFlacParseClass * klass)
   baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
   baseparse_class->get_sink_caps =
       GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
+  baseparse_class->src_event = GST_DEBUG_FUNCPTR (gst_flac_parse_src_eventfunc);
 }
 
 static void
@@ -257,6 +260,113 @@ gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
   flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
 }
 
+static gboolean
+gst_flac_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+{
+  GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+  gboolean handled = FALSE;
+
+  GST_LOG_OBJECT (flacparse, "handling %s event", GST_EVENT_TYPE_NAME (event));
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+    {
+      GstPad* srcpad = gst_element_get_pad(parse, "src");
+      handled = gst_flac_parse_do_seek(parse, srcpad, event);
+      gst_object_unref(srcpad);
+      if(!handled)
+      {
+        handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
+      }
+      break;
+    }
+    default:
+      handled = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
+      break;
+  }
+  return handled;
+}
+
+static gboolean
+gst_flac_parse_do_seek (GstBaseParse * parse, GstPad * pad, GstEvent * event)
+{
+  GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+
+  gdouble rate;
+  GstFormat format;
+  GstSeekFlags flags;
+  GstSeekType cur_type, stop_type;
+  gint64 cur, stop;
+  gboolean res = FALSE;
+
+  gint64 total_file_size = 0, start_offset = 0;
+  gint64 duration = 0;
+  gint64 seeked_time = 0;
+
+  gint64 estimate_sample = 0;
+  gint64 estimate_byte = 0;
+  GstClockTime current_ts = GST_CLOCK_TIME_NONE;
+
+
+  gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop);
+
+  if (rate <= 0)
+    goto unsupported_seek;
+
+  cur_type = GST_SEEK_TYPE_SET;
+  stop_type = GST_SEEK_TYPE_NONE;
+  stop = -1;
+  flags |= GST_SEEK_FLAG_FLUSH;
+
+  gst_base_parse_get_upstream_size(parse, &total_file_size);
+  gst_base_parse_get_index_last_ts(parse, &current_ts);
+
+  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));
+    return res;
+  } 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));
+  }
+  duration = flacparse->total_samples / flacparse->samplerate;
+  seeked_time = GST_TIME_AS_SECONDS(cur);
+
+  estimate_byte = (seeked_time * total_file_size) / duration;
+  GST_DEBUG_OBJECT(flacparse, "Initial estimate position %"G_GINT64_FORMAT, estimate_byte);
+  while(1)
+  {
+    GstBuffer* buffer = NULL;
+    const guint8 * data;
+    res = gst_pad_pull_range (parse->sinkpad, estimate_byte, flacparse->max_framesize, &buffer);
+    if (res != GST_FLOW_OK) {
+      GST_ERROR ("gst_pad_pull_range failed!");
+      break;
+    }
+    GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
+    gint off = 0;
+    off = gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000, 0, GST_BUFFER_SIZE (buffer));
+    if (off > 0) {
+      GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
+      estimate_byte += off;
+      gst_base_parse_add_index_entry (parse, estimate_byte, cur, TRUE, TRUE);
+      gst_buffer_unref (buffer);
+      break;
+    } else {
+      GST_DEBUG_OBJECT (flacparse, "Sync code not found");
+      estimate_byte += (GST_BUFFER_SIZE (buffer) - 3);
+      gst_buffer_unref (buffer);
+      continue;
+    }
+  }
+estimate:
+  GST_DEBUG_OBJECT(flacparse, "seeking to offset %"G_GINT64_FORMAT, estimate_byte);
+  return FALSE;
+
+unsupported_seek:
+  {
+    GST_DEBUG_OBJECT (flacparse, "unsupported seek, seek aborted.");
+    return FALSE;
+  }
+}
+
 static void
 gst_flac_parse_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -1254,6 +1364,7 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
     gboolean is_last = ((data[0] & 0x80) == 0x80);
     guint type = (data[0] & 0x7F);
+    gboolean hdr_ok = TRUE;
 
     if (type == 127) {
       GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
@@ -1264,20 +1375,16 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 
     switch (type) {
       case 0:                  /* STREAMINFO */
-        if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
-          return GST_FLOW_ERROR;
+        hdr_ok = gst_flac_parse_handle_streaminfo (flacparse, buffer);
         break;
       case 3:                  /* SEEKTABLE */
-        if (!gst_flac_parse_handle_seektable (flacparse, buffer))
-          return GST_FLOW_ERROR;
+        hdr_ok = gst_flac_parse_handle_seektable (flacparse, buffer);
         break;
       case 4:                  /* VORBIS_COMMENT */
-        if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
-          return GST_FLOW_ERROR;
+        hdr_ok = gst_flac_parse_handle_vorbiscomment (flacparse, buffer);
         break;
       case 6:                  /* PICTURE */
-        if (!gst_flac_parse_handle_picture (flacparse, buffer))
-          return GST_FLOW_ERROR;
+        hdr_ok = gst_flac_parse_handle_picture (flacparse, buffer);
         break;
       case 1:                  /* PADDING */
       case 2:                  /* APPLICATION */
@@ -1286,13 +1393,26 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
         break;
     }
 
-    GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
-    GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
-    GST_BUFFER_OFFSET (buffer) = 0;
-    GST_BUFFER_OFFSET_END (buffer) = 0;
+    if (hdr_ok) {
+      GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
+      GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
+      GST_BUFFER_OFFSET (buffer) = 0;
+      GST_BUFFER_OFFSET_END (buffer) = 0;
 
-    flacparse->headers =
-        g_list_append (flacparse->headers, gst_buffer_ref (buffer));
+      if(type != 6) {
+        flacparse->headers =
+            g_list_append (flacparse->headers, gst_buffer_ref (buffer));
+      }
+    } else {
+      GST_WARNING_OBJECT (flacparse, "failed to parse header of type %u", type);
+
+      /* error out unless we have a STREAMINFO header */
+      if (flacparse->samplerate == 0 || flacparse->bps == 0)
+        return GST_FLOW_ERROR;
+
+      /* .. in which case just stop header parsing and try to find audio */
+      is_last = TRUE;
+    }
 
     if (is_last) {
       if (!gst_flac_parse_handle_headers (flacparse))
index 2381fc3..f25c711 100644 (file)
@@ -70,6 +70,23 @@ GST_DEBUG_CATEGORY_STATIC (mpeg_audio_parse_debug);
 
 #define MIN_FRAME_SIZE       6
 
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+#define ALP_MPEGAUDIOPARSE_BUFFER_SIZE   (32 * 1024)
+#define DEFAULT_CHECK_ALP_MP3DEC FALSE
+#endif
+
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+#define DEFAULT_CHECK_HTTP_SEEK   FALSE
+#endif
+
+/* Property */
+enum
+{
+  PROP_0,
+  PROP_CHECK_ALP_MP3DEC,
+  PROP_CHECK_HTTP_SEEK
+};
+
 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
@@ -87,12 +104,27 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) 1")
     );
 
-static void gst_mpeg_audio_parse_finalize (GObject * object);
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+  /* make full mp3 index table when seek */
+  #define MP3_MAX_PULL_RANGE_BUF    ( 5 * 1024 * 1024)    /*  5 mbyte */
+  #define MP3_LARGE_FILE_SIZE             ( 50 * 1024 * 1024)    /* 50 mbyte */
+  static guint  mp3_type_frame_length_calculation (GstMpegAudioParse *mp3parse, guint32 header);
+  static gboolean gst_mpeg_audio_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event);
+#endif
 
+static void gst_mpeg_audio_parse_finalize (GObject * object);
 static gboolean gst_mpeg_audio_parse_start (GstBaseParse * parse);
 static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse);
 static gboolean gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame, guint * size, gint * skipsize);
+static void gst_mpeg_audio_parse_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_mpeg_audio_parse_get_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+static gboolean gst_mpeg_audio_parse_check_valid_frame_alp (GstBaseParse * parse,
+    GstBaseParseFrame * frame, guint * size, gint * skipsize);
+#endif
 static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame);
 static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
@@ -168,6 +200,25 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
 
   object_class->finalize = gst_mpeg_audio_parse_finalize;
 
+  object_class->set_property = gst_mpeg_audio_parse_set_property;
+  object_class->get_property = gst_mpeg_audio_parse_get_property;
+
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+    g_object_class_install_property (object_class, PROP_CHECK_ALP_MP3DEC,
+           g_param_spec_boolean ("alp-mp3dec", "enable/disable",
+          "enable/disable alp mp3dec",
+          DEFAULT_CHECK_ALP_MP3DEC,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
+
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+    g_object_class_install_property (object_class, PROP_CHECK_HTTP_SEEK,
+           g_param_spec_boolean ("http-pull-mp3dec", "enable/disable",
+          "enable/disable mp3dec http seek pull mode",
+          DEFAULT_CHECK_HTTP_SEEK,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
+
   parse_class->start = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_start);
   parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_stop);
   parse_class->check_valid_frame =
@@ -180,6 +231,11 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
   parse_class->get_sink_caps =
       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_get_sink_caps);
 
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+  /* make full mp3 index table when seek */
+  parse_class->src_event = gst_mpeg_audio_parse_src_eventfunc;
+#endif
+
   /* register tags */
 #define GST_TAG_CRC      "has-crc"
 #define GST_TAG_MODE     "channel-mode"
@@ -222,16 +278,80 @@ gst_mpeg_audio_parse_reset (GstMpegAudioParse * mp3parse)
 
   mp3parse->encoder_delay = 0;
   mp3parse->encoder_padding = 0;
+  mp3parse->encoded_file_size = 0;
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  if (mp3parse->alp_mode_flag) {
+    mp3parse->mp3alp_initialized = 0;
+    mp3parse->mp3alp_frame_1st = 0;
+    mp3parse->mp3alp_frame_count = 0;
+    mp3parse->mp3alp_buffer_count = 0;
+    mp3parse->mp3alp_frame_duration = 0;
+    mp3parse->mp3alp_buffer_duration = 0;
+    mp3parse->mp3alp_frame_duration_float = 0.0;
+    mp3parse->mp3alp_frame_1st_bitrate= 0;
+  }
+#endif
 }
 
 static void
 gst_mpeg_audio_parse_init (GstMpegAudioParse * mp3parse,
     GstMpegAudioParseClass * klass)
 {
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  GST_INFO_OBJECT (klass, "Not Ready : mp3parse->alp_mode_flag (%d)", mp3parse->alp_mode_flag);
+#endif
   gst_mpeg_audio_parse_reset (mp3parse);
 }
 
 static void
+gst_mpeg_audio_parse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (object);
+  GST_INFO_OBJECT (mp3parse, "set_property() START- prop_id(%d)",prop_id);
+  switch (prop_id) {
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+    case PROP_CHECK_ALP_MP3DEC:
+      mp3parse->alp_mp3dec = g_value_get_boolean (value);
+      GST_INFO_OBJECT (mp3parse, "alp_mode_flag(%d)", mp3parse->alp_mp3dec);
+      break;
+#endif
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+    case PROP_CHECK_HTTP_SEEK:
+      mp3parse->http_seek_flag = g_value_get_boolean (value);
+      GST_INFO_OBJECT (mp3parse, "http_seek_flag(%d)", mp3parse->http_seek_flag);
+      break;
+#endif
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_mpeg_audio_parse_get_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (object);
+  GST_INFO_OBJECT (mp3parse, "get_property() START- prop_id(%d)",prop_id);
+  switch (prop_id) {
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+    case PROP_CHECK_ALP_MP3DEC:
+      g_value_set_boolean (value, mp3parse->alp_mp3dec);
+      GST_INFO_OBJECT (mp3parse, "alp_mode_flag(%d)", mp3parse->alp_mp3dec);
+      break;
+#endif
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+    case PROP_CHECK_HTTP_SEEK:
+      g_value_set_boolean (value, mp3parse->http_seek_flag);
+      GST_INFO_OBJECT (mp3parse, "http_seek_flag(%d)", mp3parse->http_seek_flag);
+      break;
+#endif
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 gst_mpeg_audio_parse_finalize (GObject * object)
 {
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -245,8 +365,34 @@ gst_mpeg_audio_parse_start (GstBaseParse * parse)
   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (mp3parse), MIN_FRAME_SIZE);
   GST_DEBUG_OBJECT (parse, "starting");
 
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  mp3parse->alp_mode_flag = mp3parse->alp_mp3dec;
+#endif
+
   gst_mpeg_audio_parse_reset (mp3parse);
 
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  if(mp3parse->alp_mode_flag) {
+    gst_base_parse_set_alp_mode(parse, mp3parse->alp_mode_flag);
+    GST_INFO_OBJECT (parse, "=============================");
+    GST_INFO_OBJECT (parse, "starting - ALP MODE");
+    GST_INFO_OBJECT (parse, "=============================");
+  } else {
+    GST_INFO_OBJECT (parse, "-----------------------------");
+    GST_INFO_OBJECT (parse, "starting - Normal MODE");
+    GST_INFO_OBJECT (parse, "-----------------------------");
+  }
+#else
+  GST_INFO_OBJECT (parse, "-----------------------------");
+  GST_INFO_OBJECT (parse, "starting - Normal MODE / No ALP");
+  GST_INFO_OBJECT (parse, "-----------------------------");
+#endif
+
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+  if (mp3parse->http_seek_flag)
+    GST_INFO_OBJECT (parse, "starting - No Accurate Seek table (in http pull mode)");
+#endif
+
   return TRUE;
 }
 
@@ -256,7 +402,6 @@ gst_mpeg_audio_parse_stop (GstBaseParse * parse)
   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
 
   GST_DEBUG_OBJECT (parse, "stopping");
-
   gst_mpeg_audio_parse_reset (mp3parse);
 
   return TRUE;
@@ -353,6 +498,22 @@ mp3_type_frame_length_from_header (GstMpegAudioParse * mp3parse, guint32 header,
   if (put_crc)
     *put_crc = crc;
 
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  if (mp3parse->alp_mode_flag) {
+    if (layer == 1)
+      mp3parse->spf = 384;
+    else if (layer == 2)
+      mp3parse->spf = 1152;
+    else if (version == 1) {
+      mp3parse->spf = 1152;
+    } else {
+      /* MPEG-2 or "2.5" */
+      mp3parse->spf = 576;
+    }
+     mp3parse->rate = samplerate;
+  }
+#endif
+
   return length;
 }
 
@@ -486,6 +647,148 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
   return TRUE;
 }
 
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+static gboolean
+gst_mpeg_audio_parse_check_valid_frame_alp (GstBaseParse * parse,
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+  GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
+  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+  gint off, bpf;
+  gboolean lost_sync, draining, valid, caps_change;
+  guint32 header;
+  guint bitrate, layer, rate, channels, version, mode, crc;
+
+  guint framecount = 0;
+  gint32 offset = 0;
+  guint8 *data = NULL;
+  gint64 buf_szie;
+
+  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
+    return FALSE;
+
+  gst_base_parse_get_initial_frame(parse, &mp3parse->mp3alp_initialized);   //for NEXT Play, I need initial indicatior
+  if(!mp3parse->mp3alp_initialized) 
+     GST_INFO_OBJECT (parse, "[FILE_OPEN] baseparse ->framecount is 0");
+
+  off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffe00000, 0xffe00000,
+      0, GST_BUFFER_SIZE (buf));
+
+  GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
+
+  /* didn't find anything that looks like a sync word, skip */
+  if (off < 0) {
+    *skipsize = GST_BUFFER_SIZE (buf) - 3;
+    return FALSE;
+  }
+
+  /* possible frame header, but not at offset 0? skip bytes before sync */
+  if (off > 0) {
+    *skipsize = off;
+    return FALSE;
+  }
+
+  data= GST_BUFFER_DATA(buf);
+  *framesize = 0;
+
+  while (offset <= ALP_MPEGAUDIOPARSE_BUFFER_SIZE) {
+    /* make sure the values in the frame header look sane */
+    header = GST_READ_UINT32_BE (data);
+    if (!gst_mpeg_audio_parse_head_check (mp3parse, header)) {
+      buf_szie = GST_BUFFER_SIZE (buf) + GST_BUFFER_OFFSET (buf);
+      if (mp3parse->encoded_file_size > 0) {
+        if (buf_szie >= mp3parse->encoded_file_size) {
+          GST_INFO_OBJECT(parse, "BUF SIZE(%" G_GUINT64_FORMAT ") >= TOTAL(%" G_GUINT64_FORMAT ") ", buf_szie, mp3parse->encoded_file_size);
+          break; 
+        }
+      } else {
+        GST_WARNING_OBJECT(parse, "filesize is under zero");
+      }
+
+      *skipsize = 1;
+      return FALSE;
+    }
+
+    bpf = mp3_type_frame_length_from_header (mp3parse, header, 
+             &version, &layer, &channels, &bitrate, &rate, &mode, &crc);
+    g_assert (bpf != 0);
+
+    if (!mp3parse->mp3alp_initialized) {
+       if (channels != mp3parse->channels || rate != mp3parse->rate ||
+              layer != mp3parse->layer || version != mp3parse->version)
+        caps_change = TRUE;
+      else
+        caps_change = FALSE;
+
+      lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
+      draining = GST_BASE_PARSE_DRAINING (parse);
+
+      if (!draining && (lost_sync || caps_change)) {
+         if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, draining, &valid)) {
+           /* not enough data */
+          gst_base_parse_set_min_frame_size (parse, valid);
+          *skipsize = 0;
+          return FALSE;
+        } else {
+           if (!valid) {
+             *skipsize = off + 2;
+             return FALSE;
+           }
+        }
+      } else if (draining && lost_sync && caps_change && mp3parse->rate > 0) {
+        /* avoid caps jitter that we can't be sure of */
+        *skipsize = off + 2;
+        return FALSE;
+      }
+
+      mp3parse->mp3alp_frame_1st = 1;
+      if (mp3parse->rate > 0) {
+        mp3parse->mp3alp_frame_duration_float = (gdouble)(mp3parse->spf * 1000 * 1000 ) / (gdouble)mp3parse->rate;
+      }
+      mp3parse->mp3alp_frame_duration = (gint64)(mp3parse->mp3alp_frame_duration_float  * 1000);                         /* duration per frame (msec) 1152/44.1=26122448  */
+
+      gst_base_parse_set_1st_frame(parse, mp3parse->mp3alp_frame_1st, bpf);
+      GST_INFO_OBJECT (parse, "[ONE_TIME] alp_mode_flag(%d) frame_1st(%d) frame_duration  (%"GST_TIME_FORMAT")", 
+                                         mp3parse->alp_mode_flag, mp3parse->mp3alp_frame_1st, GST_TIME_ARGS(mp3parse->mp3alp_frame_duration));
+      mp3parse->mp3alp_initialized = TRUE;   /*only 1st time */
+    }
+
+    if ((bpf > 0) && (bpf < (ALP_MPEGAUDIOPARSE_BUFFER_SIZE - offset))) {
+      offset += bpf;
+      data += bpf;
+      framecount++;
+      if (mp3parse->mp3alp_frame_1st) {
+        if ((framecount == 10) && (mp3parse->mp3alp_frame_duration > 0)) {
+          mp3parse->mp3alp_frame_1st_bitrate = (8 * offset * GST_SECOND) /(mp3parse->mp3alp_frame_duration * 10);
+          GST_INFO_OBJECT (parse, "[TEST] mp3alp_frame_1st_bitrate (%d)", mp3parse->mp3alp_frame_1st_bitrate);
+        }
+      }
+    } else if (bpf >= (ALP_MPEGAUDIOPARSE_BUFFER_SIZE - offset)) {
+      break;
+    } else {
+      GST_WARNING_OBJECT(parse, "[4F] we lost sync");
+      data++;
+      offset++;
+    }
+  }
+
+  mp3parse->mp3alp_frame_1st = 0;
+  mp3parse->mp3alp_frame_count = framecount;
+  mp3parse->mp3alp_buffer_count++; 
+  mp3parse->mp3alp_buffer_duration = mp3parse->mp3alp_frame_duration * framecount;
+  gst_base_parse_set_frame_info(parse, mp3parse->mp3alp_frame_count, mp3parse->mp3alp_frame_duration, mp3parse->mp3alp_frame_1st_bitrate);
+  gst_base_parse_set_buffer_info(parse, mp3parse->mp3alp_buffer_count, mp3parse->mp3alp_buffer_duration);
+  gst_base_parse_set_buffer_size(parse, offset);
+
+  /* restore default minimum */
+  gst_base_parse_set_min_frame_size (parse, MIN_FRAME_SIZE);
+
+  *framesize = offset;
+  return TRUE;
+}
+#endif
+
 static gboolean
 gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
@@ -498,6 +801,13 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
   guint32 header;
   guint bitrate, layer, rate, channels, version, mode, crc;
 
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  if (mp3parse->alp_mode_flag) {
+    gboolean ret;
+    ret = gst_mpeg_audio_parse_check_valid_frame_alp(parse, frame, framesize, skipsize);
+    return ret;
+  }
+#endif
   if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
     return FALSE;
 
@@ -563,6 +873,7 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
   gst_base_parse_set_min_frame_size (parse, MIN_FRAME_SIZE);
 
   *framesize = bpf;
+  mp3parse->frame_byte = bpf;
   return TRUE;
 }
 
@@ -621,6 +932,8 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
   if (!gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
               (mp3parse)), &fmt, &upstream_total_bytes))
     upstream_total_bytes = 0;
+    GST_INFO_OBJECT (mp3parse, "gst_pad_query_peer_duration -upstream_total_bytes (%"G_GUINT64_FORMAT")", upstream_total_bytes);
+    mp3parse->encoded_file_size = upstream_total_bytes;
 
   if (read_id_xing == xing_id || read_id_xing == info_id) {
     guint32 xing_flags;
@@ -975,12 +1288,27 @@ gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
   guint bitrate, layer, rate, channels, version, mode, crc;
 
   g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR);
+  if(GST_BUFFER_SIZE (buf) <  4) {
+    GST_INFO_OBJECT (parse, "_parse_parse_frame() :  buffer->size(%d)",GST_BUFFER_SIZE (buf));
+  }
 
   if (!mp3_type_frame_length_from_header (mp3parse,
           GST_READ_UINT32_BE (GST_BUFFER_DATA (buf)),
           &version, &layer, &channels, &bitrate, &rate, &mode, &crc))
     goto broken_header;
 
+#ifdef GST_EXT_MPEGAUDIO_MODIFICATION
+  /* For Layer-2 there are some combinations of bitrate and mode which are not allowed. */
+  if (version == 1 && layer == 2) {
+    if ((channels == 1 && bitrate >= 224 * 1000) ||
+      (channels == 2 && (bitrate == 32 * 1000 || bitrate == 48 * 1000 || bitrate == 56 * 1000 || bitrate == 80 * 1000))) {
+      GST_ERROR_OBJECT (mp3parse,
+          "Mpeg version %d layer %d  channel:%d  bitrate:%d   spec out!", version, layer, channels, bitrate);
+      goto broken_header;
+    }
+  }
+#endif
+
   if (G_UNLIKELY (channels != mp3parse->channels || rate != mp3parse->rate ||
           layer != mp3parse->layer || version != mp3parse->version)) {
     GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
@@ -1304,3 +1632,410 @@ gst_mpeg_audio_parse_get_sink_caps (GstBaseParse * parse)
 
   return res;
 }
+
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+
+/**
+ * gst_mpeg_audio_parse_src_eventfunc:
+ * @parse: #GstBaseParse. #event
+ *
+ * Fast calculation of frame length
+ *
+ * Returns: frame length on success.
+ */
+static guint
+ mp3_type_frame_length_calculation (GstMpegAudioParse *mp3parse, guint32 header)
+ {
+   guint length;
+   guint padding,  bitrate, lsf, layer;
+   guint mpg25;
+   /* The caller has ensured we have a valid header, so bitrate can't be zero here. */ 
+   if(header==0)  /*case which buffer was filled out.*/
+   {
+     length=0;
+     return length;
+   }
+
+   /* For VBR Xing play seek -  GST_MP3PARSE_ALP_SEEK */
+   /* if it's an invalid MPEG version */
+   if (((header >> 19) & 3) == 0x1) {
+     GST_ERROR ("[ERROR] invalid MPEG version: 0x%lx \n", (header >> 19) & 3);
+     return -1;
+   } else {
+     if (header & (1 << 20)) {
+       lsf = (header & (1 << 19)) ? 0 : 1;
+     } else {
+       lsf = 1;
+     }
+   }
+
+   /* if it's an invalid layer */
+   if (!((header >> 17) & 3)) {
+     GST_ERROR ("[ERROR] invalid layer: 0x%lx \n", (header >> 17) & 3);
+     return -2;
+   } else {
+       layer = 4 - ((header >> 17) & 0x3);
+   }
+
+   /* if it's an invalid bitrate */
+   if (((header >> 12) & 0xf) == 0xf) {
+     GST_ERROR ("[ERROR] invalid bitrate: 0x%lx \n", (header >> 12) & 0xf);
+     return -3;
+   } else {
+     bitrate = (header >> 12) & 0xF;
+     mp3parse->hdr_bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
+     /* The caller has ensured we have a valid header, so bitrate can't be zero here. */
+     // g_assert (bitrate != 0);
+     if(mp3parse->hdr_bitrate == 0)
+       return -3;
+   }
+
+   padding = (header >> 9) & 0x1;
+   switch (mp3parse->layer) {
+   case 1:
+     length = 4 * ((mp3parse->hdr_bitrate * 12) / mp3parse->rate + padding);
+     break;
+   case 2:
+     length = (mp3parse->hdr_bitrate * 144) / mp3parse->rate + padding;
+     break;
+   default:
+   case 3:
+     if (header & (1 << 20)) {
+       mp3parse->lsf = (header & (1 << 19)) ? 0 : 1;
+     } else {
+       mp3parse->lsf = 1;
+     }
+       length = (mp3parse->hdr_bitrate * 144) / (mp3parse->rate << mp3parse->lsf) + padding;
+       break;
+     }
+     return length;
+ }
+
+#ifdef GST_EXT_BASEPARSER_MODIFICATION
+/* perform seek in push based mode:
+   find BYTE position to move to based on time and delegate to upstream
+*/
+static gboolean
+gst_mpeg_audio_parse_do_push_seek (GstBaseParse * parse, GstPad * pad, GstEvent * event)
+{
+  GstMpegAudioParse *mp3parse;
+  mp3parse = GST_MPEG_AUDIO_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;
+
+  GST_INFO_OBJECT (parse, "doing 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;
+  byte_cur = 0;
+
+  /* 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;
+    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)) * mp3parse->frame_byte;
+    if (mp3parse->rate > 0)
+      frame_dur = (mp3parse->spf * 1000) / mp3parse->rate;
+    else
+      goto unsupported_seek;
+    if (frame_dur > 0)
+      byte_cur =  esimate_byte / (frame_dur);
+    else
+      goto unsupported_seek;
+
+    if ( (byte_cur == -1) || (byte_cur > mp3parse->encoded_file_size))
+    {
+      GST_INFO_OBJECT(parse, "[WEB-ERROR] seek cur (%"G_GINT64_FORMAT") > file_size (%"G_GINT64_FORMAT") ", cur, mp3parse->encoded_file_size );
+      goto abort_seek;
+    }
+
+    GST_INFO_OBJECT(parse, "frame_byte(%d) spf(%d)  rate (%d) ", mp3parse->frame_byte, mp3parse->spf, mp3parse->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 );
+  }
+
+
+  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;
+  }
+}
+#endif
+
+/**
+ * gst_mpeg_audio_parse_src_eventfunc:
+ * @parse: #GstBaseParse. #event
+ *
+ * before baseparse handles seek event, make full mp3 index table.
+ *
+ * Returns: TRUE on success.
+ */
+static gboolean
+gst_mpeg_audio_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
+{
+  gboolean handled = FALSE;
+  GstMpegAudioParse *mp3parse;
+  mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_SEEK:
+      {
+        GstFlowReturn res = GST_FLOW_OK;
+        gint64 base_offset = 0, sync_offset = 0, cur = 0;
+        gint32 frame_count = 1;        /* do not add first frame because it is already in index table */
+        guint64 second_count = 0;    /* initial 1 second */
+        gint64 total_file_size = 0, start_offset = 0;
+        GstClockTime current_ts = GST_CLOCK_TIME_NONE;
+        GstActivateMode pad_mode = GST_ACTIVATE_NONE;
+       gboolean large_file_flag = FALSE;
+
+        GST_DEBUG("gst_mpeg_audio_parse_src_eventfunc GST_EVENT_SEEK enter");
+
+#ifdef GST_EXT_BASEPARSER_MODIFICATION /* check baseparse define these fuction */
+        gst_base_parse_get_pad_mode(parse, &pad_mode);
+        if (pad_mode != GST_ACTIVATE_PULL) {
+          gboolean ret = FALSE;
+          GST_INFO_OBJECT (mp3parse, "mp3 parser is PUSH MODE.");
+          GstPad* srcpad = gst_element_get_pad(parse, "src");
+          /* check NULL */
+          ret = gst_mpeg_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 (mp3parse->http_seek_flag) {
+          GST_INFO_OBJECT (mp3parse, "souphttpsrc is PULL MODE (so accurate seek mode is OFF)");
+          gst_base_parse_set_seek_mode(parse, 0);
+          goto mp3_seek_null_exit;
+        }
+
+        if (total_file_size > MP3_LARGE_FILE_SIZE ) {
+          large_file_flag = TRUE;
+          gst_base_parse_set_seek_mode(parse, 0);
+          GST_INFO_OBJECT (mp3parse, "larger than big size (50MB)");
+          goto mp3_seek_null_exit;
+        }
+
+        if (mp3parse->encoded_file_size > 0) {
+          GST_INFO_OBJECT(parse, "[SEEK] total_file_size (%"G_GINT64_FORMAT")= encoded_file_size(%"G_GINT64_FORMAT")+ ID3(%"G_GINT64_FORMAT")",
+                                            total_file_size,  mp3parse->encoded_file_size, (total_file_size -  mp3parse->encoded_file_size) );
+          total_file_size =  mp3parse->encoded_file_size;
+        } else {
+          GST_INFO_OBJECT(parse, "[SEEK] encoded_file_siz (%"G_GINT64_FORMAT") is WRONG", mp3parse->encoded_file_size );
+        }
+#else
+        GST_ERROR("baseparser does not define get private param functions. can not make index table here.");
+        break;
+#endif
+
+        if (total_file_size == 0 || start_offset >= total_file_size) {
+          GST_ERROR("last index offset (%"G_GUINT64_FORMAT") is larger than file size (%"G_GUINT64_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 MP3 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 = (1000*1000*1000) */
+
+    /************************************/
+    /* STEP 0: Initialize parse informaion */
+    /************************************/
+    if ((mp3parse->layer > 0) && (mp3parse->rate > 0) &&
+        (mp3parse->hdr_bitrate > 0) &&(mp3parse->channels > 0)) {
+      if (mp3parse->layer == 1)
+        mp3parse->spf = 384;
+      else if (mp3parse->layer == 2)
+        mp3parse->spf = 1152;
+      else if (mp3parse->version == 1) {
+        mp3parse->spf = 1152;
+      } else {
+        /* MPEG-2 or "2.5" */
+        mp3parse->spf = 576;
+      }
+    
+      mp3parse->frame_duration = (mp3parse->spf * GST_MSECOND) / mp3parse->rate;   /* duration per frame (msec) */
+      mp3parse->frame_per_sec = (mp3parse->rate) / mp3parse->spf;           /* frames per second (ea) */
+    } else {
+      GST_WARNING("[CEHCK UP] we must need 'mp3parse->xxxx' information ");
+    }
+
+        /************************************/
+        /* STEP 1: MAX_PULL_RANGE_BUF cycle */
+       /************************************/
+        while (total_file_size - base_offset >= MP3_MAX_PULL_RANGE_BUF) {
+          gint64 offset = 0;
+          GstBuffer *buffer = NULL;
+          guint8 *buf = NULL;
+
+         GST_INFO("gst_pad_pull_range %d bytes (from %"G_GINT64_FORMAT") use max size", MP3_MAX_PULL_RANGE_BUF, base_offset);
+          res = gst_pad_pull_range (parse->sinkpad, base_offset, base_offset + MP3_MAX_PULL_RANGE_BUF, &buffer);
+          if (res != GST_FLOW_OK) {
+            GST_ERROR ("gst_pad_pull_range failed!");
+            break;
+          }
+
+          buf = GST_BUFFER_DATA(buffer);
+          if (buf == NULL) {
+            GST_WARNING("buffer is NULL in make mp3 seek table's STEP1");
+            gst_buffer_unref (buffer);
+            goto mp3_seek_null_exit;
+          }
+
+          while (offset <= MP3_MAX_PULL_RANGE_BUF) {
+            gint frame_size = 0;
+            guint32 header;
+
+            /* make sure the values in the frame header look sane */
+            header = GST_READ_UINT32_BE (buf);
+            frame_size = mp3_type_frame_length_calculation (mp3parse, header);
+
+            if ((frame_size > 0) && (frame_size < (MP3_MAX_PULL_RANGE_BUF - offset))) {
+              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);
+              current_ts += mp3parse->frame_duration * GST_USECOND; /* each frame is (frame_duration) ms */
+              offset += frame_size;
+              buf += frame_size;
+              frame_count++;
+            } else if (frame_size >= (MP3_MAX_PULL_RANGE_BUF - offset)) {
+              GST_DEBUG("we need refill buffer");
+              break;
+            } else {
+              if (frame_size == 0) {
+                GST_WARNING("frame size is 0 , decoding end");
+                goto mp3_seek_null_exit;
+              }
+              GST_WARNING("we lost sync");
+              buf++;
+              offset++;
+            }
+          } /* while */
+          base_offset = base_offset + offset;
+          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;
+
+          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;
+          }
+
+          buf = GST_BUFFER_DATA(buffer);
+          if (buf == NULL) {
+            GST_WARNING("buffer is NULL in make mp3 seek table's STEP2");
+            gst_buffer_unref (buffer);
+            goto mp3_seek_null_exit;
+          }
+
+          while (base_offset + offset < total_file_size) {
+            gint frame_size = 0;
+            guint32 header;
+
+            /* make sure the values in the frame header look sane */
+            header = GST_READ_UINT32_BE (buf);
+            frame_size = mp3_type_frame_length_calculation (mp3parse, header);
+
+            if ((frame_size > 0) && (frame_size <= (total_file_size - (base_offset + offset)))) {
+              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);
+              current_ts += mp3parse->frame_duration * GST_USECOND; /* 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 , decoding end");
+              break;
+            } else {
+              GST_WARNING("we lost sync");
+              buf++;
+              offset++;
+            }
+          } /* while */
+
+          gst_buffer_unref (buffer);
+        } /* end remain_buf buffer cycle */
+
+        GST_DEBUG("gst_mpeg_audio_parse_src_eventfunc GST_EVENT_SEEK leave");
+      }
+     break;
+
+    default:
+      break;
+  }
+
+mp3_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
\ No newline at end of file
index 7580001..bd4008a 100644 (file)
@@ -39,6 +39,9 @@ G_BEGIN_DECLS
 #define GST_IS_MPEG_AUDIO_PARSE_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_MPEG_AUDIO_PARSE))
 
+#define GST_EXT_MP3PARSER_MODIFICATION
+#define GST_MP3PARSE_ALP_EXYNOS
+
 typedef struct _GstMpegAudioParse GstMpegAudioParse;
 typedef struct _GstMpegAudioParseClass GstMpegAudioParseClass;
 
@@ -60,6 +63,13 @@ struct _GstMpegAudioParse {
   /* samples per frame */
   gint        spf;
 
+  /* added for make seek table */
+  guint32         lsf;
+  guint32        frame_duration;
+  guint32        frame_per_sec;
+  gint64          encoded_file_size;
+  guint32        frame_byte;
+
   gboolean     sent_codec_tag;
   guint        last_posted_bitrate;
   gint         last_posted_crc, last_crc;
@@ -92,6 +102,24 @@ struct _GstMpegAudioParse {
   /* LAME info */
   guint32      encoder_delay;
   guint32      encoder_padding;
+
+#ifdef GST_MP3PARSE_ALP_EXYNOS
+  gboolean       alp_mp3dec;
+  gboolean       alp_mode_flag;
+  gboolean       mp3alp_initialized;
+  /* ALP - for frame number */
+  guint32         mp3alp_frame_1st;
+  guint32         mp3alp_frame_count;
+  guint32         mp3alp_buffer_count; 
+  gint64         mp3alp_frame_duration;
+  gint64         mp3alp_buffer_duration;  
+  gdouble         mp3alp_frame_duration_float;
+  guint32         mp3alp_frame_1st_bitrate;
+#endif
+
+#ifdef GST_EXT_MP3PARSER_MODIFICATION
+  gboolean       http_seek_flag;
+#endif
 };
 
 /**
index ae8332d..4f1745a 100644 (file)
@@ -39,8 +39,10 @@ plugin_init (GstPlugin * plugin)
       GST_RANK_PRIMARY + 1, GST_TYPE_AMR_PARSE);
   ret &= gst_element_register (plugin, "ac3parse",
       GST_RANK_PRIMARY + 1, GST_TYPE_AC3_PARSE);
+#ifdef GST_EXT_ENABLE_PARSER_MODIFICATION // should be disable in mobile because not supported codec
   ret &= gst_element_register (plugin, "dcaparse",
       GST_RANK_PRIMARY + 1, GST_TYPE_DCA_PARSE);
+#endif
   ret &= gst_element_register (plugin, "flacparse",
       GST_RANK_PRIMARY + 1, GST_TYPE_FLAC_PARSE);
   ret &= gst_element_register (plugin, "mpegaudioparse",
old mode 100644 (file)
new mode 100755 (executable)
index 0b5a55e..e8bef94
 #define ENTRY_SET_KEYFRAME(e) ((e)->flags = GST_AVI_KEYFRAME)
 #define ENTRY_UNSET_KEYFRAME(e) ((e)->flags = 0)
 
+#ifdef AVIDEMUX_MODIFICATION
+enum
+{
+  PROP_0,
+  PROP_PLAYBACK_PROTECTION,
+};
+#endif
 
 GST_DEBUG_CATEGORY_STATIC (avidemux_debug);
 #define GST_CAT_DEFAULT avidemux_debug
@@ -157,6 +164,8 @@ gst_avi_demux_find_frame_type (GstAviStream *stream, GstBuffer *buf, int *frame_
 static void gst_avidemux_forward_trickplay (GstAviDemux * avi, GstAviStream * stream, guint64 *timestamp);
 static void gst_avidemux_backward_trickplay (GstAviDemux * avi, GstAviStream * stream, guint64 *timestamp);
 static GstFlowReturn gst_avidemux_seek_to_previous_keyframe (GstAviDemux *avi);
+static void gst_avidemux_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_avidemux_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
 #endif
 
 static GstElementClass *parent_class = NULL;
@@ -347,12 +356,25 @@ gst_avi_demux_class_init (GstAviDemuxClass * klass)
   parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->finalize = gst_avi_demux_finalize;
+
+#ifdef AVIDEMUX_MODIFICATION
+  gobject_class->set_property = gst_avidemux_set_property;
+  gobject_class->get_property = gst_avidemux_get_property;
+#endif
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_avi_demux_change_state);
 
   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_avi_demux_set_index);
   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_avi_demux_get_index);
 
+#ifdef AVIDEMUX_MODIFICATION
+  g_object_class_install_property (gobject_class, PROP_PLAYBACK_PROTECTION,
+          g_param_spec_boolean ("playback-protection", "whether file is playback protected or not",
+          "TRUE->playback protected, FALSE->not playback protected", FALSE,
+          G_PARAM_READWRITE));
+#endif
+
 #ifdef DIVX_DRM
        gst_tag_register ("drm_divx", GST_TAG_FLAG_META,
                        G_TYPE_STRING,
@@ -362,6 +384,43 @@ gst_avi_demux_class_init (GstAviDemuxClass * klass)
 #endif
 }
 
+#ifdef AVIDEMUX_MODIFICATION
+static void
+gst_avidemux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAviDemux *avi = GST_AVI_DEMUX (object);
+  switch (prop_id) {
+    case PROP_PLAYBACK_PROTECTION:
+    {
+      avi->playback_protected = g_value_get_boolean(value);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_avidemux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAviDemux *avi = GST_AVI_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_PLAYBACK_PROTECTION:
+    {
+      g_value_set_boolean(value, avi->playback_protected);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+#endif
+
 static void
 gst_avi_demux_init (GstAviDemux * avi)
 {
@@ -379,7 +438,9 @@ gst_avi_demux_init (GstAviDemux * avi)
   gst_element_add_pad (GST_ELEMENT_CAST (avi), avi->sinkpad);
 
   avi->adapter = gst_adapter_new ();
-
+#ifdef AVIDEMUX_MODIFICATION
+  avi->playback_protected =  FALSE;
+#endif
   gst_avi_demux_reset (avi);
 }
 
@@ -748,11 +809,7 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
           GST_DEBUG_OBJECT (query, "total frames is %" G_GUINT32_FORMAT,
               stream->idx_n);
 
-          if (stream->idx_n >= 0)
-            gst_query_set_duration (query, fmt, stream->idx_n);
-          else if (gst_pad_query_convert (pad, GST_FORMAT_TIME,
-                  duration, &fmt, &dur))
-            gst_query_set_duration (query, fmt, dur);
+          gst_query_set_duration (query, fmt, stream->idx_n);
           break;
         }
         default:
@@ -1085,6 +1142,7 @@ gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
       for (i = 0; i < avi->num_streams; i++) {
         avi->stream[i].last_flow = GST_FLOW_OK;
         avi->stream[i].discont = TRUE;
+        avi->stream[i].sent_eos = FALSE;
       }
       /* fall through to default case so that the event gets passed downstream */
     }
@@ -1483,8 +1541,7 @@ invalid_params:
   {
     GST_ERROR_OBJECT (avi, "invalid index parameters (num = %d, bpe = %d)",
         num, bpe);
-    if (buf)
-      gst_buffer_unref (buf);
+    gst_buffer_unref (buf);
     return FALSE;
   }
 }
@@ -2088,6 +2145,13 @@ gst_riff_parse_strd (GstAviDemux * avi,
   GST_DEBUG_OBJECT (avi, " version    %d",  ((gst_riff_strd*)GST_BUFFER_DATA(buf))->version);
   GST_DEBUG_OBJECT (avi, " drm_size %d",  ((gst_riff_strd*)GST_BUFFER_DATA(buf))->drm_size);
 
+  if(avi->playback_protected) {
+    gst_buffer_unref (buf);
+    GST_ERROR_OBJECT (avi, "Trusted OPL violation error");
+    GST_ELEMENT_ERROR (avi, STREAM, DECRYPT_NOKEY, ("Trusted opl violation error"), (NULL));
+    return FALSE;
+  }
+
   return  gst_avi_demux_init_divx_drm (avi, GST_BUFFER_DATA(buf)+sizeof(gst_riff_strd));
 
   /* ERRORS */
@@ -2257,6 +2321,14 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
             stream->is_vbr = (stream->strh->samplesize == 0)
                 && stream->strh->scale > 1
                 && stream->strf.auds->blockalign != 1;
+#ifdef AVIDEMUX_MODIFICATION
+            /* This is processing for exception condition.
+            * samplesize is not 0, but is_vbr must become true. */
+            if(stream->strf.auds->format == GST_RIFF_WAVE_FORMAT_AAC) {
+              if (stream->strh->scale > 1 && stream->strf.auds->blockalign != 1)
+                stream->is_vbr = TRUE;
+            }
+#endif
             GST_DEBUG_OBJECT (element, "marking audio as VBR:%d, res %d",
                 stream->is_vbr, res);
             /* we need these or we have no way to come up with timestamps */
@@ -2434,6 +2506,9 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
         g_free (vprp);
         vprp = NULL;
       }
+#ifdef AVIDEMUX_MODIFICATION
+     gst_caps_set_simple (caps, "ts-linear", G_TYPE_BOOLEAN, TRUE, NULL);
+#endif
       tag_name = GST_TAG_VIDEO_CODEC;
       avi->num_v_streams++;
       break;
@@ -2531,6 +2606,7 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
 
   stream->idx_n = 0;
   stream->idx_max = 0;
+  stream->sent_eos = FALSE;
 
   gst_pad_set_element_private (pad, stream);
   avi->num_streams++;
@@ -2706,7 +2782,7 @@ gst_avi_demux_index_for_time (GstAviDemux * avi,
     GstAviStream * stream, guint64 time)
 {
   guint index = -1;
-  guint64 total;
+  guint64 total = 0;
 
   GST_LOG_OBJECT (avi, "search time:%" GST_TIME_FORMAT, GST_TIME_ARGS (time));
 
@@ -2793,7 +2869,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
   gst_riff_index_entry *index;
   GstClockTime stamp;
   GstAviStream *stream;
-  GstAviIndexEntry entry;
+  GstAviIndexEntry entry = {0};
   guint32 id;
 
   if (!buf)
@@ -2927,6 +3003,35 @@ gst_avi_demux_stream_index (GstAviDemux * avi)
   tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
   size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
   if (tag == GST_RIFF_TAG_LIST) {
+
+#ifdef AVIDEMUX_MODIFICATION
+    /* check for multiple list tag */
+    do {
+      GstBuffer *temp_buf;
+      guint32 temp_tag;
+      guint32 temp_size;
+      res = gst_pad_pull_range (avi->sinkpad, offset + 20, 8, &temp_buf);
+      if (res != GST_FLOW_OK)
+        goto pull_failed;
+      else if (GST_BUFFER_SIZE (buf) < 8)
+        goto too_small;
+      /* check tag first before blindy trying to read 'size' bytes */
+      temp_tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (temp_buf));
+      temp_size = GST_READ_UINT32_LE (GST_BUFFER_DATA (temp_buf) + 4);
+      if (temp_tag == GST_RIFF_TAG_LIST) {
+        GST_WARNING_OBJECT (avi, "there are multiple list tags in the file, so skipping them");
+        gst_buffer_unref (buf);
+        buf = temp_buf;
+        tag = temp_tag;
+        size = temp_size;
+        offset += 20;
+        avi->offset += 20;
+      }
+      else
+        break;
+    } while (1);
+#endif
+
     /* this is the movi tag */
     GST_DEBUG_OBJECT (avi, "skip LIST chunk, size %" G_GUINT32_FORMAT,
         (8 + GST_ROUND_UP_2 (size)));
@@ -3408,6 +3513,7 @@ gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
 {
   gboolean result = FALSE;
   gint i;
+  GstEventType etype = GST_EVENT_TYPE (event);
 
   GST_DEBUG_OBJECT (avi, "sending %s event to %d streams",
       GST_EVENT_TYPE_NAME (event), avi->num_streams);
@@ -3416,6 +3522,15 @@ gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
     GstAviStream *stream = &avi->stream[i];
 
     if (stream->pad) {
+      if (etype == GST_EVENT_EOS) {
+        /* let's not send twice */
+        if (stream->sent_eos) {
+         result = TRUE;
+          continue;
+       }
+        GST_DEBUG_OBJECT(avi, "Sending EOS for stream %d", i);
+        stream->sent_eos = TRUE;
+      }
       result = TRUE;
       gst_pad_push_event (stream->pad, gst_event_ref (event));
     }
@@ -4305,6 +4420,7 @@ gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream,
     stream->start_entry = index;
     stream->step_entry = index;
     stream->stop_entry = gst_avi_demux_index_last (avi, stream);
+    stream->sent_eos = FALSE;
   }
   if (stream->current_entry != index) {
     GST_DEBUG_OBJECT (avi, "Move DISCONT from %u to %u",
@@ -4442,7 +4558,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
   GstFormat format;
   GstSeekFlags flags;
   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
-  gint64 cur, stop;
+  gint64 cur = 0, stop;
   gboolean flush;
   gboolean update;
   GstSegment seeksegment = { 0, };
@@ -5093,6 +5209,25 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
     /* we have the stream now */
     stream = &avi->stream[stream_num];
 
+    if ((stream->current_entry + 1) > stream->stop_entry) {
+      if (stream->sent_eos == FALSE) {
+       if(avi->segment.applied_rate > 0.0)
+        {
+           GstEvent *event = NULL;
+           event = gst_event_new_new_segment_full (FALSE,
+                        avi->segment.rate, avi->segment.applied_rate, avi->segment.format,
+                        stream->hdr_duration, stream->hdr_duration, avi->segment.time);
+           gst_pad_push_event (stream->pad, event);
+        }
+
+        GST_DEBUG_OBJECT(avi, "Sending EOS for stream %d", stream_num);
+        gst_pad_push_event(stream->pad, gst_event_new_eos ());
+        stream->sent_eos = TRUE;
+        stream->last_flow = GST_FLOW_UNEXPECTED;
+        continue;
+      }
+    }
+
     /* skip streams without pads */
     if (!stream->pad) {
       GST_DEBUG_OBJECT (avi, "skipping entry from stream %d without pad",
@@ -5131,8 +5266,13 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
 
     if (avi->segment.rate > 0.0) {
       /* only check this for fowards playback for now */
+#ifdef AVIDEMUX_MODIFICATION
+      if (GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
+          && (timestamp > avi->segment.stop)) {
+#else
       if (keyframe && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
           && (timestamp > avi->segment.stop)) {
+#endif
         goto eos_stop;
       }
     }
old mode 100644 (file)
new mode 100755 (executable)
index 174d8a8..8e3afec
@@ -141,6 +141,7 @@ typedef struct {
   GstTagList   *taglist;
 
   gint           index_id;
+  gboolean       sent_eos;
 } GstAviStream;
 
 typedef enum {
@@ -210,6 +211,9 @@ typedef struct _GstAviDemux {
   gint           index_id;
   gboolean       seekable;
 
+  //playback protection
+  gboolean       playback_protected;
+
 #ifdef DIVX_DRM
   uint8_t* drmContext;
   void *divx_handle;
old mode 100644 (file)
new mode 100755 (executable)
index fbf7e25..9057ec2
@@ -811,6 +811,11 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
   /* Combine them */
   pts |= pts_ext << 24;
 
+  if((pts * GST_MSECOND) < demux->segment.last_stop)
+  {
+    return GST_FLOW_OK;
+  }
+
   GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
       data[2], data[3], pts);
 
@@ -1369,9 +1374,6 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
     demux->video_need_discont = FALSE;
   }
 
-  gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME,
-      GST_BUFFER_TIMESTAMP (outbuf));
-
   /* Do we need a newsegment event ? */
   if (G_UNLIKELY (demux->video_need_segment)) {
     if (demux->close_seg_event)
@@ -2007,7 +2009,7 @@ gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
         "partial pull got %d when expecting %d from offset %" G_GUINT64_FORMAT,
         GST_BUFFER_SIZE (*buffer), size, offset);
     gst_buffer_unref (*buffer);
-    ret = GST_FLOW_UNEXPECTED;
+    ret = GST_FLOW_NOT_SUPPORTED;
     *buffer = NULL;
     return ret;
   }
@@ -2248,7 +2250,7 @@ exit:
 static gint64
 gst_flv_demux_get_metadata (GstFlvDemux * demux)
 {
-  gint64 ret = 0, offset;
+  gint64 ret = 0, offset = 0;
   GstFormat fmt = GST_FORMAT_BYTES;
   size_t tag_size, size;
   GstBuffer *buffer = NULL;
@@ -2456,12 +2458,14 @@ gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment)
           GST_TIME_ARGS (segment->last_stop), GST_TIME_ARGS (time), bytes);
 
       /* Key frame seeking */
-      if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
+#ifndef FLVDEMUX_MODIFICATION
+      if (segment->flags & GST_SEEK_FLAG_KEY_UNIT)
+#endif
+      {
         /* Adjust the segment so that the keyframe fits in */
         if (time < segment->start) {
           segment->start = segment->time = time;
         }
-        segment->last_stop = time;
       }
     } else {
       GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
old mode 100644 (file)
new mode 100755 (executable)
index 07559a5..2d064b7
@@ -34,6 +34,9 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLV_DEMUX))
 #define GST_IS_FLV_DEMUX_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLV_DEMUX))
+
+#define FLVDEMUX_MODIFICATION
+
 typedef struct _GstFlvDemux GstFlvDemux;
 typedef struct _GstFlvDemuxClass GstFlvDemuxClass;
 
index 010e09c..d7be13e 100644 (file)
@@ -1,7 +1,7 @@
 
 plugin_LTLIBRARIES = libgstisomp4.la
 
-libgstisomp4_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+libgstisomp4_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DRM_CLIENT_CFLAGS) $(DRM_TRUSTED_CFLAGS)
 libgstisomp4_la_LIBADD = \
     $(GST_PLUGINS_BASE_LIBS) \
     -lgstriff-@GST_MAJORMINOR@ \
@@ -9,7 +9,7 @@ libgstisomp4_la_LIBADD = \
     -lgstrtp-@GST_MAJORMINOR@ \
     -lgsttag-@GST_MAJORMINOR@ \
     -lgstpbutils-@GST_MAJORMINOR@ \
-    $(GST_BASE_LIBS) $(GST_LIBS) $(ZLIB_LIBS)
+    $(GST_BASE_LIBS) $(GST_LIBS) $(ZLIB_LIBS)  $(DRM_CLIENT_LIBS) $(DRM_TRUSTED_LIBS)
 libgstisomp4_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS}
 libgstisomp4_la_SOURCES = isomp4-plugin.c gstrtpxqtdepay.c \
        qtdemux.c qtdemux_types.c qtdemux_dump.c qtdemux_lang.c \
old mode 100644 (file)
new mode 100755 (executable)
index 295d17e..eb36cb5
@@ -55,14 +55,10 @@ G_BEGIN_DECLS
 #define FOURCC_clip     GST_MAKE_FOURCC('c','l','i','p')
 #define FOURCC_trak     GST_MAKE_FOURCC('t','r','a','k')
 #define FOURCC_udta     GST_MAKE_FOURCC('u','d','t','a')
-#define FOURCC_ctab     GST_MAKE_FOURCC('c','t','a','b')
 #define FOURCC_tkhd     GST_MAKE_FOURCC('t','k','h','d')
 #define FOURCC_crgn     GST_MAKE_FOURCC('c','r','g','n')
-#define FOURCC_matt     GST_MAKE_FOURCC('m','a','t','t')
-#define FOURCC_kmat     GST_MAKE_FOURCC('k','m','a','t')
 #define FOURCC_edts     GST_MAKE_FOURCC('e','d','t','s')
 #define FOURCC_elst     GST_MAKE_FOURCC('e','l','s','t')
-#define FOURCC_load     GST_MAKE_FOURCC('l','o','a','d')
 #define FOURCC_tref     GST_MAKE_FOURCC('t','r','e','f')
 #define FOURCC_imap     GST_MAKE_FOURCC('i','m','a','p')
 #define FOURCC___in     GST_MAKE_FOURCC(' ',' ','i','n')
@@ -78,7 +74,6 @@ G_BEGIN_DECLS
 #define FOURCC_smhd     GST_MAKE_FOURCC('s','m','h','d')
 #define FOURCC_gmhd     GST_MAKE_FOURCC('g','m','h','d')
 #define FOURCC_hmhd     GST_MAKE_FOURCC('h','m','h','d')
-#define FOURCC_gmin     GST_MAKE_FOURCC('g','m','i','n')
 #define FOURCC_dinf     GST_MAKE_FOURCC('d','i','n','f')
 #define FOURCC_dref     GST_MAKE_FOURCC('d','r','e','f')
 #define FOURCC_stbl     GST_MAKE_FOURCC('s','t','b','l')
@@ -93,7 +88,6 @@ G_BEGIN_DECLS
 #define FOURCC_strm     GST_MAKE_FOURCC('s','t','r','m')
 #define FOURCC_rtsp     GST_MAKE_FOURCC('r','t','s','p')
 #define FOURCC_co64     GST_MAKE_FOURCC('c','o','6','4')
-#define FOURCC_cmov     GST_MAKE_FOURCC('c','m','o','v')
 #define FOURCC_dcom     GST_MAKE_FOURCC('d','c','o','m')
 #define FOURCC_cmvd     GST_MAKE_FOURCC('c','m','v','d')
 #define FOURCC_hint     GST_MAKE_FOURCC('h','i','n','t')
@@ -134,13 +128,7 @@ G_BEGIN_DECLS
 #define FOURCC_free     GST_MAKE_FOURCC('f','r','e','e')
 #define FOURCC_data     GST_MAKE_FOURCC('d','a','t','a')
 #define FOURCC_SVQ3     GST_MAKE_FOURCC('S','V','Q','3')
-#define FOURCC_rmra     GST_MAKE_FOURCC('r','m','r','a')
-#define FOURCC_rmda     GST_MAKE_FOURCC('r','m','d','a')
-#define FOURCC_rdrf     GST_MAKE_FOURCC('r','d','r','f')
 #define FOURCC__gen     GST_MAKE_FOURCC(0xa9, 'g', 'e', 'n')
-#define FOURCC_rmdr     GST_MAKE_FOURCC('r','m','d','r')
-#define FOURCC_rmvc     GST_MAKE_FOURCC('r','m','v','c')
-#define FOURCC_qtim     GST_MAKE_FOURCC('q','t','i','m')
 #define FOURCC_drms     GST_MAKE_FOURCC('d','r','m','s')
 #define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
 #define FOURCC_h263     GST_MAKE_FOURCC('h','2','6','3')
@@ -188,6 +176,11 @@ G_BEGIN_DECLS
 #define FOURCC_sosn     GST_MAKE_FOURCC('s','o','s','n')
 #define FOURCC_XMP_     GST_MAKE_FOURCC('X','M','P','_')
 #define FOURCC_uuid     GST_MAKE_FOURCC('u','u','i','d')
+#define FOURCC_pssh     GST_MAKE_FOURCC('p','s','s','h')
+#define FOURCC_saiz     GST_MAKE_FOURCC('s','a','i','z')
+#define FOURCC_saio     GST_MAKE_FOURCC('s','a','i','o')
+#define FOURCC_senc     GST_MAKE_FOURCC('s','e','n','c')
+#define FOURCC_mfhd     GST_MAKE_FOURCC('m','f','h','d')
 
 
 /* SVQ3 fourcc */
old mode 100644 (file)
new mode 100755 (executable)
index 29d7ef5..cc15f89
 #ifdef HAVE_ZLIB
 # include <zlib.h>
 #endif
+#ifdef QTDEMUX_MODIFICATION
+#include <gst/base/gstbytereader.h>
+#define READ_UINT8(reader, val, nbits) G_STMT_START { \
+  if (!gst_bit_reader_get_bits_uint8 (reader, &val, nbits)) { \
+    GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
+    goto failed; \
+  } \
+}G_STMT_END
+#define MARKER_UNCHECKED(br) G_STMT_START { \
+  if (!gst_bit_reader_get_bits_uint8_unchecked (br, 1)) { \
+    GST_WARNING ("Wrong marker bit"); \
+    goto failed; \
+  } \
+}G_STMT_END
+#define CHECK_REMAINING(br, needed) G_STMT_START { \
+  if (gst_bit_reader_get_remaining (br) < needed) \
+    goto failed; \
+} G_STMT_END
+#define READ_UINT16(reader, val, nbits) G_STMT_START { \
+  if (!gst_bit_reader_get_bits_uint16 (reader, &val, nbits)) { \
+    GST_WARNING ("failed to read uint16, nbits: %d", nbits); \
+    goto failed; \
+  } \
+}G_STMT_END
+#define SKIP(reader, nbits) G_STMT_START { \
+  if (!gst_bit_reader_skip (reader, nbits)) { \
+    GST_WARNING ("failed to skip nbits: %d", nbits); \
+    goto failed; \
+  } \
+} G_STMT_END
+#define CHECK_ALLOWED(val, min, max) G_STMT_START { \
+  if (val < min || val > max) { \
+    GST_WARNING ("value not in allowed range. value: %d, range %d-%d", \
+                     val, min, max); \
+    goto failed; \
+  } \
+}G_STMT_END
+static const guint8 default_intra_quant_mat[64] = {
+  8, 17, 18, 19, 21, 23, 25, 27,
+  17, 18, 19, 21, 23, 25, 27, 28,
+  20, 21, 22, 23, 24, 26, 28, 30,
+  21, 22, 23, 24, 26, 28, 30, 32,
+  22, 23, 24, 26, 28, 30, 32, 35,
+  23, 24, 26, 28, 30, 32, 35, 38,
+  25, 26, 28, 30, 32, 35, 38, 41,
+  27, 28, 30, 32, 35, 38, 41, 45
+};
 
+static const guint8 default_non_intra_quant_mat[64] = {
+  16, 17, 18, 19, 20, 21, 22, 23,
+  17, 18, 19, 20, 21, 22, 23, 24,
+  18, 19, 20, 21, 22, 23, 24, 25,
+  19, 20, 21, 22, 23, 24, 26, 27,
+  20, 21, 22, 23, 25, 26, 27, 28,
+  21, 22, 23, 24, 26, 27, 28, 30,
+  22, 23, 24, 26, 27, 28, 30, 31,
+  23, 24, 25, 27, 28, 30, 31, 33,
+};
+static const guint8 mpeg4_zigzag_8x8[64] = {
+  0, 1, 8, 16, 9, 2, 3, 10,
+  17, 24, 32, 25, 18, 11, 4, 5,
+  12, 19, 26, 33, 40, 48, 41, 34,
+  27, 20, 13, 6, 7, 14, 21, 28,
+  35, 42, 49, 56, 57, 50, 43, 36,
+  29, 22, 15, 23, 30, 37, 44, 51,
+  58, 59, 52, 45, 38, 31, 39, 46,
+  53, 60, 61, 54, 47, 55, 62, 63
+};
+#endif
 /* max. size considered 'sane' for non-mdat atoms */
 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
 
 /* if the sample index is larger than this, something is likely wrong */
-#define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
+#define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (60*1024*1024)
 
 /* For converting qt creation times to unix epoch times */
 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
 #ifdef QTDEMUX_MODIFICATION
 /* default value of buffer-size property */
 #define QTDEMUX_MAX_BUFFER_SIZE   (100*1024*1024)
-
+#ifdef DRM_ENABLE
+#define QTDEMUX_DRM_WORD_SIZE  50
+#endif
+#define QTDEMUX_MAX_SAMPLE_DURATION 2*GST_SECOND
 #define QTDEMUX_DEFAULT_FWD_TRICKPLAY_MODE  0 /* 0: sending P-frames also, 1: only key frames */
 /* properties considering different cases of file formats */
+
 enum
 {
   PROP_0,
   PROP_MAX_BUFFER_SIZE,
   PROP_TEMP_LOCATION,
   PROP_FWDTRICK_MODE,
+  PROP_PLAYBACK_PROTECTION,
 };
 #endif
 
@@ -112,6 +185,11 @@ typedef struct _QtDemuxSample QtDemuxSample;
 
 #ifdef QTDEMUX_MODIFICATION
 typedef struct _TrickPlayInfo TrickPlayInfo;
+typedef struct _QtDemuxSubSampleEncryption QtDemuxSubSampleEncryption;
+typedef struct _QtDemuxSubSampleEntryInfo QtDemuxSubSampleEntryInfo;
+typedef struct _QtDemuxTfraTable QtDemuxTfraTable;
+typedef struct _QtDemuxTfraEntryInfo QtDemuxTfraEntryInfo;
+typedef struct _QtDemuxLanguageStruct QtDemuxLanguageStruct;
 
 struct _TrickPlayInfo
 {
@@ -121,6 +199,37 @@ struct _TrickPlayInfo
   gint32 show_samples; /* samples to show between two consecutive key frames */
   guint64 start_pos; /* trickplay start position */
 };
+
+struct _QtDemuxSubSampleEntryInfo
+{
+  guint16 LenofClearData;
+  guint32 LenofEncryptData;
+};
+
+struct _QtDemuxSubSampleEncryption
+{
+  guint16 n_entries;
+  QtDemuxSubSampleEntryInfo *sub_entry;
+};
+
+struct _QtDemuxTfraEntryInfo
+{
+  guint64 time;
+  guint64 moof_offset;
+};
+
+struct _QtDemuxTfraTable
+{
+  guint32 n_entries;
+  GArray *tfra_entries;
+};
+
+struct _QtDemuxLanguageStruct
+{
+  gchar* language_code;
+  gchar* language_key;
+  gboolean active;
+};
 #endif
 
 
@@ -136,9 +245,13 @@ struct _QtDemuxSample
   guint32 size;
   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
   guint64 offset;
-  guint64 timestamp;            /* DTS In mov time */
+  guint64 timestamp;          /* DTS In mov time */
   guint32 duration;             /* In mov time */
-  gboolean keyframe;            /* TRUE when this packet is a keyframe */
+  gboolean keyframe;         /* TRUE when this packet is a keyframe */
+#ifdef QTDEMUX_MODIFICATION
+  guint8 *iv;                         /* initialization vector for decryption*/
+  QtDemuxSubSampleEncryption *sub_encry;
+#endif
 };
 
 /* timestamp is the DTS */
@@ -213,6 +326,70 @@ struct _QtDemuxSample
  *
  * This is a good usecase for the GStreamer accumulated SEGMENT events.
  */
+#ifdef QTDEMUX_MODIFICATION
+typedef char uuid_t[16];
+
+static const uuid_t tfxd_uuid =
+  {
+    0x6d, 0x1d, 0x9b, 0x05,
+    0x42, 0xd5, 0x44, 0xe6,
+    0x80, 0xe2, 0x14, 0x1d,
+    0xaf, 0xf7, 0x57, 0xb2
+  };
+
+static const uuid_t tfrf_uuid =
+  {
+    0xd4, 0x80, 0x7e, 0xf2,
+    0xca, 0x39, 0x46, 0x95,
+    0x8e, 0x54, 0x26, 0xcb,
+    0x9e, 0x46, 0xa7, 0x9f
+  };
+
+static const uuid_t encrypt_uuid =
+  {
+    0xa2, 0x39, 0x4f, 0x52,
+    0x5a, 0x9b, 0x4f, 0x14,
+    0xa2, 0x44, 0x6c, 0x42,
+    0x7c, 0x64, 0x8d, 0xf4
+  };
+
+static const uuid_t protection_uuid =
+  {
+    0xd0, 0x8a, 0x4f, 0x18,
+    0x10, 0xf3, 0x4a, 0x82,
+    0xb6, 0xc8, 0x32, 0xd8,
+    0xab, 0xa1, 0x83, 0xd3
+  };
+static const uuid_t playready_system_id =
+  {
+    0x9a, 0x04, 0xf0, 0x79,
+    0x98, 0x40, 0x42, 0x86,
+    0xab, 0x92, 0xe6, 0x5b,
+    0xe0, 0x88, 0x5f, 0x95
+  };
+
+static const uuid_t dash_playready_system_id =
+  {
+    0x79, 0xf0, 0x04, 0x9a,
+    0x40, 0x98, 0x86, 0x42,
+    0xab, 0x92, 0xe6, 0x5b,
+    0xe0, 0x88, 0x5f, 0x95
+  };
+
+#define SE_OVERRIDE_TE_FLAGS 0x000001
+#define SE_USE_SUBSAMPLE_ENCRYPTION 0x000002
+
+#ifdef DRM_ENABLE
+typedef enum
+{
+  UUID_UNKNOWN = -1,
+  UUID_TFXD,
+  UUID_TFRF,
+  UUID_SAMPLE_ENCRYPT,
+  UUID_PROTECTION_HEADER,
+}uuid_type_t;
+#endif // DRM_ENABLE
+#endif
 
 struct _QtDemuxSegment
 {
@@ -225,7 +402,20 @@ struct _QtDemuxSegment
   guint64 media_stop;
   gdouble rate;
 };
-
+#ifdef QTDEMUX_MODIFICATION
+#ifdef DRM_ENABLE
+struct _QtDemuxDrm
+{
+  drm_trusted_open_decrypt_info_s open_input_data ;
+  drm_trusted_open_decrypt_resp_data_s open_output_data ;
+  drm_trusted_set_consumption_state_info_s state_input_data;
+  drm_permission_type_e status_perm_type;
+  drm_license_status_e license_status ;
+  gchar *license_file_path;
+  drm_bool_type_e is_drm_file;
+};
+#endif
+#endif
 struct _QtDemuxStream
 {
   GstPad *pad;
@@ -253,7 +443,7 @@ struct _QtDemuxStream
   QtDemuxSample *samples;
   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
   guint32 min_duration;         /* duration in timescale of first sample, used for figuring out
-                                   the framerate, in timescale units */
+                                                 the framerate, in timescale units */
 
   /* if we use chunks or samples */
   gboolean sampled;
@@ -324,7 +514,6 @@ struct _QtDemuxStream
   GstByteReader stsc;
   GstByteReader stts;
   GstByteReader stss;
-  GstByteReader stps;
   GstByteReader ctts;
 
   gboolean chunks_are_chunks;
@@ -356,10 +545,7 @@ struct _QtDemuxStream
   gboolean stss_present;
   guint32 n_sample_syncs;
   guint32 stss_index;
-  /* stps */
-  gboolean stps_present;
   guint32 n_sample_partial_syncs;
-  guint32 stps_index;
   /* ctts */
   gboolean ctts_present;
   guint32 n_composition_times;
@@ -374,7 +560,14 @@ struct _QtDemuxStream
   guint32 def_sample_size;
   guint32 def_sample_flags;
 #ifdef QTDEMUX_MODIFICATION
+  guint32 orientation;
   TrickPlayInfo *trickplay_info; /* trickplay specific handle */
+  guint32 prev_n_samples;
+  GQueue *frag_queue; /* used for PIFF fragments in chain mode */
+  QtDemuxTfraTable *tfra_table;
+  /* dash specified */
+  guint64 dash_seek_offset;
+  guint64 moof_seeked_time;
 #endif
 };
 
@@ -462,8 +655,16 @@ static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux,
 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
     QtDemuxStream * stream, guint32 n);
 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
+static GstFlowReturn qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
+    guint64 * length, guint32 fourcc);
 
 #ifdef QTDEMUX_MODIFICATION
+static void gst_qtdemux_stream_clear (GstQTDemux *qtdemux, QtDemuxStream * stream);
+static void gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream);
+static gboolean gst_qtdemux_sink_setcaps (GstPad * pad, GstCaps *caps);
+static void gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
+    QtDemuxStream * stream);
+static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
 static void gst_qtdemux_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_qtdemux_get_property (GObject * object, guint prop_id,
@@ -471,6 +672,14 @@ static void gst_qtdemux_get_property (GObject * object, guint prop_id,
 static gint32 gst_qtdemux_find_next_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str, guint32 index);
 static void gst_qtdemux_forward_trickplay (GstQTDemux * qtdemux, QtDemuxStream * stream, guint64 *timestamp);
 static void gst_qtdemux_backward_trickplay (GstQTDemux * qtdemux, QtDemuxStream * stream, guint64 *timestamp);
+
+#ifdef DRM_ENABLE
+static gboolean qtdemux_get_playready_licence (GstQTDemux * qtdemux, guint8* data, guint size, char* query_file_path);
+void test_drm_trusted_operation_cb(drm_trusted_user_operation_info_s *operation_info, void *output_data);
+static gboolean qtdemux_parse_playready_system_id(GstQTDemux * qtdemux, GstByteReader *uuid_data);
+static uuid_type_t qtdemux_get_uuid_type(GstQTDemux * qtdemux, GstByteReader *uuid_data, gint64 *uuid_offset);
+static void qtdemux_post_drm_error (GstQTDemux * qtdemux, int drm_error);
+#endif // DRM_ENABLE
 #endif
 
 static void
@@ -523,7 +732,7 @@ gst_qtdemux_class_init (GstQTDemuxClass * klass)
         "Maximum buffer size for mdat atom buffering in case it comes before the moov atom",
         1, G_MAXUINT, QTDEMUX_MAX_BUFFER_SIZE,
         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  
+
   g_object_class_install_property (gobject_class, PROP_TEMP_LOCATION,
       g_param_spec_string ("temp-location", "temp-location",
         "Location for the mdat atom buffering incase it comes before the moov atom",
@@ -536,6 +745,11 @@ gst_qtdemux_class_init (GstQTDemuxClass * klass)
         "(0) Sending Non-Keyframes also in forward trickplay (1) Sending only keyframes in forward trickplay",
         QTDEMUX_DEFAULT_FWD_TRICKPLAY_MODE,
         G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_PLAYBACK_PROTECTION,
+        g_param_spec_boolean ("playback-protection", "whether file is playback protected or not",
+          "TRUE->playback protected, FALSE->not playback protected", FALSE,
+          G_PARAM_READWRITE));
 #endif
 
 
@@ -554,9 +768,15 @@ gst_qtdemux_init (GstQTDemux * qtdemux, GstQTDemuxClass * klass)
       qtdemux_sink_activate_push);
   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
-  gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
 
   qtdemux->state = QTDEMUX_STATE_INITIAL;
+#ifdef QTDEMUX_MODIFICATION
+  gst_pad_set_setcaps_function (qtdemux->sinkpad, gst_qtdemux_sink_setcaps);
+  gst_pad_set_element_private (qtdemux->sinkpad, qtdemux);
+  gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
+
+  qtdemux->protection_header_present = FALSE;
+#endif
   qtdemux->pullbased = FALSE;
   qtdemux->posted_redirect = FALSE;
   qtdemux->neededbytes = 16;
@@ -568,7 +788,12 @@ gst_qtdemux_init (GstQTDemux * qtdemux, GstQTDemuxClass * klass)
   qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
   qtdemux->mdatbuffer = NULL;
   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
+#ifdef MULTI_AUDIO
+  qtdemux->Language_list = NULL;
+#endif
 #ifdef QTDEMUX_MODIFICATION
+   qtdemux->is_dash = FALSE;
+   qtdemux->dash_init_offset = GST_CLOCK_TIME_NONE;
    /* Initialization of properties with default values*/
    qtdemux->filename = g_strdup("/tmp/qtdemux");
    qtdemux->file = NULL;
@@ -576,6 +801,31 @@ gst_qtdemux_init (GstQTDemux * qtdemux, GstQTDemuxClass * klass)
    qtdemux->filesize = 0;
    qtdemux->maxbuffersize = QTDEMUX_MAX_BUFFER_SIZE;
    qtdemux->fwdtrick_mode = QTDEMUX_DEFAULT_FWD_TRICKPLAY_MODE;
+#ifdef DRM_ENABLE
+   qtdemux->encrypt_content = FALSE;
+   qtdemux->pr_handle = NULL;
+#endif
+   qtdemux->piff_fragmented = FALSE;
+   qtdemux->max_pop_ts = 0;
+   qtdemux->playback_protected = FALSE;
+   qtdemux->need_parsing_moov = FALSE;
+   qtdemux->sample_count[0] = 0;
+   qtdemux->sample_count[1] = 0;
+   qtdemux->current_sample[0] = 0;
+   qtdemux->current_sample[1] = 0;
+   qtdemux->sequence_id = 0;
+   qtdemux->dash_content = FALSE;
+   qtdemux->sub_sample_count = NULL;
+   qtdemux->encrypted_data = NULL;
+   qtdemux->clear_data = NULL;
+   qtdemux->iv_data_audio = NULL;
+   qtdemux->iv_data_video = NULL;
+   qtdemux->no_of_audio_samples = 0;
+   qtdemux->no_of_video_samples = 0;
+   qtdemux->moof_offsets = NULL;
+   qtdemux->need_moof_parsing = FALSE;
+   qtdemux->mfra_offset = 0;
+   qtdemux->Subtitle_language_list = NULL;
 #endif
 }
 
@@ -610,13 +860,16 @@ gst_qtdemux_set_property (GObject * object, guint prop_id,
       demux->maxbuffersize = g_value_get_uint (value);
       break;
     case PROP_TEMP_LOCATION:
-      if (demux->filename) 
+      if (demux->filename)
         g_free (demux->filename);
       demux->filename = g_strdup (g_value_get_string (value));
       break;
     case PROP_FWDTRICK_MODE:
       demux->fwdtrick_mode = g_value_get_boolean(value);
       break;
+    case PROP_PLAYBACK_PROTECTION:
+      demux->playback_protected = g_value_get_boolean(value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -624,7 +877,7 @@ gst_qtdemux_set_property (GObject * object, guint prop_id,
 }
 
 static void
-gst_qtdemux_get_property (GObject * object, guint prop_id, 
+gst_qtdemux_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
   GstQTDemux *demux;
@@ -640,6 +893,9 @@ gst_qtdemux_get_property (GObject * object, guint prop_id,
     case PROP_FWDTRICK_MODE:
       g_value_set_boolean(value, demux->fwdtrick_mode);
       break;
+    case PROP_PLAYBACK_PROTECTION:
+      g_value_set_boolean(value, demux->playback_protected);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -661,7 +917,190 @@ gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
         ("no known streams found"));
   }
 }
+#ifdef QTDEMUX_MODIFICATION
+#ifdef DRM_ENABLE
+static gboolean
+qtdemux_playready_parse_uuid(GNode * uuid,GstQTDemux * qtdemux)
+{
+  QtDemuxDrm struct_drm = {0, };
+  GstByteReader uuid_data;
+  guint32 protection_header_size = 0;
+  guint8 *protection_header_data = NULL;
+  gint64 uuid_offset = 0;
+  int ret = -1;
+  int i = 0;
+  guint8 *buffer = (guint8 *) uuid->data;
+  gint len_protection_header = 0;
+  gboolean is_video = FALSE;
+  uuid_type_t uuid_type;
+  struct_drm.license_status = DRM_LICENSE_STATUS_UNDEFINED;
+  struct_drm.license_file_path = NULL;
+  struct_drm.is_drm_file = DRM_UNKNOWN;
+
+  gst_byte_reader_init (&uuid_data, buffer, QT_UINT32 (buffer));
+  uuid_type = qtdemux_get_uuid_type (qtdemux, &uuid_data, &uuid_offset);/*this function call is neccesary for changing uudi data offset*/
+  if(!qtdemux) {
+    goto fail;
+  }
+  if(qtdemux->n_streams) {
+    for(i = 0 ; i < qtdemux->n_streams;i++ ) {
+      if(qtdemux->streams[i]->subtype == FOURCC_vide) {
+        GST_INFO_OBJECT(qtdemux,"video stream is present in content");
+        is_video = TRUE;
+        break;
+      }
+    }
+  }
+  if (qtdemux->playback_protected && is_video )  {
+    GST_ERROR_OBJECT (qtdemux, "Video file is playback protected, so exiting now");
+    GST_ERROR_OBJECT (qtdemux, "Trusted OPL violation error");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT_NOKEY, ("Trusted opl violation error"), (NULL));
+    goto fail;
+  }
+
+  if (!qtdemux_parse_playready_system_id (qtdemux, &uuid_data)) {
+    GST_ERROR_OBJECT (qtdemux, "not a playready system id..");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), ("not a valid playready system ID"));
+    goto fail;
+  }
+
+/* Enters into if body when valid system ID is present.*/
+  gst_byte_reader_skip (&uuid_data, 12);
+
+  gst_byte_reader_get_uint16_le (&uuid_data, &protection_header_size);
+
+  GST_DEBUG_OBJECT(qtdemux,"protection header size: %d ", protection_header_size);
+
+  if (!gst_byte_reader_dup_data(&uuid_data, protection_header_size , &protection_header_data)) {
+    GST_ERROR_OBJECT (qtdemux, "failed to duplicate bytereader data...");
+    GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+    goto fail;
+  }
+/* for adding wchar null check */
+  protection_header_size = protection_header_size + 2;
+
+  protection_header_data = (guint8 *) realloc (protection_header_data,protection_header_size);
+  if (!protection_header_data) {
+    GST_ERROR_OBJECT (qtdemux, "failed to allocate memory...");
+    GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+    goto fail;
+  }
+
+/* adding wchar null character */
+  protection_header_data[protection_header_size-2] = '\0';
+  protection_header_data[protection_header_size-1] = '\0';
+
+  GST_DEBUG_OBJECT(qtdemux,"protection header size: %d ", protection_header_size);
+
+  struct_drm.license_file_path = (gchar*)calloc((QTDEMUX_DRM_WORD_SIZE + 32 + protection_header_size), sizeof(gchar));
+  if(struct_drm.license_file_path == NULL) {
+    GST_ERROR_OBJECT (qtdemux, "failed to allocate memory...");
+    GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+    goto fail;
+  }
+
+  strcpy(struct_drm.license_file_path, "ismv");
+
+  struct_drm.license_file_path[4] = '?';
+  for(i = 0; i < 16; i++) {
+    sprintf(struct_drm.license_file_path + 4 + 1 + (i*2), "%02x", qtdemux->uuid_protection[i]);
+  }
+
+  for(i = 0; i < 8; i++) {
+    struct_drm.license_file_path[(QTDEMUX_DRM_WORD_SIZE - 13 ) + i] = '0';
+  }
+
+  for(i = 0; i < 16; i++) {
+    sprintf(struct_drm.license_file_path + (QTDEMUX_DRM_WORD_SIZE -5 ) + (i*2), "%02x", qtdemux->uuid_playready[i]);
+  }
+
+  struct_drm.license_file_path[(QTDEMUX_DRM_WORD_SIZE -5 ) + 32] = '?';
+  len_protection_header = sprintf(struct_drm.license_file_path + (QTDEMUX_DRM_WORD_SIZE -5 ) + 32 + 1 , "%d", protection_header_size);
+  GST_DEBUG_OBJECT(qtdemux, "protection header size length %d", len_protection_header);
+
+  for(i = 0; i < protection_header_size; i++) {
+    struct_drm.license_file_path[(QTDEMUX_DRM_WORD_SIZE -5 ) + 32 + 1 + len_protection_header + i] = protection_header_data[i];
+  }
+
+  GST_DEBUG_OBJECT(qtdemux, "ismv header is %s", struct_drm.license_file_path);
+
+  ret = drm_is_drm_file(struct_drm.license_file_path, &struct_drm.is_drm_file);
+  if(DRM_RETURN_SUCCESS != ret) {
+    GST_ERROR_OBJECT (qtdemux, "Failed to read is DRM_FILE information");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("Failed to read is DRM_FILE information"), (NULL));
+    goto fail;
+  }
+
+  GST_DEBUG_OBJECT(qtdemux, "is drm is drm %d", struct_drm.is_drm_file);
+
+
+  struct_drm.status_perm_type = DRM_PERMISSION_TYPE_PLAY;
+  ret = drm_get_license_status (struct_drm.license_file_path, struct_drm.status_perm_type, &struct_drm.license_status);
+
+  if (DRM_RETURN_SUCCESS != ret) {
+    GST_ERROR_OBJECT (qtdemux, "failed to get license status : 0x%x", ret);
+    qtdemux_post_drm_error (qtdemux, DRM_LICENSE_STATUS_UNDEFINED);
+    goto fail;
+  }
+
+  if (DRM_LICENSE_STATUS_VALID != struct_drm.license_status) {
+    GST_ERROR ("DRM license status is not valid, license_status=%d", struct_drm.license_status);
+    qtdemux_post_drm_error (qtdemux, struct_drm.license_status);
+    goto fail;
+  }
+
+  GST_DEBUG_OBJECT (qtdemux, "successfully got the license status..");
+
+
+#ifdef GET_DRM_LICENSE
+  license_ret = qtdemux_get_playready_licence(qtdemux, protection_header_data, protection_header_size);
+  if(!license_ret) {
+    GST_ERROR_OBJECT (qtdemux, "failed to get playready license");
+    goto fail;
+  }
+#endif
+
+  struct_drm.open_input_data.file_type = DRM_TRUSTED_TYPE_PIFF;
+  struct_drm.open_input_data.permission = DRM_TRUSTED_PERMISSION_TYPE_PLAY;
+  struct_drm.open_input_data.operation_callback.callback = test_drm_trusted_operation_cb;
+  struct_drm.open_input_data.lic_header.header = (unsigned char *) protection_header_data;
+  struct_drm.open_input_data.lic_header.header_len = protection_header_size;
+
+/* Open Decrypt Session*/
+  ret = drm_trusted_open_decrypt_session(&struct_drm.open_input_data, &struct_drm.open_output_data, &(qtdemux->pr_handle));
+  if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+    GST_ERROR_OBJECT (qtdemux, "failed to open decrypt session");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("failed to open decrypt session"), (NULL));
+    goto fail;
+  }
+
+/* Before Read, Appropriate state MUST be SET */
+  struct_drm.state_input_data.state = DRM_CONSUMPTION_STARTED;
+  ret = drm_trusted_set_decrypt_state(qtdemux->pr_handle, &struct_drm.state_input_data);
+  if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+    GST_ERROR_OBJECT (qtdemux, "failed to set decrypt state...");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("failed to set decrypt state"), (NULL));
+    goto fail;
+  }
+  qtdemux->encrypt_content = TRUE;
+
+  free(struct_drm.license_file_path);
+  free (protection_header_data);
+  return TRUE;
+fail:
+  if (protection_header_data) {
+    free (protection_header_data);
+  }
 
+  if(struct_drm.license_file_path) {
+    free(struct_drm.license_file_path);
+    struct_drm.license_file_path = NULL;
+  }
+  GST_ERROR_OBJECT(qtdemux,"fail to parse uuid atom in qtdemux_playready_parse_uuid func ");
+  return FALSE;
+}
+#endif
+#endif
 static GstFlowReturn
 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
     GstBuffer ** buf)
@@ -836,13 +1275,35 @@ gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
 
       gst_query_parse_duration (query, &fmt, NULL);
       if (fmt == GST_FORMAT_TIME) {
-        gint64 duration = -1;
+        /* First try to query upstream */
+        res = gst_pad_query_default (pad, query);
+        if (!res) {
+          gint64 duration = -1;
+
+          gst_qtdemux_get_duration (qtdemux, &duration);
+          if (duration > 0) {
+            gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+            res = TRUE;
+          }
+        }
+#ifdef QTDEMUX_MODIFICATION
+        else {
+          gint64 duration = -1;
 
-        gst_qtdemux_get_duration (qtdemux, &duration);
-        if (duration > 0) {
-          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
-          res = TRUE;
+          gst_query_parse_duration(query, &fmt, &duration);
+
+          if (duration <= 0) {
+            gst_qtdemux_get_duration (qtdemux, &duration);
+
+            GST_LOG_OBJECT (pad, "set duration %"G_GUINT64_FORMAT, duration);
+
+            if (duration > 0) {
+              gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+              res = TRUE;
+            }
+          }
         }
+#endif
       }
       break;
     }
@@ -1406,6 +1867,46 @@ no_format:
   }
 }
 
+#ifdef QTDEMUX_MODIFICATION
+static gboolean
+gst_qtdemux_update_moof_offset (GstQTDemux * qtdemux, QtDemuxStream *stream, gint64 desired_offset, guint64 *moof_offset)
+{
+  guint32 idx = 0;
+  QtDemuxTfraTable *tfra_table = stream->tfra_table;
+  QtDemuxTfraEntryInfo *entry = NULL;
+  gboolean found_entry = FALSE;
+  guint64 time = 0;
+
+  entry = &g_array_index (tfra_table->tfra_entries, QtDemuxTfraEntryInfo, idx);
+  *moof_offset = entry->moof_offset;
+
+  for (idx = 0; idx < tfra_table->n_entries; idx++) {
+    entry = &g_array_index (tfra_table->tfra_entries, QtDemuxTfraEntryInfo, idx);
+    if (gst_util_uint64_scale (entry->time, GST_SECOND, stream->timescale) > desired_offset) {
+      GST_INFO_OBJECT (stream->pad, "found moof time greater than desired time...");
+      found_entry = TRUE;
+      break;
+    }
+    *moof_offset = entry->moof_offset;
+    time = entry->time;
+  }
+
+  if (!found_entry) {
+    GST_WARNING_OBJECT (qtdemux, "Did not find entry...tfra table is not complete");
+    *moof_offset = -1;
+    stream->moof_seeked_time = 0;
+    return FALSE;
+  }
+
+  stream->moof_seeked_time = time;
+
+  GST_INFO_OBJECT (stream->pad, "desired moof_offset = %"G_GUINT64_FORMAT" & fragment start time = %"GST_TIME_FORMAT,
+    *moof_offset, gst_util_uint64_scale (time, GST_SECOND, stream->timescale));
+
+  return TRUE;
+}
+#endif
+
 /* perform the seek.
  *
  * We set all segment_indexes in the streams to unknown and
@@ -1427,6 +1928,10 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
 {
   gint64 desired_offset;
   gint n;
+#ifdef QTDEMUX_MODIFICATION
+  guint64 min_moof_offset = -1;
+  gboolean bret = TRUE;
+#endif
 
   desired_offset = segment->last_stop;
 
@@ -1464,6 +1969,52 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
   segment->last_stop = desired_offset;
   segment->time = desired_offset;
 
+#ifdef QTDEMUX_MODIFICATION
+  if (qtdemux->fragmented) {
+    QtDemuxTfraEntryInfo *entry = NULL;
+    gint count = 0;
+
+    for (n = 0; n < qtdemux->n_streams; n++) {
+      QtDemuxStream *stream = qtdemux->streams[n];
+      guint64 cur_moof_offset = 0;
+
+      if (stream->tfra_table && bret) {
+        /* all streams' tfra should be complete.. otherwise ignore seeking using tfra/mfra */
+        bret = gst_qtdemux_update_moof_offset (qtdemux, stream, desired_offset, &cur_moof_offset);
+        count++;
+        if (!bret) {
+          min_moof_offset = -1;
+          break;
+        }
+        min_moof_offset = min_moof_offset < cur_moof_offset ? min_moof_offset : cur_moof_offset;
+        GST_INFO_OBJECT (qtdemux, "min moof offset = %"G_GUINT64_FORMAT, min_moof_offset < cur_moof_offset ? min_moof_offset : cur_moof_offset);
+      }
+    }
+
+    if (min_moof_offset != -1 && (count == qtdemux->n_streams)) {
+      GST_INFO_OBJECT (qtdemux, "updated moof_offset = %" G_GUINT64_FORMAT, min_moof_offset);
+      for (n = 0; n < qtdemux->moof_offsets->len; n++) {
+        entry = &g_array_index (qtdemux->moof_offsets, QtDemuxTfraEntryInfo, n);
+        if (entry->moof_offset == min_moof_offset)
+          break;
+      }
+      GST_INFO_OBJECT (qtdemux, "updated moof index = %d", n);
+      qtdemux->moof_offset = qtdemux->offset = min_moof_offset;
+      qtdemux->need_moof_parsing = TRUE;
+
+      GST_INFO_OBJECT (qtdemux, "after seek : offset = %" G_GUINT64_FORMAT, min_moof_offset);
+
+      /*reset sample table */
+      for (n = 0; n < qtdemux->n_streams; n++) {
+        QtDemuxStream *stream = qtdemux->streams[n];
+        g_free(stream->samples);
+        stream->n_samples = 0;
+        stream->stbl_index = -1;
+      }
+    }
+  }
+#endif
+
   /* we stop at the end */
   if (segment->stop == -1)
     segment->stop = segment->duration;
@@ -1479,7 +2030,7 @@ gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
   GstFormat format;
   GstSeekFlags flags;
   GstSeekType cur_type, stop_type;
-  gint64 cur, stop;
+  gint64 cur = 0, stop;
   gboolean flush;
   gboolean update;
   GstSegment seeksegment;
@@ -1657,8 +2208,11 @@ gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event)
     }
       if (qtdemux->pullbased) {
         res = gst_qtdemux_do_seek (qtdemux, pad, event);
-      } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams &&
-          !qtdemux->fragmented) {
+      } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
+        GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
+        res = TRUE;
+      } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
+          && !qtdemux->fragmented) {
         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
       } else {
         GST_DEBUG_OBJECT (qtdemux,
@@ -1763,6 +2317,178 @@ gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
   if (_index)
     *_index = index;
 }
+#ifdef QTDEMUX_MODIFICATION
+static void
+gst_qtdemux_reset(GstQTDemux *qtdemux, gboolean hard)
+{
+  gint n;
+  gint ret;
+
+  qtdemux->offset = 0;
+  gst_adapter_clear (qtdemux->adapter);
+  qtdemux->neededbytes = -1;
+
+  if(hard || qtdemux->is_dash)
+  {
+    qtdemux->state = QTDEMUX_STATE_INITIAL;
+    qtdemux->neededbytes = 16;
+    qtdemux->todrop = 0;
+    qtdemux->pullbased = FALSE;
+    qtdemux->posted_redirect = FALSE;
+    qtdemux->first_mdat = -1;
+    qtdemux->header_size = 0;
+    qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
+    if (qtdemux->mdatbuffer)
+      gst_buffer_unref (qtdemux->mdatbuffer);
+    qtdemux->mdatbuffer = NULL;
+    if (qtdemux->comp_brands)
+      gst_buffer_unref (qtdemux->comp_brands);
+    qtdemux->comp_brands = NULL;
+    if (qtdemux->tag_list)
+      gst_tag_list_free (qtdemux->tag_list);
+    qtdemux->tag_list = NULL;
+    gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
+    qtdemux->requested_seek_time = GST_CLOCK_TIME_NONE;
+    qtdemux->seek_offset = 0;
+    qtdemux->upstream_seekable = FALSE;
+    qtdemux->upstream_size = 0;
+    qtdemux->dash_init_offset = GST_CLOCK_TIME_NONE;
+  }
+
+  if(hard)
+  {
+    for (n = 0; n < qtdemux->n_streams; n++) {
+      gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
+      qtdemux->streams[n] = NULL;
+    }
+
+    qtdemux->got_moov = FALSE;
+    qtdemux->major_brand = 0;
+    qtdemux->n_streams = 0;
+    qtdemux->n_video_streams = 0;
+    qtdemux->n_audio_streams = 0;
+    qtdemux->n_sub_streams = 0;
+    qtdemux->is_dash = FALSE;
+    qtdemux->video_max_width = 0;
+    qtdemux->video_max_height = 0;
+
+    if (qtdemux->element_index)
+      gst_object_unref (qtdemux->element_index);
+    qtdemux->element_index = NULL;
+    // TODO: Check new modifications
+    if (qtdemux->file) {
+      fclose (qtdemux->file);
+      if (qtdemux->ofile)
+        fclose (qtdemux->ofile);
+      if(!remove (qtdemux->filename)) GST_DEBUG_OBJECT (qtdemux, "Error removing temp file");
+    }
+    qtdemux->file = NULL;
+    qtdemux->ofile = NULL;
+    qtdemux->filesize = 0;
+    qtdemux->maxbuffersize = QTDEMUX_MAX_BUFFER_SIZE;
+#ifdef DRM_ENABLE
+    if (qtdemux->pr_handle) {
+      if (!drm_trusted_close_decrypt_session(&qtdemux->pr_handle)) {
+        GST_ERROR_OBJECT (qtdemux, "failed to close decrypt session...");
+      }
+    }
+
+    ret = drm_process_request(DRM_REQUEST_TYPE_CLIENT_CLEAN_UP, NULL, NULL);
+    if (DRM_RETURN_SUCCESS == ret) {
+      GST_INFO_OBJECT(qtdemux, "Clean Up successful!!");
+    } else {
+      GST_ERROR_OBJECT (qtdemux, "Clean Up Failed!!, ret = 0x%x", ret);
+    }
+
+    ret = drm_trusted_handle_request(DRM_TRUSTED_REQ_TYPE_CLIENT_CLEAN_UP, NULL, NULL);
+    if (DRM_RETURN_SUCCESS == ret) {
+      GST_INFO_OBJECT(qtdemux, "Clean Up successful!!");
+    } else {
+      GST_ERROR_OBJECT (qtdemux, "Clean Up Failed!!, ret = 0x%x", ret);
+    }
+
+    qtdemux->encrypt_content = FALSE;
+#endif
+#ifdef MULTI_AUDIO
+    if(qtdemux->Language_list)
+    {
+      g_list_free(qtdemux->Language_list);
+      qtdemux->Language_list = NULL;
+    }
+#endif
+
+    if (qtdemux->Subtitle_language_list) {
+      g_list_free (qtdemux->Subtitle_language_list);
+      qtdemux->Subtitle_language_list = NULL;
+    }
+
+    if(qtdemux->sub_sample_count) {
+      g_free(qtdemux->sub_sample_count);
+      qtdemux->sub_sample_count = NULL;
+    }
+    if(qtdemux->clear_data) {
+      g_free(qtdemux->clear_data);
+      qtdemux->clear_data = NULL;
+    }
+    if(qtdemux->encrypted_data) {
+      g_free(qtdemux->encrypted_data);
+      qtdemux->encrypted_data = NULL;
+    }
+
+    if(qtdemux->iv_data_audio) {
+      for(int i = 0; i < qtdemux->no_of_audio_samples; i++) {
+        g_free(qtdemux->iv_data_audio[i]);
+        qtdemux->iv_data_audio[i] = NULL;
+      }
+      g_free(qtdemux->iv_data_audio);
+      qtdemux->iv_data_audio = NULL;
+    }
+
+    if(qtdemux->iv_data_video) {
+      for(int i = 0; i < qtdemux->no_of_video_samples; i++) {
+        g_free(qtdemux->iv_data_video[i]);
+        qtdemux->iv_data_video[i] = NULL;
+      }
+      g_free(qtdemux->iv_data_video);
+      qtdemux->iv_data_video = NULL;
+    }
+  }else if(qtdemux->is_dash){
+    for (n = 0; n < qtdemux->n_streams; n++) {
+      gst_qtdemux_stream_clear(qtdemux,qtdemux->streams[n]);
+      qtdemux->streams[n]->dash_seek_offset = GST_CLOCK_TIME_NONE;
+    }
+  }else{
+    for (n = 0; n < qtdemux->n_streams; n++) {
+      qtdemux->streams[n]->last_ret = GST_FLOW_OK;
+      qtdemux->streams[n]->sent_eos = FALSE;
+    }
+  }
+}
+
+static gboolean
+gst_qtdemux_sink_setcaps (GstPad * pad, GstCaps *caps)
+{
+  const gchar *variant;
+  GstStructure *structure;
+  GstQTDemux *demux = GST_QTDEMUX_CAST (gst_pad_get_element_private(pad));
+
+  structure = gst_caps_get_structure (caps, 0);
+  variant = gst_structure_get_string (structure, "variant");
+  if(variant && strcmp (variant,"dash-fragmented") == 0) {
+    demux->is_dash = TRUE;
+    demux->fragmented = TRUE;
+  }
+
+  if (gst_structure_has_field(structure, "max-width")
+      && gst_structure_has_field(structure, "max-height"))
+  {
+    gst_structure_get_int(structure, "max-width", &demux->video_max_width);
+    gst_structure_get_int(structure, "max-height", &demux->video_max_height);
+  }
+
+  return gst_pad_set_caps (pad, caps);
+}
+#endif
 
 static gboolean
 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
@@ -1793,6 +2519,31 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
           "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
           &segment);
 
+#ifdef QTDEMUX_MODIFICATION
+      /*Processing event from dashdemux after seeking.*/
+      if(demux->is_dash && format == GST_FORMAT_TIME)
+      {
+        int i;
+        demux->dash_init_offset = start;
+
+        /* allows seek for multiple streams */
+        for (i = 0; i < demux->n_streams; i++) {
+            demux->streams[i]->dash_seek_offset = start;
+        }
+
+        gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,
+            GST_FORMAT_TIME, start, stop, start);
+        GST_DEBUG_OBJECT (demux, "Pushing newseg update %d, rate %g, "
+            "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "
+            "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,
+            GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+        gst_qtdemux_push_event (demux,
+            gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME,
+                start, stop, start));
+        goto exit;
+      }
+#endif
+
       /* chain will send initial newsegment after pads have been added */
       if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
         GST_DEBUG_OBJECT (demux, "still starting, eating event");
@@ -1867,6 +2618,9 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
     }
     case GST_EVENT_FLUSH_STOP:
     {
+#ifdef QTDEMUX_MODIFICATION
+      gst_qtdemux_reset(demux,FALSE);
+#else
       gint i;
 
       /* clean up, force EOS if no more info follows */
@@ -1878,6 +2632,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
         demux->streams[i]->last_ret = GST_FLOW_OK;
         demux->streams[i]->sent_eos = FALSE;
       }
+#endif
       break;
     }
     case GST_EVENT_EOS:
@@ -1886,6 +2641,23 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
       if (!demux->pullbased) {
         gint i;
         gboolean has_valid_stream = FALSE;
+
+#ifdef QTDEMUX_MODIFICATION
+            if (demux->piff_fragmented) {
+              GstBuffer *pop_buf = NULL;
+              GstFlowReturn fret = GST_FLOW_OK;
+
+              for (i = 0; i < demux->n_streams; i++) {
+                if (demux->streams[i]->pad != NULL) {
+                  while (!g_queue_is_empty (demux->streams[i]->frag_queue)) {
+                    pop_buf = g_queue_pop_head (demux->streams[i]->frag_queue);
+                    fret = gst_pad_push (demux->streams[i]->pad, pop_buf);
+                    GST_DEBUG_OBJECT (demux->streams[i]->pad, "pushing from event_func : %s\n", gst_flow_get_name (fret));
+                  }
+                }
+              }
+            }
+#endif
         for (i = 0; i < demux->n_streams; i++) {
           if (demux->streams[i]->pad != NULL) {
             has_valid_stream = TRUE;
@@ -1942,7 +2714,367 @@ gst_qtdemux_get_index (GstElement * element)
 
   return result;
 }
-
+#ifdef QTDEMUX_MODIFICATION
+static void
+mpeg4_util_par_from_info (guint8 aspect_ratio_info, guint8 * par_width,
+    guint8 * par_height)
+{
+  switch (aspect_ratio_info) {
+    case 0x02:
+      *par_width = 12;
+      *par_height = 11;
+      break;
+    case 0x03:
+      *par_width = 10;
+      *par_height = 11;
+      break;
+    case 0x04:
+      *par_width = 16;
+      *par_height = 11;
+      break;
+    case 0x05:
+      *par_width = 40;
+      *par_height = 33;
+      break;
+
+    case 0x01:
+    default:
+      *par_width = 1;
+      *par_height = 1;
+  }
+}
+
+static gboolean
+parse_quant (GstBitReader * br, guint8 quant_mat[64],
+    const guint8 default_quant_mat[64], guint8 * load_quant_mat)
+{
+  READ_UINT8 (br, *load_quant_mat, 1);
+  if (*load_quant_mat) {
+    guint i;
+    guint8 val;
+
+    val = 1;
+    for (i = 0; i < 64; i++) {
+
+      if (val != 0)
+        READ_UINT8 (br, val, 8);
+
+      if (val == 0) {
+        if (i == 0)
+          goto invalid_quant_mat;
+        quant_mat[mpeg4_zigzag_8x8[i]] = quant_mat[mpeg4_zigzag_8x8[i - 1]];
+      } else
+        quant_mat[mpeg4_zigzag_8x8[i]] = val;
+    }
+  } else
+    memcpy (quant_mat, default_quant_mat, 64);
+
+  return TRUE;
+
+failed:
+  GST_WARNING ("failed parsing quant matrix");
+  return FALSE;
+
+invalid_quant_mat:
+  GST_WARNING ("the first value should be non zero");
+  goto failed;
+}
+static GstMpeg4ParseResult gst_mpeg4_parse_video_object_layer (GstMpeg4VideoObjectLayer * vol,
+    GstMpeg4VisualObject * vo, const guint8 * data, gsize size)
+{
+  guint8 video_object_layer_start_code;
+  /* Used for enums types */
+  guint8 tmp;
+  GstBitReader br = GST_BIT_READER_INIT (data, size);
+
+  g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR);
+
+  GST_DEBUG ("Parsing video object layer");
+
+  READ_UINT8 (&br, video_object_layer_start_code, 8);
+  if (!(video_object_layer_start_code >= 0x20 &&
+          video_object_layer_start_code <= 0x2f))
+    goto wrong_start_code;
+
+  /* set default values */
+  if (vo) {
+    vol->verid = vo->verid;
+    vol->priority = vo->priority;
+  }
+
+  vol->low_delay = FALSE;
+  vol->chroma_format = 1;
+  vol->vbv_parameters = FALSE;
+  vol->quant_precision = 5;
+  vol->bits_per_pixel = 8;
+  vol->quarter_sample = FALSE;
+  vol->newpred_enable = FALSE;
+  vol->interlaced = 0;
+  vol->width = 0;
+  vol->height = 0;
+
+  READ_UINT8 (&br, vol->random_accessible_vol, 1);
+  READ_UINT8 (&br, vol->video_object_type_indication, 8);
+  READ_UINT8 (&br, vol->is_object_layer_identifier, 1);
+  if (vol->is_object_layer_identifier) {
+    READ_UINT8 (&br, vol->verid, 4);
+    READ_UINT8 (&br, vol->priority, 3);
+  }
+
+  READ_UINT8 (&br, tmp, 4);
+  vol->aspect_ratio_info = tmp;
+  if (vol->aspect_ratio_info != GST_MPEG4_EXTENDED_PAR) {
+    mpeg4_util_par_from_info (vol->aspect_ratio_info, &vol->par_width,
+        &vol->par_height);
+
+  } else {
+    gint v;
+
+    READ_UINT8 (&br, vol->par_width, 8);
+    v = vol->par_width;
+    CHECK_ALLOWED (v, 1, 255);
+
+    READ_UINT8 (&br, vol->par_height, 8);
+    v = vol->par_height;
+    CHECK_ALLOWED (v, 1, 255);
+  }
+  READ_UINT8 (&br, vol->control_parameters, 1);
+  if (vol->control_parameters) {
+    guint8 chroma_format;
+
+    READ_UINT8 (&br, chroma_format, 2);
+    vol->chroma_format = chroma_format;
+    READ_UINT8 (&br, vol->low_delay, 1);
+    READ_UINT8 (&br, vol->vbv_parameters, 1);
+    if (vol->vbv_parameters) {
+      CHECK_REMAINING (&br, 79);
+
+      vol->first_half_bitrate =
+          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
+      MARKER_UNCHECKED (&br);
+
+      vol->latter_half_bitrate =
+          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
+      MARKER_UNCHECKED (&br);
+
+      vol->bit_rate =
+          (vol->first_half_bitrate << 15) | vol->latter_half_bitrate;
+
+      vol->first_half_vbv_buffer_size =
+          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
+      GST_ERROR("reading the vol->first_half_vbv_buffer_size 15 bit = %x",vol->first_half_vbv_buffer_size);
+      MARKER_UNCHECKED (&br);
+
+      vol->latter_half_vbv_buffer_size =
+          gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
+      MARKER_UNCHECKED (&br);
+
+      vol->vbv_buffer_size = (vol->first_half_vbv_buffer_size << 15) |
+          vol->latter_half_vbv_buffer_size;
+
+      vol->first_half_vbv_occupancy =
+          gst_bit_reader_get_bits_uint16_unchecked (&br, 11);
+      MARKER_UNCHECKED (&br);
+
+      vol->latter_half_vbv_occupancy =
+          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
+      MARKER_UNCHECKED (&br);
+    }
+  }
+
+  READ_UINT8 (&br, tmp, 2);
+  vol->shape = tmp;
+
+  if (vol->shape == GST_MPEG4_GRAYSCALE) {
+    /* TODO support grayscale shapes, for now we just pass */
+
+    /* Something the standard starts to define... */
+    GST_ERROR ("Grayscale shaped not supported");
+    goto failed;
+  }
+
+  if (vol->shape == GST_MPEG4_GRAYSCALE && vol->verid != 0x01)
+    READ_UINT8 (&br, vol->shape_extension, 4);
+  CHECK_REMAINING (&br, 19);
+
+  MARKER_UNCHECKED (&br);
+  vol->vop_time_increment_resolution =
+      gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
+  if (vol->vop_time_increment_resolution < 1) {
+    GST_ERROR ("value not in allowed range. value: %d, range %d-%d",
+        vol->vop_time_increment_resolution, 1, G_MAXUINT16);
+    goto failed;
+  }
+  vol->vop_time_increment_bits =
+      g_bit_storage (vol->vop_time_increment_resolution);
+  MARKER_UNCHECKED (&br);
+  vol->fixed_vop_rate = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+  if (vol->fixed_vop_rate)
+    READ_UINT16 (&br, vol->fixed_vop_time_increment,
+        vol->vop_time_increment_bits);
+
+  if (vol->shape != GST_MPEG4_BINARY_ONLY) {
+    if (vol->shape == GST_MPEG4_RECTANGULAR) {
+      CHECK_REMAINING (&br, 29);
+
+      MARKER_UNCHECKED (&br);
+      vol->width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
+      MARKER_UNCHECKED (&br);
+      vol->height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
+      MARKER_UNCHECKED (&br);
+    }
+
+    READ_UINT8 (&br, vol->interlaced, 1);
+    READ_UINT8 (&br, vol->obmc_disable, 1);
+
+    if (vol->verid == 0x1) {
+      READ_UINT8 (&br, tmp, 1);
+      vol->sprite_enable = tmp;
+    } else {
+    READ_UINT8 (&br, tmp, 2);
+    vol->sprite_enable = tmp;
+    }
+    if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC ||
+        vol->sprite_enable == GST_MPEG4_SPRITE_GMG) {
+
+      if (vol->sprite_enable == GST_MPEG4_SPRITE_GMG)
+        CHECK_REMAINING (&br, 9);
+      else {
+        CHECK_REMAINING (&br, 65);
+
+        vol->sprite_width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
+        MARKER_UNCHECKED (&br);
+        vol->sprite_height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
+        MARKER_UNCHECKED (&br);
+
+        vol->sprite_left_coordinate =
+            gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
+        MARKER_UNCHECKED (&br);
+
+        vol->sprite_top_coordinate =
+            gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
+        MARKER_UNCHECKED (&br);
+      }
+      vol->no_of_sprite_warping_points =
+          gst_bit_reader_get_bits_uint8_unchecked (&br, 6);
+      vol->sprite_warping_accuracy =
+          gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
+      vol->sprite_brightness_change =
+          gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+      if (vol->sprite_enable != GST_MPEG4_SPRITE_GMG) {
+        vol->low_latency_sprite_enable =
+        gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+      }
+    }
+
+    if (vol->shape != GST_MPEG4_RECTANGULAR) {
+      READ_UINT8 (&br, vol->sadct_disable, 1);
+    }
+    READ_UINT8 (&br, vol->not_8_bit, 1);
+    if (vol->not_8_bit) {
+      READ_UINT8 (&br, vol->quant_precision, 4);
+      CHECK_ALLOWED (vol->quant_precision, 3, 9);
+      READ_UINT8 (&br, vol->bits_per_pixel, 4);
+      CHECK_ALLOWED (vol->bits_per_pixel, 4, 12);
+    }
+
+    if (vol->shape == GST_MPEG4_GRAYSCALE) {
+      /* We don't actually support it */
+      READ_UINT8 (&br, vol->no_gray_quant_update, 1);
+      READ_UINT8 (&br, vol->composition_method, 1);
+      READ_UINT8 (&br, vol->linear_composition, 1);
+    }
+
+    READ_UINT8 (&br, vol->quant_type, 1);
+    if (vol->quant_type) {
+      if (!parse_quant (&br, vol->intra_quant_mat, default_intra_quant_mat,
+              &vol->load_intra_quant_mat))
+        goto failed;
+
+      if (!parse_quant (&br, vol->non_intra_quant_mat,
+              default_non_intra_quant_mat, &vol->load_non_intra_quant_mat))
+        goto failed;
+
+      if (vol->shape == GST_MPEG4_GRAYSCALE) {
+        /* Something the standard starts to define... */
+        GST_ERROR ("Grayscale shaped not supported");
+        goto failed;
+      }
+
+    } else {
+      memset (&vol->intra_quant_mat, 0, 64);
+      memset (&vol->non_intra_quant_mat, 0, 64);
+    }
+
+    if (vol->verid != 0x1)
+      READ_UINT8 (&br, vol->quarter_sample, 1);
+
+    READ_UINT8 (&br, vol->complexity_estimation_disable, 1);
+    if (!vol->complexity_estimation_disable)
+      goto complexity_estimation_error;
+
+
+    READ_UINT8 (&br, vol->resync_marker_disable, 1);
+    READ_UINT8 (&br, vol->data_partitioned, 1);
+    GST_DEBUG("reading vol->data_partitioned 1 bit = %x ",vol->data_partitioned);
+    if (vol->data_partitioned)
+    {
+      READ_UINT8 (&br, vol->reversible_vlc, 1);
+    }
+  }
+  /* ... */
+
+  return GST_MPEG4_PARSER_OK;
+
+failed:
+  GST_ERROR ("failed parsing \"Video Object Layer\"");
+  return GST_MPEG4_PARSER_ERROR;
+
+wrong_start_code:
+  GST_ERROR ("got buffer with wrong start code");
+  goto failed;
+
+complexity_estimation_error:
+  GST_ERROR ("don't support complexity estimation");
+         goto failed;
+}
+static GstMpeg4ParseResult
+gst_mpeg4_parse_visual_object (GstMpeg4VisualObject * vo, const guint8 * data, gsize size)
+{
+  guint8 vo_start_code, type;
+  GstBitReader br = GST_BIT_READER_INIT (data, size);
+
+  g_return_val_if_fail (vo != NULL, GST_MPEG4_PARSER_ERROR);
+
+  GST_DEBUG ("Parsing visual object");
+
+  READ_UINT8 (&br, vo_start_code, 8);
+  if (vo_start_code != 0xb5)
+    goto wrong_start_code;
+
+  /* set default values */
+  vo->verid = 0x1;
+  vo->priority = 1;
+  READ_UINT8 (&br, vo->is_identifier, 1);
+  if (vo->is_identifier) {
+    READ_UINT8 (&br, vo->verid, 4);
+    READ_UINT8 (&br, vo->priority, 3);
+  }
+
+  READ_UINT8 (&br, type, 4);
+  vo->type = type;
+  return GST_MPEG4_PARSER_OK;
+
+wrong_start_code:
+  GST_ERROR ("got buffer with wrong start code");
+  return GST_MPEG4_PARSER_ERROR;
+
+failed:
+  GST_ERROR ("failed parsing \"Visual Object\"");
+  return GST_MPEG4_PARSER_ERROR;
+}
+#endif
+
 static void
 gst_qtdemux_stbl_free (QtDemuxStream * stream)
 {
@@ -1956,34 +3088,115 @@ gst_qtdemux_stbl_free (QtDemuxStream * stream)
   stream->stts.data = NULL;
   g_free ((gpointer) stream->stss.data);
   stream->stss.data = NULL;
-  g_free ((gpointer) stream->stps.data);
-  stream->stps.data = NULL;
   g_free ((gpointer) stream->ctts.data);
   stream->ctts.data = NULL;
 }
 
+#ifdef QTDEMUX_MODIFICATION
 static void
-gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
+gst_qtdemux_stream_clear (GstQTDemux *qtdemux, QtDemuxStream *stream)
 {
   while (stream->buffers) {
     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
   }
-  if (stream->pad)
-    gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
+
+#ifdef DRM_ENABLE
+  if (qtdemux->encrypt_content && qtdemux->dash_content == FALSE) {
+    int i =0;
+
+    for (i = 0 ; i < stream->n_samples; i++) {
+      if (stream->samples[i].sub_encry) {
+        if (stream->samples[i].sub_encry->sub_entry) {
+          g_free (stream->samples[i].sub_encry->sub_entry);
+          stream->samples[i].sub_encry->sub_entry = NULL;
+        }
+        free (stream->samples[i].sub_encry);
+        stream->samples[i].sub_encry = NULL;
+      }
+      free(stream->samples[i].iv);
+      stream->samples[i].iv = NULL;
+    }
+  }
+#endif
+
+  if (qtdemux->piff_fragmented && stream->frag_queue) {
+    while (!g_queue_is_empty (stream->frag_queue)) {
+      GstBuffer *buf = g_queue_pop_head (stream->frag_queue);
+      gst_buffer_unref (buf);
+    }
+  }
+
   g_free (stream->samples);
-  if (stream->caps)
-    gst_caps_unref (stream->caps);
+  stream->samples = NULL;
   g_free (stream->segments);
+  stream->segments = NULL;
+
   if (stream->pending_tags)
     gst_tag_list_free (stream->pending_tags);
+  stream->pending_tags = NULL;
   g_free (stream->redirect_uri);
+  stream->redirect_uri = NULL;
   /* free stbl sub-atoms */
   gst_qtdemux_stbl_free (stream);
-#ifdef QTDEMUX_MODIFICATION
+
   if (stream->trickplay_info)
     g_free (stream->trickplay_info);
+  stream->trickplay_info = NULL;
+
+  stream->last_ret = GST_FLOW_OK;
+  stream->sent_eos = FALSE;
+  stream->segment_index = -1;
+  stream->time_position = 0;
+  stream->sample_index = -1;
+  stream->stbl_index = -1;
+  stream->n_samples = 0;
+}
+#endif
+
+static void
+gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
+{
+#ifdef QTDEMUX_MODIFICATION
+  gst_qtdemux_stream_clear(qtdemux, stream);
+
+  if (qtdemux->piff_fragmented && stream->frag_queue) {
+    g_queue_free (stream->frag_queue);
+    stream->frag_queue = NULL;
+  }
+#else
+  while (stream->buffers) {
+    gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
+    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
+  }
+
+  g_free (stream->samples);
+  stream->samples = NULL;
+  g_free (stream->segments);
+  stream->segments = NULL;
+
+  if (stream->pending_tags)
+    gst_tag_list_free (stream->pending_tags);
+  stream->pending_tags = NULL;
+  g_free (stream->redirect_uri);
+  stream->redirect_uri = NULL;
+  /* free stbl sub-atoms */
+  gst_qtdemux_stbl_free (stream);
+
+  stream->last_ret = GST_FLOW_OK;
+  stream->sent_eos = FALSE;
+  stream->segment_index = -1;
+  stream->time_position = 0;
+  stream->sample_index = -1;
+  stream->stbl_index = -1;
+  stream->n_samples = 0;
 #endif
+
+  if (stream->caps)
+    gst_caps_unref (stream->caps);
+  if (stream->pad)
+    gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
+
   g_free (stream);
 }
 
@@ -2004,6 +3217,9 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:{
+#ifdef QTDEMUX_MODIFICATION
+      gst_qtdemux_reset(qtdemux,TRUE);
+#else
       gint n;
 
       qtdemux->state = QTDEMUX_STATE_INITIAL;
@@ -2016,6 +3232,13 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
       qtdemux->header_size = 0;
       qtdemux->got_moov = FALSE;
       qtdemux->mdatoffset = GST_CLOCK_TIME_NONE;
+#ifdef MULTI_AUDIO
+      if(qtdemux->Language_list)
+      {
+        g_list_free(qtdemux->Language_list);
+        qtdemux->Language_list = NULL;
+      }
+#endif
       if (qtdemux->mdatbuffer)
         gst_buffer_unref (qtdemux->mdatbuffer);
       qtdemux->mdatbuffer = NULL;
@@ -2029,19 +3252,7 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
         gst_object_unref (qtdemux->element_index);
       qtdemux->element_index = NULL;
       gst_adapter_clear (qtdemux->adapter);
-#ifdef QTDEMUX_MODIFICATION
-     // TODO: Check new modifications
-      if (qtdemux->file) {
-        fclose (qtdemux->file);
-        if (qtdemux->ofile)
-          fclose (qtdemux->ofile);
-        remove (qtdemux->filename);
-      }
-      qtdemux->file = NULL;
-      qtdemux->ofile = NULL;
-      qtdemux->filesize = 0;
-      qtdemux->maxbuffersize = QTDEMUX_MAX_BUFFER_SIZE;
-#endif
+
       for (n = 0; n < qtdemux->n_streams; n++) {
         gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
         qtdemux->streams[n] = NULL;
@@ -2056,6 +3267,7 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
       qtdemux->seek_offset = 0;
       qtdemux->upstream_seekable = FALSE;
       qtdemux->upstream_size = 0;
+#endif
       break;
     }
     default:
@@ -2092,8 +3304,26 @@ qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
     qtdemux->major_brand = QT_FOURCC (buffer + 8);
     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
         GST_FOURCC_ARGS (qtdemux->major_brand));
+
+#ifdef QTDEMUX_MODIFICATION
+    /* checking for piff major brand */
+    if (qtdemux->major_brand == GST_MAKE_FOURCC ('i', 's', 'm', 'l') ||
+        qtdemux->major_brand == GST_MAKE_FOURCC ('p', 'i', 'f', 'f')) {
+        GST_INFO_OBJECT (qtdemux, "clip has PIFF as major brand");
+        qtdemux->piff_fragmented = TRUE;
+    }
+#endif
+
     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
     memcpy (GST_BUFFER_DATA (buf), buffer + 16, GST_BUFFER_SIZE (buf));
+
+#ifdef QTDEMUX_MODIFICATION
+    /* checking for piff major brand */
+    if (g_strrstr_len (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), "piff")) {
+        GST_INFO_OBJECT (qtdemux, "clip has PIFF as compatible brand");
+        qtdemux->piff_fragmented = TRUE;
+    }
+#endif
   }
 }
 
@@ -2297,6 +3527,8 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
       stream->track_id, d_sample_duration, d_sample_size, d_sample_flags,
       *base_offset);
 
+  qtdemux->sequence_id = stream->track_id;
+  GST_DEBUG("sequence id is %d", qtdemux->sequence_id);
   /* presence of stss or not can't really tell us much,
    * and flags and so on tend to be marginally reliable in these files */
   if (stream->subtype == FOURCC_soun) {
@@ -2321,6 +3553,7 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
     if (*base_offset == -1) {
       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
       *base_offset = moof_offset;
+      ismv=TRUE;/*according to piff specification base_offset should be omitted*/
     }
     *running_offset = *base_offset + data_offset;
   } else {
@@ -2401,9 +3634,21 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
     goto out_of_memory;
 
   if (G_UNLIKELY (stream->n_samples == 0)) {
+#ifdef QTDEMUX_MODIFICATION
+    if(qtdemux->is_dash && GST_CLOCK_TIME_IS_VALID(qtdemux->dash_init_offset))
+      timestamp = gst_util_uint64_scale(qtdemux->dash_init_offset, stream->timescale, GST_SECOND);
+    else if (qtdemux->fragmented) {
+      timestamp = stream->moof_seeked_time;
+    } else {
+     /* the timestamp of the first sample is also provided by the tfra entry
+         * but we shouldnt rely on it as it is at the end of files */
+      timestamp = 0;
+    }
+#else
     /* the timestamp of the first sample is also provided by the tfra entry
      * but we shouldn't rely on it as it is at the end of files */
     timestamp = 0;
+#endif
   } else {
     /* subsequent fragments extend stream */
     timestamp =
@@ -2453,11 +3698,20 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
      * now idea how it relates to bitfield other than massive LE/BE confusion */
     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
+
+    /* For a video track, the first sample in a fragment MUST be an IDR frame(Key frame) according to
+     * PIFF specs (PIFF 1.1, page no. 17) */
+    if (ismv && stream->subtype == FOURCC_vide && i == 0) {
+      sample->keyframe = TRUE;
+    }
+
     *running_offset += size;
     timestamp += dur;
     sample++;
   }
-
+#ifdef QTDEMUX_MODIFICATION
+  stream->prev_n_samples = stream->n_samples;
+#endif
   stream->n_samples += samples_count;
 
   return TRUE;
@@ -2570,67 +3824,387 @@ unknown_stream:
     return TRUE;
   }
 }
-
+#ifdef QTDEMUX_MODIFICATION
 static gboolean
-qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
-    guint64 moof_offset, QtDemuxStream * stream)
+qtdemux_parse_sample_encryption(GstQTDemux * qtdemux, GstByteReader *sample_encrypt, QtDemuxStream * stream)
 {
-  GNode *moof_node, *traf_node, *tfhd_node, *trun_node;
-  GstByteReader trun_data, tfhd_data;
-  guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
-  gint64 base_offset, running_offset;
+  guint32 flags = 0;
+  guint32 sample_count = 0;
+  guint32 i = 0;
+  guint32 algo_id;
+  guint8 iv_size = 0;
+
+  if (!gst_byte_reader_skip (sample_encrypt, 1) ||
+      !gst_byte_reader_get_uint24_be (sample_encrypt, &flags))
+    goto invalid_encryption;
+
+  if (flags & SE_OVERRIDE_TE_FLAGS) {
+    /* get algorithm id */
+    if (!gst_byte_reader_get_uint32_be (sample_encrypt, &algo_id))
+      goto invalid_encryption;
+
+    /* get IV size */
+    if (!gst_byte_reader_get_uint8 (sample_encrypt, &iv_size))
+      goto invalid_encryption;
+
+    GST_DEBUG_OBJECT(qtdemux,"iv is %2x",iv_size);
+    // TODO: need to add reading of KID
+  } else {
+    GST_INFO_OBJECT (qtdemux, "Override flags are not present... taking default IV_Size = 8");
+    iv_size = 8;
+  }
 
-  /* NOTE @stream ignored */
+  /* Get sample count*/
+  if (!gst_byte_reader_get_uint32_be (sample_encrypt, &sample_count))
+    goto invalid_encryption;
 
-  moof_node = g_node_new ((guint8 *) buffer);
-  qtdemux_parse_node (qtdemux, moof_node, buffer, length);
-  qtdemux_node_dump (qtdemux, moof_node);
+  GST_INFO_OBJECT (qtdemux, "Sample count = %d", sample_count);
 
-  /* unknown base_offset to start with */
-  base_offset = running_offset = -1;
-  traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
-  while (traf_node) {
-    /* Fragment Header node */
-    tfhd_node =
-        qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
-        &tfhd_data);
-    if (!tfhd_node)
-      goto missing_tfhd;
-    if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
-            &ds_size, &ds_flags, &base_offset))
-      goto missing_tfhd;
-    if (G_UNLIKELY (!stream)) {
-      /* we lost track of offset, we'll need to regain it,
-       * but can delay complaining until later or avoid doing so altogether */
-      base_offset = -2;
-      goto next;
+#if 0
+  if (sample_count != stream->n_samples) {
+    GST_ERROR_OBJECT (qtdemux, "Not all samples has IV vectors... Don't know how to handle. sample_cnt = %d and stream->n_samples = %d",
+      sample_count, stream->n_samples);
+    goto invalid_encryption;
+  }
+#endif
+
+  for (i = stream->prev_n_samples; i < stream->n_samples; i++) {
+    guint8 iv_idx = iv_size;
+
+    /* resetting entire IV array */
+    stream->samples[i].iv = (guint8 *) malloc (iv_size);
+    if (NULL == stream->samples[i].iv) {
+      GST_ERROR_OBJECT (qtdemux, "Failed to allocate memory...\n");
+      GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+      return FALSE;
     }
-    if (G_UNLIKELY (base_offset < -1))
-      goto lost_offset;
-    /* Track Run node */
-    trun_node =
-        qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
-        &trun_data);
-    while (trun_node) {
-      qtdemux_parse_trun (qtdemux, &trun_data, stream,
-          ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
-          &running_offset);
-      /* iterate all siblings */
-      trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
-          &trun_data);
+    stream->samples[i].sub_encry = NULL;
+    memset (stream->samples[i].iv, 0x00, iv_size);
+
+    iv_idx = 0;
+    while (iv_idx < iv_size) {
+      /* get IV byte */
+      if (!gst_byte_reader_get_uint8 (sample_encrypt, &(stream->samples[i].iv[iv_idx])))
+        goto invalid_encryption;
+
+      iv_idx++;
     }
-    /* if no new base_offset provided for next traf,
-     * base is end of current traf */
-    base_offset = running_offset;
-    running_offset = -1;
-  next:
-    /* iterate all siblings */
-    traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
-  }
-  g_node_destroy (moof_node);
-  return TRUE;
 
-missing_tfhd:
+#ifdef DEBUG_IV
+  {
+    guint8 tmp_idx = 0;
+    g_print ("sample[%d] : 0x ", i);
+
+    while (tmp_idx < iv_size ) {
+      g_print ("%02x ", stream->samples[i].iv[tmp_idx]);
+      tmp_idx++;
+    }
+    g_print ("\n");
+  }
+#endif
+
+    if (flags & SE_USE_SUBSAMPLE_ENCRYPTION) {
+      guint16 n_entries;
+      guint16 n_idx;
+
+      /* NumberofEntries in SubSampleEncryption */
+      if (!gst_byte_reader_get_uint16_be (sample_encrypt, &n_entries))
+        goto invalid_encryption;
+
+      stream->samples[i].sub_encry = (QtDemuxSubSampleEncryption *) malloc (sizeof (QtDemuxSubSampleEncryption));
+      if (NULL == stream->samples[i].sub_encry) {
+        GST_ERROR_OBJECT (qtdemux, "Failed to allocate memory...\n");
+        GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+        return FALSE;
+      }
+
+      stream->samples[i].sub_encry->sub_entry = g_try_new0 (QtDemuxSubSampleEntryInfo, n_entries);
+      if (NULL == stream->samples[i].sub_encry->sub_entry) {
+        GST_ERROR_OBJECT (qtdemux, "Failed to allocate memory...\n");
+        GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+        return FALSE;
+      }
+
+      stream->samples[i].sub_encry->n_entries = n_entries;
+
+      GST_DEBUG_OBJECT (qtdemux,"No. of subsample entries = %d", stream->samples[i].sub_encry->n_entries);
+
+      for (n_idx = 0; n_idx < n_entries; n_idx++) {
+        if (!gst_byte_reader_get_uint16_be (sample_encrypt, &(stream->samples[i].sub_encry->sub_entry[n_idx].LenofClearData)))
+          goto invalid_encryption;
+
+        GST_DEBUG_OBJECT (qtdemux,"entry[%d] and lengthofClearData = %d", n_idx, stream->samples[i].sub_encry->sub_entry[n_idx].LenofClearData);
+
+        if (!gst_byte_reader_get_uint32_be (sample_encrypt, &(stream->samples[i].sub_encry->sub_entry[n_idx].LenofEncryptData)))
+          goto invalid_encryption;
+
+        GST_DEBUG_OBJECT (qtdemux,"entry[%d] and lengthofEncryptData = %d", n_idx, stream->samples[i].sub_encry->sub_entry[n_idx].LenofEncryptData);
+      }
+    }
+  }
+
+  return TRUE;
+
+invalid_encryption:
+  {
+    GST_ERROR_OBJECT (qtdemux, "invalid sample encryption header");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("invalid encryption"), (NULL));
+    return FALSE;
+  }
+}
+#endif
+
+static gboolean
+qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
+    guint64 * decode_time)
+{
+  guint32 version = 0;
+
+  if (!gst_byte_reader_get_uint32_be (br, &version))
+    return FALSE;
+
+  version >>= 24;
+  if (version == 1) {
+    if (!gst_byte_reader_get_uint64_be (br, decode_time))
+      goto failed;
+  } else {
+    guint32 dec_time = 0;
+    if (!gst_byte_reader_get_uint32_be (br, &dec_time))
+      goto failed;
+    *decode_time = dec_time;
+  }
+
+  GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
+      *decode_time);
+
+  return TRUE;
+
+failed:
+  {
+    GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
+    return FALSE;
+  }
+}
+
+static gboolean
+qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
+    guint64 moof_offset, QtDemuxStream * stream)
+{
+  GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *senc_node;
+
+  GstByteReader trun_data, tfhd_data, tfdt_data;
+  guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
+  gint64 base_offset, running_offset;
+#ifdef QTDEMUX_MODIFICATION
+  GNode *uuid_node;
+  GstByteReader uuid_data;
+  gint64 uuid_offset=-1;
+  gboolean bret = FALSE;
+#endif
+  /* NOTE @stream ignored */
+
+  moof_node = g_node_new ((guint8 *) buffer);
+#ifdef QTDEMUX_MODIFICATION
+  GST_DEBUG_OBJECT(qtdemux, "in parse moof");
+  bret = qtdemux_parse_node (qtdemux, moof_node, buffer, length);
+  if(!bret) {
+    GST_ERROR_OBJECT(qtdemux, "failed to parse node object");
+    return bret;
+  }
+#else
+  qtdemux_parse_node (qtdemux, moof_node, buffer, length);
+#endif
+  //qtdemux_node_dump (qtdemux, moof_node);
+
+  /* unknown base_offset to start with */
+  base_offset = running_offset = -1;
+  traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
+  while (traf_node) {
+    /* Fragment Header node */
+         GST_DEBUG("Traf node detected");
+    tfhd_node =
+        qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
+        &tfhd_data);
+    if (!tfhd_node)
+      goto missing_tfhd;
+    else
+      GST_DEBUG("tfhd node detected");
+    if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
+            &ds_size, &ds_flags, &base_offset))
+      goto missing_tfhd;
+    tfdt_node =
+        qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
+        &tfdt_data);
+    if (tfdt_node) {
+      guint64 decode_time = 0;
+      GST_DEBUG("tfdt node detected");
+      qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
+      /* If there is a new segment pending, update the time/position */
+      if (qtdemux->pending_newsegment) {
+        gst_event_replace (&qtdemux->pending_newsegment,
+            gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                0, GST_CLOCK_TIME_NONE,
+                gst_util_uint64_scale (decode_time,
+                    GST_SECOND, stream->timescale)));
+      }
+    }
+
+    if (G_UNLIKELY (!stream)) {
+      /* we lost track of offset, we'll need to regain it,
+       * but can delay complaining until later or avoid doing so altogether */
+      base_offset = -2;
+      goto next;
+    }
+    if (G_UNLIKELY (base_offset < -1))
+      goto lost_offset;
+    /* Track Run node */
+    trun_node =
+        qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
+        &trun_data);
+    while (trun_node) {
+      qtdemux_parse_trun (qtdemux, &trun_data, stream,
+          ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
+          &running_offset);
+      GST_DEBUG("trun node detected");
+      /* iterate all siblings */
+      trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
+          &trun_data);
+    }
+
+#ifdef QTDEMUX_MODIFICATION
+#ifdef DRM_ENABLE
+    uuid_node =  qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
+
+    while (uuid_node) {
+      uuid_type_t uuid_type;
+
+      guint8 *buffer = (guint8 *) uuid_node->data;
+
+      GST_DEBUG_OBJECT(qtdemux, "uuid node detected");
+
+      gst_byte_reader_init (&uuid_data, buffer, QT_UINT32 (buffer));
+
+      uuid_type = qtdemux_get_uuid_type (qtdemux, &uuid_data, &uuid_offset);
+
+      if (UUID_SAMPLE_ENCRYPT == uuid_type) {
+        if (!qtdemux_parse_sample_encryption (qtdemux, &uuid_data, stream))
+          goto fail;
+      } else {
+        GST_WARNING_OBJECT (qtdemux, "Ignoring Wrong UUID...");
+      }
+
+      /* iterate all siblings */
+      uuid_node = qtdemux_tree_get_sibling_by_type (uuid_node, FOURCC_uuid);
+    }
+#endif //DRM_ENABLE
+
+    senc_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_senc);
+    if(senc_node) {
+      guint8 *buffer = (guint8 *) senc_node->data;
+      int i = 0;
+      int j = 0;
+
+      GST_INFO_OBJECT(qtdemux, "senc node detected...");
+      qtdemux->iv_size_video = 8;
+      qtdemux->iv_size_audio = 8;
+
+      /* video stream will have even sequence_id and audio will have odd sequence_id */
+      if(qtdemux->sequence_id%2 == 0) {
+
+        GST_DEBUG_OBJECT(qtdemux, "iv size is %d", qtdemux->iv_size_video);
+
+        qtdemux->sample_count[qtdemux->sequence_id - 1] = QT_UINT32 (buffer + 12);
+        GST_DEBUG("sample count for video is %d", qtdemux->sample_count[qtdemux->sequence_id - 1]);
+
+        qtdemux->iv_data_video = (gchar**)malloc(sizeof(gchar*) * qtdemux->sample_count[qtdemux->sequence_id - 1]);
+        if (NULL == qtdemux->iv_data_video) {
+          GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for iv_data_video...");
+          goto fail;
+        }
+
+        qtdemux->no_of_video_samples = qtdemux->sample_count[qtdemux->sequence_id - 1];
+
+        for(i = 0 ; i < qtdemux->sample_count[qtdemux->sequence_id - 1] ; i++) {
+          qtdemux->iv_data_video[i] = (gchar*)malloc(sizeof(gchar) * qtdemux->iv_size_video);
+          if(NULL == qtdemux->iv_data_video[i]) {
+            GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for iv_data_video index...");
+            goto fail;
+          }
+        }
+
+        qtdemux->sub_sample_count = (gint*)malloc(sizeof(gint) * qtdemux->sample_count[qtdemux->sequence_id - 1]);
+        if (NULL == qtdemux->sub_sample_count) {
+          GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for sub_sample_count...");
+          goto fail;
+        }
+
+        qtdemux->clear_data = (gint*)malloc(sizeof(gint) * qtdemux->sample_count[qtdemux->sequence_id - 1]);
+        if (NULL == qtdemux->clear_data) {
+          GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for clear_data...");
+          goto fail;
+        }
+
+        qtdemux->encrypted_data = (gint*)malloc(sizeof(gint) * qtdemux->sample_count[qtdemux->sequence_id - 1]);
+        if (NULL == qtdemux->encrypted_data) {
+          GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for encrypted_data...");
+          goto fail;
+        }
+
+        for(i = 0 ; i < qtdemux->sample_count[qtdemux->sequence_id - 1] ; i++) {
+          for(j = 0 ; j < qtdemux->iv_size_video ; j++) {
+            qtdemux->iv_data_video[i][j] = buffer[16 + (qtdemux->iv_size_video * i * 2) + j];
+          }
+          qtdemux->sub_sample_count[i] = QT_UINT16 (buffer + 16 + (qtdemux->iv_size_video * i * 2) + qtdemux->iv_size_video);
+          qtdemux->clear_data[i] = QT_UINT16 (buffer + 16 + (qtdemux->iv_size_video * i * 2) + qtdemux->iv_size_video + 2);
+          qtdemux->encrypted_data[i] = QT_UINT32 (buffer + 16 + (qtdemux->iv_size_video * i * 2) + qtdemux->iv_size_video + 2 + 2);
+        }
+        qtdemux->current_sample[0] = 0;
+
+      } else if(qtdemux->sequence_id%2 == 1) {
+
+        GST_DEBUG_OBJECT(qtdemux, "iv size is %d", qtdemux->iv_size_audio);
+
+        qtdemux->sample_count[qtdemux->sequence_id - 1] = QT_UINT32 (buffer + 12);
+
+        GST_INFO_OBJECT(qtdemux, "sample count for audio is %d", qtdemux->sample_count[qtdemux->sequence_id - 1]);
+
+        qtdemux->iv_data_audio = (gchar**)malloc(sizeof(gchar*) * qtdemux->sample_count[qtdemux->sequence_id - 1]);
+        if (NULL == qtdemux->iv_data_audio) {
+          GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for iv_data_audio...");
+          goto fail;
+        }
+
+        qtdemux->no_of_audio_samples = qtdemux->sample_count[qtdemux->sequence_id - 1];
+
+        for(i = 0 ; i < qtdemux->sample_count[qtdemux->sequence_id - 1] ; i++) {
+          qtdemux->iv_data_audio[i] = (gchar*)malloc(sizeof(gchar) * qtdemux->iv_size_audio);
+          if(NULL == qtdemux->iv_data_audio[i]) {
+            GST_ERROR_OBJECT (qtdemux, "failed to allocate memory for iv_data_audio index...");
+            goto fail;
+          }
+        }
+
+        for(i = 0 ; i < qtdemux->sample_count[qtdemux->sequence_id - 1] ; i++) {
+          for(j = 0 ; j < qtdemux->iv_size_audio ; j++) {
+            qtdemux->iv_data_audio[i][j] = buffer[16 + (qtdemux->iv_size_audio * i) + j];
+          }
+        }
+        qtdemux->current_sample[1] = 0;
+      }
+    }
+#endif
+    /* if no new base_offset provided for next traf,
+     * base is end of current traf */
+    base_offset = running_offset;
+    running_offset = -1;
+  next:
+    /* iterate all siblings */
+    traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
+  }
+  g_node_destroy (moof_node);
+  return TRUE;
+
+missing_tfhd:
   {
     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
     goto fail;
@@ -2649,21 +4223,25 @@ fail:
   }
 }
 
+#ifdef QTDEMUX_MODIFICATION
+
 /* might be used if some day we actually use mfra & co
  * for random access to fragments,
  * but that will require quite some modifications and much less relying
  * on a sample array */
-#if 0
 static gboolean
-qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node,
-    QtDemuxStream * stream)
+qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
 {
   guint64 time = 0, moof_offset = 0;
   guint32 ver_flags, track_id, len, num_entries, i;
   guint value_size, traf_size, trun_size, sample_size;
-  GstBuffer *buf = NULL;
-  GstFlowReturn ret;
   GstByteReader tfra;
+  guint n = 0;
+  QtDemuxStream *stream = NULL;
+  gboolean found_track = FALSE;
+  QtDemuxTfraTable *tfra_table = NULL;
+
+  GST_DEBUG_OBJECT (qtdemux, "Starting tfra parsing...");
 
   gst_byte_reader_init (&tfra, (guint8 *) tfra_node->data + (4 + 4),
       QT_UINT32 ((guint8 *) tfra_node->data) - (4 + 4));
@@ -2676,44 +4254,67 @@ qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node,
           gst_byte_reader_get_uint32_be (&tfra, &num_entries)))
     return FALSE;
 
-  GST_LOG_OBJECT (qtdemux, "id %d == stream id %d ?",
-      track_id, stream->track_id);
-  if (track_id != stream->track_id) {
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    stream = qtdemux->streams[n];
+
+    if (stream->track_id == track_id) {
+      GST_INFO_OBJECT (qtdemux, "found stream with track_id = %d", track_id);
+      found_track = TRUE;
+      break;
+    }
+  }
+
+  if (!stream || !found_track) {
+    GST_WARNING_OBJECT (qtdemux, "not able to parse tfra...");
     return FALSE;
   }
 
+  GST_LOG_OBJECT (qtdemux, "id %d == stream id %d ?",
+      track_id, stream->track_id);
+
+  GST_INFO_OBJECT (stream->pad, "number of tfra entries = %u", num_entries);
+
+  if (num_entries == 0)
+    goto no_samples;
+
+  tfra_table = g_new0 (QtDemuxTfraTable, 1);
+  tfra_table->n_entries = num_entries;
+  tfra_table->tfra_entries = g_array_sized_new (FALSE, FALSE, sizeof (QtDemuxTfraEntryInfo), num_entries);
+
   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
   sample_size = (len & 3) + 1;
   trun_size = ((len & 12) >> 2) + 1;
   traf_size = ((len & 48) >> 4) + 1;
 
-  if (num_entries == 0)
-    goto no_samples;
+  GST_DEBUG_OBJECT (stream->pad, "value_size = %u, sample_size = %u, trun_size = %u and traf_size = %u",
+    value_size, sample_size, trun_size, traf_size);
 
   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
           value_size + value_size + traf_size + trun_size + sample_size))
     goto corrupt_file;
 
   for (i = 0; i < num_entries; i++) {
+    QtDemuxTfraEntryInfo entry = {0, };
+
     qt_atom_parser_get_offset (&tfra, value_size, &time);
     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
 
-    GST_LOG_OBJECT (qtdemux,
-        "fragment time: %" GST_TIME_FORMAT " moof_offset: %u",
-        GST_TIME_ARGS (gst_util_uint64_scale (time, GST_SECOND,
-                stream->timescale)), moof_offset);
+    entry.time = time;
+    entry.moof_offset = moof_offset;
+    g_array_append_val (tfra_table->tfra_entries, entry);
 
-    ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
-    if (ret != GST_FLOW_OK)
-      goto corrupt_file;
-    qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
-        moof_offset, stream);
-    gst_buffer_unref (buf);
+    GST_LOG_OBJECT (stream->pad,
+        "fragment time apend: %" GST_TIME_FORMAT " moof_offset: %"G_GUINT64_FORMAT,
+        GST_TIME_ARGS (gst_util_uint64_scale (time, GST_SECOND, stream->timescale)), entry.moof_offset);
   }
 
+  stream->tfra_table = tfra_table;
+
+  GST_DEBUG_OBJECT (qtdemux, "successfully built tfra table...");
+
   return TRUE;
 
 /* ERRORS */
@@ -2730,41 +4331,91 @@ no_samples:
   }
 }
 
-static gboolean
-qtdemux_parse_mfra (GstQTDemux * qtdemux, QtDemuxStream * stream)
+
+static gint
+gst_qtdemux_moof_offset_compare (QtDemuxTfraEntryInfo * i1, QtDemuxTfraEntryInfo * i2)
 {
-  GstFlowReturn ret;
+  return (i1->moof_offset - i2->moof_offset);
+}
+
+static GstFlowReturn
+qtdemux_parse_mfra (GstQTDemux * qtdemux)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
   GNode *mfra_node, *tfra_node;
-  GstBuffer *buffer;
+  gint n = 0;
+  GstBuffer *buffer = NULL;
+  gboolean bret = FALSE;
 
-  if (!qtdemux->mfra_offset)
-    return FALSE;
+  GST_DEBUG_OBJECT (qtdemux, "Starting mfra atom parsing...");
 
   ret = gst_qtdemux_pull_atom (qtdemux, qtdemux->mfra_offset, 0, &buffer);
   if (ret != GST_FLOW_OK)
     goto corrupt_file;
 
   mfra_node = g_node_new ((guint8 *) GST_BUFFER_DATA (buffer));
-  qtdemux_parse_node (qtdemux, mfra_node, GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer));
+  qtdemux_parse_node (qtdemux, mfra_node, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
 
   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
 
   while (tfra_node) {
-    qtdemux_parse_tfra (qtdemux, tfra_node, stream);
+    bret = qtdemux_parse_tfra (qtdemux, tfra_node);
+    if (!bret) {
+      GST_WARNING_OBJECT (qtdemux, "issue in parsing tfra atom..");
+      break;
+    }
     /* iterate all siblings */
     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
   }
+
+  if (!bret) {
+    GST_WARNING_OBJECT (qtdemux, "ignore parsing of mfra atom because of errors");
+    goto exit;
+  }
+
+  qtdemux->moof_offsets = g_array_new (FALSE, FALSE, sizeof (QtDemuxTfraEntryInfo));
+
+  /* prepare consolidated moof_offset_table */
+  for (n = 0; n < qtdemux->n_streams; n++) {
+    QtDemuxStream *stream = qtdemux->streams[n];
+    QtDemuxTfraEntryInfo *entry = NULL;
+
+    if (stream->tfra_table) {
+      guint32 idx = 0;
+      guint32 prev_len = qtdemux->moof_offsets->len;
+
+      GST_INFO_OBJECT (stream->pad, "prev len = %d and entries = %d", prev_len, stream->tfra_table->n_entries);
+
+      for (idx = 0; idx < stream->tfra_table->n_entries; idx++) {
+        QtDemuxTfraEntryInfo new_entry = {0, };
+        entry = &g_array_index (stream->tfra_table->tfra_entries, QtDemuxTfraEntryInfo, idx);
+        new_entry.time = entry->time;
+        new_entry.moof_offset = entry->moof_offset;
+        g_array_append_val (qtdemux->moof_offsets, new_entry);
+        GST_DEBUG_OBJECT (stream->pad, "appended %"G_GUINT64_FORMAT" to moof_offsets", entry->moof_offset);
+      }
+    }
+  }
+
+  /* sort the moof_offsets array */
+  g_array_sort (qtdemux->moof_offsets, (GCompareFunc)gst_qtdemux_moof_offset_compare);
+
+  for (n = 0; n < qtdemux->moof_offsets->len; n++) {
+    QtDemuxTfraEntryInfo *entry = &g_array_index (qtdemux->moof_offsets, QtDemuxTfraEntryInfo, n);
+    GST_LOG_OBJECT (qtdemux, "idx = %d and moof_offset = %"G_GUINT64_FORMAT, n, entry->moof_offset);
+  }
+
+exit:
   g_node_destroy (mfra_node);
   gst_buffer_unref (buffer);
 
-  return TRUE;
+  return GST_FLOW_OK;
 
 corrupt_file:
   {
     GST_ELEMENT_ERROR (qtdemux, STREAM, DECODE,
         (_("This file is corrupt and cannot be played.")), (NULL));
-    return FALSE;
+    return ret;
   }
 }
 
@@ -2778,6 +4429,8 @@ qtdemux_parse_mfro (GstQTDemux * qtdemux, guint64 * mfra_offset,
   gint64 len;
   GstFormat fmt = GST_FORMAT_BYTES;
 
+  GST_DEBUG_OBJECT (qtdemux, "Starting mfro atom parsing...");
+
   if (!gst_pad_query_peer_duration (qtdemux->sinkpad, &fmt, &len)) {
     GST_DEBUG_OBJECT (qtdemux, "upstream size not available; "
         "can not locate mfro");
@@ -2789,8 +4442,10 @@ qtdemux_parse_mfro (GstQTDemux * qtdemux, guint64 * mfra_offset,
     goto exit;
 
   fourcc = QT_FOURCC (GST_BUFFER_DATA (mfro) + 4);
-  if (fourcc != FOURCC_mfro)
+  if (fourcc != FOURCC_mfro) {
+    GST_WARNING_OBJECT (qtdemux, "mfro atom is not available, so mfra as well...");
     goto exit;
+  }
 
   GST_INFO_OBJECT (qtdemux, "Found mfro atom: fragmented mp4 container");
   if (GST_BUFFER_SIZE (mfro) >= 16) {
@@ -2811,16 +4466,13 @@ exit:
   return ret;
 }
 
-static void
+static GstFlowReturn
 qtdemux_parse_fragmented (GstQTDemux * qtdemux)
 {
   GstFlowReturn ret;
   guint32 mfra_size = 0;
   guint64 mfra_offset = 0;
 
-  /* default */
-  qtdemux->fragmented = FALSE;
-
   /* We check here if it is a fragmented mp4 container */
   ret = qtdemux_parse_mfro (qtdemux, &mfra_offset, &mfra_size);
   if (ret == GST_FLOW_OK && mfra_size != 0 && mfra_offset != 0) {
@@ -2829,6 +4481,8 @@ qtdemux_parse_fragmented (GstQTDemux * qtdemux)
         "mfra atom expected at offset %" G_GUINT64_FORMAT, mfra_offset);
     qtdemux->mfra_offset = mfra_offset;
   }
+
+  return ret;
 }
 #endif
 
@@ -2840,6 +4494,9 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
   GstBuffer *buf = NULL;
   GstFlowReturn ret = GST_FLOW_OK;
   guint64 cur_offset = qtdemux->offset;
+#ifdef QTDEMUX_MODIFICATION
+  gboolean bret = FALSE;
+#endif
 
   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
@@ -2862,15 +4519,33 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
   switch (fourcc) {
     case FOURCC_moof:
       /* record for later parsing when needed */
+#ifdef QTDEMUX_MODIFICATION
       if (!qtdemux->moof_offset) {
         qtdemux->moof_offset = qtdemux->offset;
+        GST_INFO_OBJECT (qtdemux, "received first moof atom...");
+
+        if (!qtdemux->moof_offsets) {
+          GST_WARNING_OBJECT (qtdemux, "Did not receive mfra yet.. look at the end of file");
+
+          /* ignoring return value, as it is not mandatory for our seeking/playback */
+          ret = qtdemux_parse_fragmented (qtdemux);
+
+          if (qtdemux->mfra_offset) {
+            ret = qtdemux_parse_mfra (qtdemux);
+            if (ret != GST_FLOW_OK)
+              goto beach;
+          }
+        }
+      }
+#else
+       if (!qtdemux->moof_offset) {
+        qtdemux->moof_offset = qtdemux->offset;
       }
+#endif
       /* fall-through */
     case FOURCC_mdat:
     case FOURCC_free:
-    case FOURCC_wide:
     case FOURCC_PICT:
-    case FOURCC_pnot:
     {
       GST_LOG_OBJECT (qtdemux,
           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
@@ -2881,7 +4556,9 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
     case FOURCC_moov:
     {
       GstBuffer *moov;
-
+#ifdef QTDEMUX_MODIFICATION
+      gboolean tree_ret;
+#endif
       if (qtdemux->got_moov) {
         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
         qtdemux->offset += length;
@@ -2931,10 +4608,24 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       }
       qtdemux->offset += length;
 
-      qtdemux_parse_moov (qtdemux, GST_BUFFER_DATA (moov), length);
+#ifdef QTDEMUX_MODIFICATION
+      bret = qtdemux_parse_moov (qtdemux, GST_BUFFER_DATA (moov), length);
+      if(!bret) {
+        GST_DEBUG_OBJECT(qtdemux, "Failed to parse moov atom");
+        return GST_FLOW_ERROR;
+      }
+#else
       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
-
+#endif
+#ifdef QTDEMUX_MODIFICATION
+      tree_ret = qtdemux_parse_tree (qtdemux);
+      if(!tree_ret) {
+        GST_ERROR_OBJECT(qtdemux,"fail to parse uuid atom in tree");
+        return GST_FLOW_ERROR;
+      }
+#else
       qtdemux_parse_tree (qtdemux);
+#endif
       g_node_destroy (qtdemux->moov_node);
       gst_buffer_unref (moov);
       qtdemux->moov_node = NULL;
@@ -2953,6 +4644,12 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       qtdemux->offset += length;
       qtdemux_parse_ftyp (qtdemux, GST_BUFFER_DATA (ftyp),
           GST_BUFFER_SIZE (ftyp));
+#ifndef TIZEN_KEEP_QT_ATOMS
+      if (qtdemux->major_brand == FOURCC_qt__) {
+        GST_ERROR_OBJECT (qtdemux, "Unsupported major brand...");
+        return GST_FLOW_ERROR;
+      }
+#endif
       gst_buffer_unref (ftyp);
       break;
     }
@@ -2970,6 +4667,18 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       gst_buffer_unref (uuid);
       break;
     }
+#ifdef QTDEMUX_MODIFICATION
+    case FOURCC_mfra:
+    {
+      GST_DEBUG_OBJECT (qtdemux, "Got mfra atom...");
+      qtdemux->mfra_offset = cur_offset;
+      qtdemux->offset += length;
+      ret = qtdemux_parse_mfra (qtdemux);
+      if (ret != GST_FLOW_OK)
+        goto beach;
+      break;
+    }
+#endif
     default:
     {
       GstBuffer *unknown;
@@ -2990,8 +4699,11 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
   }
 
 beach:
-  if (ret == GST_FLOW_UNEXPECTED && qtdemux->got_moov) {
+  if ((qtdemux->moof_offset != 0 || ret == GST_FLOW_UNEXPECTED) && qtdemux->got_moov) {
     /* digested all data, show what we have */
+#ifdef QTDEMUX_MODIFICATION
+    qtdemux_prepare_streams (qtdemux);
+#endif
     ret = qtdemux_expose_streams (qtdemux);
 
     /* Only post, event on pads is done after newsegment */
@@ -3022,7 +4734,7 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
 #ifdef QTDEMUX_MODIFICATION
   QtDemuxSample *sample;
   gdouble minusone = -1;
-  guint64 time_position;
+  guint64 time_position = 0;
 #endif
 
   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
@@ -3032,7 +4744,12 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
     QtDemuxStream *str = qtdemux->streams[n];
 
 #ifdef QTDEMUX_MODIFICATION
-    sample = &str->samples[str->sample_index];
+
+    sample = &str->samples[str->from_sample];
+
+    GST_DEBUG_OBJECT (qtdemux, "from sample timestamp = %"GST_TIME_FORMAT, GST_TIME_ARGS(sample->timestamp));
+
+    time_position = sample->timestamp;
 
     if((time_position - (minusone *qtdemux->segment.rate)*sample->duration)>0)
       time_position -= (minusone *qtdemux->segment.rate)*sample->duration;
@@ -3751,8 +5468,11 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
     /* no further processing needed */
     stream->need_process = FALSE;
   }
-
+#ifdef QTDEMUX_MODIFICATION
+  if (G_UNLIKELY (stream->subtype != FOURCC_text) && G_UNLIKELY (stream->subtype != FOURCC_sbtl)) {
+#else
   if (G_UNLIKELY (stream->subtype != FOURCC_text)) {
+#endif
     return buf;
   }
 
@@ -3824,6 +5544,21 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
     goto exit;
   }
 
+#ifdef QTDEMUX_MODIFICATION
+  if (qtdemux->is_dash && GST_CLOCK_TIME_IS_VALID(stream->dash_seek_offset) && qtdemux->n_video_streams == 0) {
+    /* Dropping audio buffers for syncronization audio and video streams when
+     *playing MPEG DASH content and audio stream have personal demuxer. */
+    if ( (timestamp < stream->dash_seek_offset || !keyframe) ) {
+      GST_LOG_OBJECT (qtdemux, "Ignoring dash buffer with ts=%"GST_TIME_FORMAT
+              " before newsegment start time.", GST_TIME_ARGS(timestamp));
+      gst_buffer_unref (buf);
+      goto exit;
+    } else {
+        stream->dash_seek_offset = GST_CLOCK_TIME_NONE;
+    }
+  }
+#endif
+
   /* send out pending buffers */
   while (stream->buffers) {
     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
@@ -3891,6 +5626,231 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
 
   gst_buffer_set_caps (buf, stream->caps);
 
+#ifdef QTDEMUX_MODIFICATION
+
+#ifdef DRM_ENABLE
+  if (qtdemux->encrypt_content) {
+    unsigned int i = 0;
+    QtDemuxSample *sample = NULL;
+    guint n_entries = 0;
+    guint running_offset = 0;
+
+    unsigned char *indata = NULL;
+    unsigned int insize = 0;
+    guint indata_offset = 0;
+    drm_trusted_payload_info_s read_input_data = {0, };
+    drm_trusted_read_decrypt_resp_data_s read_output_data = {0, };
+    drm_trusted_result_e drm_ret = DRM_TRUSTED_RETURN_SUCCESS;
+
+    sample = &stream->samples[stream->sample_index];
+
+    if (sample->sub_encry && qtdemux->dash_content == FALSE) {
+      n_entries = sample->sub_encry->n_entries;
+      GST_DEBUG_OBJECT (qtdemux, " number of sub-sample entries = %d", n_entries);
+    }
+
+    if (n_entries > 0) {
+      /* create indata */
+      indata = (unsigned char *) malloc (GST_BUFFER_SIZE(buf));
+      if (!indata) {
+        GST_ERROR_OBJECT (qtdemux, "failed to create indata...");
+        return GST_FLOW_ERROR;
+      }
+
+      /* copy encrypted data only */
+      do {
+        gint clear_len = 0;
+
+        gint encrypted_len = 0;
+
+        clear_len = sample->sub_encry->sub_entry[i].LenofClearData;
+        encrypted_len = sample->sub_encry->sub_entry[i].LenofEncryptData;
+        running_offset += clear_len;
+
+        GST_LOG_OBJECT (qtdemux, "entry = %d and copying %d bytes of encrypted data", i, encrypted_len);
+        memcpy (indata + insize, GST_BUFFER_DATA (buf)+ running_offset, encrypted_len);
+        insize += encrypted_len;
+        running_offset += encrypted_len;
+        i++;
+      } while (i < n_entries);
+    } else if(qtdemux->clear_data && stream->subtype == FOURCC_vide) {
+      gint clear_len = 0;
+      gint encrypted_len = 0;
+      indata = (unsigned char *) malloc (GST_BUFFER_SIZE(buf));
+      if (!indata) {
+        GST_ERROR_OBJECT (qtdemux, "failed to create indata...");
+        return GST_FLOW_ERROR;
+      }
+      clear_len = qtdemux->clear_data[qtdemux->current_sample[0]];
+      encrypted_len = qtdemux->encrypted_data[qtdemux->current_sample[0]];
+      running_offset += clear_len;
+
+      GST_LOG_OBJECT (qtdemux, "entry = %d and copying %d bytes of encrypted data", i, encrypted_len);
+      memcpy (indata + insize, GST_BUFFER_DATA (buf)+ running_offset, encrypted_len);
+      insize += encrypted_len;
+      running_offset += encrypted_len;
+    } else {
+      indata = GST_BUFFER_DATA (buf);
+      insize = GST_BUFFER_SIZE (buf);
+    }
+
+    read_input_data.media_offset = 0;
+    read_input_data.payload_data =  indata;
+    read_input_data.payload_data_len = insize;
+    read_input_data.payload_data_output = read_input_data.payload_data; /* inplace decryption */
+
+    if(qtdemux->sample_count[0] || qtdemux->sample_count[1]) {
+      if(stream->subtype == FOURCC_vide) {
+        read_input_data.payload_iv_len = qtdemux->iv_size_video;
+        read_input_data.payload_iv = (unsigned char *) malloc (qtdemux->iv_size_video);
+        if (NULL == read_input_data.payload_iv) {
+          GST_ERROR_OBJECT (qtdemux, "Failed to allocate memory...\n");
+          GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+          ret = GST_FLOW_ERROR;
+          goto exit;
+        }
+        for(i = 0 ; i < read_input_data.payload_iv_len; i++) {
+          read_input_data.payload_iv[i] = (unsigned char*)qtdemux->iv_data_video[qtdemux->current_sample[0]][i];
+        }
+        qtdemux->current_sample[0]++;
+      } else if(stream->subtype == FOURCC_soun) {
+        read_input_data.payload_iv_len = qtdemux->iv_size_audio;
+        read_input_data.payload_iv = (unsigned char *) malloc (qtdemux->iv_size_audio);
+        if (NULL == read_input_data.payload_iv) {
+          GST_ERROR_OBJECT (qtdemux, "Failed to allocate memory...\n");
+          GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+          ret = GST_FLOW_ERROR;
+          goto exit;
+        }
+        for(i = 0 ; i < read_input_data.payload_iv_len; i++) {
+          read_input_data.payload_iv[i] = (unsigned char*)qtdemux->iv_data_audio[qtdemux->current_sample[1]][i];
+        }
+        qtdemux->current_sample[1]++;
+      }
+    } else {
+      read_input_data.payload_iv_len = 8;
+      read_input_data.payload_iv = (unsigned char *) malloc (8);
+      if (NULL == read_input_data.payload_iv) {
+        GST_ERROR_OBJECT (qtdemux, "Failed to allocate memory...\n");
+        GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+        ret = GST_FLOW_ERROR;
+        goto exit;
+      }
+      memcpy (read_input_data.payload_iv, sample->iv, 8);
+    }
+
+    drm_ret = drm_trusted_read_decrypt_session(qtdemux->pr_handle , &read_input_data, &read_output_data);
+    if (DRM_TRUSTED_RETURN_SUCCESS != drm_ret) {
+      GST_ERROR_OBJECT (qtdemux, "failed to decrypt buffer...");
+      if (DRM_TRUSTED_RETURN_OPL_ERROR == drm_ret) {
+        GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("opl violation"), (NULL));
+      } else {
+        GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("decryption failed"), (NULL));
+      }
+
+      free (read_input_data.payload_iv);
+      ret = GST_FLOW_ERROR;
+      goto exit;
+    }
+
+    GST_LOG_OBJECT (qtdemux, "decryption is successful");
+
+    if (read_output_data.read_size != read_input_data.payload_data_len) {
+      GST_INFO_OBJECT (qtdemux, "Decrypter did not consume data fully...");
+    }
+
+    if(read_input_data.payload_iv)
+      free (read_input_data.payload_iv);
+    read_input_data.payload_iv = NULL;
+
+
+    i = 0;
+    running_offset = 0;
+
+    if (n_entries > 0) {
+      do {
+        gint clear_len = 0;
+        gint encrypted_len = 0;
+
+        clear_len = sample->sub_encry->sub_entry[i].LenofClearData;
+        encrypted_len = sample->sub_encry->sub_entry[i].LenofEncryptData;
+        running_offset += clear_len;
+
+        GST_LOG_OBJECT (qtdemux, "entry = %d and copying back %d bytes of decrypted data", i, encrypted_len);
+        memcpy (GST_BUFFER_DATA (buf)+ running_offset, indata+indata_offset, encrypted_len);
+        running_offset += encrypted_len;
+        indata_offset += encrypted_len;
+        i++;
+      } while (i < n_entries);
+      free (indata);
+    } else if(qtdemux->clear_data > 0 && stream->subtype == FOURCC_vide) {
+      gint clear_len = 0;
+      gint encrypted_len = 0;
+
+      clear_len = qtdemux->clear_data[qtdemux->current_sample[0] - 1];
+      encrypted_len = qtdemux->encrypted_data[qtdemux->current_sample[0] - 1];
+      running_offset += clear_len;
+
+      GST_LOG_OBJECT (qtdemux, "entry = %d and copying back %d bytes of decrypted data", i, encrypted_len);
+      memcpy (GST_BUFFER_DATA (buf)+ running_offset, indata+indata_offset, encrypted_len);
+      running_offset += encrypted_len;
+      indata_offset += encrypted_len;
+      free (indata);
+    }
+  }
+#endif // DRM_ENABLE
+  if (qtdemux->piff_fragmented && !qtdemux->pullbased) {
+    gboolean all_queues_filled = TRUE;
+    gint i = 0;
+    QtDemuxStream *cstream = NULL;
+
+    /* push current buffer */
+    g_queue_push_tail (stream->frag_queue, buf);
+    GST_LOG_OBJECT (stream->pad, "pushing buffer into frag_queue with ts = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)));
+
+    for (i = 0; i < qtdemux->n_streams; i++) {
+      cstream = qtdemux->streams[i];
+      if (g_queue_is_empty (cstream->frag_queue)) {
+        all_queues_filled = FALSE;
+      }
+    }
+
+    if (all_queues_filled) {
+      /* all stream queues have data */
+      for (i = 0; i < qtdemux->n_streams; i++) {
+        GstBuffer *pop_buf = NULL;
+        cstream = qtdemux->streams[i];
+
+pop_again:
+        pop_buf = g_queue_pop_head (cstream->frag_queue);
+
+        qtdemux->max_pop_ts = GST_BUFFER_TIMESTAMP(pop_buf) > qtdemux->max_pop_ts ?
+          GST_BUFFER_TIMESTAMP(pop_buf) : qtdemux->max_pop_ts;
+
+        GST_DEBUG_OBJECT (cstream->pad,
+            "Pushing buffer with time %" GST_TIME_FORMAT ", duration %"
+            GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (pop_buf)),
+            GST_TIME_ARGS (GST_BUFFER_DURATION (pop_buf)));
+
+        ret = gst_pad_push (cstream->pad, pop_buf);
+        if (ret != GST_FLOW_OK) {
+          GST_WARNING_OBJECT (cstream->pad, "pad_push returned = %s", gst_flow_get_name (ret));
+          return ret;
+        }
+
+        pop_buf =  g_queue_peek_head (cstream->frag_queue);
+
+        if (pop_buf && (GST_BUFFER_TIMESTAMP(pop_buf) < qtdemux->max_pop_ts)) {
+          GST_LOG_OBJECT (cstream->pad, "pop again next ts = %"GST_TIME_FORMAT" and max_pop_ts = %"GST_TIME_FORMAT,
+            GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (pop_buf)), GST_TIME_ARGS(qtdemux->max_pop_ts));
+          goto pop_again;
+        }
+      }
+    }
+
+    return GST_FLOW_OK;
+  }
+#endif
   GST_LOG_OBJECT (qtdemux,
       "Pushing buffer with time %" GST_TIME_FORMAT ", duration %"
       GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
@@ -3928,12 +5888,16 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
 
     stream = qtdemux->streams[i];
     position = stream->time_position;
-
     /* position of -1 is EOS */
     if (position != -1 && position < min_time) {
       min_time = position;
       index = i;
     }
+    if (stream->sample_index == stream->n_samples && stream->sent_eos == FALSE) {
+      GST_DEBUG_OBJECT (qtdemux, "Sending EOS for Stream %d", i);
+      gst_pad_push_event(stream->pad, gst_event_new_eos ());
+      stream->sent_eos = TRUE;
+    }
   }
   /* all are EOS */
   if (G_UNLIKELY (index == -1)) {
@@ -4010,15 +5974,23 @@ eos_stream:
 static void
 gst_qtdemux_loop (GstPad * pad)
 {
-  GstQTDemux *qtdemux;
-  guint64 cur_offset;
-  GstFlowReturn ret;
+  GstQTDemux *qtdemux = NULL;
+  guint64 cur_offset = 0;
+  GstFlowReturn ret = GST_FLOW_OK;
 
   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
 
   cur_offset = qtdemux->offset;
   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %d",
       cur_offset, qtdemux->state);
+#ifdef QTDEMUX_MODIFICATION
+  if (qtdemux->need_moof_parsing) {
+    ret = qtdemux_prepare_streams (qtdemux);
+    if (ret != GST_FLOW_OK)
+      goto pause;
+    qtdemux->need_moof_parsing = FALSE;
+  }
+#endif
 
   switch (qtdemux->state) {
     case QTDEMUX_STATE_INITIAL:
@@ -4250,9 +6222,11 @@ done:
 static GstFlowReturn
 gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
 {
-  GstQTDemux *demux;
+  GstQTDemux *demux = NULL;
   GstFlowReturn ret = GST_FLOW_OK;
-
+#ifdef QTDEMUX_MODIFICATION
+  gboolean bret = FALSE;
+#endif
   demux = GST_QTDEMUX (gst_pad_get_parent (sinkpad));
 
 #ifdef QTDEMUX_MODIFICATION
@@ -4284,7 +6258,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
 
 #ifdef QTDEMUX_MODIFICATION
   /* Added consideration of demuxer state and file size*/
-  while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes 
+  while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes
            || (demux->file && demux->state == QTDEMUX_STATE_MOVIE && demux->filesize >= demux->neededbytes))
            && ret == GST_FLOW_OK) {
 #else
@@ -4296,6 +6270,12 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
         "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,
         demux->state, demux->neededbytes, demux->offset);
 
+#ifdef QTDEMUX_MODIFICATION
+    if(demux->is_dash && GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(inbuf))) {
+      demux->dash_init_offset = GST_BUFFER_TIMESTAMP(inbuf);
+    }
+#endif
+
     switch (demux->state) {
       case QTDEMUX_STATE_INITIAL:{
         const guint8 *data;
@@ -4386,7 +6366,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
               demux->neededbytes = size;
 #ifdef QTDEMUX_MODIFICATION
-              if ((demux->filename && demux->file == NULL) || !demux->mdatbuffer)
+              if ((demux->filename && demux->file == NULL) && !demux->mdatbuffer)
 #else
               if (!demux->mdatbuffer)
 #endif
@@ -4428,6 +6408,29 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
         if (fourcc == FOURCC_moov) {
           GST_DEBUG_OBJECT (demux, "Parsing [moov]");
 
+#ifdef QTDEMUX_MODIFICATION
+          if (demux->got_moov && demux->fragmented) {
+               demux->need_parsing_moov = TRUE;//need to parse 2nd moov
+               GST_DEBUG_OBJECT (demux,
+                  "Got a second moov, clean up data from old one");
+               if (demux->moov_node)
+                 g_node_destroy (demux->moov_node);
+               demux->moov_node = NULL;
+               demux->moov_node_compressed = NULL;
+          }
+
+          /* prepare newsegment to send when streaming actually starts */
+          if (!demux->pending_newsegment && !demux->got_moov) {
+            demux->pending_newsegment =
+                gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+                0, GST_CLOCK_TIME_NONE, 0);
+          }
+          bret = qtdemux_parse_moov (demux, data, demux->neededbytes);
+          if(!bret) {
+            GST_DEBUG_OBJECT(demux, "returning from chain");
+            return GST_FLOW_ERROR;
+          }
+#else
           demux->got_moov = TRUE;
 
           /* prepare newsegment to send when streaming actually starts */
@@ -4436,12 +6439,29 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
                 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
                 0, GST_CLOCK_TIME_NONE, 0);
           }
-
           qtdemux_parse_moov (demux, data, demux->neededbytes);
+#endif
           qtdemux_node_dump (demux, demux->moov_node);
           qtdemux_parse_tree (demux);
-          qtdemux_expose_streams (demux);
+#ifdef QTDEMUX_MODIFICATION
+          qtdemux_prepare_streams (demux);
+          if (!demux->got_moov)
+            qtdemux_expose_streams (demux);
+          else {
+            gint n;
+
+            for (n = 0; n < demux->n_streams; n++) {
+              QtDemuxStream *stream = demux->streams[n];
 
+              gst_qtdemux_configure_stream (demux, stream);
+            }
+          }
+
+          demux->got_moov = TRUE;
+          demux->need_parsing_moov = FALSE;//reset 2nd moov
+#else
+          qtdemux_expose_streams (demux);
+#endif
           g_node_destroy (demux->moov_node);
           demux->moov_node = NULL;
           GST_DEBUG_OBJECT (demux, "Finished parsing the header");
@@ -4559,7 +6579,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
             GST_FOURCC_ARGS (QT_FOURCC (GST_BUFFER_DATA (buf) + 4)));
 
 #ifdef QTDEMUX_MODIFICATION
-        if (demux->filename == NULL) {
+        if (demux->file == NULL) {
 #endif
         if (demux->mdatbuffer)
           demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);
@@ -4645,8 +6665,8 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
           gst_adapter_flush (demux->adapter, demux->todrop);
 #ifdef QTDEMUX_MODIFICATION
           else {
-            fseek (demux->ofile, (long) demux->todrop, SEEK_CUR);
-            demux->filesize -= demux->todrop;
+            if(!fseek (demux->ofile, (long) demux->todrop, SEEK_CUR))
+              demux->filesize -= demux->todrop;
           }
 #endif
           demux->neededbytes -= demux->todrop;
@@ -4887,74 +6907,46 @@ qtdemux_inflate (void *z_buffer, guint z_length, guint length)
 static gboolean
 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
 {
-  GNode *cmov;
-
+#ifdef QTDEMUX_MODIFICATION
+  gboolean bret = FALSE;
+#endif
   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
 
   /* counts as header data */
   qtdemux->header_size += length;
 
   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
-  qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
-
-  cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
-  if (cmov) {
-    guint32 method;
-    GNode *dcom;
-    GNode *cmvd;
-
-    dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
-    cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
-    if (dcom == NULL || cmvd == NULL)
-      goto invalid_compression;
-
-    method = QT_FOURCC ((guint8 *) dcom->data + 8);
-    switch (method) {
-#ifdef HAVE_ZLIB
-      case GST_MAKE_FOURCC ('z', 'l', 'i', 'b'):{
-        guint uncompressed_length;
-        guint compressed_length;
-        guint8 *buf;
-
-        uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
-        compressed_length = QT_UINT32 ((guint8 *) cmvd->data + 4) - 12;
-        GST_LOG ("length = %u", uncompressed_length);
-
-        buf =
-            (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
-            compressed_length, uncompressed_length);
-
-        qtdemux->moov_node_compressed = qtdemux->moov_node;
-        qtdemux->moov_node = g_node_new (buf);
 
-        qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
-            uncompressed_length);
-        break;
-      }
-#endif /* HAVE_ZLIB */
-      default:
-        GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
-            "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
-        break;
-    }
+#ifdef QTDEMUX_MODIFICATION
+  bret = qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
+  if(!bret) {
+    GST_ERROR_OBJECT(qtdemux, "Failed to parse node object");
+    return bret;
   }
+#else
+  qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
+#endif
   return TRUE;
-
-  /* ERRORS */
-invalid_compression:
-  {
-    GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
-    return FALSE;
-  }
 }
 
 static gboolean
+#ifdef QTDEMUX_MODIFICATION
+qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, guint8 * buf,
+    const guint8 * end)
+#else
 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
     const guint8 * end)
+#endif
 {
   while (G_UNLIKELY (buf < end)) {
     GNode *child;
     guint32 len;
+#ifdef QTDEMUX_MODIFICATION
+    guint32 fourcc;
+    guint8 i,j;
+    gboolean found_sinf = FALSE;
+    gboolean bret = FALSE;
+#endif
 
     if (G_UNLIKELY (buf + 4 > end)) {
       GST_LOG_OBJECT (qtdemux, "buffer overrun");
@@ -4975,11 +6967,43 @@ qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
       break;
     }
 
+#ifdef QTDEMUX_MODIFICATION
+/* Replacing the fourcc value of 'enca' or 'encv' node with the fourcc value of original format stored in 'sinf' node. */
+    fourcc = QT_FOURCC (buf + 4);
+
+    if((fourcc & 0xFFFFFF) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)) {
+      for(i = 0; i < len ; i++) {
+        fourcc = QT_FOURCC(buf + i);
+        if( fourcc == GST_MAKE_FOURCC ('s','i','n','f')) {
+          found_sinf = TRUE;
+          break;
+        }
+      }
+
+      if (!found_sinf) {
+        GST_ERROR_OBJECT (qtdemux, "failed to find sinf for encx format");
+        GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("failed to find sinf atom"), (NULL));
+        return FALSE;
+      }
+
+      fourcc = QT_FOURCC(buf + i +12);
+      GST_LOG_OBJECT(qtdemux,"Original format present in encX node is %"GST_FOURCC_FORMAT , GST_FOURCC_ARGS(fourcc));
+      for(j=0; j<4;j++)
+      buf[4+j] = buf[12 + i + j];
+    }
+#endif
     child = g_node_new ((guint8 *) buf);
     g_node_append (node, child);
     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
+#ifdef QTDEMUX_MODIFICATION
+    bret = qtdemux_parse_node (qtdemux, child, buf, len);
+    if(!bret) {
+      GST_ERROR_OBJECT(qtdemux, "failed to parse node object");
+      return bret;
+    }
+#else
     qtdemux_parse_node (qtdemux, child, buf, len);
-
+#endif
     buf += len;
   }
   return TRUE;
@@ -5054,6 +7078,9 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
   guint32 node_length = 0;
   const QtNodeType *type;
   const guint8 *end;
+#ifdef QTDEMUX_MODIFICATION
+  gboolean bret =  FALSE;
+#endif
 
   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
 
@@ -5079,9 +7106,35 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
     goto broken_atom_size;
 
   if (type->flags & QT_FLAG_CONTAINER) {
+#ifdef QTDEMUX_MODIFICATION
+    bret = qtdemux_parse_container (qtdemux, node, buffer + 8, end);
+    if(!bret) {
+      GST_ERROR_OBJECT(qtdemux, "failed to parse container object");
+      return bret;
+    }
+#else
     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
+#endif
   } else {
     switch (fourcc) {
+      case FOURCC_saiz:
+      {
+        GST_DEBUG("found saiz atom");
+        if(qtdemux->sequence_id == 2) {
+          qtdemux->iv_size_audio = QT_UINT32 (buffer + 9);
+          GST_INFO("iv size is %d", qtdemux->iv_size_audio);
+        } else if(qtdemux->sequence_id == 1) {
+          qtdemux->iv_size_video = QT_UINT32 (buffer + 9);
+          qtdemux->iv_size_video = 8;
+          GST_INFO("iv size is %d", qtdemux->iv_size_video);
+        }
+        break;
+      }
+      case FOURCC_saio:
+      {
+        GST_DEBUG("found saio atom");
+        break;
+      }
       case FOURCC_stsd:
       {
         if (node_length < 20) {
@@ -5093,6 +7146,220 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
         break;
       }
+#ifdef DRM_ENABLE
+#ifdef QTDEMUX_MODIFICATION
+      case FOURCC_uuid:
+      {
+        GstByteReader uuid_data;
+        guint8 *protection_header_data = NULL;
+        gint64 uuid_offset = 0;
+        uuid_type_t uuid_type;
+
+        gst_byte_reader_init (&uuid_data, buffer, QT_UINT32 (buffer));
+        uuid_type = qtdemux_get_uuid_type (qtdemux, &uuid_data, &uuid_offset);
+        if (UUID_PROTECTION_HEADER != uuid_type) {
+          GST_WARNING_OBJECT (qtdemux, "Ignoring Wrong UUID...");
+          return TRUE;
+        } else {
+          qtdemux->protection_header_present = TRUE;
+          GST_DEBUG_OBJECT (qtdemux, "protection_header is present in uuid...");
+        }
+        break;
+      }
+#endif
+      case FOURCC_pssh:
+      {
+          GstByteReader uuid_data;
+          guint32 protection_header_size = 0;
+          gchar *protection_header_data = NULL;
+          int ret = -1;
+          drm_trusted_open_decrypt_info_s open_input_data;
+          drm_trusted_open_decrypt_resp_data_s open_output_data;
+          drm_trusted_set_consumption_state_info_s state_input_data;
+          guint8 *buffer = (guint8 *) node->data;
+          drm_permission_type_e status_perm_type;
+          drm_license_status_e license_status = DRM_LICENSE_STATUS_UNDEFINED;
+          GstQuery *query = NULL;
+          gchar *file_path = NULL;
+          gchar *query_file_path = NULL;
+          gchar *modified_path = NULL;
+          gchar *drm_compatible_path = NULL;
+          drm_bool_type_e is_drm_file = DRM_UNKNOWN;
+          gint len_protection_header = 0;
+          int a = 0;
+
+          if (qtdemux->dash_content) {
+            GST_WARNING_OBJECT (qtdemux, "Skipping second pssh");
+            break;
+          }
+
+          qtdemux->dash_content = TRUE;
+
+          gst_byte_reader_init (&uuid_data, buffer, QT_UINT32 (buffer));
+
+          /* Skipping fourcc & length*/
+          if (!gst_byte_reader_skip (&uuid_data, 8))
+           goto not_enough_data;
+
+          if (!qtdemux_parse_playready_system_id (qtdemux, &uuid_data)) {
+            GST_ERROR_OBJECT (qtdemux, "not a playready system id..");
+            GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), ("not a valid playready system ID"));
+            return FALSE;
+          }
+
+          query = gst_query_new_uri ();
+          if (!gst_pad_peer_query (qtdemux->sinkpad, query)) {
+            GST_ERROR_OBJECT (qtdemux, "failed to query URI from upstream");
+            GST_ELEMENT_ERROR (qtdemux, CORE, FAILED, (NULL), ("failed to get uri from upstream"));
+            gst_query_unref (query);
+            return FALSE;
+          }
+          gst_query_parse_uri (query, &query_file_path);
+
+          gst_query_unref (query);
+          query = NULL;
+
+          if (g_str_has_prefix (query_file_path, "file://")) {
+            modified_path = query_file_path + 7;
+          } else {
+            modified_path = query_file_path;
+          }
+          GST_INFO_OBJECT (qtdemux, "file path : %s", query_file_path);
+          GST_INFO_OBJECT (qtdemux, "modified path : %s", modified_path);
+          drm_compatible_path = g_uri_unescape_string(modified_path, NULL);
+          if(drm_compatible_path == NULL) {
+            GST_WARNING_OBJECT(qtdemux, "unsuccessful in converting the string continuing with the modified path");
+            drm_compatible_path = modified_path;
+          } else {
+            GST_INFO_OBJECT (qtdemux, "DRM Compatible path : %s", drm_compatible_path);
+            if(query_file_path) {
+              g_free (query_file_path);
+              query_file_path = NULL;
+            }
+          }
+
+          //drm_compatible_path = "http://img.samsungvideohub.com/cms-private/store/057e52tw7h/PRD/C00000682330/Movie_HEVC_SD/I00001645829/I00001645829.mpd?AWSAccessKeyId=AKIAJW7RUCSLREJCX3IA&Expires=1374745300&Signature=FnPehyWVpoQoSKs9dxSSm7U551E%3D[]<>0418hwir93[]<>nk61lxvw9v[]<>356449050005148[]<>10060079181422907[]<>V[]<>STG";
+          //drm_compatible_path = "http://img.samsungvideohub.com/cms-private/store/057e52tw7h/PRD/C00000107359/Movie_HEVC_SD/I00001645159/I00001645159.mpd?AWSAccessKeyId=AKIAJW7RUCSLREJCX3IA&Expires=1375434936&Signature=rzKiT1HUIVsTEa5QHaSDhEqR%2Frc%3D[]<>0418hwir93[]<>nk61lxvw9v[]<>356449050005148[]<>10060081508510332[]<>V[]<>STG";
+
+
+          /* Enters into if body when valid system ID is present.*/
+          gst_byte_reader_skip (&uuid_data, 12);
+
+          gst_byte_reader_get_uint16_le (&uuid_data, &protection_header_size);
+
+          GST_DEBUG_OBJECT(qtdemux,"protection header size: %d ", protection_header_size);
+
+          if (!gst_byte_reader_dup_data(&uuid_data, protection_header_size , &protection_header_data)) {
+            GST_ERROR_OBJECT (qtdemux, "failed to duplicate bytereader data...");
+            GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+            return FALSE;
+          }
+          /* for adding wchar null check */
+          protection_header_size = protection_header_size + 2;
+
+          protection_header_data = (guint8 *) realloc (protection_header_data,protection_header_size);
+          if (!protection_header_data) {
+            GST_ERROR_OBJECT (qtdemux, "failed to allocate memory...");
+            GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+            return FALSE;
+          }
+
+          /* adding wchar null character */
+          protection_header_data[protection_header_size-2] = '\0';
+          protection_header_data[protection_header_size-1] = '\0';
+
+          GST_DEBUG_OBJECT(qtdemux,"protection header size: %d ", protection_header_size);
+
+          file_path = (gchar*)calloc((4 + 1 + 32 + 4 + 1 + protection_header_size), sizeof(gchar));
+          if(file_path == NULL) {
+            GST_ERROR_OBJECT (qtdemux, "failed to allocate memory...");
+            GST_ELEMENT_ERROR (qtdemux, RESOURCE, NO_SPACE_LEFT, (NULL), ("failed to allocate memory"));
+            return FALSE;
+          }
+
+          strcpy(file_path, "dash");
+
+          file_path[4] = '?';
+          for(a = 0; a < 16; a++) {
+            sprintf(file_path + 4 + 1 + (a*2), "%02x", qtdemux->uuid_playready[a]);
+          }
+
+          file_path[4 + 1 + 32] = '?';
+          len_protection_header = sprintf(file_path + 4 + 1 + 32 + 1, "%d", protection_header_size);
+          for(a = 0; a < protection_header_size; a++) {
+            file_path[4 + 1 + 32 + len_protection_header + 1 + a] = protection_header_data[a];
+          }
+
+          GST_DEBUG_OBJECT(qtdemux, "pssh header is %s", file_path);
+
+          GST_DEBUG_OBJECT(qtdemux, "file path info is %s", query_file_path);
+
+          ret = drm_is_drm_file(file_path, &is_drm_file);
+          if(ret != 0) {
+            GST_ERROR_OBJECT (qtdemux, "Failed to read is DRM_FILE information");
+            GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("Failed to read is DRM_FILE information"), (NULL));
+            free (protection_header_data);
+            free (file_path);
+            return FALSE;
+          }
+
+          GST_DEBUG_OBJECT(qtdemux, "is drm is drm %d", is_drm_file);
+
+          status_perm_type = DRM_PERMISSION_TYPE_PLAY;
+          ret = drm_get_license_status (file_path, status_perm_type, &license_status);
+          if (DRM_RETURN_SUCCESS != ret) {
+            GST_ERROR_OBJECT (qtdemux, "failed to get license status : 0x%x", ret);
+            qtdemux_post_drm_error (qtdemux, DRM_LICENSE_STATUS_UNDEFINED);
+            free (protection_header_data);
+            free (file_path);
+            return FALSE;
+          }
+
+          GST_DEBUG_OBJECT(qtdemux, "license status is %d", license_status);
+          if(license_status != DRM_LICENSE_STATUS_VALID) {
+            if(!qtdemux_get_playready_licence(qtdemux, protection_header_data, protection_header_size, drm_compatible_path)) {
+              GST_ERROR_OBJECT (qtdemux, "failed to get playready license");
+              free (protection_header_data);
+              free (file_path);
+              return FALSE;
+            }
+          }
+
+          open_input_data.file_type = DRM_TRUSTED_TYPE_PIFF;
+          open_input_data.permission = DRM_TRUSTED_PERMISSION_TYPE_PLAY;
+          open_input_data.operation_callback.callback = test_drm_trusted_operation_cb;
+          open_input_data.lic_header.header = (unsigned char *) protection_header_data;
+          open_input_data.lic_header.header_len = protection_header_size;
+
+          /* Open Decrypt Session*/
+          ret = drm_trusted_open_decrypt_session(&open_input_data, &open_output_data, &(qtdemux->pr_handle));
+          if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+            GST_ERROR_OBJECT (qtdemux, "failed to open decrypt session");
+            GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("failed to open decrypt session"), (NULL));
+            free (protection_header_data);
+            free (file_path);
+            return FALSE;
+          }
+
+          /* Before Read, Appropriate state MUST be SET */
+          state_input_data.state = DRM_CONSUMPTION_STARTED;
+          ret = drm_trusted_set_decrypt_state(qtdemux->pr_handle, &state_input_data);
+          if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+            GST_ERROR_OBJECT (qtdemux, "failed to set decrypt state...");
+            GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, ("failed to set decrypt state"), (NULL));
+            free (protection_header_data);
+            free (file_path);
+            return FALSE;
+          }
+
+          qtdemux->encrypt_content = TRUE;
+
+          free (protection_header_data);
+          free (file_path);
+          /* iterate all siblings */
+          break;
+      }
+#endif
       case FOURCC_mp4a:
       case FOURCC_alac:
       {
@@ -5132,7 +7399,7 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
             offset = 0x24;
             break;
           case 1:
-            offset = 0x34;
+            offset = 0x24;
             break;
           case 2:
             offset = 0x48;
@@ -5308,32 +7575,244 @@ qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
   guint8 *buffer;
   guint32 child_fourcc, child_len;
 
-  for (child = g_node_next_sibling (node); child;
-      child = g_node_next_sibling (child)) {
-    buffer = (guint8 *) child->data;
+  for (child = g_node_next_sibling (node); child;
+      child = g_node_next_sibling (child)) {
+    buffer = (guint8 *) child->data;
+
+    child_fourcc = QT_FOURCC (buffer + 4);
+
+    if (child_fourcc == fourcc) {
+      if (parser) {
+        child_len = QT_UINT32 (buffer);
+        if (G_UNLIKELY (child_len < (4 + 4)))
+          return NULL;
+        /* FIXME: must verify if atom length < parent atom length */
+        gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
+      }
+      return child;
+    }
+  }
+  return NULL;
+}
+
+static GNode *
+qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
+{
+  return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
+}
+
+#ifdef QTDEMUX_MODIFICATION
+static void
+gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
+{
+
+  gst_segment_set_newsegment (&stream->segment, FALSE, 1.0, GST_FORMAT_TIME,
+      0, GST_CLOCK_TIME_NONE, 0);
+
+  if (stream->subtype == FOURCC_vide) {
+
+    /* fps is calculated base on the duration of the first frames since
+     * qt does not have a fixed framerate. */
+    if ((stream->n_samples == 1) && (stream->min_duration == 0)) {
+      /* still frame */
+      stream->fps_n = 0;
+      stream->fps_d = 1;
+    } else {
+      stream->fps_n = stream->timescale;
+      if (stream->min_duration == 0)
+        stream->fps_d = 1;
+      else
+        stream->fps_d = stream->min_duration;
+    }
+
+    if (stream->caps) {
+      gboolean gray;
+      gint depth, palette_count;
+      const guint32 *palette_data = NULL;
+
+      stream->caps = gst_caps_make_writable (stream->caps);
+
+      gst_caps_set_simple (stream->caps,
+          "width", G_TYPE_INT, stream->width,
+          "height", G_TYPE_INT, stream->height,
+          "framerate", GST_TYPE_FRACTION, stream->fps_n, stream->fps_d, NULL);
+
+      if((qtdemux->video_max_width > 0) && (qtdemux->video_max_height > 0)) {
+        gst_caps_set_simple (stream->caps,
+            "max-width", G_TYPE_INT, qtdemux->video_max_width,
+            "max-height", G_TYPE_INT, qtdemux->video_max_height, NULL);
+      }
+
+      /* calculate pixel-aspect-ratio using display width and height */
+      GST_DEBUG_OBJECT (qtdemux,
+          "video size %dx%d, target display size %dx%d", stream->width,
+          stream->height, stream->display_width, stream->display_height);
+
+      if (stream->display_width > 0 && stream->display_height > 0 &&
+          stream->width > 0 && stream->height > 0) {
+        gint n, d;
+
+        /* calculate the pixel aspect ratio using the display and pixel w/h */
+        n = stream->display_width * stream->height;
+        d = stream->display_height * stream->width;
+        if (n == d)
+          n = d = 1;
+        GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
+        gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
+            GST_TYPE_FRACTION, n, d, NULL);
+      }
+
+      /* qt file might have pasp atom */
+      if (stream->par_w > 0 && stream->par_h > 0) {
+        GST_DEBUG_OBJECT (qtdemux, "par %d:%d", stream->par_w, stream->par_h);
+        gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
+            GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
+      }
+
+      depth = stream->bits_per_sample;
+
+      /* more than 32 bits means grayscale */
+      gray = (depth > 32);
+      /* low 32 bits specify the depth  */
+      depth &= 0x1F;
+
+      /* different number of palette entries is determined by depth. */
+      palette_count = 0;
+      if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
+        palette_count = (1 << depth);
+
+      switch (palette_count) {
+        case 0:
+          break;
+        case 2:
+          palette_data = ff_qt_default_palette_2;
+          break;
+        case 4:
+          palette_data = ff_qt_default_palette_4;
+          break;
+        case 16:
+          if (gray)
+            palette_data = ff_qt_grayscale_palette_16;
+          else
+            palette_data = ff_qt_default_palette_16;
+          break;
+        case 256:
+          if (gray)
+            palette_data = ff_qt_grayscale_palette_256;
+          else
+            palette_data = ff_qt_default_palette_256;
+          break;
+        default:
+          GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
+              (_("The video in this file might not play correctly.")),
+              ("unsupported palette depth %d", depth));
+          break;
+      }
+      if (palette_data) {
+        GstBuffer *palette;
+
+        /* make sure it's not writable. We leave MALLOCDATA to NULL so that we
+         * don't free any of the buffer data. */
+        palette = gst_buffer_new ();
+        GST_BUFFER_FLAG_SET (palette, GST_BUFFER_FLAG_READONLY);
+        GST_BUFFER_DATA (palette) = (guint8 *) palette_data;
+        GST_BUFFER_SIZE (palette) = sizeof (guint32) * palette_count;
+
+        gst_caps_set_simple (stream->caps, "palette_data",
+            GST_TYPE_BUFFER, palette, NULL);
+        gst_buffer_unref (palette);
+      }
+    }
+  } else if (stream->subtype == FOURCC_soun) {
+    if (stream->caps) {
+      stream->caps = gst_caps_make_writable (stream->caps);
+      gst_caps_set_simple (stream->caps,
+          "rate", G_TYPE_INT, (int) stream->rate,
+          "channels", G_TYPE_INT, stream->n_channels, NULL);
+    }
+  }
+
+  if (stream->pad) {
+    GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
+
+    gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
+    gst_pad_set_query_type_function (stream->pad,
+                                     gst_qtdemux_get_src_query_types);
+    gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
+    gst_pad_set_active(stream->pad, TRUE);
+    gst_pad_use_fixed_caps (stream->pad);
+
+    GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
+    gst_pad_set_caps (stream->pad, stream->caps);
+
+  }
+  return;
+}
+static gboolean
+gst_qtdemux_add_stream (GstQTDemux * qtdemux,
+    QtDemuxStream * stream, GstTagList * list)
+{
+  /* consistent default for push based mode */
+ gst_segment_init (&stream->segment, GST_FORMAT_TIME);
+
+ if (stream->subtype == FOURCC_vide) {
+     gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
+
+     stream->pad =
+         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
+     g_free (name);
+     gst_qtdemux_configure_stream(qtdemux,stream);
+     qtdemux->n_video_streams++;
+ } else if (stream->subtype == FOURCC_soun) {
+     gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
+
+     stream->pad =
+          gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
+     g_free (name);
+     gst_qtdemux_configure_stream(qtdemux,stream);
+     qtdemux->n_audio_streams++;
+ }else if (stream->subtype == FOURCC_strm) {
+   GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
+#ifdef QTDEMUX_MODIFICATION
+ } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) {
+#else
+ } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
+#endif
+   gchar *name = g_strdup_printf ("subtitle_%02d", qtdemux->n_sub_streams);
+
+   stream->pad =
+       gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
+   g_free (name);
+   gst_qtdemux_configure_stream(qtdemux,stream);
+   qtdemux->n_sub_streams++;
+ } else {
+   GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
+   goto done;
+ }
 
-    child_fourcc = QT_FOURCC (buffer + 4);
 
-    if (child_fourcc == fourcc) {
-      if (parser) {
-        child_len = QT_UINT32 (buffer);
-        if (G_UNLIKELY (child_len < (4 + 4)))
-          return NULL;
-        /* FIXME: must verify if atom length < parent atom length */
-        gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
-      }
-      return child;
+  if (stream->pad) {
+    GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
+        GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
+    gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
+    if (stream->pending_tags)
+      gst_tag_list_free (stream->pending_tags);
+    stream->pending_tags = list;
+    if (list) {
+      /* post now, send event on pad later */
+      GST_DEBUG_OBJECT (qtdemux, "Posting tags %" GST_PTR_FORMAT, list);
+      gst_element_post_message (GST_ELEMENT (qtdemux),
+          gst_message_new_tag_full (GST_OBJECT (qtdemux), stream->pad,
+              gst_tag_list_copy (list)));
     }
+    /* global tags go on each pad anyway */
+    stream->send_global_tags = TRUE;
   }
-  return NULL;
-}
-
-static GNode *
-qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
-{
-  return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
+done:
+  return TRUE;
 }
-
+#else
+/* Deprecated */
 static gboolean
 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
     QtDemuxStream * stream, GstTagList * list)
@@ -5475,7 +7954,11 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
     qtdemux->n_audio_streams++;
   } else if (stream->subtype == FOURCC_strm) {
     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
+#ifdef QTDEMUX_MODIFICATION
+  } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) {
+#else
   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
+#endif
     gchar *name = g_strdup_printf ("subtitle_%02d", qtdemux->n_sub_streams);
 
     stream->pad =
@@ -5519,7 +8002,7 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
 done:
   return TRUE;
 }
-
+#endif
 /* find next atom with @fourcc starting at @offset */
 static GstFlowReturn
 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
@@ -5676,7 +8159,6 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
   }
 
   /* sync sample atom */
-  stream->stps_present = FALSE;
   if ((stream->stss_present =
           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
               &stream->stss) ? TRUE : FALSE) == TRUE) {
@@ -5693,29 +8175,6 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
         goto corrupt_file;
     }
-
-    /* partial sync sample atom */
-    if ((stream->stps_present =
-            ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
-                &stream->stps) ? TRUE : FALSE) == TRUE) {
-      /* copy atom data into a new buffer for later use */
-      stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
-
-      /* skip version + flags */
-      if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
-          !gst_byte_reader_get_uint32_be (&stream->stps,
-              &stream->n_sample_partial_syncs))
-        goto corrupt_file;
-
-      /* if there are no entries, the stss table contains the real
-       * sync samples */
-      if (stream->n_sample_partial_syncs) {
-        /* make sure there's enough data */
-        if (!qt_atom_parser_has_chunks (&stream->stps,
-                stream->n_sample_partial_syncs, 4))
-          goto corrupt_file;
-      }
-    }
   }
 
   /* sample size */
@@ -5878,9 +8337,13 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
     goto out_of_samples;
 
   GST_OBJECT_LOCK (qtdemux);
+#ifdef QTDEMUX_MODIFICATION
+  if (n <= stream->stbl_index && !qtdemux->need_parsing_moov)
+    goto already_parsed;
+#else
   if (n <= stream->stbl_index)
     goto already_parsed;
-
+#endif
   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
 
   if (!stream->stsz.data) {
@@ -6089,7 +8552,21 @@ done2:
             (guint) (cur - samples), j,
             GST_TIME_ARGS (gst_util_uint64_scale (stts_time, GST_SECOND,
                     stream->timescale)));
-
+#ifdef QTDEMUX_MODIFICATION
+      if(G_UNLIKELY (stream->subtype != FOURCC_text) && G_UNLIKELY (stream->subtype != FOURCC_sbtl) &&
+        G_UNLIKELY (stream->subtype != FOURCC_subp)) { /* can not make bogus code check for sub-titles */
+        if(gst_util_uint64_scale (stts_duration, GST_SECOND,stream->timescale) > QTDEMUX_MAX_SAMPLE_DURATION && stream->stts_samples ==1) {
+          GST_WARNING_OBJECT(qtdemux,"got the bogus duration and hence finding the last correct duration to replace with");
+          for(k = (guint)(cur - samples-1);k >= 0;k--) {
+            if(gst_util_uint64_scale (samples[k].duration, GST_SECOND,stream->timescale) < QTDEMUX_MAX_SAMPLE_DURATION) {
+              stts_duration = samples[k].duration;
+              GST_INFO_OBJECT(qtdemux,"find the last valid duration and replacing bogus duration with %d",samples[k].duration);
+              break;
+            }
+          }
+        }
+      }
+#endif
         cur->timestamp = stts_time;
         cur->duration = stts_duration;
 
@@ -6155,37 +8632,6 @@ done3:
         /* save state */
         stream->stss_index = i;
       }
-
-      /* stps marks partial sync frames like open GOP I-Frames */
-      if (stream->stps_present == TRUE) {
-        guint32 n_sample_partial_syncs;
-
-        n_sample_partial_syncs = stream->n_sample_partial_syncs;
-
-        /* if there are no entries, the stss table contains the real
-         * sync samples */
-        if (n_sample_partial_syncs) {
-          for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
-            /* note that the first sample is index 1, not 0 */
-            guint32 index;
-
-            index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
-
-            if (G_LIKELY (index > 0 && index <= n_samples)) {
-              index -= 1;
-              samples[index].keyframe = TRUE;
-              GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
-              /* and exit if we have enough samples */
-              if (G_UNLIKELY (index >= n)) {
-                i++;
-                break;
-              }
-            }
-          }
-          /* save state */
-          stream->stps_index = i;
-        }
-      }
     } else {
       /* no stss, all samples are keyframes */
       stream->all_keyframe = TRUE;
@@ -6359,6 +8805,21 @@ qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
     GST_DEBUG_OBJECT (qtdemux, "found %d non-empty segments", count);
     stream->n_segments = count;
   }
+
+#ifdef QTDEMUX_MODIFICATION
+  if (stream->n_segments) {
+    GstClockTime movie_duration =
+            gst_util_uint64_scale (stream->duration, GST_SECOND, stream->timescale);
+    /* Any difference between the movie's duration and the track's duration
+     * is expressed as an implicit empty edit */
+    if (stime != movie_duration) {
+      GST_WARNING_OBJECT (qtdemux, "Movie duration and track duration from segments "
+                                    "is not matching, so assuming empty edits");
+      stream->n_segments = 0;
+    }
+  }
+#endif
+
 done:
 
   /* push based does not handle segments, so act accordingly here,
@@ -6644,6 +9105,67 @@ bad_data:
   return 0;
 }
 
+#ifdef QTDEMUX_MODIFICATION
+static gboolean
+gst_codec_utils_hevc_caps_set_level_and_profile (GstCaps * caps,
+    const guint8 * sps, guint len)
+{
+  const gchar *level, *profile;
+
+  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
+  g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
+  g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "video/hevc"), FALSE);
+  g_return_val_if_fail (sps != NULL, FALSE);
+
+  level = gst_codec_utils_h264_get_level (sps, len);
+
+  if (level != NULL)
+    gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
+
+  profile = gst_codec_utils_h264_get_profile (sps, len);
+
+  if (profile != NULL)
+    gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
+
+  GST_LOG ("profile : %s", (profile) ? profile : "---");
+  GST_LOG ("level   : %s", (level) ? level : "---");
+
+  return (level != NULL && profile != NULL);
+}
+#endif
+
+#ifdef QTDEMUX_MODIFICATION
+static QtDemuxStream *
+_create_stream(GstQTDemux *qtdemux)
+{
+  QtDemuxStream *stream;
+  stream = g_new0 (QtDemuxStream, 1);
+  /* new streams always need a discont */
+  stream->discont = TRUE;
+  /* we enable clipping for raw audio/video streams */
+  stream->need_clip = FALSE;
+  stream->need_process = FALSE;
+  stream->segment_index = -1;
+  stream->time_position = 0;
+  stream->sample_index = -1;
+  stream->last_ret = GST_FLOW_OK;
+  /* dash specified */
+  stream->dash_seek_offset = GST_CLOCK_TIME_NONE;
+
+  stream->trickplay_info = g_new0 (TrickPlayInfo, 1);
+  stream->trickplay_info->prev_kidx = 0;
+  stream->trickplay_info->next_kidx = 0;
+  stream->trickplay_info->kidxs_dur_diff = 0;
+  stream->orientation = -1;
+  stream->prev_n_samples=0;
+  stream->moof_seeked_time = 0;
+
+  if (qtdemux->piff_fragmented)
+    stream->frag_queue = g_queue_new ();
+
+  return stream;
+}
+#endif
 /* parse the traks.
  * With each track we associate a new QtDemuxStream that contains all the info
  * about the trak.
@@ -6653,29 +9175,41 @@ static gboolean
 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
 {
   GstByteReader tkhd;
-  int offset;
-  GNode *mdia;
-  GNode *mdhd;
-  GNode *hdlr;
-  GNode *minf;
-  GNode *stbl;
-  GNode *stsd;
-  GNode *mp4a;
-  GNode *mp4v;
-  GNode *wave;
-  GNode *esds;
-  GNode *pasp;
-  QtDemuxStream *stream;
+  int offset = 0;
+  GNode *mdia = NULL;
+  GNode *mdhd = NULL;
+  GNode *hdlr = NULL;
+  GNode *minf = NULL;
+  GNode *stbl = NULL;
+  GNode *stsd = NULL;
+  GNode *mp4a = NULL;
+  GNode *mp4v = NULL;
+  GNode *wave = NULL;
+  GNode *esds = NULL;
+  GNode *pasp = NULL;
+  QtDemuxStream *stream = NULL;
   GstTagList *list = NULL;
   gchar *codec = NULL;
-  const guint8 *stsd_data;
-  guint16 lang_code;            /* quicktime lang code or packed iso code */
-  guint32 version;
+  const guint8 *stsd_data = NULL;
+  guint16 lang_code = 0;            /* quicktime lang code or packed iso code */
+  guint32 version = 0;
   guint32 tkhd_flags = 0;
   guint8 tkhd_version = 0;
-  guint32 fourcc;
-  guint value_size, len;
-
+  guint32 fourcc = 0;
+  guint value_size = 0, len = 0;
+#ifdef QTDEMUX_MODIFICATION
+  guint32 track_id;
+  guint32 a = 0;
+  guint32 b = 0;
+  guint32 c = 0;
+  guint32 d = 0;
+
+  guint16 layer = 0;
+  guint16 alternate_group = 0;
+  guint16 volume = 0;
+  GstClockTime duration = 0;
+  int height, width;
+#else
   stream = g_new0 (QtDemuxStream, 1);
   /* new streams always need a discont */
   stream->discont = TRUE;
@@ -6686,12 +9220,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
   stream->time_position = 0;
   stream->sample_index = -1;
   stream->last_ret = GST_FLOW_OK;
-#ifdef QTDEMUX_MODIFICATION
-  stream->trickplay_info = g_new0 (TrickPlayInfo, 1);
-  stream->trickplay_info->prev_kidx = 0;
-  stream->trickplay_info->next_kidx = 0;
-  stream->trickplay_info->kidxs_dur_diff = 0;
 #endif
+
   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
@@ -6700,12 +9230,117 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
   /* pick between 64 or 32 bits */
   value_size = tkhd_version == 1 ? 8 : 4;
   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
-      !gst_byte_reader_get_uint32_be (&tkhd, &stream->track_id))
+      !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
     goto corrupt_file;
 
+#ifdef QTDEMUX_MODIFICATION
+  if (!qtdemux->got_moov) {
+    if (!qtdemux->got_moov && qtdemux_find_stream (qtdemux, track_id))
+      goto existing_stream;
+    stream = _create_stream (qtdemux);
+    stream->track_id = track_id;
+  } else {
+    stream = qtdemux_find_stream (qtdemux, track_id);
+    if (!stream) {
+      GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
+      goto skip_track;
+    }
+  }
+#endif
+
   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
       tkhd_version, tkhd_flags, stream->track_id);
+#ifdef QTDEMUX_MODIFICATION
+  if (!gst_byte_reader_skip (&tkhd, 4))   //skipping for reserved bits
+    goto corrupt_file;
+
+  //reading duration from the tkhd atom, 64 bits if version is 1 and 32 bits if version is 0
+  if(tkhd_version == 1) {
+    if(gst_byte_reader_get_uint64_be (&tkhd, &duration)) {
+      GST_LOG_OBJECT(qtdemux, "the duration from tkhd field is %"GST_TIME_FORMAT, GST_TIME_ARGS(duration));
+    } else {
+      GST_LOG_OBJECT(qtdemux ,"no duration information present");
+      goto corrupt_file;
+    }
+  } else {
+    if(gst_byte_reader_get_uint32_be (&tkhd, &duration)) {
+      GST_LOG_OBJECT(qtdemux, "the duration from tkhd field is %"GST_TIME_FORMAT, GST_TIME_ARGS(duration));
+    } else {
+      GST_LOG_OBJECT(qtdemux, "no duration information present");
+      goto corrupt_file;
+    }
+  }
+
+  if(!gst_byte_reader_skip(&tkhd, 8)) {    //skipping for reserved
+    GST_LOG_OBJECT(qtdemux, "tkhd doesn't have more information");
+    goto corrupt_file;
+  }
+
+//reading layer, alternate_group and volume information from tkhd atom
+  if(!gst_byte_reader_get_uint16_be(&tkhd, &layer) ||
+     !gst_byte_reader_get_uint16_be(&tkhd, &alternate_group) ||
+     !gst_byte_reader_get_uint16_be(&tkhd, &volume)) {
+    GST_LOG_OBJECT(qtdemux, "tkhd doesn't have layer, group or volume information");
+    goto corrupt_file;
+  } else {
+    GST_LOG_OBJECT(qtdemux, "the layer info is %d", layer);
+    GST_LOG_OBJECT(qtdemux, "the alternate group info is %d", alternate_group);
+    GST_LOG_OBJECT(qtdemux, "the volume information is %d", volume);
+  }
+  if(!gst_byte_reader_skip(&tkhd, 2)) {  //skipping for reserved
+    GST_LOG_OBJECT(qtdemux, "no information present in tkhd");
+    goto corrupt_file;
+  }
+
+  //reading the orientation matrix information
+  if(!gst_byte_reader_get_uint32_be(&tkhd, &a) ||
+     !gst_byte_reader_get_uint32_be(&tkhd, &b)) {
+    GST_LOG_OBJECT(qtdemux, "No matrix information present");
+    goto corrupt_file;
+  } else {
+    GST_LOG_OBJECT(qtdemux, "matrix a and b info is %08x %08x", a, b);
+  }
+
+  if(!gst_byte_reader_skip(&tkhd, 4)) {  //skipping some unrelevant information
+    GST_LOG_OBJECT(qtdemux, "tkhd doesn't have more information");
+    goto corrupt_file;
+  }
+
+  if(!gst_byte_reader_get_uint32_be(&tkhd, &c) ||
+     !gst_byte_reader_get_uint32_be(&tkhd, &d)) {
+    goto corrupt_file;
+  } else {
+    GST_LOG_OBJECT(qtdemux, "c and d info is %08x %08x", c, d);
+  }
+
+  //Checking the orientation information with parsed matrix information
+  if(a == 0x00010000 && b == 0x00000000 && c == 0x00000000 && d == 0x00010000)
+    stream->orientation = 0;
+  if(a == 0x00000000 && b == 0x00010000 && c == 0xFFFF0000 && d == 0x00000000)
+    stream->orientation = 90;
+  if(a == 0xFFFF0000 && b == 0x00000000 && c == 0x00000000 && d == 0xFFFF0000)
+    stream->orientation = 180;
+  if(a == 0x00000000 && b == 0xFFFF0000 && c == 0x00010000 && d == 0x00000000)
+    stream->orientation = 270;
+
+  GST_INFO("the orientation is %d", stream->orientation);
+  int cur_pos =   gst_byte_reader_get_pos(&tkhd);
+  if(!gst_byte_reader_skip(&tkhd, 16)) {  //skipping some unrelevant information
+    GST_LOG_OBJECT(qtdemux, "tkhd doesn't have more information");
+    goto corrupt_file;
+  }
+
+  if(!gst_byte_reader_get_uint32_be(&tkhd, &height) ||
+     !gst_byte_reader_get_uint32_be(&tkhd, &width)) {
+    goto corrupt_file;
+  } else {
+    height = height >> 16;
+    width = width >> 16;
+    GST_LOG_OBJECT(qtdemux, "height and width info is %d %d", height, width);
+  }
 
+  gst_byte_reader_set_pos(&tkhd, cur_pos);
+#endif
   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
     goto corrupt_file;
 
@@ -6765,7 +9400,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
      * some of those trailers, nowadays, have prologue images that are
      * themselves vide tracks as well. I haven't really found a way to
      * identify those yet, except for just looking at their duration. */
-    if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
+    if ((stream->subtype == FOURCC_vide) && tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
       GST_WARNING_OBJECT (qtdemux,
           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
@@ -6817,9 +9452,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
   stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
       GST_FOURCC_ARGS (stream->fourcc));
-
+#ifdef QTDEMUX_MODIFICATION
+  if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) )
+#else
   if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
       ((fourcc & 0xFFFFFF00) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
+#endif
     goto error_encrypted;
 
   if (stream->subtype == FOURCC_vide) {
@@ -6828,9 +9466,15 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     stream->sampled = TRUE;
 
     /* version 1 uses some 64-bit ints */
+#ifdef QTDEMUX_MODIFICATION
+    if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
+        || !gst_byte_reader_get_uint32_be (&tkhd, &h))
+#else
     if (!gst_byte_reader_skip (&tkhd, 56 + value_size)
         || !gst_byte_reader_get_uint32_be (&tkhd, &w)
         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
+#endif
+
       goto corrupt_file;
 
     stream->display_width = w >> 16;
@@ -6842,6 +9486,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
 
     stream->width = QT_UINT16 (stsd_data + offset + 32);
     stream->height = QT_UINT16 (stsd_data + offset + 34);
+    if(stream->height == 0) {
+      stream->height = height;
+      GST_WARNING_OBJECT(qtdemux, "replacing height by tkhd since height obtained from stsd is zero");
+    }
+    if(stream->width == 0) {
+      stream->width = width;
+      GST_WARNING_OBJECT(qtdemux, "replacing width by tkhd since width obtained from stsd is zero");
+    }
     stream->fps_n = 0;          /* this is filled in later */
     stream->fps_d = 0;          /* this is filled in later */
     stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
@@ -6985,6 +9637,59 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
 
           break;
         }
+#ifdef QTDEMUX_MODIFICATION
+        case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
+        {
+          gint len = QT_UINT32 (stsd_data) - 0x66;
+          const guint8 *hevc_data = stsd_data + 0x66;
+
+          /* find hevc */
+          while (len >= 0x8) {
+            gint size;
+
+            if (QT_UINT32 (hevc_data) <= len)
+              size = QT_UINT32 (hevc_data) - 0x8;
+            else
+              size = len - 0x8;
+
+            if (size < 1)
+              /* No real data, so break out */
+              break;
+
+            switch (QT_FOURCC (hevc_data + 0x4)) {
+              case GST_MAKE_FOURCC ('h', 'v', 'c', 'C'):
+              {
+                /* parse, if found */
+                GstBuffer *buf;
+
+                GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
+
+                /* First 4 bytes are the length of the atom, the next 4 bytes
+                 * are the fourcc, the next 1 byte is the version, and the
+                 * subsequent bytes are sequence parameter set like data. */
+                //gst_codec_utils_hevc_caps_set_level_and_profile (stream->caps,
+                 //   hevc_data + 8 + 1, size - 1);
+
+                buf = gst_buffer_new_and_alloc (size);
+                memcpy (GST_BUFFER_DATA (buf), hevc_data + 0x8, size);
+                gst_caps_set_simple (stream->caps,
+                    "codec_data", GST_TYPE_BUFFER, buf, NULL);
+                gst_buffer_unref (buf);
+
+                break;
+              }
+
+              default:
+                break;
+            }
+
+            len -= size + 8;
+            hevc_data += size + 8;
+          }
+
+          break;
+        }
+#endif
         case FOURCC_mp4v:
         case FOURCC_MP4V:
         case FOURCC_fmp4:
@@ -7006,7 +9711,13 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
             guint8 *data;
             GstBuffer *buf;
             gint len;
-
+#ifdef QTDEMUX_MODIFICATION
+            gsize size_codec=0;
+            gint idx=0;
+            guint8 *vol1=NULL;
+            guint8 *vol_start=NULL;
+            guint8 *vo_start=NULL;
+#endif
             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
             data = glbl->data;
             len = QT_UINT32 (data);
@@ -7014,8 +9725,36 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
               len -= 0x8;
               buf = gst_buffer_new_and_alloc (len);
               memcpy (GST_BUFFER_DATA (buf), data + 8, len);
-              gst_caps_set_simple (stream->caps,
-                  "codec_data", GST_TYPE_BUFFER, buf, NULL);
+#ifdef QTDEMUX_MODIFICATION
+              vol1 = GST_BUFFER_DATA (buf);
+              size_codec=len;
+              while (idx < size_codec) {
+                if (vol1[idx] == 0x00 && vol1[idx+1] == 0x00 && vol1[idx+2] == 0x01 && (vol1[idx+3] >= 0x20 && vol1[idx+3] <= 0x2f)) {
+                  vol_start = vol1+idx+3;
+                  GST_DEBUG_OBJECT(qtdemux,"find the vol start  byte");
+                  break;
+                }
+                if (vol1[idx] == 0x00 && vol1[idx+1] == 0x00 && vol1[idx+2] == 0x01 && vol1[idx+3]==0xb5) {
+                  vo_start = vol1+idx+3;
+                  GST_DEBUG_OBJECT(qtdemux,"find the vo start  byte");
+                }
+                idx++;
+              }
+              GstMpeg4VideoObjectLayer * vol;
+              GstMpeg4VisualObject * vo;
+              vol=g_malloc(sizeof(GstMpeg4VideoObjectLayer));
+              vo=g_malloc(sizeof(GstMpeg4VisualObject));
+              vol->data_partitioned=0;
+              if (vo_start!=NULL && vol_start!=NULL) {
+                if (gst_mpeg4_parse_visual_object(vo,vo_start,size_codec)==GST_MPEG4_PARSER_OK) {
+                  gst_mpeg4_parse_video_object_layer (vol,vo,vol_start,size_codec);
+                }
+              }
+              gst_caps_set_simple (stream->caps,"data_partitioned", G_TYPE_BOOLEAN, vol->data_partitioned, NULL);
+              g_free(vol);
+              g_free(vo);
+#endif
+              gst_caps_set_simple (stream->caps,"codec_data", GST_TYPE_BUFFER, buf, NULL);
               gst_buffer_unref (buf);
             }
           }
@@ -7602,6 +10341,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
             }
           } else
             GST_DEBUG ("Didn't find waveheadernode for this codec");
+        } else {
+          GST_ERROR_OBJECT(qtdemux, "failed to parse node object");
+          return FALSE;
         }
         g_node_destroy (wavenode);
       }
@@ -7717,8 +10459,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
       goto unknown_stream;
     }
     stream->sampled = TRUE;
+#ifdef QTDEMUX_MODIFICATION
+  } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) {
+#else
   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
-
+#endif
     stream->sampled = TRUE;
 
     offset = 16;
@@ -7801,9 +10546,59 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     stream->sampled = TRUE;
   }
 
-  /* collect sample information */
-  if (!qtdemux_stbl_init (qtdemux, stream, stbl))
-    goto samples_failed;
+  /* collect sample information */
+#ifdef QTDEMUX_MODIFICATION
+  if(!qtdemux->got_moov){
+    if (!qtdemux_stbl_init (qtdemux, stream, stbl))
+      goto samples_failed;
+  }
+#else
+    if (!qtdemux_stbl_init (qtdemux, stream, stbl))
+      goto samples_failed;
+#endif
+#ifdef QTDEMUX_MODIFICATION
+  if(stream->caps && stream->subtype == FOURCC_soun) {
+    GstStructure *s;
+
+    if(stream->caps) {
+      float new_bitrate = 0;
+      gint bitrate = 0;
+      float duration;
+      float audio_stream_size;
+      GST_DEBUG("the details for bitrate are as follows timescale: %u sec", stream->timescale);
+      GST_DEBUG("duration is %" G_GUINT64_FORMAT, stream->duration);
+      GST_DEBUG("sample size is %u", stream->sample_size);
+      GST_DEBUG("sample count is %u", stream->n_samples);
+
+      //new_bitrate = (stream->sample_size * stream->n_samples) /(stream->duration/stream->timescale) * 8;
+      if(stream->timescale != 0) {
+        duration = (float)stream->duration/(float)stream->timescale;
+        audio_stream_size = (float)stream->sample_size * (float)stream->n_samples;
+        GST_DEBUG("the audio stream size is %f and duration is %f", audio_stream_size, duration);
+        if(duration != 0.0) {
+          new_bitrate = (audio_stream_size / duration) * 8;
+          GST_DEBUG("the new bitrate is %f", new_bitrate);
+        }
+      }
+
+      s = gst_caps_get_structure (stream->caps, 0);
+      gst_structure_get_int (s, "bitrate", &bitrate);
+      GST_DEBUG("the original bitrate is %u", bitrate);
+
+     /* some bitrate info may have ended up in caps */
+      if (bitrate <= 0.0 && new_bitrate > 0.0) {
+        GST_DEBUG("tagging the new bitrate");
+        bitrate = new_bitrate;
+        if (!list) {
+          GST_DEBUG("creating a new list for tag");
+          list = gst_tag_list_new ();
+        }
+        gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
+               bitrate, NULL);
+      }
+    }
+  }
+#endif
 
   if (qtdemux->fragmented) {
     guint32 dummy;
@@ -7844,26 +10639,58 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     lang_code = gst_tag_get_language_code (stream->lang_id);
     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
+#ifdef MULTI_AUDIO
+    if (stream->subtype == FOURCC_soun)
+      qtdemux->Language_list = g_list_append (qtdemux->Language_list,(lang_code) ? lang_code : stream->lang_id);
+#endif
+#ifdef QTDEMUX_MODIFICATION
+    if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) {
+      QtDemuxLanguageStruct* new = NULL;
+      new = g_new0 (QtDemuxLanguageStruct, 1);
+      new->language_code = (lang_code ? lang_code : stream->lang_id);
+      new->language_key = (lang_code ? lang_code : stream->lang_id);
+      new->active = FALSE;
+      qtdemux->Subtitle_language_list = g_list_append (qtdemux->Subtitle_language_list, new);
+    }
+#endif
   }
 
   /* now we are ready to add the stream */
   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
     goto too_many_streams;
 
-  stream->pending_tags = list;
-  qtdemux->streams[qtdemux->n_streams] = stream;
-  qtdemux->n_streams++;
-  GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
+#ifdef QTDEMUX_MODIFICATION
+  if(!qtdemux->got_moov) {
+    stream->pending_tags = list;
+    qtdemux->streams[qtdemux->n_streams] = stream;
+    qtdemux->n_streams++;
+    GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
+  }
+#else
+    stream->pending_tags = list;
+    qtdemux->streams[qtdemux->n_streams] = stream;
+    qtdemux->n_streams++;
+    GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
+#endif
 
   return TRUE;
 
 /* ERRORS */
+#ifdef QTDEMUX_MODIFICATION
+skip_track:
+  {
+    GST_INFO_OBJECT (qtdemux, "skip track");
+    g_free (stream);
+    return TRUE;
+  }
+#endif
 corrupt_file:
   {
     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
         (_("This file is corrupt and cannot be played.")), (NULL));
 #ifdef QTDEMUX_MODIFICATION
-    g_free (stream->trickplay_info);
+    if(stream && stream->trickplay_info)
+      g_free (stream->trickplay_info);
 #endif
     g_free (stream);
     return FALSE;
@@ -7889,6 +10716,14 @@ segments_failed:
     g_free (stream);
     return FALSE;
   }
+#ifdef QTDEMUX_MODIFICATION
+existing_stream:
+  {
+    GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
+                     track_id);
+    return TRUE;
+  }
+#endif
 unknown_stream:
   {
     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
@@ -8001,6 +10836,147 @@ gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
       GST_TAG_BITRATE, bitrate, NULL);
 }
 
+#ifdef QTDEMUX_MODIFICATION
+static GstFlowReturn
+qtdemux_prepare_streams (GstQTDemux * qtdemux)
+{
+  gint i;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  GST_DEBUG_OBJECT (qtdemux, "preparing streams");
+
+  for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
+    QtDemuxStream *stream = qtdemux->streams[i];
+    guint32 sample_num = 0;
+    guint samples = 20;
+    GArray *durations;
+
+    GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
+        i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
+    if (qtdemux->fragmented) {
+      /* need all moov samples first */
+      GST_OBJECT_LOCK (qtdemux);
+      while (stream->n_samples == 0)
+        if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
+          break;
+      GST_OBJECT_UNLOCK (qtdemux);
+    } else {
+      /* discard any stray moof */
+      qtdemux->moof_offset = 0;
+    }
+
+    /* prepare braking */
+    if (ret != GST_FLOW_ERROR)
+      ret = GST_FLOW_OK;
+
+    /* in pull mode, we should have parsed some sample info by now;
+     * and quite some code will not handle no samples.
+     * in push mode, we'll just have to deal with it */
+    if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
+      GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
+      gst_qtdemux_stream_free (qtdemux, stream);
+      memmove (&(qtdemux->streams[i]), &(qtdemux->streams[i + 1]),
+          sizeof (QtDemuxStream *) * (GST_QTDEMUX_MAX_STREAMS - i - 1));
+      qtdemux->streams[GST_QTDEMUX_MAX_STREAMS - 1] = NULL;
+      qtdemux->n_streams--;
+      i--;
+      continue;
+    }
+
+    /* parse number of initial sample to set frame rate cap */
+    while (sample_num < stream->n_samples && sample_num < samples) {
+      if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
+        break;
+      ++sample_num;
+    }
+    /* collect and sort durations */
+    samples = MIN (stream->stbl_index + 1, samples);
+    GST_DEBUG_OBJECT (qtdemux, "%d samples for framerate", samples);
+    if (samples) {
+      durations = g_array_sized_new (FALSE, FALSE, sizeof (guint32), samples);
+      sample_num = 0;
+      while (sample_num < samples) {
+        g_array_append_val (durations, stream->samples[sample_num].duration);
+        sample_num++;
+      }
+      g_array_sort (durations, less_than);
+      stream->min_duration = g_array_index (durations, guint32, samples / 2);
+      g_array_free (durations, TRUE);
+    }
+  }
+  return ret;
+}
+
+static GstFlowReturn
+qtdemux_expose_streams (GstQTDemux * qtdemux)
+{
+  gint i;
+  GstFlowReturn ret = GST_FLOW_OK;
+  GSList *oldpads = NULL;
+  GSList *iter;
+
+  GST_DEBUG_OBJECT (qtdemux, "exposing streams");
+
+  for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
+    QtDemuxStream *stream = qtdemux->streams[i];
+    GstPad *oldpad = stream->pad;
+    GstTagList *list;
+
+    GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
+                      i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
+
+    /* now we have all info and can expose */
+    list = stream->pending_tags;
+    stream->pending_tags = NULL;
+    if (oldpad)
+      oldpads = g_slist_prepend (oldpads, oldpad);
+    gst_qtdemux_add_stream (qtdemux, stream, list);
+#ifdef DRM_ENABLE
+    if (qtdemux->encrypt_content && stream->subtype == FOURCC_vide) {
+      GstEvent* drm_custom_event = NULL;
+      drm_custom_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+                                                 gst_structure_new ("Content_Is_DRM_Playready", NULL));
+      GST_DEBUG_OBJECT (qtdemux, "sending custom event to xvimagesink for playready content");
+      if (!gst_pad_push_event (stream->pad, drm_custom_event))
+        GST_ERROR_OBJECT (qtdemux, "failed to push custom event for drm playready content");
+    }
+#endif
+  }
+
+  gst_qtdemux_guess_bitrate (qtdemux);
+
+  gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
+
+  for (iter = oldpads; iter; iter = g_slist_next (iter)) {
+    GstPad *oldpad = iter->data;
+
+    gst_pad_push_event (oldpad, gst_event_new_eos ());
+    gst_pad_set_active (oldpad, FALSE);
+    gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
+    gst_object_unref (oldpad);
+  }
+
+  /* check if we should post a redirect in case there is a single trak
+   * and it is a redirecting trak */
+  if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
+    GstMessage *m;
+
+    qtdemux_post_global_tags (qtdemux);
+
+    GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
+        "an external content");
+    m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
+        gst_structure_new ("redirect",
+            "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
+            NULL));
+    gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
+    qtdemux->posted_redirect = TRUE;
+  }
+
+  return ret;
+}
+#else
+/* Deprecated */
 static GstFlowReturn
 qtdemux_expose_streams (GstQTDemux * qtdemux)
 {
@@ -8100,6 +11076,7 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
   return ret;
 }
 
+#endif
 /* check if major or compatible brand is 3GP */
 static inline gboolean
 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
@@ -8926,8 +11903,6 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
   if (QT_FOURCC (data + 4) == FOURCC_____ ||
       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
     style = "itunes";
-  else if (demux->major_brand == FOURCC_qt__)
-    style = "quicktime";
   /* fall back to assuming iso/3gp tag style */
   else
     style = "iso";
@@ -9116,82 +12091,6 @@ qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
 static gboolean
 qtdemux_parse_redirects (GstQTDemux * qtdemux)
 {
-  GNode *rmra, *rmda, *rdrf;
-
-  rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
-  if (rmra) {
-    GList *redirects = NULL;
-
-    rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
-    while (rmda) {
-      GstQtReference ref = { NULL, NULL, 0, 0 };
-      GNode *rmdr, *rmvc;
-
-      if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
-        ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
-        GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
-            ref.min_req_bitrate);
-      }
-
-      if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
-        guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
-        guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
-
-#ifndef GST_DISABLE_GST_DEBUG
-        guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
-#endif
-        guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
-
-        GST_LOG_OBJECT (qtdemux,
-            "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
-            ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
-            bitmask, check_type);
-        if (package == FOURCC_qtim && check_type == 0) {
-          ref.min_req_qt_version = version;
-        }
-      }
-
-      rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
-      if (rdrf) {
-        guint32 ref_type;
-        guint8 *ref_data;
-
-        ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
-        ref_data = (guint8 *) rdrf->data + 20;
-        if (ref_type == FOURCC_alis) {
-          guint record_len, record_version, fn_len;
-
-          /* MacOSX alias record, google for alias-layout.txt */
-          record_len = QT_UINT16 (ref_data + 4);
-          record_version = QT_UINT16 (ref_data + 4 + 2);
-          fn_len = QT_UINT8 (ref_data + 50);
-          if (record_len > 50 && record_version == 2 && fn_len > 0) {
-            ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
-          }
-        } else if (ref_type == FOURCC_url_) {
-          ref.location = g_strdup ((gchar *) ref_data);
-        } else {
-          GST_DEBUG_OBJECT (qtdemux,
-              "unknown rdrf reference type %" GST_FOURCC_FORMAT,
-              GST_FOURCC_ARGS (ref_type));
-        }
-        if (ref.location != NULL) {
-          GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
-          redirects = g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
-        } else {
-          GST_WARNING_OBJECT (qtdemux,
-              "Failed to extract redirect location from rdrf atom");
-        }
-      }
-
-      /* look for others */
-      rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
-    }
-
-    if (redirects != NULL) {
-      qtdemux_process_redirects (qtdemux, redirects);
-    }
-  }
   return TRUE;
 }
 
@@ -9207,8 +12106,6 @@ qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
     fmt = "Motion JPEG 2000";
   else if ((qtdemux->major_brand & 0xffff) == GST_MAKE_FOURCC ('3', 'g', 0, 0))
     fmt = "3GP";
-  else if (qtdemux->major_brand == FOURCC_qt__)
-    fmt = "Quicktime";
   else if (qtdemux->fragmented)
     fmt = "ISO fMP4";
   else
@@ -9230,14 +12127,17 @@ qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
 static gboolean
 qtdemux_parse_tree (GstQTDemux * qtdemux)
 {
-  GNode *mvhd;
-  GNode *trak;
-  GNode *udta;
-  GNode *mvex;
-  gint64 duration;
-  guint64 creation_time;
+  GNode *mvhd = NULL;
+  GNode *trak = NULL;
+  GNode *udta = NULL;
+  GNode *mvex = NULL;
+  gint64 duration = 0;
+  guint64 creation_time = 0;
   GstDateTime *datetime = NULL;
-  gint version;
+  gint version = 0;
+#ifdef QTDEMUX_MODIFICATION
+  GNode *uuid_node;
+#endif
 
   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
   if (mvhd == NULL) {
@@ -9322,8 +12222,33 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
     /* iterate all siblings */
     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
   }
-
-  /* find tags */
+#ifdef MULTI_AUDIO
+  if(qtdemux->Language_list != NULL)
+  {
+        GstMessage *m;
+        m = gst_message_new_element(GST_OBJECT_CAST(qtdemux),gst_structure_new("Language_list","lang_list",G_TYPE_POINTER,qtdemux->Language_list,NULL));
+        gst_element_post_message(GST_ELEMENT_CAST(qtdemux),m);
+  }
+#endif
+#ifdef QTDEMUX_MODIFICATION
+  if (qtdemux->Subtitle_language_list != NULL) {
+    QtDemuxLanguageStruct* First_Language = g_list_nth_data (qtdemux->Subtitle_language_list, 0);
+    First_Language->active = TRUE;
+    GstMessage *m;
+    m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
+                                 gst_structure_new ("Int_Sub_Language_List", "lang_list",
+                                 G_TYPE_POINTER, qtdemux->Subtitle_language_list, NULL));
+    gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
+  }
+  uuid_node = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_uuid);
+#ifdef DRM_ENABLE
+  if (uuid_node && qtdemux->protection_header_present) {
+    GST_INFO_OBJECT(qtdemux,"calling qtdemux_playready_parse_uuid");
+    return qtdemux_playready_parse_uuid(uuid_node,qtdemux);
+  }
+#endif // DRM_ENABLE
+#endif
+/* find tags */
   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
   if (udta) {
     qtdemux_parse_udta (qtdemux, udta);
@@ -9556,10 +12481,43 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
   /* Add the codec_data attribute to caps, if we have it */
   if (data_ptr) {
     GstBuffer *buffer;
+#ifdef QTDEMUX_MODIFICATION
+    gsize size_codec=0;
+    gint idx=0;
+    guint8 *vol1=NULL;
+    guint8 *vo_start=NULL;
+    guint8 *vol_start=NULL;
+    GstMpeg4VideoObjectLayer * vol;
+    GstMpeg4VisualObject * vo;
+#endif
 
     buffer = gst_buffer_new_and_alloc (data_len);
     memcpy (GST_BUFFER_DATA (buffer), data_ptr, data_len);
-
+#ifdef QTDEMUX_MODIFICATION
+    GST_DEBUG_OBJECT (qtdemux,"found not glbl data in stsd");
+    size_codec=data_len;
+    vol1 = GST_BUFFER_DATA (buffer);
+    while (idx < size_codec) {
+      if (vol1[idx] == 0x00 && vol1[idx+1] == 0x00 && vol1[idx+2] == 0x01 && (vol1[idx+3] >= 0x20 && vol1[idx+3] <= 0x2f)) {
+        vol_start = vol1+idx+3;
+        GST_DEBUG_OBJECT(qtdemux,"find the vol byte");
+        break;
+      }
+      if (vol1[idx] == 0x00 && vol1[idx+1] == 0x00 && vol1[idx+2] == 0x01 && vol1[idx+3]==0xb5) {
+        vo_start = vol1+idx+3;
+        GST_DEBUG_OBJECT(qtdemux,"find the VO  byte");
+      }
+      idx++;
+    }
+    vol=g_malloc(sizeof(GstMpeg4VideoObjectLayer));
+    vo=g_malloc(sizeof(GstMpeg4VisualObject));
+    vol->data_partitioned=0;
+    if (vo_start!=NULL && vol_start!=NULL) {
+      if (gst_mpeg4_parse_visual_object(vo,vo_start,size_codec)==GST_MPEG4_PARSER_OK){
+        gst_mpeg4_parse_video_object_layer (vol,vo, vol_start,size_codec);
+      }
+    }
+#endif
     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
 
@@ -9569,10 +12527,10 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
       gboolean err = TRUE;
       int i;
 
-      GST_ERROR_OBJECT (qtdemux, "Checking for the Possibility of H263");
+      GST_INFO_OBJECT (qtdemux, "Checking for the Possibility of H263");
       for(i=0; i<data_len-4; i++) {
         if(QT_UINT32(data_ptr+i) == 0x00000120) {
-          GST_ERROR_OBJECT (qtdemux, "Found the VOL Marker in DCI Info, It is MPEG-4 Content");
+          GST_INFO_OBJECT (qtdemux, "Found the VOL Marker in DCI Info, It is MPEG-4 Content");
           err = FALSE;
           break;
         }
@@ -9586,7 +12544,11 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
       }
     }
 #endif
-
+#ifdef QTDEMUX_MODIFICATION
+    gst_caps_set_simple (stream->caps,"data_partitioned", G_TYPE_BOOLEAN, vol->data_partitioned, NULL);
+    g_free(vol);
+    g_free(vo);
+#endif
     gst_caps_set_simple (stream->caps, "codec_data", GST_TYPE_BUFFER,
         buffer, NULL);
     gst_buffer_unref (buffer);
@@ -9917,6 +12879,12 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
           NULL);
       break;
+#ifdef QTDEMUX_MODIFICATION
+    case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
+      _codec ("HEVC");
+      caps = gst_caps_from_string ("video/hevc");
+      break;
+#endif
     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
     default:
     {
@@ -9929,6 +12897,12 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     }
   }
 
+#ifdef QTDEMUX_MODIFICATION
+  if(stream->orientation != -1) {
+    gst_caps_set_simple (caps, "orientation", G_TYPE_INT, stream->orientation, NULL);
+  }
+#endif
+
   /* enable clipping for raw video streams */
   s = gst_caps_get_structure (caps, 0);
   name = gst_structure_get_name (s);
@@ -10216,7 +13190,10 @@ gst_qtdemux_forward_trickplay (GstQTDemux * qtdemux, QtDemuxStream * stream, gui
 
         /* find no.of samples between present and previous key frames */
         nsamples = stream->trickplay_info->next_kidx - stream->trickplay_info->prev_kidx;
-
+        if(nsamples == 0){
+          GST_LOG_OBJECT (qtdemux, "nsamples comes as 0.. not applying trickplay algo");
+          return;
+        }
         /* find average duration between key frames */
         stream->trickplay_info->kidxs_dur_diff = (QTSAMPLE_PTS (stream, &stream->samples[stream->trickplay_info->next_kidx]) -
                                                                        QTSAMPLE_PTS (stream, &stream->samples[stream->trickplay_info->prev_kidx])) /
@@ -10316,5 +13293,193 @@ beach:
   return new_index;
 }
 
+#ifdef DRM_ENABLE
+/* Provides key to decrypt encrypted data.*/
+static gboolean
+qtdemux_get_playready_licence (GstQTDemux * qtdemux, unsigned char * data, guint size, char* query_file_path)
+{
+  int ret = -1;
+  char *tok = NULL;
+  char *parse_string = NULL;
+  char *parse_sub_string = NULL;
+  int query_length = 0;
+  int count = 0;
+  drm_trusted_piff_get_license_info_s license_info;
+  drm_trusted_request_type_e request_type = DRM_TRUSTED_REQ_TYPE_PIFF_GET_LICENSE;
+  GST_DEBUG_OBJECT(qtdemux,"size is %d",size);
+  memset(&license_info, 0x00, sizeof(drm_trusted_piff_get_license_info_s));
+
+  query_length = strlen(query_file_path);
+  license_info.lic_header.header = (unsigned char*)data;
+  license_info.lic_header.header_len = size;
+  //license_info.content_provider = DRM_TRUSTED_CONTENT_PROVIDER_VIDEO_HUB;
+
+  GST_DEBUG("filepath infor is %s and lenght is %d", query_file_path, query_length);
+  parse_string = (char*)malloc(sizeof(char) * (query_length + 1));
+  if(parse_string == NULL) {
+     GST_ERROR_OBJECT(qtdemux, "Failed to allocate memory");
+     return FALSE;
+  }
+  strncpy(parse_string, query_file_path, query_length);
+  parse_string[query_length] = '\0';
+  GST_DEBUG("parse string infor is %s and lenght is %d", parse_string, query_length);
+
+  parse_sub_string = strstr(parse_string, "[]<>");
+  GST_DEBUG("filepath infor is %s", parse_sub_string);
+
+  tok = strtok(parse_sub_string, "[]<>");
+  while(tok != NULL) {
+    GST_DEBUG("some info %s", tok);
+    count++;
+    if(count == 1)
+      strcpy(license_info.custom_data.app_id, tok);
+    if(count == 2)
+      strcpy(license_info.custom_data.user_guid, tok);
+    if(count == 3)
+      strcpy(license_info.custom_data.device_id, tok);
+    if(count == 4)
+      strcpy(license_info.custom_data.order_id, tok);
+    if(count == 5)
+      strcpy(license_info.custom_data.mv_id, tok);
+    if(count == 6)
+      strcpy(license_info.custom_data.svr_id, tok);
+    tok = strtok(NULL, "[]<>");
+  }
+  free (parse_string);
+  ret = drm_trusted_handle_request (request_type, (void *) &license_info, NULL);
+  GST_DEBUG_OBJECT(qtdemux, "return value from drm handle request is 0x%x", ret);
+  if (DRM_TRUSTED_RETURN_SUCCESS != ret) {
+    GST_ERROR_OBJECT (qtdemux,"failed to get license...");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT_NOKEY, ("failed to get playready license"), (NULL));
+    return FALSE;
+  }
+
+  GST_INFO_OBJECT (qtdemux, "Got license....\n");
+
+  return TRUE;
+}
+
+void
+test_drm_trusted_operation_cb(drm_trusted_user_operation_info_s *operation_info, void *output_data)
+{
+  GST_DEBUG ("Callback Hit:test_drm_trusted_operation_cb\n");
+  GST_DEBUG ("operation_status=%d\n",operation_info->operation_status);
+  GST_DEBUG ("operation_type=%d\n",operation_info->operation_type);
+}
+
+/* Find out which uuid type is present in uuid node.
+    and returns uuid_type present in uuid node.*/
+
+static uuid_type_t
+qtdemux_get_uuid_type(GstQTDemux * qtdemux, GstByteReader *uuid_data, gint64 *uuid_offset)
+{
+  guint32 box_len = 0;
+  guint64 box_long_len = 0;
+  gchar uuid[16] = {0,};
+  int i = 0;
+
+  if (!gst_byte_reader_get_uint32_be (uuid_data, &box_len))
+    goto invalid_uuid;
+
+  /* Skipping fourcc */
+  if (!gst_byte_reader_skip (uuid_data, 4))
+    goto invalid_uuid;
+  if (box_len == 1) {
+    GST_WARNING_OBJECT (qtdemux, "TfxdBoxLongLength field is present...");
+    if (!gst_byte_reader_get_uint64_be (uuid_data, &box_long_len))
+      goto invalid_uuid;
+
+    GST_DEBUG_OBJECT (qtdemux, "tfxd long length = %llu", box_long_len);
+
+    *uuid_offset = box_long_len;
+  } else {
+    GST_DEBUG_OBJECT (qtdemux, "Box Len = %d", (box_len));
+    *uuid_offset = box_len;
+  }
+
+  for (i = 0; i < sizeof (uuid); i++) {
+    if (!gst_byte_reader_get_uint8 (uuid_data, &(uuid[i])))
+      goto invalid_uuid;
+  }
+
+  if (!memcmp(uuid, tfxd_uuid, sizeof (uuid_t))) {
+    GST_INFO_OBJECT (qtdemux, "Found TFXD box");
+    return UUID_TFXD;
+  } else if (!memcmp(uuid, tfrf_uuid, sizeof (uuid_t))) {
+    GST_INFO_OBJECT (qtdemux, "Found TFRF box");
+    return UUID_TFRF;
+  } else if (!memcmp(uuid, encrypt_uuid, sizeof (uuid_t))) {
+    GST_INFO_OBJECT (qtdemux,"Found sample encryption box");
+    return UUID_SAMPLE_ENCRYPT;
+  } else if (!memcmp(uuid, protection_uuid, sizeof (uuid_t))) {
+    GST_INFO_OBJECT (qtdemux,"Found protection header box");
+    for (i = 0; i < sizeof (uuid); i++) {
+      qtdemux->uuid_protection[i] = uuid[i];
+    }
+    return UUID_PROTECTION_HEADER;
+  } else {
+    GST_WARNING_OBJECT (qtdemux, "Not an valid UUID box..");
+    goto invalid_uuid;
+  }
+
+invalid_uuid:
+  GST_ERROR_OBJECT (qtdemux, "Error in parsing UUID atom...");
+  return UUID_UNKNOWN;
+}
+
+/*Authenticating whether valid play ready system ID is present in uuid node or not.*/
+
+static gboolean
+qtdemux_parse_playready_system_id(GstQTDemux * qtdemux, GstByteReader *uuid_data)
+{
+  //gchar uuid[16] = {0,};
+  guint i;
+  if (!gst_byte_reader_skip (uuid_data, 4))
+    goto invalid_uuid;
+
+  for (i = 0; i < sizeof (qtdemux->uuid_playready); i++){
+    if (!gst_byte_reader_get_uint8 (uuid_data, &(qtdemux->uuid_playready[i])))
+      goto invalid_uuid;
+  }
+
+  if (!memcmp(qtdemux->uuid_playready, playready_system_id, sizeof (uuid_t))){
+    GST_INFO_OBJECT (qtdemux, "Found Play Ready System ID");
+    return TRUE;
+  }
+
+  if (!memcmp(qtdemux->uuid_playready, dash_playready_system_id, sizeof (uuid_t))){
+    GST_INFO_OBJECT (qtdemux, "Found DASH Play Ready System ID");
+    return TRUE;
+  }
+
+invalid_uuid:
+  GST_ERROR_OBJECT (qtdemux, "Invalid system ID...");
+  return FALSE;
+}
+
+static void
+qtdemux_post_drm_error (GstQTDemux * qtdemux, int drm_error)
+{
+  switch (drm_error) {
+    case DRM_LICENSE_STATUS_EXPIRED:
+    GST_ERROR_OBJECT (qtdemux, "posting error as rights expired");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT_NOKEY, ("rights expired"), (NULL));
+    break;
+    case DRM_LICENSE_STATUS_NO_LICENSE:
+    GST_ERROR_OBJECT (qtdemux, "posting error as no rights");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT_NOKEY, ("no rights"), (NULL));
+    break;
+    case DRM_LICENSE_STATUS_FUTURE_USE:
+    GST_ERROR_OBJECT (qtdemux, "posting error as rights for future");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT_NOKEY, ("has future rights"), (NULL));
+    break;
+    case DRM_LICENSE_STATUS_UNDEFINED:
+    default:
+    GST_ERROR_OBJECT (qtdemux, "posting error as undefined");
+    GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT_NOKEY, ("undefind error"), (NULL));
+    break;
+  }
+}
+#endif
 #endif
 
old mode 100644 (file)
new mode 100755 (executable)
index dd60dcc..71bd4a2
 #include <gst/base/gstadapter.h>
 
 #define QTDEMUX_MODIFICATION
+#define MULTI_AUDIO 1
 
 #ifdef QTDEMUX_MODIFICATION
 #include <stdio.h>
+#ifdef DRM_ENABLE
+#include <drm_client.h>
+#include <drm_trusted_client.h>
+#include <drm_client_types.h>
+#include <drm_trusted_client_types.h>
+#endif
+#include <gst/base/gstbitreader.h>
 #endif
 
 G_BEGIN_DECLS
@@ -58,6 +66,149 @@ typedef struct _GstQTDemux GstQTDemux;
 typedef struct _GstQTDemuxClass GstQTDemuxClass;
 typedef struct _QtDemuxStream QtDemuxStream;
 
+#ifdef QTDEMUX_MODIFICATION
+typedef struct _GstMpeg4VideoObjectLayer        GstMpeg4VideoObjectLayer;
+typedef struct _GstMpeg4VisualObject            GstMpeg4VisualObject;
+typedef struct _QtDemuxDrm QtDemuxDrm;
+typedef enum {
+  GST_MPEG4_SQUARE        = 0x01,
+  GST_MPEG4_625_TYPE_4_3  = 0x02,
+  GST_MPEG4_525_TYPE_4_3  = 0x03,
+  GST_MPEG4_625_TYPE_16_9 = 0x04,
+  GST_MPEG4_525_TYPE_16_9 = 0x05,
+  GST_MPEG4_EXTENDED_PAR  = 0x0f,
+} GstMpeg4AspectRatioInfo;
+typedef enum {
+  GST_MPEG4_VIDEO_ID         = 0x01,
+  GST_MPEG4_STILL_TEXTURE_ID = 0x02,
+  GST_MPEG4_STILL_MESH_ID    = 0x03,
+  GST_MPEG4_STILL_FBA_ID     = 0x04,
+  GST_MPEG4_STILL_3D_MESH_ID = 0x05,
+  /*... reserved */
+
+} GstMpeg4VisualObjectType;
+typedef enum {
+  /* Other value are reserved */
+  GST_MPEG4_CHROMA_4_2_0 = 0x01
+} GstMpeg4ChromaFormat;
+typedef enum {
+  GST_MPEG4_RECTANGULAR,
+  GST_MPEG4_BINARY,
+  GST_MPEG4_BINARY_ONLY,
+  GST_MPEG4_GRAYSCALE
+} GstMpeg4VideoObjectLayerShape;
+typedef enum {
+  GST_MPEG4_SPRITE_UNUSED,
+  GST_MPEG4_SPRITE_STATIC,
+  GST_MPEG4_SPRITE_GMG
+} GstMpeg4SpriteEnable;
+typedef enum {
+  GST_MPEG4_PARSER_OK,
+  GST_MPEG4_PARSER_BROKEN_DATA,
+  GST_MPEG4_PARSER_NO_PACKET,
+  GST_MPEG4_PARSER_NO_PACKET_END,
+  GST_MPEG4_PARSER_ERROR,
+} GstMpeg4ParseResult;
+struct _GstMpeg4VideoObjectLayer {
+  guint8 random_accessible_vol;
+  guint8 video_object_type_indication;
+
+  guint8 is_object_layer_identifier;
+  /* if is_object_layer_identifier */
+  guint8 verid;
+  guint8 priority;
+
+  GstMpeg4AspectRatioInfo aspect_ratio_info;
+  guint8 par_width;
+  guint8 par_height;
+
+  guint8 control_parameters;
+  /* if control_parameters */
+  GstMpeg4ChromaFormat chroma_format;
+  guint8 low_delay;
+  guint8 vbv_parameters;
+  /* if vbv_parameters */
+  guint16 first_half_bitrate;
+  guint16 latter_half_bitrate;
+  guint16 first_half_vbv_buffer_size;
+  guint16 latter_half_vbv_buffer_size;
+  guint16 first_half_vbv_occupancy;
+  guint16 latter_half_vbv_occupancy;
+
+  /* Computed values */
+  guint32 bit_rate;
+  guint32 vbv_buffer_size;
+
+  GstMpeg4VideoObjectLayerShape shape;
+  /* if shape == GST_MPEG4_GRAYSCALE && verid =! 1 */
+  guint8 shape_extension;
+
+  guint16 vop_time_increment_resolution;
+  guint8 vop_time_increment_bits;
+  guint8 fixed_vop_rate;
+  /* if fixed_vop_rate */
+  guint16 fixed_vop_time_increment;
+
+  guint16 width;
+  guint16 height;
+  guint8 interlaced;
+  guint8 obmc_disable;
+
+  GstMpeg4SpriteEnable sprite_enable;
+  /* if vol->sprite_enable == SPRITE_GMG or SPRITE_STATIC*/
+  /* if vol->sprite_enable != GST_MPEG4_SPRITE_GMG */
+  guint16 sprite_width;
+  guint16 sprite_height;
+  guint16 sprite_left_coordinate;
+  guint16 sprite_top_coordinate;
+
+  guint8 no_of_sprite_warping_points;
+  guint8 sprite_warping_accuracy;
+  guint8 sprite_brightness_change;
+  /* if vol->sprite_enable != GST_MPEG4_SPRITE_GMG */
+  guint8 low_latency_sprite_enable;
+
+  /* if shape != GST_MPEG4_RECTANGULAR */
+  guint8 sadct_disable;
+
+  guint8 not_8_bit;
+
+  /* if no_8_bit */
+  guint8 quant_precision;
+  guint8 bits_per_pixel;
+
+  /* if shape == GRAYSCALE */
+  guint8 no_gray_quant_update;
+  guint8 composition_method;
+  guint8 linear_composition;
+
+  guint8 quant_type;
+  /* if quant_type */
+  guint8 load_intra_quant_mat;
+  guint8 intra_quant_mat[64];
+  guint8 load_non_intra_quant_mat;
+  guint8 non_intra_quant_mat[64];
+
+  guint8 quarter_sample;
+  guint8 complexity_estimation_disable;
+  guint8 resync_marker_disable;
+  guint8 data_partitioned;
+  guint8 reversible_vlc;
+  guint8 newpred_enable;
+  guint8 reduced_resolution_vop_enable;
+  guint8 scalability;
+  guint8 enhancement_type;
+
+  //GstMpeg4VideoPlaneShortHdr short_hdr;
+};
+struct _GstMpeg4VisualObject {
+  guint8 is_identifier;
+  /* If is_identifier */
+  guint8 verid;
+  guint8 priority;
+ GstMpeg4VisualObjectType type;
+};
+#endif
 struct _GstQTDemux {
   GstElement element;
 
@@ -77,7 +228,6 @@ struct _GstQTDemux {
 
   guint32 timescale;
   guint64 duration;
-
   gboolean fragmented;
   /* offset of the mfra atom */
   guint64 mfra_offset;
@@ -118,14 +268,49 @@ struct _GstQTDemux {
 
   gboolean upstream_seekable;
   gboolean upstream_size;
-
+#ifdef MULTI_AUDIO
+  GList *Language_list;
+#endif
 #ifdef QTDEMUX_MODIFICATION
+  /*For smooth streaming*/
+  gboolean is_dash;
+  gint64 dash_init_offset;
+  gint video_max_width;
+  gint video_max_height;
+
+  gboolean protection_header_present;
   FILE* file;
   FILE* ofile;
   gchar* filename;
   guint filesize;
   guint maxbuffersize;
   gboolean fwdtrick_mode;
+#ifdef DRM_ENABLE
+  gboolean encrypt_content;
+  DRM_DECRYPT_HANDLE pr_handle;
+  gchar uuid_playready[16];
+  gchar uuid_protection[16];
+#endif
+  gboolean piff_fragmented;
+  GstClockTime max_pop_ts;
+  gboolean playback_protected;
+  gboolean need_parsing_moov;
+  gint iv_size_video;
+  gint iv_size_audio;
+  gchar **iv_data_video;
+  gchar **iv_data_audio;
+  gint sequence_id;
+  gint sample_count[2];
+  gint current_sample[2];
+  gint *sub_sample_count;
+  gint *clear_data;
+  gint *encrypted_data;
+  gboolean dash_content;
+  gint no_of_audio_samples;
+  gint no_of_video_samples;
+  GArray *moof_offsets;
+  gboolean need_moof_parsing;
+  GList *Subtitle_language_list;
 #endif
 };
 
index fa66767..a45afd9 100644 (file)
@@ -330,27 +330,6 @@ qtdemux_dump_stts (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 }
 
 gboolean
-qtdemux_dump_stps (GstQTDemux * qtdemux, GstByteReader * data, int depth)
-{
-  guint32 ver_flags = 0, num_entries = 0, i;
-
-  if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
-      !gst_byte_reader_get_uint32_be (data, &num_entries))
-    return FALSE;
-
-  GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
-  GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
-
-  if (!qt_atom_parser_has_chunks (data, num_entries, 4))
-    return FALSE;
-
-  for (i = 0; i < num_entries; i++) {
-    GST_LOG ("%*s    sample:        %u", depth, "", GET_UINT32 (data));
-  }
-  return TRUE;
-}
-
-gboolean
 qtdemux_dump_stss (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 {
   guint32 ver_flags = 0, num_entries = 0, i;
@@ -489,27 +468,6 @@ qtdemux_dump_co64 (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 }
 
 gboolean
-qtdemux_dump_dcom (GstQTDemux * qtdemux, GstByteReader * data, int depth)
-{
-  if (!qt_atom_parser_has_remaining (data, 4))
-    return FALSE;
-
-  GST_LOG ("%*s  compression type: %" GST_FOURCC_FORMAT, depth, "",
-      GST_FOURCC_ARGS (GET_FOURCC (data)));
-  return TRUE;
-}
-
-gboolean
-qtdemux_dump_cmvd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
-{
-  if (!qt_atom_parser_has_remaining (data, 4))
-    return FALSE;
-
-  GST_LOG ("%*s  length: %d", depth, "", GET_UINT32 (data));
-  return TRUE;
-}
-
-gboolean
 qtdemux_dump_mfro (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 {
   if (!qt_atom_parser_has_remaining (data, 4))
@@ -721,6 +679,28 @@ qtdemux_dump_mehd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 }
 
 gboolean
+qtdemux_dump_tfdt (GstQTDemux * qtdemux, GstByteReader * data, int depth)
+{
+  guint32 version = 0;
+  guint64 decode_time;
+  guint value_size;
+
+  if (!gst_byte_reader_get_uint32_be (data, &version))
+    return FALSE;
+
+  GST_LOG ("%*s  version/flags: %08x", depth, "", version);
+
+  value_size = ((version >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
+  if (qt_atom_parser_get_offset (data, value_size, &decode_time)) {
+    GST_LOG ("%*s  Track fragment decode time: %" G_GUINT64_FORMAT,
+        depth, "", decode_time);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+gboolean
 qtdemux_dump_sdtp (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 {
   guint32 version;
index 9bb1f95..988c822 100644 (file)
@@ -45,8 +45,6 @@ gboolean qtdemux_dump_stts (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
 gboolean qtdemux_dump_stss (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
-gboolean qtdemux_dump_stps (GstQTDemux * qtdemux, GstByteReader * data,
-    int depth);
 gboolean qtdemux_dump_stsc (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
 gboolean qtdemux_dump_stsz (GstQTDemux * qtdemux, GstByteReader * data,
@@ -55,10 +53,6 @@ gboolean qtdemux_dump_stco (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
 gboolean qtdemux_dump_co64 (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
-gboolean qtdemux_dump_dcom (GstQTDemux * qtdemux, GstByteReader * data,
-    int depth);
-gboolean qtdemux_dump_cmvd (GstQTDemux * qtdemux, GstByteReader * data,
-    int depth);
 gboolean qtdemux_dump_ctts (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
 gboolean qtdemux_dump_mfro (GstQTDemux * qtdemux, GstByteReader * data,
@@ -75,6 +69,8 @@ gboolean qtdemux_dump_mehd (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
 gboolean qtdemux_dump_sdtp (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
+gboolean qtdemux_dump_tfdt (GstQTDemux * qtdemux, GstByteReader * data,
+    int depth);
 gboolean qtdemux_dump_unknown (GstQTDemux * qtdemux, GstByteReader * data,
     int depth);
 
old mode 100644 (file)
new mode 100755 (executable)
index 6666a94..bc65dbc
@@ -31,14 +31,10 @@ G_BEGIN_DECLS
 #define FOURCC_clip     GST_MAKE_FOURCC('c','l','i','p')
 #define FOURCC_trak     GST_MAKE_FOURCC('t','r','a','k')
 #define FOURCC_udta     GST_MAKE_FOURCC('u','d','t','a')
-#define FOURCC_ctab     GST_MAKE_FOURCC('c','t','a','b')
 #define FOURCC_tkhd     GST_MAKE_FOURCC('t','k','h','d')
 #define FOURCC_crgn     GST_MAKE_FOURCC('c','r','g','n')
-#define FOURCC_matt     GST_MAKE_FOURCC('m','a','t','t')
-#define FOURCC_kmat     GST_MAKE_FOURCC('k','m','a','t')
 #define FOURCC_edts     GST_MAKE_FOURCC('e','d','t','s')
 #define FOURCC_elst     GST_MAKE_FOURCC('e','l','s','t')
-#define FOURCC_load     GST_MAKE_FOURCC('l','o','a','d')
 #define FOURCC_tref     GST_MAKE_FOURCC('t','r','e','f')
 #define FOURCC_imap     GST_MAKE_FOURCC('i','m','a','p')
 #define FOURCC___in     GST_MAKE_FOURCC(' ',' ','i','n')
@@ -50,15 +46,12 @@ G_BEGIN_DECLS
 #define FOURCC_minf     GST_MAKE_FOURCC('m','i','n','f')
 #define FOURCC_vmhd     GST_MAKE_FOURCC('v','m','h','d')
 #define FOURCC_smhd     GST_MAKE_FOURCC('s','m','h','d')
-#define FOURCC_gmhd     GST_MAKE_FOURCC('g','m','h','d')
-#define FOURCC_gmin     GST_MAKE_FOURCC('g','m','i','n')
 #define FOURCC_dinf     GST_MAKE_FOURCC('d','i','n','f')
 #define FOURCC_dref     GST_MAKE_FOURCC('d','r','e','f')
 #define FOURCC_stbl     GST_MAKE_FOURCC('s','t','b','l')
 #define FOURCC_stsd     GST_MAKE_FOURCC('s','t','s','d')
 #define FOURCC_stts     GST_MAKE_FOURCC('s','t','t','s')
 #define FOURCC_stss     GST_MAKE_FOURCC('s','t','s','s')
-#define FOURCC_stps     GST_MAKE_FOURCC('s','t','p','s')
 #define FOURCC_stsc     GST_MAKE_FOURCC('s','t','s','c')
 #define FOURCC_stsz     GST_MAKE_FOURCC('s','t','s','z')
 #define FOURCC_stco     GST_MAKE_FOURCC('s','t','c','o')
@@ -68,9 +61,6 @@ G_BEGIN_DECLS
 #define FOURCC_strm     GST_MAKE_FOURCC('s','t','r','m')
 #define FOURCC_rtsp     GST_MAKE_FOURCC('r','t','s','p')
 #define FOURCC_co64     GST_MAKE_FOURCC('c','o','6','4')
-#define FOURCC_cmov     GST_MAKE_FOURCC('c','m','o','v')
-#define FOURCC_dcom     GST_MAKE_FOURCC('d','c','o','m')
-#define FOURCC_cmvd     GST_MAKE_FOURCC('c','m','v','d')
 #define FOURCC_hint     GST_MAKE_FOURCC('h','i','n','t')
 #define FOURCC_mp4a     GST_MAKE_FOURCC('m','p','4','a')
 #define FOURCC_mp4v     GST_MAKE_FOURCC('m','p','4','v')
@@ -129,13 +119,7 @@ G_BEGIN_DECLS
 #define FOURCC_free     GST_MAKE_FOURCC('f','r','e','e')
 #define FOURCC_data     GST_MAKE_FOURCC('d','a','t','a')
 #define FOURCC_SVQ3     GST_MAKE_FOURCC('S','V','Q','3')
-#define FOURCC_rmra     GST_MAKE_FOURCC('r','m','r','a')
-#define FOURCC_rmda     GST_MAKE_FOURCC('r','m','d','a')
-#define FOURCC_rdrf     GST_MAKE_FOURCC('r','d','r','f')
 #define FOURCC__gen     GST_MAKE_FOURCC(0xa9, 'g', 'e', 'n')
-#define FOURCC_rmdr     GST_MAKE_FOURCC('r','m','d','r')
-#define FOURCC_rmvc     GST_MAKE_FOURCC('r','m','v','c')
-#define FOURCC_qtim     GST_MAKE_FOURCC('q','t','i','m')
 #define FOURCC_drms     GST_MAKE_FOURCC('d','r','m','s')
 #define FOURCC_drmi     GST_MAKE_FOURCC('d','r','m','i')
 #define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
@@ -213,7 +197,13 @@ G_BEGIN_DECLS
 
 #define FOURCC_XMP_     GST_MAKE_FOURCC('X','M','P','_')
 #define FOURCC_uuid     GST_MAKE_FOURCC('u','u','i','d')
-
+#define FOURCC_encv     GST_MAKE_FOURCC('e','n','c','v')
+#define FOURCC_enca     GST_MAKE_FOURCC('e','n','c','a')
+#define FOURCC_pssh     GST_MAKE_FOURCC('p','s','s','h')
+#define FOURCC_saiz     GST_MAKE_FOURCC('s','a','i','z')
+#define FOURCC_saio     GST_MAKE_FOURCC('s','a','i','o')
+#define FOURCC_senc     GST_MAKE_FOURCC('s','e','n','c')
+#define FOURCC_mfhd     GST_MAKE_FOURCC('m','f','h','d')
 /* Fragmented MP4 */
 #define FOURCC_mehd     GST_MAKE_FOURCC('m','e','h','d')
 #define FOURCC_mfhd     GST_MAKE_FOURCC('m','f','h','d')
@@ -229,7 +219,12 @@ G_BEGIN_DECLS
 #define FOURCC_trun     GST_MAKE_FOURCC('t','r','u','n')
 #define FOURCC_ovc1     GST_MAKE_FOURCC('o','v','c','1')
 #define FOURCC_owma     GST_MAKE_FOURCC('o','w','m','a')
+#ifdef QTDEMUX_MODIFICATION
+#define FOURCC_sbtl            GST_MAKE_FOURCC('s','b','t','l')
+#endif
 
+/* MPEG DASH */
+#define FOURCC_tfdt     GST_MAKE_FOURCC('t','f','d','t')
 G_END_DECLS
 
 #endif /* __GST_QTDEMUX_FOURCC_H__ */
old mode 100644 (file)
new mode 100755 (executable)
index 38da35b..3f0a574
@@ -28,16 +28,12 @@ static const QtNodeType qt_node_types[] = {
   {FOURCC_clip, "clipping", QT_FLAG_CONTAINER,},
   {FOURCC_trak, "track", QT_FLAG_CONTAINER,},
   {FOURCC_udta, "user data", QT_FLAG_CONTAINER,},       /* special container */
-  {FOURCC_ctab, "color table", 0,},
   {FOURCC_tkhd, "track header", 0,
       qtdemux_dump_tkhd},
   {FOURCC_crgn, "clipping region", 0,},
-  {FOURCC_matt, "track matte", QT_FLAG_CONTAINER,},
-  {FOURCC_kmat, "compressed matte", 0,},
   {FOURCC_edts, "edit", QT_FLAG_CONTAINER,},
   {FOURCC_elst, "edit list", 0,
       qtdemux_dump_elst},
-  {FOURCC_load, "track load settings", 0,},
   {FOURCC_tref, "track reference", QT_FLAG_CONTAINER,},
   {FOURCC_imap, "track input map", QT_FLAG_CONTAINER,},
   {FOURCC___in, "track input", 0,},     /* special container */
@@ -51,8 +47,6 @@ static const QtNodeType qt_node_types[] = {
   {FOURCC_vmhd, "video media information", 0,
       qtdemux_dump_vmhd},
   {FOURCC_smhd, "sound media information", 0},
-  {FOURCC_gmhd, "base media information header", 0},
-  {FOURCC_gmin, "base media info", 0},
   {FOURCC_dinf, "data information", QT_FLAG_CONTAINER},
   {FOURCC_dref, "data reference", 0,
       qtdemux_dump_dref},
@@ -61,8 +55,6 @@ static const QtNodeType qt_node_types[] = {
       qtdemux_dump_stsd},
   {FOURCC_stts, "time-to-sample", 0,
       qtdemux_dump_stts},
-  {FOURCC_stps, "partial sync sample", 0,
-      qtdemux_dump_stps},
   {FOURCC_stss, "sync sample", 0,
       qtdemux_dump_stss},
   {FOURCC_stsc, "sample-to-chunk", 0,
@@ -74,9 +66,6 @@ static const QtNodeType qt_node_types[] = {
   {FOURCC_co64, "64-bit chunk offset", 0,
       qtdemux_dump_co64},
   {FOURCC_vide, "video media", 0},
-  {FOURCC_cmov, "compressed movie", QT_FLAG_CONTAINER},
-  {FOURCC_dcom, "compressed data", 0, qtdemux_dump_dcom},
-  {FOURCC_cmvd, "compressed movie data", 0, qtdemux_dump_cmvd},
   {FOURCC_hint, "hint", 0,},
   {FOURCC_mp4a, "mp4a", 0,},
   {FOURCC_mp4v, "mp4v", 0,},
@@ -141,9 +130,6 @@ static const QtNodeType qt_node_types[] = {
   {FOURCC_data, "data", 0, qtdemux_dump_unknown},
   {FOURCC_free, "free", 0,},
   {FOURCC_SVQ3, "SVQ3", 0,},
-  {FOURCC_rmra, "rmra", QT_FLAG_CONTAINER,},
-  {FOURCC_rmda, "rmda", QT_FLAG_CONTAINER,},
-  {FOURCC_rdrf, "rdrf", 0,},
   {FOURCC__gen, "Custom Genre", QT_FLAG_CONTAINER,},
   {FOURCC_ctts, "Composition time to sample", 0, qtdemux_dump_ctts},
   {FOURCC_XiTh, "XiTh", 0},
@@ -171,6 +157,8 @@ static const QtNodeType qt_node_types[] = {
       qtdemux_dump_mehd},
   {FOURCC_ovc1, "ovc1", 0},
   {FOURCC_owma, "owma", 0},
+  {FOURCC_senc, "senc", 0},
+  {FOURCC_tfdt, "Track fragment decode time", 0, qtdemux_dump_tfdt},
   {0, "unknown", 0,},
 };
 
old mode 100644 (file)
new mode 100755 (executable)
index 337640f..a81ad3c
@@ -189,6 +189,7 @@ static GstFlowReturn gst_matroska_demux_trickplay_parse_blockgroup_or_simplebloc
 static gint32 gst_matroska_demux_trickplay_nframes2show_bw_keyframes (GstMatroskaDemux* demux, GstMatroskaTrackContext * stream);
 static GstFlowReturn gst_matroska_demux_backward_trickplay (GstMatroskaDemux* demux, GstMatroskaTrackContext * stream, GstBuffer* sub);
 static GstFlowReturn gst_matroska_demux_forward_trickplay (GstMatroskaDemux* demux, GstMatroskaTrackContext * stream, GstBuffer *buffer, gboolean *skip);
+static gboolean gst_matroska_demux_create_index_table(GstMatroskaDemux* demux);
 #endif
 
 GType gst_matroska_demux_get_type (void);
@@ -297,6 +298,12 @@ gst_matroska_demux_init (GstMatroskaDemux * demux,
   demux->is_eos_blockgroup = FALSE;
   demux->is_eos_simpleblock = FALSE;
   demux->video_keyframe_pushed = FALSE;
+  demux->seek_head_cluster_info_absent = FALSE;
+  demux->seek_head_cue_info_absent = FALSE;
+  demux->index_table_created = TRUE;
+  demux->index_table_array_creation = FALSE;
+  demux->first_index_table_creation = TRUE;
+  demux->Subtitle_language_list = NULL;
 #endif
 
   /* property defaults */
@@ -508,6 +515,12 @@ gst_matroska_demux_reset (GstElement * element)
   }
 
   demux->invalid_duration = FALSE;
+#ifdef MKV_DEMUX_MODIFICATION
+  if (demux->Subtitle_language_list) {
+    g_list_free (demux->Subtitle_language_list);
+    demux->Subtitle_language_list = NULL;
+  }
+#endif
 }
 
 static GstBuffer *
@@ -1318,6 +1331,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml)
     lang = gst_tag_get_language_code (context->language);
     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
         GST_TAG_LANGUAGE_CODE, (lang) ? lang : context->language, NULL);
+
+#ifdef MKV_DEMUX_MODIFICATION
+    if (context->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE) {
+      GstMatroskaLanguageStruct* new = NULL;
+      new = g_new0 (GstMatroskaLanguageStruct, 1);
+      new->language_code = (lang ? lang : context->language);
+      new->language_key = (lang ? lang : context->language);
+      new->active = FALSE;
+      demux->Subtitle_language_list = g_list_append (demux->Subtitle_language_list, new);
+    }
+#endif
   }
 
   if (caps == NULL) {
@@ -2044,17 +2068,28 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
       GST_OBJECT_UNLOCK (demux);
       return FALSE;
     }
+#ifdef MKV_DEMUX_MODIFICATION
+  } else {
+    GST_INFO_OBJECT (demux, "Entry Details are");
+    GST_INFO_OBJECT (demux, "entry->block %u", (guint)entry->block);
+    GST_INFO_OBJECT (demux, "entry->pos %"G_GUINT64_FORMAT, entry->pos);
+    GST_INFO_OBJECT (demux, "entry->time %"GST_TIME_FORMAT, GST_TIME_ARGS(entry->time));
+    GST_INFO_OBJECT (demux, "entry->track %u", (guint)entry->track);
+#endif
   }
 
 #ifdef MKV_DEMUX_MODIFICATION
-  if (entry == NULL)
+  if (entry == NULL) {
+    GST_OBJECT_UNLOCK (demux);
     return FALSE;
+  }
 
   if (seeksegment.rate < 0.0) {
     GST_INFO("Current Index is %"GST_TIME_FORMAT, GST_TIME_ARGS(entry->time));
     next_entry = gst_matroska_demux_get_next_index (demux, track, entry);
     if (next_entry == NULL) {
       GST_ERROR ("Entry Not found....");
+      GST_OBJECT_UNLOCK (demux);
       return FALSE;
     }
     GST_INFO("Next Index is %"GST_TIME_FORMAT, GST_TIME_ARGS(next_entry->time));
@@ -2128,7 +2163,8 @@ next:
       seeksegment.start = cur;
       seeksegment.time = cur;
       seeksegment.last_stop = cur;
-      seeksegment.stop = seeksegment.duration;
+      //seeksegment.stop = seeksegment.duration;
+      GST_DEBUG_OBJECT (demux, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
     } else if (seeksegment.rate < 0.0) {/* Reverse trick play */
       seeksegment.start = 0.0;
       seeksegment.stop = next_entry->time;
@@ -3510,6 +3546,15 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
       goto done;
     }
 
+    if(demux->first_index_table_creation == FALSE &&
+              demux->index_table_created == FALSE &&
+              !(flags == 0x80 || (!delta_unit && stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)))
+    {
+      GST_INFO("Returning without doing nothing");
+      if (buf)
+        gst_buffer_unref (buf);
+      return GST_FLOW_OK;
+    }
     for (n = 0; n < laces; n++) {
       GstBuffer *sub;
 #ifdef MKV_DEMUX_MODIFICATION
@@ -3563,6 +3608,11 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
       sub = gst_buffer_create_sub (buf,
           GST_BUFFER_SIZE (buf) - size, lace_size[n]);
       GST_DEBUG_OBJECT (demux, "created subbuffer %p", sub);
+#ifdef MKV_DEMUX_MODIFICATION
+      if(demux->index_table_created == FALSE) {
+        demux->common.segment.duration = 0;
+      }
+#endif
 
       if (delta_unit)
         GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
@@ -3626,7 +3676,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
           if (diff > 0 && diff > demux->max_gap_time
               && lace_time > demux->common.segment.start
               && (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)
-                  || lace_time < demux->common.segment.stop)) {
+                  || lace_time < demux->common.segment.stop) && demux->index_table_created == TRUE) {
             GST_DEBUG_OBJECT (demux,
                 "Gap of %" G_GINT64_FORMAT " ns detected in"
                 "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
@@ -3675,9 +3725,15 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
           demux->last_stop_end = last_stop_end;
 
         GST_OBJECT_LOCK (demux);
+#ifdef MKV_DEMUX_MODIFICATION
+        if ((demux->common.segment.duration == -1 ||
+            demux->stream_start_time + demux->common.segment.duration <
+            last_stop_end) && demux->index_table_created == TRUE) {
+#else
         if (demux->common.segment.duration == -1 ||
             demux->stream_start_time + demux->common.segment.duration <
             last_stop_end) {
+#endif
           gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME,
               last_stop_end - demux->stream_start_time);
           GST_OBJECT_UNLOCK (demux);
@@ -3771,7 +3827,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         }
       } else if (demux->common.segment.rate < 0.0) {
         ret = gst_matroska_demux_backward_trickplay (demux, stream, sub);
-      } else 
+      } else
 #endif
     {
       /* At this point, we have a sub-buffer pointing at data within a larger
@@ -3791,8 +3847,58 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         gst_buffer_unref (sub);
         sub = buffer;
       }
-
+#ifdef MKV_DEMUX_MODIFICATION
+      if(demux->index_table_created == FALSE) {
+        // flag checking sufficient for simple block and delta unit for Block group
+        if(flags == 128 || (!delta_unit && stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)) {
+          GST_INFO("Keyframe Found");
+
+          //Information required for index table creation
+          GstMatroskaIndex *idx = NULL;
+          idx = (GstMatroskaIndex*)malloc(sizeof(GstMatroskaIndex));
+          if(idx == NULL) {
+            GST_INFO("Unable to create memory");
+            ret = GST_FLOW_UNEXPECTED;
+            goto done;
+          }
+          idx->pos = (cluster_offset - demux->initial_offset);
+          idx->track = 1;
+          idx->time = GST_BUFFER_TIMESTAMP(sub);
+          idx->block = 1;
+
+          // Creating new/Over-Writing index table
+          if(!demux->index_table_array_creation) {
+            GST_INFO("Keyframe time stamp is %"GST_TIME_FORMAT"pos %"G_GUINT64_FORMAT, GST_TIME_ARGS(idx->time), idx->pos);
+            GST_INFO("Index table creation first time");
+            g_array_unref(demux->common.index);
+            demux->common.index = NULL;//g_array_unref(demux->common.index);
+            demux->common.index = g_array_new(FALSE, FALSE, sizeof(GstMatroskaIndex));
+            g_array_append_val(demux->common.index, *idx);
+            GST_INFO("size of the index is %d",demux->common.index->len);
+            demux->index_table_array_creation = TRUE;
+            demux->duration = GST_BUFFER_TIMESTAMP(sub) + GST_BUFFER_DURATION (sub);
+          } else {
+            GST_INFO("Adding Keyframe info to index table");
+            GST_INFO("Keyframe time stamp is %"GST_TIME_FORMAT"pos %"G_GUINT64_FORMAT, GST_TIME_ARGS(idx->time), idx->pos);
+            g_array_append_val(demux->common.index, *idx);
+            GST_INFO("size of the index is %d",demux->common.index->len);
+            demux->duration = GST_BUFFER_TIMESTAMP(sub) + GST_BUFFER_DURATION (sub);
+            GST_INFO("The duration of the video is %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->duration));
+          }
+          free(idx);
+          idx = NULL;
+        } else {
+          //demux->common.segment.duration = (GST_BUFFER_TIMESTAMP(sub) + GST_BUFFER_DURATION (sub));
+          demux->duration = GST_BUFFER_TIMESTAMP(sub) + GST_BUFFER_DURATION (sub);
+          GST_INFO("duration is in capturing not setting%"GST_TIME_FORMAT, GST_TIME_ARGS(demux->duration));
+          GST_INFO("duration in segment duration still not set%"GST_TIME_FORMAT, GST_TIME_ARGS(demux->common.segment.duration));
+        }
+      } else {
+        ret = gst_pad_push (stream->pad, sub);
+      }
+#else
       ret = gst_pad_push (stream->pad, sub);
+#endif
     }
 
       if (demux->common.segment.rate < 0) {
@@ -3824,6 +3930,7 @@ done:
 
   return ret;
 
+#ifndef MKV_DEMUX_MODIFICATION
   /* EXITS */
 eos:
   {
@@ -3833,6 +3940,8 @@ eos:
     ret = gst_matroska_demux_combine_flows (demux, stream, ret);
     goto done;
   }
+#endif
+
 invalid_lacing:
   {
     GST_ELEMENT_WARNING (demux, STREAM, DEMUX, (NULL), ("Invalid lacing size"));
@@ -3962,6 +4071,12 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
             G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %"
             G_GUINT64_FORMAT ")", seek_pos, demux->common.ebml_segment_start,
             length);
+#ifdef MKV_DEMUX_MODIFICATION
+        demux->seek_head_cluster_info_absent = TRUE;
+        demux->seek_head_cue_info_absent = TRUE;
+        demux->index_table_created = FALSE;
+        GST_INFO("Need to create index table this might take time");
+#endif
         break;
       }
 
@@ -4318,6 +4433,10 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
           GST_DEBUG_OBJECT (demux,
               "Found Segment start at offset %" G_GUINT64_FORMAT,
               demux->common.offset);
+#ifdef MKV_DEMUX_MODIFICATION
+          demux->initial_offset = demux->common.offset;
+          GST_INFO("Initial offset storing is %u", demux->initial_offset);
+#endif
           /* seeks are from the beginning of the segment,
            * after the segment ID/length */
           demux->common.ebml_segment_start = demux->common.offset;
@@ -4356,6 +4475,17 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
           if (!demux->tracks_parsed) {
             GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml));
             ret = gst_matroska_demux_parse_tracks (demux, &ebml);
+#ifdef MKV_DEMUX_MODIFICATION
+            if (demux->Subtitle_language_list != NULL) {
+              GstMatroskaLanguageStruct* First_Language = g_list_nth_data (demux->Subtitle_language_list, 0);
+              First_Language->active = TRUE;
+              GstMessage *m;
+              m = gst_message_new_element (GST_OBJECT_CAST (demux),
+                                           gst_structure_new ("Int_Sub_Language_List", "lang_list",
+                                           G_TYPE_POINTER, demux->Subtitle_language_list, NULL));
+              gst_element_post_message (GST_ELEMENT_CAST (demux), m);
+            }
+#endif
           } else {
             GST_READ_CHECK (gst_matroska_demux_flush (demux, read));
           }
@@ -4440,8 +4570,9 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
         int i =0;
         int minusone = -1;
         guint64 duration = 0;
-        GstClockTime time_position;
+        GstClockTime time_position = 0;
         GstMatroskaIndex *entry = NULL;
+        guint64 time=0;
 
         demux->next_keyframe_ts = demux->prev_keyframe_ts;
         GST_INFO("next_keyframe_ts is %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->next_keyframe_ts));
@@ -4471,10 +4602,9 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
             if ((entry = gst_matroska_read_common_do_index_seek (&demux->common, stream, time_position, NULL, NULL)) == NULL) {
               GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
             }
-
             GST_DEBUG_OBJECT (demux, "pos = %"G_GUINT64_FORMAT", track = %d, block = %d, time = %"GST_TIME_FORMAT"\n",
                 entry->pos, entry->track, entry->block, GST_TIME_ARGS(entry->time));
-
+            time = entry->time;
             offset =  entry->pos + demux->common.ebml_segment_start;
             if (offset >= gst_matroska_read_common_get_length(&demux->common)) {
               GST_INFO_OBJECT (demux, " Seek failed");
@@ -4482,7 +4612,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
             }
             demux->common.offset = offset;
           }
-          stream->pos = entry->time;
+          stream->pos = time;
           stream->set_discont = TRUE;
           stream->last_flow = GST_FLOW_OK;
           if (stream->pos > 0.0) {
@@ -4495,12 +4625,12 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
               GST_INFO_OBJECT (demux, "Reached EOS.....");
             }
           }
-          demux->common.segment.last_stop = entry->time;
+          demux->common.segment.last_stop = time;
 
           GST_OBJECT_UNLOCK (demux);
         }
 
-        if (entry->time == 0.0 && demux->is_eos_blockgroup == TRUE && demux->is_eos_simpleblock == TRUE) {
+        if (time == 0.0 && demux->is_eos_blockgroup == TRUE && demux->is_eos_simpleblock == TRUE) {
           gst_segment_init (&demux->common.segment, GST_FORMAT_TIME);
           gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME, demux->duration);
 
@@ -4512,7 +4642,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
 
         demux->found_videokeyframe = FALSE;
         demux->found_audioframe = FALSE;
-        demux->prev_keyframe_ts = entry->time;
+        demux->prev_keyframe_ts = time;
         GST_INFO("prev_keyframe in blockgroup is %"GST_TIME_FORMAT,GST_TIME_ARGS(demux->prev_keyframe_ts));
         return ret;
       }
@@ -4536,7 +4666,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
             int i =0;
             int minusone = -1;
             guint64 duration = 0;
-            GstClockTime time_position;
+            GstClockTime time_position = 0;
             GstMatroskaIndex *entry = NULL;
 
             demux->next_keyframe_ts = demux->prev_keyframe_ts;
@@ -4576,6 +4706,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
               offset =  entry->pos + demux->common.ebml_segment_start;
               if (offset >= gst_matroska_read_common_get_length(&demux->common)) {
                 GST_INFO_OBJECT (demux, " Seek failed");
+                GST_OBJECT_UNLOCK (demux);
                 goto seek_failed;
               }
               demux->common.offset = offset;
@@ -4781,16 +4912,52 @@ gst_matroska_demux_loop (GstPad * pad)
 
     g_assert (demux->common.num_streams == demux->common.src->len);
     for (i = 0; i < demux->common.src->len; i++) {
-      GstMatroskaTrackContext *context = g_ptr_array_index (demux->common.src,
-          i);
+
+#ifdef MKV_DEMUX_MODIFICATION
+//Index table Creation Logic
+      if((demux->seek_head_cluster_info_absent || demux->seek_head_cue_info_absent) && !demux->index_table_created) {
+        GST_INFO("Index table needs to be created");
+
+        guint64 index_offset = demux->common.offset;
+
+        GST_INFO("offset index is %"G_GUINT64_FORMAT, demux->common.offset);
+        demux->common.segment.duration = -1;
+        gint64 start = g_get_monotonic_time ();
+        gint64 end = 0;
+        demux->first_index_table_creation = FALSE;
+        gst_matroska_demux_create_index_table(demux);
+        demux->first_index_table_creation = TRUE;
+        end = g_get_monotonic_time ();
+        GST_INFO("the duration of the clip is %"GST_TIME_FORMAT, GST_TIME_ARGS(demux->duration));
+        GST_INFO("Index table build time is time: %llu\n",(end-start));
+        GST_INFO("size of the index is %d",demux->common.index->len);
+        //gst_matroska_demux_sync_streams (demux);
+
+        demux->common.offset = index_offset;
+        demux->index_table_created = TRUE;
+        demux->common.segment.last_stop = 0;
+        demux->common.segment.duration = demux->duration;
+        GST_INFO("index table creation completed");
+      }
+#endif
+      GstMatroskaTrackContext *context = g_ptr_array_index (demux->common.src, i);
       GST_DEBUG_OBJECT (context->pad, "pos %" GST_TIME_FORMAT,
           GST_TIME_ARGS (context->pos));
+      if(context->pos > demux->common.segment.stop) {
+        GST_DEBUG("Going to EOS since we reached the Stop position");
+        context->eos = TRUE;
+      }
       if (context->eos == FALSE)
         goto next;
     }
 
     GST_INFO_OBJECT (demux, "All streams are EOS");
     ret = GST_FLOW_UNEXPECTED;
+#ifdef MKV_DEMUX_MODIFICATION
+    if(demux->is_eos_blockgroup || demux->is_eos_simpleblock) {
+      demux->seek_entry = 0;
+    }
+#endif
     goto eos;
   }
 
@@ -5252,9 +5419,41 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
       GstBuffer *priv = gst_buffer_new_and_alloc (size);
 
       memcpy (GST_BUFFER_DATA (priv), data, size);
+#ifdef MKV_DEMUX_MODIFICATION
+      gsize size_codec = 0;
+      gint idx = 0;
+      guint8 *vol1 = NULL;
+      guint8 *vol_start = NULL;
+      guint8 *vo_start = NULL;
+
+      vol1 = GST_BUFFER_DATA (priv);
+      size_codec = size;
+      while (idx < size_codec) {
+        if (vol1[idx] == 0x00 && vol1[idx+1] == 0x00 && vol1[idx+2] == 0x01 && (vol1[idx+3] >= 0x20 && vol1[idx+3] <= 0x2f)) {
+          vol_start = vol1+idx+3;
+          GST_DEBUG("found the vol start  byte");
+          break;
+        }
+        if (vol1[idx] == 0x00 && vol1[idx+1] == 0x00 && vol1[idx+2] == 0x01 && vol1[idx+3]==0xb5) {
+          vo_start = vol1+idx+3;
+          GST_DEBUG("found the vo start  byte");
+        }
+        idx++;
+      }
+      if (vo_start == NULL || vol_start == NULL) {
+        GST_ERROR ("could not find vo & vol start codes");
+        return NULL;
+      }
+#endif
       gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
       gst_buffer_unref (priv);
     }
+#ifdef MKV_DEMUX_MODIFICATION
+    else {
+      GST_ERROR("codec data is not present");
+      return NULL;
+    }
+#endif
     if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP))
       *codec_name = g_strdup ("MPEG-4 advanced simple profile");
     else
@@ -6319,7 +6518,7 @@ gst_matroska_demux_trickplay_parse_blockgroup_or_simpleblock (GstMatroskaDemux *
     gboolean delta_unit;
 
     stream = g_ptr_array_index (demux->common.src, stream_num);
-       
+
     if (cluster_time != GST_CLOCK_TIME_NONE) {
       /* FIXME: What to do with negative timestamps? Give timestamp 0 or -1?
        * Drop unless the lace contains timestamp 0? */
@@ -6402,7 +6601,7 @@ gst_matroska_demux_trickplay_nframes2show_bw_keyframes (GstMatroskaDemux* demux,
   guint64 prev_cluster_time = demux->cluster_time;
   guint64 prev_cluster_offset = demux->cluster_offset;
   int i = 0;
-  
+
   while (stream->found_next_kframe == FALSE) {
     next_keyframe_offset = demux->common.offset;
 
@@ -6415,7 +6614,7 @@ gst_matroska_demux_trickplay_nframes2show_bw_keyframes (GstMatroskaDemux* demux,
     }
     GST_LOG_OBJECT (demux, "trickplay : Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
       "size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id,
-      length, needed); 
+      length, needed);
 
     if (ret != GST_FLOW_OK) {
       GST_WARNING_OBJECT (demux, "Error in id_length_pull flow ret...reason : %s\n", gst_flow_get_name (ret));
@@ -6445,12 +6644,12 @@ gst_matroska_demux_trickplay_nframes2show_bw_keyframes (GstMatroskaDemux* demux,
       context->frames_to_show_bw_keyframes = context->num_frames_bw_keyframes / demux->common.segment.rate;
     }
   }
-  
+
   /* keeping previous offset values for normal operation */
   demux->common.offset = prev_offset;
   demux->cluster_offset = prev_cluster_offset;
   demux->cluster_time = prev_cluster_time;
-  
+
   return stream->num_frames_bw_keyframes;
 }
 
@@ -6462,19 +6661,19 @@ gst_matroska_demux_backward_trickplay (GstMatroskaDemux* demux, GstMatroskaTrack
   if (((stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO) || (!GST_BUFFER_FLAG_IS_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT)))
               && (demux->prev_keyframe_ts <= (GST_BUFFER_TIMESTAMP (sub)) <= demux->next_keyframe_ts)) {
 
-       if(stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && !demux->video_keyframe_pushed) {
+    if(stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && !demux->video_keyframe_pushed) {
       demux->video_keyframe_pushed = TRUE;
-       } else if(stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && demux->video_keyframe_pushed){
-         GST_INFO("unreffing the video frame (already sent one keyframe)");
-         gst_buffer_unref (sub);
-         return ret;
-       }
-
-       if(demux->prev_keyframe_ts == demux->next_keyframe_ts || demux->prev_keyframe_ts > demux->next_keyframe_ts) {
-         GST_INFO("Unreffing the already pushed buffer");
+    } else if(stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && demux->video_keyframe_pushed){
+      GST_INFO("unreffing the video frame (already sent one keyframe)");
+      gst_buffer_unref (sub);
+      return ret;
+    }
+
+    if(demux->prev_keyframe_ts == demux->next_keyframe_ts || demux->prev_keyframe_ts > demux->next_keyframe_ts) {
+      GST_INFO("Unreffing the already pushed buffer");
       gst_buffer_unref (sub);
-         return ret;
-       }
+      return ret;
+    }
 
     GST_DEBUG_OBJECT (demux, "Pushing data of size %d for stream %d, time=%"GST_TIME_FORMAT
             " and duration=%" GST_TIME_FORMAT,
@@ -6543,9 +6742,9 @@ gst_matroska_demux_forward_trickplay (GstMatroskaDemux* demux, GstMatroskaTrackC
         *skip = TRUE;
 
       if(stream->frames_to_show_bw_keyframes > 0) {
-       GST_INFO("Time stamp modification %"GST_TIME_FORMAT,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+        GST_INFO("Time stamp modification %"GST_TIME_FORMAT,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
 
-       time_escalation = ((stream->num_frames_bw_keyframes/demux->common.segment.rate) - stream->frames_to_show_bw_keyframes) * stream->avg_duration_bw_keyframes * demux->common.segment.rate;
+        time_escalation = ((stream->num_frames_bw_keyframes/demux->common.segment.rate) - stream->frames_to_show_bw_keyframes) * stream->avg_duration_bw_keyframes * demux->common.segment.rate;
 
         GST_BUFFER_TIMESTAMP(buffer) = stream->prev_kframe_timestamp + time_escalation;
         GST_INFO("Time stamp modified %"GST_TIME_FORMAT,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
@@ -6636,6 +6835,41 @@ gst_matroska_demux_get_property (GObject * object,
   }
 }
 
+#ifdef MKV_DEMUX_MODIFICATION
+static gboolean gst_matroska_demux_create_index_table(GstMatroskaDemux* demux)
+{
+  GstFlowReturn ret;
+  guint32 id_index;
+  guint64 length_index;
+  guint needed_index;
+
+  while(TRUE) {
+    ret = gst_matroska_read_common_peek_id_length_pull (&demux->common,
+          GST_ELEMENT_CAST (demux), &id_index, &length_index, &needed_index);
+
+    if (ret == GST_FLOW_UNEXPECTED || ret != GST_FLOW_OK) {
+      GST_INFO("problem in pulling data or eos reached");
+      demux->index_table_created = TRUE;
+      break;
+    }
+
+    GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
+        "size %" G_GUINT64_FORMAT ", needed %d", demux->common.offset, id_index,
+        length_index, needed_index);
+
+    ret = gst_matroska_demux_parse_id (demux, id_index, length_index, needed_index);
+
+    if(ret == GST_FLOW_UNEXPECTED || ret != GST_FLOW_OK) {
+      GST_INFO("problem in pulling data or eos reached");
+      demux->index_table_created = TRUE;
+      break;
+    }
+  }
+
+  return TRUE;
+}
+#endif
+
 gboolean
 gst_matroska_demux_plugin_init (GstPlugin * plugin)
 {
old mode 100644 (file)
new mode 100755 (executable)
index c59bc90..98e8cf6
@@ -89,6 +89,12 @@ typedef struct _GstMatroskaDemux {
   gboolean video;
   gboolean found_videokeyframe;
   gboolean found_audioframe;
+  gboolean seek_head_cluster_info_absent;
+  gboolean seek_head_cue_info_absent;
+  gboolean index_table_created;
+  gboolean index_table_array_creation;
+  gboolean first_index_table_creation;
+  guint32  initial_offset;
 #endif
 
   /* index stuff */
@@ -113,6 +119,7 @@ typedef struct _GstMatroskaDemux {
   gboolean              is_eos_simpleblock;
   gint                  no_video_frame;
   gboolean              video_keyframe_pushed;
+  GList*                Subtitle_language_list;
 #endif
 
   /* gap handling */
index c88555c..e0ffddf 100644 (file)
@@ -630,6 +630,12 @@ typedef struct _GstMatroskaTrackEncoding {
   guint   comp_settings_length;
 } GstMatroskaTrackEncoding;
 
+typedef struct _GstMatroskaLanguageStruct {
+  gchar* language_code;
+  gchar* language_key;
+  gboolean active;
+} GstMatroskaLanguageStruct;
+
 gboolean gst_matroska_track_init_video_context    (GstMatroskaTrackContext ** p_context);
 gboolean gst_matroska_track_init_audio_context    (GstMatroskaTrackContext ** p_context);
 gboolean gst_matroska_track_init_subtitle_context (GstMatroskaTrackContext ** p_context);
index 1104acc..1baa4d7 100644 (file)
@@ -1117,8 +1117,9 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
   GstFlowReturn ret = GST_FLOW_OK;
   guint i;
 
-  if (common->index)
-    g_array_free (common->index, TRUE);
+  if (common->index){
+    return ret;
+  }
   common->index =
       g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
 
index 9d3e56a..ab02659 100644 (file)
@@ -486,6 +486,12 @@ gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
   header = g_strdup_printf ("--%s\r\nContent-Type: %s\r\n"
       "Content-Length: %u\r\n\r\n",
       mux->boundary, mime, GST_BUFFER_SIZE (best->buffer));
+#ifdef GST_EXT_ENHANCEMENT
+  if (header == NULL) {
+    GST_ERROR_OBJECT(mux, "failed to alloc header");
+    goto alloc_failed;
+  }
+#endif /* GST_EXT_ENHANCEMENT */
   headerlen = strlen (header);
 
   ret = gst_pad_alloc_buffer_and_set_caps (mux->srcpad, GST_BUFFER_OFFSET_NONE,
@@ -495,6 +501,9 @@ gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
 
   memcpy (GST_BUFFER_DATA (headerbuf), header, headerlen);
   g_free (header);
+#ifdef GST_EXT_ENHANCEMENT
+  header = NULL;
+#endif /* GST_EXT_ENHANCEMENT */
 
   /* the header has the same timestamp as the data buffer (which we will push
    * below) and has a duration of 0 */
@@ -592,7 +601,14 @@ alloc_failed:
   {
     GST_WARNING_OBJECT (mux,
         "failed allocating a %" G_GSIZE_FORMAT " bytes buffer", headerlen);
+#ifdef GST_EXT_ENHANCEMENT
+    if (header) {
+      g_free (header);
+      header = NULL;
+    }
+#else /* GST_EXT_ENHANCEMENT */
     g_free (header);
+#endif /* GST_EXT_ENHANCEMENT */
     goto beach;
   }
 }
old mode 100644 (file)
new mode 100755 (executable)
index 1566f97..0e05ccd
@@ -158,5 +158,5 @@ gboolean
 gst_rtp_depay_plugin_init (GstPlugin * plugin)
 {
   return gst_element_register (plugin, "rtpdepay",
-      GST_RANK_SECONDARY, GST_TYPE_RTP_DEPAY);
+      GST_RANK_MARGINAL, GST_TYPE_RTP_DEPAY);
 }
index 55ef623..1fd9194 100644 (file)
 
 #include "gstrtpmp2tpay.h"
 
+#define DEFAULT_RTP_FLUSH           FALSE
+
+enum {
+  PROP_0,
+  PROP_RTP_FLUSH
+};
+
 static GstStaticPadTemplate gst_rtp_mp2t_pay_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -45,6 +52,10 @@ GST_STATIC_PAD_TEMPLATE ("src",
         "clock-rate = (int) 90000, " "encoding-name = (string) \"MP2T-ES\"")
     );
 
+static void gst_rtp_mp2t_pay_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_rtp_mp2t_pay_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 static gboolean gst_rtp_mp2t_pay_setcaps (GstBaseRTPPayload * payload,
     GstCaps * caps);
 static GstFlowReturn gst_rtp_mp2t_pay_handle_buffer (GstBaseRTPPayload *
@@ -83,6 +94,18 @@ gst_rtp_mp2t_pay_class_init (GstRTPMP2TPayClass * klass)
 
   gstbasertppayload_class->set_caps = gst_rtp_mp2t_pay_setcaps;
   gstbasertppayload_class->handle_buffer = gst_rtp_mp2t_pay_handle_buffer;
+
+  gobject_class->set_property = gst_rtp_mp2t_pay_set_property;
+  gobject_class->get_property = gst_rtp_mp2t_pay_get_property;
+  /* GstRTPMP2TPay: rtp-flush
+   * Try to use this option to flush rtp packet if adaptation field is present
+   * in mpeg2-ts packet. If this option is disabled then packet will be flushed
+   * based on MTU of RTP packet.*/
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_RTP_FLUSH,
+        g_param_spec_boolean ("rtp-flush", "RTP-FLUSH",
+            "Flush RTP packet when adaptation field is present in MP2TS packet",
+            DEFAULT_RTP_FLUSH, G_PARAM_READWRITE));
 }
 
 static void
@@ -92,6 +115,7 @@ gst_rtp_mp2t_pay_init (GstRTPMP2TPay * rtpmp2tpay, GstRTPMP2TPayClass * klass)
   GST_BASE_RTP_PAYLOAD_PT (rtpmp2tpay) = GST_RTP_PAYLOAD_MP2T;
 
   rtpmp2tpay->adapter = gst_adapter_new ();
+  rtpmp2tpay->rtp_flush = DEFAULT_RTP_FLUSH;
 }
 
 static void
@@ -107,6 +131,38 @@ gst_rtp_mp2t_pay_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static void gst_rtp_mp2t_pay_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec) {
+  GstRTPMP2TPay *rtpmp2tpay;
+
+  rtpmp2tpay = GST_RTP_MP2T_PAY (object);
+
+  switch (prop_id) {
+    case PROP_RTP_FLUSH:
+      rtpmp2tpay->rtp_flush = g_value_get_boolean (value);
+      break;
+    default :
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void gst_rtp_mp2t_pay_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec) {
+  GstRTPMP2TPay *rtpmp2tpay;
+
+  rtpmp2tpay = GST_RTP_MP2T_PAY (object);
+
+  switch (prop_id) {
+    case PROP_RTP_FLUSH:
+      g_value_set_boolean (value, rtpmp2tpay->rtp_flush);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
 static gboolean
 gst_rtp_mp2t_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
 {
@@ -159,13 +215,14 @@ gst_rtp_mp2t_pay_handle_buffer (GstBaseRTPPayload * basepayload,
   guint size, avail, packet_len;
   GstClockTime timestamp, duration;
   GstFlowReturn ret;
-
+  guint8 *outbuf = NULL;
+  gboolean check_flush = FALSE;
   rtpmp2tpay = GST_RTP_MP2T_PAY (basepayload);
 
   size = GST_BUFFER_SIZE (buffer);
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   duration = GST_BUFFER_DURATION (buffer);
-
+  outbuf = GST_BUFFER_DATA(buffer);
   ret = GST_FLOW_OK;
   avail = gst_adapter_available (rtpmp2tpay->adapter);
 
@@ -182,7 +239,9 @@ gst_rtp_mp2t_pay_handle_buffer (GstBaseRTPPayload * basepayload,
   /* if this buffer is going to overflow the packet, flush what we
    * have. */
   if (gst_basertppayload_is_filled (basepayload,
-          packet_len, rtpmp2tpay->duration + duration)) {
+          packet_len, rtpmp2tpay->duration + duration) ) {
+          GST_DEBUG ("**frame has been flushed and size of frame is %d", packet_len);
+    check_flush = TRUE;
     ret = gst_rtp_mp2t_pay_flush (rtpmp2tpay);
     rtpmp2tpay->first_ts = timestamp;
     rtpmp2tpay->duration = duration;
@@ -196,6 +255,12 @@ gst_rtp_mp2t_pay_handle_buffer (GstBaseRTPPayload * basepayload,
   /* copy buffer to adapter */
   gst_adapter_push (rtpmp2tpay->adapter, buffer);
 
+  /* If last MP2TSmux packet has adaptation field then flush the RTP packet. */
+  if((rtpmp2tpay->rtp_flush == TRUE) && (outbuf[3] & 0x20) && (check_flush == FALSE)) {
+    ret = gst_rtp_mp2t_pay_flush (rtpmp2tpay);
+    rtpmp2tpay->first_ts = timestamp;
+    rtpmp2tpay->duration = duration;
+  }
   return ret;
 
 }
index e7a679b..d51ef09 100644 (file)
@@ -48,6 +48,7 @@ struct _GstRTPMP2TPay
   GstAdapter  *adapter;
   GstClockTime first_ts;
   GstClockTime duration;
+  gboolean rtp_flush;
 };
 
 struct _GstRTPMP2TPayClass
index de14225..20fb6e1 100644 (file)
@@ -536,6 +536,10 @@ gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)
   src->udp_buffer_size = DEFAULT_UDP_BUFFER_SIZE;
   src->short_header = DEFAULT_SHORT_HEADER;
 
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+  src->wait_pause_response = FALSE;
+#endif
+
   /* get a list of all extensions */
   src->extensions = gst_rtsp_ext_list_get ();
 
@@ -4499,6 +4503,11 @@ again:
 
   gst_rtsp_connection_reset_timeout (conn);
 
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+  if(request->type_data.request.method == GST_RTSP_PAUSE)
+    src->wait_pause_response = TRUE;
+#endif
+
 next:
   res = gst_rtspsrc_connection_receive (src, conn, response, src->ptcp_timeout);
   if (res < 0)
@@ -4507,6 +4516,15 @@ next:
   if (src->debug)
     gst_rtsp_message_dump (response);
 
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+  if(request->type_data.request.method != GST_RTSP_PAUSE && src->wait_pause_response) {
+    GST_DEBUG_OBJECT(src, "ignoring PAUSE response message");
+    src->wait_pause_response = FALSE;
+    goto next;
+  }
+#endif
+
+
   switch (response->type) {
     case GST_RTSP_MESSAGE_REQUEST:
       res = gst_rtspsrc_handle_request (src, conn, response);
@@ -4533,6 +4551,11 @@ next:
 
   GST_DEBUG_OBJECT (src, "got response message %d", thecode);
 
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+  if(request->type_data.request.method == GST_RTSP_PAUSE)
+    src->wait_pause_response = FALSE;
+#endif
+
   /* if the caller wanted the result code, we store it. */
   if (code)
     *code = thecode;
@@ -4571,7 +4594,11 @@ receive_error:
     switch (res) {
       case GST_RTSP_EEOF:
         GST_WARNING_OBJECT (src, "server closed connection, doing reconnect");
-        if (try == 0) {
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+        if(request->type_data.request.method == GST_RTSP_PAUSE)
+          src->wait_pause_response = FALSE;
+#endif
+       if (try == 0) {
           try++;
           /* if reconnect succeeds, try again */
           if ((res =
@@ -6093,8 +6120,15 @@ gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment, gboolean async)
   if (!(src->methods & GST_RTSP_PLAY))
     goto not_supported;
 
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+  if (src->state == GST_RTSP_STATE_PLAYING) {
+    if(src->wait_pause_response == FALSE)
+      goto was_playing;
+  }
+#else
   if (src->state == GST_RTSP_STATE_PLAYING)
     goto was_playing;
+#endif
 
   if (!src->conninfo.connection || !src->conninfo.connected)
     goto done;
index cf8f81c..c4f4a73 100644 (file)
@@ -227,6 +227,11 @@ struct _GstRTSPSrc {
   gchar             *control;
   guint              next_port_num;
 
+#ifdef GST_EXT_RTSPSRC_MODIFICATION
+  gboolean          wait_pause_response;
+#endif
+
   /* supported methods */
   gint               methods;
 
old mode 100644 (file)
new mode 100755 (executable)
index b65ab8c..d1d1ad2
@@ -960,6 +960,7 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
   }
 
   len = sizeof (sndsize);
+#if 0 //WFD Wifi Device socket size issue, kernel 3.4.5 patch (sendto() performance -to use default buffer size
   if (sink->buffer_size != 0) {
     sndsize = sink->buffer_size;
 
@@ -976,7 +977,7 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
               sndsize, ret, g_strerror (errno), errno));
     }
   }
-
+#endif
   /* read the value of the receive buffer. Note that on linux this returns 2x the
    * value we set because the kernel allocates extra memory for metadata.
    * The default on Linux is about 100K (which is about 50K without metadata) */
index cce76d0..818ebac 100644 (file)
@@ -757,7 +757,7 @@ gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos)
     return TRUE;
   }
 
-  if (wav->bps > 0) {
+  if (wav->bps > 0 && !(wav->fact)) {          /* bug fix */
     *bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND);
     return TRUE;
   } else if (wav->fact) {
@@ -1122,7 +1122,7 @@ gst_wavparse_calculate_duration (GstWavParse * wav)
   if (wav->duration > 0)
     return TRUE;
 
-  if (wav->bps > 0) {
+  if (wav->bps > 0 && !(wav->fact)) {          /* bug fix */
     GST_INFO_OBJECT (wav, "Got datasize %" G_GUINT64_FORMAT, wav->datasize);
     wav->duration =
         uint64_ceiling_scale (wav->datasize, GST_SECOND, (guint64) wav->bps);
@@ -1268,8 +1268,38 @@ gst_wavparse_stream_headers (GstWavParse * wav)
         break;
       }
       case GST_RIFF_WAVE_FORMAT_PCM:
+#ifdef WAVPARSER_MODIFICATION
+        /* This spec-out case occurs in certain product.
+          * So, we added code such as lower part. */
+        if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0)) {
+          guint32 tmp_bps = (wav->rate * wav->depth * wav->channels) / 8;
+          if (wav->av_bps == (tmp_bps * 8) ) {
+            GST_WARNING_OBJECT (wav, "invalid_blockalign : worng blockalign = %u, bps = %u", (guint) wav->blockalign, wav->av_bps);
+            GST_WARNING_OBJECT (wav, "must update caps for spec-out case ");
+            wav->blockalign = wav->channels * (guint) ceil (wav->depth / 8.0);
+            if (wav->channels > 0)
+              wav->width = (wav->blockalign * 8) / wav->channels;
+            else
+              goto no_channels;
+            wav->av_bps =  wav->rate * wav->blockalign * wav->channels;
+            wav->bps = wav->av_bps;
+            caps = gst_caps_new_simple ("audio/x-raw-int",
+              "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
+              "channels", G_TYPE_INT, wav->channels,
+              "width", G_TYPE_INT, wav->width,
+              "depth", G_TYPE_INT, (guint) wav->depth,
+              "signed", G_TYPE_BOOLEAN, wav->width != 8,
+              "rate", G_TYPE_INT, wav->rate,
+              NULL);
+            break;
+          } else {
+            goto invalid_blockalign;
+          }
+        }
+#else
         if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0))
           goto invalid_blockalign;
+#endif
         /* fall through */
       default:
         if (wav->av_bps > wav->blockalign * wav->rate)
@@ -1285,6 +1315,13 @@ gst_wavparse_stream_headers (GstWavParse * wav)
     if (wav->bytes_per_sample <= 0)
       goto no_bytes_per_sample;
 
+#ifdef WAVPARSER_MODIFICATION
+    if (wav->depth > 32 || wav->width > 32) {
+      GST_WARNING_OBJECT (wav, " invalid_bitresolution : depths (%d) width (%d)", wav->depth, wav->width);
+     goto invalid_bitresolution;
+    }
+#endif
+
     GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
     GST_DEBUG_OBJECT (wav, "width      = %u", (guint) wav->width);
     GST_DEBUG_OBJECT (wav, "depth      = %u", (guint) wav->depth);
@@ -1678,6 +1715,14 @@ header_read_error:
         ("Couldn't read in header %d (%s)", res, gst_flow_get_name (res)));
     goto fail;
   }
+#ifdef WAVPARSER_MODIFICATION
+invalid_bitresolution :
+  {
+    GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
+        ("Not support higher than 32 bit resolution"));
+    goto fail;
+  }
+#endif
 }
 
 /*
@@ -1937,7 +1982,7 @@ iterate_adapter:
     }
   }
 
-  if (wav->bps > 0) {
+  if (wav->bps > 0 && !(wav->fact)) {          /* bug fix */
     /* and timestamps if we have a bitrate, be careful for overflows */
     timestamp = uint64_ceiling_scale (pos, GST_SECOND, (guint64) wav->bps);
     next_timestamp =
@@ -2234,7 +2279,11 @@ gst_wavparse_sink_event (GstPad * pad, GstEvent * event)
           guint64 bps = wav->bps;
 
           /* operating in format TIME, so we can convert */
+#if 0     /* original */
           if (!bps && wav->fact)
+#else     /* bug fix */
+                                       if (wav->fact)
+#endif
             bps =
                 gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
           if (bps) {
@@ -2357,7 +2406,7 @@ gst_wavparse_pad_convert (GstPad * pad,
           GST_INFO_OBJECT (wavparse,
               "src=%" G_GINT64_FORMAT ", offset=%" G_GINT64_FORMAT, src_value,
               wavparse->offset);
-          if (wavparse->bps > 0)
+          if (wavparse->bps > 0 && !(wavparse->fact))          /* bug fix */
             *dest_value = uint64_ceiling_scale (src_value, GST_SECOND,
                 (guint64) wavparse->bps);
           else if (wavparse->fact) {
@@ -2393,7 +2442,7 @@ gst_wavparse_pad_convert (GstPad * pad,
     case GST_FORMAT_TIME:
       switch (*dest_format) {
         case GST_FORMAT_BYTES:
-          if (wavparse->bps > 0)
+          if (wavparse->bps > 0  && !(wavparse->fact))         /* bug fix */
             *dest_value = gst_util_uint64_scale (src_value,
                 (guint64) wavparse->bps, GST_SECOND);
           else {
old mode 100644 (file)
new mode 100755 (executable)
index d5362a6..46ef78d
@@ -1,10 +1,10 @@
 #sbs-git:slp/pkgs/g/gst-plugins-good0.10 gst-plugins-good 0.10.31 6e8625ba6fe94fb9d09e6c3be220b54ffaa01273
 Name:       gst-plugins-good
 Summary:    GStreamer plugins from the "good" set
-Version:    0.10.31
-Release:    3
+Version:    0.10.34
+Release:    127
 Group:      Applications/Multimedia
-License:    LGPLv2+
+License:    LGPL-2.1+
 Source0:    %{name}-%{version}.tar.gz
 #Patch0 :    gst-plugins-good-divx-drm.patch
 #Patch1 :    gst-plugins-good-ebml-read.patch
@@ -16,10 +16,9 @@ Patch6 :    gst-plugins-good-disable-gtk-doc.patch
 BuildRequires:  gettext
 BuildRequires:  which
 BuildRequires:  gst-plugins-base-devel  
-BuildRequires:  libjpeg-devel
+BuildRequires:  libjpeg-turbo-devel
 BuildRequires:  pkgconfig(gstreamer-0.10) 
 BuildRequires:  pkgconfig(glib-2.0)
-BuildRequires:  pkgconfig(liboil-0.3)
 BuildRequires:  pkgconfig(libpng)
 BuildRequires:  pkgconfig(libsoup-2.4)
 BuildRequires:  pkgconfig(libpulse)
@@ -27,6 +26,11 @@ BuildRequires:  pkgconfig(x11)
 BuildRequires:  pkgconfig(xfixes)
 BuildRequires:  pkgconfig(xdamage)
 BuildRequires:  pkgconfig(xext)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(iniparser)
+#BuildRequires:  pkgconfig(drm-client)
+#BuildRequires:  pkgconfig(drm-trusted)
+#BuildRequires:        pkgconfig(libdrm)
 
 %description
 GStreamer is a streaming media framework, based on graphs of filters
@@ -35,7 +39,6 @@ anything from real-time sound processing to playing videos, and just
 about anything else media-related.  Its plugin-based architecture means
 that new data types or processing capabilities can be added simply by
 installing new plug-ins.
-.
 This package contains the GStreamer plugins from the "good" set, a set
 of good-quality plug-ins under the LGPL license.
 
@@ -50,12 +53,17 @@ of good-quality plug-ins under the LGPL license.
 #%patch5 -p1
 %patch6 -p1
 
-
 %build
 ./autogen.sh
 
 export CFLAGS+=" -Wall -g -fPIC\
- -DGST_EXT_SOUP_MODIFICATION"
+ -DGST_EXT_SOUP_MODIFICATION \
+ -DGST_EXT_RTSPSRC_MODIFICATION \
+ -DGST_EXT_AMRPARSER_MODIFICATION \
+ -DGST_EXT_AACPARSER_MODIFICATION \
+ -DGST_EXT_SS_TYPE \
+ -DGST_EXT_MPEGAUDIO_MODIFICATION \
+ -DGST_EXT_ENHANCEMENT"
 
 %configure --prefix=%{_prefix}\
  --disable-static\
@@ -75,7 +83,7 @@ export CFLAGS+=" -Wall -g -fPIC\
  --disable-deinterlace\
  --disable-effectv\
  --disable-equalizer\
- --disable-icydemux\
+ --enable-icydemux\
  --disable-flx\
  --disable-goom\
  --disable-goom2k1\
@@ -114,15 +122,20 @@ make %{?jobs:-j%jobs}
 
 %install
 rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp COPYING %{buildroot}/usr/share/license/%{name}
 %make_install
 
 
 
 
 %files
+%manifest gst-plugins-good.manifest
 %defattr(-,root,root,-)
 %{_libdir}/gstreamer-0.10
 %{_libdir}/gstreamer-0.10/libgstavi.so
+%{_libdir}/gstreamer-0.10/libgstflv.so
+%{_libdir}/gstreamer-0.10/libgstmatroska.so
 %{_libdir}/gstreamer-0.10/libgstrtsp.so
 %{_libdir}/gstreamer-0.10/libgstisomp4.so
 %{_libdir}/gstreamer-0.10/libgstvideocrop.so
@@ -130,7 +143,6 @@ rm -rf %{buildroot}
 %{_libdir}/gstreamer-0.10/libgstpulse.so
 %{_libdir}/gstreamer-0.10/libgstmultifile.so
 %{_libdir}/gstreamer-0.10/libgstpng.so
-%{_libdir}/gstreamer-0.10/libgstflv.so
 %{_libdir}/gstreamer-0.10/libgstudp.so
 %{_libdir}/gstreamer-0.10/libgstximagesrc.so
 %{_libdir}/gstreamer-0.10/libgstalaw.so
@@ -140,7 +152,6 @@ rm -rf %{buildroot}
 %{_libdir}/gstreamer-0.10/libgstjpeg.so
 %{_libdir}/gstreamer-0.10/libgstautodetect.so
 %{_libdir}/gstreamer-0.10/libgstvideofilter.so
-%{_libdir}/gstreamer-0.10/libgstmatroska.so
 %{_libdir}/gstreamer-0.10/libgstmulaw.so
 %{_libdir}/gstreamer-0.10/libgstrtp.so
 %{_libdir}/gstreamer-0.10/libgstwavparse.so
@@ -149,3 +160,4 @@ rm -rf %{buildroot}
 %{_libdir}/gstreamer-0.10/libgstshapewipe.so
 %{_libdir}/gstreamer-0.10/libgstoss4audio.so
 %{_libdir}/gstreamer-0.10/libgstsouphttpsrc.so
+/usr/share/license/%{name}
index b81c6a4..51cc0ce 100644 (file)
@@ -181,7 +181,6 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
     GST_LOG_OBJECT (pool->v4l2elem, "  MMAP offset:  %u",
         ret->vbuffer.m.offset);
   GST_LOG_OBJECT (pool->v4l2elem, "  length:    %u", ret->vbuffer.length);
-  GST_LOG_OBJECT (pool->v4l2elem, "  input:     %u", ret->vbuffer.input);
 
   data = (guint8 *) v4l2_mmap (0, ret->vbuffer.length,
       PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
index 309bfb6..ca10bc4 100644 (file)
@@ -294,8 +294,12 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
         break;
       case V4L2_CID_HFLIP:
       case V4L2_CID_VFLIP:
+#ifndef V4L2_CID_PAN_RESET
       case V4L2_CID_HCENTER:
+#endif
+#ifndef V4L2_CID_TILT_RESET
       case V4L2_CID_VCENTER:
+#endif
 #ifdef V4L2_CID_PAN_RESET
       case V4L2_CID_PAN_RESET:
 #endif