From d16ea653fedafcd6b6547a1a2684fe7d262cd29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Wed, 23 May 2018 01:16:27 +0200 Subject: [PATCH 01/21] GetSourceImage WIP --- src/WSRequestHandler.cpp | 1 + src/WSRequestHandler.h | 1 + src/WSRequestHandler_Sources.cpp | 68 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/src/WSRequestHandler.cpp b/src/WSRequestHandler.cpp index 374a8ab7..c247fbc6 100644 --- a/src/WSRequestHandler.cpp +++ b/src/WSRequestHandler.cpp @@ -85,6 +85,7 @@ QHash WSRequestHandler::messageM { "GetSourceTypesList", WSRequestHandler::HandleGetSourceTypesList }, { "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings }, { "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings }, + { "GetSourceImage", WSRequestHandler::HandleGetSourceImage }, { "GetSourceFilters", WSRequestHandler::HandleGetSourceFilters }, { "AddFilterToSource", WSRequestHandler::HandleAddFilterToSource }, diff --git a/src/WSRequestHandler.h b/src/WSRequestHandler.h index 6824a385..92fa54b1 100644 --- a/src/WSRequestHandler.h +++ b/src/WSRequestHandler.h @@ -116,6 +116,7 @@ class WSRequestHandler : public QObject { static HandlerResponse HandleGetSourceTypesList(WSRequestHandler* req); static HandlerResponse HandleGetSourceSettings(WSRequestHandler* req); static HandlerResponse HandleSetSourceSettings(WSRequestHandler* req); + static void HandleGetSourceImage(WSRequestHandler* req); static HandlerResponse HandleGetSourceFilters(WSRequestHandler* req); static HandlerResponse HandleAddFilterToSource(WSRequestHandler* req); diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 03ab8ada..9ceb5a93 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1332,3 +1332,71 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler return req->SendOKResponse(); } + +void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { + if (!req->hasField("sourceName")) { + req->SendErrorResponse("missing request parameters"); + return; + } + + const char* sourceName = obs_data_get_string(req->data, "sourceName"); + OBSSourceAutoRelease source = obs_get_source_by_name(sourceName); + if (!source) { + req->SendErrorResponse("specified source doesn't exist"); + return; + } + + const uint32_t imgWidth = obs_source_get_base_width(source); + const uint32_t imgHeight = obs_source_get_base_height(source); + const uint32_t imgBufSize = imgWidth * imgHeight * 4; + QByteArray imgSourceBuf(imgBufSize, '\0'); + + uint8_t* videoData = nullptr; + uint32_t videoLinesize = 0; + + obs_enter_graphics(); + + gs_texrender_t* texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); + gs_stagesurf_t* stagesurface = gs_stagesurface_create(imgWidth, imgHeight, GS_RGBA); + + bool renderSuccess = false; + gs_texrender_reset(texrender); + if (gs_texrender_begin(texrender, imgWidth, imgHeight)) { + struct vec4 background; + vec4_zero(&background); + + gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0); + gs_ortho(0.0f, (float)imgWidth, 0.0f, (float)imgHeight, -100.0f, 100.0f); + + gs_blend_state_push(); + gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); + + obs_source_video_render(source); + + gs_blend_state_pop(); + gs_texrender_end(texrender); + + gs_stage_texture(stagesurface, gs_texrender_get_texture(texrender)); + if (gs_stagesurface_map(stagesurface, &videoData, &videoLinesize)) { + memcpy((void*)imgSourceBuf.constData(), videoData, videoLinesize * imgHeight); + gs_stagesurface_unmap(stagesurface); + renderSuccess = true; + } + } + + gs_stagesurface_destroy(stagesurface); + gs_texrender_destroy(texrender); + + obs_leave_graphics(); + + if (renderSuccess) { + QString imgDataB64(imgSourceBuf.toBase64()); + + OBSDataAutoRelease response = obs_data_create(); + obs_data_set_string(response, "sourceName", obs_source_get_name(source)); + obs_data_set_string(response, "img_base64", imgDataB64.toUtf8().constData()); + req->SendOKResponse(response); + } else { + req->SendErrorResponse("Source render failed."); + } +} From 87c13b6f2608cf63aa78c9375e6ccd172d7b1ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Wed, 23 May 2018 02:01:35 +0200 Subject: [PATCH 02/21] Working PNG output --- src/WSRequestHandler_Sources.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 9ceb5a93..99354f97 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include "Utils.h" #include "WSRequestHandler.h" @@ -1349,7 +1352,7 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { const uint32_t imgWidth = obs_source_get_base_width(source); const uint32_t imgHeight = obs_source_get_base_height(source); const uint32_t imgBufSize = imgWidth * imgHeight * 4; - QByteArray imgSourceBuf(imgBufSize, '\0'); + uint8_t* imgBuf = new uint8_t[imgBufSize]; uint8_t* videoData = nullptr; uint32_t videoLinesize = 0; @@ -1378,7 +1381,7 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { gs_stage_texture(stagesurface, gs_texrender_get_texture(texrender)); if (gs_stagesurface_map(stagesurface, &videoData, &videoLinesize)) { - memcpy((void*)imgSourceBuf.constData(), videoData, videoLinesize * imgHeight); + memcpy(imgBuf, videoData, videoLinesize * imgHeight); gs_stagesurface_unmap(stagesurface); renderSuccess = true; } @@ -1390,13 +1393,24 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { obs_leave_graphics(); if (renderSuccess) { - QString imgDataB64(imgSourceBuf.toBase64()); + QImage sourceImage(imgBuf, imgWidth, imgHeight, QImage::Format::Format_RGBA8888); + + QByteArray pngBytes; + QBuffer pngBytesBuf(&pngBytes); + pngBytesBuf.open(QBuffer::ReadWrite); + sourceImage.save(&pngBytesBuf, "PNG"); + pngBytesBuf.close(); + + QString pngBase64(pngBytes.toBase64()); + pngBase64.prepend("data:image/png;base64,"); OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); - obs_data_set_string(response, "img_base64", imgDataB64.toUtf8().constData()); + obs_data_set_string(response, "img", pngBase64.toUtf8().constData()); req->SendOKResponse(response); } else { req->SendErrorResponse("Source render failed."); } + + delete imgBuf; } From 89f95f64595c8f2418284e5e2c5b03f6cc1ef550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Wed, 23 May 2018 02:29:40 +0200 Subject: [PATCH 03/21] switch to WebP --- src/WSRequestHandler_Sources.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 99354f97..9217a912 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1395,18 +1395,18 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { if (renderSuccess) { QImage sourceImage(imgBuf, imgWidth, imgHeight, QImage::Format::Format_RGBA8888); - QByteArray pngBytes; - QBuffer pngBytesBuf(&pngBytes); - pngBytesBuf.open(QBuffer::ReadWrite); - sourceImage.save(&pngBytesBuf, "PNG"); - pngBytesBuf.close(); + QByteArray encodedImgBytes; + QBuffer buffer(&encodedImgBytes); + buffer.open(QBuffer::WriteOnly); + sourceImage.save(&buffer, "WEBP", 0); + buffer.close(); - QString pngBase64(pngBytes.toBase64()); - pngBase64.prepend("data:image/png;base64,"); + QString imgBase64(encodedImgBytes.toBase64()); + imgBase64.prepend("data:image/webp;base64,"); OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); - obs_data_set_string(response, "img", pngBase64.toUtf8().constData()); + obs_data_set_string(response, "img", imgBase64.toUtf8().constData()); req->SendOKResponse(response); } else { req->SendErrorResponse("Source render failed."); From 79ddb43ac316946e237cfbb2c28e3bc96947295f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Sun, 27 May 2018 20:11:32 +0200 Subject: [PATCH 04/21] use QImage buf directly --- src/WSRequestHandler_Sources.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 9217a912..aac42bb4 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1351,8 +1351,8 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { const uint32_t imgWidth = obs_source_get_base_width(source); const uint32_t imgHeight = obs_source_get_base_height(source); - const uint32_t imgBufSize = imgWidth * imgHeight * 4; - uint8_t* imgBuf = new uint8_t[imgBufSize]; + QImage sourceImage(imgWidth, imgHeight, QImage::Format::Format_RGBA8888); + sourceImage.fill(0); uint8_t* videoData = nullptr; uint32_t videoLinesize = 0; @@ -1381,7 +1381,7 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { gs_stage_texture(stagesurface, gs_texrender_get_texture(texrender)); if (gs_stagesurface_map(stagesurface, &videoData, &videoLinesize)) { - memcpy(imgBuf, videoData, videoLinesize * imgHeight); + memcpy(sourceImage.bits(), videoData, videoLinesize * imgHeight); gs_stagesurface_unmap(stagesurface); renderSuccess = true; } @@ -1393,12 +1393,10 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { obs_leave_graphics(); if (renderSuccess) { - QImage sourceImage(imgBuf, imgWidth, imgHeight, QImage::Format::Format_RGBA8888); - QByteArray encodedImgBytes; QBuffer buffer(&encodedImgBytes); buffer.open(QBuffer::WriteOnly); - sourceImage.save(&buffer, "WEBP", 0); + sourceImage.save(&buffer, "WEBP", 50); buffer.close(); QString imgBase64(encodedImgBytes.toBase64()); @@ -1411,6 +1409,4 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { } else { req->SendErrorResponse("Source render failed."); } - - delete imgBuf; } From fe00f3114794509eef32add0dd49eb68ceee6c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Thu, 18 Apr 2019 21:45:30 +0200 Subject: [PATCH 05/21] sources: fix GetSourceImage method --- src/WSRequestHandler.h | 2 +- src/WSRequestHandler_Sources.cpp | 40 +++++++++++++++----------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/WSRequestHandler.h b/src/WSRequestHandler.h index 92fa54b1..0017e813 100644 --- a/src/WSRequestHandler.h +++ b/src/WSRequestHandler.h @@ -116,7 +116,7 @@ class WSRequestHandler : public QObject { static HandlerResponse HandleGetSourceTypesList(WSRequestHandler* req); static HandlerResponse HandleGetSourceSettings(WSRequestHandler* req); static HandlerResponse HandleSetSourceSettings(WSRequestHandler* req); - static void HandleGetSourceImage(WSRequestHandler* req); + static HandlerResponse HandleGetSourceImage(WSRequestHandler* req); static HandlerResponse HandleGetSourceFilters(WSRequestHandler* req); static HandlerResponse HandleAddFilterToSource(WSRequestHandler* req); diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index aac42bb4..976a40c0 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1336,17 +1336,15 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler return req->SendOKResponse(); } -void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { +HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { if (!req->hasField("sourceName")) { - req->SendErrorResponse("missing request parameters"); - return; + return req->SendErrorResponse("missing request parameters"); } const char* sourceName = obs_data_get_string(req->data, "sourceName"); OBSSourceAutoRelease source = obs_get_source_by_name(sourceName); if (!source) { - req->SendErrorResponse("specified source doesn't exist"); - return; + return req->SendErrorResponse("specified source doesn't exist");; } const uint32_t imgWidth = obs_source_get_base_width(source); @@ -1392,21 +1390,21 @@ void WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { obs_leave_graphics(); - if (renderSuccess) { - QByteArray encodedImgBytes; - QBuffer buffer(&encodedImgBytes); - buffer.open(QBuffer::WriteOnly); - sourceImage.save(&buffer, "WEBP", 50); - buffer.close(); - - QString imgBase64(encodedImgBytes.toBase64()); - imgBase64.prepend("data:image/webp;base64,"); - - OBSDataAutoRelease response = obs_data_create(); - obs_data_set_string(response, "sourceName", obs_source_get_name(source)); - obs_data_set_string(response, "img", imgBase64.toUtf8().constData()); - req->SendOKResponse(response); - } else { - req->SendErrorResponse("Source render failed."); + if (!renderSuccess) { + return req->SendErrorResponse("Source render failed."); } + + QByteArray encodedImgBytes; + QBuffer buffer(&encodedImgBytes); + buffer.open(QBuffer::WriteOnly); + sourceImage.save(&buffer, "WEBP", 50); + buffer.close(); + + QString imgBase64(encodedImgBytes.toBase64()); + imgBase64.prepend("data:image/webp;base64,"); + + OBSDataAutoRelease response = obs_data_create(); + obs_data_set_string(response, "sourceName", obs_source_get_name(source)); + obs_data_set_string(response, "img", imgBase64.toUtf8().constData()); + return req->SendOKResponse(response); } From c5cdbc48a9686ef7aaaec271e181a64d32bcf4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Fri, 26 Apr 2019 13:57:48 +0200 Subject: [PATCH 06/21] requests(sources): fix includes --- src/WSRequestHandler_Sources.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 976a40c0..07d78d81 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1,6 +1,7 @@ -#include -#include -#include +#include +#include +#include + #include "Utils.h" #include "WSRequestHandler.h" From 8f88d1b7c44db466be0d3da078b217c9c2ab0953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Fri, 26 Apr 2019 14:05:12 +0200 Subject: [PATCH 07/21] request(GetSourceImage): use PNG --- src/WSRequestHandler_Sources.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 07d78d81..0b334a66 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1398,7 +1398,7 @@ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { QByteArray encodedImgBytes; QBuffer buffer(&encodedImgBytes); buffer.open(QBuffer::WriteOnly); - sourceImage.save(&buffer, "WEBP", 50); + sourceImage.save(&buffer, "PNG", 50); buffer.close(); QString imgBase64(encodedImgBytes.toBase64()); @@ -1406,6 +1406,6 @@ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); - obs_data_set_string(response, "img", imgBase64.toUtf8().constData()); + obs_data_set_string(response, "img", imgBase64.toUtf8()); return req->SendOKResponse(response); } From ab73d61178fa465e6018d00a9ef7e0bb4881bc3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Fri, 26 Apr 2019 14:07:07 +0200 Subject: [PATCH 08/21] request(GetSourceImage): add todo --- src/WSRequestHandler_Sources.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 0b334a66..559360ea 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1356,11 +1356,12 @@ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { uint8_t* videoData = nullptr; uint32_t videoLinesize = 0; + // TODO asynchronous rendering and encoding obs_enter_graphics(); gs_texrender_t* texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); gs_stagesurf_t* stagesurface = gs_stagesurface_create(imgWidth, imgHeight, GS_RGBA); - + bool renderSuccess = false; gs_texrender_reset(texrender); if (gs_texrender_begin(texrender, imgWidth, imgHeight)) { From 8305d907e3b07c154c0f9341b5dcc1b6f885eb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Fri, 26 Apr 2019 14:08:18 +0200 Subject: [PATCH 09/21] request(GetSourceImage): fix mime type --- src/WSRequestHandler_Sources.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 559360ea..8c3593b4 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1403,7 +1403,7 @@ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { buffer.close(); QString imgBase64(encodedImgBytes.toBase64()); - imgBase64.prepend("data:image/webp;base64,"); + imgBase64.prepend("data:image/png;base64,"); OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); From 4f1fa3bc32708fceb57096edfe5873426b7e0d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 26 Apr 2019 20:41:46 +0200 Subject: [PATCH 10/21] requests(GetSourceImage): add picture format parameter --- src/WSRequestHandler_Sources.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 8c3593b4..0a7ce841 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "Utils.h" @@ -1337,8 +1338,22 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler return req->SendOKResponse(); } +/** +* Take a picture snapshot of a source and sends it in the response a Data URI (base64-encoded data) +* +* @param {String} `sourceName` Source name +* @param {String} `pictureFormat` Format of the encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) +* +* @return {String} `sourceName` Source name +* @return {String} `img` Image Data URI +* +* @api requests +* @name GetSourceImage +* @category sources +* @since 4.6.0 +*/ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { - if (!req->hasField("sourceName")) { + if (!req->hasField("sourceName") || !req->hasField("pictureFormat")) { return req->SendErrorResponse("missing request parameters"); } @@ -1348,6 +1363,14 @@ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { return req->SendErrorResponse("specified source doesn't exist");; } + const char* pictureFormat = obs_data_get_string(req->data, "pictureFormat"); + + auto supportedFormats = QImageWriter::supportedImageFormats(); + if (!supportedFormats.contains(pictureFormat)) { + QString errorMessage = QString("Unsupported picture format: %1").arg(pictureFormat); + return req->SendErrorResponse(errorMessage.toUtf8()); + } + const uint32_t imgWidth = obs_source_get_base_width(source); const uint32_t imgHeight = obs_source_get_base_height(source); QImage sourceImage(imgWidth, imgHeight, QImage::Format::Format_RGBA8888); @@ -1399,11 +1422,13 @@ HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { QByteArray encodedImgBytes; QBuffer buffer(&encodedImgBytes); buffer.open(QBuffer::WriteOnly); - sourceImage.save(&buffer, "PNG", 50); + sourceImage.save(&buffer, pictureFormat, 50); buffer.close(); QString imgBase64(encodedImgBytes.toBase64()); - imgBase64.prepend("data:image/png;base64,"); + imgBase64.prepend( + QString("data:image/%1;base64,").arg(pictureFormat) + ); OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); From f955d81c5e3ad83d595dd79ad59a90fd3d5577a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 26 Apr 2019 20:49:09 +0200 Subject: [PATCH 11/21] requests: rename GetSourceImage to TakeSourceScreenshot --- src/WSRequestHandler.cpp | 2 +- src/WSRequestHandler.h | 2 +- src/WSRequestHandler_Sources.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WSRequestHandler.cpp b/src/WSRequestHandler.cpp index c247fbc6..22ca5b85 100644 --- a/src/WSRequestHandler.cpp +++ b/src/WSRequestHandler.cpp @@ -85,7 +85,7 @@ QHash WSRequestHandler::messageM { "GetSourceTypesList", WSRequestHandler::HandleGetSourceTypesList }, { "GetSourceSettings", WSRequestHandler::HandleGetSourceSettings }, { "SetSourceSettings", WSRequestHandler::HandleSetSourceSettings }, - { "GetSourceImage", WSRequestHandler::HandleGetSourceImage }, + { "TakeSourceScreenshot", WSRequestHandler::HandleTakeSourceScreenshot }, { "GetSourceFilters", WSRequestHandler::HandleGetSourceFilters }, { "AddFilterToSource", WSRequestHandler::HandleAddFilterToSource }, diff --git a/src/WSRequestHandler.h b/src/WSRequestHandler.h index 0017e813..b483d796 100644 --- a/src/WSRequestHandler.h +++ b/src/WSRequestHandler.h @@ -116,7 +116,7 @@ class WSRequestHandler : public QObject { static HandlerResponse HandleGetSourceTypesList(WSRequestHandler* req); static HandlerResponse HandleGetSourceSettings(WSRequestHandler* req); static HandlerResponse HandleSetSourceSettings(WSRequestHandler* req); - static HandlerResponse HandleGetSourceImage(WSRequestHandler* req); + static HandlerResponse HandleTakeSourceScreenshot(WSRequestHandler* req); static HandlerResponse HandleGetSourceFilters(WSRequestHandler* req); static HandlerResponse HandleAddFilterToSource(WSRequestHandler* req); diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 0a7ce841..c13b5add 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1348,11 +1348,11 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * @return {String} `img` Image Data URI * * @api requests -* @name GetSourceImage +* @name TakeSourceScreenshot * @category sources * @since 4.6.0 */ -HandlerResponse WSRequestHandler::HandleGetSourceImage(WSRequestHandler* req) { +HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* req) { if (!req->hasField("sourceName") || !req->hasField("pictureFormat")) { return req->SendErrorResponse("missing request parameters"); } From 2e3a24d32ef208941d0251bb5b58427ee84a1c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 26 Apr 2019 21:14:48 +0200 Subject: [PATCH 12/21] TakeSourceScreenshot: add width and height optional parameters --- src/WSRequestHandler_Sources.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index c13b5add..dca4b583 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1343,6 +1343,8 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * * @param {String} `sourceName` Source name * @param {String} `pictureFormat` Format of the encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) +* @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. +* @param {int (optional)} `height` Screenshot height. Defaults to the source's base heigh. * * @return {String} `sourceName` Source name * @return {String} `img` Image Data URI @@ -1371,8 +1373,29 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r return req->SendErrorResponse(errorMessage.toUtf8()); } - const uint32_t imgWidth = obs_source_get_base_width(source); - const uint32_t imgHeight = obs_source_get_base_height(source); + const uint32_t sourceWidth = obs_source_get_base_width(source); + const uint32_t sourceHeight = obs_source_get_base_height(source); + const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight); + + uint32_t imgWidth = sourceWidth; + uint32_t imgHeight = sourceHeight; + + if (req->hasField("width")) { + imgWidth = obs_data_get_int(req->data, "width"); + + if (!req->hasField("height")) { + imgHeight = ((double)imgWidth / sourceAspectRatio); + } + } + + if (req->hasField("height")) { + imgHeight = obs_data_get_int(req->data, "height"); + + if (!req->hasField("width")) { + imgWidth = ((double)imgHeight * sourceAspectRatio); + } + } + QImage sourceImage(imgWidth, imgHeight, QImage::Format::Format_RGBA8888); sourceImage.fill(0); @@ -1392,7 +1415,7 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r vec4_zero(&background); gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0); - gs_ortho(0.0f, (float)imgWidth, 0.0f, (float)imgHeight, -100.0f, 100.0f); + gs_ortho(0.0f, (float)sourceWidth, 0.0f, (float)sourceHeight, -100.0f, 100.0f); gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); From f5ae89500f05fdacc2dadb60025a900b3845f47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 26 Apr 2019 21:18:20 +0200 Subject: [PATCH 13/21] TakeSourceScreenshot: fix docs --- src/WSRequestHandler_Sources.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index dca4b583..b71ec742 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1339,12 +1339,14 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler } /** -* Take a picture snapshot of a source and sends it in the response a Data URI (base64-encoded data) +* Takes a picture snapshot of a source and sends it in the response a Data URI (base64-encoded data) +* Clients can specify `width` and `height` parameters to receive scaled pictures. Aspect ratio is +* preserved if only one of these two parameters is specified. * * @param {String} `sourceName` Source name * @param {String} `pictureFormat` Format of the encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) -* @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. -* @param {int (optional)} `height` Screenshot height. Defaults to the source's base heigh. +* @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. +* @param {int (optional)} `height` Screenshot height. Defaults to the source's base height. * * @return {String} `sourceName` Source name * @return {String} `img` Image Data URI From f10c0d2558c0551271531a36e86f23f5b5bc66a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 3 May 2019 00:02:53 +0200 Subject: [PATCH 14/21] TakeSourceScreenshot: use default quality --- src/WSRequestHandler_Sources.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index b71ec742..c5ce2753 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1345,7 +1345,7 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * * @param {String} `sourceName` Source name * @param {String} `pictureFormat` Format of the encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) -* @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. +* @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. * @param {int (optional)} `height` Screenshot height. Defaults to the source's base height. * * @return {String} `sourceName` Source name @@ -1404,7 +1404,6 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r uint8_t* videoData = nullptr; uint32_t videoLinesize = 0; - // TODO asynchronous rendering and encoding obs_enter_graphics(); gs_texrender_t* texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); @@ -1447,7 +1446,7 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r QByteArray encodedImgBytes; QBuffer buffer(&encodedImgBytes); buffer.open(QBuffer::WriteOnly); - sourceImage.save(&buffer, pictureFormat, 50); + sourceImage.save(&buffer, pictureFormat); buffer.close(); QString imgBase64(encodedImgBytes.toBase64()); From 059244bb325bda61930b6f5e281b6741c6b3f11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 3 May 2019 00:49:55 +0200 Subject: [PATCH 15/21] TakeSourceScreenshot: fix heap corruption on windows --- src/WSRequestHandler_Sources.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index c5ce2753..0726a87d 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1369,7 +1369,7 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r const char* pictureFormat = obs_data_get_string(req->data, "pictureFormat"); - auto supportedFormats = QImageWriter::supportedImageFormats(); + QByteArrayList supportedFormats = QImageWriter::supportedImageFormats(); if (!supportedFormats.contains(pictureFormat)) { QString errorMessage = QString("Unsupported picture format: %1").arg(pictureFormat); return req->SendErrorResponse(errorMessage.toUtf8()); @@ -1412,7 +1412,7 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r bool renderSuccess = false; gs_texrender_reset(texrender); if (gs_texrender_begin(texrender, imgWidth, imgHeight)) { - struct vec4 background; + vec4 background; vec4_zero(&background); gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0); @@ -1428,7 +1428,10 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r gs_stage_texture(stagesurface, gs_texrender_get_texture(texrender)); if (gs_stagesurface_map(stagesurface, &videoData, &videoLinesize)) { - memcpy(sourceImage.bits(), videoData, videoLinesize * imgHeight); + int linesize = sourceImage.bytesPerLine(); + for (int y = 0; y < imgHeight; y++) { + memcpy(sourceImage.scanLine(y), videoData + (y * linesize), linesize); + } gs_stagesurface_unmap(stagesurface); renderSuccess = true; } From c92477b45765e1d24794d84825b09305326300cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 3 May 2019 01:11:36 +0200 Subject: [PATCH 16/21] TakeSourceScreenshot: fix tearing issue when scaling --- src/WSRequestHandler_Sources.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 0726a87d..9a05faa3 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1430,7 +1430,7 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r if (gs_stagesurface_map(stagesurface, &videoData, &videoLinesize)) { int linesize = sourceImage.bytesPerLine(); for (int y = 0; y < imgHeight; y++) { - memcpy(sourceImage.scanLine(y), videoData + (y * linesize), linesize); + memcpy(sourceImage.scanLine(y), videoData + (y * videoLinesize), linesize); } gs_stagesurface_unmap(stagesurface); renderSuccess = true; From d46c1f86873a81355e2ffaef0da3dc0a9bdfb3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 3 May 2019 01:14:58 +0200 Subject: [PATCH 17/21] TakeSourceScreenshot: fix off-screen sources rendering --- src/WSRequestHandler_Sources.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 9a05faa3..1382f30a 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1421,7 +1421,9 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r gs_blend_state_push(); gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); + obs_source_inc_showing(source); obs_source_video_render(source); + obs_source_dec_showing(source); gs_blend_state_pop(); gs_texrender_end(texrender); From 53b9a46feb8d643befc91957f44000122edd4e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Fri, 3 May 2019 19:14:17 +0200 Subject: [PATCH 18/21] TakeSourceScreenshot: direct file save --- src/WSRequestHandler_Sources.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 1382f30a..a92b15ff 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1345,6 +1345,7 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * * @param {String} `sourceName` Source name * @param {String} `pictureFormat` Format of the encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) +* @param {String (optional)} `saveToFilePath` Full file path (file extension included) where the captured image is to be saved. Can be in a format different from `pictureFormat`. * @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. * @param {int (optional)} `height` Screenshot height. Defaults to the source's base height. * @@ -1454,6 +1455,11 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r sourceImage.save(&buffer, pictureFormat); buffer.close(); + if (req->hasField("saveToFilePath")) { + QString imageFilePath = obs_data_get_string(req->data, "saveToFilePath"); + sourceImage.save(imageFilePath); + } + QString imgBase64(encodedImgBytes.toBase64()); imgBase64.prepend( QString("data:image/%1;base64,").arg(pictureFormat) From 7177913d9b32116adbdc543f12933896a3de8498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Fri, 3 May 2019 22:01:40 +0200 Subject: [PATCH 19/21] TakeSourceScreenshot: ability to choose between save to file and/or data uri --- src/WSRequestHandler_Sources.cpp | 72 ++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index a92b15ff..3ae88c25 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1339,18 +1339,25 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler } /** -* Takes a picture snapshot of a source and sends it in the response a Data URI (base64-encoded data) +* Takes a picture snapshot of a source and then can either or both: +* - Send it over as a Data URI (base64-encoded data) in the response (by specifying `embedPictureFormat` in the request) +* - Save it to disk (by specifying `saveToFilePath` in the request) +* +* At least `embedPictureFormat` or `saveToFilePath` must be specified. +* * Clients can specify `width` and `height` parameters to receive scaled pictures. Aspect ratio is * preserved if only one of these two parameters is specified. * +* * @param {String} `sourceName` Source name -* @param {String} `pictureFormat` Format of the encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) +* @param {String (optional)} `embedPictureFormat` Format of the Data URI encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) * @param {String (optional)} `saveToFilePath` Full file path (file extension included) where the captured image is to be saved. Can be in a format different from `pictureFormat`. * @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. * @param {int (optional)} `height` Screenshot height. Defaults to the source's base height. * * @return {String} `sourceName` Source name -* @return {String} `img` Image Data URI +* @return {String} `img` Image Data URI (if `embedPictureFormat` was specified in the request) +* @return {String} `imageFile` Image file path (if `saveToFilePath` was specified in the request) * * @api requests * @name TakeSourceScreenshot @@ -1358,24 +1365,20 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * @since 4.6.0 */ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* req) { - if (!req->hasField("sourceName") || !req->hasField("pictureFormat")) { + if (!req->hasField("sourceName")) { return req->SendErrorResponse("missing request parameters"); } + if (!req->hasField("embedPictureFormat") && !req->hasField("saveToFilePath")) { + return req->SendErrorResponse("At least 'embedPictureFormat' or 'saveToFilePath' must be specified"); + } + const char* sourceName = obs_data_get_string(req->data, "sourceName"); OBSSourceAutoRelease source = obs_get_source_by_name(sourceName); if (!source) { return req->SendErrorResponse("specified source doesn't exist");; } - const char* pictureFormat = obs_data_get_string(req->data, "pictureFormat"); - - QByteArrayList supportedFormats = QImageWriter::supportedImageFormats(); - if (!supportedFormats.contains(pictureFormat)) { - QString errorMessage = QString("Unsupported picture format: %1").arg(pictureFormat); - return req->SendErrorResponse(errorMessage.toUtf8()); - } - const uint32_t sourceWidth = obs_source_get_base_width(source); const uint32_t sourceHeight = obs_source_get_base_height(source); const double sourceAspectRatio = ((double)sourceWidth / (double)sourceHeight); @@ -1446,27 +1449,44 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r obs_leave_graphics(); if (!renderSuccess) { - return req->SendErrorResponse("Source render failed."); + return req->SendErrorResponse("Source render failed"); } - QByteArray encodedImgBytes; - QBuffer buffer(&encodedImgBytes); - buffer.open(QBuffer::WriteOnly); - sourceImage.save(&buffer, pictureFormat); - buffer.close(); + OBSDataAutoRelease response = obs_data_create(); + + if (req->hasField("embedPictureFormat")) { + const char* pictureFormat = obs_data_get_string(req->data, "embedPictureFormat"); + + QByteArrayList supportedFormats = QImageWriter::supportedImageFormats(); + if (!supportedFormats.contains(pictureFormat)) { + QString errorMessage = QString("Unsupported picture format: %1").arg(pictureFormat); + return req->SendErrorResponse(errorMessage.toUtf8()); + } + + QByteArray encodedImgBytes; + QBuffer buffer(&encodedImgBytes); + buffer.open(QBuffer::WriteOnly); + if (!sourceImage.save(&buffer, pictureFormat)) { + return req->SendErrorResponse("Embed image encoding failed"); + } + buffer.close(); + + QString imgBase64(encodedImgBytes.toBase64()); + imgBase64.prepend( + QString("data:image/%1;base64,").arg(pictureFormat) + ); + + obs_data_set_string(response, "img", imgBase64.toUtf8()); + } if (req->hasField("saveToFilePath")) { QString imageFilePath = obs_data_get_string(req->data, "saveToFilePath"); - sourceImage.save(imageFilePath); + if (!sourceImage.save(imageFilePath)) { + return req->SendErrorResponse("Image save failed"); + } + obs_data_set_string(response, "imageFile", imageFilePath.toUtf8()); } - QString imgBase64(encodedImgBytes.toBase64()); - imgBase64.prepend( - QString("data:image/%1;base64,").arg(pictureFormat) - ); - - OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "sourceName", obs_source_get_name(source)); - obs_data_set_string(response, "img", imgBase64.toUtf8()); return req->SendOKResponse(response); } From 5745da54663f313f5d72fab6108f8558a43b6e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Sat, 4 May 2019 11:50:29 +0200 Subject: [PATCH 20/21] TakeSourceScreenshot: always provide an absolute path in `imageFile` response --- src/WSRequestHandler_Sources.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 3ae88c25..3e7ffc1f 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -1351,13 +1352,13 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * * @param {String} `sourceName` Source name * @param {String (optional)} `embedPictureFormat` Format of the Data URI encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) -* @param {String (optional)} `saveToFilePath` Full file path (file extension included) where the captured image is to be saved. Can be in a format different from `pictureFormat`. +* @param {String (optional)} `saveToFilePath` Full file path (file extension included) where the captured image is to be saved. Can be in a format different from `pictureFormat`. Can be a relative path. * @param {int (optional)} `width` Screenshot width. Defaults to the source's base width. * @param {int (optional)} `height` Screenshot height. Defaults to the source's base height. * * @return {String} `sourceName` Source name * @return {String} `img` Image Data URI (if `embedPictureFormat` was specified in the request) -* @return {String} `imageFile` Image file path (if `saveToFilePath` was specified in the request) +* @return {String} `imageFile` Absolute path to the saved image file (if `saveToFilePath` was specified in the request) * * @api requests * @name TakeSourceScreenshot @@ -1480,11 +1481,14 @@ HandlerResponse WSRequestHandler::HandleTakeSourceScreenshot(WSRequestHandler* r } if (req->hasField("saveToFilePath")) { - QString imageFilePath = obs_data_get_string(req->data, "saveToFilePath"); - if (!sourceImage.save(imageFilePath)) { + QString filePathStr = obs_data_get_string(req->data, "saveToFilePath"); + QFileInfo filePathInfo(filePathStr); + QString absoluteFilePath = filePathInfo.absoluteFilePath(); + + if (!sourceImage.save(absoluteFilePath)) { return req->SendErrorResponse("Image save failed"); } - obs_data_set_string(response, "imageFile", imageFilePath.toUtf8()); + obs_data_set_string(response, "imageFile", absoluteFilePath.toUtf8()); } obs_data_set_string(response, "sourceName", obs_source_get_name(source)); From c95b709f39463f4a129ffe9ece1f697c4e60bd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Sat, 4 May 2019 12:19:15 +0200 Subject: [PATCH 21/21] TakeSourceScreenshot: fix docs --- src/WSRequestHandler_Sources.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 3e7ffc1f..fbe056ca 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -1349,7 +1349,6 @@ HandlerResponse WSRequestHandler::HandleSetSourceFilterSettings(WSRequestHandler * Clients can specify `width` and `height` parameters to receive scaled pictures. Aspect ratio is * preserved if only one of these two parameters is specified. * -* * @param {String} `sourceName` Source name * @param {String (optional)} `embedPictureFormat` Format of the Data URI encoded picture. Can be "png", "jpg", "jpeg" or "bmp" (or any other value supported by Qt's Image module) * @param {String (optional)} `saveToFilePath` Full file path (file extension included) where the captured image is to be saved. Can be in a format different from `pictureFormat`. Can be a relative path.