Merge pull request #1498

Decoders: set up picture state inside the panic guard
This commit is contained in:
Brandon Thomas committed 2026-10-30 15:42:29 -04:00
commit b3ccea8577
2 files changed
+45 -42

No files matched your search

+30 -29
View File
@@ -557,16 +557,16 @@ impl Decoder {
/// Decode all slices of one picture and publish its rows.
fn run_job(frame: FrameRef, slices: Vec<SliceJob>, shared: &Shared, draft: bool) {
let reuse = shared.pool.lock().ok().and_then(|mut p| p.pop());
let mut pic = match reuse {
Some(mut p) if p.mb_w == frame.mb_w && p.mb_h == frame.mb_h() => {
p.reset(frame.clone());
p
}
_ => PicState::new(frame.clone()),
};
pic.skip_deblock = draft;
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let reuse = shared.pool.lock().ok().and_then(|mut p| p.pop());
let mut pic = match reuse {
Some(mut p) if p.mb_w == frame.mb_w && p.mb_h == frame.mb_h() => {
p.reset(frame.clone());
p
}
_ => PicState::new(frame.clone()),
};
pic.skip_deblock = draft;
let mut first_err = None;
for s in &slices {
if let Err(e) = decode_slice(s, &mut pic) {
@@ -574,10 +574,10 @@ fn run_job(frame: FrameRef, slices: Vec<SliceJob>, shared: &Shared, draft: bool)
}
}
pic.flush_rows(true);
first_err
(pic, first_err)
}));
let err = match result {
Ok(e) => e,
let (pic, err) = match result {
Ok((pic, err)) => (Some(pic), err),
Err(_) => {
// Make sure readers never block on this frame.
let fallback = Planes::gray(frame.width, frame.height);
@@ -587,34 +587,35 @@ fn run_job(frame: FrameRef, slices: Vec<SliceJob>, shared: &Shared, draft: bool)
frame.publish(r, Frame::make_row(&fallback, r, &blank, &|_, _, _| u32::MAX));
}
}
pic = PicState::new(frame.clone());
Some(Error::Invalid("internal error while decoding a picture".into()))
(None, Some(Error::Invalid("internal error while decoding a picture".into())))
}
};
if let Ok(mut s) = shared.stats.lock() {
s.pictures += 1;
s.draft_pictures += draft as u64;
for st in &pic.mbs {
match st.kind {
MbKind::I4x4 => s.mb_i4x4 += 1,
MbKind::I8x8 => s.mb_i8x8 += 1,
MbKind::I16x16 => s.mb_i16x16 += 1,
MbKind::IPcm => s.mb_pcm += 1,
MbKind::PSkip => s.mb_p_skip += 1,
MbKind::BSkip => s.mb_b_skip += 1,
MbKind::BDirect16x16 => s.mb_b_direct16x16 += 1,
MbKind::Inter => s.mb_inter += 1,
MbKind::None => {}
}
if st.transform_8x8 && !st.kind.is_intra() {
s.mb_inter_8x8_transform += 1;
if let Some(pic) = &pic {
for st in &pic.mbs {
match st.kind {
MbKind::I4x4 => s.mb_i4x4 += 1,
MbKind::I8x8 => s.mb_i8x8 += 1,
MbKind::I16x16 => s.mb_i16x16 += 1,
MbKind::IPcm => s.mb_pcm += 1,
MbKind::PSkip => s.mb_p_skip += 1,
MbKind::BSkip => s.mb_b_skip += 1,
MbKind::BDirect16x16 => s.mb_b_direct16x16 += 1,
MbKind::Inter => s.mb_inter += 1,
MbKind::None => {}
}
if st.transform_8x8 && !st.kind.is_intra() {
s.mb_inter_8x8_transform += 1;
}
}
}
}
if let (Some(e), Ok(mut slot)) = (err, shared.error.lock()) {
slot.get_or_insert(e);
}
if let Ok(mut p) = shared.pool.lock()
if let (Some(pic), Ok(mut p)) = (pic, shared.pool.lock())
&& p.len() < 4
{
p.push(pic);
+15 -13
View File
@@ -561,9 +561,9 @@ fn run_job(
draft: bool,
shared: &Shared,
) {
let mut pic = PicState::new(frame.clone(), sps, pps, layout, scaling);
pic.draft = draft;
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let mut pic = PicState::new(frame.clone(), sps, pps, layout, scaling);
pic.draft = draft;
let mut first_err = None;
for s in &slices {
if let Err(e) = SliceDecoder::decode(&mut pic, s) {
@@ -571,10 +571,10 @@ fn run_job(
}
}
crate::filter::finish(&mut pic);
first_err
(pic, first_err)
}));
let err = match result {
Ok(e) => e,
let (pic, err) = match result {
Ok((pic, err)) => (Some(pic), err),
Err(_) => {
// make sure readers never block on this frame
let gray = Frame::gray(0, frame.poc, &frame);
@@ -584,18 +584,20 @@ fn run_job(
frame.publish(r, crate::picture::FrameRow { y: row.y.clone(), cb: row.cb.clone(), cr: row.cr.clone(), col: row.col.clone() });
}
}
Some(Error::Invalid("internal error while decoding a picture".into()))
(None, Some(Error::Invalid("internal error while decoding a picture".into())))
}
};
if let Ok(mut s) = shared.stats.lock() {
s.pictures += 1;
for b in &pic.blk {
if b.flags & F_INTRA != 0 {
s.intra_4x4_blocks += 1;
} else if b.flags & F_SKIP != 0 {
s.skip_4x4_blocks += 1;
} else if b.flags != 0 {
s.inter_4x4_blocks += 1;
if let Some(pic) = &pic {
for b in &pic.blk {
if b.flags & F_INTRA != 0 {
s.intra_4x4_blocks += 1;
} else if b.flags & F_SKIP != 0 {
s.skip_4x4_blocks += 1;
} else if b.flags != 0 {
s.inter_4x4_blocks += 1;
}
}
}
}