tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.git] / sys / xvimage / xvimagesink.c
similarity index 82%
rename from wearable/sys/xvimage/xvimagesink.c
rename to sys/xvimage/xvimagesink.c
index 52632b8..72d8310 100755 (executable)
 #include <dri2/dri2.h>
 #include <tbm_bufmgr.h>
 
-/* for performance checking */
-#include <mm_ta.h>
+/* for setting vconf about xv state */
+#include <vconf.h>
+#include <vconf-internal-player-keys.h>
+
 
 enum {
     SECURE_PATH_INIT = -1,
@@ -160,6 +162,22 @@ enum {
     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,
@@ -448,6 +466,11 @@ gst_xvimagesink_BOOLEAN__POINTER (GClosure         *closure,
 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 };
@@ -492,6 +515,9 @@ 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
@@ -540,8 +566,8 @@ enum
   PROP_ZOOM,
   PROP_ZOOM_POS_X,
   PROP_ZOOM_POS_Y,
+  PROP_ORIENTATION,
   PROP_DST_ROI_MODE,
-  PROP_DST_ROI_ORIENTATION,
   PROP_DST_ROI_X,
   PROP_DST_ROI_Y,
   PROP_DST_ROI_W,
@@ -553,8 +579,16 @@ enum
   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 */
 };
 
@@ -828,7 +862,6 @@ gst_xvimagesink_check_xshm_calls (GstXContext * xcontext)
   SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
   if (SHMInfo.shmid == -1) {
     GST_WARNING ("could not get shared memory of %d bytes", size);
-    GST_ERROR("Failed to shmget: %s", g_strerror (errno));
     goto beach;
   }
 
@@ -925,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);
@@ -1065,7 +1102,6 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
               xvimage->width, xvimage->height),
           ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
               xvimage->size));
-      GST_ERROR_OBJECT(xvimagesink, "Failed to shmget: %s", g_strerror (errno));
       goto beach_unlocked;
     }
 
@@ -1158,271 +1194,6 @@ beach_unlocked:
   return xvimage;
 }
 
