Commit Graph

19 Commits

Author SHA1 Message Date
Scott Lamb
1e4d7d5ad9 make json api more idiomatic
* camelCase
* lose the "days":null in the overall cameras dict
2017-10-09 21:58:44 -07:00
Scott Lamb
57985079cc bugfix: in /recordings, end_id should be inclusive 2017-10-04 06:36:30 -07:00
Scott Lamb
bd4104b446 add start_id and end_id to .../recordings json
This was added to the API documentation in eee887b9 but never actually
implemented then. It's necessary to actually fetch the .mp4 in question.
2017-10-04 00:00:56 -07:00
Scott Lamb
04e9f3f160 support segmented mp4s
This is intended to support HTML5 Media Source Extensions, which I expect to
be the most practical way to make a good web UI with a proper scrub bar and
such.

This feature has had very limited testing on Chrome and Firefox, and that was
not entirely successful. More work is needed before it's usable, but this
seems like a helpful progress checkpoint.
2017-10-01 15:29:22 -07:00
Scott Lamb
11420df065 update deps (particularly hyper) + fix warnings 2017-09-21 21:51:58 -07:00
Scott Lamb
bebd6ee79a update dependencies
* The mylog update fixes a couple bad bugs.
* Otherwise, just keep up with the Rust ecosystem.
2017-06-11 12:57:55 -07:00
Scott Lamb
4806c62ca1 reuse reqwest client in serve_camera_html bench
This makes a huge difference in the reported time - 863 usec rather than 6
milliseconds on my laptop. Part of the difference is in reqwest client setup
(it apparently initializes a SSL_CTX that is never used in this test), part
fresh connections vs keepalive, part I don't know what. None of it seems
relevant to the logic I want to test.
2017-03-03 22:26:29 -08:00
Scott Lamb
1cf27c189f upgrade to async hyper
serve_generated_bytes is >3X faster. One caveat is that the reactor thread may
stall when reading from the memory-mapped slice. Moonfire NVR is basically a
single-user program, so that may not be so bad, but we'll see.
2017-03-02 19:29:28 -08:00
Scott Lamb
2d0c78a6d8 style improvements
* remove stuttering: mp4::Mp4Foo -> mp4::Foo
* stop using a &MutexGuard<Foo> where a &Foo will do
2017-02-24 21:33:26 -08:00
Scott Lamb
da4e439b9c benchmark camera page, fix broken schema
This page was noticeably slower than necessary because the recording_cover
index wasn't actually covering the query. Both the schema for new databases
and the upgrade query were broken (and not even in the same way).

No new schema version to correct this, at least for now. I'll probably have
another reason to change the schema soon anyway and can throw this in.
2017-02-12 20:37:03 -08:00
Scott Lamb
f97e232131 upgrade dependencies
Rust 1.15+ now supports serde codegen on stable without the build.rs.
Update to serde 0.9 and uuid crate 0.4 to match.
2017-02-05 20:13:51 -08:00
Scott Lamb
a6ec68027a add matching time parsing and formatting routines
* add a --ts subcommand to convert between numeric and human-readable
  representations. This is handy when directly inspecting the SQLite database
  or API output.
* also take the human-readable form in the web interface's camera view.
* to reduce confusion, when using trim=true on the web interface's camera
  view, trim the displayed starting and ending times as well as the actual
  .mp4 file links.
2017-01-12 23:09:02 -08:00
Scott Lamb
0f4c554ec5 improve the camera html page
* sort by newest recording first (even if time jumps backwards), which seems
  more useful / less confusing.

* add a trim=true URL parameter to trim the .mp4s to not extend beyond the
  range in question. Otherwise it's quite difficult to produce such a URL in
  the new s= format: you'd have to manually inspect the database to find the
  precise start time of the recording and do the math by hand.
2017-01-01 22:47:26 -08:00
Scott Lamb
eee887b9a6 schema version 1
The advantages of the new schema are:

* overlapping recordings can be unambiguously described and viewed.
  This is a significant problem right now; the clock on my cameras appears to
  run faster than the (NTP-synchronized) clock on my NVR. Thus, if an
  RTSP session drops and is quickly reconnected, there's likely to be
  overlap.

* less I/O is required to view mp4s when there are multiple cameras.
  This is a pretty dramatic difference in the number of database read
  syscalls with pragma page_size = 1024 (605 -> 39 in one test),
  although I'm not sure how much of that maps to actual I/O wait time.
  That's probably as dramatic as it is due to overflow page chaining.
  But even with larger page sizes, there's an improvement. It helps to
  stop interleaving the video_index fields from different cameras.

