Commit Graph

199 Commits

Author SHA1 Message Date
Scott Lamb ce363162f4 trim 16 bytes from each recording::Segment
This reduces the working set by another 960 bytes for a typical one-hour recording, improving cache efficiency a bit more.

8 bytes from SampleIndexIterator:
   * reduce the three "bytes" fields to two. Doing so as "bytes_key" vs
     "bytes_nonkey" slowed it down a bit, perhaps because the "bytes" is
     needed right away and requires a branch. But "bytes" vs "bytes_other"
     seems fine. Looks like it can do this with cmovs in parallel with other
     stuff.
   * stuff "is_key" into the "i" field.

8 bytes from recording::Segment itself:
   * make "frames" and "key_frame" u16s
   * stuff "trailing_zero" into "video_sample_entry_id"
2017-02-27 21:14:06 -08:00
Scott Lamb 15609ddb8e improve build_index performance by 5-10%
I just switched a couple inner loop ?s back to try!(...) to work around
https://github.com/rust-lang/rust/issues/37939
2017-02-26 20:21:46 -08:00
Scott Lamb acb6f8d809 isolated benchmark of building stts/stss/stsz 2017-02-26 20:10:02 -08:00
Scott Lamb f3b17a4bd8 switch to a hyper vendor branch with Nagle fix
There were Nagle's algorithm delays in both the "fresh_client" and
"reuse_client" versions of the .mp4 serving benchmark. Now performance is much
more consistent.
2017-02-26 19:05:05 -08:00
Scott Lamb f24daba299 shrink mp4::Segment 128 -> 112 bytes (on 64-bit)
* don't store sizes of mp4-format sample indexes; recalculate them.
   * keep SampleIndexIterator position as a u32 rather than a usize.

This is 960 bytes for a 60-minute mp4; another small cache usage improvement.
2017-02-26 00:02:49 -08:00
Scott Lamb 21212be18a use associated types for Slice
This is more readable; in particular, it avoids the need for awkward the
PhantomData in the Slices struct.
2017-02-25 18:54:52 -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 0a683b0846 Shrink mp4 file slices from 16 to 8 bytes each
For a one-hour recording, this is about 2 KiB, so a decent chunk of a
Raspberry Pi 2's L1 cache. Generating the Slices and searching/scanning
it should be a bit faster and pollute the cache less.

This is a pretty small optimization now when transferring a decent chunk
of the moov or mdat, but it's easy enough to do. It will be much more
noticeable if I end up interleaving the captions between each key frame.
2017-02-21 19:37:36 -08:00
Scott Lamb c6813bd886 clean up adjust_day implementation
Entry::Occupied has a remove_entry method that allows this to be a little more
readable, and a little more efficient (one btree traversal rather than two).
mmstick on reddit pointed this out:

https://www.reddit.com/r/rust/comments/5tzw5q/how_are_if_else_scopes_are_handled_in_rust/dds0r37/?context=3
2017-02-15 19:16:34 -08:00
Scott Lamb 13c6af45a1 avoid heap allocation reading uuid from sqlite
As described here:
https://github.com/jgallagher/rusqlite/issues/158#issuecomment-277884643
2017-02-13 19:36:05 -08:00
Scott Lamb 5d727a9c83 enforce foreign keys, swap delete order
This came up when I tried using the "bundled" feature of rusqlite. Its build
script passes -DSQLITE_DEFAULT_FOREIGN_KEYS=1, which caused a test to fail.
Fix the bug that this option revealed, and set the pragma so we'll catch
such problems in the future even when using a system library not compiled in
this way.
2017-02-12 20:56:04 -08:00
Scott Lamb b7957edb5a fix "Edit retention" fs capacity calculation
This was completely wrong: it overflowed on large filesystems and
double-counted the used bytes.

The new logic is still imperfect in that if there are a bunch of files in the
process of being deleted (moved from recording to reserved_sample_files but
not yet unlinked), they'll be taken out of the total capacity. Maybe it should
stat everything in the sample file directory instead of relying on the
recording table. It's definitely an improvement, though.
2017-02-12 20:45:46 -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 3314673b8f fix ncurses package names 2017-02-05 21:58:41 -08:00
Scott Lamb 04c124546b update dependencies 2017-02-05 21:22:06 -08:00
Scott Lamb 625c6f807b small dep README.md/prep.sh fixes
These are things that weren't quite right in the comit
c82f038bef.
2017-02-05 20:55:41 -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 c82f038bef new "moonfire-nvr config" subcommand
This is a ncurses-based user interface for configuration. This fills a major
usability gap: the system can be configured without manual SQL commands.
2017-02-05 19:58:41 -08:00
Scott Lamb b3a7795407 update to latest http-entity 2017-01-28 20:10:21 -08:00
Scott Lamb 87de4b4f5c update several dependencies
I left serde alone because uuid hasn't been updated for the new version.
2017-01-27 20:58:04 -08:00
Scott Lamb 168cd743f4 new command to initialize a database 2017-01-17 14:21:13 -08:00
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 02d3bf5e39 better schema.sql comments 2017-01-07 23:11:34 -08:00
Scott Lamb db3d78ba69 better error msg if unable to open sample file dir 2017-01-07 19:48:40 -08:00
Scott Lamb 3e58230813 avoid a SQLite3 sort in list_recordings_by_time
This fixes a minor performance regression for recording lists introduced in
eee887b by ordering by the start_time_90k (the natural order of the
recording_cover index) rather than the composite_id (which requires a sort
pass).