-#ifdef GST_EXT_XV_ENHANCEMENT
-/* This function handles GstXvImage creation depending on XShm availability */
-static GstXvImageBuffer *
-gst_xvimagesink_xvimage_new_for_last_image (GstXvImageSink * xvimagesink, gint im_format)
-{
-  GstXvImageBuffer *xvimage = NULL;
-  GstStructure *structure = NULL;
-  gboolean succeeded = FALSE;
-  int (*handler) (Display *, XErrorEvent *);
-
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
-  xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
-  GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer for last image");
-
-  xvimage->width = xvimagesink->xvimage->width;
-  xvimage->height = xvimagesink->xvimage->height;
-
-  GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
-      xvimage->height);
-
-  xvimage->im_format = im_format;
-  if (xvimage->im_format == -1) {
-    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-        ("Failed to create output image buffer of %dx%d pixels",
-            xvimage->width, xvimage->height), ("Invalid input caps"));
-    goto beach_unlocked;
-  }
-  xvimage->xvimagesink = gst_object_ref (xvimagesink);
-
-  g_mutex_lock (xvimagesink->x_lock);
-
-  XSync (xvimagesink->xcontext->disp, FALSE);
-
-  /* Setting an error handler to catch failure */
-  error_caught = FALSE;
-  handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
-  if (xvimagesink->xcontext->use_xshm) {
-    int expected_size;
-
-    xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimage->im_format, NULL,
-        xvimage->width, xvimage->height, &xvimage->SHMInfo);
-    if (!xvimage->xvimage || error_caught) {
-      g_mutex_unlock (xvimagesink->x_lock);
-
-      /* Reset error flag */
-      error_caught = FALSE;
-
-      /* Push a warning */
-      GST_ELEMENT_WARNING (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("could not XvShmCreateImage a %dx%d image",
-              xvimage->width, xvimage->height));
-
-      /* must not change "use_xshm",
-         because it causes memory curruption when buffer created by XvShmCreateImage is destroyed */
-      goto beach_unlocked;
-    }
-
-    /* we have to use the returned data_size for our shm size */
-    xvimage->size = xvimage->xvimage->data_size;
-    GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
-        xvimage->size);
-
-    /* calculate the expected size.  This is only for sanity checking the
-     * number we get from X. */
-    switch (xvimage->im_format) {
-      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
-      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
-      {
-        gint pitches[3];
-        gint offsets[3];
-        guint plane;
-
-        offsets[0] = 0;
-        pitches[0] = GST_ROUND_UP_4 (xvimage->width);
-        offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (xvimage->height);
-        pitches[1] = GST_ROUND_UP_8 (xvimage->width) / 2;
-        offsets[2] =
-            offsets[1] + pitches[1] * GST_ROUND_UP_2 (xvimage->height) / 2;
-        pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
-
-        expected_size =
-            offsets[2] + pitches[2] * GST_ROUND_UP_2 (xvimage->height) / 2;
-
-        for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
-          GST_DEBUG_OBJECT (xvimagesink,
-              "Plane %u has a expected pitch of %d bytes, " "offset of %d",
-              plane, pitches[plane], offsets[plane]);
-        }
-        break;
-      }
-      case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
-      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
-      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
-        expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2);
-        break;
-      default:
-        expected_size = 0;
-        break;
-    }
-    if (expected_size != 0 && xvimage->size != expected_size) {
-      GST_WARNING_OBJECT (xvimagesink,
-          "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
-          xvimage->size, expected_size);
-    }
-
-    /* Be verbose about our XvImage stride */
-    {
-      guint plane;
-
-      for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
-        GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
-            "offset of %d", plane, xvimage->xvimage->pitches[plane],
-            xvimage->xvimage->offsets[plane]);
-      }
-    }
-
-    xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
-        IPC_CREAT | 0777);
-    if (xvimage->SHMInfo.shmid == -1) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
-              xvimage->size));
-      GST_ERROR_OBJECT(xvimagesink, "Failed to shmget: %s", g_strerror (errno));
-      goto beach_unlocked;
-    }
-
-    xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
-    if (xvimage->SHMInfo.shmaddr == ((void *) -1)) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("Failed to shmat: %s", g_strerror (errno)));
-      /* Clean up the shared memory segment */
-      shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
-      goto beach_unlocked;
-    }
-
-    xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
-    xvimage->SHMInfo.readOnly = FALSE;
-
-    if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
-      /* Clean up the shared memory segment */
-      shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
-
-      g_mutex_unlock (xvimagesink->x_lock);
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create output image buffer of %dx%d pixels",
-              xvimage->width, xvimage->height), ("Failed to XShmAttach"));
-      goto beach_unlocked;
-    }
-
-    XSync (xvimagesink->xcontext->disp, FALSE);
-
-    /* Delete the shared memory segment as soon as we everyone is attached.
-     * This way, it will be deleted as soon as we detach later, and not
-     * leaked if we crash. */
-    shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
-
-    GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
-        xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
-  } else
-#endif /* HAVE_XSHM */
-  {
-    xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
-        xvimagesink->xcontext->xv_port_id,
-        xvimage->im_format, NULL, xvimagesink->aligned_width, xvimagesink->aligned_height);
-    if (!xvimage->xvimage || error_caught) {
-      g_mutex_unlock (xvimagesink->x_lock);
-      /* Reset error handler */
-      error_caught = FALSE;
-      XSetErrorHandler (handler);
-      /* Push an error */
-      GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
-          ("Failed to create outputimage buffer of %dx%d pixels",
-              xvimage->width, xvimage->height),
-          ("could not XvCreateImage a %dx%d image",
-              xvimage->width, xvimage->height));
-      goto beach_unlocked;
-    }
-
-    /* we have to use the returned data_size for our image size */
-    xvimage->size = xvimage->xvimage->data_size;
-    xvimage->xvimage->data = g_malloc (xvimage->size);
-
-    XSync (xvimagesink->xcontext->disp, FALSE);
-  }
-
-  /* Reset error handler */
-  error_caught = FALSE;
-  XSetErrorHandler (handler);
-
-  succeeded = TRUE;
-
-  GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
-  GST_BUFFER_SIZE (xvimage) = xvimage->size;
-
-  g_mutex_unlock (xvimagesink->x_lock);
-
-beach_unlocked:
-  if (!succeeded) {
-    gst_xvimage_buffer_free (xvimage);
-    xvimage = NULL;
-  }
-
-  return xvimage;
-}
-
-static gboolean
-gst_xvimagesink_xvimage_handle_last_buffer (GstXvImageSink * xvimagesink, gint im_format)
-{
-  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
-
-  xvimagesink->last_image = gst_xvimagesink_xvimage_new_for_last_image (xvimagesink, im_format);
-  if (!xvimagesink->last_image) {
-    /* The create method should have posted an informative error */
-    GST_WARNING_OBJECT (xvimagesink, "could not create last image");
-    return FALSE;
-  }
-
-  GST_INFO_OBJECT(xvimagesink, "last_image(%p)->xvimage->data:0x%x, last_image->size:%d",
-                  xvimagesink->last_image, xvimagesink->last_image->xvimage->data, xvimagesink->last_image->size);
-
-  switch (im_format) {
-  case GST_MAKE_FOURCC('N', 'V', '1', '2'):
-  {
-    int i = 0;
-    gint y_size = 0;
-    char *y_data = xvimagesink->last_image->xvimage->data;
-    y_size = xvimagesink->last_image->width * xvimagesink->last_image->height;
-    if (xvimagesink->last_image_vaddr[0]) {
-      for(i = 0; i < xvimagesink->last_image->height; i++) {
-        memcpy (y_data + i*xvimagesink->last_image->width, xvimagesink->last_image_vaddr[0] + i*xvimagesink->aligned_width, xvimagesink->last_image->width);
-      }
-    }
-    if (xvimagesink->last_image_vaddr[1]) {
-      for(i = 0; i < xvimagesink->last_image->height/2; i++) {
-        memcpy (y_data + y_size + i*xvimagesink->last_image->width, xvimagesink->last_image_vaddr[1] + i*xvimagesink->aligned_width, xvimagesink->last_image->width);
-      }
-    }
-    GST_LOG_OBJECT(xvimagesink, "last image was copied in NV12 format (w:%d, h:%d, y_size:%d", xvimagesink->last_image->width, xvimagesink->last_image->height, y_size);
-    break;
-  }
-  default:
-    GST_ERROR_OBJECT(xvimagesink, "Not support format for last image");
-    gst_xvimage_buffer_destroy (xvimagesink->last_image);
-    xvimagesink->last_image = NULL;
-    GST_WARNING_OBJECT (xvimagesink, "could not create last image");
-    return FALSE;
-  }
-
-  return TRUE;
-}
-#endif
-
 /* We are called with the x_lock taken */
 static void
 gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
