mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-11-13 23:31:37 -05:00
add a basic test of Streamer, fix it
This test is copied from the C++ implementation. It ensures the timestamps are calculated accurately from the pts rather than using ffmpeg's estimated duration. The Rust implementation was doing the easy-but-inaccurate thing, so fix that to make the test pass. Additionally, I did this with a code structure that should ensure the Rust code never drops a Writer without indicating to the syncer that its uuid is abandoned. Such a bug essentially leaks the partially-written file, although a restart would cause it to be properly unlinked and marked as such. There are no tests (yet) that exercise this scenario, though.
This commit is contained in:
25
src/mp4.rs
25
src/mp4.rs
@@ -1200,7 +1200,7 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::str;
|
||||
use super::*;
|
||||
use stream::StreamSource;
|
||||
use stream::{self, Opener, Stream};
|
||||
use testutil::{self, TestDb};
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -1397,25 +1397,34 @@ mod tests {
|
||||
}
|
||||
|
||||
fn copy_mp4_to_db(db: &TestDb) {
|
||||
let mut input = StreamSource::File("src/testdata/clip.mp4").open().unwrap();
|
||||
let mut input =
|
||||
stream::FFMPEG.open(stream::Source::File("src/testdata/clip.mp4")).unwrap();
|
||||
|
||||
// 2015-04-26 00:00:00 UTC.
|
||||
const START_TIME: recording::Time = recording::Time(1430006400i64 * TIME_UNITS_PER_SEC);
|
||||
let extra_data = input.get_extra_data().unwrap();
|
||||
let video_sample_entry_id = db.db.lock().insert_video_sample_entry(
|
||||
extra_data.width, extra_data.height, &extra_data.sample_entry).unwrap();
|
||||
let mut output = db.dir.create_writer(START_TIME, START_TIME, TEST_CAMERA_ID,
|
||||
video_sample_entry_id).unwrap();
|
||||
let mut output = db.dir.create_writer(&db.syncer_channel, START_TIME, START_TIME,
|
||||
TEST_CAMERA_ID, video_sample_entry_id).unwrap();
|
||||
|
||||
// end_pts is the pts of the end of the most recent frame (start + duration).
|
||||
// It's needed because dir::Writer calculates a packet's duration from its pts and the
|
||||
// next packet's pts. That's more accurate for RTSP than ffmpeg's estimate of duration.
|
||||
// To write the final packet of this sample .mp4 with a full duration, we need to fake a
|
||||
// next packet's pts from the ffmpeg-supplied duration.
|
||||
let mut end_pts = None;
|
||||
loop {
|
||||
let pkt = match input.get_next() {
|
||||
Ok(p) => p,
|
||||
Err(ffmpeg::Error::Eof) => { break; },
|
||||
Err(e) => { panic!("unexpected input error: {}", e); },
|
||||
};
|
||||
output.write(pkt.data().expect("packet without data"), pkt.duration() as i32,
|
||||
output.write(pkt.data().expect("packet without data"), pkt.pts().unwrap(),
|
||||
pkt.is_key()).unwrap();
|
||||
end_pts = Some(pkt.pts().unwrap() + pkt.duration());
|
||||
}
|
||||
db.syncer_channel.async_save_writer(output).unwrap();
|
||||
output.close(end_pts).unwrap();
|
||||
db.syncer_channel.flush();
|
||||
}
|
||||
|
||||
@@ -1475,8 +1484,8 @@ mod tests {
|
||||
}
|
||||
|
||||
fn compare_mp4s(new_filename: &str, pts_offset: i64, shorten: i64) {
|
||||
let mut orig = StreamSource::File("src/testdata/clip.mp4").open().unwrap();
|
||||
let mut new = StreamSource::File(new_filename).open().unwrap();
|
||||
let mut orig = stream::FFMPEG.open(stream::Source::File("src/testdata/clip.mp4")).unwrap();
|
||||
let mut new = stream::FFMPEG.open(stream::Source::File(new_filename)).unwrap();
|
||||
assert_eq!(orig.get_extra_data().unwrap(), new.get_extra_data().unwrap());
|
||||
let mut final_durations = None;
|
||||
loop {
|
||||
|
||||
Reference in New Issue
Block a user