obs-studio/UI/window-basic-main-outputs.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

109 lines
3.1 KiB
C++
Raw Permalink Normal View History

#pragma once
2024-04-18 13:41:36 +00:00
#include <memory>
#include <string>
2024-04-18 13:41:36 +00:00
#include <QFuture>
#include "qt-helpers.hpp"
#include "multitrack-video-output.hpp"
class OBSBasic;
struct BasicOutputHandler {
2021-11-26 09:25:39 +00:00
OBSOutputAutoRelease fileOutput;
OBSOutputAutoRelease streamOutput;
OBSOutputAutoRelease replayBuffer;
OBSOutputAutoRelease virtualCam;
bool streamingActive = false;
bool recordingActive = false;
bool delayActive = false;
bool replayBufferActive = false;
bool virtualCamActive = false;
OBSBasic *main;
2024-04-18 13:41:36 +00:00
std::unique_ptr<MultitrackVideoOutput> multitrackVideo;
bool multitrackVideoActive = false;
OBSOutputAutoRelease StreamingOutput() const
{
return (multitrackVideo && multitrackVideoActive)
? multitrackVideo->StreamingOutput()
: OBSOutputAutoRelease{
obs_output_get_ref(streamOutput)};
}
obs_view_t *virtualCamView = nullptr;
video_t *virtualCamVideo = nullptr;
obs_scene_t *vCamSourceScene = nullptr;
obs_sceneitem_t *vCamSourceSceneItem = nullptr;
std::string outputType;
std::string lastError;
std::string lastRecordingPath;
OBSSignal startRecording;
OBSSignal stopRecording;
OBSSignal startReplayBuffer;
OBSSignal stopReplayBuffer;
OBSSignal startStreaming;
OBSSignal stopStreaming;
OBSSignal startVirtualCam;
OBSSignal stopVirtualCam;
UI: Wait for full vcam deactivation to destroy its view A bug which was technically introduced in df446c3f6e: the author assigned video mixes to the virtual camera and did not realize you have to wait for full capture stop with the "deactivate" signal rather than the "stop" signal. This situation is understandable because these signals are likely confusing and need more documentation. The way an output works when it stops is it has three stages: - "stopping", which is the moment the user themselves stop the output - "stop", when the output's implementation has stopped and returns success or an error code - "deactivate", when the output inself (not the implementation) has fully stopped capturing encoded or raw frame data after the implementation has stopped. This is done in a separate thread, end_data_capture_thread(), for performance and data race reasons, and is when it's "actually fully stopped for real this time" (Lain note: I sincerely apologize for this confusing signal design) The author of df446c3f6e was likely confused as to why they could not destroy the video mix in the "stop" signal without triggering a race condition in end_data_capture_thread(), and instead decided to make a workaround to clear the video mix set to the output before destroying the video mix. Unsetting the video mix I'm guessing *seemed* to fix the problem for them at the time, and destroying the video mix separately after that automatically stops capture, so it *technically* worked because the deactivate thread cannot be called until the implementation's stop signal has executed. However, it was still the incorrect way to handle the problem, because it circumvents the output's mechanism for deactivating the frame data capture by destroying the view instead. The reason this was the incorrect way to handle the problem became exposed in 7cd7ca80f8, when tytan made it so it uses the main video mix under certain circumstances. The main view is special and cannot be destroyed, so the mechanism to stop frame data capture that the virtualcam was using before failed, and raw frame data capture continued perpetually until the end of the program erroneously. This fix solves the bug by using the "deactivate" signal rather than the "stop" signal, thus allowing the output to fully end its data capture and *then* destroy the video mix. Fixes obsproject/obs-studio#9153
2023-07-06 21:56:48 +00:00
OBSSignal deactivateVirtualCam;
OBSSignal streamDelayStarting;
OBSSignal streamStopping;
OBSSignal recordStopping;
OBSSignal recordFileChanged;
OBSSignal replayBufferStopping;
OBSSignal replayBufferSaved;
inline BasicOutputHandler(OBSBasic *main_);
virtual ~BasicOutputHandler(){};
2024-04-18 13:41:36 +00:00
virtual FutureHolder<bool> SetupStreaming(obs_service_t *service) = 0;
virtual bool StartStreaming(obs_service_t *service) = 0;
virtual bool StartRecording() = 0;
virtual bool StartReplayBuffer() { return false; }
virtual bool StartVirtualCam();
virtual void StopStreaming(bool force = false) = 0;
virtual void StopRecording(bool force = false) = 0;
virtual void StopReplayBuffer(bool force = false) { (void)force; }
virtual void StopVirtualCam();
virtual bool StreamingActive() const = 0;
virtual bool RecordingActive() const = 0;
virtual bool ReplayBufferActive() const { return false; }
virtual bool VirtualCamActive() const;
virtual void Update() = 0;
virtual void SetupOutputs() = 0;
virtual void UpdateVirtualCamOutputSource();
virtual void DestroyVirtualCamView();
virtual void DestroyVirtualCameraScene();
inline bool Active() const
{
return streamingActive || recordingActive || delayActive ||
2024-04-18 13:41:36 +00:00
replayBufferActive || virtualCamActive ||
multitrackVideoActive;
}
protected:
2023-04-03 13:48:55 +00:00
void SetupAutoRemux(const char *&container);
std::string GetRecordingFilename(const char *path,
const char *container, bool noSpace,
bool overwrite, const char *format,
bool ffmpeg);
2024-04-18 13:41:36 +00:00
FutureHolder<std::optional<bool>> SetupMultitrackVideo(
obs_service_t *service, std::string audio_encoder_id,
size_t main_audio_mixer, std::optional<size_t> vod_track_mixer);
2024-04-18 13:41:36 +00:00
OBSDataAutoRelease GenerateMultitrackVideoStreamDumpConfig();
};
BasicOutputHandler *CreateSimpleOutputHandler(OBSBasic *main);
BasicOutputHandler *CreateAdvancedOutputHandler(OBSBasic *main);