@@ -1480,6 +1251,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
   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;
@@ -1491,11 +1263,15 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
   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
@@ -1538,19 +1314,10 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
           return TRUE;
         }
       } else {
-        GST_WARNING_OBJECT(xvimagesink, "XGetWindowAttributes failed");
+      GST_WARNING_OBJECT(xvimagesink, "XGetWindowAttributes failed");
       }
     }
   }
-
-  /* check visible status */
-  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;
-  }
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
   /* Draw borders when displaying the first frame. After this
@@ -1597,8 +1364,44 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
   }
 
 #ifdef GST_EXT_XV_ENHANCEMENT
+  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));
@@ -1621,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;
@@ -1726,8 +1542,8 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
       case ROI_DISP_GEO_METHOD_LETTER_BOX:
        {
         GstVideoRectangle roi_result;
-        if (xvimagesink->dst_roi_orientation == DEGREE_0 ||
-            xvimagesink->dst_roi_orientation == DEGREE_180) {
+        if (xvimagesink->orientation == DEGREE_0 ||
+            xvimagesink->orientation == DEGREE_180) {
           src.w = src_origin.w;
           src.h = src_origin.h;
         } else {
@@ -1793,17 +1609,17 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
       }
 
       /* orientation setting for auto rotation in DST ROI */
-      if (xvimagesink->dst_roi_orientation) {
-        res_rotate_angle = (xvimagesink->rotate_angle - xvimagesink->dst_roi_orientation);
+      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->dst_roi_orientation, xvimagesink->rotate_angle, res_rotate_angle);
+                     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->dst_roi_orientation, xvimagesink->dst_roi_mode,
+                     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);
       break;
@@ -1813,30 +1629,53 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
   }
 
   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]",
+    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;
-    gint default_offset_x = ((gint)(w - (w/xvimagesink->zoom)))>>1;
-    gint default_offset_y = ((gint)(h - (h/xvimagesink->zoom)))>>1;
-    GST_LOG_OBJECT(xvimagesink, "default offset x:%d y:%d", default_offset_x, default_offset_y);
+    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 ((gint)w/xvimagesink->zoom > w - xvimagesink->zoom_pos_x) {
-        xvimagesink->zoom_pos_x = default_offset_x * 2;
+      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;
       }
-      src_input.x += xvimagesink->zoom_pos_x;
     }
     if (xvimagesink->zoom_pos_y == -1) {
       src_input.y += default_offset_y;
     } else {
-      if ((gint)h/xvimagesink->zoom > h - xvimagesink->zoom_pos_y) {
-        xvimagesink->zoom_pos_y = default_offset_y * 2;
+      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.y += 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]",
@@ -1912,18 +1751,6 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
         src_input.h += 1;
     }
 
-    if ((xvimagesink->display_geometry_method == DISP_GEO_METHOD_LETTER_BOX ||
-         xvimagesink->display_geometry_method == DISP_GEO_METHOD_FULL_SCREEN) &&
-        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 = xvimagesink->src_crop.x;
-        src_input.y = xvimagesink->src_crop.y;
-        src_input.w = xvimagesink->src_crop.w;
-        src_input.h = xvimagesink->src_crop.h;
-    }
-
     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,
@@ -1950,29 +1777,74 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
       return TRUE;
     }
 
-    /* set display rotation */
-    if (atom_rotation == None) {
-      atom_rotation = XInternAtom(xvimagesink->xcontext->disp,
+    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 (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 );
 
-    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;
+        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");
     }
 
-    /* set display flip */
-    if (atom_hflip == None) {
-      atom_hflip = XInternAtom(xvimagesink->xcontext->disp,
-                               "_USER_WM_PORT_ATTRIBUTE_HFLIP", 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;
     }
-    if (atom_vflip == None) {
-      atom_vflip = XInternAtom(xvimagesink->xcontext->disp,
-                               "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
+
+    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) {
@@ -1997,15 +1869,40 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
 
     GST_LOG("set HFLIP %d, VFLIP %d", set_hflip, set_vflip);
 
-    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_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);
+      }
     }
-    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);
+
+    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 */
@@ -2027,7 +1924,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
       }
 
       /* store buffer */
