fix(qsv): end the inner borrow before the retarget param rebuild
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1401,30 +1401,36 @@ impl Encoder for QsvEncoder {
|
|||||||
/// requires completed sync operations, so the in-flight window is drained (into `ready`)
|
/// requires completed sync operations, so the in-flight window is drained (into `ready`)
|
||||||
/// first; a drain that can't finish inside the budget falls back to the caller's rebuild.
|
/// first; a drain that can't finish inside the budget falls back to the caller's rebuild.
|
||||||
fn reconfigure_bitrate(&mut self, bps: u64) -> bool {
|
fn reconfigure_bitrate(&mut self, bps: u64) -> bool {
|
||||||
let Some(inner) = self.inner.as_mut() else {
|
// Drain phase in its own scope so the `inner` borrow ends before the param rebuild
|
||||||
self.bitrate_bps = bps;
|
// below reads `self` again (the raw session pointer stays valid — `self.inner` is not
|
||||||
return true;
|
// touched in between).
|
||||||
};
|
let session = {
|
||||||
let deadline = std::time::Instant::now() + BUSY_BUDGET;
|
let Some(inner) = self.inner.as_mut() else {
|
||||||
while !inner.pending.is_empty() {
|
self.bitrate_bps = bps;
|
||||||
match sync_one(inner, 5) {
|
return true;
|
||||||
Ok(Some(au)) => inner.ready.push_back(au),
|
};
|
||||||
Ok(None) => {
|
let deadline = std::time::Instant::now() + BUSY_BUDGET;
|
||||||
if std::time::Instant::now() >= deadline {
|
while !inner.pending.is_empty() {
|
||||||
tracing::warn!(
|
match sync_one(inner, 5) {
|
||||||
"QSV bitrate retarget: in-flight frames didn't settle — falling \
|
Ok(Some(au)) => inner.ready.push_back(au),
|
||||||
back to a rebuild"
|
Ok(None) => {
|
||||||
);
|
if std::time::Instant::now() >= deadline {
|
||||||
|
tracing::warn!(
|
||||||
|
"QSV bitrate retarget: in-flight frames didn't settle — falling \
|
||||||
|
back to a rebuild"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::thread::sleep(std::time::Duration::from_micros(250));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(error = %format!("{e:#}"), "QSV retarget drain failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::thread::sleep(std::time::Duration::from_micros(250));
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!(error = %format!("{e:#}"), "QSV retarget drain failed");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
inner.session.0
|
||||||
|
};
|
||||||
let old = self.bitrate_bps;
|
let old = self.bitrate_bps;
|
||||||
self.bitrate_bps = bps;
|
self.bitrate_bps = bps;
|
||||||
let cfg = self.encode_config();
|
let cfg = self.encode_config();
|
||||||
@@ -1441,7 +1447,7 @@ impl Encoder for QsvEncoder {
|
|||||||
set.par.NumExtParam = set.ptrs.len() as u16;
|
set.par.NumExtParam = set.ptrs.len() as u16;
|
||||||
// SAFETY: session live on this thread, no operation in flight (drained above); the
|
// SAFETY: session live on this thread, no operation in flight (drained above); the
|
||||||
// param block + ext chain outlive the synchronous call.
|
// param block + ext chain outlive the synchronous call.
|
||||||
let sts = unsafe { vpl::MFXVideoENCODE_Reset(inner.session.0, &mut set.par) };
|
let sts = unsafe { vpl::MFXVideoENCODE_Reset(session, &mut set.par) };
|
||||||
if sts < vpl::MFX_ERR_NONE {
|
if sts < vpl::MFX_ERR_NONE {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
mbps = bps / 1_000_000,
|
mbps = bps / 1_000_000,
|
||||||
|
|||||||
Reference in New Issue
Block a user