test the new local time logic

The test ensures it solves the problem of the initial buffering throwing off
the start time of the first segment.

Along the way, I tested and fixed the new TrailingZero flag; it wasn't being
set.
This commit is contained in:
Scott Lamb 2016-12-29 17:14:36 -08:00
parent c7443436a5
commit a71f6e66d8
3 changed files with 40 additions and 10 deletions

View File

@ -554,6 +554,8 @@ impl<'a> InnerWriter<'a> {
sha1_bytes.copy_from_slice(&self.hasher.finish()?[..]);
let start_time = self.prev_end.unwrap_or(local_start);
let end = start_time + recording::Duration(self.index.total_duration_90k as i64);
let flags = if self.index.has_trailing_zero() { db::RecordingFlags::TrailingZero as i32 }
else { 0 };
let recording = db::RecordingToInsert{
camera_id: self.camera_id,
sample_file_bytes: self.index.sample_file_bytes,
@ -566,7 +568,7 @@ impl<'a> InnerWriter<'a> {
video_index: self.index.video_index,
sample_file_sha1: sha1_bytes,
run_offset: self.run_offset,
flags: 0, // TODO
flags: flags,
};
self.syncer_channel.async_save_recording(recording, self.f);
Ok(PreviousWriter{

View File

@ -335,6 +335,8 @@ impl SampleIndexEncoder {
append_varint32((zigzag32(duration_delta) << 1) | (is_key as u32), &mut self.video_index);
append_varint32(zigzag32(bytes_delta), &mut self.video_index);
}
pub fn has_trailing_zero(&self) -> bool { self.prev_duration_90k == 0 }
}
/// A segment represents a view of some or all of a single recording, starting from a key frame.

View File

@ -192,6 +192,7 @@ mod tests {
use ffmpeg::packet::Mut;
use h264;
use recording;
use std::cmp;
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::atomic::{AtomicBool, Ordering};
use stream::{self, Opener, Stream};
@ -201,18 +202,22 @@ mod tests {
struct ProxyingStream<'a> {
clock: &'a clock::SimulatedClock,
inner: stream::FfmpegStream,
last_duration: time::Duration,
buffered: time::Duration,
slept: time::Duration,
ts_offset: i64,
ts_offset_pkts_left: u32,
pkts_left: u32,
}
impl<'a> ProxyingStream<'a> {
fn new(clock: &'a clock::SimulatedClock, inner: stream::FfmpegStream) -> ProxyingStream {
fn new(clock: &'a clock::SimulatedClock, buffered: time::Duration,
inner: stream::FfmpegStream) -> ProxyingStream {
clock.sleep(buffered);
ProxyingStream {
clock: clock,
inner: inner,
last_duration: time::Duration::seconds(0),
buffered: buffered,
slept: time::Duration::seconds(0),
ts_offset: 0,
ts_offset_pkts_left: 0,
pkts_left: 0,
@ -227,13 +232,21 @@ mod tests {
}
self.pkts_left -= 1;
// Advance clock to when this packet starts.
self.clock.sleep(self.last_duration);
let mut pkt = self.inner.get_next()?;
self.last_duration = time::Duration::nanoseconds(
pkt.duration() * 1_000_000_000 / recording::TIME_UNITS_PER_SEC);
// Advance clock to the end of this frame.
// Avoid accumulating conversion error by tracking the total amount to sleep and how
// much we've already slept, rather than considering each frame in isolation.
{
let goal = pkt.pts().unwrap() + pkt.duration();
let goal = time::Duration::nanoseconds(
goal * 1_000_000_000 / recording::TIME_UNITS_PER_SEC);
let duration = goal - self.slept;
let buf_part = cmp::min(self.buffered, duration);
self.buffered = self.buffered - buf_part;
self.clock.sleep(duration - buf_part);
self.slept = goal;
}
if self.ts_offset_pkts_left > 0 {
self.ts_offset_pkts_left -= 1;
@ -309,9 +322,10 @@ mod tests {
fn basic() {
testutil::init();
let clock = clock::SimulatedClock::new();
clock.sleep(time::Duration::seconds(1430006400)); // 2015-04-26 00:00:00 UTC
let stream = stream::FFMPEG.open(stream::Source::File("src/testdata/clip.mp4")).unwrap();
let mut stream = ProxyingStream::new(&clock, stream);
let mut stream = ProxyingStream::new(&clock, time::Duration::seconds(2), stream);
stream.ts_offset = 180000; // starting pts of the input should be irrelevant
stream.ts_offset_pkts_left = u32::max_value();
stream.pkts_left = u32::max_value();
@ -358,5 +372,17 @@ mod tests {
Frame{start_90k: 0, duration_90k: 90011, is_key: true},
Frame{start_90k: 90011, duration_90k: 0, is_key: false},
]);
let mut recordings = Vec::new();
db.list_recordings_by_id(testutil::TEST_CAMERA_ID, 1..3, |r| {
recordings.push(r);
Ok(())
}).unwrap();
assert_eq!(2, recordings.len());
assert_eq!(1, recordings[0].id);
assert_eq!(recording::Time(128700575999999), recordings[0].start);
assert_eq!(0, recordings[0].flags);
assert_eq!(2, recordings[1].id);
assert_eq!(recording::Time(128700576719993), recordings[1].start);
assert_eq!(db::RecordingFlags::TrailingZero as i32, recordings[1].flags);
}
}