"explain query plan" before:
0|0|0|SEARCH TABLE recording USING INDEX recording_cover (start_time_90k>? AND start_time_90k<?)
0|0|0|USE TEMP B-TREE FOR ORDER BY

after:
0|0|0|SEARCH TABLE recording USING INDEX recording_cover (start_time_90k>? AND start_time_90k<?)

The list_aggregated_recordings algorithm is already designed to work in this
case; see the comments there. I must have forgotten to switch the order by
clause since writing that algorithm.

There's still a sort post-aggregation but that's over less data.
2017-01-07 00:24:53 -08:00
Scott Lamb 6f2b66c406 be robust to crazy timestamps in ffmpeg streams 2017-01-06 23:30:24 -08:00
Scott Lamb cdbcad6c80 add a --check subcommand 2017-01-06 22:54:19 -08:00
Scott Lamb 21b8e0b6df gracefully handle bad video_indexes during upgrade
Dolf reported hitting this problem:

$ sudo -u moonfire-nvr RUST_LOG=info RUST_BACKTRACE=1 release/moonfire-nvr --upgrade
Jan 06 17:10:57.148 INFO Upgrading database from version 0 to version 1...
Jan 06 17:10:57.149 INFO ...database now in journal_mode delete (requested delete).
Jan 06 17:10:57.149 INFO ...from version 0 to version 1
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { description: "zero duration only allowed at end; have 3123 bytes left", cause: None }', /buildslave/rust-buildbot/slave/stable-dist-rustc-cross-host-linux/build/src/libcore/result.rs:837

The indexes were being scanned on upgrade to set the trailing zero flag which
is some sanity checking for /view.mp4 URLs. It's not a big problem to skip it
for some funny recordings to let the update proceed.

Separately, I'll add validation of the pts when writing a recording; it will
report error and end the recording (retrying a second later) rather than write
an unplayable database enty.

Probably also a good time to add a --check to spot database problems such as
this and recording rows without a matching sample file or vice versa.
2017-01-06 20:48:06 -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 586902d30f Merge branch 'new-schema' 2017-01-01 22:59:49 -08:00
Scott Lamb e1cb5f4204 small improvements to schema upgrade instructions 2017-01-01 22:58:27 -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 462d2b9a01 merge rust branch into master
The Rust branch still isn't perfect - in particular, the ffmpeg
dependency is very picky - but it's the future of the project.
2017-01-01 18:38:45 -08:00
Scott Lamb 068890fa8a Improve ClockAdjuster comments 2016-12-30 19:44:41 -08:00
Scott Lamb fb057309f5 slightly simplify local_start logic 2016-12-30 19:35:50 -08:00
Scott Lamb 14461fcad9 bugfix: only double length of first recording 2016-12-30 06:39:09 -08:00
Scott Lamb bca92fbf8d compilation fix for 32-bit arm 2016-12-30 06:35:10 -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 a71f6e66d8 test the new local time logic
The test ensures it solves the problem of the initial buffering throwing off
the start time of the first segment.

Along the way, I tested and fixed the new TrailingZero flag; it wasn't being
set.
2016-12-29 17:14:36 -08:00
Scott Lamb c7443436a5 skip the first rotation
This is as described in design/time.md.
2016-12-29 13:07:25 -08:00
Scott Lamb cc297adc75 clean up Writer interface slightly 2016-12-29 12:33:34 -08:00
Scott Lamb d001e4893c new logic for calculating a recording's start time
This is as described in design/time.md. Other aspects of that design
(including using the monotonic clock and adjusting the durations to compensate
for camera clock frequency error) are not implemented yet. No new tests yet.
Just trying to get some flight miles on these ideas as soon as I can.
2016-12-28 20:56:08 -08:00
Scott Lamb 063708c9ab try again to fix time.md diagram
This time, I've given up on svg and am using png. The inline svg seems to be
totally stripped out by github's markdown->html conversion, and img links
don't work because .svg files are served with an incorrect Content-Type.
2016-12-26 21:41:19 -08:00
Scott Lamb 8ee44efcf2 try to fix some time.md formatting 2016-12-26 21:39:00 -08:00
Scott Lamb f8f7c755ff attempt to fix svg linking 2016-12-26 21:00:42 -08:00
Scott Lamb 5a6cd4e590 new design doc describing approach to time
This is more sophisticated than the current implementation. It's an attempt
to address the problems created by the 9 seconds/day of drift I'm seeing for
long-running streams.
2016-12-26 20:55:43 -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