mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-24 14:55:37 +00:00
fix(windows): finalize WGC recordings safely
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
"helpers": {
|
||||
"wgc-capture": {
|
||||
"binaryName": "wgc-capture.exe",
|
||||
"binarySha256": "72d8f0703a5360a0e911a95bf8839354c877df5fa51294af75ded83a17c0c32e",
|
||||
"binarySha256": "5f364b07b016c597288f90a9b61c581e6559d6d32b79ffadceb37859bbea8dd2",
|
||||
"sourceDir": "electron/native/wgc-capture",
|
||||
"sourceFingerprint": "f30dee6b4956a5b57f4fc4d8d586f3470c793c8f7e3242f4160394debbb3f3be",
|
||||
"updatedAt": "2026-03-28T05:17:10.449Z"
|
||||
"sourceFingerprint": "9e9bce082266ca5968cf5f0b535b469d47c4ec3a775a93726171c0dfdbcdaa44",
|
||||
"updatedAt": "2026-03-28T05:48:46.587Z"
|
||||
},
|
||||
"cursor-monitor": {
|
||||
"binaryName": "cursor-monitor.exe",
|
||||
|
||||
Binary file not shown.
@@ -13,6 +13,7 @@
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
|
||||
static std::atomic<bool> g_stopRequested{false};
|
||||
static std::atomic<bool> g_pauseRequested{false};
|
||||
@@ -249,6 +250,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Set up frame callback
|
||||
std::atomic<int64_t> frameCount{0};
|
||||
std::atomic<bool> recordingStartedAnnounced{false};
|
||||
session.setFrameCallback([&](ID3D11Texture2D* texture, int64_t timestampHns) {
|
||||
g_lastFrameTimestampHns = timestampHns;
|
||||
if (g_stopRequested) return;
|
||||
@@ -269,7 +271,11 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
if (encoder.writeFrame(texture, adjustedTimestampHns)) {
|
||||
frameCount++;
|
||||
const int64_t writtenFrames = frameCount.fetch_add(1) + 1;
|
||||
if (writtenFrames == 1 && !recordingStartedAnnounced.exchange(true)) {
|
||||
std::cout << "Recording started" << std::endl;
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -312,9 +318,6 @@ int main(int argc, char* argv[]) {
|
||||
micActive = micCapture.start();
|
||||
}
|
||||
|
||||
std::cout << "Recording started" << std::endl;
|
||||
std::cout.flush();
|
||||
|
||||
// Wait for stop signal while pausing/resuming audio tracks in lockstep.
|
||||
while (!g_stopRequested) {
|
||||
if (g_pauseRequested) {
|
||||
@@ -333,7 +336,17 @@ int main(int argc, char* argv[]) {
|
||||
session.stopCapture();
|
||||
if (audioActive) loopback.stop();
|
||||
if (micActive) micCapture.stop();
|
||||
encoder.finalize();
|
||||
|
||||
if (frameCount.load() <= 0) {
|
||||
std::cerr << "ERROR: No video frames were captured before stop" << std::endl;
|
||||
DeleteFileW(outputPathW.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!encoder.finalize()) {
|
||||
std::cerr << "ERROR: Failed to finalize Media Foundation encoder" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Recording stopped. Output path: " << config.outputPath << std::endl;
|
||||
if (audioActive) {
|
||||
|
||||
@@ -22,6 +22,8 @@ MFEncoder::~MFEncoder() {
|
||||
|
||||
bool MFEncoder::initialize(const std::wstring& outputPath, int width, int height, int fps,
|
||||
ID3D11Device* device, ID3D11DeviceContext* context) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (initialized_) return false;
|
||||
|
||||
if (width % 2 != 0 || height % 2 != 0) {
|
||||
@@ -124,6 +126,8 @@ bool MFEncoder::initialize(const std::wstring& outputPath, int width, int height
|
||||
}
|
||||
|
||||
bool MFEncoder::writeFrame(ID3D11Texture2D* texture, int64_t timestampHns) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (!initialized_ || !sinkWriter_) return false;
|
||||
|
||||
context_->CopyResource(stagingTexture_.Get(), texture);
|
||||
@@ -186,20 +190,28 @@ bool MFEncoder::writeFrame(ID3D11Texture2D* texture, int64_t timestampHns) {
|
||||
sample->SetSampleDuration(10000000LL / fps_);
|
||||
|
||||
hr = sinkWriter_->WriteSample(streamIndex_, sample.Get());
|
||||
if (FAILED(hr)) {
|
||||
std::cerr << "ERROR: WriteSample failed: 0x" << std::hex << hr << std::endl;
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool MFEncoder::finalize() {
|
||||
if (!initialized_) return false;
|
||||
initialized_ = false;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (!initialized_) return false;
|
||||
if (!sinkWriter_) return false;
|
||||
|
||||
HRESULT hr = sinkWriter_->Finalize();
|
||||
if (FAILED(hr)) {
|
||||
std::cerr << "ERROR: SinkWriter Finalize failed: 0x" << std::hex << hr << std::endl;
|
||||
}
|
||||
|
||||
initialized_ = false;
|
||||
sinkWriter_.Reset();
|
||||
stagingTexture_.Reset();
|
||||
nv12Buffer_.clear();
|
||||
nv12Buffer_.shrink_to_fit();
|
||||
|
||||
if (!sinkWriter_) return false;
|
||||
HRESULT hr = sinkWriter_->Finalize();
|
||||
sinkWriter_.Reset();
|
||||
MFShutdown();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user