diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp index 91d6772cad..17eb46681e 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp @@ -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(cropBox->left) || + PtrLeft > static_cast(cropBox->right) || + (PtrTop + PtrHeight) < static_cast(cropBox->top) || + PtrTop > static_cast(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); diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.h b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.h index 3c9ce3e589..b582d8e9a4 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.h +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.h @@ -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, diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapturesrc.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapturesrc.cpp index e6a16b129b..2e7b301fb7 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapturesrc.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapturesrc.cpp @@ -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) {