Skip to content

Commit 73572a9

Browse files
committed
Support Immediate Exit
1 parent 9b53c84 commit 73572a9

File tree

7 files changed

+61
-15
lines changed

7 files changed

+61
-15
lines changed

src/api/channel/by_gop.rs

+2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ fn workerpool<T: Pixel>(
163163
wl.send.send(p).unwrap();
164164
}
165165
Err(EncoderStatus::Encoded) => {}
166+
Err(EncoderStatus::ImmediateExit) => break,
166167
_ => todo!("Error management {:?}", r),
167168
}
168169
}
@@ -178,6 +179,7 @@ fn workerpool<T: Pixel>(
178179
Ok(p) => wl.send.send(p).unwrap(),
179180
Err(EncoderStatus::LimitReached) => break,
180181
Err(EncoderStatus::Encoded) => {}
182+
Err(EncoderStatus::ImmediateExit) => break,
181183
_ => todo!("Error management"),
182184
}
183185
}

src/api/config/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ impl Config {
249249
inner.rc_state.setup_second_pass(s);
250250
}
251251

252+
if let Some(ref progress) = self.progress {
253+
inner.progress = Arc::clone(progress);
254+
}
255+
252256
Ok(inner)
253257
}
254258

src/api/internal.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ use std::fs;
3535
use std::path::PathBuf;
3636
use std::sync::Arc;
3737

38+
use super::{DefaultProgress, GranularProgress};
39+
3840
/// The set of options that controls frame re-ordering and reference picture
3941
/// selection.
4042
/// The options stored here are invariant over the whole encode.
@@ -257,6 +259,9 @@ pub(crate) struct ContextInner<T: Pixel> {
257259
next_lookahead_output_frameno: u64,
258260
/// Optional opaque to be sent back to the user
259261
opaque_q: BTreeMap<u64, Opaque>,
262+
263+
/// Progress callback
264+
pub(crate) progress: Arc<dyn GranularProgress>,
260265
}
261266

262267
impl<T: Pixel> ContextInner<T> {
@@ -309,6 +314,7 @@ impl<T: Pixel> ContextInner<T> {
309314
next_lookahead_frame: 1,
310315
next_lookahead_output_frameno: 0,
311316
opaque_q: BTreeMap::new(),
317+
progress: Arc::new(DefaultProgress {}) as Arc<dyn GranularProgress>,
312318
}
313319
}
314320

@@ -1162,8 +1168,13 @@ impl<T: Pixel> ContextInner<T> {
11621168

11631169
if self.rc_state.needs_trial_encode(fti) {
11641170
let mut trial_fs = frame_data.fs.clone();
1165-
let data =
1166-
encode_frame(&frame_data.fi, &mut trial_fs, &self.inter_cfg);
1171+
let data = encode_frame(
1172+
&frame_data.fi,
1173+
&mut trial_fs,
1174+
&self.inter_cfg,
1175+
self.progress.as_ref(),
1176+
)
1177+
.ok_or(EncoderStatus::ImmediateExit)?;
11671178
self.rc_state.update_state(
11681179
(data.len() * 8) as i64,
11691180
fti,
@@ -1181,8 +1192,14 @@ impl<T: Pixel> ContextInner<T> {
11811192
frame_data.fi.set_quantizers(&qps);
11821193
}
11831194

1184-
let data =
1185-
encode_frame(&frame_data.fi, &mut frame_data.fs, &self.inter_cfg);
1195+
let data = encode_frame(
1196+
&frame_data.fi,
1197+
&mut frame_data.fs,
1198+
&self.inter_cfg,
1199+
self.progress.as_ref(),
1200+
)
1201+
.ok_or(EncoderStatus::ImmediateExit)?;
1202+
11861203
let enc_stats = frame_data.fs.enc_stats.clone();
11871204
self.maybe_prev_log_base_q = Some(qps.log_base_q);
11881205
// TODO: Add support for dropping frames.

src/api/util.rs

+3
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ pub enum EncoderStatus {
175175
/// [`Context::twopass_out()`]: struct.Context.html#method.twopass_out
176176
#[error("not ready")]
177177
NotReady,
178+
/// Immediate exit was requested
179+
#[error("immediate exit")]
180+
ImmediateExit,
178181
}
179182

180183
/// Represents a packet.

src/bin/rav1e.rs

+3
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ fn process_frame<T: Pixel, D: Decoder>(
191191
Err(e @ EncoderStatus::NotReady) => {
192192
(Err(e.context("Mismanaged handling of two-pass stats data")), false)
193193
}
194+
Err(e @ EncoderStatus::ImmediateExit) => {
195+
(Err(e.context("Immediate exit requested")), false)
196+
}
194197
Err(EncoderStatus::Encoded) => (Ok(Some(frame_summaries)), true),
195198
};
196199

src/capi.rs

+4
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ pub enum EncoderStatus {
124124
/// was provided in the second pass of a 2-pass encode to encode the next
125125
/// frame.
126126
NotReady = -2,
127+
/// Immediate exit requested
128+
ImmediateExit = -3,
127129
}
128130

129131
impl EncoderStatus {
@@ -137,6 +139,7 @@ impl EncoderStatus {
137139
Encoded => "A Frame had been encoded but not emitted yet\0".as_ptr(),
138140
Failure => "Generic fatal error\0".as_ptr(),
139141
NotReady => "First-pass stats data not retrieved or not enough second-pass data provided\0".as_ptr(),
142+
ImmediateExit => "Immediate exit requested\0".as_ptr(),
140143
}
141144
}
142145
}
@@ -152,6 +155,7 @@ impl From<Option<rav1e::EncoderStatus>> for EncoderStatus {
152155
rav1e::EncoderStatus::Encoded => EncoderStatus::Encoded,
153156
rav1e::EncoderStatus::Failure => EncoderStatus::Failure,
154157
rav1e::EncoderStatus::NotReady => EncoderStatus::NotReady,
158+
rav1e::EncoderStatus::ImmediateExit => EncoderStatus::ImmediateExit,
155159
},
156160
}
157161
}

