avfvideosrc: Allow specifying crop coordinates during screen capture

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3153>
This commit is contained in:
Piotr Brzeziński 2022-10-08 00:29:03 +02:00 committed by GStreamer Marge Bot
parent f5451f7ff2
commit 1e70525bc9

View file

@ -194,6 +194,10 @@ gst_avf_video_source_device_type_get_type (void)
BOOL captureScreen; BOOL captureScreen;
BOOL captureScreenCursor; BOOL captureScreenCursor;
BOOL captureScreenMouseClicks; BOOL captureScreenMouseClicks;
guint cropX;
guint cropY;
guint cropWidth;
guint cropHeight;
BOOL useVideoMeta; BOOL useVideoMeta;
GstGLContextHelper *ctxh; GstGLContextHelper *ctxh;
@ -214,6 +218,10 @@ gst_avf_video_source_device_type_get_type (void)
@property BOOL captureScreen; @property BOOL captureScreen;
@property BOOL captureScreenCursor; @property BOOL captureScreenCursor;
@property BOOL captureScreenMouseClicks; @property BOOL captureScreenMouseClicks;
@property guint cropX;
@property guint cropY;
@property guint cropWidth;
@property guint cropHeight;
- (BOOL)openScreenInput; - (BOOL)openScreenInput;
- (BOOL)openDeviceInput; - (BOOL)openDeviceInput;
@ -294,7 +302,7 @@ static AVCaptureVideoOrientation GstAVFVideoSourceOrientation2AVCaptureVideoOrie
@implementation GstAVFVideoSrcImpl @implementation GstAVFVideoSrcImpl
@synthesize deviceIndex, deviceName, position, orientation, deviceType, doStats, @synthesize deviceIndex, deviceName, position, orientation, deviceType, doStats,
fps, captureScreen, captureScreenCursor, captureScreenMouseClicks; fps, captureScreen, captureScreenCursor, captureScreenMouseClicks, cropX, cropY, cropWidth, cropHeight;
- (id)init - (id)init
{ {
@ -393,6 +401,7 @@ static AVCaptureVideoOrientation GstAVFVideoSourceOrientation2AVCaptureVideoOrie
return NO; return NO;
#else #else
CGDirectDisplayID displayId; CGDirectDisplayID displayId;
int screenHeight, screenWidth;
GST_DEBUG_OBJECT (element, "Opening screen input"); GST_DEBUG_OBJECT (element, "Opening screen input");
@ -403,7 +412,6 @@ static AVCaptureVideoOrientation GstAVFVideoSourceOrientation2AVCaptureVideoOrie
AVCaptureScreenInput *screenInput = AVCaptureScreenInput *screenInput =
[[AVCaptureScreenInput alloc] initWithDisplayID:displayId]; [[AVCaptureScreenInput alloc] initWithDisplayID:displayId];
@try { @try {
[screenInput setValue:[NSNumber numberWithBool:captureScreenCursor] [screenInput setValue:[NSNumber numberWithBool:captureScreenCursor]
forKey:@"capturesCursor"]; forKey:@"capturesCursor"];
@ -415,6 +423,24 @@ static AVCaptureVideoOrientation GstAVFVideoSourceOrientation2AVCaptureVideoOrie
} }
GST_WARNING ("Capturing cursor is only supported in OS X >= 10.8"); GST_WARNING ("Capturing cursor is only supported in OS X >= 10.8");
} }
screenHeight = CGDisplayPixelsHigh (displayId);
screenWidth = CGDisplayPixelsWide (displayId);
if (cropX + cropWidth > screenWidth || cropY + cropHeight > screenHeight) {
GST_WARNING ("Capture region outside of screen bounds, ignoring");
} else {
/* If width/height is not specified, assume max possible values */
int rectWidth = cropWidth ? cropWidth : (screenWidth - cropX);
int rectHeight = cropHeight ? cropHeight : (screenHeight - cropY);
/* cropRect (0,0) is bottom left, which feels counterintuitive.
* Make cropY relative to the top edge instead */
CGRect cropRect = CGRectMake (cropX, screenHeight - cropY - rectHeight,
rectWidth, rectHeight);
[screenInput setCropRect:cropRect];
}
screenInput.capturesMouseClicks = captureScreenMouseClicks; screenInput.capturesMouseClicks = captureScreenMouseClicks;
input = screenInput; input = screenInput;
return YES; return YES;
@ -771,7 +797,14 @@ checked:
if (captureScreen) { if (captureScreen) {
#if !HAVE_IOS #if !HAVE_IOS
CGRect rect = CGDisplayBounds ([self getDisplayIdFromDeviceIndex]); CGRect rect;
AVCaptureScreenInput *screenInput = (AVCaptureScreenInput *)input;
if (CGRectIsEmpty (screenInput.cropRect)) {
rect = CGDisplayBounds ([self getDisplayIdFromDeviceIndex]);
} else {
rect = screenInput.cropRect;
}
float scale = [self getScaleFactorFromDeviceIndex]; float scale = [self getScaleFactorFromDeviceIndex];
for (NSNumber *pixel_format in pixel_formats) { for (NSNumber *pixel_format in pixel_formats) {
GstVideoFormat gst_format = [self getGstVideoFormat:pixel_format]; GstVideoFormat gst_format = [self getGstVideoFormat:pixel_format];
@ -1244,6 +1277,10 @@ enum
PROP_CAPTURE_SCREEN, PROP_CAPTURE_SCREEN,
PROP_CAPTURE_SCREEN_CURSOR, PROP_CAPTURE_SCREEN_CURSOR,
PROP_CAPTURE_SCREEN_MOUSE_CLICKS, PROP_CAPTURE_SCREEN_MOUSE_CLICKS,
PROP_CAPTURE_SCREEN_CROP_X,
PROP_CAPTURE_SCREEN_CROP_Y,
PROP_CAPTURE_SCREEN_CROP_WIDTH,
PROP_CAPTURE_SCREEN_CROP_HEIGHT,
#endif #endif
}; };
@ -1353,6 +1390,22 @@ gst_avf_video_src_class_init (GstAVFVideoSrcClass * klass)
g_param_spec_boolean ("capture-screen-mouse-clicks", "Enable mouse clicks capture", g_param_spec_boolean ("capture-screen-mouse-clicks", "Enable mouse clicks capture",
"Enable mouse clicks capture while capturing screen", FALSE, "Enable mouse clicks capture while capturing screen", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CAPTURE_SCREEN_CROP_X,
g_param_spec_uint ("screen-crop-x", "Screen capture crop X",
"Horizontal coordinate of top left corner of the screen capture area",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CAPTURE_SCREEN_CROP_Y,
g_param_spec_uint ("screen-crop-y", "Screen capture crop Y",
"Vertical coordinate of top left corner of the screen capture area",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CAPTURE_SCREEN_CROP_WIDTH,
g_param_spec_uint ("screen-crop-width", "Screen capture crop width",
"Width of the screen capture area (0 = maximum)",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CAPTURE_SCREEN_CROP_HEIGHT,
g_param_spec_uint ("screen-crop-height", "Screen capture crop height",
"Height of the screen capture area (0 = maximum)",
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#endif #endif
GST_DEBUG_CATEGORY_INIT (gst_avf_video_src_debug, "avfvideosrc", GST_DEBUG_CATEGORY_INIT (gst_avf_video_src_debug, "avfvideosrc",
@ -1394,6 +1447,18 @@ gst_avf_video_src_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_CAPTURE_SCREEN_MOUSE_CLICKS: case PROP_CAPTURE_SCREEN_MOUSE_CLICKS:
g_value_set_boolean (value, impl.captureScreenMouseClicks); g_value_set_boolean (value, impl.captureScreenMouseClicks);
break; break;
case PROP_CAPTURE_SCREEN_CROP_X:
g_value_set_uint (value, impl.cropX);
break;
case PROP_CAPTURE_SCREEN_CROP_Y:
g_value_set_uint (value, impl.cropY);
break;
case PROP_CAPTURE_SCREEN_CROP_WIDTH:
g_value_set_uint (value, impl.cropWidth);
break;
case PROP_CAPTURE_SCREEN_CROP_HEIGHT:
g_value_set_uint (value, impl.cropHeight);
break;
#endif #endif
case PROP_DEVICE_INDEX: case PROP_DEVICE_INDEX:
g_value_set_int (value, impl.deviceIndex); g_value_set_int (value, impl.deviceIndex);
@ -1441,6 +1506,18 @@ gst_avf_video_src_set_property (GObject * object, guint prop_id,
case PROP_CAPTURE_SCREEN_MOUSE_CLICKS: case PROP_CAPTURE_SCREEN_MOUSE_CLICKS:
impl.captureScreenMouseClicks = g_value_get_boolean (value); impl.captureScreenMouseClicks = g_value_get_boolean (value);
break; break;
case PROP_CAPTURE_SCREEN_CROP_X:
impl.cropX = g_value_get_uint (value);
break;
case PROP_CAPTURE_SCREEN_CROP_Y:
impl.cropY = g_value_get_uint (value);
break;
case PROP_CAPTURE_SCREEN_CROP_WIDTH:
impl.cropWidth = g_value_get_uint (value);
break;
case PROP_CAPTURE_SCREEN_CROP_HEIGHT:
impl.cropHeight = g_value_get_uint (value);
break;
#endif #endif
case PROP_DEVICE_INDEX: case PROP_DEVICE_INDEX:
impl.deviceIndex = g_value_get_int (value); impl.deviceIndex = g_value_get_int (value);