mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
d3d11screencapturesrc: Allow capturing screen sub-area
Adds crop-x, crop-y, crop-width, crop-height properties specifying the screen area to capture. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1932>
This commit is contained in:
parent
253ee75a72
commit
df55700f44
3 changed files with 127 additions and 20 deletions
|
@ -344,7 +344,7 @@ public:
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
bool DrawMouse (ID3D11RenderTargetView * rtv)
|
||||
bool DrawMouse (ID3D11RenderTargetView * rtv, D3D11_BOX * cropBox)
|
||||
{
|
||||
GST_TRACE ("Drawing mouse");
|
||||
|
||||
|
@ -428,14 +428,21 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
/* Nothing draw */
|
||||
if (PtrWidth == 0 || PtrHeight == 0) {
|
||||
/* Nothing to draw */
|
||||
if (PtrWidth == 0 || PtrHeight == 0 ||
|
||||
(PtrLeft + PtrWidth) < static_cast<INT>(cropBox->left) ||
|
||||
PtrLeft > static_cast<INT>(cropBox->right) ||
|
||||
(PtrTop + PtrHeight) < static_cast<INT>(cropBox->top) ||
|
||||
PtrTop > static_cast<INT>(cropBox->bottom)) {
|
||||
if (InitBuffer)
|
||||
delete[] InitBuffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PtrLeft -= cropBox->left;
|
||||
PtrTop -= cropBox->top;
|
||||
|
||||
Vertices[0].Pos.x = (PtrLeft - CenterX) / (FLOAT)CenterX;
|
||||
Vertices[0].Pos.y = -1 * ((PtrTop + PtrHeight) - CenterY) / (FLOAT)CenterY;
|
||||
Vertices[1].Pos.x = (PtrLeft - CenterX) / (FLOAT)CenterX;
|
||||
|
@ -523,13 +530,13 @@ public:
|
|||
}
|
||||
|
||||
void
|
||||
CopyToTexture (ID3D11Texture2D * texture)
|
||||
CopyToTexture (ID3D11Texture2D * texture, D3D11_BOX * cropBox)
|
||||
{
|
||||
ID3D11DeviceContext *context_handle =
|
||||
gst_d3d11_device_get_device_context_handle (device_);
|
||||
|
||||
context_handle->CopySubresourceRegion (texture, 0, 0, 0, 0,
|
||||
shared_texture_.Get(), 0, nullptr);
|
||||
shared_texture_.Get(), 0, cropBox);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1790,10 +1797,9 @@ gst_d3d11_screen_capture_get_size (GstD3D11ScreenCapture * capture,
|
|||
GstFlowReturn
|
||||
gst_d3d11_screen_capture_do_capture (GstD3D11ScreenCapture * capture,
|
||||
ID3D11Texture2D * texture, ID3D11RenderTargetView * rtv,
|
||||
gboolean draw_mouse)
|
||||
D3D11_BOX * crop_box, gboolean draw_mouse)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
guint width, height;
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D11_SCREEN_CAPTURE (capture), GST_FLOW_ERROR);
|
||||
|
@ -1811,11 +1817,12 @@ gst_d3d11_screen_capture_do_capture (GstD3D11ScreenCapture * capture,
|
|||
|
||||
gst_d3d11_screen_capture_get_size (capture, &width, &height);
|
||||
|
||||
texture->GetDesc (&desc);
|
||||
if (desc.Width != width || desc.Height != height) {
|
||||
if (crop_box->left > width || crop_box->right > width ||
|
||||
crop_box->top > height || crop_box->bottom > height) {
|
||||
GST_INFO_OBJECT (capture,
|
||||
"Different texture size, ours: %dx%d, external: %dx%d",
|
||||
width, height, desc.Width, desc.Height);
|
||||
"Capture area (%u, %u, %u, %u) doesn't fit into screen size %ux%u",
|
||||
crop_box->left, crop_box->right, crop_box->top,
|
||||
crop_box->bottom, width, height);
|
||||
g_rec_mutex_unlock (&capture->lock);
|
||||
|
||||
return GST_D3D11_SCREEN_CAPTURE_FLOW_SIZE_CHANGED;
|
||||
|
@ -1843,9 +1850,9 @@ gst_d3d11_screen_capture_do_capture (GstD3D11ScreenCapture * capture,
|
|||
|
||||
GST_LOG_OBJECT (capture, "Capture done");
|
||||
|
||||
capture->dupl_obj->CopyToTexture (texture);
|
||||
capture->dupl_obj->CopyToTexture (texture, crop_box);
|
||||
if (draw_mouse)
|
||||
capture->dupl_obj->DrawMouse (rtv);
|
||||
capture->dupl_obj->DrawMouse (rtv, crop_box);
|
||||
gst_d3d11_device_unlock (capture->device);
|
||||
g_rec_mutex_unlock (&capture->lock);
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ gboolean gst_d3d11_screen_capture_get_size (GstD3D11ScreenCapture * captu
|
|||
|
||||
GstFlowReturn gst_d3d11_screen_capture_do_capture (GstD3D11ScreenCapture * capture,
|
||||
ID3D11Texture2D * texture,
|
||||
ID3D11RenderTargetView *rtv,
|
||||
ID3D11RenderTargetView * rtv,
|
||||
D3D11_BOX * crop_box,
|
||||
gboolean draw_mouse);
|
||||
|
||||
HRESULT gst_d3d11_screen_capture_find_output_for_monitor (HMONITOR monitor,
|
||||
|
|
|
@ -55,6 +55,10 @@ enum
|
|||
PROP_MONITOR_INDEX,
|
||||
PROP_MONITOR_HANDLE,
|
||||
PROP_SHOW_CURSOR,
|
||||
PROP_CROP_X,
|
||||
PROP_CROP_Y,
|
||||
PROP_CROP_WIDTH,
|
||||
PROP_CROP_HEIGHT,
|
||||
|
||||
PROP_LAST,
|
||||
};
|
||||
|
@ -87,6 +91,12 @@ struct _GstD3D11ScreenCaptureSrc
|
|||
HMONITOR monitor_handle;
|
||||
gboolean show_cursor;
|
||||
|
||||
guint crop_x;
|
||||
guint crop_y;
|
||||
guint crop_w;
|
||||
guint crop_h;
|
||||
D3D11_BOX crop_box;
|
||||
|
||||
gboolean flushing;
|
||||
GstClockTime min_latency;
|
||||
GstClockTime max_latency;
|
||||
|
@ -157,6 +167,30 @@ gst_d3d11_screen_capture_src_class_init (GstD3D11ScreenCaptureSrcClass * klass)
|
|||
DEFAULT_SHOW_CURSOR,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties[PROP_CROP_X] =
|
||||
g_param_spec_uint ("crop-x", "Crop X",
|
||||
"Horizontal coordinate of top left corner for the screen capture area",
|
||||
0, G_MAXUINT, 0,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties[PROP_CROP_Y] =
|
||||
g_param_spec_uint ("crop-y", "Crop Y",
|
||||
"Vertical coordinate of top left corner for the screen capture area",
|
||||
0, G_MAXUINT, 0,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties[PROP_CROP_WIDTH] =
|
||||
g_param_spec_uint ("crop-width", "Crop Width",
|
||||
"Width of screen capture area (0 = maximum)",
|
||||
0, G_MAXUINT, 0,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties[PROP_CROP_HEIGHT] =
|
||||
g_param_spec_uint ("crop-height", "Crop Height",
|
||||
"Height of screen capture area (0 = maximum)",
|
||||
0, G_MAXUINT, 0,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, properties);
|
||||
|
||||
element_class->set_context =
|
||||
|
@ -232,6 +266,18 @@ gst_d3d11_screen_capture_src_set_property (GObject * object, guint prop_id,
|
|||
case PROP_SHOW_CURSOR:
|
||||
self->show_cursor = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_CROP_X:
|
||||
self->crop_x = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_CROP_Y:
|
||||
self->crop_y = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_CROP_WIDTH:
|
||||
self->crop_w = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_CROP_HEIGHT:
|
||||
self->crop_h = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -254,6 +300,18 @@ gst_d3d11_screen_capture_src_get_property (GObject * object, guint prop_id,
|
|||
case PROP_SHOW_CURSOR:
|
||||
g_value_set_boolean (value, self->show_cursor);
|
||||
break;
|
||||
case PROP_CROP_X:
|
||||
g_value_set_uint (value, self->crop_x);
|
||||
break;
|
||||
case PROP_CROP_Y:
|
||||
g_value_set_uint (value, self->crop_y);
|
||||
break;
|
||||
case PROP_CROP_WIDTH:
|
||||
g_value_set_uint (value, self->crop_w);
|
||||
break;
|
||||
case PROP_CROP_HEIGHT:
|
||||
g_value_set_uint (value, self->crop_h);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -272,6 +330,36 @@ gst_d3d11_screen_capture_src_set_context (GstElement * element,
|
|||
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
|
||||
}
|
||||
|
||||
static D3D11_BOX
|
||||
gst_d3d11_screen_capture_src_get_crop_box (GstD3D11ScreenCaptureSrc * self)
|
||||
{
|
||||
D3D11_BOX box;
|
||||
guint screen_width, screen_height;
|
||||
|
||||
box.front = 0;
|
||||
box.back = 1;
|
||||
|
||||
gst_d3d11_screen_capture_get_size (self->capture, &screen_width,
|
||||
&screen_height);
|
||||
|
||||
if ((self->crop_x + self->crop_w) > screen_width ||
|
||||
(self->crop_y + self->crop_h) > screen_height) {
|
||||
GST_WARNING ("Capture region outside of the screen bounds; ignoring.");
|
||||
|
||||
box.left = 0;
|
||||
box.top = 0;
|
||||
box.right = screen_width;
|
||||
box.bottom = screen_height;
|
||||
} else {
|
||||
box.left = self->crop_x;
|
||||
box.top = self->crop_y;
|
||||
box.right = self->crop_w ? (self->crop_x + self->crop_w) : screen_width;
|
||||
box.bottom = self->crop_h ? (self->crop_y + self->crop_h) : screen_height;
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_d3d11_screen_capture_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||
{
|
||||
|
@ -284,11 +372,9 @@ gst_d3d11_screen_capture_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
|||
return gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
|
||||
}
|
||||
|
||||
if (!gst_d3d11_screen_capture_get_size (self->capture, &width, &height)) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
||||
("Cannot query supported resolution"), (NULL));
|
||||
return NULL;
|
||||
}
|
||||
self->crop_box = gst_d3d11_screen_capture_src_get_crop_box (self);
|
||||
width = self->crop_box.right - self->crop_box.left;
|
||||
height = self->crop_box.bottom - self->crop_box.top;
|
||||
|
||||
caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
|
||||
caps = gst_caps_make_writable (caps);
|
||||
|
@ -691,6 +777,7 @@ gst_d3d11_screen_capture_src_create (GstBaseSrc * bsrc, guint64 offset,
|
|||
gint unsupported_retry_count = 100;
|
||||
GstBuffer *buffer = NULL;
|
||||
GstBuffer *sysmem_buf = NULL;
|
||||
D3D11_BOX crop_box;
|
||||
|
||||
if (!self->capture) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ,
|
||||
|
@ -704,6 +791,18 @@ gst_d3d11_screen_capture_src_create (GstBaseSrc * bsrc, guint64 offset,
|
|||
if (fps_n <= 0 || fps_d <= 0)
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
|
||||
crop_box = gst_d3d11_screen_capture_src_get_crop_box (self);
|
||||
if (crop_box.left != self->crop_box.left ||
|
||||
crop_box.right != self->crop_box.right ||
|
||||
crop_box.top != self->crop_box.top ||
|
||||
crop_box.bottom != self->crop_box.bottom) {
|
||||
GST_INFO_OBJECT (self, "Capture area changed, need negotiation");
|
||||
if (!gst_base_src_negotiate (bsrc)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to negotiate with new capture area");
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
}
|
||||
|
||||
again:
|
||||
clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
|
||||
if (!clock) {
|
||||
|
@ -820,7 +919,7 @@ again:
|
|||
before_capture = gst_clock_get_time (clock);
|
||||
ret =
|
||||
gst_d3d11_screen_capture_do_capture (self->capture, texture, rtv,
|
||||
draw_mouse);
|
||||
&self->crop_box, draw_mouse);
|
||||
gst_memory_unmap (mem, &info);
|
||||
|
||||
switch (ret) {
|
||||
|
|
Loading…
Reference in a new issue