Commit Graph

13 Commits

Author SHA1 Message Date
Scott Lamb
3af9aeee96 use xsv-style subcommands like "moonfire-nvr run"
This makes it easier to understand which options are valid with each
command.

Additionally, there's more separation of implementations. The most
obvious consequence is that "moonfire-nvr ts ..." no longer uselessly
locks/opens a database.
2017-01-17 12:51:56 -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
c96f306e18 fix up the benchmarks
These are currently the only thing which require a nightly Rust. I haven't run
them since adding the feature gates. The feature gates were slightly broken,
and the actual benchmarks had bitrotted a bit. Fix these things. Also put them
into a separate submodule from the regular tests, so that not as many
feature gates (#[cfg(feature="nightly")]) are required.
2017-01-08 14:22:35 -08:00
Scott Lamb
cdbcad6c80 add a --check subcommand 2017-01-06 22:54:19 -08:00
Scott Lamb
a7e1c9473a extract varint/zigzag stuff to separate module
They can be used for more than recording. In particular, I plan to use these
from the db module for the representation of signals/events.
2017-01-03 10:33:53 -08:00
Scott Lamb
938d8a752f camera clock frequency correction
As described in design/time.md:

* get the realtime-monotonic once at the start of a run and use the
  monotonic clock afterward to avoid problems with local time steps

* on every recording, try to correct the latest local_time_delta at up
  to 500 ppm

Let's see how this works...
2016-12-29 21:05:57 -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
8e499aa070 compile with stable Rust
The benchmarks now require "cargo bench --features=nightly". The
extra #[cfg(nightly)] switches in the code needed for it are a bit
annoying; I may move the benches to a separate directory to avoid this.
But for now, this works.
2016-12-09 22:04:35 -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
678500bc88 stop using a couple unstable features
It would be nice to build on stable Rust. In particular, I'm hitting
compiler bugs in Rust nightly, such at this one:
https://github.com/rust-lang/rust/issues/38177
I imagine beta/stable compilers would be less problematic.

These two features were easy to get rid of:

* alloc was used to get a Box<[u8]> to uninitialized memory.
  Looks like that's possible with Vec.

* box_syntax wasn't actually used at all. (Maybe a leftover from something.)

The remaining features are:

* plugin, for clippy.
  https://github.com/rust-lang/rust/issues/29597
  I could easily gate it with a "nightly" cargo feature.

* proc_macro, for serde_derive.
  https://github.com/rust-lang/rust/issues/35900
  serde does support stable rust, although it's annoying.
  https://serde.rs/codegen-stable.html
  I might just wait a bit; this feature looks like it's getting close to
  stabilization.
2016-12-07 21:05:49 -08:00
Scott Lamb
8df0eae567 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.
2016-12-06 18:41:44 -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