-      if (xvimagesink->is_zero_copy_format && xvimage->xvimage->data && !xvimagesink->last_image) {
+      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);
@@ -2271,7 +2168,7 @@ static gboolean set_display_mode(GstXContext *xcontext, int set_mode)
   }
 
   if (is_exist) {
-    GST_WARNING("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,
@@ -2621,6 +2518,7 @@ static void _release_flush_buffer(GstXvImageSink *xvimagesink)
        return;
 }
 
+
 static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_data, GstBuffer *buffer)
 {
        int i = 0;
@@ -2704,7 +2602,6 @@ static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_
                                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];
-                               xvimagesink->displaying_buffers[i].vaddr[j] = img_data->vaddr[j];
                        }
 
                        /* set buffer info */
@@ -2729,7 +2626,7 @@ static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_
                                                                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], vaddr [%p, %p, %p]",
+                               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],
@@ -2739,10 +2636,7 @@ static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_
                                                              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],
-                                                             xvimagesink->displaying_buffers[i].vaddr[0],
-                                                             xvimagesink->displaying_buffers[i].vaddr[1],
-                                                             xvimagesink->displaying_buffers[i].vaddr[2]);
+                                                             xvimagesink->displaying_buffers[i].gem_name[2]);
                        }
 
                        /* set last added buffer index */
@@ -2772,196 +2666,204 @@ static void _add_displaying_buffer(GstXvImageSink *xvimagesink, XV_DATA_PTR img_
 
 static void _remove_displaying_buffer(GstXvImageSink *xvimagesink, unsigned int *gem_name)
 {
-  int i = 0;
-  int j = 0;
+       int i = 0;
+       int j = 0;
 
-  gboolean enable_last_buffer = FALSE;
+       if (!xvimagesink || !gem_name) {
+               GST_ERROR_OBJECT(xvimagesink, "handle is NULL %p, %p", xvimagesink, gem_name);
+               return;
+       }
 
-  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);
 
-  /* 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;
+       }
 
-  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);
 
-  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;
 
-  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]);
-      }
+                       /* 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);
 
-      /* decrease displaying buffer count */
-      xvimagesink->displaying_buffer_count--;
+    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;
+    }
 
-      /* decrease ref count */
-      xvimagesink->displaying_buffers[i].ref_count--;
+    if (handler) {
+      error_caught = FALSE;
+      XSetErrorHandler (handler);
+    }
 
-      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;
+    if (!num_ret) {
+      GST_WARNING_OBJECT(xvimagesink, "XGetWindowProperty num_ret failed");
+      if (prop_ret) {
+        XFree(prop_ret);
       }
+      return False;
+    }
 
-      /* 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);
+    if (prop_ret) {
+      switch (size_ret) {
+      case 8:
+        for (i = 0 ; i < num_ret ; i++) {
+          (&data)[i] = prop_ret[i];
         }
-      }
-
-      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]));
+        break;
+      case 16:
+        for (i = 0 ; i < num_ret ; i++) {
+          ((unsigned short *)&data)[i] = ((unsigned short *)prop_ret)[i];
         }
-        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);
-        g_object_get(G_OBJECT(xvimagesink), "enable-last-buffer", &enable_last_buffer, NULL);
-        if(!enable_last_buffer) {
-          if (xvimagesink->cur_image) {
-            GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
-            gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image));
-            xvimagesink->cur_image = NULL;
-          }
+        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;
 
-      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;
+      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");
   }
 
-  /* 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;
-       Atom atom_output_external;
-
-       atom_output_external = XInternAtom(xvimagesink->xcontext->disp,
-                                          "XV_OUTPUT_EXTERNAL", False);
-       if (atom_output_external != None) {
-               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);
-               if (ret != Success) {
-                       GST_WARNING_OBJECT(xvimagesink, "XGetWindowProperty failed");
-                       if (prop_ret) {
-                               XFree(prop_ret);
-                       }
-                       return False;
-               }
-
-               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;
+  return False;
 }
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
@@ -2975,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);
@@ -3024,7 +2926,6 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
 
   /* Make window manager not to change window size as Full screen */
   win_attr.override_redirect = True;
-
   if(!xvimagesink->is_pixmap)
     XChangeWindowAttributes(xvimagesink->xcontext->disp, xwindow->win, CWOverrideRedirect, &win_attr);
 #else /* GST_EXT_XV_ENHANCEMENT */
@@ -3051,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 */
@@ -3140,7 +3048,7 @@ 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;
@@ -3196,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,
@@ -3224,6 +3142,10 @@ 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));
 
@@ -3338,6 +3260,8 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * 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 */
@@ -3439,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)) {
@@ -3477,12 +3400,14 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
   /* 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;
 
@@ -3499,6 +3424,35 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
 
           _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 */
 
@@ -3525,32 +3479,20 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
 
             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)) {
-#if 0
-              atom_stream = XInternAtom(xvimagesink->xcontext->disp,
-                                        "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False);
-
-              GST_WARNING_OBJECT(xvimagesink, "call STREAM_OFF");
-
-              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");
-                }
-
-              } else {
-                GST_WARNING_OBJECT(xvimagesink, "atom_stream is NONE");
-              }
-#endif
-              xvimagesink->is_hided = TRUE;
+              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 {
-              GST_WARNING_OBJECT(xvimagesink, "external display is enabled. skip STREAM_OFF");
+              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");
@@ -3560,6 +3502,7 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
               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);
