X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=sys%2Fxvimage%2Fxvimagesink.c;fp=wearable%2Fsys%2Fxvimage%2Fxvimagesink.c;h=72d83100c8997cee09fb163b79f75126879063a9;hb=refs%2Fheads%2Ftizen_2.3;hp=52632b86911637ec85b77db7da32a5ebc8fb2a71;hpb=b692b5b643614ff3a2b42a4534de308987013e49;p=framework%2Fmultimedia%2Fgst-plugins-base0.10.git diff --git a/wearable/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c similarity index 82% rename from wearable/sys/xvimage/xvimagesink.c rename to sys/xvimage/xvimagesink.c index 52632b8..72d8310 100755 --- a/wearable/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -146,8 +146,10 @@ #include #include -/* for performance checking */ -#include +/* for setting vconf about xv state */ +#include +#include + 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(¤t_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(¤t_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) + +