Skip to content

Commit 828976d

Browse files
committed
Add option to create rolling video recordings
1 parent 72fb6e4 commit 828976d

File tree

6 files changed

+44
-10
lines changed

6 files changed

+44
-10
lines changed

alvr/server/cpp/alvr_server/NalParsing.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void sendHeaders(int codec, unsigned char *&buf, int &len, int nalNum) {
5959
return;
6060
}
6161

62-
InitializeDecoder((const unsigned char *)buf, headersLen, codec);
62+
SetVideoConfigNals((const unsigned char *)buf, headersLen, codec);
6363

6464
// move the cursor forward excluding config NALs
6565
buf = cursor;

alvr/server/cpp/alvr_server/alvr_server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ void (*LogInfo)(const char *stringPtr);
183183
void (*LogDebug)(const char *stringPtr);
184184
void (*LogPeriodically)(const char *tag, const char *stringPtr);
185185
void (*DriverReadyIdle)(bool setDefaultChaprone);
186-
void (*InitializeDecoder)(const unsigned char *configBuffer, int len, int codec);
186+
void (*SetVideoConfigNals)(const unsigned char *configBuffer, int len, int codec);
187187
void (*VideoSend)(unsigned long long targetTimestampNs, unsigned char *buf, int len, bool isIdr);
188188
void (*HapticsSend)(unsigned long long path, float duration_s, float frequency, float amplitude);
189189
void (*ShutdownRuntime)();

alvr/server/cpp/alvr_server/bindings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extern "C" void (*LogInfo)(const char *stringPtr);
106106
extern "C" void (*LogDebug)(const char *stringPtr);
107107
extern "C" void (*LogPeriodically)(const char *tag, const char *stringPtr);
108108
extern "C" void (*DriverReadyIdle)(bool setDefaultChaprone);
109-
extern "C" void (*InitializeDecoder)(const unsigned char *configBuffer, int len, int codec);
109+
extern "C" void (*SetVideoConfigNals)(const unsigned char *configBuffer, int len, int codec);
110110
extern "C" void (*VideoSend)(unsigned long long targetTimestampNs,
111111
unsigned char *buf,
112112
int len,

alvr/server/src/connection.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::{
22
bitrate::BitrateManager,
33
buttons::BUTTON_PATH_FROM_ID,
4+
create_recording_file,
45
face_tracking::FaceTrackingSink,
56
haptics,
67
sockets::WelcomeSocket,
@@ -42,7 +43,7 @@ use std::{
4243
Arc,
4344
},
4445
thread,
45-
time::Duration,
46+
time::{Duration, Instant},
4647
};
4748

4849
const RETRY_CONNECT_MIN_INTERVAL: Duration = Duration::from_secs(1);
@@ -1036,7 +1037,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
10361037
}
10371038
}
10381039

