Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requests: GetStreamScreenshot #1189

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ghostzero
Copy link

@ghostzero ghostzero commented Dec 11, 2023

Description

Adds a new request called GetStreamScreenshot which returns a Base64-encoded screenshot of the stream (program).

Motivation and Context

I require this feature for a remote production where I cannot use remote desktop software to see the actual program in real time. Currently there is no way to take a screenshot of the program, which is "immutable" until the transition button is pressed. This feature allows you to take a screenshot of the main texture frame (which also contains stinger transitions). This PR also closes #1130.

WindowsTerminal_I5HJ3QmOBm.mp4

How Has This Been Tested?

Tested OS(s): Windows 11 22H2 22621.2715

I checked out the obs-studio repository, followed the build instructions, made changes to the plugins\obs-websocket folder, and built obs-studio to test my changes. Since this is mostly copy/paste from the source screenshot request with tweaks to capture the main texture, I expect no problems.

Types of changes

  • New request/event (non-breaking)

Checklist:

  • I have read the Contributing Guidelines.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • My code is not on master or a release/* branch.
  • The code has been tested.
  • I have included updates to all appropriate documentation.
Adds a new request called `GetStreamScreenshot` which returns a
Base64-encoded screenshot of the stream (program).
@ghostzero
Copy link
Author

Is there anything blocking this?

@@ -166,6 +166,7 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
{"StartStream", &RequestHandler::StartStream},
{"StopStream", &RequestHandler::StopStream},
{"SendStreamCaption", &RequestHandler::SendStreamCaption},
{"GetStreamScreenshot", &RequestHandler::GetStreamScreenshot},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel GetProgramScreenshot would be a better name because Stream is used for the output layer APIs. And, the implementation should be in RequestHandler_Outputs.cpp instead of RequestHandler_Stream.cpp. I want tt2468 to comment about the name as he has overhauled a lot of API names in version 5.0.

Comment on lines +71 to +85
gs_texrender_reset(texRender);
if (gs_texrender_begin(texRender, imgWidth, imgHeight)) {
vec4 background;
vec4_zero(&background);

gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0);
gs_ortho(0.0f, (float)streamWidth, 0.0f, (float)streamHeight, -100.0f, 100.0f);

gs_blend_state_push();
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);

obs_render_main_texture();

gs_blend_state_pop();
gs_texrender_end(texRender);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function obs_get_main_texture() returns the main texture. This texture should be sufficient for this purpose.
If the requested geometry is same as the base size, just pass the texture to gs_stage_texture. If not, still need to use gs_texture_render to rescale.

obs_leave_graphics();

return ret;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The majority of this function TakeStreamScreenshot looks same as TakeSourceScreenshot.
Can we share the code? For example, creating QImage and copying the pixel data to QImage can be a common function.

*
* @responseField imageData | String | Base64-encoded screenshot
*
* @requestType GetOutputScreenshot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is GetOutputScreenshot a typo? (This name sounds also good though.)

Comment on lines +87 to +88
gs_stage_texture(stageSurface, gs_texrender_get_texture(texRender));
if (gs_stagesurface_map(stageSurface, &videoData, &videoLinesize)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for your information and for a future improvement,
gs_stagesurface_map followed by gs_stage_texture is sometimes slow.
It might be better to release the graphics context, wait, and take the context again.

Comment on lines +89 to +92
int lineSize = ret.bytesPerLine();
for (uint y = 0; y < imgHeight; y++) {
memcpy(ret.scanLine(y), videoData + (y * videoLinesize), lineSize);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for your information,
between gs_stagesurface_map and gs_stagesurface_unmap, we may release the graphics context so that the graphics thread won't be blocked while copying the pixel data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants