tizen 2.3.1 release tizen_2.3.1 submit/tizen_2.3.1/20150915.081228 tizen_2.3.1_release
authorjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:27:39 +0000 (22:27 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:27:39 +0000 (22:27 +0900)
45 files changed:
configure.ac
debian/changelog
debian/rules
ext/alsa/gstalsa.c [changed mode: 0644->0755]
ext/alsa/gstalsasrc.c [changed mode: 0644->0755]
ext/alsa/gstalsasrc.h [changed mode: 0644->0755]
ext/ogg/gstoggdemux.c
ext/ogg/gstoggstream.c
gst-libs/gst/app/gstappsrc.c [changed mode: 0644->0755]
gst-libs/gst/audio/gstaudiodecoder.c
gst-libs/gst/audio/gstbaseaudiosink.c [changed mode: 0644->0755]
gst-libs/gst/audio/gstringbuffer.c
gst-libs/gst/interfaces/cameracontrol.c
gst-libs/gst/interfaces/cameracontrol.h
gst-libs/gst/interfaces/cameracontrolchannel.c
gst-libs/gst/interfaces/cameracontrolchannel.h
gst-libs/gst/riff/riff-media.c [changed mode: 0644->0755]
gst-libs/gst/rtsp/gstrtspconnection.c [changed mode: 0644->0755]
gst-libs/gst/rtsp/gstrtspdefs.h [changed mode: 0644->0755]
gst-libs/gst/rtsp/gstrtsptransport.c
gst-libs/gst/tag/gstxmptag.c
gst-libs/gst/video/video.c
gst-libs/gst/video/video.h [changed mode: 0644->0755]
gst-plugins-base-tools.manifest [new file with mode: 0755]
gst-plugins-base.manifest [new file with mode: 0755]
gst/audioconvert/gstaudioconvert.c
gst/ffmpegcolorspace/gstffmpegcodecmap.c
gst/ffmpegcolorspace/gstffmpegcolorspace.c
gst/playback/gstdecodebin2.c [changed mode: 0644->0755]
gst/playback/gstplaysink.c [changed mode: 0644->0755]
gst/subparse/Makefile.am
gst/subparse/gstsubparse.c [changed mode: 0644->0755]
gst/subparse/gstsubparse.h [changed mode: 0644->0755]
gst/subparse/samiparse.c [changed mode: 0644->0755]
gst/subparse/samiparse.h [changed mode: 0644->0755]
gst/typefind/gsttypefindfunctions.c [changed mode: 0644->0755]
gst/videorate/gstvideorate.c
gst/videorate/gstvideorate.h
gst/volume/gstvolume.c
packaging/gst-plugins-base.spec [changed mode: 0644->0755]
sys/xvimage/Makefile.am
sys/xvimage/xv_types.h [changed mode: 0644->0755]
sys/xvimage/xvimagesink.c [changed mode: 0644->0755]
sys/xvimage/xvimagesink.h [changed mode: 0644->0755]
tools/Makefile.am

index 1901bcf..8569474 100644 (file)
@@ -118,6 +118,14 @@ AG_GST_ARG_ENABLE_EXTERNAL
 
 AG_GST_ARG_ENABLE_EXPERIMENTAL
 
+PKG_CHECK_MODULES(DRM, libdrm)
+AC_SUBST(DRM_CFLAGS)
+AC_SUBST(DRM_LIBS)
+
+PKG_CHECK_MODULES(DRM, libdrm-devel)
+AC_SUBST(DRM_DEVEL_CFLAGS)
+AC_SUBST(DRM_DEVEL_LIBS)
+
 dnl *** checks for platform ***
 AG_GST_PLATFORM
 
@@ -434,9 +442,15 @@ AG_GST_CHECK_PLUGIN(volume)
 
 dnl check for gstreamer core features (subsystems)
 dnl FIXME: this assumes srcdir == builddir for uninstalled setups
-GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-0.10`"/gst/gstconfig.h"
-AG_GST_PARSE_SUBSYSTEM_DISABLES($GST_CONFIGPATH)
-AM_CONDITIONAL(USE_XML, test $GST_DISABLE_XML != "1")
+dnl YeJin Cho : subparse needs xml for parsing smi, enalbe USE_XML
+dnl GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-0.10`"/gst/gstconfig.h"
+dnl AG_GST_PARSE_SUBSYSTEM_DISABLES($GST_CONFIGPATH)
+dnl AM_CONDITIONAL(USE_XML, test $GST_DISABLE_XML != "1")
+
+AM_CONDITIONAL(USE_XML, true)
+PKG_CHECK_MODULES(XML, libxml-2.0)
+AC_SUBST(XML_CFLAGS)
+AC_SUBST(XML_LIBS)
 
 dnl disable plug-ins that require libxml2's HTML support if it is not available
 if test "x$HAVE_LIBXML_HTML" != "xyes"; then
@@ -923,6 +937,42 @@ dnl whatevertarget_LIBS and -L flags here affect the rest of the linking
 GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_desc.*' $GST_ALL_LDFLAGS"
 AC_SUBST(GST_PLUGIN_LDFLAGS)
 
+dnl use xfixes
+PKG_CHECK_MODULES(XFIXES, xfixes)
+AC_SUBST(XFIXES_CFLAGS)
+AC_SUBST(XFIXES_LIBS)
+
+dnl use dri2proto
+PKG_CHECK_MODULES(DRI2PROTO, dri2proto)
+AC_SUBST(DRI2PROTO_CFLAGS)
+AC_SUBST(DRI2PROTO_LIBS)
+
+dnl use dri2
+PKG_CHECK_MODULES(DRI2, libdri2)
+AC_SUBST(DRI2_CFLAGS)
+AC_SUBST(DRI2_LIBS)
+
+dnl use tbm
+PKG_CHECK_MODULES(TBM, libtbm)
+AC_SUBST(TBM_CFLAGS)
+AC_SUBST(TBM_LIBS)
+
+dnl Check Savs Codec Packages
+#PKG_CHECK_MODULES(SAVSCODEC_HEVC, libsavscodec-neon-hevc)
+#AC_SUBST(SAVSCODEC_HEVC_LDFLAGS)
+#AC_SUBST(SAVSCODEC_HEVC_CFLAGS)
+#AC_SUBST(SAVSCODEC_HEVC_LIBS)
+
+dnl use utilX
+PKG_CHECK_MODULES(UTILX, utilX)
+AC_SUBST(UTILX_CFLAGS)
+AC_SUBST(UTILX_LIBS)
+
+dnl use vconf
+PKG_CHECK_MODULES(VCONF, vconf)
+AC_SUBST(VCONF_CFLAGS)
+AC_SUBST(VCONF_LIBS)
+
 dnl *** output files ***
 
 AC_CONFIG_FILES(
index 3d1b849..925f233 100644 (file)
@@ -1,3 +1,351 @@
+gst-plugins-base0.10 (0.10.36-74) unstable; urgency=low
+
+  * [xvimagesink] Check whether external display is connected or not when VisibilityNofify FALSE event is received
+  * Tag: gst-plugins-base0.10_0.10.36-74
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Sat, 01 Jun 2013 13:25:22 +0900
+
+gst-plugins-base0.10 (0.10.36-73) unstable; urgency=low
+
+  * [xvimagesink] Update window if window handle is changed and state is PAUSED
+  * Tag: gst-plugins-base0.10_0.10.36-73
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 30 May 2013 17:46:10 +0900
+
+gst-plugins-base0.10 (0.10.36-68) unstable; urgency=low
+
+  * [xvimagesink] Fix bug - skip putimage because of abnormal condition check code
+  * Tag: gst-plugins-base0.10_0.10.36-68
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Wed, 08 May 2013 13:35:56 +0900
+
+gst-plugins-base0.10 (0.10.36-66) unstable; urgency=low
+
+  * [cameracontrol] Add new field for embedded data
+  * Tag: gst-plugins-base0.10_0.10.36-66
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 18 Apr 2013 19:22:01 +0900
+
+gst-plugins-base0.10 (0.10.36-65) unstable; urgency=low
+
+  * [xvimagesink] Add new property for color space range
+  * Tag: gst-plugins-base0.10_0.10.36-65
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 18 Apr 2013 17:29:09 +0900
+
+gst-plugins-base0.10 (0.10.36-64) unstable; urgency=low
+
+  * [xvimagesink] Fix prevent issue
+  * Tag: gst-plugins-base0.10_0.10.36-64
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Mon, 15 Apr 2013 14:38:35 +0900
+
+gst-plugins-base0.10 (0.10.36-63) unstable; urgency=low
+
+  * [xvimagesink] Skip putimage when too many buffers are already put
+  * Tag: gst-plugins-base0.10_0.10.36-63
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Fri, 05 Apr 2013 20:17:24 +0900
+
+gst-plugins-base0.10 (0.10.36-62) unstable; urgency=low
+
+  * [xvimagesink] Init aligned size when change image size while playing
+  * Tag: gst-plugins-base0.10_0.10.36-62
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Fri, 05 Apr 2013 14:04:22 +0900
+
+gst-plugins-base0.10 (0.10.36-60) unstable; urgency=low
+
+  * [xvimagesink] Modify structure of SCMN_IMGB for compatibility
+  * Tag: gst-plugins-base0.10_0.10.36-60
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Fri, 22 Mar 2013 13:57:43 +0900
+
+gst-plugins-base0.10 (0.10.36-59) unstable; urgency=low
+
+  * [xvimagesink] Support new fourcc "SR32" and new buffer share method(TIZEN_BUFFER)
+  * Tag: gst-plugins-base0.10_0.10.36-59
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 21 Mar 2013 14:12:38 +0900
+
+gst-plugins-base0.10 (0.10.36-57) unstable; urgency=low
+
+  * [xvimagesink] Putimage with invalid gem name when receive duplicated buffer
+  * Tag: gst-plugins-base0.10_0.10.36-57
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 14 Feb 2013 09:54:06 +0900
+
+gst-plugins-base0.10 (0.10.36-56) unstable; urgency=low
+
+  * [xvimagesink] check if the xcontext was made when setting visible property
+  * Tag: gst-plugins-base0.10_0.10.36-56
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 12 Feb 2013 10:01:45 +0900
+
+gst-plugins-base0.10 (0.10.36-55) unstable; urgency=low
+
+  * [xvimagesink] Enahance buffer management when DMABUF mode
+  * Tag: gst-plugins-base0.10_0.10.36-55
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Mon, 04 Feb 2013 18:27:02 +0900
+
+gst-plugins-base0.10 (0.10.36-54) unstable; urgency=low
+
+  * [xvimagesink] Add log at state_change function
+  * Tag: gst-plugins-base0.10_0.10.36-54
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Tue, 29 Jan 2013 15:04:01 +0900
+
+gst-plugins-base0.10 (0.10.36-53) unstable; urgency=low
+
+  * [xvimagesink] Fix memory leak when error or non-visible case
+  * Tag: gst-plugins-base0.10_0.10.36-53
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 24 Jan 2013 21:34:01 +0900
+
+gst-plugins-base0.10 (0.10.36-52) unstable; urgency=low
+
+  * [xvimagesink] Wait displaying buffer when drm close
+  * Tag: gst-plugins-base0.10_0.10.36-52
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Wed, 23 Jan 2013 15:26:08 +0900
+
+gst-plugins-base0.10 (0.10.36-51) unstable; urgency=low
+
+  * Update boilerplate for license
+  * Tag: gst-plugins-base0.10_0.10.36-51
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Sat, 19 Jan 2013 11:23:18 +0900
+
+gst-plugins-base0.10 (0.10.36-49) unstable; urgency=low
+
+  * [xvimagesink] Added "frame-render-error" signal for error caught case when calling XvPutImage()
+  * Tag: gst-plugins-base0.10_0.10.36-49
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Fri, 18 Jan 2013 14:25:32 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+46) unstable; urgency=low
+
+  * [xvimagesink] 1. do not store buffer information at displaying_buffers when using pixmap callback  2. change display geometry method enum type ordering
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+46
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Tue, 02 Jan 2013 16:06:11 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+45) unstable; urgency=low
+
+  * [xvimagesink] Fix prevent issue
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+45
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Mon, 31 Dec 2012 11:13:02 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+42) unstable; urgency=low
+
+  * [xvimagesink] Fix prevent defects
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+42
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Sat, 22 Dec 2012 15:55:23 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+41) unstable; urgency=low
+
+  * Fix prevent issue
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+41
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Sat, 22 Dec 2012 14:29:44 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+38) unstable; urgency=low
+
+  * [xvimagesink] add ORIGIN_SIZE_OR_LETTER_BOX mode for geometry method type
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+38
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Sun, 09 Dec 2012 14:22:43 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+37) unstable; urgency=low
+
+  * [xvimagesink] fix bug - refer im_format in xvimage(not in xvimagesink handle) created by _buffer_alloc()
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+37
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Sat, 08 Dec 2012 19:14:17 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+36) unstable; urgency=low
+
+  * [xvimagesink] add defensive code not to unref finalized buffer
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+36
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 06 Dec 2012 20:07:48 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+35) unstable; urgency=low
+
+  * [xvimagesink] move g_mutex_lock(flow_lock) code caused of unlock many times
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+35
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 05 Dec 2012 13:54:11 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+33) unstable; urgency=low
+
+  * [xvimagesink] Improve buffer management when DMABUF mode
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+33
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Tue, 04 Dec 2012 15:26:38 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+31) unstable; urgency=low
+
+  * [xvimagesink] do drm_fini() when GST_STATE_CHANGE_PAUSED_TO_READY
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+31
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 28 Nov 2012 20:50:12 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+30) unstable; urgency=low
+
+  * [xvimagesink] add code for posting "prepare-xid" element message with video size and display size on the bus to give applications an opportunity to set xwindow or xpixmap
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+30
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Fri, 16 Nov 2012 13:36:23 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+29) unstable; urgency=low
+
+  * [xvimagesink] Support SN21 format
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+29
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Wed, 14 Nov 2012 21:02:56 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+28) unstable; urgency=low
+
+  * [xvimagesink] add flow_lock/unlock in _show_frame() preparing in the event of using _set_window_handle()
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+28
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 14 Nov 2012 10:34:56 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+27) unstable; urgency=low
+
+  * [typefind] Modify aac type find to select correctly
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+27
+
+ -- Sunghyun Eum <sunghyun.eum@samsung.com>  Wed, 07 Nov 2012 21:11:36 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+26) unstable; urgency=low
+
+  * [xvimagesink] fix bug - first incoming pixmap's drawing region was set 0 when using multiple pixmaps
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+26
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Wed, 07 Nov 2012 17:08:56 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+25) unstable; urgency=low
+
+  * [xvimagesink] Improve code for dmabuf mode - close gem handle after putimage
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+25
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Tue, 06 Nov 2012 18:06:19 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+22) unstable; urgency=low
+
+  * [xvimagesink] Add new property "flip"
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+22
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Mon, 29 Oct 2012 16:32:17 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+21) unstable; urgency=low
+
+  * [xvimagesink] support multiple pixmaps usage
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+21
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Fri, 26 Oct 2012 16:38:56 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+20) unstable; urgency=low
+
+  * [xvimagesink] fix resources leak in drm_init()
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+20
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Thu, 25 Oct 2012 15:48:53 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+19) unstable; urgency=low
+
+  * [xvimagesink] remove code for closing fd
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+19
+
+ -- Sangchul Lee <sc11.lee@samsung.com>  Thu, 25 Oct 2012 00:22:49 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+18) unstable; urgency=low
+
+  * [subparse] fix for suaparse to enable smi
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+18 
+
+ -- Yejin Cho <cho.yejin@samsung.com>  Mon, 22 Oct 2012 15:23:54 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+17) unstable; urgency=low
+
+  * [ffmpegcolorspace] Support ITLV(actucally UYVY) fourcc
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+17
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Fri, 12 Oct 2012 10:47:00 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+16) unstable; urgency=low
+
+  * [xvimagesink] Fix leak for DRM device open and close
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+16
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 11 Oct 2012 13:17:30 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+13) unstable; urgency=low
+
+  * [xvimagesink] Update code for checking window event
+  * Git: gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+13
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 27 Sep 2012 14:10:20 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+12) unstable; urgency=low
+
+  * [xvimagesink] Apply dmabuf feature
+  * Git: framework/multimedia/gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+12
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 20 Sep 2012 17:29:24 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+11) unstable; urgency=low
+
+  * Add manifest file
+  * Git: framework/multimedia/gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+11
+
+ -- Jeongmo Yang <jm80.yang@samsung.com>  Thu, 20 Sep 2012 14:29:27 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+10) unstable; urgency=low
+
+  * Add extended profile to support 3g2 file
+  * Git: framework/multimedia/gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+10
+
+ -- Sunghyun Eum <sunghyun.eum@samsung.com>  Wed, 19 Sep 2012 10:09:38 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+8) unstable; urgency=low
+
+  * Add specific fourcc to gst_video_format_parse_caps for proper checking
+  * Git: framework/multimedia/gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+8
+
+ -- Sunghyun Eum <sunghyun.eum@samsung.com>  Tue, 11 Sep 2012 09:10:29 +0900
+
+gst-plugins-base0.10 (0.10.36-1slp2+7) unstable; urgency=low
+
+  * Modified TCP data handling for WFD specific case
+  * Git: slp/pkgs/g/gst-plugins-base0.10
+  * Tag: gst-plugins-base0.10_0.10.36-1slp2+7
+
+ -- Santhoshi KS <santhoshi.ks@samsung.com>  Tue, 28 Aug 2012 19:46:30 +0900
+
 gst-plugins-base0.10 (0.10.36-1slp2+6) unstable; urgency=low
 
   * Destroy xim_transparenter image when destroying xwindow
index 25fc4fb..9ad8294 100755 (executable)
@@ -30,7 +30,8 @@ CONFIGURE_OPTION +=--prefix=/usr              \
 CFLAGS += -Wall -g -fPIC                       \
                -DGST_EXT_XV_ENHANCEMENT        \
                -DGST_EXT_LINK_FIMCCONVERT      \
-               -DGST_EXT_MIME_TYPES
+               -DGST_EXT_MIME_TYPES            \
+               -DGST_EXT_ENABLE_SMI
 
 ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
        CFLAGS += -O0
old mode 100644 (file)
new mode 100755 (executable)
index 94ed44c..dcb52e7
@@ -121,8 +121,11 @@ gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
 
     s = gst_caps_get_structure (in_caps, i);
     if (!gst_structure_has_name (s, "audio/x-raw-int")) {
-      GST_WARNING_OBJECT (obj, "skipping non-int format");
-      continue;
+      GST_WARNING_OBJECT (obj, "checking for LPCM format");
+      if(!gst_structure_has_name (s, "audio/x-lpcm")) {
+        GST_WARNING_OBJECT (obj, "skipping non-int format");
+        continue;
+      }
     }
     if (!gst_structure_get_int (s, "width", &width) ||
         !gst_structure_get_int (s, "depth", &depth))
old mode 100644 (file)
new mode 100755 (executable)
index 917f0dc..ce875aa
@@ -62,6 +62,7 @@ enum
   PROP_DEVICE,
   PROP_DEVICE_NAME,
   PROP_CARD_NAME,
+  PROP_IS_LIVE,
   PROP_LAST
 };
 
@@ -88,6 +89,7 @@ static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
 static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
 static guint gst_alsasrc_delay (GstAudioSrc * asrc);
 static void gst_alsasrc_reset (GstAudioSrc * asrc);
+static GstStateChangeReturn gst_alsasrc_change_state (GstElement * element, GstStateChange transition);
 
 /* AlsaSrc signals and args */
 enum
@@ -105,7 +107,13 @@ static GstStaticPadTemplate alsasrc_src_factory =
     GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
+    GST_STATIC_CAPS ("audio/x-lpcm, "
+        "endianness = (int) { 1234, 4321 }, "
+        "signed = (boolean) { TRUE, FALSE }, "
+        "width = (int) 16, "
+        "depth = (int) 16, "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];"
+        "audio/x-raw-int, "
         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
         "signed = (boolean) { TRUE, FALSE }, "
         "width = (int) 32, "
@@ -202,8 +210,10 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
   GObjectClass *gobject_class;
   GstBaseSrcClass *gstbasesrc_class;
   GstAudioSrcClass *gstaudiosrc_class;
+  GstElementClass *gstelement_class;
 
   gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
   gstbasesrc_class = (GstBaseSrcClass *) klass;
   gstaudiosrc_class = (GstAudioSrcClass *) klass;
 
@@ -220,6 +230,7 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
   gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
   gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_alsasrc_change_state);
 
   g_object_class_install_property (gobject_class, PROP_DEVICE,
       g_param_spec_string ("device", "Device",
@@ -235,6 +246,86 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
       g_param_spec_string ("card-name", "Card name",
           "Human-readable name of the sound card",
           DEFAULT_PROP_CARD_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_IS_LIVE,
+     g_param_spec_boolean ("is-live",
+     "is live session",
+     "is live session",
+     0, G_PARAM_READWRITE));
+}
+
+static gboolean timer_flush_data(GstAlsaSrc *src)
+{
+  if(src->handle_pause) {
+    gint32 frames = 0;
+    gint err;
+    frames = snd_pcm_avail(src->handle);
+    if(frames>0) {
+      GST_DEBUG("Frames avail for reading: %d", frames);
+      err = snd_pcm_forward(src->handle,frames);
+      if (err < 0)
+        GST_WARNING("Can't recovery from suspend, prepare failed: %s", snd_strerror (err));
+    }
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static GstStateChangeReturn
+gst_alsasrc_change_state (GstElement * element, GstStateChange transition)
+{
+  GstAlsaSrc *src = GST_ALSA_SRC (element);
+
+  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+  switch (transition) {
+  case GST_STATE_CHANGE_NULL_TO_READY:
+    GST_INFO("GST_STATE_CHANGE_NULL_TO_READY");
+    break;
+  case GST_STATE_CHANGE_READY_TO_PAUSED:
+    GST_INFO("GST_STATE_CHANGE_READY_TO_PAUSED");
+    break;
+  case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+    GST_INFO("GST_STATE_CHANGE_PAUSED_TO_PLAYING");
+    if(src->is_live) {
+      GstAudioSrc * asrc = (GstAudioSrc*)src;
+      gint err;
+      GST_ALSA_SRC_LOCK (asrc);
+
+      gint32 frames = 0;
+      frames = snd_pcm_avail(src->handle);
+      if(frames>0) {
+        GST_DEBUG("Frames avail for reading: %d", frames);
+        err = snd_pcm_forward(src->handle,frames);
+        if (err < 0)
+          GST_WARNING("Can't recovery from suspend, prepare failed: %s", snd_strerror (err));
+      }
+      GST_ALSA_SRC_UNLOCK (asrc);
+      src->handle_pause = FALSE;
+      g_cond_signal(src->pause_cond);
+    }
+    break;
+  case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+    GST_INFO("GST_STATE_CHANGE_PLAYING_TO_PAUSED");
+    if(src->is_live) {
+      src->handle_pause = TRUE;
+      src->flush_src_id = g_timeout_add(100, timer_flush_data, src);
+    }
+    break;
+  case GST_STATE_CHANGE_PAUSED_TO_READY:
+    GST_INFO("GST_STATE_CHANGE_PAUSED_TO_READY");
+    if (src->is_live) {
+      if (src->flush_src_id > 0) g_source_remove(src->flush_src_id);
+      src->handle_pause = FALSE;
+    }
+    break;
+  case GST_STATE_CHANGE_READY_TO_NULL:
+    GST_INFO("GST_STATE_CHANGE_READY_TO_NULL");
+    break;
+  default :
+    break;
+  }
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  return result;
 }
 
 static void
@@ -253,6 +344,10 @@ gst_alsasrc_set_property (GObject * object, guint prop_id,
         src->device = g_strdup (DEFAULT_PROP_DEVICE);
       }
       break;
+    case PROP_IS_LIVE:
+      src->is_live = g_value_get_boolean (value);
+      GST_DEBUG("is_live %d", src->is_live);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -281,6 +376,9 @@ gst_alsasrc_get_property (GObject * object, guint prop_id,
           gst_alsa_find_card_name (GST_OBJECT_CAST (src),
               src->device, SND_PCM_STREAM_CAPTURE));
       break;
+    case PROP_IS_LIVE:
+      g_value_set_boolean (value, src->is_live);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -296,6 +394,9 @@ gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
   alsasrc->cached_caps = NULL;
 
   alsasrc->alsa_lock = g_mutex_new ();
+  alsasrc->pause_cond = g_cond_new ();
+  alsasrc->pause_lock = g_mutex_new ();
+  alsasrc->handle_pause = FALSE;
 }
 
 #define CHECK(call, error) \
@@ -745,6 +846,7 @@ xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
 
   if (err == -EPIPE) {          /* under-run */
+    GST_DEBUG_OBJECT (alsa, "overrun case");
     err = snd_pcm_prepare (handle);
     if (err < 0)
       GST_WARNING_OBJECT (alsa,
@@ -780,6 +882,8 @@ gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
   cptr = length / alsa->bytes_per_sample;
   ptr = data;
 
+  if(alsa->is_live && alsa->handle_pause) g_cond_wait(alsa->pause_cond, alsa->pause_lock);
+
   GST_ALSA_SRC_LOCK (asrc);
   while (cptr > 0) {
     if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) {
old mode 100644 (file)
new mode 100755 (executable)
index d0fcbf0..6a92bae
@@ -69,10 +69,15 @@ struct _GstAlsaSrc {
   guint                 period_time;
   snd_pcm_uframes_t     buffer_size;
   snd_pcm_uframes_t     period_size;
+  gboolean              is_live;
+  guint                 flush_src_id;
 
   GstAlsaMixer          *mixer;
 
   GMutex                *alsa_lock;
+  gboolean              handle_pause;
+  GCond                 *pause_cond;
+  GMutex                *pause_lock;
 };
 
 struct _GstAlsaSrcClass {
index ac01b05..102e16d 100644 (file)
@@ -796,7 +796,7 @@ gst_ogg_demux_collect_sync_time (GstOggDemux * ogg, GstOggChain * chain)
 
 /* submit a packet to the oggpad, this function will run the
  * typefind code for the pad if this is the first packet for this
- * stream 
+ * stream
  */
 static GstFlowReturn
 gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
@@ -1049,7 +1049,7 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
   return ret;
 }
 
-/* flush at most @npackets from the stream layer. All packets if 
+/* flush at most @npackets from the stream layer. All packets if
  * @npackets is 0;
  */
 static GstFlowReturn
@@ -2337,7 +2337,7 @@ boundary_reached:
 }
 
 /* from the current offset, find the previous page, seeking backwards
- * until we find the page. 
+ * until we find the page.
  */
 static GstFlowReturn
 gst_ogg_demux_get_prev_page (GstOggDemux * ogg, ogg_page * og, gint64 * offset)
@@ -2440,7 +2440,7 @@ gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg)
     pad->added = FALSE;
   }
 
-  /* if we cannot seek back to the chain, we can destroy the chain 
+  /* if we cannot seek back to the chain, we can destroy the chain
    * completely */
   if (!ogg->pullmode) {
     gst_ogg_chain_free (chain);
@@ -2617,7 +2617,7 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
 static gboolean
 do_binary_search (GstOggDemux * ogg, GstOggChain * chain, gint64 begin,
     gint64 end, gint64 begintime, gint64 endtime, gint64 target,
-    gint64 * offset)
+    gint64 * offset, gboolean only_serial_no, gint serialno)
 {
   gint64 best;
   GstFlowReturn ret;
@@ -2691,6 +2691,11 @@ do_binary_search (GstOggDemux * ogg, GstOggChain * chain, gint64 begin,
           continue;
         }
 
+        /* Avoid seeking to an incorrect granuletime by only considering
+           the stream for which we found the earliest time */
+        if (only_serial_no && ogg_page_serialno (&og) != serialno)
+          continue;
+
         /* get the stream */
         pad = gst_ogg_chain_get_stream (chain, ogg_page_serialno (&og));
         if (pad == NULL || pad->map.is_skeleton)
@@ -2808,8 +2813,8 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
   gint64 total;
   gint64 result = 0;
   GstFlowReturn ret;
-  gint i, pending, len;
-  gboolean first_parsed_page = TRUE;
+  gint i, pending;
+  gint serialno = 0;
 
   position = segment->last_stop;
 
@@ -2833,14 +2838,14 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
   target = position - total + begintime;
 
   if (!do_binary_search (ogg, chain, begin, end, begintime, endtime, target,
-          &best))
+          &best, FALSE, 0))
     goto seek_error;
 
   /* second step: find pages for all streams, we use the keyframe_granule to keep
    * track of which ones we saw. If we have seen a page for each stream we can
    * calculate the positions of each keyframe. */
   GST_DEBUG_OBJECT (ogg, "find keyframes");
-  len = pending = chain->streams->len;
+  pending = chain->streams->len;
 
   /* figure out where the keyframes are */
   keytarget = target;
@@ -2874,32 +2879,6 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
       continue;
     }
 
-    /* we only do this the first time we pass here */
-    if (first_parsed_page) {
-      /* Now that we have a time reference from the page, we can check
-       * whether all streams still have pages from here on.
-       *
-       * This would be more elegant before the loop, but getting the page from
-       * there without breaking anything would be more costly */
-      granule_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map,
-          granulepos);
-      for (i = 0; i < len; i++) {
-        GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i);
-
-        if (stream == pad)
-          /* we already know we have at least one page (the current one)
-           * for this stream */
-          continue;
-
-        if (granule_time > stream->map.total_time)
-          /* we won't encounter any more pages of this stream, so we don't
-           * try finding a key frame for it */
-          pending--;
-      }
-      first_parsed_page = FALSE;
-    }
-
-
     /* in reverse we want to go past the page with the lower timestamp */
     if (segment->rate < 0.0) {
       /* get time for this pad */
@@ -2934,8 +2913,10 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
     /* collect smallest value */
     if (keyframe_time != -1) {
       keyframe_time += begintime;
-      if (keyframe_time < keytarget)
+      if (keyframe_time < keytarget) {
+        serialno = pad->map.serialno;
         keytarget = keyframe_time;
+      }
     }
 
   next:
@@ -2954,7 +2935,7 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
 
     /* last step, seek to the location of the keyframe */
     if (!do_binary_search (ogg, chain, begin, end, begintime, endtime,
-            keytarget, &best))
+            keytarget, &best, TRUE, serialno))
       goto seek_error;
   } else {
     /* seek back to previous position */
@@ -3208,7 +3189,7 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event)
 
     ogg->segment_running = TRUE;
     ogg->seqnum = seqnum;
-    /* restart our task since it might have been stopped when we did the 
+    /* restart our task since it might have been stopped when we did the
      * flush. */
     gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
         ogg->sinkpad);
@@ -3245,8 +3226,12 @@ gst_ogg_demux_get_duration_push (GstOggDemux * ogg, int flags)
      granpos there, but it's fairly likely */
   position =
       ogg->push_byte_length - DURATION_CHUNK_OFFSET - EOS_AVOIDANCE_THRESHOLD;
-  if (position < 0)
-    position = 0;
+  if (position < 0) {
+    if (ogg->push_byte_length > EOS_AVOIDANCE_THRESHOLD)
+      position = ogg->push_byte_length - (EOS_AVOIDANCE_THRESHOLD / 2);
+   else
+      position = 0;
+  }
 
   GST_DEBUG_OBJECT (ogg,
       "Getting duration, seeking near the end, to %" G_GINT64_FORMAT, position);
@@ -3578,9 +3563,9 @@ done:
 }
 
 /* read a chain from the ogg file. This code will
- * read all BOS pages and will create and return a GstOggChain 
- * structure with the results. 
- * 
+ * read all BOS pages and will create and return a GstOggChain
+ * structure with the results.
+ *
  * This function will also read N pages from each stream in the
  * chain and submit them to the decoders. When the decoder has
  * decoded the first buffer, we know the timestamp of the first
index 3b267fa..5fa0eb9 100644 (file)
@@ -797,7 +797,7 @@ setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet)
 static gboolean
 is_header_vorbis (GstOggStream * pad, ogg_packet * packet)
 {
-  if (packet->bytes > 0 && (packet->packet[0] & 0x01) == 0)
+  if (packet->bytes == 0 || (packet->packet[0] & 0x01) == 0)
     return FALSE;
 
   if (packet->packet[0] == 5) {
old mode 100644 (file)
new mode 100755 (executable)
index 24686b9..58039d1
@@ -234,6 +234,7 @@ static gboolean gst_app_src_query (GstBaseSrc * src, GstQuery * query);
 
 static GstFlowReturn gst_app_src_push_buffer_action (GstAppSrc * appsrc,
     GstBuffer * buffer);
+static gboolean gst_app_src_send_event (GstElement * element, GstEvent * event);
 
 static guint gst_app_src_signals[LAST_SIGNAL] = { 0 };
 
@@ -272,12 +273,14 @@ gst_app_src_class_init (GstAppSrcClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
   GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass;
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);;
 
   gobject_class->dispose = gst_app_src_dispose;
   gobject_class->finalize = gst_app_src_finalize;
 
   gobject_class->set_property = gst_app_src_set_property;
   gobject_class->get_property = gst_app_src_get_property;
+  gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_app_src_send_event);
 
   /**
    * GstAppSrc::caps
@@ -1637,6 +1640,47 @@ gst_app_src_set_callbacks (GstAppSrc * appsrc,
   GST_OBJECT_UNLOCK (appsrc);
 }
 
+static gboolean
+gst_app_src_send_event (GstElement * element, GstEvent * event)
+{
+  GstAppSrc *appsrc;
+  gboolean result = FALSE;
+  GstBaseSrc *src;
+
+  src = GST_BASE_SRC (element);
+  appsrc = GST_APP_SRC (element);
+  GstAppSrcPrivate *priv = appsrc->priv;
+
+  GST_DEBUG_OBJECT (appsrc, "handling event %p %" GST_PTR_FORMAT, event, event);
+
+  switch (GST_EVENT_TYPE (event)) {
+      /* bidirectional events */
+    case GST_EVENT_FLUSH_STOP:
+      g_mutex_lock (priv->mutex);
+      GST_INFO_OBJECT (appsrc, "flushing internal queue");
+      gst_app_src_flush_queued (appsrc);
+      priv->flushing = FALSE;
+      g_mutex_unlock (priv->mutex);
+      result = gst_pad_push_event (src ->srcpad, event);
+      break;
+      /* fallback */
+    case GST_EVENT_FLUSH_START:
+      g_mutex_lock (priv->mutex);
+      priv->flushing = TRUE;
+      g_mutex_unlock (priv->mutex);
+      result = gst_pad_push_event (src ->srcpad, event);
+      break;
+    case GST_EVENT_NEWSEGMENT:
+      result = gst_pad_push_event (src ->srcpad, event);
+      break;
+    default:
+      result = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
+      break;
+  }
+
+  return result;
+}
+
 /*** GSTURIHANDLER INTERFACE *************************************************/
 
 static GstURIType
index e35779e..e258d44 100644 (file)
@@ -220,6 +220,9 @@ struct _GstAudioDecoderPrivate
   GstAdapter *adapter;
   /* tracking input ts for changes */
   GstClockTime prev_ts;
+#if 1
+  guint64 prev_distance;
+#endif
   /* frames obtained from input */
   GQueue frames;
   /* collected output data */
@@ -444,6 +447,9 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full)
   dec->priv->out_ts = GST_CLOCK_TIME_NONE;
   dec->priv->out_dur = 0;
   dec->priv->prev_ts = GST_CLOCK_TIME_NONE;
+#if 1
+  dec->priv->prev_distance = 0;
+#endif
   dec->priv->drained = TRUE;
   dec->priv->base_ts = GST_CLOCK_TIME_NONE;
   dec->priv->samples = 0;
@@ -976,6 +982,7 @@ gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
     if (G_LIKELY (av)) {
       gint len;
       GstClockTime ts;
+      guint64 distance;
 
       /* parse if needed */
       if (klass->parse) {
@@ -1015,6 +1022,7 @@ gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
         len = av;
       }
       /* track upstream ts, but do not get stuck if nothing new upstream */
+#if 0
       ts = gst_adapter_prev_timestamp (priv->adapter, NULL);
       if (ts == priv->prev_ts) {
         GST_LOG_OBJECT (dec, "ts == prev_ts; discarding");
@@ -1022,6 +1030,16 @@ gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
       } else {
         priv->prev_ts = ts;
       }
+#else
+      ts = gst_adapter_prev_timestamp (priv->adapter, &distance);
+      if (ts != priv->prev_ts || distance <= priv->prev_distance) {
+        priv->prev_ts = ts;
+        priv->prev_distance = distance;
+      } else {
+        GST_LOG_OBJECT (dec, "ts == prev_ts; discarding");
+        ts = GST_CLOCK_TIME_NONE;
+      }
+#endif
       buffer = gst_adapter_take_buffer (priv->adapter, len);
       buffer = gst_buffer_make_metadata_writable (buffer);
       GST_BUFFER_TIMESTAMP (buffer) = ts;
old mode 100644 (file)
new mode 100755 (executable)
index e7ff30d..0dd84c9
@@ -1438,7 +1438,8 @@ gst_base_audio_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj)
   }
 
   /* start ringbuffer so we can start slaving right away when we need to */
-  gst_ring_buffer_start (sink->ringbuffer);
+  if (sink->priv->slave_method != GST_BASE_AUDIO_SINK_SLAVE_NONE)
+    gst_ring_buffer_start (sink->ringbuffer);
 
   GST_DEBUG_OBJECT (sink,
       "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT,
index 5069304..385d7b7 100644 (file)
@@ -329,7 +329,7 @@ gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
   /* we have to differentiate between int and float formats */
   mimetype = gst_structure_get_name (structure);
 
-  if (g_str_equal (mimetype, "audio/x-raw-int")) {
+  if (g_str_equal (mimetype, "audio/x-raw-int") || g_str_equal (mimetype, "audio/x-lpcm")) {
     gint endianness;
     const FormatDef *def;
     gint j, bytes;
index 73ba697..60d77a8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GStreamer Camera Control Interface
  *
- * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd.
  *
  * Contact: Jeongmo Yang <jm80.yang@samsung.com>
  *
@@ -132,8 +132,13 @@ static void gst_camera_control_class_init(GstCameraControlClass *klass)
        klass->get_part_color = NULL;
        klass->get_exif_info = NULL;
        klass->set_capture_command = NULL;
+        klass->set_record_command = NULL;
        klass->start_face_zoom = NULL;
        klass->stop_face_zoom = NULL;
+       klass->set_ae_lock = NULL;
+       klass->get_ae_lock = NULL;
+       klass->set_awb_lock = NULL;
+       klass->get_awb_lock = NULL;
 }
 
 const GList* gst_camera_control_list_channels(GstCameraControl *control)
@@ -148,23 +153,23 @@ const GList* gst_camera_control_list_channels(GstCameraControl *control)
 }
 
 
-gboolean gst_camera_control_set_value(GstCameraControl *control, GstCameraControlChannel *control_channel)
+gboolean gst_camera_control_set_value(GstCameraControl *control, GstCameraControlChannel *control_channel, gint value)
 {
        GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
 
        if (klass->set_value) {
-               return klass->set_value(control, control_channel);
+               return klass->set_value(control, control_channel, value);
        }
 
        return FALSE;
 }
 
-gboolean gst_camera_control_get_value(GstCameraControl *control, GstCameraControlChannel *control_channel)
+gboolean gst_camera_control_get_value(GstCameraControl *control, GstCameraControlChannel *control_channel, gint *value)
 {
        GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
 
        if (klass->get_value) {
-               return klass->get_value(control, control_channel);
+               return klass->get_value(control, control_channel, value);
        }
 
        return FALSE;
@@ -493,6 +498,16 @@ void gst_camera_control_set_capture_command(GstCameraControl *control, GstCamera
 
        return;
 }
+void gst_camera_control_set_record_command(GstCameraControl *control, GstCameraControlRecordCommand cmd)
+{
+        GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
+
+        if (klass->set_record_command) {
+                klass->set_record_command(control, cmd);
+        }
+
+        return;
+}
 
 gboolean gst_camera_control_start_face_zoom(GstCameraControl *control, gint x, gint y, gint zoom_level)
 {
@@ -516,6 +531,50 @@ gboolean gst_camera_control_stop_face_zoom(GstCameraControl *control)
        return FALSE;
 }
 
+gboolean gst_camera_control_set_ae_lock(GstCameraControl *control, gboolean lock)
+{
+       GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
+
+       if (klass->set_ae_lock) {
+               return klass->set_ae_lock(control, lock);
+       }
+
+       return FALSE;
+}
+
+gboolean gst_camera_control_get_ae_lock(GstCameraControl *control, gboolean *lock)
+{
+       GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
+
+       if (klass->get_ae_lock) {
+               return klass->get_ae_lock(control, lock);
+       }
+
+       return FALSE;
+}
+
+gboolean gst_camera_control_set_awb_lock(GstCameraControl *control, gboolean lock)
+{
+       GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
+
+       if (klass->set_awb_lock) {
+               return klass->set_awb_lock(control, lock);
+       }
+
+       return FALSE;
+}
+
+gboolean gst_camera_control_get_awb_lock(GstCameraControl *control, gboolean *lock)
+{
+       GstCameraControlClass *klass = GST_CAMERA_CONTROL_GET_CLASS(control);
+
+       if (klass->get_awb_lock) {
+               return klass->get_awb_lock(control, lock);
+       }
+
+       return FALSE;
+}
+
 void gst_camera_control_value_changed(GstCameraControl *control, GstCameraControlChannel *control_channel, gint value)
 {
        g_signal_emit(G_OBJECT(control), gst_camera_control_signals[CONTROL_VALUE_CHANGED], 0, control_channel, value);
index f5ec544..d4780c4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GStreamer Camera Control Interface
  *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd.
  *
  * Contact: Jeongmo Yang <jm80.yang@samsung.com>
  *
@@ -154,7 +154,15 @@ typedef enum
        GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP_MULTISHOT,
 } GstCameraControlCaptureCommand;
 
-
+/**
+ * Enumerations for Camera record command.
+ */
+typedef enum
+{
+        GST_CAMERA_CONTROL_RECORD_COMMAND_NONE,
+        GST_CAMERA_CONTROL_RECORD_COMMAND_START,
+        GST_CAMERA_CONTROL_RECORD_COMMAND_STOP,
+} GstCameraControlRecordCommand;
 
 /////////////////////////////////
 //  For Query functionalities  //
@@ -356,6 +364,7 @@ typedef struct _GstCameraControlExifInfo {
        gint exif_image_height;
        gint exposure_bias_in_APEX;         /* Exposure bias in APEX standard */
        gint software_used;                 /* Firmware S/W version */
+       unsigned char *p_embedded_data;     /* Pointer for embedded data */
 
        /* Fixed value */
        gint component_configuration;       /* color components arrangement */
@@ -376,8 +385,8 @@ typedef struct _GstCameraControlClass {
        /* virtual functions */
        const GList*(*list_channels)                   (GstCameraControl *control);
 
-       gboolean        (*set_value)                   (GstCameraControl *control, GstCameraControlChannel *control_channel);
-       gboolean        (*get_value)                   (GstCameraControl *control, GstCameraControlChannel *control_channel);
+       gboolean        (*set_value)                   (GstCameraControl *control, GstCameraControlChannel *control_channel, gint value);
+       gboolean        (*get_value)                   (GstCameraControl *control, GstCameraControlChannel *control_channel, gint *value);
        gboolean        (*set_exposure)                (GstCameraControl *control, gint type, gint value1, gint value2);
        gboolean        (*get_exposure)                (GstCameraControl *control, gint type, gint *value1, gint *value2);
        gboolean        (*set_capture_mode)            (GstCameraControl *control, gint type, gint value);
@@ -407,8 +416,13 @@ typedef struct _GstCameraControlClass {
        gboolean        (*get_misc_dev_info)           (GstCameraControl *control, gint dev_id, GstCameraControlCtrlListInfoType *info);
        gboolean        (*get_extra_dev_info)          (GstCameraControl *control, gint dev_id, GstCameraControlExtraInfoType *info);
        void            (*set_capture_command)         (GstCameraControl *control, GstCameraControlCaptureCommand cmd);
+       void            (*set_record_command)          (GstCameraControl *control, GstCameraControlRecordCommand cmd);
        gboolean        (*start_face_zoom)             (GstCameraControl *control, gint x, gint y, gint zoom_level);
        gboolean        (*stop_face_zoom)              (GstCameraControl *control);
+       gboolean        (*set_ae_lock)                 (GstCameraControl *control, gboolean lock);
+       gboolean        (*get_ae_lock)                 (GstCameraControl *control, gboolean *lock);
+       gboolean        (*set_awb_lock)                (GstCameraControl *control, gboolean lock);
+       gboolean        (*get_awb_lock)                (GstCameraControl *control, gboolean *lock);
 
        /* signals */
        void (* value_changed)                          (GstCameraControl *control, GstCameraControlChannel *channel, gint value);
@@ -419,8 +433,8 @@ GType gst_camera_control_get_type(void);
 /* virtual class function wrappers */
 const GList*   gst_camera_control_list_channels        (GstCameraControl *control);
 
-gboolean       gst_camera_control_set_value            (GstCameraControl *control, GstCameraControlChannel *control_channel);
-gboolean       gst_camera_control_get_value            (GstCameraControl *control, GstCameraControlChannel *control_channel);
+gboolean       gst_camera_control_set_value            (GstCameraControl *control, GstCameraControlChannel *control_channel, gint value);
+gboolean       gst_camera_control_get_value            (GstCameraControl *control, GstCameraControlChannel *control_channel, gint *value);
 gboolean       gst_camera_control_set_exposure         (GstCameraControl *control, gint type, gint value1, gint value2);
 gboolean       gst_camera_control_get_exposure         (GstCameraControl *control, gint type, gint *value1, gint *value2);
 gboolean       gst_camera_control_set_capture_mode     (GstCameraControl *control, gint type, gint value);
@@ -450,8 +464,13 @@ gboolean   gst_camera_control_get_basic_dev_info   (GstCameraControl *control, gin
 gboolean       gst_camera_control_get_misc_dev_info    (GstCameraControl *control, gint dev_id, GstCameraControlCtrlListInfoType *info);
 gboolean       gst_camera_control_get_extra_dev_info   (GstCameraControl *control, gint dev_id, GstCameraControlExtraInfoType *info);
 void           gst_camera_control_set_capture_command  (GstCameraControl *control, GstCameraControlCaptureCommand cmd);
+void            gst_camera_control_set_record_command   (GstCameraControl *control, GstCameraControlRecordCommand cmd);
 gboolean       gst_camera_control_start_face_zoom      (GstCameraControl *control, gint x, gint y, gint zoom_level);
 gboolean       gst_camera_control_stop_face_zoom       (GstCameraControl *control);
+gboolean       gst_camera_control_set_ae_lock          (GstCameraControl *control, gboolean lock);
+gboolean       gst_camera_control_get_ae_lock          (GstCameraControl *control, gboolean *lock);
+gboolean       gst_camera_control_set_awb_lock         (GstCameraControl *control, gboolean lock);
+gboolean       gst_camera_control_get_awb_lock         (GstCameraControl *control, gboolean *lock);
 
 
 /* trigger signal */
index 415210e..86c7ce9 100644 (file)
@@ -1,5 +1,8 @@
 /* GStreamer Camera Control Channel Interface
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
  *
  * cameracontrolchannel.c: cameracontrol channel object design
  *
index 417debd..d8a2979 100644 (file)
@@ -1,5 +1,8 @@
 /* GStreamer Camera Control Channel Interface
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
  *
  * cameracontrolchannel.h: individual channel object
  *
old mode 100644 (file)
new mode 100755 (executable)
index bc7ac84..a862e94
@@ -60,7 +60,7 @@ gst_riff_create_video_caps (guint32 codec_fcc,
 
   switch (codec_fcc) {
     case GST_MAKE_FOURCC ('D', 'I', 'B', ' '): /* uncompressed RGB */
-    case GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00):
+    //case GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00):   /*Commented so that FOURCC 0000 doesn't get detected as RGB format. ALso no standard for FOURCC 0000 */
     case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
     case GST_MAKE_FOURCC ('R', 'A', 'W', ' '):
     {
@@ -1396,7 +1396,12 @@ gst_riff_create_audio_caps (guint16 codec_id,
     {
       gint version = (codec_id - GST_RIFF_WAVE_FORMAT_WMAV1) + 1;
 
-      channels_max = 6;
+      /*Since gstreamer already knows GST_RIFF_WAVE_FORMAT_WMAV3_L (WMA lossless media) as version 3.*/
+      if(codec_id == GST_RIFF_WAVE_FORMAT_WMAV3_L)
+        version = (codec_id - GST_RIFF_WAVE_FORMAT_WMAV1);
+
+      /* WMA Pro supports upto 8 channels */
+      channels_max = 8;
       block_align = TRUE;
 
       caps = gst_caps_new_simple ("audio/x-wma",
old mode 100644 (file)
new mode 100755 (executable)
index 731add3..bf721d5
@@ -1409,9 +1409,9 @@ message_to_string (GstRTSPConnection * conn, GstRTSPMessage * message)
     case GST_RTSP_MESSAGE_REQUEST:
       /* create request string, add CSeq */
       g_string_append_printf (str, "%s %s RTSP/1.0\r\n"
-          "CSeq: %d\r\n",
-          gst_rtsp_method_as_text (message->type_data.request.method),
-          message->type_data.request.uri, conn->cseq++);
+      "CSeq: %d\r\n",
+      gst_rtsp_method_as_text (message->type_data.request.method),
+      message->type_data.request.uri, conn->cseq++);
       /* add session id if we have one */
       if (conn->session_id[0] != '\0') {
         gst_rtsp_message_remove_header (message, GST_RTSP_HDR_SESSION, -1);
@@ -1443,8 +1443,19 @@ message_to_string (GstRTSPConnection * conn, GstRTSPMessage * message)
       break;
     case GST_RTSP_MESSAGE_DATA:
     {
-      guint8 data_header[4];
+#ifdef SAMSUNG_WFD_SPEC
+      /* This change is made because WFD Sink does not understand the first 2
+      * bytes i.e (magic number and channel) of TCP Interleaved data. This
+      * is done specifically to support WFD Sink's limitation */
 
+      guint8 data_header[2];
+      data_header[0] = (message->body_size >> 8) & 0xff;
+      data_header[1] = message->body_size & 0xff;
+
+      /* create string with header and data */
+      str = g_string_append_len (str, (gchar *) data_header, 2);
+#else
+      guint8 data_header[4];
       /* prepare data header */
       data_header[0] = '$';
       data_header[1] = message->type_data.data.channel;
@@ -1453,6 +1464,7 @@ message_to_string (GstRTSPConnection * conn, GstRTSPMessage * message)
 
       /* create string with header and data */
       str = g_string_append_len (str, (gchar *) data_header, 4);
+#endif
       str =
           g_string_append_len (str, (gchar *) message->body,
           message->body_size);
old mode 100644 (file)
new mode 100755 (executable)
index 3727bf2..32bc3ee
@@ -81,6 +81,7 @@ G_STMT_START { \
  * @GST_RTSP_ETIMEOUT: a timeout occured
  * @GST_RTSP_ETGET: the tunnel GET request has been performed
  * @GST_RTSP_ETPOST: the tunnel POST request has been performed
+ * @GST_RTSP_ENOHDCPKEY: HDCP key was not installed
  * @GST_RTSP_ELAST: last error
  *
  * Result codes from the RTSP functions.
@@ -104,8 +105,8 @@ typedef enum {
   GST_RTSP_ETIMEOUT    = -14,
   GST_RTSP_ETGET       = -15,
   GST_RTSP_ETPOST      = -16,
-
-  GST_RTSP_ELAST       = -17
+  GST_RTSP_ENOHDCPKEY  = -17,
+  GST_RTSP_ELAST       = -18
 } GstRTSPResult;
 
 /**
index ab834a5..8f2e862 100644 (file)
@@ -568,16 +568,11 @@ gst_rtsp_transport_as_text (GstRTSPTransport * transport)
     goto invalid_transport;
   g_ptr_array_add (strs, g_ascii_strup (tmp, -1));
 
-  if (transport->trans != GST_RTSP_TRANS_RTP ||
-      transport->profile != GST_RTSP_PROFILE_AVP ||
-      transport->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
-    g_ptr_array_add (strs, g_strdup ("/"));
-
-    if ((tmp = rtsp_transport_ltrans_as_text (transport)) == NULL)
-      goto invalid_transport;
-
-    g_ptr_array_add (strs, g_ascii_strup (tmp, -1));
-  }
+  g_printf("\n %d transport->lower_transport=%d \n", __LINE__, transport->lower_transport);
+  g_ptr_array_add (strs, g_strdup ("/"));
+  if ((tmp = rtsp_transport_ltrans_as_text (transport)) == NULL)
+    goto invalid_transport;
+  g_ptr_array_add (strs, g_ascii_strup (tmp, -1));
 
   /*
    * the order of the following parameters is the same as the one specified in
index 1fb7f39..5a51f62 100644 (file)
@@ -173,8 +173,11 @@ xmp_tag_type_get_name (GstXmpTagType tagtype)
     case GstXmpTagTypeBag:
       return "rdf:Bag";
     default:
-      g_assert_not_reached ();
+      break;
   }
+
+  /* Make compiler happy */
+  g_return_val_if_reached ("");
 }
 
 struct _PendingXmpTag
index f22ff4c..2ad5612 100644 (file)
@@ -877,6 +877,20 @@ gst_video_format_from_fourcc (guint32 fourcc)
       return GST_VIDEO_FORMAT_IYU1;
     case GST_MAKE_FOURCC ('A', 'Y', '6', '4'):
       return GST_VIDEO_FORMAT_AYUV64;
+#ifdef GST_EXT_XV_ENHANCEMENT
+    case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
+      return GST_VIDEO_FORMAT_ST12;
+    case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
+      return GST_VIDEO_FORMAT_SN12;
+    case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
+      return GST_VIDEO_FORMAT_SUYV;
+    case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
+      return GST_VIDEO_FORMAT_SUY2;
+    case GST_MAKE_FOURCC ('S', '4', '2', '0'):
+      return GST_VIDEO_FORMAT_S420;
+    case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
+      return GST_VIDEO_FORMAT_SYVY;
+#endif
     default:
       return GST_VIDEO_FORMAT_UNKNOWN;
   }
@@ -944,6 +958,20 @@ gst_video_format_to_fourcc (GstVideoFormat format)
       return GST_MAKE_FOURCC ('I', 'Y', 'U', '1');
     case GST_VIDEO_FORMAT_AYUV64:
       return GST_MAKE_FOURCC ('A', 'Y', '6', '4');
+#ifdef GST_EXT_XV_ENHANCEMENT
+    case GST_VIDEO_FORMAT_ST12:
+      return GST_MAKE_FOURCC ('S', 'T', '1', '2');
+    case GST_VIDEO_FORMAT_SN12:
+      return GST_MAKE_FOURCC ('S', 'N', '1', '2');
+    case GST_VIDEO_FORMAT_SUYV:
+      return GST_MAKE_FOURCC ('S', 'U', 'Y', 'V');
+    case GST_VIDEO_FORMAT_SUY2:
+      return GST_MAKE_FOURCC ('S', 'U', 'Y', '2');
+    case GST_VIDEO_FORMAT_S420:
+      return GST_MAKE_FOURCC ('S', '4', '2', '0');
+    case GST_VIDEO_FORMAT_SYVY:
+      return GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y');
+#endif
     default:
       return 0;
   }
old mode 100644 (file)
new mode 100755 (executable)
index 36750e9..f45cc75
@@ -33,7 +33,7 @@ G_BEGIN_DECLS
  * @GST_VIDEO_FORMAT_I420: planar 4:2:0 YUV
  * @GST_VIDEO_FORMAT_YV12: planar 4:2:0 YVU (like I420 but UV planes swapped)
  * @GST_VIDEO_FORMAT_YUY2: packed 4:2:2 YUV (Y0-U0-Y1-V0 Y2-U2-Y3-V2 Y4 ...)
- * @GST_VIDEO_FORMAT_UYVY: packed 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...) 
+ * @GST_VIDEO_FORMAT_UYVY: packed 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...)
  * @GST_VIDEO_FORMAT_AYUV: packed 4:4:4 YUV with alpha channel (A0-Y0-U0-V0 ...)
  * @GST_VIDEO_FORMAT_RGBx: sparse rgb packed into 32 bit, space last
  * @GST_VIDEO_FORMAT_BGRx: sparse reverse rgb packed into 32 bit, space last
@@ -119,6 +119,14 @@ typedef enum {
   GST_VIDEO_FORMAT_ARGB64,
   GST_VIDEO_FORMAT_AYUV64,
   GST_VIDEO_FORMAT_r210
+#ifdef GST_EXT_XV_ENHANCEMENT
+, GST_VIDEO_FORMAT_ST12,
+  GST_VIDEO_FORMAT_SN12,
+  GST_VIDEO_FORMAT_SUYV,
+  GST_VIDEO_FORMAT_SUY2,
+  GST_VIDEO_FORMAT_S420,
+  GST_VIDEO_FORMAT_SYVY
+#endif
 } GstVideoFormat;
 
 #define GST_VIDEO_BYTE1_MASK_32  "0xFF000000"
@@ -264,13 +272,13 @@ typedef enum {
 
 #define GST_VIDEO_CAPS_RGBx \
     __GST_VIDEO_CAPS_MAKE_32 (1, 2, 3)
-  
+
 #define GST_VIDEO_CAPS_xRGB \
     __GST_VIDEO_CAPS_MAKE_32 (2, 3, 4)
-  
+
 #define GST_VIDEO_CAPS_BGRx \
     __GST_VIDEO_CAPS_MAKE_32 (3, 2, 1)
-  
+
 #define GST_VIDEO_CAPS_xBGR \
     __GST_VIDEO_CAPS_MAKE_32 (4, 3, 2)
 
@@ -278,13 +286,13 @@ typedef enum {
 
 #define GST_VIDEO_CAPS_RGBA \
     __GST_VIDEO_CAPS_MAKE_32A (1, 2, 3, 4)
-  
+
 #define GST_VIDEO_CAPS_ARGB \
     __GST_VIDEO_CAPS_MAKE_32A (2, 3, 4, 1)
-  
+
 #define GST_VIDEO_CAPS_BGRA \
     __GST_VIDEO_CAPS_MAKE_32A (3, 2, 1, 4)
-  
+
 #define GST_VIDEO_CAPS_ABGR \
     __GST_VIDEO_CAPS_MAKE_32A (4, 3, 2, 1)
 
@@ -300,9 +308,9 @@ typedef enum {
   #define GST_VIDEO_CAPS_BGRx_HOST_ENDIAN \
       GST_VIDEO_CAPS_xRGB
 #endif
-      
+
 /* 15/16 bit */
-  
+
 #define GST_VIDEO_CAPS_RGB_16 \
     __GST_VIDEO_CAPS_MAKE_16 (1, 2, 3)
 
@@ -342,9 +350,9 @@ typedef enum {
  */
 #define GST_VIDEO_CAPS_RGB8_PALETTED \
   "video/x-raw-rgb, bpp = (int)8, depth = (int)8, "                     \
-      "width = "GST_VIDEO_SIZE_RANGE" , "                              \
+      "width = " GST_VIDEO_SIZE_RANGE ", "                             \
       "height = " GST_VIDEO_SIZE_RANGE ", "                             \
-      "framerate = "GST_VIDEO_FPS_RANGE
+      "framerate = " GST_VIDEO_FPS_RANGE
 
 /**
  * GST_VIDEO_CAPS_YUV:
diff --git a/gst-plugins-base-tools.manifest b/gst-plugins-base-tools.manifest
new file mode 100755 (executable)
index 0000000..fa9a0cf
--- /dev/null
@@ -0,0 +1,8 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+       <assign>
+               <filesystem path="/usr/bin/gst-discoverer-0.10" label="_" exec_label="none" />
+       </assign>
+</manifest>
diff --git a/gst-plugins-base.manifest b/gst-plugins-base.manifest
new file mode 100755 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
index 717cf10..818c895 100644 (file)
@@ -119,6 +119,13 @@ GST_BOILERPLATE_FULL (GstAudioConvert, gst_audio_convert, GstBaseTransform,
 
 #define STATIC_CAPS \
 GST_STATIC_CAPS ( \
+  "audio/x-lpcm, " \
+    "rate = (int) [ 1, MAX ], " \
+    "channels = (int) [ 1, 2 ], " \
+    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
+    "width = (int) [1,32], " \
+    "depth = (int) [ 1, 32 ], " \
+    "signed = (boolean) { true, false }; " \
   "audio/x-raw-float, " \
     "rate = (int) [ 1, MAX ], " \
     "channels = (int) [ 1, MAX ], " \
@@ -306,7 +313,8 @@ gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt)
 
   fmt->endianness = G_BYTE_ORDER;
   fmt->is_int =
-      (strcmp (gst_structure_get_name (structure), "audio/x-raw-int") == 0);
+      (strcmp (gst_structure_get_name (structure), "audio/x-raw-int") == 0) ||
+      (strcmp (gst_structure_get_name (structure), "audio/x-lpcm") == 0);
 
   /* parse common fields */
   if (!gst_structure_get_int (structure, "channels", &fmt->channels))
index a161a65..a27087d 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
  * This file:
  * Copyright (c) 2002-2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -17,6 +18,9 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * * Modifications by Samsung Electronics Co., Ltd.
+ * 1. Support samsung extension format
  */
 
 #ifdef HAVE_CONFIG_H
@@ -630,6 +634,7 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps,
           break;
         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
         case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
+        case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
           context->pix_fmt = PIX_FMT_UYVY422;
           break;
         case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
index 7b1c18f..0ee1d46 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
  * This file:
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -17,6 +18,9 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * * Modifications by Samsung Electronics Co., Ltd.
+ * 1. Support samsung extension format
  */
 
 /**
@@ -47,7 +51,7 @@ GST_DEBUG_CATEGORY (ffmpegcolorspace_performance);
 #define FFMPEGCSP_VIDEO_CAPS                                           \
   "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , "                 \
   "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE","     \
-  "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV , A420 , SUYV , SYVY , S420 } ;" \
+  "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV , A420 , SUYV , SYVY , S420 , ITLV } ;" \
   GST_VIDEO_CAPS_RGB";"                                                        \
   GST_VIDEO_CAPS_BGR";"                                                        \
   GST_VIDEO_CAPS_RGBx";"                                               \
old mode 100644 (file)
new mode 100755 (executable)
index 8bcadde..55a092f
@@ -405,6 +405,7 @@ struct _GstDecodeChain
 
   GstPad *pad;                  /* srcpad that caused creation of this chain */
 
+  gboolean drained;             /* TRUE if the all children are drained */
   gboolean demuxer;             /* TRUE if elements->data is a demuxer */
   gboolean seekable;            /* TRUE if this chain ends on a demuxer and is seekable */
   GList *elements;              /* All elements in this group, first
@@ -2266,6 +2267,14 @@ type_found (GstElement * typefind, guint probability,
     goto exit;
   }
 
+#ifdef GST_EXT_DECODEBIN2_QUEUESIZE
+  if (gst_structure_has_name (gst_caps_get_structure (caps, 0), "application/x-hls") ||
+     gst_structure_has_name (gst_caps_get_structure (caps, 0), "application/x-ss")) {
+    GST_DEBUG_OBJECT (decode_bin, "decodebin2 got hls/ss caps.. set queue max-size-time to 1 sec");
+    decode_bin->max_size_time = 1 * GST_SECOND;
+  }
+#endif
+
   /* FIXME: we can only deal with one type, we don't yet support dynamically changing
    * caps from the typefind element */
   if (decode_bin->have_type || decode_bin->decode_chain)
@@ -2915,6 +2924,9 @@ gst_decode_group_new (GstDecodeBin * dbin, GstDecodeChain * parent)
   GstDecodeGroup *group = g_slice_new0 (GstDecodeGroup);
   GstElement *mq;
   gboolean seekable;
+#ifdef GST_EXT_DECODEBIN2_MODIFICATION
+  gboolean smooth_stream_demuxer_last = FALSE;
+#endif
 
   GST_DEBUG_OBJECT (dbin, "Creating new group %p with parent chain %p", group,
       parent);
@@ -2926,8 +2938,25 @@ gst_decode_group_new (GstDecodeBin * dbin, GstDecodeChain * parent)
   if (G_UNLIKELY (!group->multiqueue))
     goto missing_multiqueue;
 
+#ifdef GST_EXT_DECODEBIN2_MODIFICATION
+  /*Check if last parent elment is smooth streaming demuxer.*/
+  if (parent && parent->demuxer)
+  {
+    GstElement *element =
+        ((GstDecodeElement *) parent->elements->data)->element;
+    if(g_strrstr(GST_ELEMENT_NAME(element), "dashdemux"))
+      smooth_stream_demuxer_last = TRUE;
+  }
+
+  /* default is for use-buffering is FALSE
+    We should disable buffering in multiqueue after smooth streaming
+    demuxers like dashdemux because they are fake demuxers.*/
+  if (dbin->use_buffering && !smooth_stream_demuxer_last)
+#else
   /* default is for use-buffering is FALSE */
-  if (dbin->use_buffering) {
+  if (dbin->use_buffering)
+#endif
+  {
     g_object_set (mq,
         "use-buffering", TRUE,
         "low-percent", dbin->low_percent,
@@ -3120,7 +3149,6 @@ drain_and_switch_group (GstDecodeGroup * group, GstDecodePad * drainpad,
     gboolean * last_group, gboolean * drained, gboolean * switched)
 {
   gboolean handled = FALSE;
-  gboolean alldrained = TRUE;
   GList *tmp;
 
   GST_DEBUG ("Checking group %p (target pad %s:%s)",
@@ -3133,6 +3161,7 @@ drain_and_switch_group (GstDecodeGroup * group, GstDecodePad * drainpad,
 
   /* Figure out if all our chains are drained with the
    * new information */
+  group->drained = TRUE;
   for (tmp = group->children; tmp; tmp = tmp->next) {
     GstDecodeChain *chain = (GstDecodeChain *) tmp->data;
     gboolean subdrained = FALSE;
@@ -3141,13 +3170,13 @@ drain_and_switch_group (GstDecodeGroup * group, GstDecodePad * drainpad,
         drain_and_switch_chains (chain, drainpad, last_group, &subdrained,
         switched);
     if (!subdrained)
-      alldrained = FALSE;
+      group->drained = FALSE;
   }
 
 beach:
   GST_DEBUG ("group %p (last_group:%d, drained:%d, switched:%d, handled:%d)",
-      group, *last_group, alldrained, *switched, handled);
-  *drained = alldrained;
+      group, *last_group, group->drained, *switched, handled);
+  *drained = group->drained;
   return handled;
 }
 
@@ -3163,6 +3192,11 @@ drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
 
   CHAIN_MUTEX_LOCK (chain);
 
+  /* Definitely can't be in drained chains */
+  if (G_UNLIKELY (chain->drained)) {
+    goto beach;
+  }
+  
   if (chain->endpad) {
     /* Check if we're reached the target endchain */
     if (chain == drainpad->chain) {
@@ -3171,7 +3205,7 @@ drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
       handled = TRUE;
     }
 
-    *drained = chain->endpad->drained;
+    chain->drained = chain->endpad->drained;
     goto beach;
   }
 
@@ -3199,11 +3233,11 @@ drain_and_switch_chains (GstDecodeChain * chain, GstDecodePad * drainpad,
         chain->next_groups =
             g_list_delete_link (chain->next_groups, chain->next_groups);
         *switched = TRUE;
-        *drained = FALSE;
+        chain->drained = FALSE;
       } else {
         GST_DEBUG ("Group %p was the last in chain %p", chain->active_group,
             chain);
-        *drained = TRUE;
+        chain->drained = TRUE; 
         /* We're drained ! */
       }
     }
@@ -3213,7 +3247,9 @@ beach:
   CHAIN_MUTEX_UNLOCK (chain);
 
   GST_DEBUG ("Chain %p (handled:%d, last_group:%d, drained:%d, switched:%d)",
-      chain, handled, *last_group, *drained, *switched);
+      chain, handled, *last_group, chain->drained, *switched);
+
+  *drained = chain->drained;
 
   if (*drained)
     g_signal_emit (dbin, gst_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
old mode 100644 (file)
new mode 100755 (executable)
index b6e62d3..1f0f9c1
@@ -1276,7 +1276,7 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
   GstBin *bin;
   GstPad *pad;
   GstElement *head = NULL, *prev = NULL, *elem = NULL;
-  GstPlugin *p;
+  GstPlugin *p = NULL;
 
   chain = g_new0 (GstPlayVideoChain, 1);
   chain->chain.playsink = playsink;
@@ -1336,6 +1336,7 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
   gst_object_ref_sink (bin);
   gst_bin_add (bin, chain->sink);
 
+#ifndef GST_EXT_XV_ENHANCEMENT
   /* decouple decoder from sink, this improves playback quite a lot since the
    * decoder can continue while the sink blocks for synchronisation. We don't
    * need a lot of buffers as this consumes a lot of memory and we don't want
@@ -1354,6 +1355,7 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
     gst_bin_add (bin, chain->queue);
     head = prev = chain->queue;
   }
+#endif
 
   if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) {
     GST_DEBUG_OBJECT (playsink, "creating videoconverter");
index 4a33bd4..d8e4617 100644 (file)
@@ -24,6 +24,12 @@ libgstsubparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstsubparse_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
 libgstsubparse_la_LIBTOOLFLAGS = --tag=disable-static
 
+if USE_XML
+libgstsubparse_la_CFLAGS += $(XML_CFLAGS)
+libgstsubparse_la_LIBADD += $(XML_LIBS)
+endif
+
+
 noinst_HEADERS = \
        gstssaparse.h \
        gstsubparse.h \
old mode 100644 (file)
new mode 100755 (executable)
index 9c31b54..5d1d242
 #include "mpl2parse.h"
 #include "qttextparse.h"
 
+#ifdef GST_EXT_ENABLE_SMI
+#ifdef GST_DISABLE_XML
+#undef GST_DISABLE_XML
+#endif
+#endif
+
 GST_DEBUG_CATEGORY (sub_parse_debug);
 
-#define DEFAULT_ENCODING   NULL
+#define DEFAULT_ENCODING           NULL
+#ifdef SUBPARSE_MODIFICATION
+#define DEFAULT_CURRENT_LANGUAGE   NULL
+#endif
 
 enum
 {
   PROP_0,
   PROP_ENCODING,
-  PROP_VIDEOFPS
+  PROP_VIDEOFPS,
+#ifdef SUBPARSE_MODIFICATION
+  PROP_EXTSUB_CURRENT_LANGUAGE
+#endif
 };
 
 static void
@@ -172,7 +184,12 @@ gst_sub_parse_dispose (GObject * object)
     g_string_free (subparse->textbuf, TRUE);
     subparse->textbuf = NULL;
   }
-
+#ifdef SUBPARSE_MODIFICATION
+  if (subparse->state.current_language) {
+    g_free (subparse->state.current_language);
+    subparse->state.current_language = NULL;
+  }
+#endif
   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
 }
 
@@ -205,6 +222,13 @@ gst_sub_parse_class_init (GstSubParseClass * klass)
           "and the subtitle format requires it subtitles may be out of sync.",
           0, 1, G_MAXINT, 1, 24000, 1001,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#ifdef SUBPARSE_MODIFICATION
+  g_object_class_install_property (object_class, PROP_EXTSUB_CURRENT_LANGUAGE,
+      g_param_spec_string ("current-language", "Current language",
+            "Current language of the subtitle in external subtitle case.",
+            DEFAULT_CURRENT_LANGUAGE,
+            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
 }
 
 static void
@@ -227,6 +251,7 @@ gst_sub_parse_init (GstSubParse * subparse)
   subparse->textbuf = g_string_new (NULL);
   subparse->parser_type = GST_SUB_PARSE_FORMAT_UNKNOWN;
   subparse->flushing = FALSE;
+  subparse->discont_sent = FALSE;
   gst_segment_init (&subparse->segment, GST_FORMAT_TIME);
   subparse->need_segment = TRUE;
   subparse->encoding = g_strdup (DEFAULT_ENCODING);
@@ -319,24 +344,23 @@ gst_sub_parse_src_event (GstPad * pad, GstEvent * event)
         goto beach;
       }
 
+      /* Apply the seek to our segment */
+      gst_segment_set_seek (&self->segment, rate, format, self->segment_flags,
+          start_type, start, stop_type, stop, &update);
+
+      GST_DEBUG_OBJECT (self, "segment after seek: %" GST_SEGMENT_FORMAT,
+          &self->segment);
+
+      self->next_offset = 0;
+      self->need_segment = TRUE;
+
       /* Convert that seek to a seeking in bytes at position 0,
          FIXME: could use an index */
       ret = gst_pad_push_event (self->sinkpad,
           gst_event_new_seek (rate, GST_FORMAT_BYTES, self->segment_flags,
               GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, 0));
 
-      if (ret) {
-        /* Apply the seek to our segment */
-        gst_segment_set_seek (&self->segment, rate, format, self->segment_flags,
-            start_type, start, stop_type, stop, &update);
-
-        GST_DEBUG_OBJECT (self, "segment after seek: %" GST_SEGMENT_FORMAT,
-            &self->segment);
-
-        self->next_offset = 0;
-
-        self->need_segment = TRUE;
-      } else {
+      if (!ret) {
         GST_WARNING_OBJECT (self, "seek to 0 bytes failed");
       }
 
@@ -381,6 +405,16 @@ gst_sub_parse_set_property (GObject * object, guint prop_id,
       }
       break;
     }
+#ifdef SUBPARSE_MODIFICATION
+    case PROP_EXTSUB_CURRENT_LANGUAGE:
+      subparse->state.current_language = g_value_dup_string (value);
+      subparse->state.msl_language = g_value_dup_string (value);
+      GST_LOG_OBJECT (subparse, "subtitle current language set to %s",
+      GST_STR_NULL (subparse->state.current_language));
+      GST_LOG_OBJECT (subparse, "subtitle msl language set to %s",
+      GST_STR_NULL (subparse->state.msl_language));
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -402,6 +436,12 @@ gst_sub_parse_get_property (GObject * object, guint prop_id,
     case PROP_VIDEOFPS:
       gst_value_set_fraction (value, subparse->fps_n, subparse->fps_d);
       break;
+#ifdef SUBPARSE_MODIFICATION
+    case PROP_EXTSUB_CURRENT_LANGUAGE:
+      g_value_set_string (value, subparse->state.current_language);
+      GST_LOG("************getting property to %s*********************",subparse->state.current_language);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -508,6 +548,10 @@ convert_encoding (GstSubParse * self, const gchar * str, gsize len,
     g_free (self->detected_encoding);
     self->detected_encoding = NULL;
     g_error_free (err);
+#ifdef SUBPARSE_MODIFICATION
+    /* You must ensure an error is NULL before it's set */
+    err = NULL;
+#endif
   }
 
   /* Otherwise check if it's UTF8 */
@@ -540,9 +584,22 @@ convert_encoding (GstSubParse * self, const gchar * str, gsize len,
     GST_WARNING_OBJECT (self, "could not convert string from '%s' to UTF-8: %s",
         encoding, err->message);
     g_error_free (err);
-
+#ifdef SUBPARSE_MODIFICATION
+    /* You must ensure an error is NULL before it's set */
+    err = NULL;
+    if(!strcmp(self->encoding,"EUC-KR"))
+     {
+        GST_WARNING("failback case is occure with EUC-KR,so going with CP949 ");
+        g_free(self->encoding);
+        self->encoding = g_strdup("CP949");
+        ret = gst_convert_to_utf8 (str, len, encoding, consumed, &err);
+      } else {
+#endif
     /* invalid input encoding, fall back to ISO-8859-15 (always succeeds) */
-    ret = gst_convert_to_utf8 (str, len, "ISO-8859-15", consumed, NULL);
+        ret = gst_convert_to_utf8 (str, len, "ISO-8859-15", consumed, NULL);
+#ifdef SUBPARSE_MODIFICATION
+      }
+#endif
   }
 
   GST_LOG_OBJECT (self,
@@ -1197,6 +1254,11 @@ parser_state_init (ParserState * state)
   state->max_duration = 0;      /* no limit */
   state->state = 0;
   state->segment = NULL;
+#ifdef SUBPARSE_MODIFICATION
+  state->language_list = NULL;
+  state->current_language = NULL;
+  state->langlist_msg_posted = FALSE;
+#endif
 }
 
 static void
@@ -1383,6 +1445,8 @@ gst_sub_parse_format_autodetect (GstSubParse * self)
     case GST_SUB_PARSE_FORMAT_SAMI:
       self->parse_line = parse_sami;
       sami_context_init (&self->state);
+      GST_LOG("************setting property to %s*********************", self->state.current_language);
+      sami_context_change_language (&self->state);
       return gst_caps_new_simple ("text/x-pango-markup", NULL);
 #endif
     case GST_SUB_PARSE_FORMAT_TMPLAYER:
@@ -1443,14 +1507,13 @@ feed_textbuf (GstSubParse * self, GstBuffer * buf)
 
   self->offset = GST_BUFFER_OFFSET (buf) + GST_BUFFER_SIZE (buf);
   self->next_offset = self->offset;
-
+  GST_INFO("Pushing in the adapter");
   gst_adapter_push (self->adapter, buf);
 
   input =
       convert_encoding (self, (const gchar *) gst_adapter_peek (self->adapter,
           gst_adapter_available (self->adapter)),
       (gsize) gst_adapter_available (self->adapter), &consumed);
-
   if (input && consumed > 0) {
     self->textbuf = g_string_append (self->textbuf, input);
     gst_adapter_flush (self->adapter, consumed);
@@ -1459,13 +1522,65 @@ feed_textbuf (GstSubParse * self, GstBuffer * buf)
   g_free (input);
 }
 
+#ifdef SUBPARSE_MODIFICATION
+static gchar*
+get_next_sami_sync_line (gchar * line, guint* offset)
+{
+  const char *line_end = NULL;
+  gchar* sync_line = NULL;
+  int have_r = 0;
+
+  line_end = strstr (line, "<SYNC");
+
+  if (!line_end ) {
+    /* <SYNC not found, or there is only one sync in this line return offset as 0 */
+    sync_line = (gchar*)g_malloc ((strlen(line)) + 1);
+    strcpy (sync_line, line);
+    *(sync_line + strlen(line)) = '\0';
+    *offset = 0;
+    return sync_line;
+  }
+
+  if (line_end == line)
+  {
+    const gchar* tempptr = line_end;
+    line_end += strlen("<SYNC");
+    line_end = strstr (line_end, "<SYNC");
+    if (!line_end ) {
+      /* <SYNC not found, or there is only one sync in this line return offset as 0 */
+      line_end = tempptr;
+      sync_line = g_strdup(line_end);
+      *offset = 0;
+      return sync_line;
+    }
+  }
+
+  /* get rid of '\r' */
+  if (line_end != line && *(line_end - 1) == '\r') {
+    line_end--;
+    have_r = 1;
+  }
+
+  *offset = line_end - line;
+
+  sync_line = g_strndup (line, *offset);
+
+  return sync_line;
+}
+#endif
+
 static GstFlowReturn
 handle_buffer (GstSubParse * self, GstBuffer * buf)
 {
   GstFlowReturn ret = GST_FLOW_OK;
   GstCaps *caps = NULL;
   gchar *line, *subtitle;
-
+#ifdef SUBPARSE_MODIFICATION
+  GstMessage *m = NULL;
+  guint counter = 0;
+#endif
+  gboolean discont = FALSE;
+  gboolean discont_after = FALSE;
   if (self->first_buffer) {
     self->detected_encoding =
         detect_encoding ((gchar *) GST_BUFFER_DATA (buf),
@@ -1474,7 +1589,17 @@ handle_buffer (GstSubParse * self, GstBuffer * buf)
     self->state.fps_n = self->fps_n;
     self->state.fps_d = self->fps_d;
   }
-
+  if (!strcmp ((const char*)GST_BUFFER_DATA (buf), "eos")){
+    GST_DEBUG_OBJECT(self,"eos buffer is recieved");
+      if (GST_BUFFER_FLAG_IS_SET(buf,GST_BUFFER_FLAG_GAP)) {
+      GST_DEBUG_OBJECT(self,"eos buffer with flag is recieved recieved");
+      ret = gst_pad_push (self->srcpad, buf);
+      return ret;
+    }
+  }
+  discont = GST_BUFFER_IS_DISCONT (buf);
+  if(discont)
+    self->discont_sent = FALSE;
   feed_textbuf (self, buf);
 
   /* make sure we know the format */
@@ -1501,9 +1626,161 @@ handle_buffer (GstSubParse * self, GstBuffer * buf)
 
   while (!self->flushing && (line = get_next_line (self))) {
     guint offset = 0;
-
+#ifdef SUBPARSE_MODIFICATION
+    guint suboffset = 0;
+    gchar* sync_line = NULL;
+#endif
     /* Set segment on our parser state machine */
     self->state.segment = &self->segment;
+#ifdef SUBPARSE_MODIFICATION
+    if (self->parser_type == GST_SUB_PARSE_FORMAT_SAMI) {
+      do {
+        /* Now parse the line, out of segment lines will just return NULL */
+        sync_line = get_next_sami_sync_line(line + offset, &suboffset);
+        offset += suboffset;
+        GST_LOG_OBJECT (self, "Parsing line '%s'", sync_line);
+        subtitle = self->parse_line (&self->state, sync_line);
+        g_free (sync_line);
+        sync_line = NULL;
+
+        if (!self->state.langlist_msg_posted && self->state.language_list) {
+          if(self->state.language_list) {
+            m = gst_message_new_element (GST_OBJECT_CAST (self), gst_structure_new("Ext_Sub_Language_List",
+                                       "lang_list", G_TYPE_POINTER, self->state.language_list, NULL));
+
+            gst_element_post_message (GST_ELEMENT_CAST (self), m);
+            self->state.langlist_msg_posted = TRUE;
+          }
+          GST_DEBUG_OBJECT (self, "LANGLIST POSTED with current language as : %s ",self->state.current_language);
+        }
+        GST_DEBUG_OBJECT (self, "parse_line returned %x", subtitle);
+
+        if (subtitle) {
+          guint subtitle_len = strlen (subtitle);
+
+          /* +1 for terminating NUL character */
+          ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
+          GST_BUFFER_OFFSET_NONE, subtitle_len + 1,
+          GST_PAD_CAPS (self->srcpad), &buf);
+
+          if (ret == GST_FLOW_OK) {
+            /* copy terminating NUL character as well */
+            memcpy (GST_BUFFER_DATA (buf), subtitle, subtitle_len + 1);
+            GST_BUFFER_SIZE (buf) = subtitle_len;
+            GST_BUFFER_TIMESTAMP (buf) = self->state.start_time;
+            GST_BUFFER_DURATION (buf) = self->state.duration;
+            if (discont && !counter) {
+               GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+               GST_DEBUG("setting the true for discont flag and self is %p with ts is %" GST_TIME_FORMAT "\n",self,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
+               self->discont_sent = TRUE;
+               counter++;
+             } else if (!self->discont_sent && !counter) {
+               GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+               GST_DEBUG("setting the true for discont flag and self is %p with ts is %" GST_TIME_FORMAT "\n",self,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
+               self->discont_sent = TRUE;
+               counter++;
+             }
+
+            /* in some cases (e.g. tmplayer) we can only determine the duration
+             * of a text chunk from the timestamp of the next text chunk; in those
+             * cases, we probably want to limit the duration to something
+             * reasonable, so we don't end up showing some text for e.g. 40 seconds
+             * just because nothing else is being said during that time */
+            if (self->state.max_duration > 0 && GST_BUFFER_DURATION_IS_VALID (buf)) {
+              if (GST_BUFFER_DURATION (buf) > self->state.max_duration)
+                GST_BUFFER_DURATION (buf) = self->state.max_duration;
+            }
+
+            gst_segment_set_last_stop (&self->segment, GST_FORMAT_TIME, self->state.start_time);
+
+            GST_DEBUG_OBJECT (self, "Sending text '%s', %" GST_TIME_FORMAT " + %"
+                    GST_TIME_FORMAT, subtitle, GST_TIME_ARGS (self->state.start_time),
+                    GST_TIME_ARGS (self->state.duration));
+
+            ret = gst_pad_push (self->srcpad, buf);
+          }
+
+          /* move this forward (the tmplayer parser needs this) */
+          if (self->state.duration != GST_CLOCK_TIME_NONE)
+            self->state.start_time += self->state.duration;
+
+          g_free (subtitle);
+          subtitle = NULL;
+        }
+      } while (suboffset);
+      g_free (line);
+      line = NULL;
+    }
+
+    else {
+      /* Now parse the line, out of segment lines will just return NULL */
+      GST_LOG_OBJECT (self, "Parsing line '%s'", line + offset);
+      subtitle = self->parse_line (&self->state, line + offset);
+      g_free (line);
+
+      GST_DEBUG_OBJECT (self, "parse_line returned %x", subtitle);
+
+      if (subtitle) {
+        guint subtitle_len = strlen (subtitle);
+
+        /* +1 for terminating NUL character */
+        ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
+                  GST_BUFFER_OFFSET_NONE, subtitle_len + 1,
+                  GST_PAD_CAPS (self->srcpad), &buf);
+
+        if (ret == GST_FLOW_OK) {
+          /* copy terminating NUL character as well */
+          memcpy (GST_BUFFER_DATA (buf), subtitle, subtitle_len + 1);
+          GST_BUFFER_SIZE (buf) = subtitle_len;
+          GST_BUFFER_TIMESTAMP (buf) = self->state.start_time;
+          GST_BUFFER_DURATION (buf) = self->state.duration;
+
+          /* in some cases (e.g. tmplayer) we can only determine the duration
+           * of a text chunk from the timestamp of the next text chunk; in those
+           * cases, we probably want to limit the duration to something
+           * reasonable, so we don't end up showing some text for e.g. 40 seconds
+           * just because nothing else is being said during that time */
+          if (self->state.max_duration > 0 && GST_BUFFER_DURATION_IS_VALID (buf)) {
+            if (GST_BUFFER_DURATION (buf) > self->state.max_duration)
+              GST_BUFFER_DURATION (buf) = self->state.max_duration;
+          }
+
+          gst_segment_set_last_stop (&self->segment, GST_FORMAT_TIME,
+              self->state.start_time);
+
+          GST_DEBUG_OBJECT (self, "Sending text '%s', %" GST_TIME_FORMAT " + %"
+              GST_TIME_FORMAT, subtitle, GST_TIME_ARGS (self->state.start_time),
+              GST_TIME_ARGS (self->state.duration));
+          if (discont && !counter) {
+             GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+             GST_DEBUG("setting the true for discont flag and self is %p with ts is %" GST_TIME_FORMAT "\n",self,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
+             self->discont_sent = TRUE;
+             counter++;
+           } else if (!self->discont_sent && !counter) {
+             GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+             GST_DEBUG("setting the true for discont flag and self is %p with ts is %" GST_TIME_FORMAT "\n",self,GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
+             self->discont_sent = TRUE;
+             counter++;
+           }
+          GST_DEBUG_OBJECT (self, "Sent buffer with TS %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)));
+
+          ret = gst_pad_push (self->srcpad, buf);
+        }
+
+        /* move this forward (the tmplayer parser needs this) */
+        if (self->state.duration != GST_CLOCK_TIME_NONE)
+          self->state.start_time += self->state.duration;
+
+        g_free (subtitle);
+        subtitle = NULL;
+      }
+    }
+
+    if (ret != GST_FLOW_OK) {
+      GST_DEBUG_OBJECT (self, "flow: %s", gst_flow_get_name (ret));
+      break;
+    }
+#else
     /* Now parse the line, out of segment lines will just return NULL */
     GST_LOG_OBJECT (self, "Parsing line '%s'", line + offset);
     subtitle = self->parse_line (&self->state, line + offset);
@@ -1556,6 +1833,7 @@ handle_buffer (GstSubParse * self, GstBuffer * buf)
         break;
       }
     }
+#endif
   }
 
   return ret;
@@ -1576,7 +1854,7 @@ gst_sub_parse_chain (GstPad * sinkpad, GstBuffer * buf)
 
     gst_pad_push_event (self->srcpad, gst_event_new_new_segment (FALSE,
             self->segment.rate, self->segment.format,
-            self->segment.last_stop, self->segment.stop, self->segment.time));
+            self->segment.start, self->segment.stop, self->segment.time));
     self->need_segment = FALSE;
   }
 
@@ -1625,7 +1903,7 @@ gst_sub_parse_sink_event (GstPad * pad, GstEvent * event)
           &stop, &time);
 
       GST_DEBUG_OBJECT (self, "newsegment (%s)", gst_format_get_name (format));
-
+      self->need_segment = TRUE;
       if (format == GST_FORMAT_TIME) {
         gst_segment_set_newsegment (&self->segment, update, rate, format,
             start, stop, time);
old mode 100644 (file)
new mode 100755 (executable)
index 5731d91..4132e1c
@@ -24,6 +24,8 @@
 #include <gst/gst.h>
 #include <gst/base/gstadapter.h>
 
+#define SUBPARSE_MODIFICATION
+
 GST_DEBUG_CATEGORY_EXTERN (sub_parse_debug);
 #define GST_CAT_DEFAULT sub_parse_debug
 
@@ -68,6 +70,12 @@ typedef struct {
   gpointer user_data;
   gboolean have_internal_fps; /* If TRUE don't overwrite fps by property */
   gint fps_n, fps_d;     /* used by frame based parsers */
+#ifdef SUBPARSE_MODIFICATION
+  GList* language_list;
+  gchar* current_language;
+  gchar *msl_language;
+  gboolean langlist_msg_posted;
+#endif
 } ParserState;
 
 typedef gchar* (*Parser) (ParserState *state, const gchar *line);
@@ -99,6 +107,7 @@ struct _GstSubParse {
   gboolean      need_segment;
   
   gboolean flushing;
+  gboolean discont_sent;
   gboolean valid_utf8;
   gchar   *detected_encoding;
   gchar   *encoding;
@@ -106,7 +115,7 @@ struct _GstSubParse {
   gboolean first_buffer;
 
   /* used by frame based parsers */
-  gint fps_n, fps_d;          
+  gint fps_n, fps_d;
 };
 
 struct _GstSubParseClass {
old mode 100644 (file)
new mode 100755 (executable)
index 135748a..01205fb
@@ -1,5 +1,5 @@
 /* GStreamer SAMI subtitle parser
- * Copyright (c) 2006 Young-Ho Cha <ganadist at chollian net>
+ * Copyright (c) 2006, 2013 Young-Ho Cha <ganadist at gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
+#define _GNU_SOURCE
 #include "samiparse.h"
 
-#include <libxml/HTMLparser.h>
+#include <glib.h>
 #include <string.h>
+#include <stdlib.h>
 
 #define ITALIC_TAG 'i'
 #define SPAN_TAG   's'
 #define RT_TAG     't'
 #define CLEAR_TAG  '0'
 
+typedef struct _HtmlParser HtmlParser;
+typedef struct _HtmlContext HtmlContext;
 typedef struct _GstSamiContext GstSamiContext;
-
+#ifdef SUBPARSE_MODIFICATION
+typedef struct _LanguageStruct  GstLangStruct;
+struct _LanguageStruct
+{
+    gchar *language_code;
+    gchar *language_key;
+};
+#define MAX_LANGUAGE 10
+#endif
 struct _GstSamiContext
 {
   GString *buf;                 /* buffer to collect content */
@@ -43,14 +55,634 @@ struct _GstSamiContext
                                  * that tags can be closed properly on
                                  * 'sync' tags. See _context_push_state()
                                  * and _context_pop_state(). */
-  htmlParserCtxtPtr htmlctxt;   /* html parser context */
+  HtmlContext *htmlctxt;        /* html parser context */
   gboolean has_result;          /* set when ready to push out result */
   gboolean in_sync;             /* flag to avoid appending anything except the
                                  * content of the sync elements to buf */
   guint64 time1;                /* previous start attribute in sync tag */
   guint64 time2;                /* current start attribute in sync tag  */
+#ifdef SUBPARSE_MODIFICATION
+  guint64 time3;                /* To store the last current time when language is changed */
+  GList *lang_list;             /* Language list for an external subtitle file */
+  gchar *current_language;      /* Current language parsed */
+  gchar *desired_language;      /* Language set by user */
+  gboolean language_changed;    /* language changed signal */
+  gboolean end_body;            /* </BODY> reached */
+#endif
+};
+
+struct _HtmlParser
+{
+  void (*start_element) (HtmlContext * ctx,
+      const gchar * name, const gchar ** attr, gpointer user_data);
+  void (*end_element) (HtmlContext * ctx,
+      const gchar * name, gpointer user_data);
+  void (*text) (HtmlContext * ctx,
+      const gchar * text, gsize text_len, gpointer user_data);
+};
+
+struct _HtmlContext
+{
+  const HtmlParser *parser;
+  gpointer user_data;
+  GString *buf;
+};
+
+static HtmlContext *
+html_context_new (HtmlParser * parser, gpointer user_data)
+{
+  HtmlContext *ctxt = (HtmlContext *) g_new0 (HtmlContext, 1);
+  ctxt->parser = parser;
+  ctxt->user_data = user_data;
+  ctxt->buf = g_string_new (NULL);
+  return ctxt;
+}
+
+static void
+html_context_free (HtmlContext * ctxt)
+{
+  g_string_free (ctxt->buf, TRUE);
+  g_free (ctxt);
+}
+
+struct EntityMap
+{
+  const gunichar unescaped;
+  const gchar *escaped;
+};
+
+struct EntityMap XmlEntities[] = {
+  {34, "quot;"},
+  {38, "amp;"},
+  {39, "apos;"},
+  {60, "lt;"},
+  {62, "gt;"},
+  {0, NULL},
 };
 
+struct EntityMap HtmlEntities[] = {
+/* nbsp will handle manually
+{ 160, "nbsp;" }, */
+  {161, "iexcl;"},
+  {162, "cent;"},
+  {163, "pound;"},
+  {164, "curren;"},
+  {165, "yen;"},
+  {166, "brvbar;"},
+  {167, "sect;"},
+  {168, "uml;"},
+  {169, "copy;"},
+  {170, "ordf;"},
+  {171, "laquo;"},
+  {172, "not;"},
+  {173, "shy;"},
+  {174, "reg;"},
+  {175, "macr;"},
+  {176, "deg;"},
+  {177, "plusmn;"},
+  {178, "sup2;"},
+  {179, "sup3;"},
+  {180, "acute;"},
+  {181, "micro;"},
+  {182, "para;"},
+  {183, "middot;"},
+  {184, "cedil;"},
+  {185, "sup1;"},
+  {186, "ordm;"},
+  {187, "raquo;"},
+  {188, "frac14;"},
+  {189, "frac12;"},
+  {190, "frac34;"},
+  {191, "iquest;"},
+  {192, "Agrave;"},
+  {193, "Aacute;"},
+  {194, "Acirc;"},
+  {195, "Atilde;"},
+  {196, "Auml;"},
+  {197, "Aring;"},
+  {198, "AElig;"},
+  {199, "Ccedil;"},
+  {200, "Egrave;"},
+  {201, "Eacute;"},
+  {202, "Ecirc;"},
+  {203, "Euml;"},
+  {204, "Igrave;"},
+  {205, "Iacute;"},
+  {206, "Icirc;"},
+  {207, "Iuml;"},
+  {208, "ETH;"},
+  {209, "Ntilde;"},
+  {210, "Ograve;"},
+  {211, "Oacute;"},
+  {212, "Ocirc;"},
+  {213, "Otilde;"},
+  {214, "Ouml;"},
+  {215, "times;"},
+  {216, "Oslash;"},
+  {217, "Ugrave;"},
+  {218, "Uacute;"},
+  {219, "Ucirc;"},
+  {220, "Uuml;"},
+  {221, "Yacute;"},
+  {222, "THORN;"},
+  {223, "szlig;"},
+  {224, "agrave;"},
+  {225, "aacute;"},
+  {226, "acirc;"},
+  {227, "atilde;"},
+  {228, "auml;"},
+  {229, "aring;"},
+  {230, "aelig;"},
+  {231, "ccedil;"},
+  {232, "egrave;"},
+  {233, "eacute;"},
+  {234, "ecirc;"},
+  {235, "euml;"},
+  {236, "igrave;"},
+  {237, "iacute;"},
+  {238, "icirc;"},
+  {239, "iuml;"},
+  {240, "eth;"},
+  {241, "ntilde;"},
+  {242, "ograve;"},
+  {243, "oacute;"},
+  {244, "ocirc;"},
+  {245, "otilde;"},
+  {246, "ouml;"},
+  {247, "divide;"},
+  {248, "oslash;"},
+  {249, "ugrave;"},
+  {250, "uacute;"},
+  {251, "ucirc;"},
+  {252, "uuml;"},
+  {253, "yacute;"},
+  {254, "thorn;"},
+  {255, "yuml;"},
+  {338, "OElig;"},
+  {339, "oelig;"},
+  {352, "Scaron;"},
+  {353, "scaron;"},
+  {376, "Yuml;"},
+  {402, "fnof;"},
+  {710, "circ;"},
+  {732, "tilde;"},
+  {913, "Alpha;"},
+  {914, "Beta;"},
+  {915, "Gamma;"},
+  {916, "Delta;"},
+  {917, "Epsilon;"},
+  {918, "Zeta;"},
+  {919, "Eta;"},
+  {920, "Theta;"},
+  {921, "Iota;"},
+  {922, "Kappa;"},
+  {923, "Lambda;"},
+  {924, "Mu;"},
+  {925, "Nu;"},
+  {926, "Xi;"},
+  {927, "Omicron;"},
+  {928, "Pi;"},
+  {929, "Rho;"},
+  {931, "Sigma;"},
+  {932, "Tau;"},
+  {933, "Upsilon;"},
+  {934, "Phi;"},
+  {935, "Chi;"},
+  {936, "Psi;"},
+  {937, "Omega;"},
+  {945, "alpha;"},
+  {946, "beta;"},
+  {947, "gamma;"},
+  {948, "delta;"},
+  {949, "epsilon;"},
+  {950, "zeta;"},
+  {951, "eta;"},
+  {952, "theta;"},
+  {953, "iota;"},
+  {954, "kappa;"},
+  {955, "lambda;"},
+  {956, "mu;"},
+  {957, "nu;"},
+  {958, "xi;"},
+  {959, "omicron;"},
+  {960, "pi;"},
+  {961, "rho;"},
+  {962, "sigmaf;"},
+  {963, "sigma;"},
+  {964, "tau;"},
+  {965, "upsilon;"},
+  {966, "phi;"},
+  {967, "chi;"},
+  {968, "psi;"},
+  {969, "omega;"},
+  {977, "thetasym;"},
+  {978, "upsih;"},
+  {982, "piv;"},
+  {8194, "ensp;"},
+  {8195, "emsp;"},
+  {8201, "thinsp;"},
+  {8204, "zwnj;"},
+  {8205, "zwj;"},
+  {8206, "lrm;"},
+  {8207, "rlm;"},
+  {8211, "ndash;"},
+  {8212, "mdash;"},
+  {8216, "lsquo;"},
+  {8217, "rsquo;"},
+  {8218, "sbquo;"},
+  {8220, "ldquo;"},
+  {8221, "rdquo;"},
+  {8222, "bdquo;"},
+  {8224, "dagger;"},
+  {8225, "Dagger;"},
+  {8226, "bull;"},
+  {8230, "hellip;"},
+  {8240, "permil;"},
+  {8242, "prime;"},
+  {8243, "Prime;"},
+  {8249, "lsaquo;"},
+  {8250, "rsaquo;"},
+  {8254, "oline;"},
+  {8260, "frasl;"},
+  {8364, "euro;"},
+  {8465, "image;"},
+  {8472, "weierp;"},
+  {8476, "real;"},
+  {8482, "trade;"},
+  {8501, "alefsym;"},
+  {8592, "larr;"},
+  {8593, "uarr;"},
+  {8594, "rarr;"},
+  {8595, "darr;"},
+  {8596, "harr;"},
+  {8629, "crarr;"},
+  {8656, "lArr;"},
+  {8657, "uArr;"},
+  {8658, "rArr;"},
+  {8659, "dArr;"},
+  {8660, "hArr;"},
+  {8704, "forall;"},
+  {8706, "part;"},
+  {8707, "exist;"},
+  {8709, "empty;"},
+  {8711, "nabla;"},
+  {8712, "isin;"},
+  {8713, "notin;"},
+  {8715, "ni;"},
+  {8719, "prod;"},
+  {8721, "sum;"},
+  {8722, "minus;"},
+  {8727, "lowast;"},
+  {8730, "radic;"},
+  {8733, "prop;"},
+  {8734, "infin;"},
+  {8736, "ang;"},
+  {8743, "and;"},
+  {8744, "or;"},
+  {8745, "cap;"},
+  {8746, "cup;"},
+  {8747, "int;"},
+  {8756, "there4;"},
+  {8764, "sim;"},
+  {8773, "cong;"},
+  {8776, "asymp;"},
+  {8800, "ne;"},
+  {8801, "equiv;"},
+  {8804, "le;"},
+  {8805, "ge;"},
+  {8834, "sub;"},
+  {8835, "sup;"},
+  {8836, "nsub;"},
+  {8838, "sube;"},
+  {8839, "supe;"},
+  {8853, "oplus;"},
+  {8855, "otimes;"},
+  {8869, "perp;"},
+  {8901, "sdot;"},
+  {8968, "lceil;"},
+  {8969, "rceil;"},
+  {8970, "lfloor;"},
+  {8971, "rfloor;"},
+  {9001, "lang;"},
+  {9002, "rang;"},
+  {9674, "loz;"},
+  {9824, "spades;"},
+  {9827, "clubs;"},
+  {9829, "hearts;"},
+  {9830, "diams;"},
+  {0, NULL},
+};
+
+static gchar *
+unescape_string (const gchar * text)
+{
+  gint i;
+  GString *unescaped = g_string_new (NULL);
+
+  while (*text) {
+    if (*text == '&') {
+      text++;
+
+      /* unescape &nbsp and &nbsp; */
+      if (!g_ascii_strncasecmp (text, "nbsp", 4)) {
+        unescaped = g_string_append_unichar (unescaped, 160);
+        text += 4;
+        if (*text == ';') {
+          text++;
+        }
+        goto next;
+      }
+
+      /* pass xml entities. these will be processed as pango markup */
+      for (i = 0; XmlEntities[i].escaped; i++) {
+        gssize len = strlen (XmlEntities[i].escaped);
+        if (!g_ascii_strncasecmp (text, XmlEntities[i].escaped, len)) {
+          unescaped = g_string_append_c (unescaped, '&');
+          unescaped =
+              g_string_append_len (unescaped, XmlEntities[i].escaped, len);
+          text += len;
+          goto next;
+        }
+      }
+
+      /* convert html entities */
+      for (i = 0; HtmlEntities[i].escaped; i++) {
+        gssize len = strlen (HtmlEntities[i].escaped);
+        if (!strncmp (text, HtmlEntities[i].escaped, len)) {
+          unescaped =
+              g_string_append_unichar (unescaped, HtmlEntities[i].unescaped);
+          text += len;
+          goto next;
+        }
+      }
+
+      if (*text == '#') {
+        gboolean is_hex = FALSE;
+        gunichar l;
+        gchar *end = NULL;
+
+        text++;
+        if (*text == 'x') {
+          is_hex = TRUE;
+          text++;
+        }
+        errno = 0;
+        if (is_hex) {
+          l = strtoul (text, &end, 16);
+        } else {
+          l = strtoul (text, &end, 10);
+        }
+
+        if (text == end || errno != 0) {
+          /* error occured. pass it */
+          goto next;
+        }
+        unescaped = g_string_append_unichar (unescaped, l);
+        text = end;
+
+        if (*text == ';') {
+          text++;
+        }
+        goto next;
+      }
+
+      /* escape & */
+      unescaped = g_string_append (unescaped, "&amp;");
+
+    next:
+      continue;
+
+    } else if (g_ascii_isspace (*text)) {
+      unescaped = g_string_append_c (unescaped, ' ');
+      /* strip whitespace */
+      do {
+        text++;
+      } while ((*text) && g_ascii_isspace (*text));
+    } else {
+      unescaped = g_string_append_c (unescaped, *text);
+      text++;
+    }
+  }
+
+  return g_string_free (unescaped, FALSE);
+}
+
+static const gchar *
+string_token (const gchar * string, const gchar * delimiter, gchar ** first)
+{
+  gchar *next = strstr (string, delimiter);
+  if (next) {
+    *first = g_strndup (string, next - string);
+  } else {
+    *first = g_strdup (string);
+  }
+  return next;
+}
+
+static void
+html_context_handle_element (HtmlContext * ctxt,
+    const gchar * string, gboolean must_close)
+{
+  gchar *name = NULL;
+  gint count = 0, i;
+  gchar **attrs;
+  const gchar *found, *next;
+#ifdef SUBPARSE_MODIFICATION
+  const gchar *name_temp = NULL;
+  gint j = 0;
+#endif
+  /* split element name and attributes */
+  next = string_token (string, " ", &name);
+
+  if (next) {
+    /* count attributes */
+    found = next + 1;
+    while (TRUE) {
+      found = strchr (found, '=');
+      if (!found)
+        break;
+      found++;
+      count++;
+    }
+  } else {
+    count = 0;
+  }
+
+  attrs = g_new0 (gchar *, (count + 1) * 2);
+
+  for (i = 0; i < count; i += 2) {
+    gchar *attr_name = NULL, *attr_value = NULL;
+    gsize length;
+
+#ifdef SUBPARSE_MODIFICATION
+    /* sometimes count can unnecessarily be high value, because of unrequired "=" in subtitle file.
+     * In that case it should not crash */
+    if (!next)
+      break;
+#endif
+
+    next = string_token (next + 1, "=", &attr_name);
+
+#ifdef SUBPARSE_MODIFICATION
+    /* sometimes count can unnecessarily be high value, because of unrequired "=" in subtitle file.
+     * In that case it should not crash */
+    if (!next)
+      break;
+#endif
+
+    next = string_token (next + 1, " ", &attr_value);
+
+    /* strip " or ' from attribute value */
+    if (attr_value[0] == '"' || attr_value[0] == '\'') {
+      gchar *tmp = g_strdup (attr_value + 1);
+      g_free (attr_value);
+      attr_value = tmp;
+    }
+
+    length = strlen (attr_value);
+    if (attr_value[length - 1] == '"' || attr_value[length - 1] == '\'') {
+      attr_value[length - 1] = '\0';
+    }
+
+    attrs[i] = attr_name;
+    attrs[i + 1] = attr_value;
+  }
+#ifdef SUBPARSE_MODIFICATION
+  /* sometimes spaces can be there in between !-- and P
+   * that also we have to take care */
+  if (!g_ascii_strcasecmp("!--", name)) {
+    gchar* tempchar = (gchar*)(string + 3);
+    while (*tempchar == ' ') {
+      tempchar++;
+      if (*tempchar == 'P' || *tempchar == 'p') {
+        *(name + 3) = *tempchar;
+        *(name + 4) = '\0';
+        next = tempchar + 1;
+        break;
+      }
+    }
+  }
+  if (next && (!g_ascii_strcasecmp("!--P", name))) {
+    gint attrindex = 0;
+    count = 0;
+    /* count attributes */
+    found = next + 1;
+    while (TRUE) {
+      found = (gchar*)strcasestr (found, "lang");
+      if (!found)
+        break;
+      found++;
+      count++;
+    }
+    g_strfreev (attrs);
+
+    attrs = g_new0 (gchar *, count * 2);
+
+    for (i = 0; i < count; i++) {
+      gchar *attr_name = NULL, *attr_value = NULL;
+
+      next = (gchar*)strcasestr (next, "lang:");
+      attr_value = (gchar*)malloc (3);
+      next = next + 5;
+      strncpy (attr_value, next, 2);
+      attr_value[2] = '\0';
+      GST_LOG ("Language value comes as %s", attr_value);
+      name_temp = next;
+      while (TRUE) {
+        if (*name_temp == '{') {
+          int character_count = 0;
+
+          while (TRUE) {
+            name_temp--;
+
+            if (*name_temp == '.') {
+              attr_name = (gchar*) malloc (character_count + 1);
+              break;
+            }
+            else if (*name_temp != ' ')
+              character_count++;
+          }
+          break;
+        }
+        name_temp--;
+      }
+      name_temp++;
+      for (j = 0; *(name_temp + j) != ' '; j++) {
+        attr_name[j] = *(name_temp + j);
+      }
+      attr_name[j] = '\0';
+      attrs[attrindex++] = attr_name;
+      attrs[attrindex++] = attr_value;
+    }
+  } else {
+    count = 0;
+  }
+#endif
+  ctxt->parser->start_element (ctxt, name,
+      (const gchar **) attrs, ctxt->user_data);
+  if (must_close) {
+    ctxt->parser->end_element (ctxt, name, ctxt->user_data);
+  }
+  g_strfreev (attrs);
+  g_free (name);
+}
+
+static void
+html_context_parse (HtmlContext * ctxt, gchar * text, gsize text_len)
+{
+  const gchar *next = NULL;
+  ctxt->buf = g_string_append_len (ctxt->buf, text, text_len);
+  next = ctxt->buf->str;
+  if (!next) {
+    GST_ERROR ("ctxt->buf->str is NULL");
+    return;
+  }
+  while (TRUE) {
+    if (next[0] == '<') {
+      gchar *element = NULL;
+      /* find <blahblah> */
+      if (!strchr (next, '>')) {
+        /* no tag end point. buffer will be process in next time */
+        return;
+      }
+
+      next = string_token (next, ">", &element);
+      next++;
+      if (g_str_has_suffix (next, "/")) {
+        /* handle <blah/> */
+        element[strlen (element) - 1] = '\0';
+        html_context_handle_element (ctxt, element + 1, TRUE);
+      } else if (element[1] == '/') {
+        /* handle </blah> */
+        ctxt->parser->end_element (ctxt, element + 2, ctxt->user_data);
+      } else {
+        /* handle <blah> */
+        html_context_handle_element (ctxt, element + 1, FALSE);
+      }
+      g_free (element);
+    } else if (strchr (next, '<')) {
+      gchar *text = NULL;
+      gsize length;
+      next = string_token (next, "<", &text);
+      text = g_strstrip (text);
+      length = strlen (text);
+      ctxt->parser->text (ctxt, text, length, ctxt->user_data);
+      g_free (text);
+
+    } else {
+      gchar *text = (gchar *) next;
+      gsize length;
+      text = g_strstrip (text);
+      length = strlen (text);
+      ctxt->parser->text (ctxt, text, length, ctxt->user_data);
+      ctxt->buf = g_string_assign (ctxt->buf, "");
+      return;
+    }
+  }
+
+  ctxt->buf = g_string_assign (ctxt->buf, next);
+}
+
 static gchar *
 has_tag (GString * str, const gchar tag)
 {
@@ -116,26 +748,30 @@ sami_context_pop_state (GstSamiContext * sctx, char state)
 }
 
 static void
-handle_start_sync (GstSamiContext * sctx, const xmlChar ** atts)
+handle_start_sync (GstSamiContext * sctx, const gchar ** atts)
 {
   int i;
 
   sami_context_pop_state (sctx, CLEAR_TAG);
   if (atts != NULL) {
     for (i = 0; (atts[i] != NULL); i += 2) {
-      const xmlChar *key, *value;
+      const gchar *key, *value;
 
       key = atts[i];
       value = atts[i + 1];
 
       if (!value)
         continue;
-      if (!xmlStrncmp ((const xmlChar *) "start", key, 5)) {
+      if (!g_ascii_strcasecmp ("start", key)) {
         /* Only set a new start time if we don't have text pending */
         if (sctx->resultbuf->len == 0)
           sctx->time1 = sctx->time2;
 
         sctx->time2 = atoi ((const char *) value) * GST_MSECOND;
+#ifdef SUBPARSE_MODIFICATION
+        sctx->time3 = sctx->time2;
+#endif
+        sctx->time2 = MAX (sctx->time2, sctx->time1);
         g_string_append (sctx->resultbuf, sctx->buf->str);
         sctx->has_result = (sctx->resultbuf->len != 0) ? TRUE : FALSE;
         g_string_truncate (sctx->buf, 0);
@@ -145,7 +781,7 @@ handle_start_sync (GstSamiContext * sctx, const xmlChar ** atts)
 }
 
 static void
-handle_start_font (GstSamiContext * sctx, const xmlChar ** atts)
+handle_start_font (GstSamiContext * sctx, const gchar ** atts)
 {
   int i;
 
@@ -153,53 +789,53 @@ handle_start_font (GstSamiContext * sctx, const xmlChar ** atts)
   if (atts != NULL) {
     g_string_append (sctx->buf, "<span");
     for (i = 0; (atts[i] != NULL); i += 2) {
-      const xmlChar *key, *value;
+      const gchar *key, *value;
 
       key = atts[i];
       value = atts[i + 1];
 
       if (!value)
         continue;
-      if (!xmlStrncmp ((const xmlChar *) "color", key, 5)) {
+      if (!g_ascii_strcasecmp ("color", key)) {
         /*
          * There are invalid color value in many
          * sami files.
          * It will fix hex color value that start without '#'
          */
         const gchar *sharp = "";
-        int len = xmlStrlen (value);
+        int len = strlen (value);
 
         if (!(*value == '#' && len == 7)) {
           gchar *r;
 
           /* check if it looks like hex */
           if (strtol ((const char *) value, &r, 16) >= 0 &&
-              ((xmlChar *) r == (value + 6) && len == 6)) {
+              ((gchar *) r == (value + 6) && len == 6)) {
             sharp = "#";
           }
         }
         /* some colours can be found in many sami files, but X RGB database
          * doesn't contain a colour by this name, so map explicitly */
-        if (!xmlStrncasecmp (value, (const xmlChar *) "aqua", len)) {
-          value = (const xmlChar *) "#00ffff";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "crimson", len)) {
-          value = (const xmlChar *) "#dc143c";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "fuchsia", len)) {
-          value = (const xmlChar *) "#ff00ff";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "indigo", len)) {
-          value = (const xmlChar *) "#4b0082";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "lime", len)) {
-          value = (const xmlChar *) "#00ff00";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "olive", len)) {
-          value = (const xmlChar *) "#808000";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "silver", len)) {
-          value = (const xmlChar *) "#c0c0c0";
-        } else if (!xmlStrncasecmp (value, (const xmlChar *) "teal", len)) {
-          value = (const xmlChar *) "#008080";
+        if (!g_ascii_strcasecmp ("aqua", value)) {
+          value = "#00ffff";
+        } else if (!g_ascii_strcasecmp ("crimson", value)) {
+          value = "#dc143c";
+        } else if (!g_ascii_strcasecmp ("fuchsia", value)) {
+          value = "#ff00ff";
+        } else if (!g_ascii_strcasecmp ("indigo", value)) {
+          value = "#4b0082";
+        } else if (!g_ascii_strcasecmp ("lime", value)) {
+          value = "#00ff00";
+        } else if (!g_ascii_strcasecmp ("olive", value)) {
+          value = "#808000";
+        } else if (!g_ascii_strcasecmp ("silver", value)) {
+          value = "#c0c0c0";
+        } else if (!g_ascii_strcasecmp ("teal", value)) {
+          value = "#008080";
         }
         g_string_append_printf (sctx->buf, " foreground=\"%s%s\"", sharp,
             value);
-      } else if (!xmlStrncasecmp ((const xmlChar *) "face", key, 4)) {
+      } else if (!g_ascii_strcasecmp ("face", key)) {
         g_string_append_printf (sctx->buf, " font_family=\"%s\"", value);
       }
     }
@@ -208,49 +844,152 @@ handle_start_font (GstSamiContext * sctx, const xmlChar ** atts)
   }
 }
 
+#ifdef SUBPARSE_MODIFICATION
+static void
+handle_p (GstSamiContext * sctx, const gchar ** atts)
+{
+  int i;
+
+  if (atts != NULL) {
+    for (i = 0; (atts[i] != NULL); i += 2) {
+      const gchar *key, *value;
+
+      key = atts[i];
+      value = atts[i + 1];
+
+      if (sctx->current_language && value && strcmp(sctx->current_language, value)
+          && (sctx->time1 == sctx->time2))
+        sctx->language_changed = TRUE;
+
+      else if (!sctx->current_language)
+        sctx->current_language = (gchar*) malloc (128);
+
+      if (key && !g_ascii_strcasecmp ("class", key) && value) {
+        strcpy (sctx->current_language, value);
+        if (sctx->desired_language == NULL && key) {
+          sctx->desired_language = g_strdup(value);
+          GST_LOG("no language list was found and desired lang was set to %s",sctx->desired_language);
+        }
+      }
+      if (sctx->language_changed)
+      {
+         sctx->time1 = 0;
+         sctx->time2 = sctx->time3;
+         sctx->language_changed = FALSE;
+      }
+      if (!value)
+        continue;
+    }
+  }
+}
+
 static void
-start_sami_element (void *ctx, const xmlChar * name, const xmlChar ** atts)
+handle_start_language_list (GstSamiContext * sctx, const gchar ** atts)
 {
-  GstSamiContext *sctx = (GstSamiContext *) ctx;
+  int i = 0;
+  int attrIndex = 0;
+  GstLangStruct *new = NULL;
+  GstLangStruct *temp = NULL;
+
+  if (atts != NULL) {
+    if (g_list_length (sctx->lang_list)) {
+      GST_LOG ("We already got the language list");
+      return;
+    }
+    for (i = 0; (atts[attrIndex] != NULL); i++) {
+      const gchar *key, *value;
+
+      key = atts[attrIndex++];
+      value = atts[attrIndex++];
+
+      GST_LOG ("Inside handle_start_language_list key: %s, value: %s", key, value);
+
+      if (!value)
+        continue;
+
+      new = g_new0 (GstLangStruct, 1);
+      new->language_code = (gchar*) malloc (strlen(value) + 1);
+      if (new->language_code && value)
+        strcpy (new->language_code, value);
+      new->language_key = (gchar*) malloc (strlen(key) + 1);
+      if (new->language_key && key)
+        strcpy (new->language_key, key);
+      sctx->lang_list = g_list_append (sctx->lang_list, new);
+      temp = g_list_nth_data (sctx->lang_list, i);
+      if (sctx->desired_language == NULL && key){
+        sctx->desired_language = g_strdup(key);
+      }
+
+      if (temp)
+        GST_LOG ("Inside handle_start_language_list of glist key: %s, value: %s",
+                    temp->language_key, temp->language_code);
+    }
+  }
+}
+#endif
+
+static void
+handle_start_element (HtmlContext * ctx, const gchar * name,
+    const char **atts, gpointer user_data)
+{
+  GstSamiContext *sctx = (GstSamiContext *) user_data;
 
   GST_LOG ("name:%s", name);
 
-  if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) {
+  if (!g_ascii_strcasecmp ("sync", name)) {
     handle_start_sync (sctx, atts);
     sctx->in_sync = TRUE;
-  } else if (!xmlStrncmp ((const xmlChar *) "font", name, 4)) {
+  } else if (!g_ascii_strcasecmp ("font", name)) {
     handle_start_font (sctx, atts);
-  } else if (!xmlStrncmp ((const xmlChar *) "ruby", name, 4)) {
+  } else if (!g_ascii_strcasecmp ("ruby", name)) {
     sami_context_push_state (sctx, RUBY_TAG);
-  } else if (!xmlStrncmp ((const xmlChar *) "br", name, 2)) {
-    g_string_append_c (sctx->buf, '\n');
+  } else if (!g_ascii_strcasecmp ("br", name)) {
+#ifdef SUBPARSE_MODIFICATION
+    if (sctx->current_language && sctx->desired_language &&
+        !strcmp(sctx->current_language, sctx->desired_language))
+#endif
+      g_string_append_c (sctx->buf, '\n');
     /* FIXME: support for furigana/ruby once implemented in pango */
-  } else if (!xmlStrncmp ((const xmlChar *) "rt", name, 2)) {
+  } else if (!g_ascii_strcasecmp ("rt", name)) {
     if (has_tag (sctx->state, ITALIC_TAG)) {
       g_string_append (sctx->rubybuf, "<i>");
     }
     g_string_append (sctx->rubybuf, "<span size='xx-small' rise='-100'>");
     sami_context_push_state (sctx, RT_TAG);
-  } else if (!xmlStrncmp ((const xmlChar *) "p", name, 1)) {
-  } else if (!xmlStrncmp ((const xmlChar *) "i", name, 1)) {
-    g_string_append (sctx->buf, "<i>");
+  } else if (!g_ascii_strcasecmp ("i", name)) {
+#ifdef SUBPARSE_MODIFICATION
+    if (sctx->current_language && sctx->desired_language &&
+        !strcmp(sctx->current_language, sctx->desired_language))
+#endif
+      g_string_append (sctx->buf, "<i>");
     sami_context_push_state (sctx, ITALIC_TAG);
+  } else if (!g_ascii_strcasecmp ("p", name)) {
+#ifdef SUBPARSE_MODIFICATION
+    handle_p (sctx, atts);
+  } else if (!g_ascii_strcasecmp ("!--P", name)) {
+    handle_start_language_list (sctx, atts);
+#endif
   }
 }
 
 static void
-end_sami_element (void *ctx, const xmlChar * name)
+handle_end_element (HtmlContext * ctx, const char *name, gpointer user_data)
 {
-  GstSamiContext *sctx = (GstSamiContext *) ctx;
+  GstSamiContext *sctx = (GstSamiContext *) user_data;
 
   GST_LOG ("name:%s", name);
 
-  if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) {
+  if (!g_ascii_strcasecmp ("sync", name)) {
     sctx->in_sync = FALSE;
-  } else if ((!xmlStrncmp ((const xmlChar *) "body", name, 4)) ||
-      (!xmlStrncmp ((const xmlChar *) "sami", name, 4))) {
+  } else if ((!g_ascii_strcasecmp ("body", name)) ||
+      (!g_ascii_strcasecmp ("sami", name))) {
     /* We will usually have one buffer left when the body is closed
      * as we need the next sync to actually send it */
+
+#ifdef SUBPARSE_MODIFICATION
+    sctx->end_body = TRUE;
+#endif
+
     if (sctx->buf->len != 0) {
       /* Only set a new start time if we don't have text pending */
       if (sctx->resultbuf->len == 0)
@@ -261,128 +1000,109 @@ end_sami_element (void *ctx, const xmlChar * name)
       sctx->has_result = (sctx->resultbuf->len != 0) ? TRUE : FALSE;
       g_string_truncate (sctx->buf, 0);
     }
-  } else if (!xmlStrncmp ((const xmlChar *) "font", name, 4)) {
+  } else if (!g_ascii_strcasecmp ("font", name)) {
     sami_context_pop_state (sctx, SPAN_TAG);
-  } else if (!xmlStrncmp ((const xmlChar *) "ruby", name, 4)) {
+  } else if (!g_ascii_strcasecmp ("ruby", name)) {
     sami_context_pop_state (sctx, RUBY_TAG);
-  } else if (!xmlStrncmp ((const xmlChar *) "i", name, 1)) {
+  } else if (!g_ascii_strcasecmp ("i", name)) {
     sami_context_pop_state (sctx, ITALIC_TAG);
   }
 }
 
 static void
-characters_sami (void *ctx, const xmlChar * ch, int len)
+handle_text (HtmlContext * ctx, const gchar * text, gsize text_len,
+    gpointer user_data)
 {
-  GstSamiContext *sctx = (GstSamiContext *) ctx;
-  gchar *escaped;
-  gchar *tmp;
-  gint i;
+  GstSamiContext *sctx = (GstSamiContext *) user_data;
 
   /* Skip everything except content of the sync elements */
   if (!sctx->in_sync)
     return;
-
-  escaped = g_markup_escape_text ((const gchar *) ch, len);
-  g_strstrip (escaped);
-
-  /* Remove double spaces forom the string as those are
-   * usually added by newlines and indention */
-  tmp = escaped;
-  for (i = 0; i <= strlen (escaped); i++) {
-    escaped[i] = *tmp;
-    if (*tmp != ' ') {
-      tmp++;
-      continue;
-    }
-    while (*tmp == ' ')
-      tmp++;
-  }
-
+#ifdef SUBPARSE_MODIFICATION
+  if (has_tag (sctx->state, RT_TAG) && (sctx->current_language && sctx->desired_language &&
+       !strcmp(sctx->current_language, sctx->desired_language))) {
+#else
   if (has_tag (sctx->state, RT_TAG)) {
+#endif
     g_string_append_c (sctx->rubybuf, ' ');
-    g_string_append (sctx->rubybuf, escaped);
+    g_string_append (sctx->rubybuf, text);
     g_string_append_c (sctx->rubybuf, ' ');
   } else {
-    g_string_append (sctx->buf, escaped);
+#ifdef SUBPARSE_MODIFICATION
+    if (sctx->current_language && sctx->desired_language &&
+        !strcmp(sctx->current_language, sctx->desired_language))
+#endif
+      g_string_append (sctx->buf, text);
   }
-  g_free (escaped);
 }
 
-static xmlSAXHandler samiSAXHandlerStruct = {
-  NULL,                         /* internalSubset */
-  NULL,                         /* isStandalone */
-  NULL,                         /* hasInternalSubset */
-  NULL,                         /* hasExternalSubset */
-  NULL,                         /* resolveEntity */
-  NULL,                         /* getEntity */
-  NULL,                         /* entityDecl */
-  NULL,                         /* notationDecl */
-  NULL,                         /* attributeDecl */
-  NULL,                         /* elementDecl */
-  NULL,                         /* unparsedEntityDecl */
-  NULL,                         /* setDocumentLocator */
-  NULL,                         /* startDocument */
-  NULL,                         /* endDocument */
-  start_sami_element,           /* startElement */
-  end_sami_element,             /* endElement */
-  NULL,                         /* reference */
-  characters_sami,              /* characters */
-  NULL,                         /* ignorableWhitespace */
-  NULL,                         /* processingInstruction */
-  NULL,                         /* comment */
-  NULL,                         /* xmlParserWarning */
-  NULL,                         /* xmlParserError */
-  NULL,                         /* xmlParserError */
-  NULL,                         /* getParameterEntity */
-  NULL,                         /* cdataBlock */
-  NULL,                         /* externalSubset */
-  1,                            /* initialized */
-  NULL,                         /* private */
-  NULL,                         /* startElementNsSAX2Func */
-  NULL,                         /* endElementNsSAX2Func */
-  NULL                          /* xmlStructuredErrorFunc */
+static HtmlParser samiParser = {
+  handle_start_element,         /* start_element */
+  handle_end_element,           /* end_element */
+  handle_text,                  /* text */
 };
 
-static xmlSAXHandlerPtr samiSAXHandler = &samiSAXHandlerStruct;
-
 void
 sami_context_init (ParserState * state)
 {
   GstSamiContext *context;
 
   g_assert (state->user_data == NULL);
-  state->user_data = (gpointer) g_new0 (GstSamiContext, 1);
-  context = (GstSamiContext *) state->user_data;
 
-  context->htmlctxt = htmlCreatePushParserCtxt (samiSAXHandler, context,
-      "", 0, NULL, XML_CHAR_ENCODING_UTF8);
+  context = g_new0 (GstSamiContext, 1);
+
+  context->htmlctxt = html_context_new (&samiParser, context);
   context->buf = g_string_new ("");
   context->rubybuf = g_string_new ("");
   context->resultbuf = g_string_new ("");
   context->state = g_string_new ("");
+#ifdef SUBPARSE_MODIFICATION
+  context->current_language = NULL;
+  context->desired_language = NULL;
+  context->lang_list = NULL;
+  context->language_changed = FALSE;
+  context->end_body = FALSE;
+#endif
+  state->user_data = context;
 }
 
 void
 sami_context_deinit (ParserState * state)
 {
   GstSamiContext *context = (GstSamiContext *) state->user_data;
-
+#ifdef SUBPARSE_MODIFICATION
+  GstLangStruct *temp = NULL;
+  int i = 0;
+#endif
   if (context) {
-    htmlParserCtxtPtr htmlctxt = context->htmlctxt;
-
-    /* destroy sax context */
-    htmlDocPtr doc;
-
-    htmlParseChunk (htmlctxt, "", 0, 1);
-    doc = htmlctxt->myDoc;
-    htmlFreeParserCtxt (htmlctxt);
+    html_context_free (context->htmlctxt);
     context->htmlctxt = NULL;
-    if (doc)
-      xmlFreeDoc (doc);
     g_string_free (context->buf, TRUE);
     g_string_free (context->rubybuf, TRUE);
     g_string_free (context->resultbuf, TRUE);
     g_string_free (context->state, TRUE);
+#ifdef SUBPARSE_MODIFICATION
+    if (context->lang_list) {
+      while ((temp = g_list_nth_data (context->lang_list, i))) {
+        if (temp->language_code)
+          free (temp->language_code);
+        temp->language_code = NULL;
+        if (temp->language_key)
+          free (temp->language_key);
+        temp->language_key = NULL;
+        g_free (temp);
+        i++;
+      }
+      g_list_free (context->lang_list);
+    }
+    context->lang_list = NULL;
+
+    if (context->current_language)
+      free (context->current_language);
+    context->current_language = NULL;
+
+    context->desired_language = NULL;
+#endif
     g_free (context);
     state->user_data = NULL;
   }
@@ -405,70 +1125,239 @@ sami_context_reset (ParserState * state)
   }
 }
 
-static gchar *
-fix_invalid_entities (const gchar * line)
+#ifdef SUBPARSE_MODIFICATION
+void
+sami_context_change_language (ParserState * state)
 {
-  const gchar *cp, *pp;         /* current pointer, previous pointer */
-  gssize size;
-  GString *ret = g_string_new (NULL);
-
-  pp = line;
-  cp = strchr (line, '&');
-  while (cp) {
-    size = cp - pp;
-    ret = g_string_append_len (ret, pp, size);
-    cp++;
-    if (g_ascii_strncasecmp (cp, "nbsp;", 5)
-        && (!g_ascii_strncasecmp (cp, "nbsp", 4))) {
-      /* translate "&nbsp" to "&nbsp;" */
-      ret = g_string_append_len (ret, "&nbsp;", 6);
-      cp += 4;
-    } else if (g_ascii_strncasecmp (cp, "quot;", 5)
-        && g_ascii_strncasecmp (cp, "amp;", 4)
-        && g_ascii_strncasecmp (cp, "apos;", 5)
-        && g_ascii_strncasecmp (cp, "lt;", 3)
-        && g_ascii_strncasecmp (cp, "gt;", 3)
-        && g_ascii_strncasecmp (cp, "nbsp;", 5)
-        && cp[0] != '#') {
-      /* translate "&" to "&amp;" */
-      ret = g_string_append_len (ret, "&amp;", 5);
-    } else {
-      /* do not translate */
-      ret = g_string_append_c (ret, '&');
+  GstSamiContext *context = (GstSamiContext *) state->user_data;
+  GST_LOG ("**********desired language was %s**************", context->desired_language);
+  free (context->desired_language);
+  if(state->current_language) {
+    context->desired_language = state->current_language;
+  } else {
+    context->desired_language = state->msl_language;
+  }
+  GST_LOG ("desired language changed to %s", context->desired_language);
+}
+
+gchar *
+sami_convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding,
+    gsize * consumed, GError ** err, GstSubParse * self)
+{
+  gchar *ret = NULL;
+
+  /* The char cast is necessary in glib < 2.24 */
+  ret =
+      g_convert_with_fallback (str, len, "UTF-8", encoding, (char *) "*",
+      consumed, NULL, err);
+
+  if (ret == NULL)
+  {
+    GST_DEBUG_OBJECT (self, "g_convert_with_fallback returns NULL");
+    return ret;
+  }
+
+  /* + 3 to skip UTF-8 BOM if it was added */
+  len = strlen (ret);
+  if (len >= 3 && (guint8) ret[0] == 0xEF && (guint8) ret[1] == 0xBB
+      && (guint8) ret[2] == 0xBF)
+    g_memmove (ret, ret + 3, len + 1 - 3);
+
+  return ret;
+}
+
+gboolean
+sami_validate_langlist_body(GList * lang_list, GstSubParse * self){
+  gchar * file_path_type = NULL;
+  gchar * file_path = NULL;
+  gchar   line[1024];
+  FILE  * fp = NULL;
+  guint i = 0, found_count = 0;
+  const guint list_len = g_list_length(lang_list);
+  gboolean counter[MAX_LANGUAGE];
+  struct LangStruct
+  {
+      gchar *language_code;
+      gchar *language_key;
+  } * lang;
+
+  GstQuery *cquery;
+  GstStructure *structure;
+  const GValue *value;
+  structure = gst_structure_new ("FileSrcURI",
+                                 "file-uri", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  if (!gst_pad_peer_query (self->sinkpad, cquery))
+  {
+    GST_DEBUG_OBJECT (self, "failed to query SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  structure = gst_query_get_structure (cquery);
+  value = gst_structure_get_value (structure, "file-uri");
+  file_path = g_strdup (g_value_get_string (value));
+
+  if (file_path == NULL){
+    GST_DEBUG_OBJECT (self, "could not parse the SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  gst_query_unref (cquery);
+
+  GST_INFO_OBJECT (self, "file path comes as %s", file_path);
+
+  file_path_type = g_strndup ((gchar *) file_path, 4);
+  GST_INFO_OBJECT (self, "received file path by query = %s,%s", file_path,file_path_type);
+  if (!g_strcmp0(file_path_type, "file")){
+    file_path += 7;
+    GST_INFO_OBJECT (self, "file path comes as %s", file_path);
+
+    fp = fopen (file_path, "r");
+    if (!fp){
+      GST_DEBUG_OBJECT (self, "failed to open file");
+      return FALSE;
+    }
+
+    for(i=0;i<list_len;i++){
+      counter[i] = FALSE;
     }
 
-    pp = cp;
-    cp = strchr (pp, '&');
+    while(!feof(fp) && found_count < list_len){
+      GError *err = NULL;
+      gsize * consumed = NULL;
+      gint gap = 0;
+      guint charCount = 0;
+      gchar* result = NULL;
+      gchar* temp = NULL;
+      gchar* temp_lang = NULL;
+      gchar * temp1 = NULL;
+      gchar *con_temp_lang = NULL;
+      gchar *con_temp = NULL;
+      gboolean conversion = TRUE;
+      charCount = fread (line, sizeof(char), 1024, fp);
+      if (!charCount) {
+        GST_WARNING_OBJECT (self, "fread returned zero bytes");
+        continue;
+      }
+      GST_DEBUG("value of detected encoding is %s and self encoding is %s",self->detected_encoding,self->encoding);
+      if (self->detected_encoding && strcmp (self->detected_encoding, "UTF-8") && conversion){
+        result = sami_convert_to_utf8 (line, charCount, self->detected_encoding, consumed, &err, self);
+      }
+      if(result == NULL) {
+         result = line;
+         conversion =  FALSE;
+      }
+      con_temp = g_utf8_strdown (result,strlen(result));
+      temp = con_temp;
+      while(con_temp) {
+        con_temp = g_strstr_len(con_temp, strlen(con_temp),"class=");
+        if(con_temp) {
+          temp1 = g_strstr_len(con_temp+1, strlen(con_temp),"class=");
+        }
+        if(temp1 && con_temp){
+          gap = strlen(con_temp)-strlen(temp1);
+        }else if(con_temp) {
+          gap = strlen(con_temp);
+        } else {
+          continue;
+        }
+        if(con_temp){
+          for(i=0;i<list_len;i++){
+            if(counter[i]==TRUE){
+              con_temp=con_temp+1;
+              continue;
+            }
+            lang = (struct LangStruct *) g_list_nth_data(lang_list,i);
+            if(lang) {
+              temp_lang = g_strdup(lang->language_key);
+              con_temp_lang = g_utf8_strdown (temp_lang,strlen(temp_lang));
+              if(g_strstr_len(con_temp,gap,con_temp_lang)){
+                found_count++;
+                counter[i]=TRUE;
+                GST_INFO_OBJECT (self, " valid Language in list : [%s]", lang->language_key);
+                con_temp=con_temp+1;
+              }
+              g_free(temp_lang);
+              g_free(con_temp_lang);
+            }
+          }
+        }
+      }
+      if(conversion)
+       g_free (result);
+      if(temp)
+       g_free(temp);
+
+    }
+
+    if(found_count < list_len){
+      for(i=0;i<list_len;i++){
+        if(counter[i]==FALSE)
+          lang_list = g_list_delete_link(lang_list,g_list_nth(lang_list,i));
+      }
+    }
   }
-  ret = g_string_append (ret, pp);
-  return g_string_free (ret, FALSE);
+  fclose(fp);
+  return TRUE;
 }
+#endif
 
 gchar *
 parse_sami (ParserState * state, const gchar * line)
 {
-  gchar *fixed_line;
+  gchar *ret = NULL;
+#ifdef SUBPARSE_MODIFICATION
+  gint64 clip_start = 0, clip_stop = 0;
+  gboolean in_seg = FALSE;
+#endif
   GstSamiContext *context = (GstSamiContext *) state->user_data;
 
-  fixed_line = fix_invalid_entities (line);
-  htmlParseChunk (context->htmlctxt, fixed_line, strlen (fixed_line), 0);
-  g_free (fixed_line);
+  gchar *unescaped = unescape_string (line);
+  html_context_parse (context->htmlctxt, (gchar *) unescaped,
+      strlen (unescaped));
+#ifdef SUBPARSE_MODIFICATION
+  if (context->lang_list)
+    state->language_list = context->lang_list;
 
-  if (context->has_result) {
-    gchar *r;
+  if (context->desired_language)
+    state->current_language = context->desired_language;
+#endif
+  g_free (unescaped);
+#ifdef SUBPARSE_MODIFICATION
+  if (context->desired_language && context->current_language) {
+    if ((!strcmp(context->current_language, context->desired_language)) || context->end_body) {
+#endif
+      if (context->has_result) {
+        if (context->rubybuf->len) {
+          context->rubybuf = g_string_append_c (context->rubybuf, '\n');
+          g_string_prepend (context->resultbuf, context->rubybuf->str);
+          context->rubybuf = g_string_truncate (context->rubybuf, 0);
+        }
 
-    if (context->rubybuf->len) {
-      context->rubybuf = g_string_append_c (context->rubybuf, '\n');
-      g_string_prepend (context->resultbuf, context->rubybuf->str);
-      context->rubybuf = g_string_truncate (context->rubybuf, 0);
+        ret = g_string_free (context->resultbuf, FALSE);
+        context->resultbuf = g_string_new ("");
+        state->start_time = context->time1;
+        state->duration = context->time2 - context->time1;
+        context->has_result = FALSE;
+      }
+#ifdef SUBPARSE_MODIFICATION
+      context->end_body = FALSE;
     }
+  }
+  /* Check our segment start/stop */
+  in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME,
+             state->start_time, state->start_time + state->duration, &clip_start,
+             &clip_stop);
 
-    r = g_string_free (context->resultbuf, FALSE);
-    context->resultbuf = g_string_new ("");
-    state->start_time = context->time1;
-    state->duration = context->time2 - context->time1;
-    context->has_result = FALSE;
-    return r;
+  /* No need to send that text if it's out of segment */
+  if (in_seg) {
+    state->start_time = clip_start;
+    state->duration = clip_stop - clip_start;
+  } else {
+    return NULL;
   }
-  return NULL;
+#endif
+  return ret;
 }
old mode 100644 (file)
new mode 100755 (executable)
index a45de01..77ea9fe
@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifndef _SAMI_PARSE_H_
@@ -31,6 +31,12 @@ void    sami_context_init   (ParserState * state);
 void    sami_context_deinit (ParserState * state);
 
 void    sami_context_reset  (ParserState * state);
+#ifdef SUBPARSE_MODIFICATION
+void    sami_context_change_language  (ParserState * state);
+gboolean sami_validate_langlist_body(GList * lang_list, GstSubParse * self);
+gchar * sami_convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding,
+    gsize * consumed, GError ** err, GstSubParse * self);
+#endif
 
 G_END_DECLS
 
old mode 100644 (file)
new mode 100755 (executable)
index 63a6d55..7402c50
@@ -477,6 +477,67 @@ hls_type_find (GstTypeFind * tf, gpointer unused)
   }                                                                     \
 }
 
+#define XML_INC_BUFFER_DATA {                                           \
+  pos++;                                                                \
+  if (pos >= length) {                                                  \
+    return FALSE;                                                       \
+  } else {                                                              \
+    data++;                                                             \
+  }                                                                     \
+}
+
+static gboolean
+xml_check_first_element_from_data (const guint8 * data, guint length,
+    const gchar * element, guint elen, gboolean strict)
+{
+  gboolean got_xmldec;
+  guint pos = 0;
+
+  g_return_val_if_fail (data != NULL, FALSE);
+
+  if (length <= 5)
+    return FALSE;
+
+  /* look for the XMLDec
+   * see XML spec 2.8, Prolog and Document Type Declaration
+   * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-prolog-dtd */
+  got_xmldec = (memcmp (data, "<?xml", 5) == 0);
+
+  if (strict && !got_xmldec)
+    return FALSE;
+
+  /* skip XMLDec in any case if we've got one */
+  if (got_xmldec) {
+    if (pos + 5 >= length)
+      return FALSE;
+    pos += 5;
+    data += 5;
+  }
+
+  /* look for the first element, it has to be the requested element. Bail
+   * out if it is not within the first 4kB. */
+  while (data && pos < MIN (4096, length)) {
+    while (*data != '<' && pos < MIN (4096, length)) {
+      XML_INC_BUFFER_DATA;
+    }
+
+    XML_INC_BUFFER_DATA;
+    if (!g_ascii_isalpha (*data)) {
+      /* if not alphabetic, it's a PI or an element / attribute declaration
+       * like <?xxx or <!xxx */
+      XML_INC_BUFFER_DATA;
+      continue;
+    }
+
+    /* the first normal element, check if it's the one asked for */
+    if (pos + elen + 1 >= length)
+      return FALSE;
+    return (data && element && strncmp ((char *) data, element, elen) == 0);
+  }
+
+  return FALSE;
+}
+
 static gboolean
 xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen,
     gboolean strict)
@@ -584,6 +645,71 @@ smil_type_find (GstTypeFind * tf, gpointer unused)
   }
 }
 
+#ifdef GST_EXT_SS_TYPE
+/*** application/x-ss [Microsoft's Smooth Streaming]***********************************/
+
+static GstStaticCaps ss_caps = GST_STATIC_CAPS ("application/x-ss");
+
+#define SS_CAPS (gst_static_caps_get(&ss_caps))
+static void
+ss_type_find (GstTypeFind * tf, gpointer unused)
+{
+
+  if (xml_check_first_element (tf, "SmoothStreamingMedia", 20, TRUE)) {
+         gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SS_CAPS);
+       } else {
+         const guint8 *data;
+         gboolean utf16_le, utf16_be;
+         const gchar *convert_from = NULL;
+         guint8 *converted_data;
+
+         /* try detecting the charset */
+         data = gst_type_find_peek (tf, 0, 2);
+
+         if (data == NULL)
+               return;
+
+         /* look for a possible BOM */
+         utf16_le = data[0] == 0xFF && data[1] == 0xFE;
+         utf16_be = data[0] == 0xFE && data[1] == 0xFF;
+         if (utf16_le) {
+               convert_from = "UTF-16LE";
+         } else if (utf16_be) {
+               convert_from = "UTF-16BE";
+         }
+
+         if (convert_from) {
+               gsize new_size = 0;
+               guint length = gst_type_find_get_length (tf);
+
+               /* try a default that should be enough */
+               if (length == 0)
+                 length = 512;
+               data = gst_type_find_peek (tf, 0, length);
+
+               if (data) {
+                 /* skip the BOM */
+                 data += 2;
+                 length -= 2;
+
+                 converted_data =
+                         (guint8 *) g_convert ((gchar *) data, length, "UTF-8", convert_from,
+                         NULL, &new_size, NULL);
+                 if (converted_data) {
+                       if (xml_check_first_element_from_data (converted_data, new_size,
+                                       "SmoothStreamingMedia", 20, TRUE))
+                         gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM,
+                                 SS_CAPS);
+
+                       g_free (converted_data);
+                 }
+               }
+         }
+       }
+
+}
+#endif
+
 /*** text/html ***/
 
 static GstStaticCaps html_caps = GST_STATIC_CAPS ("text/html");
@@ -980,6 +1106,45 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
         }
 
         gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps);
+#ifdef GST_EXT_TYPEFIND_ENHANCEMENT
+        /* find more aac sync to select correctly */
+
+        /* check if there's a third ADTS frame */
+        len = ((c.data[3] & 0x03) << 11) | (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
+        if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
+          GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
+          goto next;
+        }
+        snc = GST_READ_UINT16_BE (c.data + len);
+        if ((snc & 0xfff6) == 0xfff0) {
+          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 5, caps); /* 85% */
+          GST_DEBUG ("Find 3rd Sync..probability is %u ", GST_TYPE_FIND_LIKELY + 5);
+        }
+
+        /* check if there's a fourth ADTS frame */
+        len = ((c.data[3] & 0x03) << 11) | (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
+        if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
+          GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
+          goto next;
+        }
+        snc = GST_READ_UINT16_BE (c.data + len);
+        if ((snc & 0xfff6) == 0xfff0) {
+          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, caps); /* 90% */
+          GST_DEBUG ("Find 4th Sync..probability is %u ", GST_TYPE_FIND_LIKELY + 10);
+        }
+
+        /* check if there's a fifth(last) ADTS frame */
+        len = ((c.data[3] & 0x03) << 11) | (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5);
+        if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
+          GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
+          goto next;
+        }
+        snc = GST_READ_UINT16_BE (c.data + len);
+        if ((snc & 0xfff6) == 0xfff0) {
+          gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, caps); /* 99% */
+          GST_DEBUG ("Find 5th Sync..probability is %u ", GST_TYPE_FIND_NEARLY_CERTAIN);
+        }
+#endif
         gst_caps_unref (caps);
         break;
       }
@@ -1831,7 +1996,7 @@ static GstStaticCaps multipart_caps =
 GST_STATIC_CAPS ("multipart/x-mixed-replace");
 #define MULTIPART_CAPS gst_static_caps_get(&multipart_caps)
 
-/* multipart/x-mixed replace is: 
+/* multipart/x-mixed replace is:
  *   <maybe some whitespace>--<some ascii chars>[\r]\n
  *   <more ascii chars>[\r]\nContent-type:<more ascii>[\r]\n */
 static void
@@ -1888,7 +2053,7 @@ static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, "
 #define IS_MPEG_PES_HEADER(data)        (IS_MPEG_HEADER (data) &&            \
                                          IS_MPEG_PES_CODE (((guint8 *)(data))[3]))
 
-#define MPEG2_MAX_PROBE_LENGTH (128 * 1024)     /* 128kB should be 64 packs of the 
+#define MPEG2_MAX_PROBE_LENGTH (128 * 1024)     /* 128kB should be 64 packs of the
                                                  * most common 2kB pack size. */
 
 #define MPEG2_MIN_SYS_HEADERS 2
@@ -2103,7 +2268,7 @@ mpeg_sys_type_find (GstTypeFind * tf, gpointer unused)
   }
 
   /* If we at least saw MIN headers, and *some* were pes headers (pack headers
-   * are optional in an mpeg system stream) then return a lower-probability 
+   * are optional in an mpeg system stream) then return a lower-probability
    * result */
   if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MIN_SYS_HEADERS)
     goto suggest;
@@ -2179,7 +2344,7 @@ mpeg_ts_probe_headers (GstTypeFind * tf, guint64 offset, gint packet_size)
 static void
 mpeg_ts_type_find (GstTypeFind * tf, gpointer unused)
 {
-  /* TS packet sizes to test: normal, DVHS packet size and 
+  /* TS packet sizes to test: normal, DVHS packet size and
    * FEC with 16 or 20 byte codes packet size. */
   const gint pack_sizes[] = { 188, 192, 204, 208 };
   const guint8 *data = NULL;
@@ -2208,7 +2373,7 @@ mpeg_ts_type_find (GstTypeFind * tf, gpointer unused)
         if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) {
           gint probability;
 
-          /* found at least 4 headers. 10 headers = MAXIMUM probability. 
+          /* found at least 4 headers. 10 headers = MAXIMUM probability.
            * Arbitrarily, I assigned 10% probability for each header we
            * found, 40% -> 100% */
           probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM);
@@ -2443,7 +2608,7 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
 {
   DataScanCtx c = { 0, NULL, 0 };
 
-  /* Stream consists of: a series of sync codes (00 00 00 01) followed 
+  /* Stream consists of: a series of sync codes (00 00 00 01) followed
    * by NALs
    */
   int nut, ref;
@@ -2708,6 +2873,14 @@ q3gp_type_find_get_profile (const guint8 * data)
       return "general";
     case GST_MAKE_FOURCC ('3', 'g', 'p', 0):
       return "basic";
+#ifdef GST_EXT_MIME_TYPES /* add extended keyword for differentiating */
+    case GST_MAKE_FOURCC ('3', 'g', '2', 0):
+      return "extended";
+    case GST_MAKE_FOURCC ('i', 's', 'm', 0): {
+      g_print ("fragment file format...\n\n");
+      return "fragmented";
+    }
+#endif
     case GST_MAKE_FOURCC ('3', 'g', 's', 0):
       return "streaming-server";
     case GST_MAKE_FOURCC ('3', 'g', 'r', 0):
@@ -2715,6 +2888,14 @@ q3gp_type_find_get_profile (const guint8 * data)
     default:
       break;
   }
+
+#ifdef GST_EXT_MIME_TYPES
+  if (GST_MAKE_FOURCC (data[0], data[1], data[2], data[3]) == GST_MAKE_FOURCC ('p', 'i', 'f', 'f')) {
+    g_print ("piff fragmented...\n\n");
+    return "fragmented";
+  }
+#endif
+
   return NULL;
 }
 
@@ -2821,7 +3002,8 @@ qt_type_find (GstTypeFind * tf, gpointer unused)
 
     if (STRNCMP (&data[4], "ftypisom", 8) == 0 ||
         STRNCMP (&data[4], "ftypavc1", 8) == 0 ||
-        STRNCMP (&data[4], "ftypmp42", 8) == 0) {
+        STRNCMP (&data[4], "ftypmp42", 8) == 0 ||
+        STRNCMP (&data[4], "ftypwmf ", 8) == 0) {
       tip = GST_TYPE_FIND_MAXIMUM;
       variant = "iso";
       break;
@@ -2841,9 +3023,8 @@ qt_type_find (GstTypeFind * tf, gpointer unused)
       }
     }
     /* other box/atom types, apparently quicktime specific */
-    else if (STRNCMP (&data[4], "pnot", 4) == 0 ||
-        STRNCMP (&data[4], "PICT", 4) == 0 ||
-        STRNCMP (&data[4], "wide", 4) == 0 ||
+    else if (STRNCMP (&data[4], "PICT", 4) == 0 ||
+       STRNCMP (&data[4], "wide", 4) == 0 ||
         STRNCMP (&data[4], "prfl", 4) == 0) {
       tip = GST_TYPE_FIND_MAXIMUM;
       break;
@@ -2863,7 +3044,8 @@ qt_type_find (GstTypeFind * tf, gpointer unused)
         if (STRNCMP (&data[4], "isom", 4) == 0 ||
             STRNCMP (&data[4], "avc1", 4) == 0 ||
             STRNCMP (&data[4], "mp41", 4) == 0 ||
-            STRNCMP (&data[4], "mp42", 4) == 0) {
+            STRNCMP (&data[4], "mp42", 4) == 0 ||
+            STRNCMP (&data[4], "wmf ", 4) == 0) {
           tip = GST_TYPE_FIND_MAXIMUM;
           variant = "iso";
           goto done;
@@ -4476,6 +4658,9 @@ plugin_init (GstPlugin * plugin)
   static const gchar *ape_exts[] = { "ape", NULL };
   static const gchar *uri_exts[] = { "ram", NULL };
   static const gchar *hls_exts[] = { "m3u8", NULL };
+#ifdef GST_EXT_SS_TYPE
+  static const gchar *ss_exts[] = { "manifest", NULL };
+#endif
   static const gchar *sdp_exts[] = { "sdp", NULL };
   static const gchar *smil_exts[] = { "smil", NULL };
   static const gchar *html_exts[] = { "htm", "html", NULL };
@@ -4503,7 +4688,7 @@ plugin_init (GstPlugin * plugin)
   static const gchar *zip_exts[] = { "zip", NULL };
   static const gchar *compress_exts[] = { "Z", NULL };
   static const gchar *m4a_exts[] = { "m4a", NULL };
-  static const gchar *q3gp_exts[] = { "3gp", NULL };
+  static const gchar *q3gp_exts[] = { "3gp", "ismv", "isma", NULL };
   static const gchar *aac_exts[] = { "aac", "adts", "adif", "loas", NULL };
   static const gchar *spc_exts[] = { "spc", NULL };
   static const gchar *wavpack_exts[] = { "wv", "wvp", NULL };
@@ -4563,12 +4748,13 @@ plugin_init (GstPlugin * plugin)
 #ifndef GST_EXT_MIME_TYPES
   TYPE_FIND_REGISTER_RIFF (plugin, "audio/qcelp", GST_RANK_PRIMARY,
       qcp_exts, "QLCM");
-  TYPE_FIND_REGISTER_RIFF (plugin, "video/x-cdxa", GST_RANK_PRIMARY,
-      cdxa_exts, "CDXA");
   TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-vcd", GST_RANK_PRIMARY,
       cdxa_exts, "\000\377\377\377\377\377\377\377\377\377\377\000", 12,
       GST_TYPE_FIND_MAXIMUM);
 #endif
+  TYPE_FIND_REGISTER_RIFF (plugin, "video/x-cdxa", GST_RANK_PRIMARY,
+      cdxa_exts, "CDXA");
+
   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-imelody", GST_RANK_PRIMARY,
       imelody_exts, "BEGIN:IMELODY", 13, GST_TYPE_FIND_MAXIMUM);
 #if 0
@@ -4612,9 +4798,9 @@ plugin_init (GstPlugin * plugin)
 #ifndef GST_EXT_MIME_TYPES
   TYPE_FIND_REGISTER (plugin, "audio/x-gsm", GST_RANK_PRIMARY, NULL, gsm_exts,
       GSM_CAPS, NULL, NULL);
+#endif
   TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY,
       mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL);
-#endif
   TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY,
       mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY,
@@ -4672,12 +4858,16 @@ plugin_init (GstPlugin * plugin)
       hls_type_find, hls_exts, HLS_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/sdp", GST_RANK_SECONDARY,
       sdp_type_find, sdp_exts, SDP_CAPS, NULL, NULL);
+#ifdef GST_EXT_SS_TYPE
+  TYPE_FIND_REGISTER (plugin, "application/x-ss", GST_RANK_PRIMARY,
+      ss_type_find, ss_exts, SS_CAPS, NULL, NULL);
+#endif
 #ifndef GST_EXT_MIME_TYPES
   TYPE_FIND_REGISTER (plugin, "application/smil", GST_RANK_SECONDARY,
       smil_type_find, smil_exts, SMIL_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/xml", GST_RANK_MARGINAL,
       xml_type_find, xml_exts, GENERIC_XML_CAPS, NULL, NULL);
-#endif  
+#endif
   TYPE_FIND_REGISTER_RIFF (plugin, "audio/x-wav", GST_RANK_PRIMARY, wav_exts,
       "WAVE");
 #ifndef GST_EXT_MIME_TYPES
@@ -4701,7 +4891,7 @@ plugin_init (GstPlugin * plugin)
       shn_type_find, shn_exts, SHN_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER (plugin, "application/x-ape", GST_RANK_SECONDARY,
       ape_type_find, ape_exts, APE_CAPS, NULL, NULL);
-#endif  
+#endif
   TYPE_FIND_REGISTER (plugin, "image/jpeg", GST_RANK_PRIMARY + 15,
       jpeg_type_find, jpeg_exts, JPEG_CAPS, NULL, NULL);
   TYPE_FIND_REGISTER_START_WITH (plugin, "image/gif", GST_RANK_PRIMARY,
index e4ba16c..1633302 100644 (file)
@@ -608,14 +608,38 @@ gst_video_rate_flush_prev (GstVideoRate * videorate, gboolean duplicate)
   GstFlowReturn res;
   GstBuffer *outbuf;
   GstClockTime push_ts;
-
+#ifdef VIDEORATE_MODIFICATION
+  GstStructure *structure;
+  guint32 format;
+  GstCaps *buf_caps;
+#endif
   if (!videorate->prevbuf)
     goto eos_before_buffers;
 
   /* make sure we can write to the metadata */
-  outbuf = gst_buffer_make_metadata_writable
-      (gst_buffer_ref (videorate->prevbuf));
-
+#ifdef VIDEORATE_MODIFICATION
+  buf_caps = gst_buffer_get_caps (videorate->prevbuf);
+  if(!buf_caps) {
+    GST_ERROR("not able to get the caps");
+    return GST_FLOW_ERROR;
+  }
+  structure = gst_caps_get_structure (buf_caps, 0);
+  if(!structure) {
+    GST_ERROR("not able to get the structure");
+    return GST_FLOW_ERROR;
+  }
+  if (!gst_structure_get_fourcc (structure, "format", &format)) {
+    GST_ERROR ("can not get format in gst structure");
+  }
+  if(format== GST_MAKE_FOURCC('S', 'T', '1', '2') || format== GST_MAKE_FOURCC('S', 'N', '1', '2')) {
+    GST_ERROR("setting the format_transcode as TRUE");
+    outbuf=videorate->prevbuf;
+    gst_caps_unref(buf_caps);
+  } else {
+    outbuf = gst_buffer_make_metadata_writable
+    (gst_buffer_ref (videorate->prevbuf));
+  }
+#endif
   GST_BUFFER_OFFSET (outbuf) = videorate->out;
   GST_BUFFER_OFFSET_END (outbuf) = videorate->out + 1;
 
index 772548c..50c8e56 100644 (file)
@@ -19,7 +19,7 @@
 
 #ifndef __GST_VIDEO_RATE_H__
 #define __GST_VIDEO_RATE_H__
-
+#define VIDEORATE_MODIFICATION
 #include <gst/gst.h>
 #include <gst/base/gstbasetransform.h>
 
index 1f40f62..6272a0d 100644 (file)
@@ -136,8 +136,15 @@ enum
         "rate = (int) [ 1,  MAX ], " \
         "endianness = (int) BYTE_ORDER, " \
         "width = (int) 32, " \
-       "depth = (int) 32, " \
-       "signed = (bool) TRUE"
+        "depth = (int) 32, " \
+        "signed = (bool) TRUE;" \
+        "audio/x-raw-int, " \
+        "channels = (int) [ 1, MAX ], " \
+        "rate = (int) [ 1,  MAX ], " \
+        "endianness = (int) BYTE_ORDER, " \
+        "width = (int) 32, " \
+        "depth = (int) 24, " \
+        "signed = (bool) TRUE"
 
 static void gst_volume_interface_init (GstImplementsInterfaceClass * klass);
 static void gst_volume_mixer_init (GstMixerClass * iface);
old mode 100644 (file)
new mode 100755 (executable)
index 5ae42b5..9762b70
@@ -1,12 +1,13 @@
 Name:       gst-plugins-base
 Summary:    GStreamer streaming media framework base plug-ins
-Version:    0.10.36
-Release:    7
+Version:    0.10.37
+Release:    171
 Group:      Applications/Multimedia
-License:    LGPLv2+
+License:    LGPL-2.0+
 Source0:    %{name}-%{version}.tar.gz
 #Patch0:     Samsung-feature-bugs.patch
 Requires(post): /sbin/ldconfig
+Requires(post): /usr/bin/vconftool
 Requires(postun): /sbin/ldconfig
 BuildRequires:  pkgconfig(ogg)
 BuildRequires:  pkgconfig(theora)
@@ -17,8 +18,15 @@ BuildRequires:  pkgconfig(alsa)
 BuildRequires:  pkgconfig(gstreamer-0.10)
 BuildRequires:  pkgconfig(gstreamer-base-0.10)
 BuildRequires:  pkgconfig(xv)
-BuildRequires:  pkgconfig(pango)
+BuildRequires:  pkgconfig(xfixes)
+BuildRequires:  pkgconfig(dri2proto)
+BuildRequires:  pkgconfig(libdri2)
+BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(libdrm)
+BuildRequires:  pkgconfig(utilX)
 BuildRequires:  intltool
+#BuildRequires: libsavscodec-neon-devel
+BuildRequires: pkgconfig(vconf)
 
 
 %description
@@ -54,10 +62,18 @@ Separate sub-package contaning helper applications of gstreamer base plugins.
 %build
 %autogen --noconfigure
 
+#Add -DSAMSUNG_WFD_SPEC to enable RTP over TCP streaming support
 export CFLAGS+=" -Wall -g -fPIC\
  -DGST_EXT_XV_ENHANCEMENT\
+ -DSAMSUNG_WFD_SPEC\
+ -DGST_EXT_SS_TYPE\
  -DGST_EXT_LINK_FIMCCONVERT\
- -DGST_EXT_MIME_TYPES"
+ -DGST_EXT_MIME_TYPES\
+ -DGST_EXT_ENABLE_SMI\
+ -DGST_EXT_TYPEFIND_ENHANCEMENT\
+ -DGST_EXT_TIME_ANALYSIS\
+ -DGST_EXT_DECODEBIN2_QUEUESIZE\
+ -DGST_EXT_DECODEBIN2_MODIFICATION"
 
 %configure --prefix=/usr\
  --disable-static\
@@ -75,7 +91,8 @@ export CFLAGS+=" -Wall -g -fPIC\
  --disable-gcov\
  --disable-gtk-doc\
  --disable-debug\
- --with-audioresample-format=int
+ --with-audioresample-format=int\
+ --disable-gst_v4l
 
 make %{?jobs:-j%jobs}
 
@@ -86,12 +103,15 @@ rm -rf %{buildroot}
 
 rm -rf %{buildroot}/tmp/dump
 
-%post -p /sbin/ldconfig
+%post
+/sbin/ldconfig
 
+/usr/bin/vconftool set -t int memory/Player/XvStateInfo 0 -g 29 -f -i -s system::vconf_multimedia
 %postun -p /sbin/ldconfig
 
 
 %files
+%manifest gst-plugins-base.manifest
 %defattr(-,root,root,-)
 #%doc COPYING 
 # libraries
@@ -123,7 +143,6 @@ rm -rf %{buildroot}/tmp/dump
 %{_libdir}/gstreamer-0.10/libgstvideorate.so
 %{_libdir}/gstreamer-0.10/libgstvideoscale.so
 %{_libdir}/gstreamer-0.10/libgsttcp.so
-%{_libdir}/gstreamer-0.10/libgstvideo4linux.so
 %{_libdir}/gstreamer-0.10/libgstaudioresample.so
 %{_libdir}/gstreamer-0.10/libgstapp.so
 %{_libdir}/gstreamer-0.10/libgstxvimagesink.so
@@ -134,7 +153,6 @@ rm -rf %{buildroot}/tmp/dump
 %{_libdir}/gstreamer-0.10/libgsttheora.so
 %{_libdir}/gstreamer-0.10/libgstvorbis.so
 %{_libdir}/gstreamer-0.10/libgstximagesink.so
-%{_libdir}/gstreamer-0.10/libgstpango.so
 %{_libdir}/gstreamer-0.10/libgstgio.so
 # data
 %{_datadir}/gst-plugins-base/license-translations.dict
@@ -250,6 +268,7 @@ rm -rf %{buildroot}/tmp/dump
 %{_libdir}/pkgconfig/*.pc
 
 %files tools
+%manifest gst-plugins-base-tools.manifest
 %defattr(-,root,root,-)
 # helper programs
 %{_bindir}/gst-discoverer-0.10
index fbff4d8..1cff228 100644 (file)
@@ -1,13 +1,18 @@
 plugin_LTLIBRARIES = libgstxvimagesink.la
 
 libgstxvimagesink_la_SOURCES =  xvimagesink.c 
-libgstxvimagesink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS)
+libgstxvimagesink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) $(XFIXES_CFLAGS) $(DRI2PROTO_CFLAGS) $(DRI2_CFLAGS) $(TBM_CFLAGS) $(UTILX_CFLAGS) $(VCONF_CFLAGS) $(DRM_CFLAGS) $(DRM_DEVEL_CFLAGS)
+#libgstxvimagesink_la_CFLAGS = $(SAVSCODEC_HEVC_CFLAGS)
 libgstxvimagesink_la_LIBADD = \
        $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \
        $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \
        $(GST_BASE_LIBS) \
        $(GST_LIBS) \
-       $(X_LIBS) $(XVIDEO_LIBS) $(XSHM_LIBS) $(LIBM)
+       $(XFIXES_LIBS) \
+       $(DRI2PROTO_LIBS) \
+       $(DRI2_LIBS) \
+       $(TBM_LIBS) \
+       $(X_LIBS) $(XVIDEO_LIBS) $(XSHM_LIBS) $(LIBM) $(UTILX_LIBS) $(VCONF_LIBS) $(DRM_LIBS) $(DRM_DEVEL_LIBS)
 libgstxvimagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstxvimagesink_la_DEPENDENCIES = $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la
 libgstxvimagesink_la_LIBTOOLFLAGS = --tag=disable-static
old mode 100644 (file)
new mode 100755 (executable)
index bbcc07d..5afaf48
@@ -1,12 +1,45 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
 /*                                                              */
 /* File name : xv_types.h                                       */
-/* Author : YoungHoon Jung (yhoon.jung@samsung.com)             */
+/* Author : Boram Park (boram1288.park@samsung.com)             */
 /* Protocol Version : 1.0.1 (Dec 16th 2009)                       */
 /* This file is for describing Xv APIs' buffer encoding method. */
 /*                                                              */
 
-#define XV_PUTIMAGE_HEADER     0xDEADCD01
-#define XV_PUTIMAGE_VERSION    0x00010001
+#ifndef __XV_TYPE_H__
+#define __XV_TYPE_H__
+
+#define XV_DATA_HEADER 0xDEADCD01
+#define XV_DATA_VERSION        0x00010001
 
 /* Return Values */
 #define XV_OK 0
 #define XV_VERSION_MISMATCH -2
 
 /* Video Mode */
-#define DISPLAY_MODE_DEFAULT                                      0
+#define DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_CLONE             0
 #define DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_FULL_SCREEN       1
 #define DISPLAY_MODE_PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN      2
 
+/* Color space range */
+#define CSC_RANGE_NARROW        0
+#define CSC_RANGE_WIDE          1
+
+/* Buffer Type */
+#define XV_BUF_TYPE_DMABUF  0
+#define XV_BUF_TYPE_LEGACY  1
+#define XV_BUF_PLANE_NUM    3
+
 /* Data structure for XvPutImage / XvShmPutImage */
-typedef struct {
-       unsigned int _header; /* for internal use only */
-       unsigned int _version; /* for internal use only */
-
-       unsigned int YPhyAddr;
-       unsigned int CbPhyAddr;
-       unsigned int CrPhyAddr;
-       unsigned int RotAngle;
-       unsigned int VideoMode;
-} XV_PUTIMAGE_DATA, * XV_PUTIMAGE_DATA_PTR;
-
-static void XV_PUTIMAGE_INIT_DATA(XV_PUTIMAGE_DATA_PTR data)
+typedef struct
 {
-       data->_header = XV_PUTIMAGE_HEADER;
-       data->_version = XV_PUTIMAGE_VERSION;
+    unsigned int _header; /* for internal use only */
+    unsigned int _version; /* for internal use only */
+
+    unsigned int YBuf;
+    unsigned int CbBuf;
+    unsigned int CrBuf;
+    unsigned int BufType;
+    unsigned int dmabuf_fd[XV_BUF_PLANE_NUM];
+    unsigned int gem_handle[XV_BUF_PLANE_NUM];
+    void *bo[XV_BUF_PLANE_NUM];
+} XV_DATA, * XV_DATA_PTR;
+
+static void
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_INIT_DATA (XV_DATA_PTR data)
+{
+    data->_header = XV_DATA_HEADER;
+    data->_version = XV_DATA_VERSION;
 }
+
+static int
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_VALIDATE_DATA (XV_DATA_PTR data)
+{
+    if (data->_header != XV_DATA_HEADER)
+        return XV_HEADER_ERROR;
+    if (data->_version != XV_DATA_VERSION)
+        return XV_VERSION_MISMATCH;
+    return XV_OK;
+}
+
+#endif
+
old mode 100644 (file)
new mode 100755 (executable)
index 079f82a..5a0d67f
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
  *               <2009>,<2010> Stefan Kost <stefan.kost@nokia.com>
+ * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * * Modifications by Samsung Electronics Co., Ltd.
+ * 1. Add display related properties
+ * 2. Support samsung extension format to improve performance
+ * 3. Support video texture overlay of OSP layer
  */
 
 /**
 /* For xv extension header for buffer transfer (output) */
 #include "xv_types.h"
 
+/* headers for drm */
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <X11/Xmd.h>
+#include <dri2/dri2.h>
+#include <tbm_bufmgr.h>
+
+/* for setting vconf about xv state */
+#include <vconf.h>
+#include <vconf-internal-player-keys.h>
+
+
+enum {
+    SECURE_PATH_INIT = -1,
+    SECURE_PATH_OFF = 0,
+    SECURE_PATH_ON = 1
+};
+
+enum {
+    DRM_LEVEL_0 = 0,
+    DRM_LEVEL_1
+ };
+
+enum
+{
+  DISPLAY_STATUS_NULL = 0,
+  DISPLAY_STATUS_HDMI_ACTIVE,
+  DISPLAY_STATUS_UNKNOWN_ACTIVE,
+};
+
+enum
+{
+  XV_STATUS_NULL = 0,
+  XV_STATUS_READY,
+  XV_STATUS_PAUSED,
+  XV_STATUS_PLAYING,
+  XV_STATUS_SEEK,
+};
+
+typedef enum {
+        BUF_SHARE_METHOD_PADDR = 0,
+        BUF_SHARE_METHOD_FD,
+        BUF_SHARE_METHOD_TIZEN_BUFFER,
+        BUF_SHARE_METHOD_FLUSH_BUFFER
+} buf_share_method_t;
+
+#define _CHECK_DISPLAYED_BUFFER_COUNT   15
+#define _EVENT_THREAD_CHECK_INTERVAL    15000   /* us */
+
 /* max channel count *********************************************************/
 #define SCMN_IMGB_MAX_PLANE         (4)
 
 typedef struct
 {
        /* width of each image plane */
-       int      w[SCMN_IMGB_MAX_PLANE];
+       int w[SCMN_IMGB_MAX_PLANE];
        /* height of each image plane */
-       int      h[SCMN_IMGB_MAX_PLANE];
+       int h[SCMN_IMGB_MAX_PLANE];
        /* stride of each image plane */
-       int      s[SCMN_IMGB_MAX_PLANE];
+       int s[SCMN_IMGB_MAX_PLANE];
        /* elevation of each image plane */
-       int      e[SCMN_IMGB_MAX_PLANE];
+       int e[SCMN_IMGB_MAX_PLANE];
        /* user space address of each image plane */
-       void   * a[SCMN_IMGB_MAX_PLANE];
+       void *a[SCMN_IMGB_MAX_PLANE];
        /* physical address of each image plane, if needs */
-       void   * p[SCMN_IMGB_MAX_PLANE];
+       void *p[SCMN_IMGB_MAX_PLANE];
        /* color space type of image */
-       int      cs;
+       int cs;
        /* left postion, if needs */
-       int      x;
+       int x;
        /* top position, if needs */
-       int      y;
+       int y;
        /* to align memory */
-       int      __dummy2;
+       int __dummy2;
        /* arbitrary data */
-       int      data[16];
+       int data[16];
+       /* dma buf fd */
+       int dmabuf_fd[SCMN_IMGB_MAX_PLANE];
+       /* buffer share method */
+       int buf_share_method;
+       /* Y plane size in case of ST12 */
+       int y_size;
+       /* UV plane size in case of ST12 */
+       int uv_size;
+       /* Tizen buffer object */
+       void *bo[SCMN_IMGB_MAX_PLANE];
+       /* JPEG data */
+       void *jpeg_data;
+       /* JPEG size */
+       int jpeg_size;
+       /* TZ memory buffer */
+       int tz_enable;
 } SCMN_IMGB;
+
+static void _release_flush_buffer(GstXvImageSink *xvimagesink);
+static void _remove_last_buffer(GstXvImageSink *xvimagesink);
+static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink);
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
 /* Debugging category */
@@ -192,6 +271,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
 
 #ifdef GST_EXT_XV_ENHANCEMENT
 #define GST_TYPE_XVIMAGESINK_DISPLAY_MODE (gst_xvimagesink_display_mode_get_type())
+#define GST_TYPE_XVIMAGESINK_CSC_RANGE (gst_xvimagesink_csc_range_get_type())
 
 static GType
 gst_xvimagesink_display_mode_get_type(void)
@@ -211,6 +291,23 @@ gst_xvimagesink_display_mode_get_type(void)
        return xvimagesink_display_mode_type;
 }
 
+static GType
+gst_xvimagesink_csc_range_get_type(void)
+{
+       static GType xvimagesink_csc_range_type = 0;
+       static const GEnumValue csc_range_type[] = {
+               { 0, "Narrow range", "NARROW"},
+               { 1, "Wide range", "WIDE"},
+               { 2, NULL, NULL},
+       };
+
+       if (!xvimagesink_csc_range_type) {
+               xvimagesink_csc_range_type = g_enum_register_static("GstXVImageSinkCSCRangeType", csc_range_type);
+       }
+
+       return xvimagesink_csc_range_type;
+}
+
 enum {
     DEGREE_0,
     DEGREE_90,
@@ -245,13 +342,32 @@ enum {
     DISP_GEO_METHOD_ORIGIN_SIZE,
     DISP_GEO_METHOD_FULL_SCREEN,
     DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
-    DISP_GEO_METHOD_CUSTOM_ROI,
+    DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
+    DISP_GEO_METHOD_CUSTOM_DST_ROI,
     DISP_GEO_METHOD_NUM,
 };
 
-#define DEF_DISPLAY_GEOMETRY_METHOD DISP_GEO_METHOD_LETTER_BOX
+enum {
+    ROI_DISP_GEO_METHOD_FULL_SCREEN = 0,
+    ROI_DISP_GEO_METHOD_LETTER_BOX,
+    ROI_DISP_GEO_METHOD_NUM,
+};
+
+#define DEF_DISPLAY_GEOMETRY_METHOD         DISP_GEO_METHOD_LETTER_BOX
+#define DEF_ROI_DISPLAY_GEOMETRY_METHOD     ROI_DISP_GEO_METHOD_FULL_SCREEN
+
+enum {
+    FLIP_NONE = 0,
+    FLIP_HORIZONTAL,
+    FLIP_VERTICAL,
+    FLIP_BOTH,
+    FLIP_NUM,
+};
+#define DEF_DISPLAY_FLIP            FLIP_NONE
 
 #define GST_TYPE_XVIMAGESINK_DISPLAY_GEOMETRY_METHOD (gst_xvimagesink_display_geometry_method_get_type())
+#define GST_TYPE_XVIMAGESINK_ROI_DISPLAY_GEOMETRY_METHOD (gst_xvimagesink_roi_display_geometry_method_get_type())
+#define GST_TYPE_XVIMAGESINK_FLIP                    (gst_xvimagesink_flip_get_type())
 
 static GType
 gst_xvimagesink_display_geometry_method_get_type(void)
@@ -262,8 +378,9 @@ gst_xvimagesink_display_geometry_method_get_type(void)
                { 1, "Origin size", "ORIGIN_SIZE"},
                { 2, "Full-screen", "FULL_SCREEN"},
                { 3, "Cropped full-screen", "CROPPED_FULL_SCREEN"},
-               { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
-               { 5, NULL, NULL},
+               { 4, "Origin size(if screen size is larger than video size(width/height)) or Letter box(if video size(width/height) is larger than screen size)", "ORIGIN_SIZE_OR_LETTER_BOX"},
+               { 5, "Explicitly described destination ROI", "CUSTOM_DST_ROI"},
+               { 6, NULL, NULL},
        };
 
        if (!xvimagesink_display_geometry_method_type) {
@@ -272,6 +389,92 @@ gst_xvimagesink_display_geometry_method_get_type(void)
 
        return xvimagesink_display_geometry_method_type;
 }
+
+static GType
+gst_xvimagesink_roi_display_geometry_method_get_type(void)
+{
+       static GType xvimagesink_roi_display_geometry_method_type = 0;
+       static const GEnumValue roi_display_geometry_method_type[] = {
+               { 0, "ROI-Full-screen", "FULL_SCREEN"},
+               { 1, "ROI-Letter box", "LETTER_BOX"},
+               { 2, NULL, NULL},
+       };
+
+       if (!xvimagesink_roi_display_geometry_method_type) {
+               xvimagesink_roi_display_geometry_method_type = g_enum_register_static("GstXVImageSinkROIDisplayGeometryMethodType", roi_display_geometry_method_type);
+       }
+
+       return xvimagesink_roi_display_geometry_method_type;
+}
+
+static GType
+gst_xvimagesink_flip_get_type(void)
+{
+       static GType xvimagesink_flip_type = 0;
+       static const GEnumValue flip_type[] = {
+               { FLIP_NONE,       "Flip NONE", "FLIP_NONE"},
+               { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
+               { FLIP_VERTICAL,   "Flip VERTICAL", "FLIP_VERTICAL"},
+               { FLIP_BOTH,       "Flip BOTH", "FLIP_BOTH"},
+               { FLIP_NUM, NULL, NULL},
+       };
+
+       if (!xvimagesink_flip_type) {
+               xvimagesink_flip_type = g_enum_register_static("GstXVImageSinkFlipType", flip_type);
+       }
+
+       return xvimagesink_flip_type;
+}
+
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+void
+gst_xvimagesink_BOOLEAN__POINTER (GClosure         *closure,
+                                     GValue         *return_value G_GNUC_UNUSED,
+                                     guint          n_param_values,
+                                     const GValue   *param_values,
+                                     gpointer       invocation_hint G_GNUC_UNUSED,
+                                     gpointer       marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer     data1,
+                                                     gpointer     arg_1,
+                                                     gpointer     data2);
+  register GMarshalFunc_BOOLEAN__POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                      g_marshal_value_peek_pointer (param_values + 1),
+                      data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+enum
+{
+    SIGNAL_FRAME_RENDER_ERROR,
+    SIGNAL_DISPLAY_STATUS,
+    SIGNAL_EXTERNAL_RESOLUTION,
+    SIGNAL_WINDOW_STATUS,
+    SIGNAL_QUICKPANEL_STATUS,
+    SIGNAL_MULTIWINDOW_STATUS,
+    LAST_SIGNAL
+};
+static guint gst_xvimagesink_signals[LAST_SIGNAL] = { 0 };
+
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
 typedef struct
@@ -286,6 +489,11 @@ MotifWmHints, MwmHints;
 
 #define MWM_HINTS_DECORATIONS   (1L << 1)
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+#define MAX_DISPLAY_IN_XVIMAGESINK  20
+static Display *g_display_id[MAX_DISPLAY_IN_XVIMAGESINK] = {0};
+#endif
+
 static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
 
 static GstBufferClass *xvimage_buffer_parent_class = NULL;
@@ -300,6 +508,16 @@ static void gst_xvimagesink_expose (GstXOverlay * overlay);
 #ifdef GST_EXT_XV_ENHANCEMENT
 static XImage *make_transparent_image(Display *d, Window win, int w, int h);
 static gboolean set_display_mode(GstXContext *xcontext, int set_mode);
+static gboolean set_csc_range(GstXContext *xcontext, int set_range);
+static void gst_xvimagesink_set_pixmap_handle(GstXOverlay *overlay, guintptr id);
+static unsigned int drm_convert_dmabuf_gemname(GstXvImageSink *xvimagesink, unsigned int dmabuf_fd, unsigned int *gem_handle);
+static void drm_close_gem(GstXvImageSink *xvimagesink, unsigned int *gem_handle);
+static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_data, GstBuffer *buffer);
+static void _remove_displaying_buffer(GstXvImageSink *xvimagesink, unsigned int *gem_name);
+static int _is_connected_to_external_display(GstXvImageSink *xvimagesink);
+static void check_hdmi_connected(GstXvImageSink *xvimagesink);
+static int get_window_prop_card32_property (Display* dpy, Window win, Atom atom, Atom type, unsigned int *val, unsigned int len);
+static gboolean check_supportable_port_attr(GstXvImageSink * xvimagesink, gchar* attr_name);
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
 /* Default template - initiated with class struct to allow gst-register to work
@@ -340,15 +558,37 @@ enum
   PROP_WINDOW_HEIGHT,
 #ifdef GST_EXT_XV_ENHANCEMENT
   PROP_DISPLAY_MODE,
+  PROP_CSC_RANGE,
   PROP_ROTATE_ANGLE,
+  PROP_FLIP,
   PROP_DISPLAY_GEOMETRY_METHOD,
   PROP_VISIBLE,
   PROP_ZOOM,
+  PROP_ZOOM_POS_X,
+  PROP_ZOOM_POS_Y,
+  PROP_ORIENTATION,
+  PROP_DST_ROI_MODE,
   PROP_DST_ROI_X,
   PROP_DST_ROI_Y,
   PROP_DST_ROI_W,
   PROP_DST_ROI_H,
+  PROP_SRC_CROP_X,
+  PROP_SRC_CROP_Y,
+  PROP_SRC_CROP_W,
+  PROP_SRC_CROP_H,
   PROP_STOP_VIDEO,
+  PROP_PIXMAP_CB,
+  PROP_PIXMAP_CB_USER_DATA,
+  PROP_SUBPICTURE,
+  PROP_EXTERNAL_WIDTH,
+  PROP_EXTERNAL_HEIGHT,
+  PROP_ENABLE_FLUSH_BUFFER,
+  PROP_PIXMAP,
+  PROP_HIDED_WINDOW,
+  PROP_QUICKPANEL_ON,
+  PROP_MULTIWINDOW_ACTIVE,
+  PROP_KEEP_EXTERNAL_FULLSCREEN_POST,
+  PROP_KEEP_EXTERNAL_FULLSCREEN_PREV,
 #endif /* GST_EXT_XV_ENHANCEMENT */
 };
 
@@ -560,8 +800,23 @@ gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
   char error_msg[1024];
 
   XGetErrorText (display, xevent->error_code, error_msg, 1024);
-  GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
-  error_caught = TRUE;
+#ifndef GST_EXT_XV_ENHANCEMENT
+  GST_DEBUG ("xvimagesink triggered an XError. error: %s, display(%p)", error_msg, display);
+#else
+  {
+    int i = 0;
+    for (i = 0; i < MAX_DISPLAY_IN_XVIMAGESINK; i++) {
+      if (g_display_id[i] == display) {
+        GST_ERROR ("xvimagesink triggered an XError. error: %s, display(%p), xevent->request_code: %d", error_msg, display, xevent->request_code);
+        error_caught = TRUE;
+        break;
+      }
+    }
+    if (i == MAX_DISPLAY_IN_XVIMAGESINK) {
+      GST_ERROR ("xvimagesink triggered an XError. error: %s, xevent->request_code: %d, but the display(%p) was not created in xvimagesink, skip it...", error_msg, xevent->request_code, display);
+    }
+  }
+#endif
   return 0;
 }
 
@@ -703,6 +958,10 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
     xvimagesink->aligned_width = xvimage->width;
     xvimagesink->aligned_height = xvimage->height;
   }
+  if (xvimagesink->subpicture) {
+    GST_LOG("because of subpicture's format, pass xvimage_new");
+    return xvimage;
+  }
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
@@ -718,6 +977,9 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
 
   g_mutex_lock (xvimagesink->x_lock);
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  XSync (xvimagesink->xcontext->disp, FALSE);
+#endif /* GST_EXT_XV_ENHANCEMENT */
   /* Setting an error handler to catch failure */
   error_caught = FALSE;
   handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
@@ -747,12 +1009,18 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
           ("could not XvShmCreateImage a %dx%d image",
               xvimage->width, xvimage->height));
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+      /* must not change "use_xshm",
+         because it causes memory curruption when buffer created by XvShmCreateImage is destroyed */
+      goto beach_unlocked;
+#else /* GST_EXT_XV_ENHANCEMENT */
       /* Retry without XShm */
       xvimagesink->xcontext->use_xshm = FALSE;
 
       /* Hold X mutex again to try without XShm */
       g_mutex_lock (xvimagesink->x_lock);
       goto no_xshm;
+#endif /* GST_EXT_XV_ENHANCEMENT */
     }
 
     /* we have to use the returned data_size for our shm size */
@@ -796,6 +1064,7 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
 #ifdef GST_EXT_XV_ENHANCEMENT
       case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
       case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
+      case GST_MAKE_FOURCC ('S', 'N', '2', '1'):
       case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
       case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
       case GST_MAKE_FOURCC ('S', '4', '2', '0'):
@@ -872,7 +1141,9 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
     GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
         xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
   } else
+#ifndef GST_EXT_XV_ENHANCEMENT
   no_xshm:
+#endif /* GST_EXT_XV_ENHANCEMENT */
 #endif /* HAVE_XSHM */
   {
     xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
@@ -978,33 +1249,74 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
 #ifdef GST_EXT_XV_ENHANCEMENT
   static Atom atom_rotation = None;
+  static Atom atom_hflip = None;
+  static Atom atom_vflip = None;
+  static Atom atom_contents_rotation = None;
+  gboolean set_hflip = FALSE;
+  gboolean set_vflip = FALSE;
+  XWindowAttributes map_attr;
 
   GstVideoRectangle src_origin = { 0, 0, 0, 0};
   GstVideoRectangle src_input  = { 0, 0, 0, 0};
   GstVideoRectangle src = { 0, 0, 0, 0};
   GstVideoRectangle dst = { 0, 0, 0, 0};
 
+  gint res_rotate_angle = 0;
   int rotate        = 0;
+  int orientation = 0;
   int ret           = 0;
+  int idx           = 0;
+  int (*handler) (Display *, XErrorEvent *) = NULL;
+  gboolean res = FALSE;
+  XV_DATA_PTR img_data = NULL;
+
+  if (xvimagesink->is_subpicture_format)
+    return TRUE;
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   /* We take the flow_lock. If expose is in there we don't want to run
      concurrently from the data flow thread */
   g_mutex_lock (xvimagesink->flow_lock);
 
-  if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
 #ifdef GST_EXT_XV_ENHANCEMENT
-    GST_INFO_OBJECT( xvimagesink, "xwindow is NULL. Skip xvimage_put." );
+  if (xvimagesink->xid_updated) {
+    if (xvimage && xvimagesink->xvimage == NULL) {
+      GST_WARNING_OBJECT (xvimagesink, "set xvimage to NULL, new xid was set right after creation of new xvimage");
+      xvimage = NULL;
+    }
+    xvimagesink->xid_updated = FALSE;
+  }
 #endif /* GST_EXT_XV_ENHANCEMENT */
+
+  if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+    if (xvimagesink->get_pixmap_cb) {
+      GST_INFO_OBJECT( xvimagesink, "xwindow is NULL, but it has get_pixmap_cb(0x%x), keep going..",xvimagesink->get_pixmap_cb );
+    } else {
+      GST_INFO_OBJECT( xvimagesink, "xwindow is NULL. Skip xvimage_put." );
+      g_mutex_unlock(xvimagesink->flow_lock);
+      return FALSE;
+    }
+#else /* GST_EXT_XV_ENHANCEMENT */
     g_mutex_unlock (xvimagesink->flow_lock);
     return FALSE;
+#endif /* GST_EXT_XV_ENHANCEMENT */
   }
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-  if (xvimagesink->visible == FALSE) {
-    GST_INFO_OBJECT(xvimagesink, "visible is FALSE. Skip xvimage_put.");
-    g_mutex_unlock(xvimagesink->flow_lock);
-    return TRUE;
+  /* check map status of window */
+  if(!xvimagesink->is_pixmap) {
+    if (xvimagesink->xcontext && xvimagesink->xwindow) {
+      if (XGetWindowAttributes(xvimagesink->xcontext->disp, xvimagesink->xwindow->win, &map_attr)) {
+        if (map_attr.map_state != IsViewable) {
+          GST_WARNING_OBJECT(xvimagesink, "window is unmapped, skip putimage");
+          g_mutex_unlock(xvimagesink->flow_lock);
+          return TRUE;
+        }
+      } else {
+      GST_WARNING_OBJECT(xvimagesink, "XGetWindowAttributes failed");
+      }
+    }
   }
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
@@ -1027,12 +1339,24 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
   /* Expose sends a NULL image, we take the latest frame */
   if (!xvimage) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+    g_mutex_lock(xvimagesink->display_buffer_lock);
+    if (xvimagesink->is_zero_copy_format  &&
+        xvimagesink->displaying_buffer_count < 1) {
+      g_mutex_unlock(xvimagesink->display_buffer_lock);
+      g_mutex_unlock (xvimagesink->flow_lock);
+      GST_WARNING_OBJECT(xvimagesink, "no buffer to display. skip putimage");
+      return TRUE;
+    }
+    g_mutex_unlock(xvimagesink->display_buffer_lock);
+#endif /* GST_EXT_XV_ENHANCEMENT */
     if (xvimagesink->cur_image) {
       draw_border = TRUE;
       xvimage = xvimagesink->cur_image;
     } else {
 #ifdef GST_EXT_XV_ENHANCEMENT
-      GST_INFO_OBJECT(xvimagesink, "cur_image is NULL. Skip xvimage_put.");
+      GST_WARNING_OBJECT(xvimagesink, "cur_image is NULL. Skip xvimage_put.");
+      /* no need to release gem handle */
 #endif /* GST_EXT_XV_ENHANCEMENT */
       g_mutex_unlock (xvimagesink->flow_lock);
       return TRUE;
@@ -1040,7 +1364,59 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
   }
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-  gst_xvimagesink_xwindow_update_geometry( xvimagesink );
+  gboolean enable_last_buffer;
+  g_object_get(G_OBJECT(xvimagesink), "enable-last-buffer", &enable_last_buffer, NULL);
+  if(enable_last_buffer) {
+    if (xvimagesink->cur_image && xvimagesink->is_zero_copy_format) {
+      GstBuffer *last_buffer= NULL;
+      g_object_get(G_OBJECT(xvimagesink), "last-buffer", &last_buffer, NULL);
+      if (last_buffer) {
+        if(last_buffer != xvimagesink->cur_image)
+        {
+          GST_LOG("curimage : %p , last_buffer : %p", xvimagesink->cur_image, last_buffer);
+        }
+      } else {
+        GST_WARNING_OBJECT(xvimagesink, "zero copy format and last buffer is NULL, so skip this putimage");
+        g_mutex_unlock (xvimagesink->flow_lock);
+        return TRUE;
+      }
+      gst_buffer_unref(last_buffer);
+      last_buffer = NULL;
+    }
+  }
+
+  if (xvimagesink->visible == FALSE ||
+      (xvimagesink->is_hided && GST_STATE(xvimagesink) != GST_STATE_PLAYING)) {
+    GST_INFO("visible[%d] or is_hided[%d]. Skip xvimage_put.",
+             xvimagesink->visible, xvimagesink->is_hided);
+    g_mutex_unlock(xvimagesink->flow_lock);
+    return TRUE;
+  }
+
+  if (!xvimagesink->get_pixmap_cb) {
+    gst_xvimagesink_xwindow_update_geometry( xvimagesink );
+    if (!xvimagesink->subpicture && !xvimagesink->is_during_seek) {
+      if(xvimagesink->is_multi_window && (GST_STATE(xvimagesink) != GST_STATE_PLAYING)) {
+        set_display_mode(xvimagesink->xcontext, DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_CLONE);
+      } else {
+        set_display_mode(xvimagesink->xcontext, xvimagesink->display_mode);
+      }
+    }
+  } else {
+    /* for multi-pixmap usage for the video texture */
+    gst_xvimagesink_set_pixmap_handle ((GstXOverlay *)xvimagesink, xvimagesink->get_pixmap_cb(xvimagesink->get_pixmap_cb_user_data));
+    idx = xvimagesink->current_pixmap_idx;
+    if (idx == -1) {
+      g_mutex_unlock (xvimagesink->flow_lock);
+      return FALSE;
+    } else if (idx == -2) {
+      GST_WARNING_OBJECT(xvimagesink, "Skip putImage()");
+      g_mutex_unlock (xvimagesink->flow_lock);
+      return TRUE;
+    }
+  }
+
+  res_rotate_angle = xvimagesink->rotate_angle;
 
   src.x = src.y = 0;
   src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
@@ -1048,6 +1424,19 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
   src_input.w = src_origin.w = xvimagesink->video_width;
   src_input.h = src_origin.h = xvimagesink->video_height;
 
+  if ((xvimagesink->display_geometry_method == DISP_GEO_METHOD_LETTER_BOX ||
+      xvimagesink->display_geometry_method == DISP_GEO_METHOD_FULL_SCREEN ||
+      xvimagesink->display_geometry_method == DISP_GEO_METHOD_CUSTOM_DST_ROI) &&
+      xvimagesink->src_crop.w && xvimagesink->src_crop.h) {
+      GST_LOG_OBJECT(xvimagesink, "set src crop %d,%d,%dx%d -> %d,%d,%dx%d",
+                                  src_input.x, src_input.y, src_input.w, src_input.h,
+                                  xvimagesink->src_crop.x, xvimagesink->src_crop.y, xvimagesink->src_crop.w, xvimagesink->src_crop.h);
+      src_input.x = src_origin.w = xvimagesink->src_crop.x;
+      src_input.y = src_origin.y = xvimagesink->src_crop.y;
+      src_input.w = src_origin.w = xvimagesink->src_crop.w;
+      src_input.h = src_origin.h = xvimagesink->src_crop.h;
+  }
+
   if (xvimagesink->rotate_angle == DEGREE_0 ||
       xvimagesink->rotate_angle == DEGREE_180) {
     src.w = src_origin.w;
@@ -1086,8 +1475,13 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
    case DISP_GEO_METHOD_FULL_SCREEN:
       result.x = result.y = 0;
-      result.w = xvimagesink->xwindow->width;
-      result.h = xvimagesink->xwindow->height;
+      if (!xvimagesink->get_pixmap_cb) {
+        result.w = xvimagesink->xwindow->width;
+        result.h = xvimagesink->xwindow->height;
+      } else {
+        result.w = xvimagesink->xpixmap[idx]->width;
+        result.h = xvimagesink->xpixmap[idx]->height;
+      }
       break;
 
    case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
@@ -1109,66 +1503,185 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
       }
       break;
 
-    case DISP_GEO_METHOD_CUSTOM_ROI:
-#ifdef GST_EXT_XV_ENHANCEMENT_ROI_MODE
+   case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
+     if (src.w > dst.w || src.h > dst.h) {
+       /* LETTER BOX */
+       gst_video_sink_center_rect (src, dst, &result, TRUE);
+       result.x += xvimagesink->render_rect.x;
+       result.y += xvimagesink->render_rect.y;
+     } else {
+       /* ORIGIN SIZE */
+       gst_video_sink_center_rect (src, dst, &result, FALSE);
+       gst_video_sink_center_rect (dst, src, &src_input, FALSE);
+
+       if (xvimagesink->rotate_angle == DEGREE_90 ||
+           xvimagesink->rotate_angle == DEGREE_270) {
+         src_input.x = src_input.x ^ src_input.y;
+         src_input.y = src_input.x ^ src_input.y;
+         src_input.x = src_input.x ^ src_input.y;
+
+         src_input.w = src_input.w ^ src_input.h;
+         src_input.h = src_input.w ^ src_input.h;
+         src_input.w = src_input.w ^ src_input.h;
+       }
+     }
+     break;
+
+    case DISP_GEO_METHOD_CUSTOM_DST_ROI:
+    {
+      GstVideoRectangle dst_roi_cmpns;
+      dst_roi_cmpns.w = xvimagesink->dst_roi.w;
+      dst_roi_cmpns.h = xvimagesink->dst_roi.h;
+      dst_roi_cmpns.x = xvimagesink->dst_roi.x;
+      dst_roi_cmpns.y = xvimagesink->dst_roi.y;
+
+      /* setting for DST ROI mode */
+      switch (xvimagesink->dst_roi_mode) {
+      case ROI_DISP_GEO_METHOD_FULL_SCREEN:
+        break;
+      case ROI_DISP_GEO_METHOD_LETTER_BOX:
+       {
+        GstVideoRectangle roi_result;
+        if (xvimagesink->orientation == DEGREE_0 ||
+            xvimagesink->orientation == DEGREE_180) {
+          src.w = src_origin.w;
+          src.h = src_origin.h;
+        } else {
+          src.w = src_origin.h;
+          src.h = src_origin.w;
+        }
+        dst.w = xvimagesink->dst_roi.w;
+        dst.h = xvimagesink->dst_roi.h;
+
+        gst_video_sink_center_rect (src, dst, &roi_result, TRUE);
+        dst_roi_cmpns.w = roi_result.w;
+        dst_roi_cmpns.h = roi_result.h;
+        dst_roi_cmpns.x = xvimagesink->dst_roi.x + roi_result.x;
+        dst_roi_cmpns.y = xvimagesink->dst_roi.y + roi_result.y;
+       }
+        break;
+      default:
+        break;
+      }
+
+      /* calculating coordinates according to rotation angle for DST ROI */
       switch (xvimagesink->rotate_angle) {
       case DEGREE_90:
-        result.w = xvimagesink->dst_roi.h;
-        result.h = xvimagesink->dst_roi.w;
+        result.w = dst_roi_cmpns.h;
+        result.h = dst_roi_cmpns.w;
 
-        result.x = xvimagesink->dst_roi.y;
-        result.y = xvimagesink->xwindow->height - xvimagesink->dst_roi.x - xvimagesink->dst_roi.w;
+        result.x = dst_roi_cmpns.y;
+        if (!xvimagesink->get_pixmap_cb) {
+          result.y = xvimagesink->xwindow->height - dst_roi_cmpns.x - dst_roi_cmpns.w;
+        } else {
+          result.y = xvimagesink->xpixmap[idx]->height - dst_roi_cmpns.x - dst_roi_cmpns.w;
+        }
         break;
       case DEGREE_180:
-        result.w = xvimagesink->dst_roi.w;
-        result.h = xvimagesink->dst_roi.h;
+        result.w = dst_roi_cmpns.w;
+        result.h = dst_roi_cmpns.h;
 
-        result.x = xvimagesink->xwindow->width - result.w - xvimagesink->dst_roi.x;
-        result.y = xvimagesink->xwindow->height - result.h - xvimagesink->dst_roi.y;
+        if (!xvimagesink->get_pixmap_cb) {
+          result.x = xvimagesink->xwindow->width - result.w - dst_roi_cmpns.x;
+          result.y = xvimagesink->xwindow->height - result.h - dst_roi_cmpns.y;
+        } else {
+          result.x = xvimagesink->xpixmap[idx]->width - result.w - dst_roi_cmpns.x;
+          result.y = xvimagesink->xpixmap[idx]->height - result.h - dst_roi_cmpns.y;
+        }
         break;
       case DEGREE_270:
-        result.w = xvimagesink->dst_roi.h;
-        result.h = xvimagesink->dst_roi.w;
+        result.w = dst_roi_cmpns.h;
+        result.h = dst_roi_cmpns.w;
 
-        result.x = xvimagesink->xwindow->width - xvimagesink->dst_roi.y - xvimagesink->dst_roi.h;
-        result.y = xvimagesink->dst_roi.x;
+        if (!xvimagesink->get_pixmap_cb) {
+          result.x = xvimagesink->xwindow->width - dst_roi_cmpns.y - dst_roi_cmpns.h;
+        } else {
+          result.x = xvimagesink->xpixmap[idx]->width - dst_roi_cmpns.y - dst_roi_cmpns.h;
+        }
+        result.y = dst_roi_cmpns.x;
         break;
       default:
-        result.x = xvimagesink->dst_roi.x;
-        result.y = xvimagesink->dst_roi.y;
-        result.w = xvimagesink->dst_roi.w;
-        result.h = xvimagesink->dst_roi.h;
+        result.x = dst_roi_cmpns.x;
+        result.y = dst_roi_cmpns.y;
+        result.w = dst_roi_cmpns.w;
+        result.h = dst_roi_cmpns.h;
         break;
       }
 
-      GST_LOG_OBJECT(xvimagesink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
-                     xvimagesink->rotate_angle,
+      /* orientation setting for auto rotation in DST ROI */
+      if (xvimagesink->orientation) {
+        res_rotate_angle = (xvimagesink->rotate_angle - xvimagesink->orientation);
+        if (res_rotate_angle < 0) {
+          res_rotate_angle += DEGREE_NUM;
+        }
+        GST_LOG_OBJECT(xvimagesink, "changing rotation value internally by ROI orientation[%d] : rotate[%d->%d]",
+                     xvimagesink->orientation, xvimagesink->rotate_angle, res_rotate_angle);
+      }
+
+      GST_LOG_OBJECT(xvimagesink, "rotate[%d], dst ROI: orientation[%d], mode[%d], input[%d,%d,%dx%d]->result[%d,%d,%dx%d]",
+                     xvimagesink->rotate_angle, xvimagesink->orientation, xvimagesink->dst_roi_mode,
                      xvimagesink->dst_roi.x, xvimagesink->dst_roi.y, xvimagesink->dst_roi.w, xvimagesink->dst_roi.h,
                      result.x, result.y, result.w, result.h);
-#else /* GST_EXT_XV_ENHANCEMENT_ROI_MODE */
-      result.x = xvimagesink->dst_roi.x;
-      result.y = xvimagesink->dst_roi.y;
-      result.w = xvimagesink->dst_roi.w;
-      result.h = xvimagesink->dst_roi.h;
-
-      if (xvimagesink->rotate_angle == DEGREE_90 ||
-          xvimagesink->rotate_angle == DEGREE_270) {
-        result.w = xvimagesink->dst_roi.h;
-        result.h = xvimagesink->dst_roi.w;
-      }
-#endif /* GST_EXT_XV_ENHANCEMENT_ROI_MODE */
       break;
-
+    }
     default:
       break;
   }
 
-  if (xvimagesink->zoom > 1 && xvimagesink->zoom < 10) {
-    src_input.x += (src_input.w-(src_input.w/xvimagesink->zoom))>>1;
-    src_input.y += (src_input.h-(src_input.h/xvimagesink->zoom))>>1;
-    src_input.w /= xvimagesink->zoom;
-    src_input.h /= xvimagesink->zoom;
+  if (xvimagesink->zoom > 1.0 && xvimagesink->zoom <= 9.0) {
+    GST_LOG_OBJECT(xvimagesink, "before zoom[%lf], src_input[x:%d,y:%d,w:%d,h:%d]",
+                   xvimagesink->zoom, src_input.x, src_input.y, src_input.w, src_input.h);
+    gint default_offset_x = 0;
+    gint default_offset_y = 0;
+    gfloat w = (gfloat)src_input.w;
+    gfloat h = (gfloat)src_input.h;
+    if (xvimagesink->orientation == DEGREE_0 ||
+        xvimagesink->orientation == DEGREE_180) {
+      default_offset_x = ((gint)(w - (w/xvimagesink->zoom)))>>1;
+      default_offset_y = ((gint)(h - (h/xvimagesink->zoom)))>>1;
+    } else {
+      default_offset_y = ((gint)(w - (w/xvimagesink->zoom)))>>1;
+      default_offset_x = ((gint)(h - (h/xvimagesink->zoom)))>>1;
+    }
+    GST_LOG_OBJECT(xvimagesink, "default offset x[%d] y[%d], orientation[%d]", default_offset_x, default_offset_y, xvimagesink->orientation);
+    if (xvimagesink->zoom_pos_x == -1) {
+      src_input.x += default_offset_x;
+    } else {
+      if (xvimagesink->orientation == DEGREE_0 ||
+          xvimagesink->orientation == DEGREE_180) {
+        if ((w/xvimagesink->zoom) > w - xvimagesink->zoom_pos_x) {
+          xvimagesink->zoom_pos_x = w - (w/xvimagesink->zoom);
+        }
+        src_input.x += xvimagesink->zoom_pos_x;
+      } else {
+        if ((h/xvimagesink->zoom) > h - xvimagesink->zoom_pos_x) {
+          xvimagesink->zoom_pos_x = h - (h/xvimagesink->zoom);
+        }
+        src_input.y += (h - h/xvimagesink->zoom) - xvimagesink->zoom_pos_x;
+      }
+    }
+    if (xvimagesink->zoom_pos_y == -1) {
+      src_input.y += default_offset_y;
+    } else {
+      if (xvimagesink->orientation == DEGREE_0 ||
+          xvimagesink->orientation == DEGREE_180) {
+        if ((h/xvimagesink->zoom) > h - xvimagesink->zoom_pos_y) {
+          xvimagesink->zoom_pos_y = h - (h/xvimagesink->zoom);
+        }
+        src_input.y += xvimagesink->zoom_pos_y;
+      } else {
+        if ((w/xvimagesink->zoom) > w - xvimagesink->zoom_pos_y) {
+          xvimagesink->zoom_pos_y = w - (w/xvimagesink->zoom);
+        }
+        src_input.x += (xvimagesink->zoom_pos_y);
+      }
+    }
+    src_input.w = (gint)(w/xvimagesink->zoom);
+    src_input.h = (gint)(h/xvimagesink->zoom);
+    GST_LOG_OBJECT(xvimagesink, "after zoom[%lf], src_input[x:%d,y:%d,w:%d,h%d], zoom_pos[x:%d,y:%d]",
+                   xvimagesink->zoom, src_input.x, src_input.y, src_input.w, src_input.h, xvimagesink->zoom_pos_x, xvimagesink->zoom_pos_y);
   }
+
 #else /* GST_EXT_XV_ENHANCEMENT */
   if (xvimagesink->keep_aspect) {
     GstVideoRectangle src, dst;
@@ -1190,7 +1703,11 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
   g_mutex_lock (xvimagesink->x_lock);
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (draw_border && xvimagesink->draw_borders && !xvimagesink->get_pixmap_cb) {
+#else
   if (draw_border && xvimagesink->draw_borders) {
+#endif /* GST_EXT_XV_ENHANCEMENT */
     gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow,
         result);
     xvimagesink->redraw_border = FALSE;
@@ -1206,7 +1723,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
         xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage);
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-    switch( xvimagesink->rotate_angle )
+    switch( res_rotate_angle )
     {
       /* There's slightly weired code (CCW? CW?) */
       case DEGREE_0:
@@ -1222,7 +1739,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
         break;
       default:
         GST_WARNING_OBJECT( xvimagesink, "Unsupported rotation [%d]... set DEGREE 0.",
-          xvimagesink->rotate_angle );
+          res_rotate_angle );
         break;
     }
 
@@ -1234,31 +1751,168 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
         src_input.h += 1;
     }
 
-    GST_LOG_OBJECT( xvimagesink, "screen[%dx%d],window[%d,%d,%dx%d],method[%d],rotate[%d],zoom[%d],dp_mode[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
-      xvimagesink->scr_w, xvimagesink->scr_h,
-      xvimagesink->xwindow->x, xvimagesink->xwindow->y, xvimagesink->xwindow->width, xvimagesink->xwindow->height,
+    if (!xvimagesink->get_pixmap_cb) {
+      GST_LOG_OBJECT( xvimagesink, "screen[%dx%d],window[%d,%d,%dx%d],method[%d],rotate[%d],zoom[%f],dp_mode[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
+        xvimagesink->scr_w, xvimagesink->scr_h,
+        xvimagesink->xwindow->x, xvimagesink->xwindow->y, xvimagesink->xwindow->width, xvimagesink->xwindow->height,
+        xvimagesink->display_geometry_method, rotate, xvimagesink->zoom, xvimagesink->display_mode,
+        src_origin.w, src_origin.h,
+        dst.x, dst.y, dst.w, dst.h,
+        src_input.x, src_input.y, src_input.w, src_input.h,
+        result.x, result.y, result.w, result.h );
+    } else {
+      GST_LOG_OBJECT( xvimagesink, "pixmap[%d,%d,%dx%d],method[%d],rotate[%d],zoom[%f],dp_mode[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
+      xvimagesink->xpixmap[idx]->x, xvimagesink->xpixmap[idx]->y, xvimagesink->xpixmap[idx]->width, xvimagesink->xpixmap[idx]->height,
       xvimagesink->display_geometry_method, rotate, xvimagesink->zoom, xvimagesink->display_mode,
       src_origin.w, src_origin.h,
       dst.x, dst.y, dst.w, dst.h,
       src_input.x, src_input.y, src_input.w, src_input.h,
       result.x, result.y, result.w, result.h );
+    }
+    /* skip request to render if dst rect is 0 */
+    if (xvimagesink->is_zero_copy_format && (!result.w || !result.h)) {
+      GST_WARNING_OBJECT(xvimagesink, "result.w[%d] or result.h[%d] is 0. Skip xvimage_put.", result.w, result.h);
+      g_mutex_unlock(xvimagesink->x_lock);
+      g_mutex_unlock(xvimagesink->flow_lock);
+      return TRUE;
+    }
+
+    static gboolean is_exist = FALSE;
+    gchar *attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_ROTATION");
+    is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+    g_free(attr_name);
 
-    if (atom_rotation == None) {
-      atom_rotation = XInternAtom(xvimagesink->xcontext->disp,
+    if (is_exist) {
+      /* set display rotation */
+      if (atom_rotation == None) {
+        atom_rotation = XInternAtom(xvimagesink->xcontext->disp,
                                   "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
+      }
+      ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
+                               atom_rotation, rotate);
+      if (ret != Success) {
+        GST_ERROR_OBJECT( xvimagesink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
+          ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_rotation, rotate );
+
+        g_mutex_unlock(xvimagesink->x_lock);
+        g_mutex_unlock(xvimagesink->flow_lock);
+        return FALSE;
+      }
+    } else {
+      GST_WARNING("_USER_WM_PORT_ATTRIBUTE_ROTATION is not existed");
     }
 
-    ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_rotation, rotate);
-    if (ret != Success) {
-      GST_ERROR_OBJECT( xvimagesink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
-        ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_rotation, rotate );
-      return FALSE;
+    switch( xvimagesink->orientation )
+    {
+      case DEGREE_0:
+        orientation = 0;
+        break;
+      case DEGREE_90:
+        orientation = 90;
+        break;
+      case DEGREE_180:
+        orientation = 180;
+        break;
+      case DEGREE_270:
+        orientation = 270;
+        break;
+      default:
+        GST_WARNING_OBJECT( xvimagesink, "Unsupported orientation [%d]...",
+          xvimagesink->orientation );
+        break;
+    }
+
+    is_exist = FALSE;
+    attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_CONTENTS_ROTATION");
+    is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+    g_free(attr_name);
+
+    if (is_exist) {
+      /* set contents rotation for connecting with external display */
+      if (atom_contents_rotation == None) {
+        atom_contents_rotation = XInternAtom(xvimagesink->xcontext->disp,
+                                 "_USER_WM_PORT_ATTRIBUTE_CONTENTS_ROTATION", False);
+      }
+      ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
+                               atom_contents_rotation, orientation);
+      if (ret != Success) {
+        GST_ERROR_OBJECT( xvimagesink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],orientation[%d]",
+          ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_contents_rotation, orientation );
+
+        g_mutex_unlock(xvimagesink->x_lock);
+        g_mutex_unlock(xvimagesink->flow_lock);
+        return FALSE;
+      }
+    }else {
+      GST_WARNING("_USER_WM_PORT_ATTRIBUTE_CONTENTS_ROTATION is not existed");
+    }
+
+    switch (xvimagesink->flip) {
+    case FLIP_HORIZONTAL:
+      set_hflip = TRUE;
+      set_vflip = FALSE;
+      break;
+    case FLIP_VERTICAL:
+      set_hflip = FALSE;
+      set_vflip = TRUE;
+      break;
+    case FLIP_BOTH:
+      set_hflip = TRUE;
+      set_vflip = TRUE;
+      break;
+    case FLIP_NONE:
+    default:
+      set_hflip = FALSE;
+      set_vflip = FALSE;
+      break;
+    }
+
+    GST_LOG("set HFLIP %d, VFLIP %d", set_hflip, set_vflip);
+
+    is_exist = FALSE;
+    attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_HFLIP");
+    is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+    g_free(attr_name);
+
+    if (is_exist) {
+      if (atom_hflip == None) {
+        /* set display flip */
+        atom_hflip = XInternAtom(xvimagesink->xcontext->disp,
+                                 "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
+    }
+      ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_hflip, set_hflip);
+      if (ret != Success) {
+        GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
+                    ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_hflip, set_hflip);
+      }
+    }
+
+    is_exist = FALSE;
+    attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_VFLIP");
+    is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+    g_free(attr_name);
+
+    if (is_exist) {
+      if (atom_vflip == None) {
+        /* set display flip */
+        atom_vflip = XInternAtom(xvimagesink->xcontext->disp,
+                                 "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
+       }
+      ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_vflip, set_vflip);
+      if (ret != Success) {
+        GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
+                    ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_vflip, set_vflip);
+      }
     }
 
+    /* set error handler */
+    error_caught = FALSE;
+    handler = XSetErrorHandler(gst_xvimagesink_handle_xerror);
+
     /* src input indicates the status when degree is 0 */
     /* dst input indicates the area that src will be shown regardless of rotate */
-
-    if (xvimagesink->visible && !xvimagesink->is_hided) {
+    if (xvimagesink->visible &&
+      ((!xvimagesink->is_hided) || (xvimagesink->is_hided && (GST_STATE(xvimagesink) == GST_STATE_PLAYING)))) {
       if (xvimagesink->xim_transparenter) {
         GST_LOG_OBJECT( xvimagesink, "Transparent related issue." );
         XPutImage(xvimagesink->xcontext->disp,
@@ -1269,13 +1923,39 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
           result.x, result.y, result.w, result.h);
       }
 
-      ret = XvShmPutImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimagesink->xwindow->win,
-        xvimagesink->xwindow->gc, xvimage->xvimage,
-        src_input.x, src_input.y, src_input.w, src_input.h,
-        result.x, result.y, result.w, result.h, FALSE);
-      GST_LOG_OBJECT( xvimagesink, "XvShmPutImage return value [%d]", ret );
+      /* store buffer */
+      if (xvimagesink->is_zero_copy_format && xvimage->xvimage->data) {
+        img_data = (XV_DATA_PTR)xvimage->xvimage->data;
+        if (img_data->BufType == XV_BUF_TYPE_DMABUF) {
+          _add_displaying_buffer(xvimagesink, img_data, xvimage->current_buffer);
+          xvimage->current_buffer = NULL;
+        }
+      }
+
+      g_mutex_lock(xvimagesink->display_buffer_lock);
+      if (xvimagesink->displaying_buffer_count > 3) {
+        GST_WARNING("too many buffers are not released. [displaying_buffer_count %d]", xvimagesink->displaying_buffer_count);
+      }
+      g_mutex_unlock(xvimagesink->display_buffer_lock);
+
+      if (xvimagesink->get_pixmap_cb) {
+        gint idx = xvimagesink->current_pixmap_idx;
+        ret = XvShmPutImage (xvimagesink->xcontext->disp,
+          xvimagesink->xcontext->xv_port_id,
+          xvimagesink->xpixmap[idx]->pixmap,
+          xvimagesink->xpixmap[idx]->gc, xvimage->xvimage,
+          src_input.x, src_input.y, src_input.w, src_input.h,
+          result.x, result.y, result.w, result.h, FALSE);
+        GST_LOG_OBJECT( xvimagesink, "XvShmPutImage return value [%d], disp[0x%x], gc[0x%x], pixmap id[%d], idx[%d]", ret, xvimagesink->xcontext->disp, xvimagesink->xpixmap[idx]->gc, xvimagesink->xpixmap[idx]->pixmap, idx);
+      } else {
+        ret = XvShmPutImage (xvimagesink->xcontext->disp,
+          xvimagesink->xcontext->xv_port_id,
+          xvimagesink->xwindow->win,
+          xvimagesink->xwindow->gc, xvimage->xvimage,
+          src_input.x, src_input.y, src_input.w, src_input.h,
+          result.x, result.y, result.w, result.h, FALSE);
+        GST_LOG_OBJECT( xvimagesink, "XvShmPutImage return value [%d], disp[0x%x], gc[0x%x], xid[%d]", ret, xvimagesink->xcontext->disp, xvimagesink->xwindow->gc, xvimagesink->xwindow->win);
+      }
     } else {
       GST_LOG_OBJECT( xvimagesink, "visible is FALSE. skip this image..." );
     }
@@ -1302,6 +1982,42 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
   XSync (xvimagesink->xcontext->disp, FALSE);
 
+#ifdef HAVE_XSHM
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (ret || error_caught || xvimagesink->get_pixmap_cb) {
+    GST_DEBUG("error or pixmap_cb");
+
+    if (ret || error_caught) {
+      GST_WARNING("putimage error : ret %d, error_caught %d, pixmap cb %p, displaying buffer count %d",
+                  ret, error_caught, xvimagesink->get_pixmap_cb, xvimagesink->displaying_buffer_count);
+
+      if (xvimagesink->get_pixmap_cb) {
+        g_signal_emit (G_OBJECT (xvimagesink),
+                       gst_xvimagesink_signals[SIGNAL_FRAME_RENDER_ERROR],
+                       0,
+                       &xvimagesink->xpixmap[idx]->pixmap,
+                       &res);
+      }
+    }
+
+    /* release gem handle */
+    if (img_data && img_data->BufType == XV_BUF_TYPE_DMABUF) {
+      unsigned int gem_name[XV_BUF_PLANE_NUM] = { 0, };
+      gem_name[0] = img_data->YBuf;
+      gem_name[1] = img_data->CbBuf;
+      gem_name[2] = img_data->CrBuf;
+      _remove_displaying_buffer(xvimagesink, gem_name);
+    }
+  }
+
+  /* Reset error handler */
+  if (handler) {
+    error_caught = FALSE;
+    XSetErrorHandler (handler);
+  }
+#endif /* GST_EXT_XV_ENHANCEMENT */
+#endif /* HAVE_XSHM */
+
   g_mutex_unlock (xvimagesink->x_lock);
 
   g_mutex_unlock (xvimagesink->flow_lock);
@@ -1390,27 +2106,29 @@ gst_xvimagesink_xwindow_set_title (GstXvImageSink * xvimagesink,
 #ifdef GST_EXT_XV_ENHANCEMENT
 static XImage *make_transparent_image(Display *d, Window win, int w, int h)
 {
-  XImage             *xim;
+  XImage *xim;
 
   /* create a normal ximage */
   xim = XCreateImage(d, DefaultVisualOfScreen(DefaultScreenOfDisplay(d)),  24, ZPixmap, 0, NULL, w, h, 32, 0);
 
+  GST_INFO("ximage %p", xim);
+
   /* allocate data for it */
   if (xim) {
     xim->data = (char *)malloc(xim->bytes_per_line * xim->height);
-  }
-
-  memset(xim->data, 0x00, xim->bytes_per_line * xim->height);
-  if (!xim || !xim->data) {
-    /* failed to create XImage or allocate data memory */
-    if (xim) {
-      XDestroyImage(xim);
+    if (xim->data) {
+      memset(xim->data, 0x00, xim->bytes_per_line * xim->height);
+      return xim;
+    } else {
+      GST_ERROR("failed to alloc data - size %d", xim->bytes_per_line * xim->height);
     }
 
-    return NULL;
+    XDestroyImage(xim);
   }
 
-  return xim;
+  GST_ERROR("failed to create Ximage");
+
+  return NULL;
 }
 
 
@@ -1433,19 +2151,24 @@ static gboolean set_display_mode(GstXContext *xcontext, int set_mode)
     int count = 0;
     XvAttribute *const attr = XvQueryPortAttributes(xcontext->disp,
                                                     xcontext->xv_port_id, &count);
-    is_exist = FALSE;
-    current_port_id = xcontext->xv_port_id;
-    for (i = 0 ; i < count ; i++) {
-      if (!strcmp(attr[i].name, "_USER_WM_PORT_ATTRIBUTE_OUTPUT")) {
-        is_exist = TRUE;
-        GST_INFO("_USER_WM_PORT_ATTRIBUTE_OUTPUT[index %d] found", i);
-        break;
+    if (attr) {
+      current_port_id = xcontext->xv_port_id;
+      for (i = 0 ; i < count ; i++) {
+        if (!strcmp(attr[i].name, "_USER_WM_PORT_ATTRIBUTE_OUTPUT")) {
+          is_exist = TRUE;
+          GST_INFO("_USER_WM_PORT_ATTRIBUTE_OUTPUT[index %d] found", i);
+          break;
+        }
       }
+      XFree(attr);
+    } else {
+      GST_WARNING("XvQueryPortAttributes disp:%d, port_id:%d failed",
+                  xcontext->disp, xcontext->xv_port_id);
     }
   }
 
   if (is_exist) {
-    GST_INFO("set display mode %d", set_mode);
+    GST_DEBUG("set display mode %d", set_mode);
     atom_output = XInternAtom(xcontext->disp,
                               "_USER_WM_PORT_ATTRIBUTE_OUTPUT", False);
     ret = XvSetPortAttribute(xcontext->disp, xcontext->xv_port_id,
@@ -1461,6 +2184,687 @@ static gboolean set_display_mode(GstXContext *xcontext, int set_mode)
 
   return FALSE;
 }
+
+
+static gboolean set_csc_range(GstXContext *xcontext, int set_range)
+{
+  int ret = 0;
+  static gboolean is_exist = FALSE;
+  static XvPortID current_port_id = -1;
+  Atom atom_csc_range = None;
+
+  if (xcontext == NULL) {
+    GST_WARNING("xcontext is NULL");
+    return FALSE;
+  }
+
+  /* check once per one xv_port_id */
+  if (current_port_id != xcontext->xv_port_id) {
+    /* check whether _USER_WM_PORT_ATTRIBUTE_OUTPUT attribute is existed */
+    int i = 0;
+    int count = 0;
+    XvAttribute *const attr = XvQueryPortAttributes(xcontext->disp,
+                                                    xcontext->xv_port_id, &count);
+    if (attr) {
+      current_port_id = xcontext->xv_port_id;
+      for (i = 0 ; i < count ; i++) {
+        if (!strcmp(attr[i].name, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE")) {
+          is_exist = TRUE;
+          GST_INFO("_USER_WM_PORT_ATTRIBUTE_OUTPUT[index %d] found", i);
+          break;
+        }
+      }
+      XFree(attr);
+    } else {
+      GST_WARNING("XvQueryPortAttributes disp:%d, port_id:%d failed",
+                  xcontext->disp, xcontext->xv_port_id);
+    }
+  }
+
+  if (is_exist) {
+    GST_WARNING("set csc range %d", set_range);
+    atom_csc_range = XInternAtom(xcontext->disp,
+                                 "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE", False);
+    ret = XvSetPortAttribute(xcontext->disp, xcontext->xv_port_id,
+                             atom_csc_range, set_range);
+    if (ret == Success) {
+      return TRUE;
+    } else {
+      GST_WARNING("csc range[%d] set failed.", set_range);
+    }
+  } else {
+    GST_WARNING("_USER_WM_PORT_ATTRIBUTE_CSC_RANGE is not existed");
+  }
+
+  return FALSE;
+}
+
+
+static void drm_init(GstXvImageSink *xvimagesink)
+{
+       Display *dpy;
+       int eventBase = 0;
+       int errorBase = 0;
+       int dri2Major = 0;
+       int dri2Minor = 0;
+       char *driverName = NULL;
+       char *deviceName = NULL;
+       struct drm_auth auth_arg = {0};
+
+       xvimagesink->drm_fd = -1;
+
+       dpy = XOpenDisplay(0);
+       if (!dpy) {
+               GST_ERROR("XOpenDisplay failed errno:%d", errno);
+               return;
+       }
+
+       GST_INFO("START");
+
+       /* DRI2 */
+       if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
+               GST_ERROR("DRI2QueryExtension !!");
+               goto DRM_INIT_ERROR;
+       }
+
+       if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
+               GST_ERROR("DRI2QueryVersion !!");
+               goto DRM_INIT_ERROR;
+       }
+
+       if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
+               GST_ERROR("DRI2Connect !!");
+               goto DRM_INIT_ERROR;
+       }
+
+       if (!driverName || !deviceName) {
+               GST_ERROR("driverName or deviceName is not valid");
+               goto DRM_INIT_ERROR;
+       }
+
+       GST_INFO("Open drm device : %s", deviceName);
+
+       /* get the drm_fd though opening the deviceName */
+       xvimagesink->drm_fd = open(deviceName, O_RDWR);
+       if (xvimagesink->drm_fd < 0) {
+               GST_ERROR("cannot open drm device (%s)", deviceName);
+               goto DRM_INIT_ERROR;
+       }
+
+       /* get magic from drm to authentication */
+       if (ioctl(xvimagesink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
+               GST_ERROR("cannot get drm auth magic [drm fd %d]", xvimagesink->drm_fd);
+               goto DRM_INIT_ERROR;
+       }
+
+       if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
+               GST_ERROR("cannot get drm authentication from X");
+               goto DRM_INIT_ERROR;
+       }
+
+       XCloseDisplay(dpy);
+       free(driverName);
+       free(deviceName);
+
+       xvimagesink->bufmgr = tbm_bufmgr_init(xvimagesink->drm_fd);
+       if (xvimagesink->bufmgr == NULL) {
+               GST_ERROR_OBJECT(xvimagesink, "tbm_bufmgr_init failed");
+               goto DRM_INIT_ERROR;
+       }
+
+       GST_INFO("DONE");
+
+       return;
+
+DRM_INIT_ERROR:
+       if (xvimagesink->drm_fd >= 0) {
+               close(xvimagesink->drm_fd);
+               xvimagesink->drm_fd = -1;
+       }
+       if (dpy) {
+               XCloseDisplay(dpy);
+       }
+       if (driverName) {
+               free(driverName);
+       }
+       if (deviceName) {
+               free(deviceName);
+       }
+
+       return;
+}
+
+static void drm_fini(GstXvImageSink *xvimagesink)
+{
+       GST_WARNING_OBJECT(xvimagesink, "START");
+
+       if (xvimagesink->drm_fd >= 0) {
+               int i = 0;
+               int j = 0;
+
+               /* close remained gem handle */
+               g_mutex_lock(xvimagesink->display_buffer_lock);
+               for (i = 0 ; i < DISPLAYING_BUFFERS_MAX_NUM ; i++) {
+                       if (xvimagesink->displaying_buffers[i].gem_name[0] > 0) {
+                               GST_WARNING_OBJECT(xvimagesink, "remained buffer %p, name %u %u %u, handle %u %u %u",
+                                           xvimagesink->displaying_buffers[i].buffer,
+                                           xvimagesink->displaying_buffers[i].gem_name[0],
+                                           xvimagesink->displaying_buffers[i].gem_name[1],
+                                           xvimagesink->displaying_buffers[i].gem_name[2],
+                                           xvimagesink->displaying_buffers[i].gem_handle[0],
+                                           xvimagesink->displaying_buffers[i].gem_handle[1],
+                                           xvimagesink->displaying_buffers[i].gem_handle[2]);
+
+                               /* release flush buffer */
+                               if (xvimagesink->flush_buffer) {
+                                       if (xvimagesink->flush_buffer->gem_name[0] == xvimagesink->displaying_buffers[i].gem_name[0] &&
+                                           xvimagesink->flush_buffer->gem_name[1] == xvimagesink->displaying_buffers[i].gem_name[1] &&
+                                           xvimagesink->flush_buffer->gem_name[2] == xvimagesink->displaying_buffers[i].gem_name[2]) {
+                                               _release_flush_buffer(xvimagesink);
+                                       }
+                               } else {
+                                       GST_WARNING_OBJECT(xvimagesink, "Force Unref buffer");
+                               }
+
+                               for (j = 0 ; j < XV_BUF_PLANE_NUM ; j++) {
+                                       if (xvimagesink->displaying_buffers[i].gem_handle[j] > 0) {
+                                               drm_close_gem(xvimagesink, &(xvimagesink->displaying_buffers[i].gem_handle[j]));
+                                       }
+                                       xvimagesink->displaying_buffers[i].gem_name[j] = 0;
+                                       xvimagesink->displaying_buffers[i].dmabuf_fd[j] = 0;
+                                       xvimagesink->displaying_buffers[i].bo[j] = NULL;
+                               }
+
+                               if (xvimagesink->displaying_buffers[i].buffer) {
+                                       gst_buffer_unref(xvimagesink->displaying_buffers[i].buffer);
+                                       xvimagesink->displaying_buffers[i].buffer = NULL;
+                               }
+                       }
+               }
+               g_mutex_unlock(xvimagesink->display_buffer_lock);
+
+               GST_WARNING_OBJECT(xvimagesink, "destroy tbm buffer manager");
+               tbm_bufmgr_deinit(xvimagesink->bufmgr);
+               xvimagesink->bufmgr = NULL;
+
+               GST_WARNING_OBJECT(xvimagesink, "close drm_fd %d", xvimagesink->drm_fd);
+               close(xvimagesink->drm_fd);
+               xvimagesink->drm_fd = -1;
+       } else {
+               GST_WARNING_OBJECT(xvimagesink, "DRM device is NOT opened");
+       }
+
+       GST_WARNING_OBJECT(xvimagesink, "DONE");
+}
+
+static unsigned int drm_convert_dmabuf_gemname(GstXvImageSink *xvimagesink, unsigned int dmabuf_fd, unsigned int *gem_handle)
+{
+       int ret = 0;
+
+       struct drm_prime_handle prime_arg = {0,};
+       struct drm_gem_flink flink_arg = {0,};
+
+       if (!xvimagesink || !gem_handle) {
+               GST_ERROR("handle[%p,%p] is NULL", xvimagesink, gem_handle);
+               return 0;
+       }
+
+       if (xvimagesink->drm_fd < 0) {
+               GST_ERROR("DRM is not opened");
+               return 0;
+       }
+
+       if (dmabuf_fd <= 0) {
+               GST_LOG("Ignore wrong dmabuf fd [%u]", dmabuf_fd);
+               return 0;
+       }
+
+       prime_arg.fd = dmabuf_fd;
+       ret = ioctl(xvimagesink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg);
+       if (ret) {
+               GST_ERROR("DRM_IOCTL_PRIME_FD_TO_HANDLE failed. ret %d, dmabuf fd : %u [drm fd %d]",
+                         ret, dmabuf_fd, xvimagesink->drm_fd);
+               return 0;
+       }
+
+       *gem_handle = prime_arg.handle;
+       flink_arg.handle = prime_arg.handle;
+       ret = ioctl(xvimagesink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg);
+       if (ret) {
+               GST_ERROR("DRM_IOCTL_GEM_FLINK failed. ret %d, gem_handle %u, gem_name %u [drm fd %d]",
+                         ret, *gem_handle, flink_arg.name, xvimagesink->drm_fd);
+               return 0;
+       }
+
+       return flink_arg.name;
+}
+
+static void drm_close_gem(GstXvImageSink *xvimagesink, unsigned int *gem_handle)
+{
+       struct drm_gem_close close_arg = {0,};
+
+       if (xvimagesink->drm_fd < 0 || !gem_handle) {
+               GST_ERROR("DRM is not opened");
+               return;
+       }
+
+       if (*gem_handle <= 0) {
+               GST_DEBUG("invalid gem handle %u", *gem_handle);
+               return;
+       }
+
+       GST_LOG("Call DRM_IOCTL_GEM_CLOSE - handle %u", *gem_handle);
+
+       close_arg.handle = *gem_handle;
+       if (ioctl(xvimagesink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
+               GST_ERROR("cannot close drm gem handle %u [drm fd %d]", *gem_handle, xvimagesink->drm_fd);
+               return;
+       }
+
+       *gem_handle = 0;
+
+       return;
+}
+
+
+static void _remove_last_buffer(GstXvImageSink *xvimagesink)
+{
+  gboolean enable_last_buffer = FALSE;
+
+  if (xvimagesink == NULL) {
+    GST_ERROR("handle is NULL");
+    return;
+  }
+
+  /* get enable-last-buffer */
+  g_object_get(G_OBJECT(xvimagesink), "enable-last-buffer", &enable_last_buffer, NULL);
+
+  GST_WARNING_OBJECT(xvimagesink, "current enable-last-buffer : %d", enable_last_buffer);
+
+  /* flush if enable-last-buffer is TRUE */
+  if (enable_last_buffer) {
+    g_object_set(G_OBJECT(xvimagesink), "enable-last-buffer", FALSE, NULL);
+    g_object_set(G_OBJECT(xvimagesink), "enable-last-buffer", TRUE, NULL);
+  }
+
+  return;
+}
+
+
+static void _release_flush_buffer(GstXvImageSink *xvimagesink)
+{
+       int i = 0;
+
+       if (xvimagesink == NULL ||
+           xvimagesink->flush_buffer == NULL) {
+               GST_WARNING("handle is NULL");
+               return;
+       }
+
+       GST_WARNING_OBJECT(xvimagesink, "release FLUSH BUFFER");
+
+       for (i = 0 ; i < XV_BUF_PLANE_NUM ; i++) {
+               if (xvimagesink->flush_buffer->bo[i]) {
+                       tbm_bo_unref(xvimagesink->flush_buffer->bo[i]);
+                       xvimagesink->flush_buffer->bo[i] = NULL;
+               }
+       }
+
+       GST_WARNING_OBJECT(xvimagesink, "release FLUSH BUFFER done");
+
+       free(xvimagesink->flush_buffer);
+       xvimagesink->flush_buffer = NULL;
+
+       return;
+}
+
+
+static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_data, GstBuffer *buffer)
+{
+       int i = 0;
+       int j = 0;
+
+       if (!xvimagesink || !img_data) {
+               GST_ERROR("handle is NULL %p, %p", xvimagesink, img_data);
+               return;
+       }
+
+       /* lock display buffer mutex */
+       g_mutex_lock(xvimagesink->display_buffer_lock);
+
+       /* increase displaying buffer count */
+       xvimagesink->displaying_buffer_count++;
+
+       /* check duplicated */
+       for (i = 0 ; i < DISPLAYING_BUFFERS_MAX_NUM ; i++) {
+               if (xvimagesink->displaying_buffers[i].gem_name[0] > 0) {
+                       if ((img_data->dmabuf_fd[0] > 0 &&
+                            xvimagesink->displaying_buffers[i].dmabuf_fd[0] == img_data->dmabuf_fd[0] &&
+                            xvimagesink->displaying_buffers[i].dmabuf_fd[1] == img_data->dmabuf_fd[1] &&
+                            xvimagesink->displaying_buffers[i].dmabuf_fd[2] == img_data->dmabuf_fd[2]) ||
+                           (img_data->bo[0] &&
+                            xvimagesink->displaying_buffers[i].bo[0] == img_data->bo[0] &&
+                            xvimagesink->displaying_buffers[i].bo[1] == img_data->bo[1] &&
+                            xvimagesink->displaying_buffers[i].bo[2] == img_data->bo[2])) {
+                               /* increase ref count */
+                               xvimagesink->displaying_buffers[i].ref_count++;
+
+                               /* set buffer info */
+                               img_data->YBuf = xvimagesink->displaying_buffers[i].gem_name[0];
+                               img_data->CbBuf = xvimagesink->displaying_buffers[i].gem_name[1];
+                               img_data->CrBuf = xvimagesink->displaying_buffers[i].gem_name[2];
+
+                               if (img_data->dmabuf_fd[0] > 0) {
+                                       GST_WARNING("already converted fd [%u %u %u] name [%u %u %u]",
+                                                   img_data->dmabuf_fd[0], img_data->dmabuf_fd[1], img_data->dmabuf_fd[2],
+                                                   img_data->YBuf, img_data->CbBuf, img_data->CrBuf);
+                               } else {
+                                       GST_WARNING("already exported bo [%p %p %p] gem name [%u %u %u]",
+                                                   img_data->bo[0], img_data->bo[1], img_data->bo[2],
+                                                   img_data->YBuf, img_data->CbBuf, img_data->CrBuf);
+                               }
+
+                               /* unlock display buffer mutex */
+                               g_mutex_unlock(xvimagesink->display_buffer_lock);
+                               return;
+                       }
+               }
+       }
+
+       /* store buffer temporarily */
+       for (i = 0 ; i < DISPLAYING_BUFFERS_MAX_NUM ; i++) {
+               if (xvimagesink->displaying_buffers[i].gem_name[0] == 0) {
+                       if (buffer) {
+                               /* increase ref count of buffer */
+                               gst_buffer_ref(buffer);
+                               xvimagesink->displaying_buffers[i].buffer = buffer;
+                       }
+
+                       if (img_data->dmabuf_fd[0] > 0) {
+                               /* convert fd to name */
+                               img_data->YBuf = drm_convert_dmabuf_gemname(xvimagesink, img_data->dmabuf_fd[0], &img_data->gem_handle[0]);
+                               img_data->CbBuf = drm_convert_dmabuf_gemname(xvimagesink, img_data->dmabuf_fd[1], &img_data->gem_handle[1]);
+                               img_data->CrBuf = drm_convert_dmabuf_gemname(xvimagesink, img_data->dmabuf_fd[2], &img_data->gem_handle[2]);
+                       } else {
+                               /* export bo */
+                               if (img_data->bo[0]) {
+                                       img_data->YBuf = tbm_bo_export(img_data->bo[0]);
+                               }
+                               if (img_data->bo[1]) {
+                                       img_data->CbBuf = tbm_bo_export(img_data->bo[1]);
+                               }
+                               if (img_data->bo[2]) {
+                                       img_data->CrBuf = tbm_bo_export(img_data->bo[2]);
+                               }
+                       }
+
+                       for (j = 0 ; j < XV_BUF_PLANE_NUM ; j++) {
+                               xvimagesink->displaying_buffers[i].dmabuf_fd[j] = img_data->dmabuf_fd[j];
+                               xvimagesink->displaying_buffers[i].gem_handle[j] = img_data->gem_handle[j];
+                               xvimagesink->displaying_buffers[i].bo[j] = img_data->bo[j];
+                       }
+
+                       /* set buffer info */
+                       xvimagesink->displaying_buffers[i].gem_name[0] = img_data->YBuf;
+                       xvimagesink->displaying_buffers[i].gem_name[1] = img_data->CbBuf;
+                       xvimagesink->displaying_buffers[i].gem_name[2] = img_data->CrBuf;
+
+                       /* set ref count */
+                       xvimagesink->displaying_buffers[i].ref_count = 1;
+
+                       if (xvimagesink->displayed_buffer_count < _CHECK_DISPLAYED_BUFFER_COUNT) {
+                               GST_WARNING_OBJECT(xvimagesink, "cnt %d - add idx %d, buf %p, fd [%u %u %u], handle [%u %u %u], name [%u %u %u]",
+                                                               xvimagesink->displayed_buffer_count,
+                                                               i, xvimagesink->displaying_buffers[i].buffer,
+                                                               xvimagesink->displaying_buffers[i].dmabuf_fd[0],
+                                                               xvimagesink->displaying_buffers[i].dmabuf_fd[1],
+                                                               xvimagesink->displaying_buffers[i].dmabuf_fd[2],
+                                                               xvimagesink->displaying_buffers[i].gem_handle[0],
+                                                               xvimagesink->displaying_buffers[i].gem_handle[1],
+                                                               xvimagesink->displaying_buffers[i].gem_handle[2],
+                                                               xvimagesink->displaying_buffers[i].gem_name[0],
+                                                               xvimagesink->displaying_buffers[i].gem_name[1],
+                                                               xvimagesink->displaying_buffers[i].gem_name[2]);
+                       } else {
+                               GST_DEBUG_OBJECT(xvimagesink, "add idx %d, buf %p, fd [%u %u %u], handle [%u %u %u], name [%u %u %u]",
+                                                             i, xvimagesink->displaying_buffers[i].buffer,
+                                                             xvimagesink->displaying_buffers[i].dmabuf_fd[0],
+                                                             xvimagesink->displaying_buffers[i].dmabuf_fd[1],
+                                                             xvimagesink->displaying_buffers[i].dmabuf_fd[2],
+                                                             xvimagesink->displaying_buffers[i].gem_handle[0],
+                                                             xvimagesink->displaying_buffers[i].gem_handle[1],
+                                                             xvimagesink->displaying_buffers[i].gem_handle[2],
+                                                             xvimagesink->displaying_buffers[i].gem_name[0],
+                                                             xvimagesink->displaying_buffers[i].gem_name[1],
+                                                             xvimagesink->displaying_buffers[i].gem_name[2]);
+                       }
+
+                       /* set last added buffer index */
+                       xvimagesink->last_added_buffer_index = i;
+                       GST_LOG_OBJECT(xvimagesink, "xvimagesink->last_added_buffer_index %d", i);
+
+                       /* unlock display buffer mutex */
+                       g_mutex_unlock(xvimagesink->display_buffer_lock);
+
+                       /* get current time */
+                       gettimeofday(&xvimagesink->request_time[i], NULL);
+                       return;
+               }
+       }
+
+       /* decrease displaying buffer count */
+       xvimagesink->displaying_buffer_count--;
+
+       /* unlock display buffer mutex */
+       g_mutex_unlock(xvimagesink->display_buffer_lock);
+
+       GST_ERROR("should not be reached here. buffer slot is FULL...");
+
+       return;
+}
+
+
+static void _remove_displaying_buffer(GstXvImageSink *xvimagesink, unsigned int *gem_name)
+{
+       int i = 0;
+       int j = 0;
+
+       if (!xvimagesink || !gem_name) {
+               GST_ERROR_OBJECT(xvimagesink, "handle is NULL %p, %p", xvimagesink, gem_name);
+               return;
+       }
+
+       /* lock display buffer mutex */
+       g_mutex_lock(xvimagesink->display_buffer_lock);
+
+       if (xvimagesink->displaying_buffer_count == 0) {
+               GST_WARNING_OBJECT(xvimagesink, "there is no displaying buffer");
+               /* unlock display buffer mutex */
+               g_mutex_unlock(xvimagesink->display_buffer_lock);
+               return;
+       }
+
+       GST_DEBUG_OBJECT(xvimagesink, "gem name [%u %u %u], displaying buffer count %d",
+                 gem_name[0], gem_name[1], gem_name[2],
+                 xvimagesink->displaying_buffer_count);
+
+       for (i = 0 ; i < DISPLAYING_BUFFERS_MAX_NUM ; i++) {
+               if (xvimagesink->displaying_buffers[i].gem_name[0] == gem_name[0] &&
+                   xvimagesink->displaying_buffers[i].gem_name[1] == gem_name[1] &&
+                   xvimagesink->displaying_buffers[i].gem_name[2] == gem_name[2]) {
+                       struct timeval current_time;
+
+                       /* get current time to calculate displaying time */
+                       gettimeofday(&current_time, NULL);
+
+                       GST_DEBUG_OBJECT(xvimagesink, "buffer return time %8d us",
+                                                     (current_time.tv_sec - xvimagesink->request_time[i].tv_sec)*1000000 + \
+                                                     (current_time.tv_usec - xvimagesink->request_time[i].tv_usec));
+
+                       if (xvimagesink->displayed_buffer_count < _CHECK_DISPLAYED_BUFFER_COUNT) {
+                               xvimagesink->displayed_buffer_count++;
+                               GST_WARNING_OBJECT(xvimagesink, "cnt %d - remove idx %d, buf %p, handle [%u %u %u], name [%u %u %u]",
+                                                               xvimagesink->displayed_buffer_count,
+                                                               i, xvimagesink->displaying_buffers[i].buffer,
+                                                               xvimagesink->displaying_buffers[i].gem_handle[0],
+                                                               xvimagesink->displaying_buffers[i].gem_handle[1],
+                                                               xvimagesink->displaying_buffers[i].gem_handle[2],
+                                                               xvimagesink->displaying_buffers[i].gem_name[0],
+                                                               xvimagesink->displaying_buffers[i].gem_name[1],
+                                                               xvimagesink->displaying_buffers[i].gem_name[2]);
+                       } else {
+                               GST_DEBUG_OBJECT(xvimagesink, "remove idx %d, buf %p, handle [%u %u %u], name [%u %u %u]",
+                                                             i, xvimagesink->displaying_buffers[i].buffer,
+                                                             xvimagesink->displaying_buffers[i].gem_handle[0],
+                                                             xvimagesink->displaying_buffers[i].gem_handle[1],
+                                                             xvimagesink->displaying_buffers[i].gem_handle[2],
+                                                             xvimagesink->displaying_buffers[i].gem_name[0],
+                                                             xvimagesink->displaying_buffers[i].gem_name[1],
+                                                             xvimagesink->displaying_buffers[i].gem_name[2]);
+                       }
+
+                       /* decrease displaying buffer count */
+                       xvimagesink->displaying_buffer_count--;
+
+                       /* decrease ref count */
+                       xvimagesink->displaying_buffers[i].ref_count--;
+
+                       if (xvimagesink->displaying_buffers[i].ref_count > 0) {
+                               GST_WARNING("ref count not zero[%d], skip close gem handle",
+                                           xvimagesink->displaying_buffers[i].ref_count);
+                               break;
+                       }
+
+                       /* release flush buffer */
+                       if (xvimagesink->flush_buffer) {
+                               if (xvimagesink->flush_buffer->gem_name[0] == gem_name[0] &&
+                                   xvimagesink->flush_buffer->gem_name[1] == gem_name[1] &&
+                                   xvimagesink->flush_buffer->gem_name[2] == gem_name[2]) {
+                                       _release_flush_buffer(xvimagesink);
+                               }
+                       }
+
+                       for (j = 0 ; j < XV_BUF_PLANE_NUM ; j++) {
+                               if (xvimagesink->displaying_buffers[i].gem_handle[j] > 0) {
+                                       drm_close_gem(xvimagesink, &(xvimagesink->displaying_buffers[i].gem_handle[j]));
+                               }
+                               xvimagesink->displaying_buffers[i].gem_name[j] = 0;
+                               xvimagesink->displaying_buffers[i].dmabuf_fd[j] = 0;
+                               xvimagesink->displaying_buffers[i].bo[j] = NULL;
+                       }
+
+                       /* reset last_added_buffer_index */
+                       if (xvimagesink->displaying_buffer_count < 1) {
+                               xvimagesink->last_added_buffer_index = -1;
+                               GST_DEBUG_OBJECT(xvimagesink, "displaying_buffer_count %d",
+                                                               xvimagesink->displaying_buffer_count);
+                       }
+
+                       if (xvimagesink->displaying_buffers[i].buffer) {
+                               gst_buffer_unref(xvimagesink->displaying_buffers[i].buffer);
+                               xvimagesink->displaying_buffers[i].buffer = NULL;
+                       } else {
+                               GST_WARNING("no buffer to unref");
+                       }
+                       break;
+               }
+       }
+
+       /* unlock display buffer mutex */
+       g_mutex_unlock(xvimagesink->display_buffer_lock);
+
+       return;
+}
+
+
+static int _is_connected_to_external_display(GstXvImageSink *xvimagesink)
+{
+  Atom type_ret = 0;
+  int i = 0;
+  int ret = 0;
+  int size_ret = 0;
+  unsigned long num_ret = 0;
+  unsigned long bytes = 0;
+  unsigned char *prop_ret = NULL;
+  unsigned int data = 0;
+  int (*handler) (Display *, XErrorEvent *) = NULL;
+  Atom atom_output_external;
+
+  atom_output_external = XInternAtom(xvimagesink->xcontext->disp,
+                                       "XV_OUTPUT_EXTERNAL", False);
+  if (atom_output_external != None) {
+    /* set error handler */
+    error_caught = FALSE;
+    handler = XSetErrorHandler(gst_xvimagesink_handle_xerror);
+
+    ret = XGetWindowProperty(xvimagesink->xcontext->disp,
+                             xvimagesink->xwindow->win,
+                             atom_output_external, 0, 0x7fffffff,
+                             False, XA_CARDINAL, &type_ret, &size_ret,
+                             &num_ret, &bytes, &prop_ret);
+    XSync(xvimagesink->xcontext->disp, FALSE);
+    if (ret != Success || error_caught) {
+      GST_WARNING_OBJECT(xvimagesink, "XGetWindowProperty failed");
+      if (prop_ret) {
+        XFree(prop_ret);
+      }
+      if (error_caught) {
+        GST_WARNING_OBJECT(xvimagesink, "error caught in XGetWindowProperty()");
+      }
+      if (handler) {
+        error_caught = FALSE;
+        XSetErrorHandler (handler);
+      }
+      return False;
+    }
+
+    if (handler) {
+      error_caught = FALSE;
+      XSetErrorHandler (handler);
+    }
+
+    if (!num_ret) {
+      GST_WARNING_OBJECT(xvimagesink, "XGetWindowProperty num_ret failed");
+      if (prop_ret) {
+        XFree(prop_ret);
+      }
+      return False;
+    }
+
+    if (prop_ret) {
+      switch (size_ret) {
+      case 8:
+        for (i = 0 ; i < num_ret ; i++) {
+          (&data)[i] = prop_ret[i];
+        }
+        break;
+      case 16:
+        for (i = 0 ; i < num_ret ; i++) {
+          ((unsigned short *)&data)[i] = ((unsigned short *)prop_ret)[i];
+        }
+        break;
+      case 32:
+        for (i = 0 ; i < num_ret ; i++) {
+          ((unsigned int *)&data)[i] = ((unsigned long *)prop_ret)[i];
+        }
+        break;
+      }
+      XFree(prop_ret);
+      prop_ret = NULL;
+
+      GST_WARNING_OBJECT(xvimagesink, "external display %d", data);
+
+      return (int)data;
+    } else {
+      GST_WARNING_OBJECT(xvimagesink, "prop_ret is NULL");
+      return False;
+    }
+  } else {
+    GST_WARNING_OBJECT(xvimagesink, "get XV_OUTPUT_EXTERNAL atom failed");
+  }
+
+  return False;
+}
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
 /* This function handles a GstXWindow creation
@@ -1473,7 +2877,7 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
   XGCValues values;
 #ifdef GST_EXT_XV_ENHANCEMENT
   XSetWindowAttributes win_attr;
-  XWindowAttributes root_attr;
+  XWindowAttributes root_attr = {0 , };
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
@@ -1492,7 +2896,8 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
     xvimagesink->render_rect.h = xwindow->height = width;
   }
 
-  XGetWindowAttributes(xvimagesink->xcontext->disp, xvimagesink->xcontext->root, &root_attr);
+  if(!xvimagesink->is_pixmap)
+    XGetWindowAttributes(xvimagesink->xcontext->disp, xvimagesink->xcontext->root, &root_attr);
 
   if (xwindow->width > root_attr.width) {
     GST_INFO_OBJECT(xvimagesink, "Width[%d] is bigger than Max width. Set Max[%d].",
@@ -1521,7 +2926,8 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
 
   /* Make window manager not to change window size as Full screen */
   win_attr.override_redirect = True;
-  XChangeWindowAttributes(xvimagesink->xcontext->disp, xwindow->win, CWOverrideRedirect, &win_attr);
+  if(!xvimagesink->is_pixmap)
+    XChangeWindowAttributes(xvimagesink->xcontext->disp, xwindow->win, CWOverrideRedirect, &win_attr);
 #else /* GST_EXT_XV_ENHANCEMENT */
   xvimagesink->render_rect.w = width;
   xvimagesink->render_rect.h = height;
@@ -1546,10 +2952,17 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
 
   if (xvimagesink->handle_events) {
     Atom wm_delete;
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+    XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xcontext->root, StructureNotifyMask | SubstructureNotifyMask);
+    XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
+         StructureNotifyMask | PointerMotionMask | KeyPressMask |
+         KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask);
+#else
     XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
         StructureNotifyMask | PointerMotionMask | KeyPressMask |
         KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
+#endif
+
 
     /* Tell the window manager we'd like delete client messages instead of
      * being killed */
@@ -1607,12 +3020,35 @@ gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink,
   g_free (xwindow);
 }
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+/* This function destroys a GstXWindow */
+static void
+gst_xvimagesink_xpixmap_destroy (GstXvImageSink * xvimagesink,
+    GstXPixmap * xpixmap)
+{
+  g_return_if_fail (xpixmap != NULL);
+  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
+
+  g_mutex_lock (xvimagesink->x_lock);
+
+  XSelectInput (xvimagesink->xcontext->disp, xpixmap->pixmap, 0);
+
+  XFreeGC (xvimagesink->xcontext->disp, xpixmap->gc);
+
+  XSync (xvimagesink->xcontext->disp, FALSE);
+
+  g_mutex_unlock (xvimagesink->x_lock);
+
+  g_free (xpixmap);
+}
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
 static void
 gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink)
 {
 #ifdef GST_EXT_XV_ENHANCEMENT
   Window root_window, child_window;
-  XWindowAttributes root_attr;
+  XWindowAttributes root_attr = {0 , };
 
   int cur_win_x = 0;
   int cur_win_y = 0;
@@ -1644,18 +3080,21 @@ gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink)
   xvimagesink->xwindow->height = cur_win_height;
 
   /* Get absolute coordinates of current window */
-  XTranslateCoordinates( xvimagesink->xcontext->disp,
-    xvimagesink->xwindow->win,
-    root_window,
-    0, 0,
-    &cur_win_x, &cur_win_y, // relative x, y to root window == absolute x, y
-    &child_window );
+  if(!xvimagesink->is_pixmap) {
+    XTranslateCoordinates( xvimagesink->xcontext->disp,
+      xvimagesink->xwindow->win,
+      root_window,
+      0, 0,
+      &cur_win_x, &cur_win_y, // relative x, y to root window == absolute x, y
+      &child_window );
+  }
 
   xvimagesink->xwindow->x = cur_win_x;
   xvimagesink->xwindow->y = cur_win_y;
 
   /* Get size of root window == size of screen */
-  XGetWindowAttributes(xvimagesink->xcontext->disp, root_window, &root_attr);
+  if(!xvimagesink->is_pixmap)
+    XGetWindowAttributes(xvimagesink->xcontext->disp, root_window, &root_attr);
 
   xvimagesink->scr_w = root_attr.width;
   xvimagesink->scr_h = root_attr.height;
@@ -1665,6 +3104,16 @@ gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink)
     xvimagesink->render_rect.w = cur_win_width;
     xvimagesink->render_rect.h = cur_win_height;
   }
+  if (xvimagesink->scr_w != xvimagesink->xwindow->width ||
+    xvimagesink->scr_h != xvimagesink->xwindow->height) {
+    xvimagesink->is_multi_window = TRUE;
+    g_signal_emit_by_name(G_OBJECT (xvimagesink), "multiwindow-active", xvimagesink->is_multi_window);
+    GST_INFO_OBJECT(xvimagesink, "It may be multi-window scenario");
+  } else {
+    xvimagesink->is_multi_window = FALSE;
+    g_signal_emit_by_name(G_OBJECT (xvimagesink), "multiwindow-active", xvimagesink->is_multi_window);
+    GST_INFO_OBJECT(xvimagesink, "It may be full-window scenario");
+  }
 
   GST_LOG_OBJECT(xvimagesink, "screen size %dx%d, current window geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
     xvimagesink->scr_w, xvimagesink->scr_h,
@@ -1693,14 +3142,24 @@ static void
 gst_xvimagesink_xwindow_clear (GstXvImageSink * xvimagesink,
     GstXWindow * xwindow)
 {
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (xvimagesink->is_subpicture_format)
+    return;
+#endif
   g_return_if_fail (xwindow != NULL);
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
 
   g_mutex_lock (xvimagesink->x_lock);
+#ifdef GST_EXT_XV_ENHANCEMENT
+  GST_WARNING_OBJECT(xvimagesink, "CALL XvStopVideo");
+#endif /* GST_EXT_XV_ENHANCEMENT */
 
   XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
       xwindow->win);
-#ifndef GST_EXT_XV_ENHANCEMENT
+#ifdef GST_EXT_XV_ENHANCEMENT
+#if 0
+  /* NOTE : it should be enabled in pixmap buffer case,
+            if we can check whether if it is a pixmap or a window by X API */
   /* Preview area is not updated before other UI is updated in the screen. */
   XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
       xvimagesink->xcontext->black);
@@ -1708,6 +3167,7 @@ gst_xvimagesink_xwindow_clear (GstXvImageSink * xvimagesink,
   XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
       xvimagesink->render_rect.x, xvimagesink->render_rect.y,
       xvimagesink->render_rect.w, xvimagesink->render_rect.h);
+#endif
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   XSync (xvimagesink->xcontext->disp, FALSE);
@@ -1798,12 +3258,21 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
 
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  GST_LOG("check x event");
+  Atom sc_status_atom = XInternAtom (xvimagesink->xcontext->disp, STR_ATOM_SCRNCONF_STATUS, FALSE);
+  Atom external_atom = XInternAtom (xvimagesink->xcontext->disp, "XV_OUTPUT_EXTERNAL", FALSE);
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
   /* Handle Interaction, produces navigation events */
 
   /* We get all pointer motion events, only the last position is
      interesting. */
   g_mutex_lock (xvimagesink->flow_lock);
   g_mutex_lock (xvimagesink->x_lock);
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (xvimagesink->xcontext->disp) {
+#endif //GST_EXT_XV_ENHANCEMENT
   while (XCheckWindowEvent (xvimagesink->xcontext->disp,
           xvimagesink->xwindow->win, PointerMotionMask, &e)) {
     g_mutex_unlock (xvimagesink->x_lock);
@@ -1821,6 +3290,9 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
     g_mutex_lock (xvimagesink->flow_lock);
     g_mutex_lock (xvimagesink->x_lock);
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
+  }
+#endif //GST_EXT_XV_ENHANCEMENT
   if (pointer_moved) {
     g_mutex_unlock (xvimagesink->x_lock);
     g_mutex_unlock (xvimagesink->flow_lock);
@@ -1891,7 +3363,6 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
     g_mutex_lock (xvimagesink->flow_lock);
     g_mutex_lock (xvimagesink->x_lock);
   }
-
   /* Handle Expose */
   while (XCheckWindowEvent (xvimagesink->xcontext->disp,
           xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
@@ -1902,9 +3373,12 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
       case ConfigureNotify:
         g_mutex_unlock (xvimagesink->x_lock);
 #ifdef GST_EXT_XV_ENHANCEMENT
-        GST_INFO_OBJECT (xvimagesink, "Call gst_xvimagesink_xwindow_update_geometry!");
+        GST_WARNING("Call gst_xvimagesink_xwindow_update_geometry!");
 #endif /* GST_EXT_XV_ENHANCEMENT */
         gst_xvimagesink_xwindow_update_geometry (xvimagesink);
+#ifdef GST_EXT_XV_ENHANCEMENT
+        GST_WARNING("Return gst_xvimagesink_xwindow_update_geometry!");
+#endif /* GST_EXT_XV_ENHANCEMENT */
         g_mutex_lock (xvimagesink->x_lock);
         configured = TRUE;
         break;
@@ -1917,104 +3391,333 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
     g_mutex_unlock (xvimagesink->x_lock);
     g_mutex_unlock (xvimagesink->flow_lock);
 
-    gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
+    gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
+
+    g_mutex_lock (xvimagesink->flow_lock);
+    g_mutex_lock (xvimagesink->x_lock);
+  }
+
+  /* Handle Display events */
+  while (XPending (xvimagesink->xcontext->disp)) {
+    XNextEvent (xvimagesink->xcontext->disp, &e);
+    switch (e.type) {
+      case ClientMessage:{
+#ifdef GST_EXT_XV_ENHANCEMENT
+        XClientMessageEvent *cme = (XClientMessageEvent *)&e;
+        Atom buffer_atom = XInternAtom(xvimagesink->xcontext->disp, "XV_RETURN_BUFFER", False);
+        Atom qp_state_atom = XInternAtom(xvimagesink->xcontext->disp, "_E_ILLUME_QUICKPANEL_STATE", False);
+        Atom qp_on_atom = XInternAtom(xvimagesink->xcontext->disp, "_E_ILLUME_QUICKPANEL_ON", False);
+        Atom qp_off_atom = XInternAtom(xvimagesink->xcontext->disp, "_E_ILLUME_QUICKPANEL_OFF", False);
+#endif /* GST_EXT_XV_ENHANCEMENT */
+        Atom wm_delete;
+
+#ifdef GST_EXT_XV_ENHANCEMENT
+        GST_LOG_OBJECT(xvimagesink, "message type %d, buffer atom %d", cme->message_type, buffer_atom);
+        if (cme->message_type == buffer_atom) {
+          unsigned int gem_name[XV_BUF_PLANE_NUM] = { 0, };
+
+          GST_DEBUG("data.l[0] -> %d, data.l[1] -> %d",
+                    cme->data.l[0], cme->data.l[1]);
+
+          gem_name[0] = cme->data.l[0];
+          gem_name[1] = cme->data.l[1];
+
+          _remove_displaying_buffer(xvimagesink, gem_name);
+          break;
+        } else if (cme->message_type == sc_status_atom) {
+          int stat = cme->data.s[0];
+          if (stat == UTILX_SCRNCONF_STATUS_NULL) {
+            GST_WARNING ("get UTILX_SCRNCONF_STATUS_NULL event\n");
+            check_hdmi_connected(xvimagesink);
+          } else if (stat == UTILX_SCRNCONF_STATUS_CONNECT) {
+            GST_WARNING ("get UTILX_SCRNCONF_STATUS_CONNECT event\n");
+            check_hdmi_connected(xvimagesink);
+          } else if (stat == UTILX_SCRNCONF_STATUS_ACTIVE) {
+            GST_WARNING ("get UTILX_SCRNCONF_STATUS_ACTIVE event\n");
+            g_signal_emit_by_name(G_OBJECT (xvimagesink), "display-status", DISPLAY_STATUS_HDMI_ACTIVE);
+            check_hdmi_connected(xvimagesink);
+          } else {
+            GST_INFO ("Wrong status\n");
+          }
+          break;
+        } else if (cme->message_type == qp_state_atom) {
+          if ((Atom) cme->data.l[0] == qp_on_atom) {
+            /* quick panel on */
+            GST_WARNING_OBJECT(xvimagesink, "quick panel is ON");
+            xvimagesink->is_quick_panel_on = TRUE;
+            g_signal_emit_by_name(G_OBJECT (xvimagesink), "quick-panel-on", TRUE);
+          } else if ((Atom) cme->data.l[0] == qp_off_atom) {
+            /* quick panel off */
+            GST_WARNING_OBJECT(xvimagesink, "quick panel is OFF");
+            xvimagesink->is_quick_panel_on = FALSE;
+            g_signal_emit_by_name(G_OBJECT (xvimagesink), "quick-panel-on", FALSE);
+          }
+          break;
+        }
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
+        wm_delete = XInternAtom (xvimagesink->xcontext->disp,
+            "WM_DELETE_WINDOW", True);
+        if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) {
+          /* Handle window deletion by posting an error on the bus */
+          GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND,
+              ("Output window was closed"), (NULL));
+
+          g_mutex_unlock (xvimagesink->x_lock);
+          gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
+          xvimagesink->xwindow = NULL;
+          g_mutex_lock (xvimagesink->x_lock);
+        }
+        break;
+      }
+#ifdef GST_EXT_XV_ENHANCEMENT
+      case VisibilityNotify:
+        if (xvimagesink->xwindow &&
+            (e.xvisibility.window == xvimagesink->xwindow->win)) {
+          if (e.xvisibility.state == VisibilityFullyObscured) {
+            Atom atom_stream;
+
+            GST_WARNING_OBJECT(xvimagesink, "current window is FULLY HIDED");
+
+            xvimagesink->is_hided = TRUE;
+            g_signal_emit_by_name(G_OBJECT (xvimagesink), "hided-window", TRUE);
+            if (!_is_connected_to_external_display(xvimagesink)) {
+              GST_WARNING_OBJECT(xvimagesink, "no external display, calling XvStopVideo()");
+              XvStopVideo(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xwindow->win);
+              XSync(xvimagesink->xcontext->disp, FALSE);
+            } else {
+              if (GST_STATE(xvimagesink) == GST_STATE_PLAYING || xvimagesink->keep_external_fullscreen_prev) {
+                GST_WARNING_OBJECT(xvimagesink, "external display is enabled. skip XvStopVideo()");
+              } else {
+                GST_WARNING_OBJECT(xvimagesink, "external display is enabled, but not in the middle of playing, calling XvStopVideo()");
+                XvStopVideo(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xwindow->win);
+                XSync(xvimagesink->xcontext->disp, FALSE);
+              }
+            }
+          } else {
+            GST_INFO_OBJECT(xvimagesink, "current window is SHOWN");
+
+            if (xvimagesink->is_hided) {
+              g_mutex_unlock(xvimagesink->x_lock);
+              g_mutex_unlock(xvimagesink->flow_lock);
+
+              xvimagesink->is_hided = FALSE;
+              g_signal_emit_by_name(G_OBJECT (xvimagesink), "hided-window", FALSE);
+              gst_xvimagesink_expose(GST_X_OVERLAY(xvimagesink));
+
+              g_mutex_lock(xvimagesink->flow_lock);
+              g_mutex_lock(xvimagesink->x_lock);
+            } else {
+              GST_INFO_OBJECT(xvimagesink, "current window is not HIDED, skip this event");
+            }
+          }
+        }
+        break;
+
+      case PropertyNotify:
+        {
+          XPropertyEvent *noti = (XPropertyEvent *)&e;
+          if(xvimagesink->xwindow) {
+            if (noti->window == xvimagesink->xwindow->win && noti->atom == external_atom) {
+              int value = 0;
+              get_window_prop_card32_property (xvimagesink->xcontext->disp,
+                                               xvimagesink->xwindow->win,
+                                               external_atom, XA_CARDINAL,
+                                               (unsigned int*)&value, 1);
+              if (value) {
+                // If value is 1, video will be displayed only on external display.
+                // video won't be displayed on LCD.
+                g_signal_emit_by_name(G_OBJECT (xvimagesink), "display-status", DISPLAY_STATUS_UNKNOWN_ACTIVE);
+                if(xvimagesink->external_width==0 && xvimagesink->external_height==0) {
+                  xvimagesink->external_width = 1920;
+                  xvimagesink->external_height = 1080;
+                  GST_WARNING("connected unknown external display");
+                }
+              } else {
+                g_signal_emit_by_name(G_OBJECT (xvimagesink), "display-status", DISPLAY_STATUS_NULL); //NULL
+                if(xvimagesink->external_width!=0 || xvimagesink->external_height!=0) {
+                  xvimagesink->external_width = 0;
+                  xvimagesink->external_height = 0;
+                  GST_WARNING("disconnected external display");
+                }
+              }
+
+              g_signal_emit_by_name(G_OBJECT (xvimagesink), "external-resolution", xvimagesink->external_width, xvimagesink->external_height);
+              GST_INFO ("external device : %s\n", (value)?"on":"off");
+            }
+          }
+          break;
+       }
+
+#endif /* GST_EXT_XV_ENHANCEMENT */
+      default:
+        break;
+    }
+  }
+  g_mutex_unlock (xvimagesink->x_lock);
+  g_mutex_unlock (xvimagesink->flow_lock);
+}
+#ifdef GST_EXT_XV_ENHANCEMENT
+static int
+get_window_prop_card32_property (Display* dpy, Window win, Atom atom, Atom type,
+                                 unsigned int *val, unsigned int len)
+{
+  unsigned char* prop_ret;
+  Atom type_ret;
+  unsigned long bytes_after, num_ret;
+  int format_ret;
+  unsigned int i;
+  int num;
+  int ret;
+  int (*handler) (Display *, XErrorEvent *) = NULL;
+
+  prop_ret = NULL;
+
+  /* set error handler */
+  error_caught = FALSE;
+  handler = XSetErrorHandler(gst_xvimagesink_handle_xerror);
+
+  ret = XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
+                           type, &type_ret, &format_ret, &num_ret,
+                           &bytes_after, &prop_ret);
+  XSync(dpy, FALSE);
+  if (ret != Success || error_caught) {
+    GST_WARNING("XGetWindowProperty failed [%d, %d]", ret, error_caught);
+    if (handler) {
+      error_caught = FALSE;
+      XSetErrorHandler (handler);
+    }
+    return -1;
+  }
+
+  if (handler) {
+    error_caught = FALSE;
+    XSetErrorHandler(handler);
+  }
+
+  if (type_ret != type || format_ret != 32)
+    num = -1;
+  else if (num_ret == 0 || !prop_ret)
+    num = 0;
+  else
+  {
+    if (num_ret < len)
+      len = num_ret;
+    for (i = 0; i < len; i++)
+      val[i] = ((unsigned long *)prop_ret)[i];
+    num = len;
+  }
+
+  if (prop_ret)
+    XFree(prop_ret);
 
-    g_mutex_lock (xvimagesink->flow_lock);
-    g_mutex_lock (xvimagesink->x_lock);
+  return num;
+}
+
+static void check_hdmi_connected(GstXvImageSink *xvimagesink)
+{
+  char *str_output = NULL;
+  char *str_resolution = NULL;
+  int external[2];
+  int cnt = 0;
+  char** list = NULL;
+  char** walk = NULL;
+
+  UtilxScrnConf *scrnconf = utilx_scrnconf_allocate();
+  if (!scrnconf)
+  {
+    GST_WARNING ("fail to allocate scrnconf");
+    return;
   }
+  utilx_scrnconf_get_info (xvimagesink->xcontext->disp, scrnconf);
 
-  /* Handle Display events */
-  while (XPending (xvimagesink->xcontext->disp)) {
-    XNextEvent (xvimagesink->xcontext->disp, &e);
+  str_output = scrnconf->str_output;
 
-    switch (e.type) {
-      case ClientMessage:{
-#ifdef GST_EXT_XV_ENHANCEMENT
-        int active_pid, deactive_pid;
-        Atom active_win_atom;
-        Atom deactive_win_atom;
-        Atom atom_stream;
-#endif /* GST_EXT_XV_ENHANCEMENT */
-        Atom wm_delete;
+  if (scrnconf->status == UTILX_SCRNCONF_STATUS_CONNECT)
+  {
+    GST_INFO("CONNECT");
+  }
+  else if (scrnconf->status == UTILX_SCRNCONF_STATUS_ACTIVE)
+  {
+     GST_INFO("ACTIVE");
 
-        wm_delete = XInternAtom (xvimagesink->xcontext->disp,
-            "WM_DELETE_WINDOW", True);
-        if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) {
-          /* Handle window deletion by posting an error on the bus */
-          GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND,
-              ("Output window was closed"), (NULL));
+    list = g_strsplit(scrnconf->str_resolution, "x", 2);
 
-          g_mutex_unlock (xvimagesink->x_lock);
-          gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
-          xvimagesink->xwindow = NULL;
-          g_mutex_lock (xvimagesink->x_lock);
-        }
-#ifdef GST_EXT_XV_ENHANCEMENT
-        GST_INFO_OBJECT( xvimagesink, "message type : %d", e.xclient.message_type );
+    if (!list)
+    {
+        if (scrnconf)
+        utilx_scrnconf_free (scrnconf);
+        return;
+    }
+    for(walk = list; *walk; walk++)
+    {
+      external[cnt++] = atoi(*walk);
+    }
+    if (cnt!=2) {
+      GST_WARNING("data error");
+      if(scrnconf)
+        utilx_scrnconf_free (scrnconf);
+      g_strfreev(list);
+      return;
+    } else {
+      xvimagesink->external_width = external[0];
+      xvimagesink->external_height = external[1];
+      g_strfreev(list);
+    }
+    GST_INFO("external display : %d * %d", xvimagesink->external_width, xvimagesink->external_height);
+    g_signal_emit_by_name(G_OBJECT (xvimagesink), "external-resolution", xvimagesink->external_width, xvimagesink->external_height);
+  }
+  else
+  {
+     GST_INFO("NULL");
+  }
 
-        active_win_atom   = XInternAtom (xvimagesink->xcontext->disp, "_X_ILLUME_ACTIVATE_WINDOW", False);
-        deactive_win_atom = XInternAtom (xvimagesink->xcontext->disp, "_X_ILLUME_DEACTIVATE_WINDOW", False);
+  str_resolution = scrnconf->str_resolution;
 
-        if (!active_win_atom || !deactive_win_atom) {
-          GST_WARNING_OBJECT( xvimagesink, "Can NOT get active[%d] or deactive[%d] win atom",
-                                           active_win_atom, deactive_win_atom );
-        } else {
-          if (e.xclient.message_type == deactive_win_atom) {
-            /* Window is DEACTIVATED */
-            /* Get pid of activated/deactivated window */
-            active_pid = e.xclient.data.l[1];
-            deactive_pid = e.xclient.data.l[3];
-
-            if (active_pid != deactive_pid) {
-              GST_INFO_OBJECT( xvimagesink, "XClientMessage : Window DEACTIVATED" );
-
-              xvimagesink->is_hided = TRUE;
-              atom_stream = XInternAtom( xvimagesink->xcontext->disp,
-                                              "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False );
-              if (atom_stream != None) {
-                if (XvSetPortAttribute(xvimagesink->xcontext->disp,
-                                       xvimagesink->xcontext->xv_port_id,
-                                       atom_stream, 0 ) != Success) {
-                  GST_WARNING_OBJECT( xvimagesink, "STREAM OFF failed" );
-                }
-                XSync( xvimagesink->xcontext->disp, FALSE );
-              }
-            } else {
-              GST_INFO_OBJECT( xvimagesink, "Window is DEACTIVATED, but same process. so Do not clear screen." );
-            }
-          } else if (e.xclient.message_type == active_win_atom) {
-            /* Window is ACTIVATED */
-            /* Get pid of activated/deactivated window */
-            active_pid = e.xclient.data.l[1];
-            deactive_pid = e.xclient.data.l[3];
+  if (scrnconf->dispmode == UTILX_SCRNCONF_DISPMODE_CLONE)
+  {
+     GST_INFO("CLONE mode");
+  }
+  else if (scrnconf->dispmode == UTILX_SCRNCONF_DISPMODE_EXTENDED)
+  {
+    GST_INFO("EXTENDED mode");
+  }
+  else
+  {
+    GST_INFO("NULL mode");
+  }
 
-            if (active_pid != deactive_pid) {
-              GST_INFO_OBJECT( xvimagesink, "XClientMessage : Window ACTIVATED" );
+  GST_INFO ("[Display status] : %s, %s\n", str_output, str_resolution);
 
-              g_mutex_unlock (xvimagesink->x_lock);
-              g_mutex_unlock (xvimagesink->flow_lock);
+  if(scrnconf)
+    utilx_scrnconf_free (scrnconf);
 
-              xvimagesink->is_hided = FALSE;
-              gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
+}
 
-              g_mutex_lock (xvimagesink->flow_lock);
-              g_mutex_lock (xvimagesink->x_lock);
-            } else {
-              GST_INFO_OBJECT( xvimagesink, "Window is ACTIVATED, but same process. so Do not redraw screen." );
-            }
-          }
-        }
-#endif /* GST_EXT_XV_ENHANCEMENT */
-        break;
+static gboolean
+check_supportable_port_attr(GstXvImageSink * xvimagesink, gchar* attr_name)
+{
+  int i = 0;
+  int count = 0;
+
+  XvAttribute *attr = XvQueryPortAttributes(xvimagesink->xcontext->disp,
+                                            xvimagesink->xcontext->xv_port_id, &count);
+  if (attr) {
+    for (i = 0 ; i < count ; i++) {
+      if (!strcmp(attr[i].name, attr_name)) {
+        GST_INFO("%s[index %d] found", attr_name, i);
+        XFree(attr);
+        return TRUE;
       }
-      default:
-        break;
     }
+    XFree(attr);
+  } else {
+    GST_WARNING("XvQueryPortAttributes disp:%d, port_id:%d failed",
+                xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id);
   }
-
-  g_mutex_unlock (xvimagesink->x_lock);
-  g_mutex_unlock (xvimagesink->flow_lock);
+  return FALSE;
 }
+#endif //GST_EXT_XV_ENHANCEMENT
 
 static void
 gst_lookup_xv_port_from_adaptor (GstXContext * xcontext,
@@ -2045,6 +3748,40 @@ gst_lookup_xv_port_from_adaptor (GstXContext * xcontext,
   }
 }
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+static void
+gst_lookup_xv_port_for_subtitle (GstXContext * xcontext,
+    XvAdaptorInfo * adaptors, guint adaptor_no, guint nb_adaptors)
+{
+  int i;
+  if (!adaptors)
+    return;
+  for (i = 0; i < nb_adaptors; i++)
+  {
+    int min, max;
+    if (!(adaptors[i].type & XvOutputMask) ||
+        !(adaptors[i].type & XvStillMask))
+        continue;
+    min = adaptors[i].base_id;
+    max = adaptors[i].base_id + adaptors[i].num_ports;
+    for (adaptors[adaptor_no].num_ports = min; adaptors[adaptor_no].num_ports < max ; adaptors[adaptor_no].num_ports++)
+    {
+      if (XvGrabPort (xcontext->disp, adaptors[adaptor_no].num_ports, 0) == Success)
+      {
+        GST_INFO ("========================================");
+        GST_INFO ("XvGrabPort  success : %ld", adaptors[adaptor_no].num_ports);
+        GST_INFO ("========================================");
+        xcontext->xv_port_id = adaptors[adaptor_no].num_ports;
+        return;
+      }
+      GST_WARNING ("fail : grab port(%ld)\n", adaptors[adaptor_no].num_ports);
+      usleep(10000);
+    }
+  }
+}
+#endif
+
+
 /* This function generates a caps with all supported format by the first
    Xv grabable port we find. We store each one of the supported formats in a
    format list and append the format to a newly created caps that we return
@@ -2085,7 +3822,7 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
 
   xcontext->xv_port_id = 0;
 
-  GST_DEBUG ("Found %u XV adaptor(s)", xcontext->nb_adaptors);
+  GST_DEBUG_OBJECT(xvimagesink, "Found %u XV adaptor(s)", xcontext->nb_adaptors);
 
   xcontext->adaptors =
       (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
@@ -2098,14 +3835,27 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
   if (xvimagesink->adaptor_no >= 0 &&
       xvimagesink->adaptor_no < xcontext->nb_adaptors) {
     /* Find xv port from user defined adaptor */
-    gst_lookup_xv_port_from_adaptor (xcontext, adaptors,
-        xvimagesink->adaptor_no);
+#ifdef GST_EXT_XV_ENHANCEMENT
+    if(!xvimagesink->subpicture)
+#endif
+      gst_lookup_xv_port_from_adaptor (xcontext, adaptors, xvimagesink->adaptor_no);
+#ifdef GST_EXT_XV_ENHANCEMENT
+    else
+      gst_lookup_xv_port_for_subtitle (xcontext, adaptors, xvimagesink->adaptor_no, xcontext->nb_adaptors);
+#endif
   }
 
   if (!xcontext->xv_port_id) {
     /* Now search for an adaptor that supports XvImageMask */
     for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
-      gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
+#ifdef GST_EXT_XV_ENHANCEMENT
+      if(!xvimagesink->subpicture)
+#endif
+        gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
+#ifdef GST_EXT_XV_ENHANCEMENT
+      else
+        gst_lookup_xv_port_for_subtitle (xcontext, adaptors, i, xcontext->nb_adaptors);
+#endif
       xvimagesink->adaptor_no = i;
     }
   }
@@ -2225,7 +3975,9 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
   }
 
   XvFreeEncodingInfo (encodings);
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+if (!xvimagesink->subpicture) {
+#endif
   /* We get all image formats supported by our port */
   formats = XvListImageFormats (xcontext->disp,
       xcontext->xv_port_id, &nb_formats);
@@ -2262,6 +4014,9 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
         }
 
         format_caps = gst_caps_new_simple ("video/x-raw-rgb",
+#ifdef GST_EXT_XV_ENHANCEMENT
+            "format", GST_TYPE_FOURCC, formats[i].id,
+#endif /* GST_EXT_XV_ENHANCEMENT */
             "endianness", G_TYPE_INT, endianness,
             "depth", G_TYPE_INT, fmt->depth,
             "bpp", G_TYPE_INT, fmt->bits_per_pixel,
@@ -2324,6 +4079,9 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
         ("No supported format found"));
     return NULL;
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
+} //subpicture
+#endif
 
   return caps;
 }
@@ -2340,8 +4098,13 @@ gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink)
     if (xvimagesink->xwindow) {
       gst_xvimagesink_handle_xevents (xvimagesink);
     }
+
+#ifdef GST_EXT_XV_ENHANCEMENT
+    g_usleep (_EVENT_THREAD_CHECK_INTERVAL);
+#else /* GST_EXT_XV_ENHANCEMENT */
     /* FIXME: do we want to align this with the framerate or anything else? */
     g_usleep (G_USEC_PER_SEC / 20);
+#endif /* GST_EXT_XV_ENHANCEMENT */
 
     GST_OBJECT_LOCK (xvimagesink);
   }
@@ -2394,6 +4157,46 @@ gst_xvimagesink_manage_event_thread (GstXvImageSink * xvimagesink)
 }
 
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+/**
+ * gst_xvimagesink_prepare_xid:
+ * @overlay: a #GstXOverlay which does not yet have an XWindow or XPixmap.
+ *
+ * This will post a "prepare-xid" element message with video size and display size on the bus
+ * to give applications an opportunity to call
+ * gst_x_overlay_set_xwindow_id() before a plugin creates its own
+ * window or pixmap.
+ *
+ * This function should only be used by video overlay plugin developers.
+ */
+static void
+gst_xvimagesink_prepare_xid (GstXOverlay * overlay)
+{
+  GstStructure *s;
+  GstMessage *msg;
+
+  g_return_if_fail (overlay != NULL);
+  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
+
+  GstXvImageSink *xvimagesink;
+  xvimagesink = GST_XVIMAGESINK (GST_OBJECT (overlay));
+
+  GST_DEBUG ("post \"prepare-xid\" element message with video-width(%d), video-height(%d), display-width(%d), display-height(%d)",
+        GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink), xvimagesink->xcontext->width, xvimagesink->xcontext->height);
+
+  GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare xid");
+  s = gst_structure_new ("prepare-xid",
+        "video-width", G_TYPE_INT, GST_VIDEO_SINK_WIDTH (xvimagesink),
+        "video-height", G_TYPE_INT, GST_VIDEO_SINK_HEIGHT (xvimagesink),
+        "display-width", G_TYPE_INT, xvimagesink->xcontext->width,
+        "display-height", G_TYPE_INT, xvimagesink->xcontext->height,
+        NULL);
+  msg = gst_message_new_element (GST_OBJECT (overlay), s);
+  gst_element_post_message (GST_ELEMENT (overlay), msg);
+}
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
+
 /* This function calculates the pixel aspect ratio based on the properties
  * in the xcontext structure and stores it there. */
 static void
@@ -2403,6 +4206,9 @@ gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
     {1, 1},                     /* regular screen */
     {16, 15},                   /* PAL TV */
     {11, 10},                   /* 525 line Rec.601 video */
+#ifdef GST_EXT_XV_ENHANCEMENT
+    {44, 46},                   /* Gear S Curved Display */
+#endif
     {54, 59},                   /* 625 line Rec.601 video */
     {64, 45},                   /* 1280x1024 on 16:9 display */
     {5, 3},                     /* 1280x1024 on 4:3 display */
@@ -2461,7 +4267,7 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
   GstXContext *xcontext = NULL;
   XPixmapFormatValues *px_formats = NULL;
   gint nb_formats = 0, i, j, N_attr;
-  XvAttribute *xv_attr;
+  XvAttribute *xv_attr = NULL;
   Atom prop_atom;
   const char *channels[4] = { "XV_HUE", "XV_SATURATION",
     "XV_BRIGHTNESS", "XV_CONTRAST"
@@ -2475,7 +4281,6 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
   g_mutex_lock (xvimagesink->x_lock);
 
   xcontext->disp = XOpenDisplay (xvimagesink->display_name);
-
   if (!xcontext->disp) {
     g_mutex_unlock (xvimagesink->x_lock);
     g_free (xcontext);
@@ -2484,6 +4289,22 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
     return NULL;
   }
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  {
+    int i = 0;
+    for (i = 0; i < MAX_DISPLAY_IN_XVIMAGESINK; i++) {
+      if (g_display_id[i] == NULL) {
+        g_display_id[i] = xcontext->disp;
+        GST_INFO_OBJECT(xvimagesink, "x display array[%d] = display(0x%x)", i, xcontext->disp);
+        break;
+      }
+    }
+    if (i == MAX_DISPLAY_IN_XVIMAGESINK) {
+      GST_WARNING_OBJECT(xvimagesink, "out of index(%d) for x display array", i);
+    }
+  }
+#endif
+
   xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
   xcontext->screen_num = DefaultScreen (xcontext->disp);
   xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
@@ -2505,6 +4326,16 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
   px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
 
   if (!px_formats) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+  {
+    int i = 0;
+    for (i = 0; i < MAX_DISPLAY_IN_XVIMAGESINK; i++) {
+      if (g_display_id[i] == xcontext->disp) {
+        g_display_id[i] = NULL;
+      }
+    }
+  }
+#endif
     XCloseDisplay (xcontext->disp);
     g_mutex_unlock (xvimagesink->x_lock);
     g_free (xcontext->par);
@@ -2542,7 +4373,21 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
 
   xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext);
 
-  if (!xcontext->caps) {
+  if (!xcontext->caps
+#ifdef GST_EXT_XV_ENHANCEMENT
+    && !xvimagesink->subpicture
+#endif
+    ) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+  {
+    int i = 0;
+    for (i = 0; i < MAX_DISPLAY_IN_XVIMAGESINK; i++) {
+      if (g_display_id[i] == xcontext->disp) {
+        g_display_id[i] = NULL;
+      }
+    }
+  }
+#endif
     XCloseDisplay (xcontext->disp);
     g_mutex_unlock (xvimagesink->x_lock);
     g_free (xcontext->par);
@@ -2551,21 +4396,26 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
     return NULL;
   }
 #ifdef HAVE_XSHM
-  /* Search for XShm extension support */
-  if (XShmQueryExtension (xcontext->disp) &&
-      gst_xvimagesink_check_xshm_calls (xcontext)) {
-    xcontext->use_xshm = TRUE;
-    GST_DEBUG ("xvimagesink is using XShm extension");
-  } else
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (!xvimagesink->subpicture) {
+#endif //GST_EXT_XV_ENHANCEMENT
+    /* Search for XShm extension support */
+    if (XShmQueryExtension (xcontext->disp) &&
+        gst_xvimagesink_check_xshm_calls (xcontext)) {
+      xcontext->use_xshm = TRUE;
+      GST_DEBUG ("xvimagesink is using XShm extension");
+    } else
 #endif /* HAVE_XSHM */
-  {
-    xcontext->use_xshm = FALSE;
-    GST_DEBUG ("xvimagesink is not using XShm extension");
-  }
-
-  xv_attr = XvQueryPortAttributes (xcontext->disp,
-      xcontext->xv_port_id, &N_attr);
+    {
+      xcontext->use_xshm = FALSE;
+      GST_DEBUG ("xvimagesink is not using XShm extension");
+    }
 
+    xv_attr = XvQueryPortAttributes (xcontext->disp,
+        xcontext->xv_port_id, &N_attr);
+#ifdef GST_EXT_XV_ENHANCEMENT
+  }
+#endif //GST_EXT_XV_ENHANCEMENT
 
   /* Generate the channels list */
   for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
@@ -2616,12 +4466,17 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
       }
     }
   }
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (!xvimagesink->subpicture) {
+#endif
   if (xv_attr)
     XFree (xv_attr);
-
 #ifdef GST_EXT_XV_ENHANCEMENT
-  set_display_mode(xcontext, xvimagesink->display_mode);
+  }
+  if(!xvimagesink->subpicture) {
+    set_display_mode(xvimagesink->xcontext, xvimagesink->display_mode);
+    set_csc_range(xcontext, xvimagesink->csc_range);
+  }
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   g_mutex_unlock (xvimagesink->x_lock);
@@ -2634,7 +4489,7 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
 static void
 gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
 {
-  GList *formats_list, *channels_list;
+  GList *formats_list, *channels_list = NULL;
   GstXContext *xcontext;
   gint i = 0;
 
@@ -2652,7 +4507,9 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
 
   GST_OBJECT_UNLOCK (xvimagesink);
 
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (!xvimagesink->subpicture)  {
+#endif
   formats_list = xcontext->formats_list;
 
   while (formats_list) {
@@ -2667,7 +4524,9 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
     g_list_free (xcontext->formats_list);
 
   channels_list = xcontext->channels_list;
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+  }
+#endif
   while (channels_list) {
     GstColorBalanceChannel *channel = channels_list->data;
 
@@ -2696,8 +4555,17 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
 
   XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  {
+    int i = 0;
+    for (i = 0; i < MAX_DISPLAY_IN_XVIMAGESINK; i++) {
+      if (g_display_id[i] == xcontext->disp) {
+        g_display_id[i] = NULL;
+      }
+    }
+  }
+#endif
   XCloseDisplay (xcontext->disp);
-
   g_mutex_unlock (xvimagesink->x_lock);
 
   g_free (xcontext);
@@ -2753,10 +4621,13 @@ gst_xvimagesink_getcaps (GstBaseSink * bsink)
   GstXvImageSink *xvimagesink;
 
   xvimagesink = GST_XVIMAGESINK (bsink);
-
-  if (xvimagesink->xcontext)
+  if (xvimagesink->xcontext
+#ifdef GST_EXT_XV_ENHANCEMENT
+    && !xvimagesink->subpicture
+#endif
+) {
     return gst_caps_ref (xvimagesink->xcontext->caps);
-
+  }
   return
       gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
           (xvimagesink)));
@@ -2779,7 +4650,15 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   const GValue *fps;
   guint num, den;
 #ifdef GST_EXT_XV_ENHANCEMENT
-  gboolean enable_last_buffer;
+  gboolean subtitle;
+  gchar *str_in = gst_caps_to_string(caps);
+  if(str_in == NULL) {
+    GST_ERROR("gst_caps_to_string() returns NULL...");
+  }else{
+    GST_INFO("In setcaps. incaps:%s", str_in);
+    g_free (str_in);
+    str_in = NULL;
+  }
 #endif /* #ifdef GST_EXT_XV_ENHANCEMENT */
 
   xvimagesink = GST_XVIMAGESINK (bsink);
@@ -2788,7 +4667,11 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
       "In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %"
       GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps);
 
-  if (!gst_caps_can_intersect (xvimagesink->xcontext->caps, caps))
+  if (!gst_caps_can_intersect (xvimagesink->xcontext->caps, caps)
+#ifdef GST_EXT_XV_ENHANCEMENT
+    && !xvimagesink->subpicture
+#endif
+    )
     goto incompatible_caps;
 
   structure = gst_caps_get_structure (caps, 0);
@@ -2796,7 +4679,13 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   ret &= gst_structure_get_int (structure, "height", &video_height);
   fps = gst_structure_get_value (structure, "framerate");
   ret &= (fps != NULL);
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if(gst_structure_get_boolean (structure, "subtitle", &subtitle) && xvimagesink->subpicture)
+  {
+    xvimagesink->is_subpicture_format = TRUE;
+    GST_LOG("It is type of subpicture and subtitle.");
+  }
+#endif
   if (!ret)
     goto incomplete_caps;
 
@@ -2804,16 +4693,19 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   xvimagesink->aligned_width = video_width;
   xvimagesink->aligned_height = video_height;
 
-  /* get enable-last-buffer */
-  g_object_get(G_OBJECT(xvimagesink), "enable-last-buffer", &enable_last_buffer, NULL);
-  GST_INFO_OBJECT(xvimagesink, "current enable-last-buffer : %d", enable_last_buffer);
-
-  /* flush if enable-last-buffer is TRUE */
-  if (enable_last_buffer) {
-    GST_INFO_OBJECT(xvimagesink, "flush last-buffer");
-    g_object_set(G_OBJECT(xvimagesink), "enable-last-buffer", FALSE, NULL);
-    g_object_set(G_OBJECT(xvimagesink), "enable-last-buffer", TRUE, NULL);
+#ifdef GST_EXT_ENABLE_HEVC
+  /*get combine prop of hevc*/
+  if(gst_structure_get_int (structure, "yuvcombine", &(xvimagesink->need_combine_data)))
+  {
+    GST_INFO_OBJECT(xvimagesink, "need combine data : %d", xvimagesink->need_combine_data);
+  }
+  else
+  {
+    /*Not need to combine data, just directly copy*/
+    xvimagesink->need_combine_data = 0;
   }
+#endif
+  _remove_last_buffer(xvimagesink);
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   xvimagesink->fps_n = gst_value_get_fraction_numerator (fps);
@@ -2821,11 +4713,15 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
 
   xvimagesink->video_width = video_width;
   xvimagesink->video_height = video_height;
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (!xvimagesink->subpicture) {
+#endif
   im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
   if (im_format == -1)
     goto invalid_format;
-
+#ifdef GST_EXT_XV_ENHANCEMENT
+  }
+#endif
   /* get aspect ratio from caps if it's present, and
    * convert video width and height to a display width and height
    * using wd / hd = wv / hv * PARv / PARd */
@@ -2902,23 +4798,37 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
 
   /* Notify application to set xwindow id now */
   g_mutex_lock (xvimagesink->flow_lock);
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (!xvimagesink->xwindow && !xvimagesink->get_pixmap_cb) {
+    g_mutex_unlock (xvimagesink->flow_lock);
+    gst_xvimagesink_prepare_xid (GST_X_OVERLAY (xvimagesink));
+#else
   if (!xvimagesink->xwindow) {
     g_mutex_unlock (xvimagesink->flow_lock);
     gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (xvimagesink));
+#endif
   } else {
     g_mutex_unlock (xvimagesink->flow_lock);
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
+if (!xvimagesink->is_subpicture_format) {
+#endif
+    /* Creating our window and our image with the display size in pixels */
+    if (GST_VIDEO_SINK_WIDTH (xvimagesink) <= 0 ||
+        GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0)
+      goto no_display_size;
 
-  /* Creating our window and our image with the display size in pixels */
-  if (GST_VIDEO_SINK_WIDTH (xvimagesink) <= 0 ||
-      GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0)
-    goto no_display_size;
-
-  g_mutex_lock (xvimagesink->flow_lock);
-  if (!xvimagesink->xwindow) {
-    xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
-        GST_VIDEO_SINK_WIDTH (xvimagesink),
-        GST_VIDEO_SINK_HEIGHT (xvimagesink));
+    g_mutex_lock (xvimagesink->flow_lock);
+#ifdef GST_EXT_XV_ENHANCEMENT
+    if (!xvimagesink->xwindow && !xvimagesink->get_pixmap_cb) {
+      GST_DEBUG_OBJECT (xvimagesink, "xwindow is null and not multi-pixmaps usage case");
+#else
+    if (!xvimagesink->xwindow) {
+#endif
+      xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
+          GST_VIDEO_SINK_WIDTH (xvimagesink),
+          GST_VIDEO_SINK_HEIGHT (xvimagesink));
+    }
   }
 
   /* After a resize, we want to redraw the borders in case the new frame size
@@ -2930,7 +4840,8 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   if ((xvimagesink->xvimage) &&
       ((im_format != xvimagesink->xvimage->im_format) ||
           (video_width != xvimagesink->xvimage->width) ||
-          (video_height != xvimagesink->xvimage->height))) {
+          (video_height != xvimagesink->xvimage->height)) &&
+          (!xvimagesink->subpicture)) {
     GST_DEBUG_OBJECT (xvimagesink,
         "old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
         GST_FOURCC_ARGS (xvimagesink->xvimage->im_format),
@@ -2940,6 +4851,12 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
     xvimagesink->xvimage = NULL;
   }
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  /* In case of starting player with connecting external display, we have to check status.
+   * It will be unconditionally executed. */
+  if(!xvimagesink->is_subpicture_format)
+    check_hdmi_connected(xvimagesink);
+#endif
   g_mutex_unlock (xvimagesink->flow_lock);
 
   return TRUE;
@@ -2974,7 +4891,9 @@ no_display_size:
         ("Error calculating the output display ratio of the video."));
     return FALSE;
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
 }
+#endif
 
 static GstStateChangeReturn
 gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
@@ -2990,6 +4909,9 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING("NULL_TO_READY start");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       /* Initializing the XContext */
       if (xvimagesink->xcontext == NULL) {
         xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
@@ -3013,32 +4935,39 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
       XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
       gst_xvimagesink_update_colorbalance (xvimagesink);
       gst_xvimagesink_manage_event_thread (xvimagesink);
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING("NULL_TO_READY done");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING("READY_TO_PAUSED start");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       g_mutex_lock (xvimagesink->pool_lock);
       xvimagesink->pool_invalid = FALSE;
       g_mutex_unlock (xvimagesink->pool_lock);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
 #ifdef GST_EXT_XV_ENHANCEMENT
-      g_mutex_lock (xvimagesink->x_lock);
-      atom_preemption = XInternAtom( xvimagesink->xcontext->disp,
-                                     "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", False );
-      if (atom_preemption != None) {
-         if (XvSetPortAttribute(xvimagesink->xcontext->disp,
-                                xvimagesink->xcontext->xv_port_id,
-                                atom_preemption, 1 ) != Success) {
-            GST_ERROR_OBJECT(xvimagesink, "%d: XvSetPortAttribute: preemption failed.\n", atom_preemption);
-         }
-         XSync (xvimagesink->xcontext->disp, FALSE);
-      }
-      g_mutex_unlock (xvimagesink->x_lock);
+      GST_WARNING("READY_TO_PAUSED done");
+#endif /* GST_EXT_XV_ENHANCEMENT */
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+#ifdef GST_EXT_XV_ENHANCEMENT
+      if(vconf_set_int(VCONFKEY_XV_STATE, (xvimagesink->eos_received << 2) | XV_STATUS_PLAYING))
+        GST_WARNING("vconf set fail");
+      GST_WARNING("PAUSED_TO_PLAYING done");
+      xvimagesink->is_during_seek = FALSE;
+      xvimagesink->keep_external_fullscreen_prev = FALSE;
 #endif /* GST_EXT_XV_ENHANCEMENT */
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING("PAUSED_TO_READY start");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       g_mutex_lock (xvimagesink->pool_lock);
       xvimagesink->pool_invalid = TRUE;
       g_mutex_unlock (xvimagesink->pool_lock);
+#ifdef GST_EXT_XV_ENHANCEMENT
+#endif /* GST_EXT_XV_ENHANCEMENT */
       break;
     default:
       break;
@@ -3049,29 +4978,119 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
   switch (transition) {
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
 #ifdef GST_EXT_XV_ENHANCEMENT
-      xvimagesink->rotate_changed = TRUE;
+      GST_WARNING("PLAYING_TO_PAUSED start");
+      g_mutex_lock (xvimagesink->flow_lock);
+      /* init displayed buffer count */
+      xvimagesink->displayed_buffer_count = 0;
+
       g_mutex_lock (xvimagesink->x_lock);
-      atom_preemption = XInternAtom( xvimagesink->xcontext->disp,
-                                     "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", False );
-      if (atom_preemption != None) {
-         if (XvSetPortAttribute(xvimagesink->xcontext->disp,
-                                xvimagesink->xcontext->xv_port_id,
-                                atom_preemption, 0 ) != Success) {
-            GST_ERROR_OBJECT(xvimagesink, "%d: XvSetPortAttribute: preemption failed.\n", atom_preemption);
-         }
-         XSync (xvimagesink->xcontext->disp, FALSE);
+      if ((xvimagesink->is_hided || xvimagesink->is_quick_panel_on || xvimagesink->is_multi_window) && _is_connected_to_external_display(xvimagesink) && !xvimagesink->keep_external_fullscreen_prev) {
+        GST_WARNING_OBJECT(xvimagesink, "release external display mode");
+        XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
+                     xvimagesink->xwindow->win);
+        XSync(xvimagesink->xcontext->disp, FALSE);
+        xvimagesink->skip_frame_due_to_external_dev = TRUE;
+      }
+      if((xvimagesink->is_hided_subpicture || xvimagesink->is_quick_panel_on_subpicture || xvimagesink->is_multi_window_subpicture)
+        && xvimagesink->is_subpicture_format && xvimagesink->pixmap_for_subpicture) {
+        GST_WARNING_OBJECT(xvimagesink, "calling XvStopVideo() for %d port [pixmap : %p]", xvimagesink->xcontext->xv_port_id, xvimagesink->pixmap_for_subpicture);
+        XvStopVideo(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->pixmap_for_subpicture);
+        XSync(xvimagesink->xcontext->disp, FALSE);
       }
       g_mutex_unlock (xvimagesink->x_lock);
+      g_mutex_unlock (xvimagesink->flow_lock);
+      if(vconf_set_int(VCONFKEY_XV_STATE, (xvimagesink->eos_received << 2) | XV_STATUS_PAUSED))
+        GST_WARNING("vconf set fail");
+      GST_WARNING("PLAYING_TO_PAUSED done");
 #endif /* GST_EXT_XV_ENHANCEMENT */
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING_OBJECT(xvimagesink, "PAUSED_TO_READY start - %d %d %d %p",
+                                      xvimagesink->is_zero_copy_format,
+                                      xvimagesink->enable_flush_buffer,
+                                      xvimagesink->secure_path,
+                                      xvimagesink->get_pixmap_cb);
+
+      if ((xvimagesink->enable_flush_buffer == FALSE ||
+           xvimagesink->secure_path == SECURE_PATH_ON) &&
+          xvimagesink->xcontext && xvimagesink->xwindow) {
+        GST_WARNING_OBJECT(xvimagesink, "Call XvStopVideo and remove last buffer");
+        g_mutex_lock(xvimagesink->x_lock);
+        XvStopVideo(xvimagesink->xcontext->disp,
+                    xvimagesink->xcontext->xv_port_id,
+                    xvimagesink->xwindow->win);
+        XSync(xvimagesink->xcontext->disp, FALSE);
+        g_mutex_unlock(xvimagesink->x_lock);
+        _remove_last_buffer(xvimagesink);
+      } else if (xvimagesink->is_zero_copy_format &&
+                 xvimagesink->xvimage &&
+                 xvimagesink->xvimage->xvimage &&
+                 !xvimagesink->get_pixmap_cb) {
+        if (gst_xvimagesink_make_flush_buffer(xvimagesink)) {
+          int i = 0;
+          XV_DATA_PTR img_data = (XV_DATA_PTR) xvimagesink->xvimage->xvimage->data;
+          memset(img_data, 0x0, sizeof(XV_DATA));
+          XV_INIT_DATA(img_data);
+
+          img_data->bo[0] = xvimagesink->flush_buffer->bo[0];
+          img_data->bo[1] = xvimagesink->flush_buffer->bo[1];
+          img_data->bo[2] = xvimagesink->flush_buffer->bo[2];
+
+          gst_xvimagesink_xvimage_put(xvimagesink, xvimagesink->xvimage);
+
+          GST_WARNING_OBJECT(xvimagesink, "gst_xvimagesink_xvimage_put done");
+
+          /* check whether putimage is succeeded or not */
+          g_mutex_lock(xvimagesink->display_buffer_lock);
+
+          for (i = 0 ; i < DISPLAYING_BUFFERS_MAX_NUM ; i++) {
+            if (xvimagesink->displaying_buffers[i].gem_name[0] > 0) {
+              if ((img_data->dmabuf_fd[0] > 0 &&
+                   xvimagesink->displaying_buffers[i].dmabuf_fd[0] == img_data->dmabuf_fd[0] &&
+                   xvimagesink->displaying_buffers[i].dmabuf_fd[1] == img_data->dmabuf_fd[1] &&
+                   xvimagesink->displaying_buffers[i].dmabuf_fd[2] == img_data->dmabuf_fd[2]) ||
+                  (img_data->bo[0] &&
+                   xvimagesink->displaying_buffers[i].bo[0] == img_data->bo[0] &&
+                   xvimagesink->displaying_buffers[i].bo[1] == img_data->bo[1] &&
+                   xvimagesink->displaying_buffers[i].bo[2] == img_data->bo[2])) {
+                GST_WARNING_OBJECT(xvimagesink, "found flush buffer in displaying_buffers");
+                break;
+              }
+            }
+          }
+
+          if (i >= DISPLAYING_BUFFERS_MAX_NUM) {
+            GST_WARNING_OBJECT(xvimagesink, "flush buffer is not existed in displaying_buffers");
+            _release_flush_buffer(xvimagesink);
+          } else {
+            _remove_last_buffer(xvimagesink);
+          }
+
+          g_mutex_unlock(xvimagesink->display_buffer_lock);
+        }
+      }
+#endif /* GST_EXT_XV_ENHANCEMENT */
       xvimagesink->fps_n = 0;
       xvimagesink->fps_d = 1;
       GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
       GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING("PAUSED_TO_READY done");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
+#ifdef GST_EXT_XV_ENHANCEMENT
+      GST_WARNING("READY_TO_NULL start");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       gst_xvimagesink_reset (xvimagesink);
+#ifdef GST_EXT_XV_ENHANCEMENT
+      /* close drm */
+      drm_fini(xvimagesink);
+      /* init displaying_buffer_count */
+      xvimagesink->displaying_buffer_count = 0;
+      GST_WARNING("READY_TO_NULL done");
+#endif /* GST_EXT_XV_ENHANCEMENT */
       break;
     default:
       break;
@@ -3102,15 +5121,178 @@ gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
   }
 }
 
+#ifdef GST_EXT_ENABLE_HEVC
+static void
+gst_xvimagesink_combine_i420_scmn_data(GstXvImageSink *xvimagesink, GstBuffer *buf)
+{
+    unsigned int outsize = 0;
+    unsigned char *temp_outbuf = xvimagesink->xvimage->xvimage->data;
+    int cnt = 0, j = 0;
+    unsigned char *temp_imgb;
+    SCMN_IMGB *imgb = NULL;
+    int stride, w, h, i;
+
+    GST_DEBUG("Begin");
+    imgb = (SCMN_IMGB *)GST_BUFFER_DATA(buf);
+    if(imgb == NULL || imgb->a[0] == NULL)
+    {
+        return;
+    }
+
+    stride = GST_ROUND_UP_4 (imgb->w[0]);
+    h = imgb->h[0];
+    w = imgb->w[0];
+    /*Y plane copy */
+    for (i = 0; i < h; i++)
+    {
+        memcpy (temp_outbuf + i * stride, imgb->a[0] + i * imgb->s[0], w);
+    }
+
+    temp_outbuf += GST_ROUND_UP_4 (imgb->w[0]) * GST_ROUND_UP_2 (imgb->h[0]);
+
+    stride = GST_ROUND_UP_4 (GST_ROUND_UP_2 (imgb->w[0]) / 2);
+    h = GST_ROUND_UP_2 (imgb->h[0]) / 2;
+    w = GST_ROUND_UP_2 (imgb->w[0]) / 2;
+    /* Cb plane copy */
+    for (i = 0; i < h; i++)
+    {
+        memcpy (temp_outbuf + i * stride, imgb->a[1] + i * imgb->s[1], w);
+    }
+
+    temp_outbuf += GST_ROUND_UP_4 (GST_ROUND_UP_2 (imgb->w[0]) / 2) * (GST_ROUND_UP_2 (imgb->h[0]) / 2);
+    /* Same stride, height, width as above */
+    /* Cr plane copy */
+    for (i = 0; i < h; i++)
+    {
+        memcpy (temp_outbuf + i * stride, imgb->a[2] + i * imgb->s[2], w);
+    }
+
+    outsize  = imgb->w[0] * imgb->h[0]* 3 >> 1;
+    xvimagesink->xvimage->size = MIN(outsize, xvimagesink->xvimage->size);
+
+    GST_DEBUG("End");
+}
+#endif
+
+#ifdef GST_EXT_XV_ENHANCEMENT
+static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink)
+{
+  GstXvImageFlushBuffer *flush_buffer = NULL;
+  GstXvImageDisplayingBuffer *display_buffer = NULL;
+  tbm_bo bo = NULL;
+  int size = 0;
+  int i = 0;
+  int ret = 0;
+
+  if (xvimagesink == NULL) {
+    GST_ERROR("handle is NULL");
+    return FALSE;
+  }
+
+  if (xvimagesink->last_added_buffer_index == -1) {
+    GST_WARNING_OBJECT(xvimagesink, "there is no remained buffer");
+    return FALSE;
+  }
+
+  if (xvimagesink->drm_fd < 0 || xvimagesink->bufmgr == NULL) {
+    GST_ERROR_OBJECT(xvimagesink, "drm fd[%d] or bufmgr[%p] is invalid",
+                                  xvimagesink->drm_fd, xvimagesink->bufmgr);
+    return FALSE;
+  }
+
+  flush_buffer = (GstXvImageFlushBuffer *)malloc(sizeof(GstXvImageFlushBuffer));
+  if (flush_buffer == NULL) {
+    GST_ERROR_OBJECT(xvimagesink, "GstXvImageFlushBuffer alloc failed");
+    return FALSE;
+  }
+
+  memset(flush_buffer, 0x0, sizeof(GstXvImageFlushBuffer));
+
+  display_buffer = &(xvimagesink->displaying_buffers[xvimagesink->last_added_buffer_index]);
+  GST_WARNING_OBJECT(xvimagesink, "last_added_buffer_index [%d]",
+                                  xvimagesink->last_added_buffer_index);
+
+  for (i = 0 ; i < XV_BUF_PLANE_NUM ; i++) {
+    if (display_buffer->bo[i]) {
+      tbm_bo_handle vaddr_src;
+      tbm_bo_handle vaddr_dst;
+
+      /* get bo size */
+      size = tbm_bo_size(display_buffer->bo[i]);
+
+      /* alloc bo */
+      bo = tbm_bo_alloc(xvimagesink->bufmgr, size, TBM_BO_DEFAULT);
+      if (bo == NULL) {
+        GST_ERROR_OBJECT(xvimagesink, "bo alloc[%d] failed", size);
+        goto FLUSH_BUFFER_FAILED;
+      }
+
+      GST_WARNING_OBJECT(xvimagesink, "[%d] bo %p, size %d alloc done", i, bo, size);
+
+      flush_buffer->gem_name[i] = tbm_bo_export(bo);
+      flush_buffer->bo[i] = bo;
+
+      /* get virtual address */
+      vaddr_src = tbm_bo_map(display_buffer->bo[i], TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+      vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+      if (vaddr_src.ptr == NULL || vaddr_dst.ptr == NULL) {
+        GST_WARNING_OBJECT(xvimagesink, "get vaddr failed src %p, dst %p",
+                                        vaddr_src.ptr, vaddr_dst.ptr);
+        if (vaddr_src.ptr) {
+          tbm_bo_unmap(display_buffer->bo[i]);
+        }
+        if (vaddr_dst.ptr) {
+          tbm_bo_unmap(bo);
+        }
+        goto FLUSH_BUFFER_FAILED;
+      }
+
+      /* copy buffer */
+      memcpy(vaddr_dst.ptr, vaddr_src.ptr, size);
+
+      tbm_bo_unmap(display_buffer->bo[i]);
+      tbm_bo_unmap(bo);
+
+      GST_WARNING_OBJECT(xvimagesink, "[%d] copy done", i);
+
+      xvimagesink->flush_buffer = flush_buffer;
+
+      ret = TRUE;
+    }
+  }
+
+  return ret;
+
+FLUSH_BUFFER_FAILED:
+  if (flush_buffer) {
+    for (i = 0 ; i < XV_BUF_PLANE_NUM ; i++) {
+      if (flush_buffer->bo[i]) {
+        tbm_bo_unref(flush_buffer->bo[i]);
+        flush_buffer->bo[i] = NULL;
+      }
+    }
+    free(flush_buffer);
+    flush_buffer = NULL;
+  }
+
+  return FALSE;
+}
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
+
 static GstFlowReturn
 gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 {
   GstXvImageSink *xvimagesink;
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-  XV_PUTIMAGE_DATA_PTR img_data = NULL;
+  XV_DATA_PTR img_data = NULL;
   SCMN_IMGB *scmn_imgb = NULL;
   gint format = 0;
+  gboolean ret = FALSE;
+  int res = -1;
+  int (*handler) (Display *, XErrorEvent *) = NULL;
+  Atom atom_overlay;
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   xvimagesink = GST_XVIMAGESINK (vsink);
@@ -3126,6 +5308,9 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
      put the ximage which is in the PRIVATE pointer */
   if (GST_IS_XVIMAGE_BUFFER (buf)) {
     GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer %p", buf);
+#ifdef GST_EXT_XV_ENHANCEMENT
+    xvimagesink->xid_updated = FALSE;
+#endif /* GST_EXT_XV_ENHANCEMENT */
     if (!gst_xvimagesink_xvimage_put (xvimagesink,
             GST_XVIMAGE_BUFFER_CAST (buf)))
       goto no_window;
@@ -3134,21 +5319,41 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
         "slow copy into bufferpool buffer %p", buf);
     /* Else we have to copy the data into our private image, */
     /* if we have one... */
-    if (!xvimagesink->xvimage) {
-      GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
+#ifdef GST_EXT_XV_ENHANCEMENT
+    g_mutex_lock (xvimagesink->flow_lock);
+    if (xvimagesink->skip_frame_due_to_external_dev) {
+      GST_WARNING_OBJECT( xvimagesink, "skip_frame_due_to_external_dev is TRUE. so skip show frame..." );
+      xvimagesink->skip_frame_due_to_external_dev = FALSE;
+      g_mutex_unlock (xvimagesink->flow_lock);
+      return GST_FLOW_OK;
+    }
+
+#endif /* GST_EXT_XV_ENHANCEMENT */
+      if (!xvimagesink->xvimage
+#ifdef GST_EXT_XV_ENHANCEMENT
+      && !xvimagesink->is_subpicture_format
+#endif
+        ) {
+        GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
 
 #ifdef GST_EXT_XV_ENHANCEMENT
       format = gst_xvimagesink_get_format_from_caps(xvimagesink, GST_BUFFER_CAPS(buf));
       switch (format) {
         case GST_MAKE_FOURCC('S', 'T', '1', '2'):
         case GST_MAKE_FOURCC('S', 'N', '1', '2'):
+        case GST_MAKE_FOURCC('S', 'N', '2', '1'):
         case GST_MAKE_FOURCC('S', '4', '2', '0'):
         case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
         case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
         case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
+        case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
+        case GST_MAKE_FOURCC('S', 'R', '3', '2'):
+        case GST_MAKE_FOURCC('S', 'V', '1', '2'):
+          xvimagesink->is_zero_copy_format = TRUE;
           scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
           if(scmn_imgb == NULL) {
             GST_DEBUG_OBJECT( xvimagesink, "scmn_imgb is NULL. Skip xvimage put..." );
+            g_mutex_unlock (xvimagesink->flow_lock);
             return GST_FLOW_OK;
           }
 
@@ -3158,6 +5363,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
             GST_WARNING_OBJECT(xvimagesink, "invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
                                             xvimagesink->video_width, xvimagesink->video_height,
                                             scmn_imgb->s[0], scmn_imgb->e[0]);
+            g_mutex_unlock (xvimagesink->flow_lock);
             return GST_FLOW_OK;
           }
 
@@ -3167,9 +5373,12 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
                                        xvimagesink->aligned_width, xvimagesink->aligned_height);
           break;
         default:
+          xvimagesink->is_zero_copy_format = FALSE;
           GST_INFO_OBJECT(xvimagesink, "Use original width,height of caps");
           break;
       }
+
+      GST_INFO("zero copy format - %d", xvimagesink->is_zero_copy_format);
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
       xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
@@ -3179,7 +5388,14 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
         /* The create method should have posted an informative error */
         goto no_image;
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+      if ((xvimagesink->is_zero_copy_format == FALSE &&
+           xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) ||
+          (xvimagesink->is_zero_copy_format &&
+           xvimagesink->xvimage->size < sizeof(SCMN_IMGB))) {
+#else /* GST_EXT_XV_ENHANCEMENT */
       if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) {
+#endif /* GST_EXT_XV_ENHANCEMENT */
         GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
             ("Failed to create output image buffer of %dx%d pixels",
                 xvimagesink->xvimage->width, xvimagesink->xvimage->height),
@@ -3192,61 +5408,232 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
     }
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-    switch (xvimagesink->xvimage->im_format) {
+    if (xvimagesink->is_zero_copy_format) {
       /* Cases for specified formats of Samsung extension */
-      case GST_MAKE_FOURCC('S', 'T', '1', '2'):
-      case GST_MAKE_FOURCC('S', 'N', '1', '2'):
-      case GST_MAKE_FOURCC('S', '4', '2', '0'):
-      case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
-      case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
-      case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
-      case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
-      {
-        GST_DEBUG("Samsung extension display format activated. fourcc:%d,display mode:%d,Rotate angle:%d",
-                  xvimagesink->xvimage->im_format, xvimagesink->display_mode, xvimagesink->rotate_angle);
+        GST_LOG("Samsung EXT format - fourcc:%c%c%c%c, display mode:%d, Rotate angle:%d",
+                xvimagesink->xvimage->im_format, xvimagesink->xvimage->im_format>>8,
+                xvimagesink->xvimage->im_format>>16, xvimagesink->xvimage->im_format>>24,
+                xvimagesink->display_mode, xvimagesink->rotate_angle);
 
         if (xvimagesink->xvimage->xvimage->data) {
-          img_data = (XV_PUTIMAGE_DATA_PTR) xvimagesink->xvimage->xvimage->data;
-          XV_PUTIMAGE_INIT_DATA(img_data);
+          int i = 0;
+          img_data = (XV_DATA_PTR) xvimagesink->xvimage->xvimage->data;
+          memset(img_data, 0x0, sizeof(XV_DATA));
+          XV_INIT_DATA(img_data);
 
           scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
           if (scmn_imgb == NULL) {
             GST_DEBUG_OBJECT( xvimagesink, "scmn_imgb is NULL. Skip xvimage put..." );
+            g_mutex_unlock (xvimagesink->flow_lock);
             return GST_FLOW_OK;
           }
 
-          img_data->YPhyAddr  = (unsigned int)scmn_imgb->p[0];
-          img_data->CbPhyAddr = (unsigned int)scmn_imgb->p[1];
-          img_data->CrPhyAddr = (unsigned int)scmn_imgb->p[2];
+          /* Keep the vaddr of current image for copying last image */
+          if (scmn_imgb->buf_share_method != BUF_SHARE_METHOD_FLUSH_BUFFER) {
+            for(i = 0; i < SCMN_IMGB_MAX_PLANE; i++) {
+              xvimagesink->last_image_vaddr[i] = (unsigned int)scmn_imgb->a[i];
+            }
+            GST_LOG("Vaddr - YBuf[0x%x], CbBuf[0x%x], CrBuf[0x%x]",
+              xvimagesink->last_image_vaddr[0], xvimagesink->last_image_vaddr[1], xvimagesink->last_image_vaddr[2]);
+          }
+
+          if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
+            img_data->YBuf = (unsigned int)scmn_imgb->p[0];
+            img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
+            img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
+            img_data->BufType = XV_BUF_TYPE_LEGACY;
+
+            GST_DEBUG("YBuf[0x%x], CbBuf[0x%x], CrBuf[0x%x]",
+                      img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
+          } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD ||
+                     scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER) {
+            gboolean do_set_secure = FALSE;
+
+            /* open drm to use gem */
+            if (xvimagesink->drm_fd < 0) {
+              drm_init(xvimagesink);
+            }
+
+            if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
+              /* keep dma-buf fd. fd will be converted in gst_xvimagesink_xvimage_put */
+              img_data->dmabuf_fd[0] = scmn_imgb->dmabuf_fd[0];
+              img_data->dmabuf_fd[1] = scmn_imgb->dmabuf_fd[1];
+              img_data->dmabuf_fd[2] = scmn_imgb->dmabuf_fd[2];
+              img_data->BufType = XV_BUF_TYPE_DMABUF;
+              GST_DEBUG("DMABUF fd %u,%u,%u", img_data->dmabuf_fd[0], img_data->dmabuf_fd[1], img_data->dmabuf_fd[2]);
+            } else {
+              /* keep bo. bo will be converted in gst_xvimagesink_xvimage_put */
+              img_data->bo[0] = scmn_imgb->bo[0];
+              img_data->bo[1] = scmn_imgb->bo[1];
+              img_data->bo[2] = scmn_imgb->bo[2];
+              GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
+            }
+
+            /* check secure contents path */
+            if (scmn_imgb->tz_enable) {
+              if (xvimagesink->secure_path != SECURE_PATH_ON) {
+                xvimagesink->secure_path = SECURE_PATH_ON;
+                do_set_secure = TRUE;
+              }
+            } else {
+              if (xvimagesink->secure_path != SECURE_PATH_OFF) {
+                xvimagesink->secure_path = SECURE_PATH_OFF;
+                do_set_secure = TRUE;
+              }
+            }
+            static gboolean is_exist = FALSE;
+            gchar *attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_SECURE");
+            is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+            g_free(attr_name);
+
+            if (do_set_secure && is_exist) {
+              Atom atom_secure = None;
+              g_mutex_lock (xvimagesink->x_lock);
+              atom_secure = XInternAtom(xvimagesink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_SECURE", False);
+              if (atom_secure != None) {
+                if (XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_secure, xvimagesink->secure_path) != Success) {
+                  GST_ERROR_OBJECT(xvimagesink, "%d: XvSetPortAttribute: secure setting failed.", atom_secure);
+                } else {
+                  GST_WARNING_OBJECT(xvimagesink, "set contents path [%d] (0:NORMAL, 1:SECURE)", xvimagesink->secure_path);
+                }
+                XSync (xvimagesink->xcontext->disp, FALSE);
+              } else {
+                GST_ERROR_OBJECT(xvimagesink, "_USER_WM_PORT_ATTRIBUTE_SECURE is not existed");
+              }
+              g_mutex_unlock (xvimagesink->x_lock);
+            }
+
+            is_exist = FALSE;
+            attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_DRM_LEVEL");
+            is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+            g_free(attr_name);
+
 
-          GST_LOG_OBJECT(xvimagesink, "Ypaddr[%p],CbPaddr[%p],CrPaddr[%p]",
-                                      img_data->YPhyAddr, img_data->CbPhyAddr, img_data->CrPhyAddr );
+            if (xvimagesink->drm_level && is_exist) {
+              Atom atom_drm = None;
+              g_mutex_lock (xvimagesink->x_lock);
+              atom_drm = XInternAtom( xvimagesink->xcontext->disp,
+                                          "_USER_WM_PORT_ATTRIBUTE_DRM_LEVEL", False);
+              if (atom_drm != None) {
+                GST_INFO_OBJECT(xvimagesink, "DRM LEVEL -> 1");
+                if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+                                     xvimagesink->xcontext->xv_port_id,
+                                     atom_drm, xvimagesink->drm_level ) != Success) {
+                  GST_WARNING_OBJECT( xvimagesink, "Set DRM LEVEL 1 failed" );
+                }
+                XSync (xvimagesink->xcontext->disp, FALSE);
+                g_mutex_unlock (xvimagesink->x_lock);
+                xvimagesink->drm_level = DRM_LEVEL_0;
+              }
+            }
 
-          img_data->RotAngle = xvimagesink->rotate_angle;
-          img_data->VideoMode = xvimagesink->display_mode;
+            /* set current buffer */
+            xvimagesink->xvimage->current_buffer = buf;
+          } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FLUSH_BUFFER) {
+            /* Flush Buffer, we are going to push a new buffer for recieving return buffer event from X */
+            GST_WARNING_OBJECT(xvimagesink, "BUF_SHARE_METHOD_FLUSH_BUFFER case");
+            if (gst_xvimagesink_make_flush_buffer(xvimagesink)) {
+              img_data->bo[0] = xvimagesink->flush_buffer->bo[0];
+              img_data->bo[1] = xvimagesink->flush_buffer->bo[1];
+              img_data->bo[2] = xvimagesink->flush_buffer->bo[2];
+            } else {
+              g_mutex_unlock(xvimagesink->flow_lock);
+              return GST_FLOW_OK;
+            }
+          } else {
+            GST_WARNING("unknown buf_share_method type [%d]. skip xvimage put...",
+                        scmn_imgb->buf_share_method);
+            g_mutex_unlock (xvimagesink->flow_lock);
+            return GST_FLOW_OK;
+          }
         } else {
           GST_WARNING_OBJECT( xvimagesink, "xvimage->data is NULL. skip xvimage put..." );
+          g_mutex_unlock (xvimagesink->flow_lock);
           return GST_FLOW_OK;
         }
-        break;
+    } else if (xvimagesink->is_subpicture_format) {
+      GC gc;
+      xvimagesink->pixmap_for_subpicture = (Pixmap)GST_BUFFER_DATA(buf);
+      if(!xvimagesink->pixmap_for_subpicture) {
+        GST_ERROR("no pixmap");
+        g_mutex_unlock (xvimagesink->flow_lock);
+        return GST_FLOW_OK;
       }
-      default:
+      if(xvimagesink->video_width!=xvimagesink->external_width || xvimagesink->video_height!=xvimagesink->external_height) {
+        GST_ERROR("pixmap's size and current resolution are different");
+        g_mutex_unlock (xvimagesink->flow_lock);
+        return GST_FLOW_OK;
+      }
+      gc = XCreateGC (xvimagesink->xcontext->disp, xvimagesink->pixmap_for_subpicture, 0, 0);
+
+      GST_WARNING_OBJECT(xvimagesink, "xvimagesink pixmap ID : %p, port : %ld, GC : %p", xvimagesink->pixmap_for_subpicture,
+        xvimagesink->xcontext->xv_port_id, gc);
+
+      /* set error handler */
+      error_caught = FALSE;
+      handler = XSetErrorHandler(gst_xvimagesink_handle_xerror);
+
+      if(!xvimagesink->set_overlay_for_subpicture_just_once)
       {
-        GST_DEBUG("Normal format activated. fourcc = %d", xvimagesink->xvimage->im_format);
-        memcpy (xvimagesink->xvimage->xvimage->data,
-        GST_BUFFER_DATA (buf),
-        MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
-        break;
+        GST_LOG("setting attribute overlay");
+        atom_overlay = XInternAtom (xvimagesink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_OVERLAY", FALSE);
+        XvSetPortAttribute (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_overlay, 1);
+        XSync (xvimagesink->xcontext->disp, FALSE);
+        xvimagesink->set_overlay_for_subpicture_just_once = TRUE;
+      }
+      res = XvGetStill(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
+        xvimagesink->pixmap_for_subpicture, gc, 0, 0, xvimagesink->external_width, xvimagesink->external_height,
+        0, 0, xvimagesink->external_width, xvimagesink->external_height);
+      XSync (xvimagesink->xcontext->disp, FALSE);
+
+      GST_WARNING_OBJECT(xvimagesink, "BUFFER TS=%" GST_TIME_FORMAT ", DUR=%" GST_TIME_FORMAT ", SIZE=%d\n",
+                          GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)),
+                          GST_TIME_ARGS(GST_BUFFER_DURATION(buf)),
+                          GST_BUFFER_SIZE(buf));
+      if(gc) {
+        GST_DEBUG("FreeGC");
+        XFreeGC (xvimagesink->xcontext->disp, gc);
       }
+      if (error_caught)
+        GST_WARNING_OBJECT(xvimagesink, "XvGetStill error");
+      else
+        GST_WARNING_OBJECT(xvimagesink, "XvGetStill %s  ==> (width : %d, height : %d)", res == 0 ? "SUCCESS" : "FAIL", xvimagesink->external_width, xvimagesink->external_height);
+
+      /* Reset error handler */
+      if (handler) {
+        error_caught = FALSE;
+        XSetErrorHandler (handler);
+      }
+    } else {
+        GST_DEBUG("Normal format activated. fourcc = %d", xvimagesink->xvimage->im_format);
+
+#ifdef GST_EXT_ENABLE_HEVC
+        if(xvimagesink->need_combine_data == 1)
+        {
+            gst_xvimagesink_combine_i420_scmn_data(xvimagesink, buf);
+        }
+        else
+#endif
+        {
+            memcpy (xvimagesink->xvimage->xvimage->data,
+            GST_BUFFER_DATA (buf),
+            MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
+        }
+    }
+
+    g_mutex_unlock (xvimagesink->flow_lock);
+    ret = gst_xvimagesink_xvimage_put(xvimagesink, xvimagesink->xvimage);
+    if (!ret && !xvimagesink->is_subpicture_format) {
+      goto no_window;
     }
 #else /* GST_EXT_XV_ENHANCEMENT */
     memcpy (xvimagesink->xvimage->xvimage->data,
         GST_BUFFER_DATA (buf),
         MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
-#endif /* GST_EXT_XV_ENHANCEMENT */
 
     if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
       goto no_window;
+#endif /* GST_EXT_XV_ENHANCEMENT */
   }
 
   return GST_FLOW_OK;
@@ -3256,6 +5643,9 @@ no_image:
   {
     /* No image available. That's very bad ! */
     GST_WARNING_OBJECT (xvimagesink, "could not create image");
+#ifdef GST_EXT_XV_ENHANCEMENT
+    g_mutex_unlock (xvimagesink->flow_lock);
+#endif
     return GST_FLOW_ERROR;
   }
 no_window:
@@ -3270,6 +5660,11 @@ static gboolean
 gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event)
 {
   GstXvImageSink *xvimagesink = GST_XVIMAGESINK (sink);
+  if(GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)
+  {
+      if(vconf_set_int(VCONFKEY_XV_STATE, (xvimagesink->eos_received << 2) | XV_STATUS_SEEK))
+        GST_WARNING("vconf set fail");
+  }
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_TAG:{
@@ -3280,14 +5675,76 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event)
       gst_tag_list_get_string (l, GST_TAG_TITLE, &title);
 
       if (title) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+        if (!xvimagesink->get_pixmap_cb) {
+#endif
         GST_DEBUG_OBJECT (xvimagesink, "got tags, title='%s'", title);
         gst_xvimagesink_xwindow_set_title (xvimagesink, xvimagesink->xwindow,
             title);
 
         g_free (title);
+#ifdef GST_EXT_XV_ENHANCEMENT
+        }
+#endif
+      }
+      break;
+    }
+#ifdef GST_EXT_XV_ENHANCEMENT
+    case GST_EVENT_FLUSH_START:
+      GST_DEBUG_OBJECT (xvimagesink, "flush start");
+      break;
+    case GST_EVENT_FLUSH_STOP:
+      GST_DEBUG_OBJECT (xvimagesink, "flush stop");
+      xvimagesink->is_during_seek = TRUE;
+      break;
+    case GST_EVENT_CUSTOM_DOWNSTREAM:
+    {
+      const GstStructure *st = NULL;
+      st = gst_event_get_structure (event);
+      if(!st) {
+        GST_WARNING_OBJECT (xvimagesink, "could not get structure for custom downstream event");
+      } else {
+        if (gst_structure_has_name (st, "Content_Is_DRM_Playready")) {
+          GST_INFO_OBJECT (xvimagesink, "got a event for DRM playready");
+          xvimagesink->drm_level = DRM_LEVEL_1;
+          if (xvimagesink->drm_level && xvimagesink->xcontext) {
+            static gboolean is_exist = FALSE;
+            gchar *attr_name = g_strdup("_USER_WM_PORT_ATTRIBUTE_DRM_LEVEL");
+            is_exist = check_supportable_port_attr(xvimagesink, attr_name);
+            g_free(attr_name);
+
+            if(is_exist)
+            {
+              Atom atom_drm = None;
+              g_mutex_lock (xvimagesink->x_lock);
+              atom_drm = XInternAtom( xvimagesink->xcontext->disp,
+                                          "_USER_WM_PORT_ATTRIBUTE_DRM_LEVEL", False);
+              if (atom_drm != None) {
+                GST_INFO_OBJECT(xvimagesink, "DRM LEVEL -> 1");
+                if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+                                     xvimagesink->xcontext->xv_port_id,
+                                     atom_drm, xvimagesink->drm_level ) != Success) {
+                  GST_WARNING_OBJECT( xvimagesink, "Set DRM LEVEL 1 failed" );
+                }
+                XSync (xvimagesink->xcontext->disp, FALSE);
+                xvimagesink->drm_level = DRM_LEVEL_0;
+              }
+              g_mutex_unlock (xvimagesink->x_lock);
+            }
+          }
+        }
       }
       break;
     }
+    case GST_EVENT_EOS:
+      xvimagesink->eos_received = TRUE;
+      GST_DEBUG_OBJECT(xvimagesink, "got eos");
+      break;
+    case GST_EVENT_NEWSEGMENT:
+      xvimagesink->eos_received = FALSE;
+      GST_DEBUG_OBJECT(xvimagesink, "got newsegment event");
+      break;
+#endif
     default:
       break;
   }
@@ -3509,6 +5966,12 @@ reuse_last_caps:
   }
 
   if (!xvimage) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+    /* init aligned size */
+    xvimagesink->aligned_width = 0;
+    xvimagesink->aligned_height = 0;
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
     /* We found no suitable image in the pool. Creating... */
     GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
     xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection);
@@ -3652,19 +6115,137 @@ gst_xvimagesink_navigation_init (GstNavigationInterface * iface)
   iface->send_event = gst_xvimagesink_navigation_send_event;
 }
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+static void
+gst_xvimagesink_set_pixmap_handle (GstXOverlay * overlay, guintptr id)
+{
+  XID pixmap_id = id;
+  int i = 0;
+  GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
+  GstXPixmap *xpixmap = NULL;
+  int (*handler) (Display *, XErrorEvent *);
+
+  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
+
+  if (xvimagesink->subpicture)
+   return;
+
+  /* If the element has not initialized the X11 context try to do so */
+  if (!xvimagesink->xcontext && !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink))) {
+    /* we have thrown a GST_ELEMENT_ERROR now */
+    return;
+  }
+
+  gst_xvimagesink_update_colorbalance (xvimagesink);
+
+  GST_DEBUG_OBJECT( xvimagesink, "pixmap id : %d", pixmap_id );
+
+  /* if the returned pixmap_id is 0, set current pixmap index to -2 to skip putImage() */
+  if (pixmap_id == 0) {
+    xvimagesink->current_pixmap_idx = -2;
+    return;
+  }
+
+  g_mutex_lock (xvimagesink->x_lock);
+
+  for (i = 0; i < MAX_PIXMAP_NUM; i++) {
+    if (!xvimagesink->xpixmap[i]) {
+      Window root_window;
+      int cur_win_x = 0;
+      int cur_win_y = 0;
+      unsigned int cur_win_width = 0;
+      unsigned int cur_win_height = 0;
+      unsigned int cur_win_border_width = 0;
+      unsigned int cur_win_depth = 0;
+
+      GST_INFO_OBJECT( xvimagesink, "xpixmap[%d] is empty, create it with pixmap_id(%d)", i, pixmap_id );
+
+      xpixmap = g_new0 (GstXPixmap, 1);
+      if (xpixmap) {
+        xpixmap->pixmap = pixmap_id;
+
+        /* Get root window and size of current window */
+        XGetGeometry(xvimagesink->xcontext->disp, xpixmap->pixmap, &root_window,
+                     &cur_win_x, &cur_win_y, /* relative x, y */
+                     &cur_win_width, &cur_win_height,
+                     &cur_win_border_width, &cur_win_depth);
+        if (!cur_win_width || !cur_win_height) {
+          GST_INFO_OBJECT( xvimagesink, "cur_win_width(%d) or cur_win_height(%d) is null..", cur_win_width, cur_win_height );
+          g_mutex_unlock (xvimagesink->x_lock);
+          return;
+        }
+        xpixmap->width = cur_win_width;
+        xpixmap->height = cur_win_height;
+
+        if (!xvimagesink->render_rect.w)
+          xvimagesink->render_rect.w = cur_win_width;
+        if (!xvimagesink->render_rect.h)
+          xvimagesink->render_rect.h = cur_win_height;
+
+        /* Setting an error handler to catch failure */
+        error_caught = FALSE;
+        handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
+
+        /* Create a GC */
+        xpixmap->gc = XCreateGC (xvimagesink->xcontext->disp, xpixmap->pixmap, 0, NULL);
+
+        XSync(xvimagesink->xcontext->disp, FALSE);
+        if (error_caught) {
+          GST_ERROR_OBJECT(xvimagesink, "XCreateGC failed [gc:0x%x, pixmap id:%d]", xpixmap->gc, xpixmap->pixmap);
+        }
+        if (handler) {
+          error_caught = FALSE;
+          XSetErrorHandler (handler);
+        }
+
+        xvimagesink->xpixmap[i] = xpixmap;
+        xvimagesink->current_pixmap_idx = i;
+      } else {
+        GST_ERROR("failed to create xpixmap errno: %d", errno);
+      }
+
+      g_mutex_unlock (xvimagesink->x_lock);
+      return;
+
+    } else if (xvimagesink->xpixmap[i]->pixmap == pixmap_id) {
+      GST_DEBUG_OBJECT( xvimagesink, "found xpixmap[%d]->pixmap : %d", i, pixmap_id );
+      xvimagesink->current_pixmap_idx = i;
+
+      g_mutex_unlock (xvimagesink->x_lock);
+      return;
+
+    } else {
+      continue;
+    }
+  }
+
+  GST_ERROR_OBJECT( xvimagesink, "could not find the pixmap id(%d) in xpixmap array", pixmap_id );
+  xvimagesink->current_pixmap_idx = -1;
+
+  g_mutex_unlock (xvimagesink->x_lock);
+  return;
+}
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
 static void
 gst_xvimagesink_set_window_handle (GstXOverlay * overlay, guintptr id)
 {
   XID xwindow_id = id;
   GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
   GstXWindow *xwindow = NULL;
+#ifdef GST_EXT_XV_ENHANCEMENT
+  GstState current_state = GST_STATE_NULL;
+  int (*handler) (Display *, XErrorEvent *);
+#endif /* GST_EXT_XV_ENHANCEMENT */
 
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
 
   g_mutex_lock (xvimagesink->flow_lock);
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-  GST_INFO_OBJECT( xvimagesink, "ENTER, id : %d", xwindow_id );
+  gst_element_get_state(GST_ELEMENT(xvimagesink), &current_state, NULL, 0);
+  GST_WARNING_OBJECT(xvimagesink, "ENTER, id : %d, current state : %d",
+                                  xwindow_id, current_state);
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   /* If we already use that window return */
@@ -3722,7 +6303,8 @@ gst_xvimagesink_set_window_handle (GstXOverlay * overlay, guintptr id)
     /* Set the event we want to receive and create a GC */
     g_mutex_lock (xvimagesink->x_lock);
 
-    XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr);
+    if(!xvimagesink->is_pixmap)
+      XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr);
 
     xwindow->width = attr.width;
     xwindow->height = attr.height;
@@ -3733,20 +6315,59 @@ gst_xvimagesink_set_window_handle (GstXOverlay * overlay, guintptr id)
       xvimagesink->render_rect.h = attr.height;
     }
     if (xvimagesink->handle_events) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xcontext->root, StructureNotifyMask | SubstructureNotifyMask);
+      XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
+          StructureNotifyMask | PointerMotionMask | KeyPressMask |
+          KeyReleaseMask | PropertyChangeMask);
+#else
       XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
           StructureNotifyMask | PointerMotionMask | KeyPressMask |
           KeyReleaseMask);
-    }
+#endif
 
+    }
+#ifdef GST_EXT_XV_ENHANCEMENT
+    /* Setting an error handler to catch failure */
+    error_caught = FALSE;
+    handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
+#endif
     xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
         xwindow->win, 0, NULL);
+#ifdef GST_EXT_XV_ENHANCEMENT
+    XSync(xvimagesink->xcontext->disp, FALSE);
+    if (error_caught) {
+      GST_ERROR_OBJECT(xvimagesink, "XCreateGC failed [gc:0x%x, xid:%d]", xwindow->gc, xwindow->win);
+    }
+    if (handler) {
+      error_caught = FALSE;
+      XSetErrorHandler (handler);
+    }
+#endif
     g_mutex_unlock (xvimagesink->x_lock);
   }
 
   if (xwindow)
     xvimagesink->xwindow = xwindow;
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+  xvimagesink->xid_updated = TRUE;
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
   g_mutex_unlock (xvimagesink->flow_lock);
+
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (current_state == GST_STATE_PAUSED) {
+    GstBuffer *last_buffer = NULL;
+    g_object_get(G_OBJECT(xvimagesink), "last-buffer", &last_buffer, NULL);
+    GST_WARNING_OBJECT(xvimagesink, "PASUED state: window handle is updated. last buffer %p", last_buffer);
+    if (last_buffer) {
+      gst_xvimagesink_show_frame((GstVideoSink *)xvimagesink, last_buffer);
+      gst_buffer_unref(last_buffer);
+      last_buffer = NULL;
+    }
+  }
+#endif /* GST_EXT_XV_ENHANCEMENT */
 }
 
 static void
@@ -3756,11 +6377,9 @@ gst_xvimagesink_expose (GstXOverlay * overlay)
 
   gst_xvimagesink_xwindow_update_geometry (xvimagesink);
 #ifdef GST_EXT_XV_ENHANCEMENT
-  GST_INFO_OBJECT( xvimagesink, "Overlay window exposed. update it");
-  gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
-#else /* GST_EXT_XV_ENHANCEMENT */
-  gst_xvimagesink_xvimage_put (xvimagesink, NULL);
+  GST_INFO_OBJECT(xvimagesink, "Overlay window exposed. update it");
 #endif /* GST_EXT_XV_ENHANCEMENT */
+  gst_xvimagesink_xvimage_put (xvimagesink, NULL);
 }
 
 static void
@@ -3782,12 +6401,26 @@ gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
 
   if (handle_events) {
     if (xvimagesink->xwindow->internal) {
+#ifdef GST_EXT_XV_ENHANCEMENT
+      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xcontext->root, StructureNotifyMask | SubstructureNotifyMask);
+#endif
       XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
+#ifdef GST_EXT_XV_ENHANCEMENT
+          ExposureMask | StructureNotifyMask | PointerMotionMask | VisibilityChangeMask | PropertyChangeMask |
+#else /* GST_EXT_XV_ENHANCEMENT */
           ExposureMask | StructureNotifyMask | PointerMotionMask |
+#endif /* GST_EXT_XV_ENHANCEMENT */
           KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
     } else {
+#ifdef GST_EXT_XV_ENHANCEMENT
+      XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xcontext->root, StructureNotifyMask | SubstructureNotifyMask);
+#endif
       XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
+#ifdef GST_EXT_XV_ENHANCEMENT
+          ExposureMask | StructureNotifyMask | PointerMotionMask | VisibilityChangeMask | PropertyChangeMask |
+#else /* GST_EXT_XV_ENHANCEMENT */
           ExposureMask | StructureNotifyMask | PointerMotionMask |
+#endif /* GST_EXT_XV_ENHANCEMENT */
           KeyPressMask | KeyReleaseMask);
     }
   } else {
@@ -4162,25 +6795,52 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
     case PROP_DISPLAY_MODE:
     {
       int set_mode = g_value_get_enum (value);
+      g_mutex_lock(xvimagesink->flow_lock);
+      xvimagesink->display_mode = set_mode;
+      if(!xvimagesink->get_pixmap_cb && !xvimagesink->subpicture) {
+        if(xvimagesink->display_mode==DISPLAY_MODE_PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN) {
+          if(!xvimagesink->is_multi_window || (GST_STATE(xvimagesink) == GST_STATE_PLAYING)) {
+            set_display_mode(xvimagesink->xcontext, xvimagesink->display_mode);
+          } else {
+            GST_WARNING_OBJECT(xvimagesink, "display-mode will be set later. just save value now(%d)", xvimagesink->display_mode);
+          }
+        } else if(xvimagesink->display_mode==DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_CLONE){
+          if(xvimagesink->is_multi_window && (GST_STATE(xvimagesink) != GST_STATE_PLAYING)) {
+            set_display_mode(xvimagesink->xcontext, xvimagesink->display_mode);
+          } else {
+            GST_WARNING_OBJECT(xvimagesink, "display-mode will be set later. just save value now(%d)", xvimagesink->display_mode);
+          }
+        } else {
+          GST_WARNING_OBJECT(xvimagesink, "unsupported format(%d)", xvimagesink->display_mode);
+        }
+      }
+      g_mutex_unlock(xvimagesink->flow_lock);
+    }
+      break;
+    case PROP_CSC_RANGE:
+    {
+      int set_range = g_value_get_enum (value);
 
       g_mutex_lock(xvimagesink->flow_lock);
       g_mutex_lock(xvimagesink->x_lock);
 
-      if (xvimagesink->display_mode != set_mode) {
-        if (xvimagesink->xcontext) {
-          /* set display mode */
-          if (set_display_mode(xvimagesink->xcontext, set_mode)) {
-            xvimagesink->display_mode = set_mode;
+      if (xvimagesink->csc_range != set_range) {
+        if (xvimagesink->xcontext && !xvimagesink->subpicture) {
+          /* set color space range */
+          if (set_csc_range(xvimagesink->xcontext, set_range)) {
+            xvimagesink->csc_range = set_range;
           } else {
-            GST_WARNING_OBJECT(xvimagesink, "display mode[%d] set failed.", set_mode);
+            GST_WARNING_OBJECT(xvimagesink, "csc range[%d] set failed.", set_range);
           }
         } else {
           /* "xcontext" is not created yet. It will be applied when xcontext is created. */
-          GST_INFO_OBJECT(xvimagesink, "xcontext is NULL. display-mode will be set later.");
-          xvimagesink->display_mode = set_mode;
+          GST_INFO_OBJECT(xvimagesink, "xcontext is NULL. color space range will be set later.");
+          xvimagesink->csc_range = set_range;
         }
+      } else if (xvimagesink->subpicture) {
+        GST_WARNING("skip to set csc range, because it is subpicture format.");
       } else {
-        GST_INFO_OBJECT(xvimagesink, "skip display mode %d, because current mode is same", set_mode);
+        GST_INFO_OBJECT(xvimagesink, "skip to set csc range %d, because current is same", set_range);
       }
 
       g_mutex_unlock(xvimagesink->x_lock);
@@ -4190,44 +6850,86 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
     case PROP_DISPLAY_GEOMETRY_METHOD:
       xvimagesink->display_geometry_method = g_value_get_enum (value);
       GST_LOG("Overlay geometry changed. update it");
-      gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
+      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED || xvimagesink->eos_received) {
+        gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
+      }
+      break;
+    case PROP_FLIP:
+      xvimagesink->flip = g_value_get_enum(value);
       break;
     case PROP_ROTATE_ANGLE:
       xvimagesink->rotate_angle = g_value_get_enum (value);
-      xvimagesink->rotate_changed = TRUE;
+      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED || xvimagesink->eos_received) {
+        gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
+      }
       break;
     case PROP_VISIBLE:
       g_mutex_lock( xvimagesink->flow_lock );
       g_mutex_lock( xvimagesink->x_lock );
 
+      GST_WARNING_OBJECT(xvimagesink, "set visible %d", g_value_get_boolean(value));
+
       if (xvimagesink->visible && (g_value_get_boolean(value) == FALSE)) {
-        Atom atom_stream = XInternAtom( xvimagesink->xcontext->disp,
-                                        "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False );
-        if (atom_stream != None) {
-          if (XvSetPortAttribute(xvimagesink->xcontext->disp,
-                                 xvimagesink->xcontext->xv_port_id,
-                                 atom_stream, 0 ) != Success) {
-            GST_WARNING_OBJECT( xvimagesink, "Set visible FALSE failed" );
+        if (xvimagesink->xcontext) {
+#if 0
+          Atom atom_stream = XInternAtom( xvimagesink->xcontext->disp,
+                                          "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False );
+          if (atom_stream != None) {
+            GST_WARNING_OBJECT(xvimagesink, "Visible FALSE -> CALL STREAM_OFF");
+            if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+                                   xvimagesink->xcontext->xv_port_id,
+                                   atom_stream, 0 ) != Success) {
+              GST_WARNING_OBJECT( xvimagesink, "Set visible FALSE failed" );
+            }
+          }
+#endif
+          xvimagesink->visible = g_value_get_boolean (value);
+          if ( xvimagesink->get_pixmap_cb ) {
+            if (xvimagesink->xpixmap[0] && xvimagesink->xpixmap[0]->pixmap) {
+              XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xpixmap[0]->pixmap);
+              }
+          } else {
+            if(xvimagesink->xwindow->win)
+              XvStopVideo(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xwindow->win);
           }
-
           XSync( xvimagesink->xcontext->disp, FALSE );
+        } else {
+          GST_WARNING_OBJECT( xvimagesink, "xcontext is null");
+          xvimagesink->visible = g_value_get_boolean (value);
         }
       } else if (!xvimagesink->visible && (g_value_get_boolean(value) == TRUE)) {
+        xvimagesink->visible = g_value_get_boolean (value);
         g_mutex_unlock( xvimagesink->x_lock );
         g_mutex_unlock( xvimagesink->flow_lock );
-        GST_INFO_OBJECT( xvimagesink, "Set visible as TRUE. Update it." );
         gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
         g_mutex_lock( xvimagesink->flow_lock );
         g_mutex_lock( xvimagesink->x_lock );
       }
 
-      xvimagesink->visible = g_value_get_boolean (value);
+      GST_INFO("set visible(%d) done", xvimagesink->visible);
 
       g_mutex_unlock( xvimagesink->x_lock );
       g_mutex_unlock( xvimagesink->flow_lock );
       break;
     case PROP_ZOOM:
-      xvimagesink->zoom = g_value_get_int (value);
+      xvimagesink->zoom = g_value_get_float (value);
+      break;
+    case PROP_ZOOM_POS_X:
+      xvimagesink->zoom_pos_x = g_value_get_int (value);
+      break;
+    case PROP_ZOOM_POS_Y:
+      xvimagesink->zoom_pos_y = g_value_get_int (value);
+      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED || xvimagesink->eos_received) {
+        gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
+      }
+      break;
+    case PROP_ORIENTATION:
+      xvimagesink->orientation = g_value_get_enum (value);
+      GST_INFO("Orientation(%d) is changed", xvimagesink->orientation);
+      break;
+    case PROP_DST_ROI_MODE:
+      xvimagesink->dst_roi_mode = g_value_get_enum (value);
+      GST_INFO("Overlay geometry(%d) for ROI is changed", xvimagesink->dst_roi_mode);
       break;
     case PROP_DST_ROI_X:
       xvimagesink->dst_roi.x = g_value_get_int (value);
@@ -4241,18 +6943,134 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
     case PROP_DST_ROI_H:
       xvimagesink->dst_roi.h = g_value_get_int (value);
       break;
+    case PROP_SRC_CROP_X:
+      xvimagesink->src_crop.x = g_value_get_int (value);
+      break;
+    case PROP_SRC_CROP_Y:
+      xvimagesink->src_crop.y = g_value_get_int (value);
+      break;
+    case PROP_SRC_CROP_W:
+      xvimagesink->src_crop.w = g_value_get_int (value);
+      break;
+    case PROP_SRC_CROP_H:
+      xvimagesink->src_crop.h = g_value_get_int (value);
+      break;
     case PROP_STOP_VIDEO:
       xvimagesink->stop_video = g_value_get_int (value);
       g_mutex_lock( xvimagesink->flow_lock );
 
       if( xvimagesink->stop_video )
       {
-        GST_INFO_OBJECT( xvimagesink, "Xwindow CLEAR when set video-stop property" );
-        gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
+        if ( xvimagesink->get_pixmap_cb ) {
+          if (xvimagesink->xpixmap[0] && xvimagesink->xpixmap[0]->pixmap) {
+            g_mutex_lock (xvimagesink->x_lock);
+            GST_WARNING_OBJECT( xvimagesink, "calling XvStopVideo()" );
+            XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xpixmap[0]->pixmap);
+            g_mutex_unlock (xvimagesink->x_lock);
+          }
+        } else {
+          GST_INFO_OBJECT( xvimagesink, "Xwindow CLEAR when set video-stop property" );
+          gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
+        }
       }
 
       g_mutex_unlock( xvimagesink->flow_lock );
       break;
+    case PROP_PIXMAP_CB:
+    {
+      void *cb_func;
+      cb_func = g_value_get_pointer(value);
+      if (cb_func) {
+        if (xvimagesink->get_pixmap_cb) {
+          int i = 0;
+          if (xvimagesink->xpixmap[0] && xvimagesink->xpixmap[0]->pixmap) {
+            g_mutex_lock (xvimagesink->x_lock);
+            GST_WARNING_OBJECT( xvimagesink, "calling XvStopVideo()" );
+            XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xpixmap[0]->pixmap);
+            g_mutex_unlock (xvimagesink->x_lock);
+          }
+          for (i = 0; i < MAX_PIXMAP_NUM; i++) {
+            if (xvimagesink->xpixmap[i]) {
+              gst_xvimagesink_xpixmap_destroy (xvimagesink, xvimagesink->xpixmap[i]);
+              xvimagesink->xpixmap[i] = NULL;
+            }
+          }
+        }
+        xvimagesink->get_pixmap_cb = cb_func;
+        GST_INFO_OBJECT (xvimagesink, "Set callback(0x%x) for getting pixmap id", xvimagesink->get_pixmap_cb);
+      }
+      break;
+    }
+    case PROP_PIXMAP_CB_USER_DATA:
+    {
+      void *user_data;
+      user_data = g_value_get_pointer(value);
+      if (user_data) {
+        xvimagesink->get_pixmap_cb_user_data = user_data;
+        GST_INFO_OBJECT (xvimagesink, "Set user data(0x%x) for getting pixmap id", xvimagesink->get_pixmap_cb_user_data);
+      }
+      break;
+    }
+    case PROP_SUBPICTURE:
+      xvimagesink->subpicture = g_value_get_boolean (value);
+    break;
+    case PROP_EXTERNAL_WIDTH:
+    {
+      xvimagesink->external_width = g_value_get_int (value);
+      GST_LOG("[set property] xvimagesink->external_width : %d", xvimagesink->external_width);
+      break;
+    }
+    case PROP_EXTERNAL_HEIGHT:
+    {
+      xvimagesink->external_height = g_value_get_int (value);
+      GST_LOG("[set property] xvimagesink->external_height : %d", xvimagesink->external_height);
+      break;
+    }
+    case PROP_ENABLE_FLUSH_BUFFER:
+      xvimagesink->enable_flush_buffer = g_value_get_boolean(value);
+      break;
+    case PROP_PIXMAP:
+      xvimagesink->is_pixmap = g_value_get_boolean(value);
+      break;
+    case PROP_HIDED_WINDOW:
+    {
+      xvimagesink->is_hided_subpicture = g_value_get_boolean(value);
+      GST_WARNING_OBJECT(xvimagesink, "update hided_window %d", xvimagesink->is_hided_subpicture);
+      break;
+    }
+    case PROP_QUICKPANEL_ON:
+    {
+      xvimagesink->is_quick_panel_on_subpicture = g_value_get_boolean(value);
+      GST_WARNING_OBJECT(xvimagesink, "update quick panel status %d", xvimagesink->is_quick_panel_on_subpicture);
+      break;
+    }
+    case PROP_MULTIWINDOW_ACTIVE:
+    {
+      xvimagesink->is_multi_window_subpicture = g_value_get_boolean(value);
+      GST_WARNING_OBJECT(xvimagesink, "update multi-window status %d", xvimagesink->is_multi_window_subpicture);
+      break;
+    }
+    case PROP_KEEP_EXTERNAL_FULLSCREEN_POST:
+    {
+      xvimagesink->keep_external_fullscreen_post = g_value_get_boolean(value);
+      GST_WARNING_OBJECT(xvimagesink, "set property %d for setting _USER_WM_PORT_ATTRIBUTE_KEEP_EXT", xvimagesink->keep_external_fullscreen_post);
+      if(xvimagesink->keep_external_fullscreen_post) {
+        Atom atom_keep_ext;
+        atom_keep_ext = XInternAtom (xvimagesink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_KEEP_EXT", False);
+        if(XvSetPortAttribute (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_keep_ext , 1) != Success)
+        {
+          GST_WARNING("set atom_keep_ext fail");
+        }
+      }
+      break;
+    }
+    case PROP_KEEP_EXTERNAL_FULLSCREEN_PREV:
+    {
+      xvimagesink->keep_external_fullscreen_prev = g_value_get_boolean(value);
+      GST_WARNING_OBJECT(xvimagesink, "set property %d for keeping external display to full screen", xvimagesink->keep_external_fullscreen_prev);
+      break;
+    }
+
 #endif /* GST_EXT_XV_ENHANCEMENT */
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -4346,9 +7164,15 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
     case PROP_DISPLAY_MODE:
       g_value_set_enum (value, xvimagesink->display_mode);
       break;
+    case PROP_CSC_RANGE:
+      g_value_set_enum (value, xvimagesink->csc_range);
+      break;
     case PROP_DISPLAY_GEOMETRY_METHOD:
       g_value_set_enum (value, xvimagesink->display_geometry_method);
       break;
+    case PROP_FLIP:
+      g_value_set_enum(value, xvimagesink->flip);
+      break;
     case PROP_ROTATE_ANGLE:
       g_value_set_enum (value, xvimagesink->rotate_angle);
       break;
@@ -4356,7 +7180,19 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
       g_value_set_boolean (value, xvimagesink->visible);
       break;
     case PROP_ZOOM:
-      g_value_set_int (value, xvimagesink->zoom);
+      g_value_set_float (value, xvimagesink->zoom);
+      break;
+    case PROP_ZOOM_POS_X:
+      g_value_set_int (value, xvimagesink->zoom_pos_x);
+      break;
+    case PROP_ZOOM_POS_Y:
+      g_value_set_int (value, xvimagesink->zoom_pos_y);
+      break;
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, xvimagesink->orientation);
+      break;
+    case PROP_DST_ROI_MODE:
+      g_value_set_enum (value, xvimagesink->dst_roi_mode);
       break;
     case PROP_DST_ROI_X:
       g_value_set_int (value, xvimagesink->dst_roi.x);
@@ -4370,9 +7206,57 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
     case PROP_DST_ROI_H:
       g_value_set_int (value, xvimagesink->dst_roi.h);
       break;
+    case PROP_SRC_CROP_X:
+      g_value_set_int (value, xvimagesink->src_crop.x);
+      break;
+    case PROP_SRC_CROP_Y:
+      g_value_set_int (value, xvimagesink->src_crop.y);
+      break;
+    case PROP_SRC_CROP_W:
+      g_value_set_int (value, xvimagesink->src_crop.w);
+      break;
+    case PROP_SRC_CROP_H:
+      g_value_set_int (value, xvimagesink->src_crop.h);
+      break;
     case PROP_STOP_VIDEO:
       g_value_set_int (value, xvimagesink->stop_video);
       break;
+    case PROP_PIXMAP_CB:
+      g_value_set_pointer (value, xvimagesink->get_pixmap_cb);
+      break;
+    case PROP_PIXMAP_CB_USER_DATA:
+      g_value_set_pointer (value, xvimagesink->get_pixmap_cb_user_data);
+      break;
+    case PROP_SUBPICTURE:
+      g_value_set_boolean (value, xvimagesink->subpicture);
+      break;
+    case PROP_EXTERNAL_WIDTH:
+      g_value_set_int (value, xvimagesink->external_width);
+      break;
+    case PROP_EXTERNAL_HEIGHT:
+      g_value_set_int (value, xvimagesink->external_height);
+      break;
+    case PROP_ENABLE_FLUSH_BUFFER:
+      g_value_set_boolean(value, xvimagesink->enable_flush_buffer);
+      break;
+    case PROP_PIXMAP:
+      g_value_set_boolean(value, xvimagesink->is_pixmap);
+      break;
+    case PROP_HIDED_WINDOW:
+      g_value_set_boolean(value, xvimagesink->is_hided_subpicture);
+      break;
+    case PROP_QUICKPANEL_ON:
+      g_value_set_boolean(value, xvimagesink->is_quick_panel_on_subpicture);
+      break;
+    case PROP_MULTIWINDOW_ACTIVE:
+      g_value_set_boolean(value, xvimagesink->is_multi_window_subpicture);
+      break;
+    case PROP_KEEP_EXTERNAL_FULLSCREEN_POST:
+      g_value_set_boolean(value, xvimagesink->keep_external_fullscreen_post);
+     break;
+    case PROP_KEEP_EXTERNAL_FULLSCREEN_PREV:
+      g_value_set_boolean(value, xvimagesink->keep_external_fullscreen_prev);
+     break;
 #endif /* GST_EXT_XV_ENHANCEMENT */
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -4418,7 +7302,31 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
     gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
     xvimagesink->xwindow = NULL;
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if(xvimagesink->is_subpicture_format && xvimagesink->pixmap_for_subpicture) {
+      GST_INFO("calling XvStopVideo() for %d port [pixmap : %p]", xvimagesink->xcontext->xv_port_id, xvimagesink->pixmap_for_subpicture);
+      XvStopVideo(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->pixmap_for_subpicture);
+      xvimagesink->pixmap_for_subpicture = 0;
+  }
 
+  if (xvimagesink->get_pixmap_cb) {
+    int i = 0;
+    if (xvimagesink->xpixmap[0] && xvimagesink->xpixmap[0]->pixmap) {
+      g_mutex_lock (xvimagesink->x_lock);
+      GST_WARNING_OBJECT( xvimagesink, "calling XvStopVideo()" );
+      XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, xvimagesink->xpixmap[0]->pixmap);
+      g_mutex_unlock (xvimagesink->x_lock);
+    }
+    for (i = 0; i < MAX_PIXMAP_NUM; i++) {
+      if (xvimagesink->xpixmap[i]) {
+        gst_xvimagesink_xpixmap_destroy (xvimagesink, xvimagesink->xpixmap[i]);
+        xvimagesink->xpixmap[i] = NULL;
+      }
+    }
+    xvimagesink->get_pixmap_cb = NULL;
+    xvimagesink->get_pixmap_cb_user_data = NULL;
+  }
+#endif /* GST_EXT_XV_ENHANCEMENT */
   xvimagesink->render_rect.x = xvimagesink->render_rect.y =
       xvimagesink->render_rect.w = xvimagesink->render_rect.h = 0;
   xvimagesink->have_render_rect = FALSE;
@@ -4459,6 +7367,12 @@ gst_xvimagesink_finalize (GObject * object)
     g_mutex_free (xvimagesink->pool_lock);
     xvimagesink->pool_lock = NULL;
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
+  if (xvimagesink->display_buffer_lock) {
+    g_mutex_free (xvimagesink->display_buffer_lock);
+    xvimagesink->display_buffer_lock = NULL;
+  }
+#endif /* GST_EXT_XV_ENHANCEMENT */
 
   g_free (xvimagesink->media_title);
 
@@ -4469,6 +7383,11 @@ static void
 gst_xvimagesink_init (GstXvImageSink * xvimagesink,
     GstXvImageSinkClass * xvimagesinkclass)
 {
+#ifdef GST_EXT_XV_ENHANCEMENT
+  int i;
+  int j;
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
   xvimagesink->display_name = NULL;
   xvimagesink->adaptor_no = 0;
   xvimagesink->xcontext = NULL;
@@ -4508,17 +7427,27 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink,
   xvimagesink->draw_borders = TRUE;
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-  xvimagesink->display_mode = DISPLAY_MODE_DEFAULT;
-  xvimagesink->rotate_changed = TRUE;
+  xvimagesink->xid_updated = FALSE;
+  xvimagesink->display_mode = DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_CLONE;
+  xvimagesink->csc_range = CSC_RANGE_NARROW;
   xvimagesink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
+  xvimagesink->flip = DEF_DISPLAY_FLIP;
   xvimagesink->rotate_angle = DEGREE_270;
   xvimagesink->visible = TRUE;
-  xvimagesink->zoom = 1;
+  xvimagesink->zoom = 1.0;
+  xvimagesink->zoom_pos_x = -1;
+  xvimagesink->zoom_pos_y = -1;
   xvimagesink->rotation = -1;
+  xvimagesink->dst_roi_mode = DEF_ROI_DISPLAY_GEOMETRY_METHOD;
+  xvimagesink->orientation = DEGREE_0;
   xvimagesink->dst_roi.x = 0;
   xvimagesink->dst_roi.y = 0;
   xvimagesink->dst_roi.w = 0;
   xvimagesink->dst_roi.h = 0;
+  xvimagesink->src_crop.x = 0;
+  xvimagesink->src_crop.y = 0;
+  xvimagesink->src_crop.w = 0;
+  xvimagesink->src_crop.h = 0;
   xvimagesink->xim_transparenter = NULL;
   xvimagesink->scr_w = 0;
   xvimagesink->scr_h = 0;
@@ -4526,6 +7455,50 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink,
   xvimagesink->aligned_height = 0;
   xvimagesink->stop_video = FALSE;
   xvimagesink->is_hided = FALSE;
+  xvimagesink->is_quick_panel_on = FALSE;
+  xvimagesink->is_multi_window = FALSE;
+  xvimagesink->drm_fd = -1;
+  xvimagesink->current_pixmap_idx = -1;
+  xvimagesink->get_pixmap_cb = NULL;
+  xvimagesink->get_pixmap_cb_user_data = NULL;
+
+  for (i = 0 ; i < DISPLAYING_BUFFERS_MAX_NUM ; i++) {
+    xvimagesink->displaying_buffers[i].buffer = NULL;
+    for (j = 0 ; j < XV_BUF_PLANE_NUM ; j++) {
+      xvimagesink->displaying_buffers[i].gem_name[j] = 0;
+      xvimagesink->displaying_buffers[i].gem_handle[j] = 0;
+      xvimagesink->displaying_buffers[i].dmabuf_fd[j] = 0;
+      xvimagesink->displaying_buffers[i].ref_count = 0;
+    }
+  }
+
+  xvimagesink->display_buffer_lock = g_mutex_new ();
+
+  xvimagesink->displayed_buffer_count = 0;
+  xvimagesink->displaying_buffer_count = 0;
+  xvimagesink->is_zero_copy_format = FALSE;
+  xvimagesink->secure_path = SECURE_PATH_INIT;
+  xvimagesink->drm_level = DRM_LEVEL_0;
+  xvimagesink->last_added_buffer_index = -1;
+  xvimagesink->bufmgr = NULL;
+  xvimagesink->flush_buffer = NULL;
+  xvimagesink->enable_flush_buffer = TRUE;
+  xvimagesink->pixmap_for_subpicture = 0;
+  xvimagesink->is_subpicture_format = FALSE;
+  xvimagesink->set_overlay_for_subpicture_just_once = FALSE;
+  xvimagesink->subpicture = FALSE;
+  xvimagesink->external_width = 0;
+  xvimagesink->external_height = 0;
+  xvimagesink->skip_frame_due_to_external_dev = FALSE;
+  xvimagesink->is_hided_subpicture = FALSE;
+  xvimagesink->is_quick_panel_on_subpicture = FALSE;
+  xvimagesink->is_multi_window_subpicture = FALSE;
+  xvimagesink->keep_external_fullscreen_post = FALSE;
+  xvimagesink->keep_external_fullscreen_prev = FALSE;
+  if(!XInitThreads())
+    GST_WARNING("FAIL to call XInitThreads()");
+  if(vconf_set_int(VCONFKEY_XV_STATE, (xvimagesink->eos_received << 2) | XV_STATUS_NULL))
+    GST_WARNING("vconf set fail");
 #endif /* GST_EXT_XV_ENHANCEMENT */
 }
 
@@ -4600,6 +7573,14 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
       g_param_spec_string ("device-name", "Adaptor name",
           "The name of the video adaptor", NULL,
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_EXTERNAL_WIDTH,
+      g_param_spec_int ("external-width", "external width",
+          "width of external display", 0, G_MAXINT,
+          0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_EXTERNAL_HEIGHT,
+      g_param_spec_int ("external-height", "external height",
+          "height of external display", 0, G_MAXINT,
+          0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   /**
    * GstXvImageSink:handle-expose
    *
@@ -4694,7 +7675,18 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
   g_object_class_install_property(gobject_class, PROP_DISPLAY_MODE,
     g_param_spec_enum("display-mode", "Display Mode",
       "Display device setting",
-      GST_TYPE_XVIMAGESINK_DISPLAY_MODE, DISPLAY_MODE_DEFAULT,
+      GST_TYPE_XVIMAGESINK_DISPLAY_MODE, DISPLAY_MODE_PRI_VIDEO_ON_AND_SEC_VIDEO_CLONE,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:csc-range
+   *
+   * select color space range
+   */
+  g_object_class_install_property(gobject_class, PROP_CSC_RANGE,
+    g_param_spec_enum("csc-range", "Color Space Range",
+      "Color space range setting",
+      GST_TYPE_XVIMAGESINK_CSC_RANGE, CSC_RANGE_NARROW,
       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
@@ -4709,6 +7701,17 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
+   * GstXvImageSink:display-flip
+   *
+   * Display flip setting
+   */
+  g_object_class_install_property(gobject_class, PROP_FLIP,
+    g_param_spec_enum("flip", "Display flip",
+      "Flip for display",
+      GST_TYPE_XVIMAGESINK_FLIP, DEF_DISPLAY_FLIP,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
    * GstXvImageSink:rotate
    *
    * Draw rotation angle setting
@@ -4732,14 +7735,56 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
   /**
    * GstXvImageSink:zoom
    *
-   * Scale small area of screen to 2X, 3X, ... , 9X
+   * Scale small area of screen to 1X~ 9X
    */
   g_object_class_install_property (gobject_class, PROP_ZOOM,
-      g_param_spec_int ("zoom", "Zoom",
-          "Zooms screen as nX", 1, 9, 1,
+      g_param_spec_float ("zoom", "Zoom",
+          "Zooms screen as nX", 1.0, 9.0, 1.0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:zoom-pos-x
+   *
+   * Standard x-position of zoom
+   */
+  g_object_class_install_property (gobject_class, PROP_ZOOM_POS_X,
+      g_param_spec_int ("zoom-pos-x", "Zoom Position X",
+          "Standard x-position of zoom", -1, 3840, -1,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
+   * GstXvImageSink:zoom-pos-y
+   *
+   * Standard y-position of zoom
+   */
+  g_object_class_install_property (gobject_class, PROP_ZOOM_POS_Y,
+      g_param_spec_int ("zoom-pos-y", "Zoom Position Y",
+          "Standard y-position of zoom", -1, 3840, -1,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:dst-roi-mode
+   *
+   * Display geometrical method of ROI setting
+   */
+  g_object_class_install_property(gobject_class, PROP_DST_ROI_MODE,
+    g_param_spec_enum("dst-roi-mode", "Display geometry method of ROI",
+      "Geometrical method of ROI for display",
+      GST_TYPE_XVIMAGESINK_ROI_DISPLAY_GEOMETRY_METHOD, DEF_ROI_DISPLAY_GEOMETRY_METHOD,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:orientation
+   *
+   * Orientation information which will be used for ROI/ZOOM
+   */
+  g_object_class_install_property(gobject_class, PROP_ORIENTATION,
+    g_param_spec_enum("orientation", "Orientation information used for ROI/ZOOM",
+      "Orientation information for display",
+      GST_TYPE_XVIMAGESINK_ROTATE_ANGLE, DEGREE_0,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
    * GstXvImageSink:dst-roi-x
    *
    * X value of Destination ROI
@@ -4788,6 +7833,220 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
       g_param_spec_int ("stop-video", "Stop-Video",
           "Stop video for releasing video source buffer", 0, 1, 0,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_PIXMAP_CB,
+      g_param_spec_pointer("pixmap-id-callback", "Pixmap-Id-Callback",
+          "pointer of callback function for getting pixmap id", G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_PIXMAP_CB_USER_DATA,
+      g_param_spec_pointer("pixmap-id-callback-userdata", "Pixmap-Id-Callback-Userdata",
+          "pointer of user data of callback function for getting pixmap id", G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_SUBPICTURE,
+      g_param_spec_boolean ("subpicture", "Subpicture",
+          "identifier of player for supporting subpicture", FALSE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:src-crop-x
+   *
+   * X value of video source crop
+   */
+  g_object_class_install_property (gobject_class, PROP_SRC_CROP_X,
+      g_param_spec_int ("src-crop-x", "Source Crop X",
+          "X value of Video source crop(only available if LETTER_BOX or FULL_SCREEN mode)", 0, XV_SCREEN_SIZE_WIDTH, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:src-crop-y
+   *
+   * Y value of video source crop
+   */
+  g_object_class_install_property (gobject_class, PROP_SRC_CROP_Y,
+      g_param_spec_int ("src-crop-y", "Source Crop X",
+          "Y value of Video source crop(only available if LETTER_BOX or FULL_SCREEN mode)", 0, XV_SCREEN_SIZE_WIDTH, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:src-crop-w
+   *
+   * Width value of video source crop
+   */
+  g_object_class_install_property (gobject_class, PROP_SRC_CROP_W,
+      g_param_spec_int ("src-crop-w", "Source Crop Width",
+          "Width value of Video source crop(only available if LETTER_BOX or FULL_SCREEN mode)", 0, XV_SCREEN_SIZE_WIDTH, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:src-crop-h
+   *
+   * Height value of video source crop
+   */
+  g_object_class_install_property (gobject_class, PROP_SRC_CROP_H,
+      g_param_spec_int ("src-crop-h", "Source Crop Height",
+          "Height value of Video source crop(only available if LETTER_BOX or FULL_SCREEN mode)", 0, XV_SCREEN_SIZE_WIDTH, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:enable-flush-buffer
+   *
+   * Enable flush buffer mechanism when state change(PAUSED_TO_READY)
+   */
+  g_object_class_install_property (gobject_class, PROP_ENABLE_FLUSH_BUFFER,
+      g_param_spec_boolean("enable-flush-buffer", "Enable flush buffer mechanism",
+          "Enable flush buffer mechanism when state change(PAUSED_TO_READY)",
+          TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:is-pixmap
+   *
+   * Check using pixmap id for blocking X api
+   */
+  g_object_class_install_property (gobject_class, PROP_PIXMAP,
+      g_param_spec_boolean("is-pixmap", "Check if use pixmap",
+          "Check using pixmap id for blocking X api",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:hided-window
+   *
+   * check window status for hiding subtitle
+   */
+  g_object_class_install_property (gobject_class, PROP_HIDED_WINDOW,
+      g_param_spec_boolean("hided-window", "Hided window",
+          "check window status for hiding subtitle",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:quick-panel-on
+   *
+   * check quick-panel status for hiding subtitle
+   */
+  g_object_class_install_property (gobject_class, PROP_QUICKPANEL_ON,
+      g_param_spec_boolean("quick-panel-on", "Quick panel On",
+          "check quick-panel status for hiding subtitle",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:multiwindow-activated
+   *
+   * check multiwindow-activated status for hiding subtitle
+   */
+  g_object_class_install_property (gobject_class, PROP_MULTIWINDOW_ACTIVE,
+      g_param_spec_boolean("multiwindow-active", "Multiwindow Activate",
+          "check multiwindow status for hiding subtitle",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:keep-external-fullscreen-post
+   *
+   * keep video-only mode for special case, it is set immediately.
+   */
+  g_object_class_install_property (gobject_class, PROP_KEEP_EXTERNAL_FULLSCREEN_POST,
+      g_param_spec_boolean("keep-external-fullscreen-post", "Keep external display to full screen",
+          "set video-only mode forcedly for special case",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink:keep-external-fullscreen-prev
+   *
+   * keep video-only mode for special case, it is set in advance.
+   */
+  g_object_class_install_property (gobject_class, PROP_KEEP_EXTERNAL_FULLSCREEN_PREV,
+      g_param_spec_boolean("keep-external-fullscreen-prev", "Keep external display to full screen",
+          "set video-only mode forcedly for special case",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstXvImageSink::frame-render-error
+   */
+  gst_xvimagesink_signals[SIGNAL_FRAME_RENDER_ERROR] = g_signal_new (
+          "frame-render-error",
+          G_TYPE_FROM_CLASS (klass),
+          G_SIGNAL_RUN_LAST,
+          0,
+          NULL,
+          NULL,
+          gst_xvimagesink_BOOLEAN__POINTER,
+          G_TYPE_BOOLEAN,
+          1,
+          G_TYPE_POINTER);
+  /**
+   * GstXvImageSink::display-status
+   */
+    gst_xvimagesink_signals[SIGNAL_DISPLAY_STATUS] = g_signal_new (
+          "display-status",
+          G_TYPE_FROM_CLASS (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          0,
+          NULL,
+          NULL,
+          g_cclosure_marshal_VOID__INT,
+          G_TYPE_NONE,
+          1,
+          G_TYPE_INT);
+
+  /**
+   * GstXvImageSink::external-resolution
+   */
+  gst_xvimagesink_signals[SIGNAL_EXTERNAL_RESOLUTION] = g_signal_new (
+          "external-resolution",
+         G_TYPE_FROM_CLASS (klass),
+         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+         0,
+         NULL,
+         NULL,
+         gst_marshal_VOID__INT_INT,
+         G_TYPE_NONE,
+         2,
+         G_TYPE_INT,
+         G_TYPE_INT);
+
+  /**
+   * GstXvImageSink::hided-window
+   */
+    gst_xvimagesink_signals[SIGNAL_WINDOW_STATUS] = g_signal_new (
+          "hided-window",
+          G_TYPE_FROM_CLASS (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          0,
+          NULL,
+          NULL,
+          g_cclosure_marshal_VOID__BOOLEAN,
+          G_TYPE_NONE,
+          1,
+          G_TYPE_BOOLEAN);
+
+  /**
+   * GstXvImageSink::quick-panel-on
+   */
+    gst_xvimagesink_signals[SIGNAL_QUICKPANEL_STATUS] = g_signal_new (
+          "quick-panel-on",
+          G_TYPE_FROM_CLASS (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          0,
+          NULL,
+          NULL,
+          g_cclosure_marshal_VOID__BOOLEAN,
+          G_TYPE_NONE,
+          1,
+          G_TYPE_BOOLEAN);
+
+  /**
+   * GstXvImageSink::multiwindow-active
+   */
+    gst_xvimagesink_signals[SIGNAL_MULTIWINDOW_STATUS] = g_signal_new (
+          "multiwindow-active",
+          G_TYPE_FROM_CLASS (klass),
+          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+          0,
+          NULL,
+          NULL,
+          g_cclosure_marshal_VOID__BOOLEAN,
+          G_TYPE_NONE,
+          1,
+          G_TYPE_BOOLEAN);
+
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   gobject_class->finalize = gst_xvimagesink_finalize;
@@ -4879,3 +8138,5 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     "xvimagesink",
     "XFree86 video output plugin using Xv extension",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
+
old mode 100644 (file)
new mode 100755 (executable)
index b3b0b5a..dfb9ed2
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
+ * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * * Modifications by Samsung Electronics Co., Ltd.
+ * 1. Add display related properties
+ * 2. Support samsung extension format to improve performance
+ * 3. Support video texture overlay of OSP layer
  */
 
 #ifndef __GST_XVIMAGESINK_H__
@@ -40,6 +46,9 @@
 #ifdef GST_EXT_XV_ENHANCEMENT
 #include <X11/Xatom.h>
 #include <stdio.h>
+#include "xv_types.h"
+#include <utilX.h>
+#include <utilX_ext.h>
 #endif
 
 #include <string.h>
@@ -60,8 +69,15 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIMAGESINK))
 
 #ifdef GST_EXT_XV_ENHANCEMENT
-#define XV_SCREEN_SIZE_WIDTH 4096
-#define XV_SCREEN_SIZE_HEIGHT 4096
+#define XV_SCREEN_SIZE_WIDTH            4096
+#define XV_SCREEN_SIZE_HEIGHT           4096
+#define DISPLAYING_BUFFERS_MAX_NUM      10
+
+#define MAX_PIXMAP_NUM 10
+typedef uint (*get_pixmap_callback)(void *user_data);
+typedef struct _GstXPixmap GstXPixmap;
+typedef struct _GstXvImageDisplayingBuffer GstXvImageDisplayingBuffer;
+typedef struct _GstXvImageFlushBuffer GstXvImageFlushBuffer;
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
 typedef struct _GstXContext GstXContext;
@@ -162,6 +178,29 @@ struct _GstXWindow {
   GC gc;
 };
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+struct _GstXPixmap {
+       Window pixmap;
+       gint x, y;
+       gint width, height;
+       GC gc;
+};
+
+struct _GstXvImageDisplayingBuffer {
+       GstBuffer *buffer;
+       unsigned int dmabuf_fd[XV_BUF_PLANE_NUM];
+       unsigned int gem_name[XV_BUF_PLANE_NUM];
+       unsigned int gem_handle[XV_BUF_PLANE_NUM];
+       void *bo[XV_BUF_PLANE_NUM];
+       unsigned int ref_count;
+};
+
+struct _GstXvImageFlushBuffer {
+       unsigned int gem_name[XV_BUF_PLANE_NUM];
+       void *bo[XV_BUF_PLANE_NUM];
+};
+#endif
+
 /**
  * GstXvImageFormat:
  * @format: the image format
@@ -199,8 +238,15 @@ struct _GstXvImageBuffer {
 
   gint width, height, im_format;
   size_t size;
+#ifdef GST_EXT_XV_ENHANCEMENT
+  GstBuffer *current_buffer;
+#endif /* GST_EXT_XV_ENHANCEMENT */
 };
 
+#ifdef GST_EXT_XV_ENHANCEMENT
+#define MAX_PLANE_NUM          4
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
 /**
  * GstXvImageSink:
  * @display_name: the name of the Display we want to render to
@@ -248,6 +294,10 @@ struct _GstXvImageSink {
   GstXWindow *xwindow;
   GstXvImageBuffer *xvimage;
   GstXvImageBuffer *cur_image;
+#ifdef GST_EXT_XV_ENHANCEMENT
+  GstXvImageBuffer *last_image;
+  unsigned int last_image_vaddr[4];
+#endif
 
   GThread *event_thread;
   gboolean running;
@@ -288,14 +338,14 @@ struct _GstXvImageSink {
   /* port attributes */
   gboolean autopaint_colorkey;
   gint colorkey;
-  
+
   gboolean draw_borders;
-  
+
   /* port features */
   gboolean have_autopaint_colorkey;
   gboolean have_colorkey;
   gboolean have_double_buffer;
-  
+
   /* stream metadata */
   gchar *media_title;
 
@@ -305,23 +355,94 @@ struct _GstXvImageSink {
 
 #ifdef GST_EXT_XV_ENHANCEMENT
   /* display mode */
+  gboolean is_pixmap;
+  gboolean xid_updated;
   guint display_mode;
+  guint csc_range;
   guint display_geometry_method;
+  guint flip;
   guint rotate_angle;
-  gboolean rotate_changed;
   gboolean visible;
-  guint zoom;
+  gfloat zoom;
+  guint zoom_pos_x;
+  guint zoom_pos_y;
   guint rotation;
   guint rotate_cnt;
+  guint orientation;
+  guint dst_roi_mode;
   GstVideoRectangle dst_roi;
   XImage* xim_transparenter;
   guint scr_w, scr_h;
   gboolean stop_video;
   gboolean is_hided;
+  gboolean is_quick_panel_on;
+  gboolean is_multi_window;
+  gboolean is_during_seek;
+  GstVideoRectangle src_crop;
+
   /* needed if fourcc is one if S series */
   guint aligned_width;
   guint aligned_height;
+  gint drm_fd;
+  void *bufmgr;
+
+  /* for using multiple pixmaps */
+  GstXPixmap *xpixmap[MAX_PIXMAP_NUM];
+  gint current_pixmap_idx;
+  get_pixmap_callback get_pixmap_cb;
+  void* get_pixmap_cb_user_data;
+
+  /* for sync displaying buffers */
+  GstXvImageDisplayingBuffer displaying_buffers[DISPLAYING_BUFFERS_MAX_NUM];
+  GMutex *display_buffer_lock;
+
+  /* buffer count check */
+  guint displayed_buffer_count;
+  guint displaying_buffer_count;
+
+  /* zero copy format */
+  gboolean is_zero_copy_format;
+
+  /* secure contents path */
+  gint secure_path;
+
+  /* DRM level */
+  gint drm_level;
+
+#ifdef GST_EXT_ENABLE_HEVC
+  /* if needed combine planes data */
+  gint need_combine_data;
 #endif
+
+  /* display request time */
+  struct timeval request_time[DISPLAYING_BUFFERS_MAX_NUM];
+
+  /* last added buffer index */
+  gint last_added_buffer_index;
+
+  /* flush buffer */
+  GstXvImageFlushBuffer *flush_buffer;
+  gboolean enable_flush_buffer;
+
+  /* subtitle format */
+  Pixmap pixmap_for_subpicture;
+  gboolean is_subpicture_format;
+  gboolean set_overlay_for_subpicture_just_once;
+  gboolean subpicture;
+  gboolean is_hided_subpicture;
+  gboolean is_quick_panel_on_subpicture;
+  gboolean is_multi_window_subpicture;
+
+  /* external display */
+  gint external_width;
+  gint external_height;
+  gboolean skip_frame_due_to_external_dev;
+  gboolean keep_external_fullscreen_post;
+  gboolean keep_external_fullscreen_prev;
+
+  gboolean eos_received;
+
+#endif /* GST_EXT_XV_ENHANCEMENT */
 };
 
 #ifdef GST_EXT_XV_ENHANCEMENT
index 647b634..278b4b0 100644 (file)
@@ -19,7 +19,7 @@ LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la\
        $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la\
        $(GST_BASE_LIBS) $(GST_LIBS)
 
-AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
+AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) -pie
 
 # generate versioned scripts from templates
 %-@GST_MAJORMINOR@: %-m.m