Count VideoToolbox sessions, frames and declined requests in perf.stats (#981)

This commit is contained in:
MarekSpodBiedry 2026-10-11 11:35:18 +02:00
parent 4e2d0bc2d3
commit d702608eaf
2 changed files with 25 additions and 2 deletions

View File

@ -133,13 +133,18 @@ pub fn videotoolbox_encoder_factory(
Ok(c) => c,
Err(why) => {
log::info!("hardware {name} encoding declined: {why}");
filmcraft_export::note_hw_encode_declined();
return None;
}
};
match VtEncoder::new(config) {
Ok(vt) => Some(Ok(Box::new(HardwareEncoder { vt, y: Vec::new(), u: Vec::new(), v: Vec::new(), decoded: 0 }))),
Ok(vt) => {
filmcraft_export::note_hw_encode_session();
Some(Ok(Box::new(HardwareEncoder { vt, y: Vec::new(), u: Vec::new(), v: Vec::new(), decoded: 0 })))
}
Err(why) => {
log::info!("hardware {name} encoding declined: {why}");
filmcraft_export::note_hw_encode_declined();
None
}
}
@ -222,6 +227,7 @@ impl VideoEncoder for HardwareEncoder {
}
filmcraft_export::timed(filmcraft_export::Stage::Convert, || filmcraft_export::rgba_to_yuv420_8(f.rgba, w, h, &mut self.y, &mut self.u, &mut self.v));
let packets = self.vt.encode(f.index, &self.y, &self.u, &self.v).map_err(ExportError::Encode)?;
filmcraft_export::note_hw_encode_frame();
// the muxer needs the parameter sets after the first group of pictures
if f.index == 0 {
let params = self.vt.parameter_sets().ok_or_else(|| ExportError::Encode("VideoToolbox returned no parameter sets for the first frame".into()))?;

View File

@ -9,7 +9,8 @@ use std::panic::AssertUnwindSafe;
use std::sync::Arc;
use filmcraft_export::{
BitrateMode, EncodedPacket, EncoderFrame, ExportSettings, Format, H264Pass, H264Profile, HardwareEncoding, Progress, VideoEncoder, export, rgba_to_yuv420_8,
BitrateMode, EncodedPacket, EncoderFrame, ExportSettings, Format, H264Pass, H264Profile, HardwareEncoding, Progress, VideoEncoder, export, hw_encode_stats,
rgba_to_yuv420_8,
};
use filmcraft_frame::PixelData;
use filmcraft_isobmff::{CodecConfig, SampleEntry};
@ -133,6 +134,22 @@ fn factory_only_acts_when_asked() {
assert!(videotoolbox_encoder_factory(Format::H264, W, H, FPS, &ExportSettings { hardware_encoding: HardwareEncoding::Off, ..s }).is_none());
}
/// `perf.stats` reads these counters: a declined request, a session and every encoded picture must show.
/// The counters are process-wide and other tests add to them, so only increases are checked.
#[test]
fn hardware_encoder_counters_follow_the_export() {
let s = hardware_settings();
let before = hw_encode_stats();
// an odd picture size is declined before any session is created
assert!(videotoolbox_encoder_factory(Format::H264, W + 1, H, FPS, &s).is_none());
assert!(hw_encode_stats().declined > before.declined, "a declined request is counted");
let Some(mut enc) = hardware(&s, W, H) else { return };
let created = hw_encode_stats();
assert!(created.sessions > before.sessions, "a created session is counted");
encode_all(&mut enc, 3);
assert!(hw_encode_stats().frames >= created.frames + 3, "every encoded picture is counted");
}
#[test]
fn round_trip_through_our_software_decoder() {
let s = hardware_settings();