src/encoder.rs

+24-11
Original file line numberDiff line numberDiff line change
@@ -2973,7 +2973,8 @@ fn get_initial_cdfcontext<T: Pixel>(fi: &FrameInvariants<T>) -> CDFContext {
29732973
#[hawktracer(encode_tile_group)]
29742974
fn encode_tile_group<T: Pixel>(
29752975
fi: &FrameInvariants<T>, fs: &mut FrameState<T>, inter_cfg: &InterConfig,
2976-
) -> Vec<u8> {
2976+
progress: &dyn GranularProgress,
2977+
) -> Option<Vec<u8>> {
29772978
let planes =
29782979
if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 };
29792980
let mut blocks = FrameBlocks::new(fi.w_in_b, fi.h_in_b);
@@ -2988,12 +2989,18 @@ fn encode_tile_group<T: Pixel>(
29882989
.zip(cdfs.iter_mut())
29892990
.collect::<Vec<_>>()
29902991
.into_par_iter()
2991-
.map(|(mut ctx, cdf)| {
2992-
let raw = encode_tile(fi, &mut ctx.ts, cdf, &mut ctx.tb, inter_cfg);
2993-
(raw, ctx.ts)
2992+
.map(|(ctx, cdf)| {
2993+
let TileContextMut { mut ts, mut tb, .. } = ctx;
2994+
let raw = encode_tile(fi, &mut ts, cdf, &mut tb, inter_cfg, progress);
2995+
raw.map(|raw| (raw, ts))
29942996
})
2997+
.while_some()
29952998
.unzip();
29962999

3000+
if raw_tiles.len() != ti.tile_count() {
3001+
return None;
3002+
}
3003+
29973004
let stats =
29983005
tile_states.into_iter().map(|ts| ts.enc_stats).collect::<Vec<_>>();
29993006
for tile_stats in stats {
@@ -3078,7 +3085,7 @@ fn encode_tile_group<T: Pixel>(
30783085
debug_assert!(max_tile_size_bytes > 0 && max_tile_size_bytes <= 4);
30793086
fs.max_tile_size_bytes = max_tile_size_bytes;
30803087

3081-
build_raw_tile_group(ti, &raw_tiles, max_tile_size_bytes)
3088+
Some(build_raw_tile_group(ti, &raw_tiles, max_tile_size_bytes))
30823089
}
30833090

30843091
fn build_raw_tile_group(
@@ -3206,8 +3213,8 @@ fn check_lf_queue<T: Pixel>(
32063213
fn encode_tile<'a, T: Pixel>(
32073214
fi: &FrameInvariants<T>, ts: &mut TileStateMut<'_, T>,
32083215
fc: &'a mut CDFContext, blocks: &'a mut TileBlocksMut<'a>,
3209-
inter_cfg: &InterConfig,
3210-
) -> Vec<u8> {
3216+
inter_cfg: &InterConfig, progress: &dyn GranularProgress,
3217+
) -> Option<Vec<u8>> {
32113218
let mut w = WriterEncoder::new();
32123219
let planes =
32133220
if fi.sequence.chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 };
@@ -3226,6 +3233,11 @@ fn encode_tile<'a, T: Pixel>(
32263233
for sbx in 0..ts.sb_width {
32273234
cw.fc_log.clear();
32283235

3236+
let data = ProgressData {};
3237+
if !progress.progress(&data) {
3238+
return None;
3239+
}
3240+
32293241
let tile_sbo = TileSuperBlockOffset(SuperBlockOffset { x: sbx, y: sby });
32303242
let mut sbs_qe = SBSQueueEntry {
32313243
sbo: tile_sbo,
@@ -3402,7 +3414,7 @@ fn encode_tile<'a, T: Pixel>(
34023414
ts.sbo.0.x,
34033415
ts.sbo.0.y
34043416
);
3405-
w.done()
3417+
Some(w.done())
34063418
}
34073419

34083420
#[allow(unused)]
@@ -3485,7 +3497,8 @@ fn get_initial_segmentation<T: Pixel>(
34853497

34863498
pub fn encode_frame<T: Pixel>(
34873499
fi: &FrameInvariants<T>, fs: &mut FrameState<T>, inter_cfg: &InterConfig,
3488-
) -> Vec<u8> {
3500+
progress: &dyn GranularProgress,
3501+
) -> Option<Vec<u8>> {
34893502
debug_assert!(!fi.show_existing_frame);
34903503
debug_assert!(!fi.invalid);
34913504
let obu_extension = 0;
@@ -3496,7 +3509,7 @@ pub fn encode_frame<T: Pixel>(
34963509
fs.segmentation = get_initial_segmentation(fi);
34973510
segmentation_optimize(fi, fs);
34983511
}
3499-
let tile_group = encode_tile_group(fi, fs, inter_cfg);
3512+
let tile_group = encode_tile_group(fi, fs, inter_cfg, progress)?;
35003513

35013514
if fi.frame_type == FrameType::KEY {
35023515
write_key_frame_obus(&mut packet, fi, obu_extension).unwrap();
@@ -3527,7 +3540,7 @@ pub fn encode_frame<T: Pixel>(
35273540
buf2.clear();
35283541

35293542
packet.write_all(&tile_group).unwrap();
3530-
packet
3543+
Some(packet)
35313544
}
35323545

35333546
pub fn update_rec_buffer<T: Pixel>(

0 commit comments

Comments
 (0)