mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-04-20 10:47:20 -04:00
style improvements
* remove stuttering: mp4::Mp4Foo -> mp4::Foo * stop using a &MutexGuard<Foo> where a &Foo will do
This commit is contained in:
parent
0a683b0846
commit
2d0c78a6d8
74
src/mp4.rs
74
src/mp4.rs
@ -95,12 +95,12 @@ use std::cmp;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::{Arc, MutexGuard};
|
use std::sync::Arc;
|
||||||
use strutil;
|
use strutil;
|
||||||
use time::Timespec;
|
use time::Timespec;
|
||||||
|
|
||||||
/// This value should be incremented any time a change is made to this file that causes different
|
/// This value should be incremented any time a change is made to this file that causes different
|
||||||
/// bytes to be output for a particular set of `Mp4Builder` options. Incrementing this value will
|
/// bytes to be output for a particular set of `Builder` options. Incrementing this value will
|
||||||
/// cause the etag to change as well.
|
/// cause the etag to change as well.
|
||||||
const FORMAT_VERSION: [u8; 1] = [0x03];
|
const FORMAT_VERSION: [u8; 1] = [0x03];
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ const SUBTITLE_TEMPLATE: &'static str = "%Y-%m-%d %H:%M:%S %z";
|
|||||||
const SUBTITLE_LENGTH: usize = 25; // "2015-07-02 17:10:00 -0700".len();
|
const SUBTITLE_LENGTH: usize = 25; // "2015-07-02 17:10:00 -0700".len();
|
||||||
|
|
||||||
/// Holds the sample indexes for a given video segment: `stts`, `stsz`, and `stss`.
|
/// Holds the sample indexes for a given video segment: `stts`, `stsz`, and `stss`.
|
||||||
struct Mp4SegmentIndex {
|
struct SegmentIndex {
|
||||||
/// Holds all three sample indexes:
|
/// Holds all three sample indexes:
|
||||||
/// &buf[.. stsz_start] is stts.
|
/// &buf[.. stsz_start] is stts.
|
||||||
/// &buf[stsz_start .. stss_start] is stsz.
|
/// &buf[stsz_start .. stss_start] is stsz.
|
||||||
@ -325,28 +325,28 @@ struct Mp4SegmentIndex {
|
|||||||
stss_start: u32,
|
stss_start: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mp4SegmentIndex {
|
impl SegmentIndex {
|
||||||
fn stts(&self) -> &[u8] { &self.buf[.. self.stsz_start as usize] }
|
fn stts(&self) -> &[u8] { &self.buf[.. self.stsz_start as usize] }
|
||||||
fn stsz(&self) -> &[u8] { &self.buf[self.stsz_start as usize .. self.stss_start as usize] }
|
fn stsz(&self) -> &[u8] { &self.buf[self.stsz_start as usize .. self.stss_start as usize] }
|
||||||
fn stss(&self) -> &[u8] { &self.buf[self.stss_start as usize ..] }
|
fn stss(&self) -> &[u8] { &self.buf[self.stss_start as usize ..] }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around `recording::Segment` that keeps some additional `.mp4`-specific state.
|
/// A wrapper around `recording::Segment` that keeps some additional `.mp4`-specific state.
|
||||||
struct Mp4Segment {
|
struct Segment {
|
||||||
s: recording::Segment,
|
s: recording::Segment,
|
||||||
|
|
||||||
/// Holds the `stts`, `stsz`, and `stss` if they've been generated.
|
/// Holds the `stts`, `stsz`, and `stss` if they've been generated.
|
||||||
/// Access only through `with_index`.
|
/// Access only through `with_index`.
|
||||||
index: RefCell<Option<Mp4SegmentIndex>>,
|
index: RefCell<Option<SegmentIndex>>,
|
||||||
|
|
||||||
/// The 1-indexed frame number in the `Mp4File` of the first frame in this segment.
|
/// The 1-indexed frame number in the `File` of the first frame in this segment.
|
||||||
first_frame_num: u32,
|
first_frame_num: u32,
|
||||||
num_subtitle_samples: u32,
|
num_subtitle_samples: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mp4Segment {
|
impl Segment {
|
||||||
fn with_index<F, R>(&self, db: &db::Database, f: F) -> Result<R, Error>
|
fn with_index<F, R>(&self, db: &db::Database, f: F) -> Result<R, Error>
|
||||||
where F: FnOnce(&Mp4SegmentIndex) -> Result<R, Error> {
|
where F: FnOnce(&SegmentIndex) -> Result<R, Error> {
|
||||||
let mut i = self.index.borrow_mut();
|
let mut i = self.index.borrow_mut();
|
||||||
if let Some(ref i) = *i {
|
if let Some(ref i) = *i {
|
||||||
return f(i);
|
return f(i);
|
||||||
@ -357,7 +357,7 @@ impl Mp4Segment {
|
|||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_index(&self, db: &db::Database) -> Result<Mp4SegmentIndex, Error> {
|
fn build_index(&self, db: &db::Database) -> Result<SegmentIndex, Error> {
|
||||||
let s = &self.s;
|
let s = &self.s;
|
||||||
let stts_len = mem::size_of::<u32>() * 2 * (s.frames as usize);
|
let stts_len = mem::size_of::<u32>() * 2 * (s.frames as usize);
|
||||||
let stsz_len = mem::size_of::<u32>() * s.frames as usize;
|
let stsz_len = mem::size_of::<u32>() * s.frames as usize;
|
||||||
@ -396,7 +396,7 @@ impl Mp4Segment {
|
|||||||
cmp::min(s.desired_range_90k.end - last_start, dur) as u32);
|
cmp::min(s.desired_range_90k.end - last_start, dur) as u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Mp4SegmentIndex{
|
Ok(SegmentIndex{
|
||||||
buf: buf,
|
buf: buf,
|
||||||
stsz_start: stts_len as u32,
|
stsz_start: stts_len as u32,
|
||||||
stss_start: (stts_len + stsz_len) as u32,
|
stss_start: (stts_len + stsz_len) as u32,
|
||||||
@ -404,10 +404,10 @@ impl Mp4Segment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Mp4FileBuilder {
|
pub struct FileBuilder {
|
||||||
/// Segments of video: one per "recording" table entry as they should
|
/// Segments of video: one per "recording" table entry as they should
|
||||||
/// appear in the video.
|
/// appear in the video.
|
||||||
segments: Vec<Mp4Segment>,
|
segments: Vec<Segment>,
|
||||||
video_sample_entries: SmallVec<[Arc<db::VideoSampleEntry>; 1]>,
|
video_sample_entries: SmallVec<[Arc<db::VideoSampleEntry>; 1]>,
|
||||||
next_frame_num: u32,
|
next_frame_num: u32,
|
||||||
duration_90k: u32,
|
duration_90k: u32,
|
||||||
@ -417,11 +417,11 @@ pub struct Mp4FileBuilder {
|
|||||||
include_timestamp_subtitle_track: bool,
|
include_timestamp_subtitle_track: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The portion of `Mp4FileBuilder` which is mutated while building the body of the file.
|
/// The portion of `FileBuilder` which is mutated while building the body of the file.
|
||||||
/// This is separated out from the rest so that it can be borrowed in a loop over
|
/// This is separated out from the rest so that it can be borrowed in a loop over
|
||||||
/// `Mp4FileBuilder::segments`; otherwise this would cause a double-self-borrow.
|
/// `FileBuilder::segments`; otherwise this would cause a double-self-borrow.
|
||||||
struct BodyState {
|
struct BodyState {
|
||||||
slices: Slices<Slice, Mp4File>,
|
slices: Slices<Slice, File>,
|
||||||
|
|
||||||
/// `self.buf[unflushed_buf_pos .. self.buf.len()]` holds bytes that should be
|
/// `self.buf[unflushed_buf_pos .. self.buf.len()]` holds bytes that should be
|
||||||
/// appended to `slices` before any other slice. See `flush_buf()`.
|
/// appended to `slices` before any other slice. See `flush_buf()`.
|
||||||
@ -429,7 +429,7 @@ struct BodyState {
|
|||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single slice of a `Mp4File`, for use with a `Slices` object. Each slice is responsible for
|
/// A single slice of a `File`, for use with a `Slices` object. Each slice is responsible for
|
||||||
/// some portion of the generated `.mp4` file. The box headers and such are generally in `Static`
|
/// some portion of the generated `.mp4` file. The box headers and such are generally in `Static`
|
||||||
/// or `Buf` slices; the others generally represent a single segment's contribution to the
|
/// or `Buf` slices; the others generally represent a single segment's contribution to the
|
||||||
/// like-named box.
|
/// like-named box.
|
||||||
@ -477,9 +477,9 @@ impl Slice {
|
|||||||
fn p(&self) -> usize { (self.0 >> 44) as usize }
|
fn p(&self) -> usize { (self.0 >> 44) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl slices::Slice<Mp4File> for Slice {
|
impl slices::Slice<File> for Slice {
|
||||||
fn end(&self) -> u64 { return self.0 & 0xFF_FF_FF_FF_FF }
|
fn end(&self) -> u64 { return self.0 & 0xFF_FF_FF_FF_FF }
|
||||||
fn write_to(&self, f: &Mp4File, r: Range<u64>, l: u64, out: &mut io::Write)
|
fn write_to(&self, f: &File, r: Range<u64>, l: u64, out: &mut io::Write)
|
||||||
-> Result<(), Error> {
|
-> Result<(), Error> {
|
||||||
let t = self.t();
|
let t = self.t();
|
||||||
let p = self.p();
|
let p = self.p();
|
||||||
@ -521,7 +521,7 @@ impl ::std::fmt::Debug for Slice {
|
|||||||
fn to_iso14496_timestamp(t: recording::Time) -> u32 { (t.unix_seconds() + 24107 * 86400) as u32 }
|
fn to_iso14496_timestamp(t: recording::Time) -> u32 { (t.unix_seconds() + 24107 * 86400) as u32 }
|
||||||
|
|
||||||
/// Writes a box length for everything appended in the supplied scope.
|
/// Writes a box length for everything appended in the supplied scope.
|
||||||
/// Used only within Mp4FileBuilder::build (and methods it calls internally).
|
/// Used only within FileBuilder::build (and methods it calls internally).
|
||||||
macro_rules! write_length {
|
macro_rules! write_length {
|
||||||
($_self:ident, $b:block) => {{
|
($_self:ident, $b:block) => {{
|
||||||
let len_pos = $_self.body.buf.len();
|
let len_pos = $_self.body.buf.len();
|
||||||
@ -537,9 +537,9 @@ macro_rules! write_length {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mp4FileBuilder {
|
impl FileBuilder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Mp4FileBuilder{
|
FileBuilder{
|
||||||
segments: Vec::new(),
|
segments: Vec::new(),
|
||||||
video_sample_entries: SmallVec::new(),
|
video_sample_entries: SmallVec::new(),
|
||||||
next_frame_num: 1,
|
next_frame_num: 1,
|
||||||
@ -567,7 +567,7 @@ impl Mp4FileBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Appends a segment for (a subset of) the given recording.
|
/// Appends a segment for (a subset of) the given recording.
|
||||||
pub fn append(&mut self, db: &MutexGuard<db::LockedDatabase>, row: db::ListRecordingsRow,
|
pub fn append(&mut self, db: &db::LockedDatabase, row: db::ListRecordingsRow,
|
||||||
rel_range_90k: Range<i32>) -> Result<(), Error> {
|
rel_range_90k: Range<i32>) -> Result<(), Error> {
|
||||||
if let Some(prev) = self.segments.last() {
|
if let Some(prev) = self.segments.last() {
|
||||||
if prev.s.have_trailing_zero {
|
if prev.s.have_trailing_zero {
|
||||||
@ -576,7 +576,7 @@ impl Mp4FileBuilder {
|
|||||||
row.camera_id, row.id, prev.s.camera_id, prev.s.recording_id)));
|
row.camera_id, row.id, prev.s.camera_id, prev.s.recording_id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.segments.push(Mp4Segment{
|
self.segments.push(Segment{
|
||||||
s: recording::Segment::new(db, &row, rel_range_90k)?,
|
s: recording::Segment::new(db, &row, rel_range_90k)?,
|
||||||
index: RefCell::new(None),
|
index: RefCell::new(None),
|
||||||
first_frame_num: self.next_frame_num,
|
first_frame_num: self.next_frame_num,
|
||||||
@ -589,9 +589,9 @@ impl Mp4FileBuilder {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the `Mp4File`, consuming the builder.
|
/// Builds the `File`, consuming the builder.
|
||||||
pub fn build(mut self, db: Arc<db::Database>, dir: Arc<dir::SampleFileDir>)
|
pub fn build(mut self, db: Arc<db::Database>, dir: Arc<dir::SampleFileDir>)
|
||||||
-> Result<Mp4File, Error> {
|
-> Result<File, Error> {
|
||||||
let mut max_end = None;
|
let mut max_end = None;
|
||||||
let mut etag = hash::Hasher::new(hash::MessageDigest::sha1())?;
|
let mut etag = hash::Hasher::new(hash::MessageDigest::sha1())?;
|
||||||
etag.update(&FORMAT_VERSION[..])?;
|
etag.update(&FORMAT_VERSION[..])?;
|
||||||
@ -679,7 +679,7 @@ impl Mp4FileBuilder {
|
|||||||
debug!("Estimated {} buf bytes; actually were {}", EST_BUF_LEN, self.body.buf.len());
|
debug!("Estimated {} buf bytes; actually were {}", EST_BUF_LEN, self.body.buf.len());
|
||||||
}
|
}
|
||||||
debug!("slices: {:?}", self.body.slices);
|
debug!("slices: {:?}", self.body.slices);
|
||||||
Ok(Mp4File{
|
Ok(File{
|
||||||
db: db,
|
db: db,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
segments: self.segments,
|
segments: self.segments,
|
||||||
@ -1110,11 +1110,11 @@ impl BodyState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Mp4File {
|
pub struct File {
|
||||||
db: Arc<db::Database>,
|
db: Arc<db::Database>,
|
||||||
dir: Arc<dir::SampleFileDir>,
|
dir: Arc<dir::SampleFileDir>,
|
||||||
segments: Vec<Mp4Segment>,
|
segments: Vec<Segment>,
|
||||||
slices: Slices<Slice, Mp4File>,
|
slices: Slices<Slice, File>,
|
||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
video_sample_entries: SmallVec<[Arc<db::VideoSampleEntry>; 1]>,
|
video_sample_entries: SmallVec<[Arc<db::VideoSampleEntry>; 1]>,
|
||||||
initial_sample_byte_pos: u64,
|
initial_sample_byte_pos: u64,
|
||||||
@ -1122,7 +1122,7 @@ pub struct Mp4File {
|
|||||||
etag: header::EntityTag,
|
etag: header::EntityTag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mp4File {
|
impl File {
|
||||||
fn write_stts(&self, i: usize, r: Range<u64>, _l: u64, out: &mut io::Write)
|
fn write_stts(&self, i: usize, r: Range<u64>, _l: u64, out: &mut io::Write)
|
||||||
-> Result<(), Error> {
|
-> Result<(), Error> {
|
||||||
self.segments[i].with_index(&self.db, |i| {
|
self.segments[i].with_index(&self.db, |i| {
|
||||||
@ -1187,7 +1187,7 @@ impl Mp4File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl http_entity::Entity<Error> for Mp4File {
|
impl http_entity::Entity<Error> for File {
|
||||||
fn add_headers(&self, hdrs: &mut header::Headers) {
|
fn add_headers(&self, hdrs: &mut header::Headers) {
|
||||||
hdrs.set(header::ContentType("video/mp4".parse().unwrap()));
|
hdrs.set(header::ContentType("video/mp4".parse().unwrap()));
|
||||||
}
|
}
|
||||||
@ -1458,8 +1458,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_mp4_from_db(db: Arc<db::Database>, dir: Arc<dir::SampleFileDir>, skip_90k: i32,
|
pub fn create_mp4_from_db(db: Arc<db::Database>, dir: Arc<dir::SampleFileDir>, skip_90k: i32,
|
||||||
shorten_90k: i32, include_subtitles: bool) -> Mp4File {
|
shorten_90k: i32, include_subtitles: bool) -> File {
|
||||||
let mut builder = Mp4FileBuilder::new();
|
let mut builder = FileBuilder::new();
|
||||||
builder.include_timestamp_subtitle_track(include_subtitles);
|
builder.include_timestamp_subtitle_track(include_subtitles);
|
||||||
let all_time = recording::Time(i64::min_value()) .. recording::Time(i64::max_value());
|
let all_time = recording::Time(i64::min_value()) .. recording::Time(i64::max_value());
|
||||||
{
|
{
|
||||||
@ -1474,7 +1474,7 @@ mod tests {
|
|||||||
builder.build(db, dir).unwrap()
|
builder.build(db, dir).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_mp4(mp4: &Mp4File, dir: &Path) -> String {
|
fn write_mp4(mp4: &File, dir: &Path) -> String {
|
||||||
let mut filename = dir.to_path_buf();
|
let mut filename = dir.to_path_buf();
|
||||||
filename.push("clip.new.mp4");
|
filename.push("clip.new.mp4");
|
||||||
let mut out = fs::OpenOptions::new().write(true).create_new(true).open(&filename).unwrap();
|
let mut out = fs::OpenOptions::new().write(true).create_new(true).open(&filename).unwrap();
|
||||||
@ -1523,9 +1523,9 @@ mod tests {
|
|||||||
/// Makes a `.mp4` file which is only good for exercising the `Slice` logic for producing
|
/// Makes a `.mp4` file which is only good for exercising the `Slice` logic for producing
|
||||||
/// sample tables that match the supplied encoder.
|
/// sample tables that match the supplied encoder.
|
||||||
fn make_mp4_from_encoder(db: &TestDb, encoder: recording::SampleIndexEncoder,
|
fn make_mp4_from_encoder(db: &TestDb, encoder: recording::SampleIndexEncoder,
|
||||||
desired_range_90k: Range<i32>) -> Mp4File {
|
desired_range_90k: Range<i32>) -> File {
|
||||||
let row = db.create_recording_from_encoder(encoder);
|
let row = db.create_recording_from_encoder(encoder);
|
||||||
let mut builder = Mp4FileBuilder::new();
|
let mut builder = FileBuilder::new();
|
||||||
builder.append(&db.db.lock(), row, desired_range_90k).unwrap();
|
builder.append(&db.db.lock(), row, desired_range_90k).unwrap();
|
||||||
builder.build(db.db.clone(), db.dir.clone()).unwrap()
|
builder.build(db.db.clone(), db.dir.clone()).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ use std::ops;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
use std::sync::MutexGuard;
|
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
pub const TIME_UNITS_PER_SEC: i64 = 90000;
|
pub const TIME_UNITS_PER_SEC: i64 = 90000;
|
||||||
@ -359,8 +358,7 @@ impl Segment {
|
|||||||
/// desired start time. (The caller is responsible for creating an edit list to skip the
|
/// desired start time. (The caller is responsible for creating an edit list to skip the
|
||||||
/// undesired portion.) It will end at the first frame after the desired range (unless the
|
/// undesired portion.) It will end at the first frame after the desired range (unless the
|
||||||
/// desired range extends beyond the recording).
|
/// desired range extends beyond the recording).
|
||||||
pub fn new(db: &MutexGuard<db::LockedDatabase>,
|
pub fn new(db: &db::LockedDatabase, recording: &db::ListRecordingsRow,
|
||||||
recording: &db::ListRecordingsRow,
|
|
||||||
desired_range_90k: Range<i32>) -> Result<Segment, Error> {
|
desired_range_90k: Range<i32>) -> Result<Segment, Error> {
|
||||||
let mut self_ = Segment{
|
let mut self_ = Segment{
|
||||||
camera_id: recording.camera_id,
|
camera_id: recording.camera_id,
|
||||||
|
@ -195,7 +195,7 @@ mod tests {
|
|||||||
use h264;
|
use h264;
|
||||||
use recording;
|
use recording;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use stream::{self, Opener, Stream};
|
use stream::{self, Opener, Stream};
|
||||||
use testutil;
|
use testutil;
|
||||||
@ -305,8 +305,7 @@ mod tests {
|
|||||||
is_key: bool,
|
is_key: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_frames(db: &MutexGuard<db::LockedDatabase>, camera_id: i32, recording_id: i32)
|
fn get_frames(db: &db::LockedDatabase, camera_id: i32, recording_id: i32) -> Vec<Frame> {
|
||||||
-> Vec<Frame> {
|
|
||||||
let rec = db.get_recording_playback(camera_id, recording_id).unwrap();
|
let rec = db.get_recording_playback(camera_id, recording_id).unwrap();
|
||||||
let mut it = recording::SampleIndexIterator::new();
|
let mut it = recording::SampleIndexIterator::new();
|
||||||
let mut frames = Vec::new();
|
let mut frames = Vec::new();
|
||||||
|
14
src/web.rs
14
src/web.rs
@ -48,7 +48,7 @@ use std::cmp;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::sync::{Arc,MutexGuard};
|
use std::sync::Arc;
|
||||||
use strutil;
|
use strutil;
|
||||||
use time;
|
use time;
|
||||||
use url::form_urlencoded;
|
use url::form_urlencoded;
|
||||||
@ -245,7 +245,7 @@ impl Handler {
|
|||||||
if json {
|
if json {
|
||||||
serde_json::to_vec(&json::ListCameras{cameras: db.cameras_by_id()})?
|
serde_json::to_vec(&json::ListCameras{cameras: db.cameras_by_id()})?
|
||||||
} else {
|
} else {
|
||||||
self.list_cameras_html(db)?
|
self.list_cameras_html(&db)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
res.headers_mut().set(header::ContentType(if json { JSON.clone() } else { HTML.clone() }));
|
res.headers_mut().set(header::ContentType(if json { JSON.clone() } else { HTML.clone() }));
|
||||||
@ -253,7 +253,7 @@ impl Handler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_cameras_html(&self, db: MutexGuard<db::LockedDatabase>) -> Result<Vec<u8>, Error> {
|
fn list_cameras_html(&self, db: &db::LockedDatabase) -> Result<Vec<u8>, Error> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.extend_from_slice(b"\
|
buf.extend_from_slice(b"\
|
||||||
<!DOCTYPE html>\n\
|
<!DOCTYPE html>\n\
|
||||||
@ -297,7 +297,7 @@ impl Handler {
|
|||||||
.ok_or_else(|| Error::new("no such camera".to_owned()))?;
|
.ok_or_else(|| Error::new("no such camera".to_owned()))?;
|
||||||
serde_json::to_vec(&json::Camera::new(camera, true))?
|
serde_json::to_vec(&json::Camera::new(camera, true))?
|
||||||
} else {
|
} else {
|
||||||
self.camera_html(db, query, uuid)?
|
self.camera_html(&db, query, uuid)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
res.headers_mut().set(header::ContentType(if json { JSON.clone() } else { HTML.clone() }));
|
res.headers_mut().set(header::ContentType(if json { JSON.clone() } else { HTML.clone() }));
|
||||||
@ -305,8 +305,8 @@ impl Handler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn camera_html(&self, db: MutexGuard<db::LockedDatabase>, query: &str,
|
fn camera_html(&self, db: &db::LockedDatabase, query: &str, uuid: Uuid)
|
||||||
uuid: Uuid) -> Result<Vec<u8>, Error> {
|
-> Result<Vec<u8>, Error> {
|
||||||
let (r, trim) = {
|
let (r, trim) = {
|
||||||
let mut time = recording::Time(i64::min_value()) .. recording::Time(i64::max_value());
|
let mut time = recording::Time(i64::min_value()) .. recording::Time(i64::max_value());
|
||||||
let mut trim = false;
|
let mut trim = false;
|
||||||
@ -437,7 +437,7 @@ impl Handler {
|
|||||||
.ok_or_else(|| Error::new("no such camera".to_owned()))?;
|
.ok_or_else(|| Error::new("no such camera".to_owned()))?;
|
||||||
camera.id
|
camera.id
|
||||||
};
|
};
|
||||||
let mut builder = mp4::Mp4FileBuilder::new();
|
let mut builder = mp4::FileBuilder::new();
|
||||||
for (key, value) in form_urlencoded::parse(query.as_bytes()) {
|
for (key, value) in form_urlencoded::parse(query.as_bytes()) {
|
||||||
let (key, value) = (key.borrow(), value.borrow());
|
let (key, value) = (key.borrow(), value.borrow());
|
||||||
match key {
|
match key {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user