@@ -3570,15 +3513,213 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
           }
         }
         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);
+
+  return num;
+}
+
+static void check_hdmi_connected(GstXvImageSink *xvimagesink)
+{
+  char *str_output = NULL;
+  char str_status[10] = {0, };
+  char *str_resolution = NULL;
+  char str_dispmode[10] = {0, };
+  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);
+
+  str_output = scrnconf->str_output;
+
+  if (scrnconf->status == UTILX_SCRNCONF_STATUS_CONNECT)
+  {
+    strcpy (str_status, "CONNECT");
+  }
+  else if (scrnconf->status == UTILX_SCRNCONF_STATUS_ACTIVE)
+  {
+    strcpy (str_status, "ACTIVE");
+
+    list = g_strsplit(scrnconf->str_resolution, "x", 2);
+
+    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
+  {
+    strcpy (str_status, "null");
+  }
+
+  str_resolution = scrnconf->str_resolution;
+
+  if (scrnconf->dispmode == UTILX_SCRNCONF_DISPMODE_CLONE)
+  {
+    strcpy (str_dispmode, "CLONE");
+  }
+  else if (scrnconf->dispmode == UTILX_SCRNCONF_DISPMODE_EXTENDED)
+  {
+    strcpy (str_dispmode, "EXTENDED");
+  }
+  else
+  {
+    strcpy (str_dispmode, "null");
+  }
+
+  GST_INFO ("[Display status] : %s, %s, %s, %s\n", str_output, str_status, str_resolution, str_dispmode);
+
+  if(scrnconf)
+    utilx_scrnconf_free (scrnconf);
+
+}
+
+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;
+      }
+    }
+    XFree(attr);
+  } else {
+    GST_WARNING("XvQueryPortAttributes disp:%d, port_id:%d failed",
+                xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id);
+  }
+  return FALSE;
+}
+#endif //GST_EXT_XV_ENHANCEMENT
 
 static void
 gst_lookup_xv_port_from_adaptor (GstXContext * xcontext,
@@ -3609,6 +3750,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
@@ -3662,14 +3837,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;
     }
   }
@@ -3789,7 +3977,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);
@@ -3891,6 +4081,9 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
         ("No supported format found"));
     return NULL;
   }
+#ifdef GST_EXT_XV_ENHANCEMENT
+} //subpicture
+#endif
 
   return caps;
 }
@@ -4015,6 +4208,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 */
@@ -4087,7 +4283,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);
@@ -4180,7 +4375,11 @@ 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;
@@ -4199,21 +4398,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++) {
@@ -4264,13 +4468,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);
-  set_csc_range(xcontext, xvimagesink->csc_range);
+  }
+  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);
@@ -4301,7 +4509,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) {
@@ -4316,7 +4526,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;
 
@@ -4356,7 +4568,6 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
   }
 #endif
   XCloseDisplay (xcontext->disp);
-
   g_mutex_unlock (xvimagesink->x_lock);
 
   g_free (xcontext);
@@ -4412,10 +4623,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)));
@@ -4438,7 +4652,7 @@ 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...");
@@ -4455,7 +4669,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);
@@ -4463,7 +4681,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;
 
@@ -4471,6 +4695,7 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   xvimagesink->aligned_width = video_width;
   xvimagesink->aligned_height = video_height;
 
+#ifdef GST_EXT_ENABLE_HEVC
   /*get combine prop of hevc*/
   if(gst_structure_get_int (structure, "yuvcombine", &(xvimagesink->need_combine_data)))
   {
@@ -4481,7 +4706,7 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
     /*Not need to combine data, just directly copy*/
     xvimagesink->need_combine_data = 0;
   }
-
+#endif
   _remove_last_buffer(xvimagesink);
 #endif /* GST_EXT_XV_ENHANCEMENT */
 
@@ -4490,11 +4715,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 */
@@ -4583,22 +4812,25 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   } 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);
+    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");
+    if (!xvimagesink->xwindow && !xvimagesink->get_pixmap_cb) {
+      GST_DEBUG_OBJECT (xvimagesink, "xwindow is null and not multi-pixmaps usage case");
 #else
-  if (!xvimagesink->xwindow) {
+    if (!xvimagesink->xwindow) {
 #endif
-    xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
-        GST_VIDEO_SINK_WIDTH (xvimagesink),
-        GST_VIDEO_SINK_HEIGHT (xvimagesink));
+      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
@@ -4610,7 +4842,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),
@@ -4620,6 +4853,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;
@@ -4654,7 +4893,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)
@@ -4713,22 +4954,11 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
 #ifdef GST_EXT_XV_ENHANCEMENT
-      GST_WARNING("PAUSED_TO_PLAYING start");
-#if 0 /* This is removed in Xorg */
-      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);
-#endif
+      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:
@@ -4738,6 +4968,8 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
       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;
@@ -4749,23 +4981,28 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
 #ifdef GST_EXT_XV_ENHANCEMENT
       GST_WARNING("PLAYING_TO_PAUSED start");