There are changes to the JSON API to take advantage of this, described
in design/api.md.

There's an upgrade procedure, described in guide/schema.md.
2016-12-20 22:08:18 -08:00
Scott Lamb
fee4141dc6 replace resource.rs with new http-entity crate
This crate is a slightly-more-polished and MIT-licensed version of
resource.rs. So far it has one advantage: running the tests doesn't
require RUST_TEST_THREADS=1.
2016-12-20 18:29:45 -08:00
Scott Lamb
1865427f75 fully implement json handling as in spec
This is a significant milestone; now the Rust branch matches the C++ branch's
features.

In the process, I switched from using serde_derive (which requires nightly
Rust) to serde_codegen (which does not). It was easier than I thought it'd
be. I'm getting close to no longer requiring nightly Rust.
2016-12-08 21:28:50 -08:00
Scott Lamb
d72feb79bb style: convert try!(...) to ...? in web.rs 2016-12-02 21:46:31 -08:00
Scott Lamb
eb2dadd4f0 test and fix .mp4 generation code
* new, more thorough tests based on a "BoxCursor" which navigates the
  resulting .mp4. This tests everything the C++ code was testing on
  Mp4SamplePieces. And it goes beyond: it tests the actual resulting .mp4
  file, not some internal logic.

* fix recording::Segment::foreach to properly handle a truncated ending.
  Before this was causing a panic.

* get rid of the separate recording::Segment::init method. This was some of
  the first Rust I ever wrote, and I must have thought I couldn't loan it my
  locked database. I can, and that's more clean. Now Segments are never
  half-initialized. Less to test, less to go wrong.

* fix recording::Segment::new to treat a trailing zero duration on a segment
  with a non-zero start in the same way as it does with a zero start. I'm
  still not sure what I'm doing makes sense, but at least it's not
  surprisingly inconsistent.

* add separate, smaller tests of recording::Segment

* address a couple TODOs in the .mp4 code and add missing comments

* change a couple panics on database corruption into cleaner error returns

* increment the etag version given the .mp4 output has changed
2016-12-02 20:40:55 -08:00
Scott Lamb
0a7535536d Rust rewrite
I should have submitted/pushed more incrementally but just played with it on
my computer as I was learning the language. The new Rust version more or less
matches the functionality of the current C++ version, although there are many
caveats listed below.

Upgrade notes: when moving from the C++ version, I recommend dropping and
recreating the "recording_cover" index in SQLite3 to pick up the addition of
the "video_sync_samples" column:

    $ sudo systemctl stop moonfire-nvr
    $ sudo -u moonfire-nvr sqlite3 /var/lib/moonfire-nvr/db/db
    sqlite> drop index recording_cover;
    sqlite3> create index ...rest of command as in schema.sql...;
    sqlite3> ^D

Some known visible differences from the C++ version:

* .mp4 generation queries SQLite3 differently. Before it would just get all
  video indexes in a single query. Now it leads with a query that should be
  satisfiable by the covering index (assuming the index has been recreated as
  noted above), then queries individual recording's indexes as needed to fill
  a LRU cache. I believe this is roughly similar speed for the initial hit
  (which generates the moov part of the file) and significantly faster when
  seeking. I would have done it a while ago with the C++ version but didn't
  want to track down a lru cache library. It was easier to find with Rust.

* On startup, the Rust version cleans up old reserved files. This is as in the
  design; the C++ version was just missing this code.

* The .html recording list output is a little different. It's in ascending
  order, with the most current segment shorten than an hour rather than the
  oldest. This is less ergonomic, but it was easy. I could fix it or just wait
  to obsolete it with some fancier JavaScript UI.

* commandline argument parsing and logging have changed formats due to
  different underlying libraries.

* The JSON output isn't quite right (matching the spec / C++ implementation)
  yet.

Additional caveats:

* I haven't done any proof-reading of prep.sh + install instructions.

* There's a lot of code quality work to do: adding (back) comments and test
  coverage, developing a good Rust style.

* The ffmpeg foreign function interface is particularly sketchy. I'd
  eventually like to switch to something based on autogenerated bindings.
  I'd also like to use pure Rust code where practical, but once I do on-NVR
  motion detection I'll need to existing C/C++ libraries for speed (H.264
  decoding + OpenCL-based analysis).
2016-11-25 14:34:00 -08:00