1039-
if settings.capture.save_video_stream {
1040+
if settings.capture.startup_video_recording {
10401041
crate::create_recording_file();
10411042
}
10421043

@@ -1101,6 +1102,7 @@ fn try_connect(mut client_ips: HashMap<IpAddr, String>) -> ConResult {
11011102
pub extern "C" fn send_video(timestamp_ns: u64, buffer_ptr: *mut u8, len: i32, is_idr: bool) {
11021103
// start in the corrupts state, the client didn't receive the initial IDR yet.
11031104
static STREAM_CORRUPTED: AtomicBool = AtomicBool::new(true);
1105+
static LAST_IDR_INSTANT: Lazy<Mutex<Instant>> = Lazy::new(|| Mutex::new(Instant::now()));
11041106

11051107
if let Some(sender) = &*VIDEO_CHANNEL_SENDER.lock() {
11061108
let buffer_size = len as usize;
@@ -1109,6 +1111,22 @@ pub extern "C" fn send_video(timestamp_ns: u64, buffer_ptr: *mut u8, len: i32, i
11091111
STREAM_CORRUPTED.store(false, Ordering::SeqCst);
11101112
}
11111113

1114+
if let Switch::Enabled(config) = &SERVER_DATA_MANAGER
1115+
.read()
1116+
.settings()
1117+
.capture
1118+
.rolling_video_files
1119+
{
1120+
if Instant::now() > *LAST_IDR_INSTANT.lock() + Duration::from_secs(config.duration_s) {
1121+
unsafe { crate::RequestIDR() };
1122+
1123+
if is_idr {
1124+
create_recording_file();
1125+
*LAST_IDR_INSTANT.lock() = Instant::now();
1126+
}
1127+
}
1128+
}
1129+
11121130
let timestamp = Duration::from_nanos(timestamp_ns);
11131131

11141132
let mut payload = vec![0; buffer_size];

alvr/server/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ pub fn create_recording_file() {
117117
"h265"
118118
};
119119

120-
let path = FILESYSTEM_LAYOUT.log_dir.join(format!("recording.{ext}"));
120+
let path = FILESYSTEM_LAYOUT
121+
.log_dir
122+
.join(format!("recording.{}.{ext}", chrono::Local::now().format("%F.%H-%M-%S")));
121123

122124
match File::create(path) {
123125
Ok(mut file) => {
@@ -326,7 +328,7 @@ pub unsafe extern "C" fn HmdDriverFactory(
326328
}
327329
}
328330

329-
extern "C" fn initialize_decoder(buffer_ptr: *const u8, len: i32, codec: i32) {
331+
extern "C" fn set_video_config_nals(buffer_ptr: *const u8, len: i32, codec: i32) {
330332
let codec = if codec == 0 {
331333
CodecType::H264
332334
} else {
@@ -435,7 +437,7 @@ pub unsafe extern "C" fn HmdDriverFactory(
435437
LogDebug = Some(log_debug);
436438
LogPeriodically = Some(log_periodically);
437439
DriverReadyIdle = Some(driver_ready_idle);
438-
InitializeDecoder = Some(initialize_decoder);
440+
SetVideoConfigNals = Some(set_video_config_nals);
439441
VideoSend = Some(connection::send_video);
440442
HapticsSend = Some(connection::send_haptics);
441443
ShutdownRuntime = Some(shutdown_driver);

alvr/session/src/settings.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,9 +869,19 @@ No action: All driver registration actions should be performed manually, ALVR in
869869
pub open_close_steamvr_with_dashboard: bool,
870870
}
871871

872+
#[derive(SettingsSchema, Serialize, Deserialize, Clone)]
873+
pub struct RollingVideoFilesConfig {
874+
#[schema(strings(display_name = "Duration"))]
875+
#[schema(suffix = "s")]
876+
pub duration_s: u64,
877+
}
878+
872879
#[derive(SettingsSchema, Serialize, Deserialize, Clone)]
873880
pub struct CaptureConfig {
874-
pub save_video_stream: bool,
881+
#[schema(strings(display_name = "Start video recording at client connection"))]
882+
pub startup_video_recording: bool,
883+
884+
pub rolling_video_files: Switch<RollingVideoFilesConfig>,
875885

876886
#[schema(flag = "steamvr-restart")]
877887
pub capture_frame_dir: String,
@@ -1266,7 +1276,11 @@ pub fn session_settings_default() -> SettingsDefault {
12661276
open_close_steamvr_with_dashboard: false,
12671277
},
12681278
capture: CaptureConfigDefault {
1269-
save_video_stream: false,
1279+
startup_video_recording: false,
1280+
rolling_video_files: SwitchDefault {
1281+
enabled: false,
1282+
content: RollingVideoFilesConfigDefault { duration_s: 5 },
1283+
},
12701284
capture_frame_dir: if !cfg!(target_os = "linux") {
12711285
"/tmp".into()
12721286
} else {

0 commit comments

Comments
 (0)