-#if 0 /* This is removed in Xorg */
-      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);
-      }
-      g_mutex_unlock (xvimagesink->x_lock);
-#endif
+      g_mutex_lock (xvimagesink->flow_lock);
       /* init displayed buffer count */
       xvimagesink->displayed_buffer_count = 0;
 
+      g_mutex_lock (xvimagesink->x_lock);
+      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;
@@ -4794,7 +5031,6 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
                  !xvimagesink->get_pixmap_cb) {
         if (gst_xvimagesink_make_flush_buffer(xvimagesink)) {
           int i = 0;
-          int is_existed = FALSE;
           XV_DATA_PTR img_data = (XV_DATA_PTR) xvimagesink->xvimage->xvimage->data;
           memset(img_data, 0x0, sizeof(XV_DATA));
           XV_INIT_DATA(img_data);
@@ -4842,12 +5078,6 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
       GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
       GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
 #ifdef GST_EXT_XV_ENHANCEMENT
-      /* close drm */
-      drm_fini(xvimagesink);
-
-      /* init displaying_buffer_count */
-      xvimagesink->displaying_buffer_count = 0;
-
       GST_WARNING("PAUSED_TO_READY done");
 #endif /* GST_EXT_XV_ENHANCEMENT */
       break;
@@ -4857,6 +5087,10 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
 #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;
@@ -4889,50 +5123,18 @@ gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
   }
 }
 
-static void
-gst_xvimagesink_generate_YUV420_black_frame(int width, int height, unsigned char *buf, unsigned int *buf_size)
-{
-    int i;
-    int y_len = 0;
-    int yuv_len = 0;
-
-    y_len = width * height;
-    yuv_len = (width * height * 3) >> 1;
-
-    for (i = 0; i < y_len; i++)
-    {
-        buf[i] = 0x00;
-    }
-
-    for (; i < yuv_len ; i++)
-    {
-        buf[i] = 0x80;
-    }
-
-    *buf_size = yuv_len;
-    GST_DEBUG("Black frame generated end");
-    return;
-}
-
+#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");
-    if(GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_LAST))
-    {
-        /*Gerate Black Frame data*/
-        GST_DEBUG("General black frame ");
-        gst_xvimagesink_generate_YUV420_black_frame(xvimagesink->xvimage->width, xvimagesink->xvimage->height, xvimagesink->xvimage->xvimage->data, &(xvimagesink->xvimage->size));
-
-        GST_BUFFER_FLAG_UNSET(buf, GST_BUFFER_FLAG_LAST);
-        return;
-    }
-
     imgb = (SCMN_IMGB *)GST_BUFFER_DATA(buf);
     if(imgb == NULL || imgb->a[0] == NULL)
     {
@@ -4972,7 +5174,7 @@ gst_xvimagesink_combine_i420_scmn_data(GstXvImageSink *xvimagesink, GstBuffer *b
 
     GST_DEBUG("End");
 }
-
+#endif
 
 #ifdef GST_EXT_XV_ENHANCEMENT
 static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink)
@@ -4980,7 +5182,6 @@ static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink)
   GstXvImageFlushBuffer *flush_buffer = NULL;
   GstXvImageDisplayingBuffer *display_buffer = NULL;
   tbm_bo bo = NULL;
-  tbm_bo temp_bo = NULL;
   int size = 0;
   int i = 0;
   int ret = 0;
