mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 08:41:07 +00:00
eglglessink: Add support for crop metadata
This commit is contained in:
parent
187350329a
commit
1e1d4da87c
2 changed files with 89 additions and 27 deletions
|
@ -117,6 +117,7 @@
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
#include <gst/video/video-frame.h>
|
#include <gst/video/video-frame.h>
|
||||||
#include <gst/video/gstvideosink.h>
|
#include <gst/video/gstvideosink.h>
|
||||||
|
#include <gst/video/gstvideometa.h>
|
||||||
#include <gst/video/videooverlay.h>
|
#include <gst/video/videooverlay.h>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
@ -363,6 +364,8 @@ static GstFlowReturn gst_eglglessink_show_frame (GstVideoSink * vsink,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
static gboolean gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps);
|
static gboolean gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps);
|
||||||
static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter);
|
static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter);
|
||||||
|
static gboolean gst_eglglessink_propose_allocation (GstBaseSink * bsink,
|
||||||
|
GstQuery * query);
|
||||||
|
|
||||||
/* VideoOverlay interface cruft */
|
/* VideoOverlay interface cruft */
|
||||||
static void gst_eglglessink_videooverlay_init (GstVideoOverlayInterface *
|
static void gst_eglglessink_videooverlay_init (GstVideoOverlayInterface *
|
||||||
|
@ -893,6 +896,7 @@ gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, gboolean reset)
|
||||||
{
|
{
|
||||||
gdouble surface_width, surface_height;
|
gdouble surface_width, surface_height;
|
||||||
gdouble x1, x2, y1, y2;
|
gdouble x1, x2, y1, y2;
|
||||||
|
gdouble tx1, tx2, ty1, ty2;
|
||||||
|
|
||||||
GST_INFO_OBJECT (eglglessink, "VBO setup. have_vbo:%d, should reset %d",
|
GST_INFO_OBJECT (eglglessink, "VBO setup. have_vbo:%d, should reset %d",
|
||||||
eglglessink->have_vbo, reset);
|
eglglessink->have_vbo, reset);
|
||||||
|
@ -915,29 +919,38 @@ gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, gboolean reset)
|
||||||
y2 = ((eglglessink->display_region.y +
|
y2 = ((eglglessink->display_region.y +
|
||||||
eglglessink->display_region.h) / surface_height) * 2.0 - 1;
|
eglglessink->display_region.h) / surface_height) * 2.0 - 1;
|
||||||
|
|
||||||
|
tx1 = (eglglessink->crop.x / eglglessink->configured_info.width);
|
||||||
|
tx2 =
|
||||||
|
((eglglessink->crop.x +
|
||||||
|
eglglessink->crop.width) / eglglessink->configured_info.width);
|
||||||
|
ty1 = (eglglessink->crop.y / eglglessink->configured_info.height);
|
||||||
|
ty2 =
|
||||||
|
((eglglessink->crop.y +
|
||||||
|
eglglessink->crop.height) / eglglessink->configured_info.height);
|
||||||
|
|
||||||
eglglessink->eglglesctx.position_array[0].x = x2;
|
eglglessink->eglglesctx.position_array[0].x = x2;
|
||||||
eglglessink->eglglesctx.position_array[0].y = y2;
|
eglglessink->eglglesctx.position_array[0].y = y2;
|
||||||
eglglessink->eglglesctx.position_array[0].z = 0;
|
eglglessink->eglglesctx.position_array[0].z = 0;
|
||||||
eglglessink->eglglesctx.position_array[0].a = 1;
|
eglglessink->eglglesctx.position_array[0].a = tx2;
|
||||||
eglglessink->eglglesctx.position_array[0].b = 0;
|
eglglessink->eglglesctx.position_array[0].b = ty1;
|
||||||
|
|
||||||
eglglessink->eglglesctx.position_array[1].x = x2;
|
eglglessink->eglglesctx.position_array[1].x = x2;
|
||||||
eglglessink->eglglesctx.position_array[1].y = y1;
|
eglglessink->eglglesctx.position_array[1].y = y1;
|
||||||
eglglessink->eglglesctx.position_array[1].z = 0;
|
eglglessink->eglglesctx.position_array[1].z = 0;
|
||||||
eglglessink->eglglesctx.position_array[1].a = 1;
|
eglglessink->eglglesctx.position_array[1].a = tx2;
|
||||||
eglglessink->eglglesctx.position_array[1].b = 1;
|
eglglessink->eglglesctx.position_array[1].b = ty2;
|
||||||
|
|
||||||
eglglessink->eglglesctx.position_array[2].x = x1;
|
eglglessink->eglglesctx.position_array[2].x = x1;
|
||||||
eglglessink->eglglesctx.position_array[2].y = y2;
|
eglglessink->eglglesctx.position_array[2].y = y2;
|
||||||
eglglessink->eglglesctx.position_array[2].z = 0;
|
eglglessink->eglglesctx.position_array[2].z = 0;
|
||||||
eglglessink->eglglesctx.position_array[2].a = 0;
|
eglglessink->eglglesctx.position_array[2].a = tx1;
|
||||||
eglglessink->eglglesctx.position_array[2].b = 0;
|
eglglessink->eglglesctx.position_array[2].b = ty1;
|
||||||
|
|
||||||
eglglessink->eglglesctx.position_array[3].x = x1;
|
eglglessink->eglglesctx.position_array[3].x = x1;
|
||||||
eglglessink->eglglesctx.position_array[3].y = y1;
|
eglglessink->eglglesctx.position_array[3].y = y1;
|
||||||
eglglessink->eglglesctx.position_array[3].z = 0;
|
eglglessink->eglglesctx.position_array[3].z = 0;
|
||||||
eglglessink->eglglesctx.position_array[3].a = 0;
|
eglglessink->eglglesctx.position_array[3].a = tx1;
|
||||||
eglglessink->eglglesctx.position_array[3].b = 1;
|
eglglessink->eglglesctx.position_array[3].b = ty2;
|
||||||
|
|
||||||
if (eglglessink->display_region.x == 0) {
|
if (eglglessink->display_region.x == 0) {
|
||||||
/* Borders top/bottom */
|
/* Borders top/bottom */
|
||||||
|
@ -1702,6 +1715,22 @@ gst_eglglessink_queue_buffer (GstEglGlesSink * eglglessink, GstBuffer * buf)
|
||||||
return (buf ? eglglessink->last_flow : GST_FLOW_OK);
|
return (buf ? eglglessink->last_flow : GST_FLOW_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_eglglessink_crop_changed (GstEglGlesSink * eglglessink,
|
||||||
|
GstVideoCropMeta * crop)
|
||||||
|
{
|
||||||
|
if (crop) {
|
||||||
|
return (crop->x != eglglessink->crop.x ||
|
||||||
|
crop->y != eglglessink->crop.y ||
|
||||||
|
crop->width != eglglessink->crop.width ||
|
||||||
|
crop->height != eglglessink->crop.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (eglglessink->crop.x != 0 || eglglessink->crop.y != 0 ||
|
||||||
|
eglglessink->crop.width != GST_VIDEO_SINK_WIDTH (eglglessink) ||
|
||||||
|
eglglessink->crop.height != GST_VIDEO_SINK_HEIGHT (eglglessink));
|
||||||
|
}
|
||||||
|
|
||||||
/* Rendering and display */
|
/* Rendering and display */
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
|
@ -1711,12 +1740,15 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
GstVideoRectangle frame, surface;
|
GstVideoRectangle frame, surface;
|
||||||
gint w, h;
|
gint w, h;
|
||||||
guint dar_n, dar_d;
|
guint dar_n, dar_d;
|
||||||
|
GstVideoCropMeta *crop;
|
||||||
|
|
||||||
memset (&vframe, 0, sizeof (vframe));
|
memset (&vframe, 0, sizeof (vframe));
|
||||||
|
|
||||||
w = GST_VIDEO_SINK_WIDTH (eglglessink);
|
w = GST_VIDEO_SINK_WIDTH (eglglessink);
|
||||||
h = GST_VIDEO_SINK_HEIGHT (eglglessink);
|
h = GST_VIDEO_SINK_HEIGHT (eglglessink);
|
||||||
|
|
||||||
|
crop = gst_buffer_get_video_crop_meta (buf);
|
||||||
|
|
||||||
if (!gst_video_frame_map (&vframe, &eglglessink->configured_info, buf,
|
if (!gst_video_frame_map (&vframe, &eglglessink->configured_info, buf,
|
||||||
GST_MAP_READ)) {
|
GST_MAP_READ)) {
|
||||||
GST_ERROR_OBJECT (eglglessink, "Couldn't map frame");
|
GST_ERROR_OBJECT (eglglessink, "Couldn't map frame");
|
||||||
|
@ -1844,39 +1876,59 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
* force_aspect_ratio to FALSE.
|
* force_aspect_ratio to FALSE.
|
||||||
*/
|
*/
|
||||||
if (gst_eglglessink_update_surface_dimensions (eglglessink) ||
|
if (gst_eglglessink_update_surface_dimensions (eglglessink) ||
|
||||||
!eglglessink->display_region.w || !eglglessink->display_region.h) {
|
!eglglessink->display_region.w || !eglglessink->display_region.h ||
|
||||||
|
gst_eglglessink_crop_changed (eglglessink, crop)) {
|
||||||
GST_OBJECT_LOCK (eglglessink);
|
GST_OBJECT_LOCK (eglglessink);
|
||||||
|
if (crop) {
|
||||||
|
eglglessink->crop.x = crop->x;
|
||||||
|
eglglessink->crop.y = crop->y;
|
||||||
|
eglglessink->crop.width = crop->width;
|
||||||
|
eglglessink->crop.height = crop->height;
|
||||||
|
} else {
|
||||||
|
eglglessink->crop.x = 0;
|
||||||
|
eglglessink->crop.y = 0;
|
||||||
|
eglglessink->crop.width = w;
|
||||||
|
eglglessink->crop.height = h;
|
||||||
|
}
|
||||||
|
|
||||||
if (!eglglessink->force_aspect_ratio) {
|
if (!eglglessink->force_aspect_ratio) {
|
||||||
eglglessink->display_region.x = 0;
|
eglglessink->display_region.x = 0;
|
||||||
eglglessink->display_region.y = 0;
|
eglglessink->display_region.y = 0;
|
||||||
eglglessink->display_region.w = eglglessink->eglglesctx.surface_width;
|
eglglessink->display_region.w = eglglessink->eglglesctx.surface_width;
|
||||||
eglglessink->display_region.h = eglglessink->eglglesctx.surface_height;
|
eglglessink->display_region.h = eglglessink->eglglesctx.surface_height;
|
||||||
} else {
|
} else {
|
||||||
if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, w, h,
|
if (!gst_video_calculate_display_ratio (&dar_n, &dar_d,
|
||||||
eglglessink->par_n, eglglessink->par_d,
|
eglglessink->crop.width, eglglessink->crop.height,
|
||||||
|
eglglessink->configured_info.par_n,
|
||||||
|
eglglessink->configured_info.par_d,
|
||||||
eglglessink->eglglesctx.pixel_aspect_ratio,
|
eglglessink->eglglesctx.pixel_aspect_ratio,
|
||||||
EGL_DISPLAY_SCALING)) {
|
EGL_DISPLAY_SCALING)) {
|
||||||
GST_WARNING_OBJECT (eglglessink, "Could not compute resulting DAR");
|
GST_WARNING_OBJECT (eglglessink, "Could not compute resulting DAR");
|
||||||
frame.w = w;
|
frame.w = eglglessink->crop.width;
|
||||||
frame.h = h;
|
frame.h = eglglessink->crop.height;
|
||||||
} else {
|
} else {
|
||||||
/* Find suitable matching new size acording to dar & par
|
/* Find suitable matching new size acording to dar & par
|
||||||
* rationale for prefering leaving the height untouched
|
* rationale for prefering leaving the height untouched
|
||||||
* comes from interlacing considerations.
|
* comes from interlacing considerations.
|
||||||
* XXX: Move this to gstutils?
|
* XXX: Move this to gstutils?
|
||||||
*/
|
*/
|
||||||
if (h % dar_d == 0) {
|
if (eglglessink->crop.height % dar_d == 0) {
|
||||||
frame.w = gst_util_uint64_scale_int (h, dar_n, dar_d);
|
frame.w =
|
||||||
frame.h = h;
|
gst_util_uint64_scale_int (eglglessink->crop.height, dar_n,
|
||||||
} else if (w % dar_n == 0) {
|
dar_d);
|
||||||
frame.h = gst_util_uint64_scale_int (w, dar_d, dar_n);
|
frame.h = eglglessink->crop.height;
|
||||||
frame.w = w;
|
} else if (eglglessink->crop.width % dar_n == 0) {
|
||||||
|
frame.h =
|
||||||
|
gst_util_uint64_scale_int (eglglessink->crop.width, dar_d, dar_n);
|
||||||
|
frame.w = eglglessink->crop.width;
|
||||||
} else {
|
} else {
|
||||||
/* Neither width nor height can be precisely scaled.
|
/* Neither width nor height can be precisely scaled.
|
||||||
* Prefer to leave height untouched. See comment above.
|
* Prefer to leave height untouched. See comment above.
|
||||||
*/
|
*/
|
||||||
frame.w = gst_util_uint64_scale_int (h, dar_n, dar_d);
|
frame.w =
|
||||||
frame.h = h;
|
gst_util_uint64_scale_int (eglglessink->crop.height, dar_n,
|
||||||
|
dar_d);
|
||||||
|
frame.h = eglglessink->crop.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2009,6 +2061,17 @@ gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
|
{
|
||||||
|
/* FIXME: Add support for video meta, i.e. arbitrary strides
|
||||||
|
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
|
||||||
|
*/
|
||||||
|
gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps)
|
gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -2295,6 +2358,8 @@ gst_eglglessink_class_init (GstEglGlesSinkClass * klass)
|
||||||
|
|
||||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps);
|
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps);
|
||||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps);
|
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps);
|
||||||
|
gstbasesink_class->propose_allocation =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_eglglessink_propose_allocation);
|
||||||
|
|
||||||
gstvideosink_class->show_frame =
|
gstvideosink_class->show_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame);
|
GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame);
|
||||||
|
@ -2348,9 +2413,6 @@ gst_eglglessink_init (GstEglGlesSink * eglglessink)
|
||||||
eglglessink->create_window = TRUE;
|
eglglessink->create_window = TRUE;
|
||||||
eglglessink->force_aspect_ratio = TRUE;
|
eglglessink->force_aspect_ratio = TRUE;
|
||||||
|
|
||||||
eglglessink->par_n = 1;
|
|
||||||
eglglessink->par_d = 1;
|
|
||||||
|
|
||||||
eglglessink->render_lock = g_mutex_new ();
|
eglglessink->render_lock = g_mutex_new ();
|
||||||
eglglessink->render_cond = g_cond_new ();
|
eglglessink->render_cond = g_cond_new ();
|
||||||
eglglessink->queue =
|
eglglessink->queue =
|
||||||
|
|
|
@ -158,8 +158,6 @@ struct _GstEglGlesImageFmt
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GstEglGlesSink:
|
* GstEglGlesSink:
|
||||||
* @par_n: Incoming frame's aspect ratio numerator
|
|
||||||
* @par_d: Incoming frame's aspect ratio denominator
|
|
||||||
* @format: Caps' video format field
|
* @format: Caps' video format field
|
||||||
* @display_region: Surface region to use as rendering canvas
|
* @display_region: Surface region to use as rendering canvas
|
||||||
* @sinkcaps: Full set of suported caps
|
* @sinkcaps: Full set of suported caps
|
||||||
|
@ -184,9 +182,11 @@ struct _GstEglGlesImageFmt
|
||||||
struct _GstEglGlesSink
|
struct _GstEglGlesSink
|
||||||
{
|
{
|
||||||
GstVideoSink videosink; /* Element hook */
|
GstVideoSink videosink; /* Element hook */
|
||||||
int par_n, par_d; /* Aspect ratio from caps */
|
|
||||||
|
|
||||||
GstVideoRectangle display_region;
|
GstVideoRectangle display_region;
|
||||||
|
struct {
|
||||||
|
gint x, y, width, height;
|
||||||
|
} crop;
|
||||||
GstCaps *sinkcaps;
|
GstCaps *sinkcaps;
|
||||||
GstCaps *current_caps, *configured_caps;
|
GstCaps *current_caps, *configured_caps;
|
||||||
GstVideoInfo configured_info;
|
GstVideoInfo configured_info;
|
||||||
|
|
Loading…
Reference in a new issue