be slightly more graceful on bad /view.mp4 (#46)

Before, this would panic from the reactor thread. After, it returns a
internal server error. Still not ideal, but better.

To return "bad request" as it should, mp4::FileBuilder::build() should
return a new error type that distinguishes "invalid argument" from
"internal" and the like. I'm thinking of using a ErrorKind enum
throughout the program that's similar to grpc::StatusCode.
This commit is contained in:
Scott Lamb 2018-12-28 09:01:47 -06:00
parent 4580038013
commit 89fa35a2f7

View File

@ -1045,8 +1045,13 @@ impl FileBuilder {
self.body.append_u32(0); // reserved
self.body.append_u32(self.duration_90k);
self.body.append_static(StaticBytestring::TkhdJunk)?;
let width = self.video_sample_entries.iter().map(|e| e.width).max().unwrap();
let height = self.video_sample_entries.iter().map(|e| e.height).max().unwrap();
let (width, height) = self.video_sample_entries.iter().fold(None, |m, e| {
match m {
None => Some((e.width, e.height)),
Some((w, h)) => Some((cmp::max(w, e.width), cmp::max(h, e.height))),
}
}).ok_or_else(|| format_err!("No video_sample_entries"))?;
self.body.append_u32((width as u32) << 16);
self.body.append_u32((height as u32) << 16);
})
@ -1870,7 +1875,7 @@ mod tests {
/// sample tables that match the supplied encoder.
fn make_mp4_from_encoders(type_: Type, db: &TestDb<RealClocks>,
mut recordings: Vec<db::RecordingToInsert>,
desired_range_90k: Range<i32>) -> File {
desired_range_90k: Range<i32>) -> Result<File, Error> {
let mut builder = FileBuilder::new(type_);
let mut duration_so_far = 0;
for r in recordings.drain(..) {
@ -1882,7 +1887,7 @@ mod tests {
duration_so_far += row.duration_90k;
builder.append(&db.db.lock(), row, d_start .. d_end).unwrap();
}
builder.build(db.db.clone(), db.dirs_by_stream_id.clone()).unwrap()
builder.build(db.db.clone(), db.dirs_by_stream_id.clone())
}
/// Tests sample table for a simple video index of all sync frames.
@ -1899,7 +1904,7 @@ mod tests {
}
// Time range [2, 2+4+6+8) means the 2nd, 3rd, and 4th samples should be included.
let mp4 = make_mp4_from_encoders(Type::Normal, &db, vec![r], 2 .. 2+4+6+8);
let mp4 = make_mp4_from_encoders(Type::Normal, &db, vec![r], 2 .. 2+4+6+8).unwrap();
let track = find_track(mp4, 1);
assert!(track.edts_cursor.is_none());
let mut cursor = track.stbl_cursor;
@ -1954,7 +1959,7 @@ mod tests {
// Time range [2+4+6, 2+4+6+8) means the 4th sample should be included.
// The 3rd gets pulled in also because it's a sync frame and the 4th isn't.
let mp4 = make_mp4_from_encoders(Type::Normal, &db, vec![r], 2+4+6 .. 2+4+6+8);
let mp4 = make_mp4_from_encoders(Type::Normal, &db, vec![r], 2+4+6 .. 2+4+6+8).unwrap();
let track = find_track(mp4, 1);
// Examine edts. It should skip the 3rd frame.
@ -2003,6 +2008,14 @@ mod tests {
]);
}
#[test]
fn test_no_segments() {
testutil::init();
let db = TestDb::new(RealClocks {});
let e = make_mp4_from_encoders(Type::Normal, &db, vec![], 0 .. 0).err().unwrap();
assert_eq!(e.to_string(), "No video_sample_entries");
}
#[test]
fn test_multi_segment() {
testutil::init();
@ -2021,7 +2034,7 @@ mod tests {
encoders.push(r);
// This should include samples 3 and 4 only, both sync frames.
let mp4 = make_mp4_from_encoders(Type::Normal, &db, encoders, 1+2 .. 1+2+3+4);
let mp4 = make_mp4_from_encoders(Type::Normal, &db, encoders, 1+2 .. 1+2+3+4).unwrap();
let mut cursor = BoxCursor::new(mp4);
cursor.down();
assert!(cursor.find(b"moov"));
@ -2056,7 +2069,7 @@ mod tests {
encoders.push(r);
// Multi-segment recording with an edit list, encoding with a zero-duration recording.
let mp4 = make_mp4_from_encoders(Type::Normal, &db, encoders, 1 .. 2+3);
let mp4 = make_mp4_from_encoders(Type::Normal, &db, encoders, 1 .. 2+3).unwrap();
let track = find_track(mp4, 1);
let mut cursor = track.edts_cursor.unwrap();
cursor.down();
@ -2081,7 +2094,7 @@ mod tests {
// Time range [2+4+6, 2+4+6+8+1) means the 4th sample and part of the 5th are included.
// The 3rd gets pulled in also because it's a sync frame and the 4th isn't.
let mp4 = make_mp4_from_encoders(Type::MediaSegment, &db, vec![r],
2+4+6 .. 2+4+6+8+1);
2+4+6 .. 2+4+6+8+1).unwrap();
let mut cursor = BoxCursor::new(mp4);
cursor.down();