@@ -5014,31 +5215,15 @@ static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink)
                                   xvimagesink->last_added_buffer_index);
 
   for (i = 0 ; i < XV_BUF_PLANE_NUM ; i++) {
-    if (display_buffer->bo[i] || display_buffer->dmabuf_fd[i] > 0) {
+    if (display_buffer->bo[i]) {
       tbm_bo_handle vaddr_src;
       tbm_bo_handle vaddr_dst;
 
-      /* get bo/fd size */
-      if (display_buffer->bo[i]) {
-        size = tbm_bo_size(display_buffer->bo[i]);
-      } else if (display_buffer->dmabuf_fd[i] > 0 && display_buffer->gem_name[i] > 0) {
-        temp_bo = tbm_bo_import(xvimagesink->bufmgr, display_buffer->gem_name[i]);
-        if (temp_bo) {
-          size = tbm_bo_size(temp_bo);
-          tbm_bo_unref(temp_bo);
-          temp_bo = NULL;
-        } else {
-          GST_ERROR_OBJECT(xvimagesink, "failed to import bo - name %u", display_buffer->gem_name[i]);
-        }
-      } else {
-        GST_ERROR_OBJECT(xvimagesink, "bo %p, gem handle %u, name %u",
-                                      display_buffer->bo[i],
-                                      display_buffer->gem_handle[i],
-                                      display_buffer->gem_name[i]);
-      }
+      /* get bo size */
+      size = tbm_bo_size(display_buffer->bo[i]);
 
       /* alloc bo */
-      bo = tbm_bo_alloc(xvimagesink->bufmgr, size, TBM_BO_NONCACHABLE);
+      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;
@@ -5050,23 +5235,26 @@ static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink)
       flush_buffer->bo[i] = bo;
 
       /* get virtual address */
-      if (display_buffer->bo[i]) {
-        vaddr_src = tbm_bo_get_handle(display_buffer->bo[i], TBM_DEVICE_CPU);
-      } else if (display_buffer->vaddr[i]) {
-        vaddr_src.ptr = display_buffer->vaddr[i];
-      } else {
-        vaddr_src.ptr = NULL;
-      }
-      vaddr_dst = tbm_bo_get_handle(bo, TBM_DEVICE_CPU);
+      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;
@@ -5078,11 +5266,6 @@ static gboolean gst_xvimagesink_make_flush_buffer(GstXvImageSink *xvimagesink)
   return ret;
 
 FLUSH_BUFFER_FAILED:
-  if (temp_bo) {
-    tbm_bo_unref(temp_bo);
-    temp_bo = NULL;
-  }
-
   if (flush_buffer) {
     for (i = 0 ; i < XV_BUF_PLANE_NUM ; i++) {
       if (flush_buffer->bo[i]) {
@@ -5109,6 +5292,9 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
   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);
@@ -5137,9 +5323,20 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
     /* if we have one... */
 #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) {
-      GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
+      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));
@@ -5248,11 +5445,6 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
             img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
             img_data->BufType = XV_BUF_TYPE_LEGACY;
 
-            /* set virtual address */
-            img_data->vaddr[0] = scmn_imgb->a[0];
-            img_data->vaddr[1] = scmn_imgb->a[1];
-            img_data->vaddr[2] = scmn_imgb->a[2];
-
             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 ||
@@ -5279,11 +5471,6 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
               GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
             }
 
-            /* set virtual address */
-            img_data->vaddr[0] = scmn_imgb->a[0];
-            img_data->vaddr[1] = scmn_imgb->a[1];
-            img_data->vaddr[2] = scmn_imgb->a[2];
-
             /* check secure contents path */
             if (scmn_imgb->tz_enable) {
               if (xvimagesink->secure_path != SECURE_PATH_ON) {
@@ -5296,8 +5483,12 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
                 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) {
+            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);
@@ -5314,7 +5505,13 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
               g_mutex_unlock (xvimagesink->x_lock);
             }
 
-            if (xvimagesink->drm_level) {
+            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);
+
+
+            if (xvimagesink->drm_level && is_exist) {
               Atom atom_drm = None;
               g_mutex_lock (xvimagesink->x_lock);
               atom_drm = XInternAtom( xvimagesink->xcontext->disp,
@@ -5334,7 +5531,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 
             /* set current buffer */
             xvimagesink->xvimage->current_buffer = buf;
-          } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FLUSH_BUFFER && !xvimagesink->get_pixmap_cb) {
+          } 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)) {
@@ -5356,14 +5553,69 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
           g_mutex_unlock (xvimagesink->flow_lock);
           return GST_FLOW_OK;
         }
+    } 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;
+      }
+      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_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),
@@ -5373,7 +5625,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
 
     g_mutex_unlock (xvimagesink->flow_lock);
     ret = gst_xvimagesink_xvimage_put(xvimagesink, xvimagesink->xvimage);
-    if (!ret) {
+    if (!ret && !xvimagesink->is_subpicture_format) {
       goto no_window;
     }
 #else /* GST_EXT_XV_ENHANCEMENT */
@@ -5410,6 +5662,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:{
@@ -5435,6 +5692,13 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event)
       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;
@@ -5446,26 +5710,42 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event)
           GST_INFO_OBJECT (xvimagesink, "got a event for DRM playready");
           xvimagesink->drm_level = DRM_LEVEL_1;
           if (xvimagesink->drm_level && xvimagesink->xcontext) {
-            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" );
+            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;
               }
-              XSync (xvimagesink->xcontext->disp, FALSE);
-              xvimagesink->drm_level = DRM_LEVEL_0;
+              g_mutex_unlock (xvimagesink->x_lock);
             }
-            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;
@@ -5849,6 +6129,9 @@ gst_xvimagesink_set_pixmap_handle (GstXOverlay * overlay, guintptr id)
 
   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 */
@@ -6034,11 +6317,18 @@ 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;
@@ -6092,7 +6382,6 @@ gst_xvimagesink_expose (GstXOverlay * overlay)
   GST_INFO_OBJECT(xvimagesink, "Overlay window exposed. update it");
 #endif /* GST_EXT_XV_ENHANCEMENT */
   gst_xvimagesink_xvimage_put (xvimagesink, NULL);
-
 }
 
 static void
@@ -6114,17 +6403,23 @@ 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 |
+          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 |
+          ExposureMask | StructureNotifyMask | PointerMotionMask | VisibilityChangeMask | PropertyChangeMask |
 #else /* GST_EXT_XV_ENHANCEMENT */
           ExposureMask | StructureNotifyMask | PointerMotionMask |
 #endif /* GST_EXT_XV_ENHANCEMENT */
