pub encoder: Box<dyn NAEncoder>,
pub scaler: Option<NAScale>,
pub scaler_buf: NABufferType,
+ pub tb_num: u32,
+ pub tb_den: u32,
+ pub cfr: bool,
+ pub last_ts: Option<u64>,
}
impl EncoderInterface for VideoEncodeContext {
} else {
buf
};
- let cfrm = NAFrame::new(frm.get_time_information(), frm.frame_type, frm.key, frm.get_info(), cbuf);
- self.encoder.encode(&cfrm).unwrap();
- while let Ok(Some(pkt)) = self.encoder.get_packet() {
- queue.queue_packet(pkt);
+ if self.scaler.is_none() && !matches!(cbuf, NABufferType::None) {
+ self.scaler_buf = cbuf.clone();
}
+
+ let ref_ts = frm.get_time_information();
+ let new_pts = if let Some(ts) = ref_ts.pts {
+ Some(NATimeInfo::ts_to_time(ts, u64::from(self.tb_den), ref_ts.tb_num, ref_ts.tb_den))
+ } else { None };
+ let new_duration = if let Some(dur) = ref_ts.duration {
+ Some(NATimeInfo::ts_to_time(dur, u64::from(self.tb_den), ref_ts.tb_num, ref_ts.tb_den))
+ } else { None };
+ let ts = NATimeInfo::new(new_pts, None, new_duration, self.tb_num, self.tb_den);
+ let mut cfrm = NAFrame::new(ts, frm.frame_type, frm.key, frm.get_info(), cbuf);
+ if self.last_ts.is_none() {
+ self.last_ts = new_pts;
+ }
+
+ let mut converted = false;
+ if let Some(ref mut last_ts) = self.last_ts {
+ if self.cfr && new_pts.is_some() {
+ let cur_ts = new_pts.unwrap_or_default();
+ let mut cur_lts = *last_ts;
+ let mut next_lts = *last_ts + u64::from(self.tb_num);
+ let mut had_frame = false;
+ while cur_ts >= cur_lts {
+ cfrm.ts.pts = Some(cur_lts);
+ self.encoder.encode(&cfrm).unwrap();
+ while let Ok(Some(pkt)) = self.encoder.get_packet() {
+ queue.queue_packet(pkt);
+ }
+ cur_lts = next_lts;
+ next_lts += u64::from(self.tb_num);
+ had_frame = true;
+ }
+ converted = true;
+ if had_frame {
+ *last_ts = cur_lts;
+ }
+ }
+ }
+ if !converted {
+ self.encoder.encode(&cfrm).unwrap();
+ while let Ok(Some(pkt)) = self.encoder.get_packet() {
+ queue.queue_packet(pkt);
+ }
+ }
+
true
}
fn flush(&mut self, queue: &mut OutputQueue) -> EncoderResult<()> {
//todo check for params mismatch
let enc_ctx: Box<dyn EncoderInterface> = match (&iformat, &real_fmt) {
(NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(dvinfo)) => {
+ let force_cfr = self.fixed_rate || (ret_eparams.flags & ENC_MODE_CFR) != 0;
if svinfo == dvinfo && !forced_out {
- Box::new(VideoEncodeContext { encoder, scaler: None, scaler_buf: NABufferType::None })
+ Box::new(VideoEncodeContext {
+ encoder,
+ scaler: None,
+ scaler_buf: NABufferType::None,
+ cfr: force_cfr,
+ last_ts: None,
+ tb_num: enc_stream.tb_num,
+ tb_den: enc_stream.tb_den,
+ })
} else {
let ofmt = ScaleInfo { fmt: dvinfo.format, width: dvinfo.width, height: dvinfo.height };
let ret = NAScale::new_with_options(ofmt, ofmt, &self.scale_opts);
return RegisterResult::Failed;
}
let scaler_buf = ret.unwrap();
- Box::new(VideoEncodeContext { encoder, scaler: Some(scaler), scaler_buf })
+ Box::new(VideoEncodeContext {
+ encoder,
+ scaler: Some(scaler),
+ scaler_buf,
+ cfr: force_cfr,
+ last_ts: None,
+ tb_num: enc_stream.tb_num,
+ tb_den: enc_stream.tb_den,
+ })
}
},
(NACodecTypeInfo::Audio(sainfo), NACodecTypeInfo::Audio(dainfo)) => {
println!("error initialising encoder");
return RegisterResult::Failed;
}
+ let enc_stream = ret.unwrap();
//todo check for params mismatch
- let enc_ctx: Box<dyn EncoderInterface> = match (&oopts.enc_params.format, &ret_eparams.format) {
+ let real_fmt = enc_stream.get_info().get_properties();
+ let enc_ctx: Box<dyn EncoderInterface> = match (&oopts.enc_params.format, &real_fmt) {
(NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(dvinfo)) => {
+ let force_cfr = self.fixed_rate || (ret_eparams.flags & ENC_MODE_CFR) != 0;
if svinfo == dvinfo {
- Box::new(VideoEncodeContext { encoder, scaler: None, scaler_buf: NABufferType::None })
+ Box::new(VideoEncodeContext {
+ encoder,
+ scaler: None,
+ scaler_buf: NABufferType::None,
+ cfr: force_cfr,
+ last_ts: None,
+ tb_num: enc_stream.tb_num,
+ tb_den: enc_stream.tb_den,
+ })
} else {
let ofmt = ScaleInfo { fmt: dvinfo.format, width: dvinfo.width, height: dvinfo.height };
let ret = NAScale::new_with_options(ofmt, ofmt, &self.scale_opts);
return RegisterResult::Failed;
}
let scaler_buf = ret.unwrap();
- Box::new(VideoEncodeContext { encoder, scaler: Some(scaler), scaler_buf })
+ Box::new(VideoEncodeContext {
+ encoder,
+ scaler: Some(scaler),
+ scaler_buf,
+ cfr: force_cfr,
+ last_ts: None,
+ tb_num: enc_stream.tb_num,
+ tb_den: enc_stream.tb_den,
+ })
}
},
(NACodecTypeInfo::Audio(sainfo), NACodecTypeInfo::Audio(dainfo)) => {
},
_ => unreachable!(),
};
- out_sm.add_stream_ref(ret.unwrap());
+ out_sm.add_stream_ref(enc_stream);
self.encoders.push(OutputMode::Encode(out_id, enc_ctx));
self.ostr_opts.push(oopts);
}