@@ -6502,28 +6797,25 @@ 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);
-      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;
+      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[%d] set failed.", set_mode);
+            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 {
-          /* "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_WARNING_OBJECT(xvimagesink, "unsupported format(%d)", xvimagesink->display_mode);
         }
-      } else {
-        GST_INFO_OBJECT(xvimagesink, "skip display mode %d, because current mode is same", set_mode);
       }
-
-      g_mutex_unlock(xvimagesink->x_lock);
       g_mutex_unlock(xvimagesink->flow_lock);
     }
       break;
@@ -6535,7 +6827,7 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
       g_mutex_lock(xvimagesink->x_lock);
 
       if (xvimagesink->csc_range != set_range) {
-        if (xvimagesink->xcontext) {
+        if (xvimagesink->xcontext && !xvimagesink->subpicture) {
           /* set color space range */
           if (set_csc_range(xvimagesink->xcontext, set_range)) {
             xvimagesink->csc_range = set_range;
@@ -6547,6 +6839,8 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
           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 to set csc range %d, because current is same", set_range);
       }
@@ -6558,7 +6852,7 @@ 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");
-      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED) {
+      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED || xvimagesink->eos_received) {
         gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
       }
       break;
@@ -6567,7 +6861,7 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
       break;
     case PROP_ROTATE_ANGLE:
       xvimagesink->rotate_angle = g_value_get_enum (value);
-      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED) {
+      if (GST_STATE(xvimagesink) == GST_STATE_PAUSED || xvimagesink->eos_received) {
         gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
       }
       break;
@@ -6606,9 +6900,9 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
           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 );
-        xvimagesink->visible = g_value_get_boolean (value);
         gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
         g_mutex_lock( xvimagesink->flow_lock );
         g_mutex_lock( xvimagesink->x_lock );
@@ -6627,15 +6921,18 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
       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_ORIENTATION:
-      xvimagesink->dst_roi_orientation = g_value_get_enum (value);
-      GST_INFO("Orientation(%d) of ROI is changed", xvimagesink->dst_roi_orientation);
-      break;
     case PROP_DST_ROI_X:
       xvimagesink->dst_roi.x = g_value_get_int (value);
       break;
@@ -6716,12 +7013,66 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
       }
       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);
@@ -6839,12 +7190,12 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
     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_ORIENTATION:
-      g_value_set_enum (value, xvimagesink->dst_roi_orientation);
-      break;
     case PROP_DST_ROI_X:
       g_value_set_int (value, xvimagesink->dst_roi.x);
       break;
@@ -6878,13 +7229,36 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
     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);
@@ -6922,12 +7296,6 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
     gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->xvimage));
     xvimagesink->xvimage = NULL;
   }
-#ifdef GST_EXT_XV_ENHANCEMENT
-  if (xvimagesink->last_image) {
-    gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->last_image));
-    xvimagesink->last_image = NULL;
-  }
-#endif /* GST_EXT_XV_ENHANCEMENT */
 
   gst_xvimagesink_imagepool_clear (xvimagesink);
 
@@ -6937,6 +7305,12 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
     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) {
@@ -7022,9 +7396,6 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink,
   xvimagesink->xwindow = NULL;
   xvimagesink->xvimage = NULL;
   xvimagesink->cur_image = NULL;
-#ifdef GST_EXT_XV_ENHANCEMENT
-  xvimagesink->last_image = NULL;
-#endif /* GST_EXT_XV_ENHANCEMENT */
 
   xvimagesink->hue = xvimagesink->saturation = 0;
   xvimagesink->contrast = xvimagesink->brightness = 0;
@@ -7059,7 +7430,7 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink,
 
 #ifdef GST_EXT_XV_ENHANCEMENT
   xvimagesink->xid_updated = FALSE;
-  xvimagesink->display_mode = DISPLAY_MODE_DEFAULT;
+  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;
@@ -7070,7 +7441,7 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink,
   xvimagesink->zoom_pos_y = -1;
   xvimagesink->rotation = -1;
   xvimagesink->dst_roi_mode = DEF_ROI_DISPLAY_GEOMETRY_METHOD;
-  xvimagesink->dst_roi_orientation = DEGREE_0;
+  xvimagesink->orientation = DEGREE_0;
   xvimagesink->dst_roi.x = 0;
   xvimagesink->dst_roi.y = 0;
   xvimagesink->dst_roi.w = 0;
@@ -7086,6 +7457,8 @@ 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;
@@ -7112,8 +7485,22 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink,
   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 */
 }
 
@@ -7188,6 +7575,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
    *
@@ -7282,7 +7677,7 @@ 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));
 
   /**
@@ -7381,12 +7776,12 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
-   * GstXvImageSink:dst-roi-orientation
+   * GstXvImageSink:orientation
    *
    * Orientation information which will be used for ROI/ZOOM
    */
-  g_object_class_install_property(gobject_class, PROP_DST_ROI_ORIENTATION,
-    g_param_spec_enum("dst-roi-orientation", "Orientation information 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));
@@ -7449,6 +7844,11 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
       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
    *
@@ -7510,6 +7910,56 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
           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 (
@@ -7523,6 +7973,81 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
           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 */
 
@@ -7615,3 +8140,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)
+
+