scottlamb / moonfire-nvr Goto Github PK
View Code? Open in Web Editor NEWMoonfire NVR, a security camera network video recorder
License: Other
Moonfire NVR, a security camera network video recorder
License: Other
Hello Scott,
first I'd like to thank you for sharing your awesome work!
I have compiled your project on my Raspberry Pi 3 and it starts well but after configuring my first camera, the moonfire-nvr stops working while opening the input stream. Here is the output:
I0502 172118.091 main moonfire_nvr::db] Loading video sample entries
I0502 172118.091 main moonfire_nvr::db] Loaded 0 video sample entries
I0502 172118.092 main moonfire_nvr::db] Loading cameras
I0502 172118.092 main moonfire_nvr::db] Loaded 1 cameras
I0502 172118.092 main moonfire_nvr::db] Loading recordings for camera Terrasse
I0502 172118.092 main moonfire_nvr::db] Loaded 0 recordings for camera Terrasse
I0502 172118.092 main moonfire_nvr::cmds::run] Database is loaded.
I0502 172118.104 stream-Terrasse moonfire_nvr::streamer] Terrasse: Opening input: rtsp://acrux:[email protected]:8554/acrux-cam-1
I0502 172118.104 main moonfire_nvr::cmds::run] Ready to serve HTTP requests
[rtsp @ 0x73e18000] Estimating duration from bitrate, this may be inaccurate
I0502 172118.616 stream-Terrasse moonfire_nvr::stream] Discarding the first packet to work around https://trac.ffmpeg.org/ticket/5018
I have tried to configure it for serval RTSP streams but it always stops with the same error (I also tried this one: rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov)
I'm using version 1.16.0 (30cf806ef 2017-03-10)
of rustc.
Do you have any idea? If you need any more information please let me know! Thanks a lot!
Regards
Chris
The TUI moonfire-nvr config
is a decent way of configuring the system for now, but long-term I'd like all configuration to be done through the web UI:
Streamer
and Syncer
interfaces in the server don't have any teardown logic, aren't exposed to the web UI in any way, etc.moonfire-nvr config
. I'm thinking a simple CLI for user manipulation which authenticates to the server over a Unix domain socket protected via file permissions or SO_PEERCRED
.The UI dependencies are quite stale. github is giving me security warnings about them (although I think they're more relevant to node-js uses than to what Moonfire NVR is doing). Let's update them.
In theory this is just a yarn update
but if I do that, following builds fail. I imagine the configs need to be reworked in some way, etc. See some previous mention at #62.
$ yarn build
yarn run v1.12.3
$ webpack --mode production --config webpack/prod.config.js
/Users/slamb/git/moonfire-nvr/node_modules/webpack-cli/bin/config-yargs.js:89
describe: optionsSchema.definitions.output.properties.path.description,
^
TypeError: Cannot read property 'properties' of undefined
at module.exports (/Users/slamb/git/moonfire-nvr/node_modules/webpack-cli/bin/config-yargs.js:89:48)
at /Users/slamb/git/moonfire-nvr/node_modules/webpack-cli/bin/webpack.js:60:27
at Object.<anonymous> (/Users/slamb/git/moonfire-nvr/node_modules/webpack-cli/bin/webpack.js:515:3)
at Module._compile (internal/modules/cjs/loader.js:722:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Module.require (internal/modules/cjs/loader.js:658:17)
at require (internal/modules/cjs/helpers.js:22:18)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
I happened to be doing UI development using a proxy to a normally running moonfire instance. Due to coding error the API for recordings was called with start and end time set to null. Rather then producing an appropriate HTTP response (may be 500, or even 404) would have been expected.
Needless to say that the connection reset causes error messages that are unwanted, but it also means API calling code does not get its error path executed.
Sample output:
[HPM] Error occurred while trying to proxy request /api/cameras/1c844181-b807-4b80-83eb-579c8e194451/recordings?startTime90k=null&endTime90k=null&split90k=324000000&_=1520229643233 from localhost:3000 to http://192.168.10.232:8080 (ECONNRESET) (https://nodejs.org/api/errors.html#errors_common_system_errors)
It'd be nice to support audio. I think there are some non-trivial things to work out, though:
recording
rows. In the video index, keep 90 kHz or even less to save storage space. The final frame is implicitly the rest of the duration of the total recording.audio_index
like video_index
..mp4
data structures? how do we represent the interleaving?Currently Moonfire NVR deletes recordings in strict FIFO order. It'd be nice to be able to explicitly say some section of video should be retained; also to have automatically increased retention when there's a motion detection event.
~T~@ ~ ~Main menu ~T~\@ ~ ~T~PT~@ ~T~@
~T~@ ~T~@ ~T~B~T~@ ~T~@ ~T~@ ~T~@ ~T~ ~T~B@ ~T~@ ~
T~@ ~T~@ ~T ~T~B~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~B
~T~Brs ~T~B
~T~B ~T~B
~T~B <Quit> ~T~B
~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@
~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~
T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@ ~T~@
locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8
During a build in a Docker instance, I got test failures on code that was straight from github/master and built and tested fine on my rPi:
failures:
---- db::tests::test_adjust_days stdout ----
thread 'db::tests::test_adjust_days' panicked at 'assertion failed: `(left == right)`
left: `Some(CameraDayValue { recordings: 1, duration: Duration(5400000) })`,
right: `None`', src/db.rs:1521:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
---- db::tests::test_day_bounds stdout ----
thread 'db::tests::test_day_bounds' panicked at 'assertion failed: `(left == right)`
left: `Time(135683424000000)..Time(135691200000000)`,
right: `Time(135685692000000)..Time(135693468000000)`', src/db.rs:1563:9
---- recording::tests::test_format_time stdout ----
thread 'recording::tests::test_format_time' panicked at 'assertion failed: `(left == right)`
left: `"2006-01-02T15:04:05:00000-08:00"`,
right: `"2006-01-02T23:04:05:00000-00:00"`', src/recording.rs:558:9
---- mp4::tests::test_round_trip_with_subtitles stdout ----
thread 'mp4::tests::test_round_trip_with_subtitles' panicked at 'assertion failed: `(left == right)`
left: `"de382684a471f178e4e3a163762711b0653bfd83"`,
right: `"cb5ff51cda4d7dbae05b4a534afd578a0e589570"`', src/mp4.rs:2135:9
---- recording::tests::test_parse_time stdout ----
thread 'recording::tests::test_parse_time' panicked at 'assertion failed: `(left == right)`
left: `102261874050000`,
right: `102259282050000`: parsing 2006-01-02T15:04:05', src/recording.rs:551:13
failures:
db::tests::test_adjust_days
db::tests::test_day_bounds
mp4::tests::test_round_trip_with_subtitles
recording::tests::test_format_time
recording::tests::test_parse_time
test result: FAILED. 43 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out
I realized that the Docker instance was on UTC time. I modified the Docker image to be on America/Los_Angeles and run the build again. This time no errors.
The initial built was run at approximately 2018-03-17 06:00 UTC or 2018-03-16 23:00 PDT, the second successful built approximately 30 minutes later (in case the actual time is relevant).
This makes me suspicious of the test code itself, but it may also point at an actual problem in the Moonfire code.
Found a crash tonight. This is probably an FYI and sort of duplicate of another issue regarding lack of robustness of the server against malformed API urls. At the time of this crash I was experiment with code and may have requested /api/cameras//view.mp4 without any query parameters.
Mar 9 23:23:33 moonfire moonfire-nvr[19022]: syncer moonfire_nvr::db] reserved 76201128-68f3-4ae4-a38d-265aec54a825
Mar 9 23:23:46 moonfire moonfire-nvr[19022]: syncer moonfire_nvr::dir] Back: deleting 10382181 bytes in 1 recordings (8773611 bytes needed)
Mar 9 23:23:46 moonfire moonfire-nvr[19022]: syncer moonfire_nvr::db] reserved 78bc3dda-2f20-4d27-b56f-fb1ced4cf4b8
Mar 9 23:24:01 moonfire moonfire-nvr[19022]: syncer moonfire_nvr::db] reserved 7f276a69-5eab-41a0-b39b-3e6511502f4f
Mar 9 23:24:11 moonfire moonfire-nvr[19022]: thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /checkout/src/libcore/option.rs:335:20
Mar 9 23:24:12 moonfire moonfire-nvr[19022]: stack backtrace:
Mar 9 23:24:12 moonfire moonfire-nvr[19022]: 0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 1: std::sys_common::backtrace::_print
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/sys_common/backtrace.rs:71
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 2: std::panicking::default_hook::{{closure}}
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/sys_common/backtrace.rs:60
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:381
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 3: std::panicking::default_hook
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:397
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 4: std::panicking::rust_panic_with_hook
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:611
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 5: std::panicking::begin_panic
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:572
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 6: std::panicking::begin_panic_fmt
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:522
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 7: rust_begin_unwind
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:498
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 8: core::panicking::panic_fmt
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libcore/panicking.rs:71
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 9: core::panicking::panic
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: at ./checkout/src/libcore/panicking.rs:51
Mar 9 23:24:13 moonfire moonfire-nvr[19022]: 10: moonfire_nvr::mp4::FileBuilder::append_moov
Mar 9 23:24:17 moonfire moonfire-nvr[19022]: syncer moonfire_nvr::dir] Front Right: deleting 22786394 bytes in 1 recordings (15704467 bytes needed)
Mar 9 23:24:17 moonfire moonfire-nvr[19022]: syncer moonfire_nvr::db] reserved 58228b76-59c7-4781-a7d6-2dbe6b6d2f76
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./checkout/src/libcore/macros.rs:32
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at src/mp4.rs:1050
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at src/mp4.rs:1024
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at src/mp4.rs:923
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: 11: moonfire_nvr::mp4::FileBuilder::build
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at src/mp4.rs:856
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: 12: moonfire_nvr::web::ServiceInner::camera_view_mp4
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at src/web.rs:378
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: 13: <tokio_proto::streaming::pipeline::server::Dispatch<S, T, P> as tokio_proto::streaming::pipeline::advanced::Dispatch>::dispatch
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at src/web.rs:467
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/git/checkouts/hyper-d300147022600c0c/c038b24/src/server/mod.rs:480
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/git/checkouts/hyper-d300147022600c0c/c038b24/src/server/mod.rs:335
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-proto-0.1.1/src/streaming/pipeline/server.rs:124
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: 14: <tokio_proto::streaming::pipeline::advanced::Pipeline<T> as futures::future::Future>::poll
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-proto-0.1.1/src/streaming/pipeline/advanced.rs:171
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-proto-0.1.1/src/streaming/pipeline/advanced.rs:121
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-proto-0.1.1/src/streaming/pipeline/advanced.rs:376
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: 15: <futures::future::map_err::MapErr<A, F> as futures::future::Future>::poll
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/future/chain.rs:42
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/future/and_then.rs:32
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/future/map_err.rs:30
Mar 9 23:24:26 moonfire moonfire-nvr[19022]: 16: tokio_core::reactor::Core::poll
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/future/mod.rs:113
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/task_impl/mod.rs:289
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/task_impl/mod.rs:350
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/task_impl/std/mod.rs:79
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/task_impl/mod.rs:350
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.16/src/task_impl/mod.rs:289
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.9/src/reactor/mod.rs:356
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-0.1.0/src/lib.rs:135
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.9/src/reactor/mod.rs:355
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.9/src/reactor/mod.rs:316
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.9/src/reactor/mod.rs:304
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.9/src/reactor/mod.rs:241
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./home/pi/.cargo/git/checkouts/hyper-d300147022600c0c/c038b24/src/server/mod.rs:425
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at src/cmds/run.rs:142
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: 18: moonfire_nvr::main
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at src/main.rs:144
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: 19: __rust_maybe_catch_panic
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./checkout/src/libpanic_unwind/lib.rs:99
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: 20: std::rt::lang_start
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panicking.rs:459
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/panic.rs:361
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: at ./checkout/src/libstd/rt.rs:61
Mar 9 23:24:28 moonfire moonfire-nvr[19022]: 21: __libc_start_main
Mar 9 23:24:28 moonfire systemd[1]: moonfire-nvr.service: main process exited, code=exited, status=101/n/a
Mar 9 23:24:28 moonfire systemd[1]: Unit moonfire-nvr.service entered failed state.
Since 857a66f, Moonfire NVR compiles with ffmpeg 3.x and doesn't segfault, but tests are failing. It looks like the .mp4
output has changed in some fashion (I've only looked at the hashed, not full diffs), and the interpretation of edit lists may have changed.
failures:
---- mp4::tests::test_round_trip_with_shorten stdout ----
thread 'mp4::tests::test_round_trip_with_shorten' panicked at 'assertion failed: `(left == right)`
left: `"e0d28ddf08e24575a82657b1ce0b2da73f32fd88"`,
right: `"c061c644f9f2188be34248da4eda5752bc916001"`', src/mp4.rs:2067:8
note: Run with `RUST_BACKTRACE=1` for a backtrace.
---- mp4::tests::test_round_trip_with_edit_list stdout ----
thread 'mp4::tests::test_round_trip_with_edit_list' panicked at 'assertion failed: `(left == right)`
left: `0`,
right: `1`', src/mp4.rs:1810:12
---- mp4::tests::test_round_trip stdout ----
thread 'mp4::tests::test_round_trip' panicked at 'assertion failed: `(left == right)`
left: `"1e5331e8371bd97ac3158b3a86494abc87cdc70e"`,
right: `"2059a2d0b797cb1b0551c1c1fddb25c788fe13ab"`', src/mp4.rs:2007:8
---- mp4::tests::test_round_trip_with_subtitles stdout ----
thread 'mp4::tests::test_round_trip_with_subtitles' panicked at 'assertion failed: `(left == right)`
left: `"de382684a471f178e4e3a163762711b0653bfd83"`,
right: `"dec3fffbdb453e420dfeb20d37816e54a3936c8b"`', src/mp4.rs:2027:8
failures:
mp4::tests::test_round_trip
mp4::tests::test_round_trip_with_edit_list
mp4::tests::test_round_trip_with_shorten
mp4::tests::test_round_trip_with_subtitles
test result: FAILED. 42 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out
I've written the server-side code to support segmented .mp4
files for HTML5 Media Source Extensions. (design/api.md talks about this.) It may have some bugs but is essentially complete.
The goal was that to use this to create the classic NVR UI where there's a scrub bar at the bottom showing an entire day, it grows over time as new stuff is recorded, and none of this has to wait for huge moov
segments to transfer.
I think this needs some significant work to be viable, though:
.mp4
files. I noticed some of them were working, some weren't. I'm not sure what was different. Maybe related to #43.There needs to be some schema for motion detection events, and ideally some similar things like events from my Elk alarm system. I think it'd just say at this wall time, the signal is "on", "off", or "unknown", with support for long-lived and momentary on events. If the system's wall clock is suspect, the data is useless, and that's okay.
It could be used:
Here's my first idea of schema.
create table signal (
id integer primary key,
uuid blob primary key check (length(uuid) = 16),
-- a uuid describing the originating object, such as the uuid of the camera
-- for built-in motion detection. There will be a JSON interface for adding
-- events; it will require this UUID to be supplied. An external uuid might
-- indicate "my house security system's zone 23".
source_uuid blob not null check (length(uuid) = 16),
-- a uuid describing the type of event. A registry (TBD) will list built-in
-- supported types, such as "Hikvision on-camera motion detection", or
-- "ONVIF on-camera motion detection". External programs can use their own
-- uuids, such as "Elk security system watcher".
type_uuid blob not null check (length(uuid) = 16),
-- a short human-readable description of the event to use in mouseovers or event
-- lists, such as "driveway motion" or "front door open".
short_name not null,
unique (source_uuid, type_uuid)
);
-- Associations between event sources and cameras.
-- For example, if two cameras have overlapping fields of view, they might be
-- configured such that each camera is associated with both its own motion and
-- the other camera's motion.
create table signal_camera (
signal_id integer references signal (id),
camera_id integer references camera (id),
-- type:
--
-- 0 means direct association, as if the event source if the camera's own
-- motion detection. Here are a couple ways this could be used:
--
-- * when viewing the camera, hotkeys to go to the start of the next or
-- previous event should respect this event.
-- * a list of events might include the recordings associated with the
-- camera in the same timespan.
--
-- 1 means indirect association. A screen associated with the camera should
-- given some indication of this event, but there should be no assumption
-- that the camera will have a direct view of the event. For example, all
-- cameras might be indirectly associated with a doorknob press. Cameras at
-- the back of the house shouldn't be expected to have a direct view of this
-- event, but motion events shortly afterward might warrant extra scrutiny.
type integer not null,
primary key (signal_id, camera_id)
) without rowid;
-- State of signals as of a given timestamp.
create table signal_state (
-- seconds since 1970-01-01 00:00:00 UTC.
time_sec integer primary key,
-- Changes at this timestamp, if any.
--
-- It's possible for a single signal to be in both newly_active and either
-- newly_inactive or newly_unknown; this means that the signal is
-- momentarily active.
--
-- The blobs each encode a list of signal ids.
-- They do so as delta-encoded varints. For example,
-- input signals: 1 3 200 (must be sorted)
-- deltas: 1 2 197
-- varint: \x01 \x02 0xc5 0x01
newly_active blob,
newly_inactive blob,
newly_unknown blob,
);
On startup, we'd do a sequential scan of the whole thing and compute the days
map. Need to ensure this doesn't make startup time unreasonable. If it's too bad, we'll need to store the days
map instead, which means ensuring the timezone information doesn't change from run to run, which may not be easy to do. (We'd also have to rows indicating the full state of all signals at some interval, but that's relatively easy.) Or we could switch to a faster database (#44).
I put together all the changes at a single timestamp in one row because I'm imagining there being times when many/all signals change at once, such as on startup or shutdown. This would be more efficient in that scenario.
During normal operation, there should be a bounded amount of IO to do on this. The JSON API for manipulating this should probably let you change a signal's state for no more than a day at a time or some such.
There needs to be a frontend interface to make this useful. The simplest one would be to just show you a expandable thing for each event with all the recordings in it +/- a minute or something.
Related schema change: ideally you could annotate a region of video or an signal-on event or some such with a bit of text.
This is probably the most user-friendly way to bind to privileged ports 80 and 443 on a modern Linux system. (One alternative would be setting up a firewall rule to redirect to 8080/8443 or some such.)
@dolfs found a nice article about it: https://www.darkcoding.net/software/systemd-socket-activation-in-go/. One of the drafts of #15 also sets up the systemd stuff for it. Not mentioned in that article: I think we'd want to use port names so we can distinguish http vs https vs maybe some other future port (rtsp for clients to use? websocket? rpc interface? who knows).
This will be more important after completing #27. Until then, ports 80 and 443 should belong to the proxy server anyway.
yarn install v1.12.3
[1/4] Resolving packages...
[2/4] Fetching packages...
error [email protected]: The engine "node" is incompatible with this module. Expected version ">=4 <=9". Got "11.2.0"
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
IMHO, this is superior to on-camera motion detection (#29) because from what I've seen on-camera motion detection kind of sucks:
on the other hand, on-NVR has more hardware needs (details TBD but significant work to do which scales with the number of cameras) and is much more complex to implement:
Hello,
I am getting a Segfault all the time.
It seems to happen right here:
I0508 232630.200 stream-Auffahrt moonfire_nvr::streamer] Auffahrt: Opening input: rtsp://*:[email protected]:554/unicast
rt_sigaction(SIGTERM, {0x54bde2f4, [], SA_RESTORER|SA_RESTART|SA_SIGINFO|SA_NOCLDSTOP, 0x75d031a0}, {SIG_DFL, [], 0}, 8) = 0
clock_gettime(CLOCK_REALTIME, {1494278790, 201676377}) = 0
clock_gettime(CLOCK_MONOTONIC, {634483, 68003909}) = 0
futex(0x749ff81c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x749ff818, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x749ff7fc, FUTEX_WAKE_PRIVATE, 1) = 1
I0508 232630.201 main moonfire_nvr::cmds::run] Ready to serve HTTP requests
clock_gettime(CLOCK_MONOTONIC, {634483, 68300106}) = 0
epoll_wait(9, {{EPOLLOUT, {u32=4, u64=4}}}, 1024, 0) = 1
clock_gettime(CLOCK_MONOTONIC, {634483, 68471043}) = 0
clock_gettime(CLOCK_MONOTONIC, {634483, 68547137}) = 0
epoll_wait(9, {}, 1024, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {634483, 68773334}) = 0
clock_gettime(CLOCK_MONOTONIC, {634483, 68842761}) = 0
epoll_wait(9, [rtsp @ 0x73e16000] Estimating duration from bitrate, this may be inaccurate
I0508 232634.707 stream-Auffahrt moonfire_nvr::stream] Discarding the first packet to work around https://trac.ffmpeg.org/ticket/5018
<unfinished ...>
+++ killed by SIGSEGV +++
Segmentation fault
The camera is running the fang hacks on a Xiaomi Wifi Cam.
Any ideas what could be missing?
ffmpeg
ffmpeg version 2.8.11 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 4.9.2 (Raspbian 4.9.2-10)
configuration: --arch=armel --target-os=linux --enable-gpl --enable-libx264 --enable-nonfree
libavutil 54. 31.100 / 54. 31.100
libavcodec 56. 60.100 / 56. 60.100
libavformat 56. 40.101 / 56. 40.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 40.101 / 5. 40.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.101 / 1. 2.101
libpostproc 53. 3.100 / 53. 3.100
Kind Regards,
Christoph
This is apparently pulled in by reqwest
.
Just tried to use the config command when (right after building) the samples directory was missing:
/usr/local/bin/moonfire-nvr config
I0302 123829.587 main moonfire_nvr::db] Loading video sample entries
I0302 123829.587 main moonfire_nvr::db] Loaded 0 video sample entries
I0302 123829.587 main moonfire_nvr::db] Loading cameras
I0302 123829.587 main moonfire_nvr::db] Loaded 0 cameras
E0302 123829.588 main moonfire_nvr] Error: unable to open sample file dir /var/lib/moonfire-nvr/sample: No such file or directory (os error 2)
cause: None
This seems to in part defeat the purpose of the config command. I would expect, as long as moonfire has been correctly built, this command to always allow changing of settings.
Could Moonfire support Arlo? Putting aside any debates about the usefulness of non-full-time streaming, it looks like others have decoded RTSP streams in Arlo. Could Moonfire record the Arlo streams?
If you change a stream's video options (for example, its resolution) while Moonfire NVR is running, it doesn't ever recognize the change. It continues recording the video with an incorrect video_sample_entry
. It will show the wrong resolution in the UI and playback will likely not work. (@dolfs reported a pure white recording.)
This should watch for the ffmpeg extra_data
changing or the new SPS/PPS NALs in the H.264 stream (server/src/h264.rs
/ transform_sample_data
) or some such.
SQLite3 is a super-reliable database, was easy to get started with, and is easy to diagnose problems with, but it's not particularly fast. I've noticed in CPU profiles: its locking around column operations, its VM operations, and its prepare steps. The latency for some operations on the Pi2 isn't quite what I'd like it to be. Consider switching to a simpler key/value store, such as:
NOTE: This is sideways related to #25
I was doing some UI development and an attempt at producing an optimized bundle produces source maps in files separate from the bundle itself:
nvr.bundle.js
nvr.bundle.js.gz
nvr.bundle.js.map
#25 mentions the inability to serve the .gz version of the bundle when gzip is offered as acceptable. This would be a little special code in lieu of on-the-fly gzipping.
The issue addressed here is that therein bundle (nvr.bundle.js) attempts to load the source map in a separate request. The request fails with a 404 status. It seems Moonfire filters available static files, possibly by extension? May be not a good idea.
If a request in a url matches an existing file, it should probably be served up, but I can see how a complication would be to have a mapping of extensions to mime types. Perhaps it is as simple, at least for this case, to add something for .map.
I think this is fairly simple to add (very similar to src/h264.rs
) but there are a couple caveats:
video_index
format.It'd be nice to have though. My Dahua camera supports H.265, and I understand it's a significant improvement in video quality per byte.
The current (table-based) UI is meant to be temporary (see #32) but will probably last a while longer.
It's quite unpleasant to use on a phone. Some ideas to improve this:
div#nav
on the left could be a pull-out menu, or just stacked on top rather than on the left. Maybe the column list could be trimmed to the essentials (just start and end time really).As of schema version 3 (a5528e1), it's possible to view recordings before they're flushed to the database. Except...the UI won't let you select the day if it has only unflushed recordings, because they're not reflected in the days
map.
We might want unflushed (or at least growing) recordings to be separate from the main days
map to not interfere with #40 , as they're still changing. (anything unflushed can go away if the system restarts; and growing stuff can change in both duration and starting timestamp.) so possibly put them in a separate map which gets merged in Javascript.
I had to do some work on my Raspberry and shut down moonfire and then took the power off. Although not planned, is later powered up, and interrupted power without a clean shutdown. Either way, once I started up to resume service, the web UI kept showing a latest recording just after 9PM (see attachment) and did not seem to catch up with the actual time which was around 10:40PM. Eventually I clicked on the 9:09PM file and it shows that it contained a recent recording (based on camera time stamp).
So, it seems that in the face of an interruption of recording(s) the time index gets messed up.
Update: After a few hours the index had not corrected. I perform a systemctl stop and then a start and after a few minutes, that seems to have cured the issue.
Realistically speaking any decent NVR must have motion detection. On-camera motion detection is one of the two paths forward. Marking milestone-1.0?
accordingly.
Needs the signals schema (#28). Additionally, needs to speak SOAP in some way:
I'd also considered using Hikvision's simple non-SOAP/ONVIF proprietary protocol, but then Dahua came out with the Starlight camera series, and I bought one...I've even got some code to watch Hikvision camera motion events but it's much less appealing to me now.
A benefit might be that it is easier to create the exact environment needed (dependent library versions etc.). A potential downside is that (a) docker would need to be installed (if not already) and (b) there might be some overhead that is not acceptable on the smallest of systems such as rPi.
During building (8de7e39):
See below output:
$ RUST_TEST_THREADS=1 MOONFIRE_LOG=trace cargo test
Finished dev [unoptimized + debuginfo] target(s) in 0.4 secs
Running target/debug/deps/moonfire_nvr-ea606875e7c62cdf
running 48 tests
test cmds::config::tests::test_decode ... ok
test coding::tests::test_bad_varints ... ok
test coding::tests::test_correct_varints ... ok
test coding::tests::test_zigzag ... ok
test db::tests::test_adjust_days ... ok
test db::tests::test_day_bounds ... ok
test db::tests::test_drop_tx ... I1022 160352.363 db::tests::test_drop_tx moonfire_nvr::db] Loading video sample entries
I1022 160352.364 db::tests::test_drop_tx moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.365 db::tests::test_drop_tx moonfire_nvr::db] Loading cameras
I1022 160352.365 db::tests::test_drop_tx moonfire_nvr::db] Loaded 0 cameras
I1022 160352.368 db::tests::test_drop_tx moonfire_nvr::db] reserved d2b629c0-7662-4a8f-a20a-4300d08db8b8
I1022 160352.370 db::tests::test_drop_tx moonfire_nvr::db] reserved d8f0ad1c-1ef5-4a2c-becf-d5dbc71af2c0
ok
test db::tests::test_fresh_db ... I1022 160352.382 db::tests::test_fresh_db moonfire_nvr::db] Loading video sample entries
I1022 160352.383 db::tests::test_fresh_db moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.383 db::tests::test_fresh_db moonfire_nvr::db] Loading cameras
I1022 160352.384 db::tests::test_fresh_db moonfire_nvr::db] Loaded 0 cameras
ok
test db::tests::test_full_lifecycle ... I1022 160352.398 db::tests::test_full_lifecycle moonfire_nvr::db] Loading video sample entries
I1022 160352.399 db::tests::test_full_lifecycle moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.400 db::tests::test_full_lifecycle moonfire_nvr::db] Loading cameras
I1022 160352.401 db::tests::test_full_lifecycle moonfire_nvr::db] Loaded 1 cameras
I1022 160352.401 db::tests::test_full_lifecycle moonfire_nvr::db] Loading recordings for camera testcam
I1022 160352.402 db::tests::test_full_lifecycle moonfire_nvr::db] Loaded 0 recordings for camera testcam
I1022 160352.405 db::tests::test_full_lifecycle moonfire_nvr::db] reserved 15410fa9-e2c6-42e1-92ea-a24b8760cd4a
I1022 160352.405 db::tests::test_full_lifecycle moonfire_nvr::db] reserved 602ceb37-7fac-4bdb-9378-b0e21e06318c
I1022 160352.425 db::tests::test_full_lifecycle moonfire_nvr::db] Loading video sample entries
I1022 160352.427 db::tests::test_full_lifecycle moonfire_nvr::db] Loaded 1 video sample entries
I1022 160352.427 db::tests::test_full_lifecycle moonfire_nvr::db] Loading cameras
I1022 160352.428 db::tests::test_full_lifecycle moonfire_nvr::db] Loaded 1 cameras
I1022 160352.429 db::tests::test_full_lifecycle moonfire_nvr::db] Loading recordings for camera testcam
I1022 160352.430 db::tests::test_full_lifecycle moonfire_nvr::db] Loaded 1 recordings for camera testcam
ok
test db::tests::test_no_version ... ok
test db::tests::test_version_too_new ... ok
test db::tests::test_version_too_old ... ok
test dir::tests::adjust ... ok
test h264::tests::test_decode ... ok
test h264::tests::test_sample_entry_from_annex_b ... ok
test h264::tests::test_sample_entry_from_avc_decoder_config ... ok
test h264::tests::test_transform_sample_data ... ok
test mp4::tests::test_all_sync_frames ... I1022 160352.509 mp4::tests::test_all_sync_frames moonfire_nvr::db] Loading video sample entries
I1022 160352.509 mp4::tests::test_all_sync_frames moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.510 mp4::tests::test_all_sync_frames moonfire_nvr::db] Loading cameras
I1022 160352.511 mp4::tests::test_all_sync_frames moonfire_nvr::db] Loaded 1 cameras
I1022 160352.511 mp4::tests::test_all_sync_frames moonfire_nvr::db] Loading recordings for camera test camera
I1022 160352.512 mp4::tests::test_all_sync_frames moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160352.513 mp4::tests::test_all_sync_frames moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160352.592 mp4::tests::test_all_sync_frames moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=2..20, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 30,
video_samples: 5,
video_sync_samples: 5,
sample_file_bytes: 45,
run_offset: 0,
flags: 0
}
T1022 160352.596 mp4::tests::test_all_sync_frames moonfire_nvr::db] cache miss for recording 1/1
D1022 160352.597 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] Estimated 21 slices; actually were 21 slices
D1022 160352.598 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] Estimated 2048 buf bytes; actually were 268
D1022 160352.598 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] segments: [
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 1,
start: Time(
128700576000000
),
begin: Some(
SampleIndexIterator {
i_and_is_key: 2147483652,
pos: 3,
start_90k: 2,
duration_90k: 4,
bytes: 6,
bytes_other: 0
}
),
file_end: 30,
desired_range_90k: 2..20,
frames: 3,
key_frames: 3,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 1,
num_subtitle_samples: 0
}
]
D1022 160352.599 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] slices: 21 slices with overall length 704:
i 0: range [ 0, 32) len 32: Static 0
i 1: range [ 32, 68) len 36: Buf 0
i 2: range [ 68, 144) len 76: Static 4
i 3: range [ 144, 188) len 44: Buf 36
i 4: range [ 188, 240) len 52: Static 5
i 5: range [ 240, 288) len 48: Buf 80
i 6: range [ 288, 321) len 33: Static 2
i 7: range [ 321, 325) len 4: Buf 128
i 8: range [ 325, 385) len 60: Static 6
i 9: range [ 385, 409) len 24: Buf 132
i 10: range [ 409, 509) len 100: VideoSampleEntry 0
i 11: range [ 509, 525) len 16: Buf 156
i 12: range [ 525, 549) len 24: Stts 0
i 13: range [ 549, 597) len 48: Buf 172
i 14: range [ 597, 609) len 12: Stsz 0
i 15: range [ 609, 625) len 16: Buf 220
i 16: range [ 625, 633) len 8: Co64 0
i 17: range [ 633, 649) len 16: Buf 236
i 18: range [ 649, 661) len 12: Stss 0
i 19: range [ 661, 677) len 16: Buf 252
i 20: range [ 677, 704) len 27: VideoSampleData 0
T1022 160352.603 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 0's range 0..8 / 32
T1022 160352.604 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /ftyp
T1022 160352.604 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for moov
T1022 160352.604 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 0's range 0..8 / 36
T1022 160352.605 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov
T1022 160352.605 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 0's range 8..16 / 36
T1022 160352.605 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/mvhd
T1022 160352.606 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for trak
T1022 160352.606 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 4..12 / 44
T1022 160352.607 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak
T1022 160352.607 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160352.608 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160352.608 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for tkhd
T1022 160352.608 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 20..21 / 44
T1022 160352.609 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 32..36 / 44
T1022 160352.609 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] found moov/trak/tkhd with id 1; want 1
T1022 160352.609 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for edts
T1022 160352.610 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 48
T1022 160352.610 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia
T1022 160352.610 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160352.611 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160352.611 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for mdia
T1022 160352.612 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 48
T1022 160352.612 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia
T1022 160352.612 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 16..24 / 48
T1022 160352.613 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/mdhd
T1022 160352.613 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for minf
T1022 160352.613 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 2's range 0..8 / 33
T1022 160352.614 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/hdlr
T1022 160352.614 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 128's range 0..4 / 4
T1022 160352.614 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 6's range 0..4 / 60
T1022 160352.615 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf
T1022 160352.615 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 6's range 4..12 / 60
T1022 160352.616 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/vmhd
T1022 160352.616 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for stbl
T1022 160352.616 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 6's range 24..32 / 60
T1022 160352.617 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/dinf
T1022 160352.617 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 132's range 0..8 / 24
T1022 160352.618 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl
T1022 160352.618 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 132's range 8..16 / 24
T1022 160352.618 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsd
T1022 160352.619 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for stts
T1022 160352.619 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 156's range 0..8 / 16
T1022 160352.619 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stts
T1022 160352.620 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] get_all: start=517, len=32
T1022 160352.620 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 156's range 8..16 / 16
T1022 160352.620 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Stts 0's range 0..24 / 24
T1022 160352.621 mp4::tests::test_all_sync_frames moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.621 mp4::tests::test_all_sync_frames moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 2
T1022 160352.622 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for stsz
T1022 160352.622 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 172's range 0..8 / 48
T1022 160352.623 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsc
T1022 160352.623 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 172's range 28..36 / 48
T1022 160352.623 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsz
T1022 160352.624 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] get_all: start=585, len=24
T1022 160352.624 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 172's range 36..48 / 48
T1022 160352.624 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Stsz 0's range 0..12 / 12
T1022 160352.625 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] looking for stss
T1022 160352.625 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 220's range 0..8 / 16
T1022 160352.626 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/co64
T1022 160352.626 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 236's range 0..8 / 16
T1022 160352.626 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stss
T1022 160352.627 mp4::tests::test_all_sync_frames moonfire_nvr::mp4::tests] get_all: start=641, len=20
T1022 160352.627 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 236's range 8..16 / 16
T1022 160352.627 mp4::tests::test_all_sync_frames moonfire_nvr::mp4] getting mp4 slice Stss 0's range 0..12 / 12
ok
test mp4::tests::test_half_sync_frames ... I1022 160352.642 mp4::tests::test_half_sync_frames moonfire_nvr::db] Loading video sample entries
I1022 160352.643 mp4::tests::test_half_sync_frames moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.644 mp4::tests::test_half_sync_frames moonfire_nvr::db] Loading cameras
I1022 160352.645 mp4::tests::test_half_sync_frames moonfire_nvr::db] Loaded 1 cameras
I1022 160352.646 mp4::tests::test_half_sync_frames moonfire_nvr::db] Loading recordings for camera test camera
I1022 160352.647 mp4::tests::test_half_sync_frames moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160352.648 mp4::tests::test_half_sync_frames moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160352.666 mp4::tests::test_half_sync_frames moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=12..20, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 30,
video_samples: 5,
video_sync_samples: 3,
sample_file_bytes: 45,
run_offset: 0,
flags: 0
}
T1022 160352.675 mp4::tests::test_half_sync_frames moonfire_nvr::db] cache miss for recording 1/1
D1022 160352.676 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] Using edit list: [Entry { segment_duration: 8, media_time: 6 }]
D1022 160352.677 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] Estimated 21 slices; actually were 21 slices
D1022 160352.678 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] Estimated 2048 buf bytes; actually were 312
D1022 160352.678 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] segments: [
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 1,
start: Time(
128700576000000
),
begin: Some(
SampleIndexIterator {
i_and_is_key: 2147483654,
pos: 9,
start_90k: 6,
duration_90k: 6,
bytes: 9,
bytes_other: 6
}
),
file_end: 30,
desired_range_90k: 12..20,
frames: 2,
key_frames: 1,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 1,
num_subtitle_samples: 0
}
]
D1022 160352.680 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] slices: 21 slices with overall length 722:
i 0: range [ 0, 32) len 32: Static 0
i 1: range [ 32, 68) len 36: Buf 0
i 2: range [ 68, 144) len 76: Static 4
i 3: range [ 144, 188) len 44: Buf 36
i 4: range [ 188, 240) len 52: Static 5
i 5: range [ 240, 332) len 92: Buf 80
i 6: range [ 332, 365) len 33: Static 2
i 7: range [ 365, 369) len 4: Buf 172
i 8: range [ 369, 429) len 60: Static 6
i 9: range [ 429, 453) len 24: Buf 176
i 10: range [ 453, 553) len 100: VideoSampleEntry 0
i 11: range [ 553, 569) len 16: Buf 200
i 12: range [ 569, 585) len 16: Stts 0
i 13: range [ 585, 633) len 48: Buf 216
i 14: range [ 633, 641) len 8: Stsz 0
i 15: range [ 641, 657) len 16: Buf 264
i 16: range [ 657, 665) len 8: Co64 0
i 17: range [ 665, 681) len 16: Buf 280
i 18: range [ 681, 685) len 4: Stss 0
i 19: range [ 685, 701) len 16: Buf 296
i 20: range [ 701, 722) len 21: VideoSampleData 0
T1022 160352.685 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 0's range 0..8 / 32
T1022 160352.685 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /ftyp
T1022 160352.686 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for moov
T1022 160352.686 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 0's range 0..8 / 36
T1022 160352.687 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov
T1022 160352.687 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 0's range 8..16 / 36
T1022 160352.688 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/mvhd
T1022 160352.688 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for trak
T1022 160352.688 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 4..12 / 44
T1022 160352.689 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak
T1022 160352.689 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160352.690 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160352.690 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for tkhd
T1022 160352.691 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 20..21 / 44
T1022 160352.691 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 32..36 / 44
T1022 160352.692 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] found moov/trak/tkhd with id 1; want 1
T1022 160352.692 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for edts
T1022 160352.692 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 92
T1022 160352.693 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/edts
T1022 160352.693 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160352.694 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160352.694 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for mdia
T1022 160352.694 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 92
T1022 160352.695 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/edts
T1022 160352.695 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 52..60 / 92
T1022 160352.696 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia
T1022 160352.696 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 60..68 / 92
T1022 160352.697 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/mdhd
T1022 160352.697 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for minf
T1022 160352.698 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 2's range 0..8 / 33
T1022 160352.698 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/hdlr
T1022 160352.698 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 172's range 0..4 / 4
T1022 160352.699 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 6's range 0..4 / 60
T1022 160352.699 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf
T1022 160352.700 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 6's range 4..12 / 60
T1022 160352.700 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/vmhd
T1022 160352.701 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for stbl
T1022 160352.701 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Static 6's range 24..32 / 60
T1022 160352.701 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/dinf
T1022 160352.702 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 176's range 0..8 / 24
T1022 160352.702 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl
T1022 160352.703 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 16..24 / 92
T1022 160352.703 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/edts/elst
T1022 160352.704 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for elst
T1022 160352.704 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] get_all: start=264, len=28
T1022 160352.704 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 80's range 24..52 / 92
T1022 160352.705 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 176's range 8..16 / 24
T1022 160352.705 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsd
T1022 160352.706 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for stts
T1022 160352.706 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 200's range 0..8 / 16
T1022 160352.707 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stts
T1022 160352.707 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] get_all: start=561, len=24
T1022 160352.707 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 200's range 8..16 / 16
T1022 160352.708 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Stts 0's range 0..16 / 16
T1022 160352.708 mp4::tests::test_half_sync_frames moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.709 mp4::tests::test_half_sync_frames moonfire_nvr::recording] foreach on recording 1/1: 2 frames, actual_start_90k: 6
T1022 160352.709 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for stsz
T1022 160352.710 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 216's range 0..8 / 48
T1022 160352.710 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsc
T1022 160352.711 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 216's range 28..36 / 48
T1022 160352.711 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsz
T1022 160352.712 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] get_all: start=621, len=20
T1022 160352.712 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 216's range 36..48 / 48
T1022 160352.712 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Stsz 0's range 0..8 / 8
T1022 160352.713 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] looking for stss
T1022 160352.713 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 264's range 0..8 / 16
T1022 160352.714 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/co64
T1022 160352.714 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 280's range 0..8 / 16
T1022 160352.715 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stss
T1022 160352.715 mp4::tests::test_half_sync_frames moonfire_nvr::mp4::tests] get_all: start=673, len=12
T1022 160352.716 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Buf 280's range 8..16 / 16
T1022 160352.716 mp4::tests::test_half_sync_frames moonfire_nvr::mp4] getting mp4 slice Stss 0's range 0..4 / 4
ok
test mp4::tests::test_media_segment ... I1022 160352.733 mp4::tests::test_media_segment moonfire_nvr::db] Loading video sample entries
I1022 160352.734 mp4::tests::test_media_segment moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.734 mp4::tests::test_media_segment moonfire_nvr::db] Loading cameras
I1022 160352.735 mp4::tests::test_media_segment moonfire_nvr::db] Loaded 1 cameras
I1022 160352.736 mp4::tests::test_media_segment moonfire_nvr::db] Loading recordings for camera test camera
I1022 160352.737 mp4::tests::test_media_segment moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160352.738 mp4::tests::test_media_segment moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160352.754 mp4::tests::test_media_segment moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=12..21, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 30,
video_samples: 5,
video_sync_samples: 3,
sample_file_bytes: 45,
run_offset: 0,
flags: 0
}
T1022 160352.758 mp4::tests::test_media_segment moonfire_nvr::db] cache miss for recording 1/1
D1022 160352.759 mp4::tests::test_media_segment moonfire_nvr::mp4] Estimated 21 slices; actually were 4 slices
D1022 160352.760 mp4::tests::test_media_segment moonfire_nvr::mp4] Estimated 2048 buf bytes; actually were 80
D1022 160352.760 mp4::tests::test_media_segment moonfire_nvr::mp4] segments: [
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 1,
start: Time(
128700576000000
),
begin: Some(
SampleIndexIterator {
i_and_is_key: 2147483654,
pos: 9,
start_90k: 6,
duration_90k: 6,
bytes: 9,
bytes_other: 6
}
),
file_end: 45,
desired_range_90k: 12..21,
frames: 3,
key_frames: 2,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 1,
num_subtitle_samples: 0
}
]
D1022 160352.761 mp4::tests::test_media_segment moonfire_nvr::mp4] slices: 4 slices with overall length 188:
i 0: range [ 0, 48) len 48: Buf 0
i 1: range [ 48, 120) len 72: Truns 0
i 2: range [ 120, 152) len 32: Buf 48
i 3: range [ 152, 188) len 36: VideoSampleData 0
T1022 160352.762 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Buf 0's range 0..8 / 48
T1022 160352.763 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /moof
T1022 160352.763 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] looking for mdat
T1022 160352.764 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Buf 48's range 16..24 / 32
T1022 160352.764 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Buf 48's range 24..32 / 32
T1022 160352.765 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /mdat
T1022 160352.765 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] looking for moof
T1022 160352.765 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Buf 0's range 8..16 / 48
T1022 160352.766 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /moof/mfhd
T1022 160352.766 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] looking for traf
T1022 160352.766 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Buf 0's range 24..32 / 48
T1022 160352.767 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /moof/traf
T1022 160352.767 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Buf 0's range 32..40 / 48
T1022 160352.768 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /moof/traf/tfhd
T1022 160352.768 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] looking for trun
T1022 160352.768 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 0..8 / 72
T1022 160352.769 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.769 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.770 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /moof/traf/trun
T1022 160352.770 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 12..16 / 72
T1022 160352.770 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.771 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.771 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 16..20 / 72
T1022 160352.772 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.772 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.772 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 20..24 / 72
T1022 160352.773 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.773 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.774 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 24..28 / 72
T1022 160352.774 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.774 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.775 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 28..32 / 72
T1022 160352.775 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.776 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.776 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 32..36 / 72
T1022 160352.776 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.777 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.777 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 36..40 / 72
T1022 160352.778 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.778 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.779 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 40..48 / 72
T1022 160352.779 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.779 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.780 mp4::tests::test_media_segment moonfire_nvr::mp4::tests] positioned at /moof/traf/trun
T1022 160352.780 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 52..56 / 72
T1022 160352.781 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.781 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.781 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 56..60 / 72
T1022 160352.782 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.782 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.783 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 60..64 / 72
T1022 160352.783 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.783 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.784 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 64..68 / 72
T1022 160352.784 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.785 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
T1022 160352.785 mp4::tests::test_media_segment moonfire_nvr::mp4] getting mp4 slice Truns 0's range 68..72 / 72
T1022 160352.785 mp4::tests::test_media_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.786 mp4::tests::test_media_segment moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 6
ok
test mp4::tests::test_multi_segment ... I1022 160352.802 mp4::tests::test_multi_segment moonfire_nvr::db] Loading video sample entries
I1022 160352.803 mp4::tests::test_multi_segment moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.804 mp4::tests::test_multi_segment moonfire_nvr::db] Loading cameras
I1022 160352.805 mp4::tests::test_multi_segment moonfire_nvr::db] Loaded 1 cameras
I1022 160352.805 mp4::tests::test_multi_segment moonfire_nvr::db] Loading recordings for camera test camera
I1022 160352.806 mp4::tests::test_multi_segment moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160352.807 mp4::tests::test_multi_segment moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160352.823 mp4::tests::test_multi_segment moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=3..6, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 6,
video_samples: 3,
video_sync_samples: 2,
sample_file_bytes: 6,
run_offset: 0,
flags: 0
}
T1022 160352.827 mp4::tests::test_multi_segment moonfire_nvr::db] cache miss for recording 1/1
T1022 160352.832 mp4::tests::test_multi_segment moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=0..4, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 2,
duration_90k: 9,
video_samples: 2,
video_sync_samples: 1,
sample_file_bytes: 9,
run_offset: 0,
flags: 0
}
T1022 160352.836 mp4::tests::test_multi_segment moonfire_nvr::db] cache miss for recording 1/2
D1022 160352.837 mp4::tests::test_multi_segment moonfire_nvr::mp4] Estimated 25 slices; actually were 25 slices
D1022 160352.838 mp4::tests::test_multi_segment moonfire_nvr::mp4] Estimated 2048 buf bytes; actually were 280
D1022 160352.838 mp4::tests::test_multi_segment moonfire_nvr::mp4] segments: [
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 1,
start: Time(
128700576000000
),
begin: Some(
SampleIndexIterator {
i_and_is_key: 2147483654,
pos: 3,
start_90k: 3,
duration_90k: 3,
bytes: 3,
bytes_other: 2
}
),
file_end: 6,
desired_range_90k: 3..6,
frames: 1,
key_frames: 1,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 1,
num_subtitle_samples: 0
},
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 2,
start: Time(
128700576000000
),
begin: Some(
SampleIndexIterator {
i_and_is_key: 2147483650,
pos: 0,
start_90k: 0,
duration_90k: 4,
bytes: 4,
bytes_other: 0
}
),
file_end: 4,
desired_range_90k: 0..4,
frames: 1,
key_frames: 1,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 2,
num_subtitle_samples: 0
}
]
D1022 160352.840 mp4::tests::test_multi_segment moonfire_nvr::mp4] slices: 25 slices with overall length 688:
i 0: range [ 0, 32) len 32: Static 0
i 1: range [ 32, 68) len 36: Buf 0
i 2: range [ 68, 144) len 76: Static 4
i 3: range [ 144, 188) len 44: Buf 36
i 4: range [ 188, 240) len 52: Static 5
i 5: range [ 240, 288) len 48: Buf 80
i 6: range [ 288, 321) len 33: Static 2
i 7: range [ 321, 325) len 4: Buf 128
i 8: range [ 325, 385) len 60: Static 6
i 9: range [ 385, 409) len 24: Buf 132
i 10: range [ 409, 509) len 100: VideoSampleEntry 0
i 11: range [ 509, 525) len 16: Buf 156
i 12: range [ 525, 533) len 8: Stts 0
i 13: range [ 533, 541) len 8: Stts 1
i 14: range [ 541, 601) len 60: Buf 172
i 15: range [ 601, 605) len 4: Stsz 0
i 16: range [ 605, 609) len 4: Stsz 1
i 17: range [ 609, 625) len 16: Buf 232
i 18: range [ 625, 641) len 16: Co64 0
i 19: range [ 641, 657) len 16: Buf 248
i 20: range [ 657, 661) len 4: Stss 0
i 21: range [ 661, 665) len 4: Stss 1
i 22: range [ 665, 681) len 16: Buf 264
i 23: range [ 681, 684) len 3: VideoSampleData 0
i 24: range [ 684, 688) len 4: VideoSampleData 1
T1022 160352.844 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Static 0's range 0..8 / 32
T1022 160352.845 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /ftyp
T1022 160352.845 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] looking for moov
T1022 160352.846 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 0's range 0..8 / 36
T1022 160352.846 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov
T1022 160352.847 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 0's range 8..16 / 36
T1022 160352.847 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/mvhd
T1022 160352.847 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] looking for trak
T1022 160352.848 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 36's range 4..12 / 44
T1022 160352.848 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak
T1022 160352.848 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160352.849 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160352.849 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] looking for mdia
T1022 160352.850 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 48
T1022 160352.850 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia
T1022 160352.850 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 80's range 16..24 / 48
T1022 160352.851 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/mdhd
T1022 160352.851 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] looking for minf
T1022 160352.851 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Static 2's range 0..8 / 33
T1022 160352.852 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/hdlr
T1022 160352.852 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 128's range 0..4 / 4
T1022 160352.852 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Static 6's range 0..4 / 60
T1022 160352.853 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf
T1022 160352.853 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Static 6's range 4..12 / 60
T1022 160352.854 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/vmhd
T1022 160352.854 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] looking for stbl
T1022 160352.854 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Static 6's range 24..32 / 60
T1022 160352.855 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/dinf
T1022 160352.855 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 132's range 0..8 / 24
T1022 160352.856 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl
T1022 160352.856 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 132's range 8..16 / 24
T1022 160352.856 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsd
T1022 160352.857 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] looking for stss
T1022 160352.857 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 156's range 0..8 / 16
T1022 160352.857 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stts
T1022 160352.858 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 172's range 0..8 / 60
T1022 160352.858 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsc
T1022 160352.859 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 172's range 40..48 / 60
T1022 160352.859 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stsz
T1022 160352.859 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 232's range 0..8 / 16
T1022 160352.860 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/co64
T1022 160352.860 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 248's range 0..8 / 16
T1022 160352.860 mp4::tests::test_multi_segment moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl/stss
T1022 160352.861 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Buf 248's range 12..16 / 16
T1022 160352.861 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Stss 0's range 0..4 / 4
T1022 160352.862 mp4::tests::test_multi_segment moonfire_nvr::db] cache hit for recording 1/1
T1022 160352.862 mp4::tests::test_multi_segment moonfire_nvr::recording] foreach on recording 1/1: 1 frames, actual_start_90k: 3
T1022 160352.863 mp4::tests::test_multi_segment moonfire_nvr::mp4] getting mp4 slice Stss 1's range 0..4 / 4
T1022 160352.863 mp4::tests::test_multi_segment moonfire_nvr::db] cache hit for recording 1/2
T1022 160352.863 mp4::tests::test_multi_segment moonfire_nvr::recording] foreach on recording 1/2: 1 frames, actual_start_90k: 0
ok
test mp4::tests::test_round_trip ... I1022 160352.878 mp4::tests::test_round_trip moonfire_nvr::db] Loading video sample entries
I1022 160352.879 mp4::tests::test_round_trip moonfire_nvr::db] Loaded 0 video sample entries
I1022 160352.879 mp4::tests::test_round_trip moonfire_nvr::db] Loading cameras
I1022 160352.880 mp4::tests::test_round_trip moonfire_nvr::db] Loaded 1 cameras
I1022 160352.881 mp4::tests::test_round_trip moonfire_nvr::db] Loading recordings for camera test camera
I1022 160352.882 mp4::tests::test_round_trip moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160352.883 mp4::tests::test_round_trip moonfire_nvr::dir] test camera: have remaining quota of 1048576
I1022 160352.970 mp4::tests::test_round_trip moonfire_ffmpeg] Initialized ffmpeg. Versions:
avcodec compiled=56.60.100 running=56.1.0
avformat compiled=56.40.101 running=56.1.0
avutil compiled=54.31.100 running=54.3.0
W1022 160352.976 mp4::tests::test_round_trip moonfire_nvr::stream] While opening URL file:src/testdata/clip.mp4, some options were not understood: advanced_editlist=false
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x73eabd00] max_analyze_duration 5000000 reached
D1022 160353.015 mp4::tests::test_round_trip moonfire_nvr::stream] Video stream index is 0
I1022 160353.017 mp4::tests::test_round_trip moonfire_nvr::dir] Committing extra transaction because there's no cached uuid
I1022 160353.018 mp4::tests::test_round_trip moonfire_nvr::db] reserved 4d92ba20-77fa-45ce-8b77-d7c65698f025
FAILED
test mp4::tests::test_round_trip_with_edit_list ... I1022 160353.049 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] Loading video sample entries
I1022 160353.050 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.051 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] Loading cameras
D1022 160353.052 syncer moonfire_nvr::dir] test camera: have remaining quota of 1036339
I1022 160353.052 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] Loaded 1 cameras
I1022 160353.053 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.054 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.055 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::dir] test camera: have remaining quota of 1048576
I1022 160353.057 syncer moonfire_nvr::db] reserved a62b385b-f6e7-4e75-971d-8b8cfd515ae2
W1022 160353.061 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::stream] While opening URL file:src/testdata/clip.mp4, some options were not understood: advanced_editlist=false
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x742abd00] max_analyze_duration 5000000 reached
D1022 160353.099 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::stream] Video stream index is 0
I1022 160353.101 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::dir] Committing extra transaction because there's no cached uuid
I1022 160353.102 mp4::tests::test_round_trip_with_edit_list moonfire_nvr::db] reserved c0d93fd1-8997-4978-93d2-5d2b8f07d77f
FAILED
test mp4::tests::test_round_trip_with_shorten ... I1022 160353.191 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] Loading video sample entries
I1022 160353.192 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.192 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] Loading cameras
I1022 160353.193 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] Loaded 1 cameras
I1022 160353.194 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.195 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.196 mp4::tests::test_round_trip_with_shorten moonfire_nvr::dir] test camera: have remaining quota of 1048576
D1022 160353.196 syncer moonfire_nvr::dir] test camera: have remaining quota of 1036339
I1022 160353.199 syncer moonfire_nvr::db] reserved 44123158-e3fe-41a4-8892-eb64ad1f309d
W1022 160353.202 mp4::tests::test_round_trip_with_shorten moonfire_nvr::stream] While opening URL file:src/testdata/clip.mp4, some options were not understood: advanced_editlist=false
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x74691a00] max_analyze_duration 5000000 reached
D1022 160353.239 mp4::tests::test_round_trip_with_shorten moonfire_nvr::stream] Video stream index is 0
I1022 160353.241 mp4::tests::test_round_trip_with_shorten moonfire_nvr::dir] Committing extra transaction because there's no cached uuid
I1022 160353.242 mp4::tests::test_round_trip_with_shorten moonfire_nvr::db] reserved acb4a23e-a48a-41f6-85e6-f639ac908e11
FAILED
test mp4::tests::test_round_trip_with_subtitles ... I1022 160353.268 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] Loading video sample entries
I1022 160353.269 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.270 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] Loading cameras
I1022 160353.271 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] Loaded 1 cameras
I1022 160353.271 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.272 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.273 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::dir] test camera: have remaining quota of 1048576
D1022 160353.335 syncer moonfire_nvr::dir] test camera: have remaining quota of 1036339
I1022 160353.339 syncer moonfire_nvr::db] reserved 941d95ef-e53b-4b4d-b6cd-764004c5d6ea
W1022 160353.339 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::stream] While opening URL file:src/testdata/clip.mp4, some options were not understood: advanced_editlist=false
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x73ea0100] max_analyze_duration 5000000 reached
D1022 160353.376 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::stream] Video stream index is 0
I1022 160353.378 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::dir] Committing extra transaction because there's no cached uuid
I1022 160353.379 mp4::tests::test_round_trip_with_subtitles moonfire_nvr::db] reserved 0f9a65eb-d1d3-44a7-a001-0bdc32edca50
FAILED
test mp4::tests::test_zero_duration_recording ... I1022 160353.408 mp4::tests::test_zero_duration_recording moonfire_nvr::db] Loading video sample entries
I1022 160353.409 mp4::tests::test_zero_duration_recording moonfire_nvr::db] Loaded 0 video sample entries
D1022 160353.409 syncer moonfire_nvr::dir] test camera: have remaining quota of 1036339
I1022 160353.410 mp4::tests::test_zero_duration_recording moonfire_nvr::db] Loading cameras
I1022 160353.411 mp4::tests::test_zero_duration_recording moonfire_nvr::db] Loaded 1 cameras
I1022 160353.411 mp4::tests::test_zero_duration_recording moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.412 mp4::tests::test_zero_duration_recording moonfire_nvr::db] Loaded 0 recordings for camera test camera
I1022 160353.412 syncer moonfire_nvr::db] reserved d54ef9c0-12b9-44f5-a09c-7b2f2bcaad77
D1022 160353.413 mp4::tests::test_zero_duration_recording moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160353.422 mp4::tests::test_zero_duration_recording moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=1..5, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 5,
video_samples: 2,
video_sync_samples: 1,
sample_file_bytes: 3,
run_offset: 0,
flags: 0
}
T1022 160353.426 mp4::tests::test_zero_duration_recording moonfire_nvr::db] cache miss for recording 1/1
T1022 160353.430 mp4::tests::test_zero_duration_recording moonfire_nvr::recording] recording::Segment::new fast path, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 2,
duration_90k: 0,
video_samples: 1,
video_sync_samples: 1,
sample_file_bytes: 3,
run_offset: 0,
flags: 0
}
D1022 160353.435 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] Using edit list: [Entry { segment_duration: 4, media_time: 1 }]
D1022 160353.436 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] Estimated 25 slices; actually were 25 slices
D1022 160353.436 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] Estimated 2048 buf bytes; actually were 324
D1022 160353.436 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] segments: [
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 1,
start: Time(
128700576000000
),
begin: Some(
SampleIndexIterator {
i_and_is_key: 2147483650,
pos: 0,
start_90k: 0,
duration_90k: 2,
bytes: 1,
bytes_other: 0
}
),
file_end: 3,
desired_range_90k: 1..5,
frames: 2,
key_frames: 1,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 1,
num_subtitle_samples: 0
},
mp4::Segment {
s: Segment {
camera_id: 1,
recording_id: 2,
start: Time(
128700576000000
),
begin: None,
file_end: 3,
desired_range_90k: 0..0,
frames: 1,
key_frames: 1,
video_sample_entry_id_and_trailing_zero: 1
},
first_frame_num: 3,
num_subtitle_samples: 0
}
]
D1022 160353.438 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] slices: 25 slices with overall length 743:
i 0: range [ 0, 32) len 32: Static 0
i 1: range [ 32, 68) len 36: Buf 0
i 2: range [ 68, 144) len 76: Static 4
i 3: range [ 144, 188) len 44: Buf 36
i 4: range [ 188, 240) len 52: Static 5
i 5: range [ 240, 332) len 92: Buf 80
i 6: range [ 332, 365) len 33: Static 2
i 7: range [ 365, 369) len 4: Buf 172
i 8: range [ 369, 429) len 60: Static 6
i 9: range [ 429, 453) len 24: Buf 176
i 10: range [ 453, 553) len 100: VideoSampleEntry 0
i 11: range [ 553, 569) len 16: Buf 200
i 12: range [ 569, 585) len 16: Stts 0
i 13: range [ 585, 593) len 8: Stts 1
i 14: range [ 593, 653) len 60: Buf 216
i 15: range [ 653, 661) len 8: Stsz 0
i 16: range [ 661, 665) len 4: Stsz 1
i 17: range [ 665, 681) len 16: Buf 276
i 18: range [ 681, 697) len 16: Co64 0
i 19: range [ 697, 713) len 16: Buf 292
i 20: range [ 713, 717) len 4: Stss 0
i 21: range [ 717, 721) len 4: Stss 1
i 22: range [ 721, 737) len 16: Buf 308
i 23: range [ 737, 740) len 3: VideoSampleData 0
i 24: range [ 740, 743) len 3: VideoSampleData 1
T1022 160353.442 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Static 0's range 0..8 / 32
T1022 160353.443 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /ftyp
T1022 160353.443 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for moov
T1022 160353.444 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 0's range 0..8 / 36
T1022 160353.444 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov
T1022 160353.444 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 0's range 8..16 / 36
T1022 160353.445 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/mvhd
T1022 160353.445 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for trak
T1022 160353.446 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 36's range 4..12 / 44
T1022 160353.446 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak
T1022 160353.446 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160353.447 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160353.447 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for tkhd
T1022 160353.448 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 36's range 20..21 / 44
T1022 160353.448 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 36's range 32..36 / 44
T1022 160353.448 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] found moov/trak/tkhd with id 1; want 1
T1022 160353.449 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for edts
T1022 160353.449 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 92
T1022 160353.449 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/edts
T1022 160353.450 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 36's range 12..20 / 44
T1022 160353.450 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/tkhd
T1022 160353.451 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for mdia
T1022 160353.451 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 8..16 / 92
T1022 160353.451 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/edts
T1022 160353.452 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 52..60 / 92
T1022 160353.452 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia
T1022 160353.452 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 60..68 / 92
T1022 160353.453 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/mdhd
T1022 160353.453 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for minf
T1022 160353.453 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Static 2's range 0..8 / 33
T1022 160353.454 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/hdlr
T1022 160353.454 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 172's range 0..4 / 4
T1022 160353.455 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Static 6's range 0..4 / 60
T1022 160353.455 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf
T1022 160353.455 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Static 6's range 4..12 / 60
T1022 160353.456 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/vmhd
T1022 160353.456 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for stbl
T1022 160353.457 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Static 6's range 24..32 / 60
T1022 160353.457 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/dinf
T1022 160353.457 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 176's range 0..8 / 24
T1022 160353.458 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/mdia/minf/stbl
T1022 160353.458 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 16..24 / 92
T1022 160353.459 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] positioned at /moov/trak/edts/elst
T1022 160353.459 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4::tests] looking for elst
T1022 160353.459 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 28..32 / 92
T1022 160353.460 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 32..40 / 92
T1022 160353.460 mp4::tests::test_zero_duration_recording moonfire_nvr::mp4] getting mp4 slice Buf 80's range 40..48 / 92
ok
test recording::tests::test_display_duration ... ok
test recording::tests::test_encode_example ... ok
test recording::tests::test_format_time ... ok
test recording::tests::test_iterator_errors ... ok
test recording::tests::test_parse_time ... ok
test recording::tests::test_round_trip ... ok
test recording::tests::test_segment_clipping_with_all_sync ... I1022 160353.688 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] Loading video sample entries
I1022 160353.689 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.690 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] Loading cameras
I1022 160353.691 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] Loaded 1 cameras
I1022 160353.691 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.692 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.693 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160353.773 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=2..20, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 30,
video_samples: 5,
video_sync_samples: 5,
sample_file_bytes: 45,
run_offset: 0,
flags: 0
}
T1022 160353.778 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] cache miss for recording 1/1
T1022 160353.779 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::db] cache hit for recording 1/1
T1022 160353.779 recording::tests::test_segment_clipping_with_all_sync moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 2
ok
test recording::tests::test_segment_clipping_with_half_sync ... I1022 160353.795 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] Loading video sample entries
I1022 160353.796 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.797 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] Loading cameras
I1022 160353.798 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] Loaded 1 cameras
I1022 160353.799 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.799 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.801 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160353.819 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=12..20, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 30,
video_samples: 5,
video_sync_samples: 3,
sample_file_bytes: 45,
run_offset: 0,
flags: 0
}
T1022 160353.827 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] cache miss for recording 1/1
T1022 160353.829 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::db] cache hit for recording 1/1
T1022 160353.829 recording::tests::test_segment_clipping_with_half_sync moonfire_nvr::recording] foreach on recording 1/1: 2 frames, actual_start_90k: 6
ok
test recording::tests::test_segment_clipping_with_trailing_zero ... I1022 160353.845 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] Loading video sample entries
I1022 160353.846 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.847 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] Loading cameras
I1022 160353.848 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] Loaded 1 cameras
I1022 160353.848 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.849 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.850 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160353.869 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=1..2, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 2,
video_samples: 3,
video_sync_samples: 3,
sample_file_bytes: 6,
run_offset: 0,
flags: 0
}
T1022 160353.873 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] cache miss for recording 1/1
T1022 160353.874 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::db] cache hit for recording 1/1
T1022 160353.875 recording::tests::test_segment_clipping_with_trailing_zero moonfire_nvr::recording] foreach on recording 1/1: 2 frames, actual_start_90k: 1
ok
test recording::tests::test_segment_fast_path ... I1022 160353.891 recording::tests::test_segment_fast_path moonfire_nvr::db] Loading video sample entries
I1022 160353.892 recording::tests::test_segment_fast_path moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.892 recording::tests::test_segment_fast_path moonfire_nvr::db] Loading cameras
I1022 160353.893 recording::tests::test_segment_fast_path moonfire_nvr::db] Loaded 1 cameras
I1022 160353.894 recording::tests::test_segment_fast_path moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.894 recording::tests::test_segment_fast_path moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160353.895 recording::tests::test_segment_fast_path moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160353.974 recording::tests::test_segment_fast_path moonfire_nvr::recording] recording::Segment::new fast path, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 30,
video_samples: 5,
video_sync_samples: 3,
sample_file_bytes: 45,
run_offset: 0,
flags: 0
}
T1022 160353.978 recording::tests::test_segment_fast_path moonfire_nvr::db] cache miss for recording 1/1
T1022 160353.979 recording::tests::test_segment_fast_path moonfire_nvr::recording] foreach on recording 1/1: 5 frames, actual_start_90k: 0
ok
test recording::tests::test_segment_fast_path_with_trailing_zero ... I1022 160353.995 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] Loading video sample entries
I1022 160353.996 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] Loaded 0 video sample entries
I1022 160353.997 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] Loading cameras
I1022 160353.998 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] Loaded 1 cameras
I1022 160353.998 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] Loading recordings for camera test camera
I1022 160353.999 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160354.000 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160354.020 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::recording] recording::Segment::new fast path, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 2,
video_samples: 3,
video_sync_samples: 3,
sample_file_bytes: 6,
run_offset: 0,
flags: 0
}
T1022 160354.024 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::db] cache miss for recording 1/1
T1022 160354.025 recording::tests::test_segment_fast_path_with_trailing_zero moonfire_nvr::recording] foreach on recording 1/1: 3 frames, actual_start_90k: 0
ok
test recording::tests::test_segment_zero_desired_duration ... I1022 160354.041 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] Loading video sample entries
I1022 160354.042 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] Loaded 0 video sample entries
I1022 160354.043 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] Loading cameras
I1022 160354.044 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] Loaded 1 cameras
I1022 160354.044 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] Loading recordings for camera test camera
I1022 160354.045 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160354.046 recording::tests::test_segment_zero_desired_duration moonfire_nvr::dir] test camera: have remaining quota of 1048576
T1022 160354.066 recording::tests::test_segment_zero_desired_duration moonfire_nvr::recording] recording::Segment::new slow path, desired_range_90k=0..0, recording=ListRecordingsRow {
start: Time(
128700576000000
),
video_sample_entry: VideoSampleEntry {
data: [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
rfc6381_codec: "avc1.000000",
id: 1,
width: 1920,
height: 1080,
sha1: [
237,
74,
119,
209,
181,
106,
17,
137,
56,
120,
143,
197,
48,
55,
117,
155,
108,
80,
30,
61
]
},
camera_id: 1,
id: 1,
duration_90k: 1,
video_samples: 1,
video_sync_samples: 1,
sample_file_bytes: 1,
run_offset: 0,
flags: 0
}
T1022 160354.070 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] cache miss for recording 1/1
T1022 160354.071 recording::tests::test_segment_zero_desired_duration moonfire_nvr::db] cache hit for recording 1/1
T1022 160354.072 recording::tests::test_segment_zero_desired_duration moonfire_nvr::recording] foreach on recording 1/1: 1 frames, actual_start_90k: 0
ok
test slices::tests::at_end ... ok
test slices::tests::everything ... ok
test slices::tests::exact_slice ... ok
test slices::tests::offset_first ... ok
test slices::tests::offset_mid ... ok
test slices::tests::size ... ok
test streamer::tests::basic ... W1022 160354.082 streamer::tests::basic moonfire_nvr::stream] While opening URL file:src/testdata/clip.mp4, some options were not understood: advanced_editlist=false
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x74696f00] max_analyze_duration 5000000 reached
D1022 160354.119 streamer::tests::basic moonfire_nvr::stream] Video stream index is 0
I1022 160354.133 streamer::tests::basic moonfire_nvr::db] Loading video sample entries
I1022 160354.134 streamer::tests::basic moonfire_nvr::db] Loaded 0 video sample entries
I1022 160354.134 streamer::tests::basic moonfire_nvr::db] Loading cameras
I1022 160354.136 streamer::tests::basic moonfire_nvr::db] Loaded 1 cameras
I1022 160354.136 streamer::tests::basic moonfire_nvr::db] Loading recordings for camera test camera
I1022 160354.137 streamer::tests::basic moonfire_nvr::db] Loaded 0 recordings for camera test camera
D1022 160354.138 streamer::tests::basic moonfire_nvr::dir] test camera: have remaining quota of 1048576
I1022 160354.214 streamer::tests::basic moonfire_nvr::streamer] test camera: Opening input: rtsp://foo:redacted@test-camera/main
T1022 160354.214 streamer::tests::basic moonfire_nvr::streamer::tests] MockOpener returning next stream
D1022 160354.216 streamer::tests::basic moonfire_nvr::streamer] test camera: video_sample_entry_id=1
D1022 160354.216 streamer::tests::basic moonfire_nvr::streamer] test camera: have first key frame
I1022 160354.217 streamer::tests::basic moonfire_nvr::dir] Committing extra transaction because there's no cached uuid
I1022 160354.217 streamer::tests::basic moonfire_nvr::db] reserved 439ef972-f328-4b70-9724-be8adccf1cbd
T1022 160354.219 streamer::tests::basic moonfire_nvr::streamer] test camera: write on normal rotation
I1022 160354.220 streamer::tests::basic moonfire_nvr::dir] Committing extra transaction because there's no cached uuid
I1022 160354.221 streamer::tests::basic moonfire_nvr::db] reserved 60a88837-d333-4217-ba65-669dfe3818fd
W1022 160354.222 streamer::tests::basic moonfire_nvr::streamer] test camera: sleeping for Duration { secs: 1, nanos: 0 } after error: Error: ffmpeg: End of file
cause: Some(Error(-1606004923))
I1022 160354.223 streamer::tests::basic moonfire_nvr::streamer] test camera: Opening input: rtsp://foo:redacted@test-camera/main
T1022 160354.223 streamer::tests::basic moonfire_nvr::streamer::tests] MockOpener shutting down
W1022 160354.224 streamer::tests::basic moonfire_nvr::streamer] test camera: sleeping for Duration { secs: 1, nanos: 0 } after error: Error: done
cause: None
I1022 160354.224 streamer::tests::basic moonfire_nvr::streamer] test camera: shutting down
D1022 160354.234 syncer moonfire_nvr::dir] test camera: have remaining quota of 1040301
I1022 160354.237 syncer moonfire_nvr::db] reserved 43236800-de46-4087-b28f-5dd62680bcac
D1022 160354.257 syncer moonfire_nvr::dir] test camera: have remaining quota of 1036339
T1022 160354.261 streamer::tests::basic moonfire_nvr::db] cache miss for recording 1/1
T1022 160354.262 streamer::tests::basic moonfire_nvr::db] cache miss for recording 1/2
ok
test strutil::tests::dehex_errors ... ok
test strutil::tests::round_trip ... ok
test web::tests::test_segments ... ok
failures:
---- mp4::tests::test_round_trip stdout ----
thread 'mp4::tests::test_round_trip' panicked at 'unexpected input error: End of file', src/mp4.rs:1778:28
note: Run with `RUST_BACKTRACE=1` for a backtrace.
---- mp4::tests::test_round_trip_with_edit_list stdout ----
thread 'mp4::tests::test_round_trip_with_edit_list' panicked at 'unexpected input error: End of file', src/mp4.rs:1778:28
---- mp4::tests::test_round_trip_with_shorten stdout ----
thread 'mp4::tests::test_round_trip_with_shorten' panicked at 'unexpected input error: End of file', src/mp4.rs:1778:28
---- mp4::tests::test_round_trip_with_subtitles stdout ----
thread 'mp4::tests::test_round_trip_with_subtitles' panicked at 'unexpected input error: End of file', src/mp4.rs:1778:28
failures:
mp4::tests::test_round_trip
mp4::tests::test_round_trip_with_edit_list
mp4::tests::test_round_trip_with_shorten
mp4::tests::test_round_trip_with_subtitles
test result: FAILED. 44 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--bin moonfire-nvr'
pi@moonfire:~/moonfire-nvr$
It'd be nice to have a way to explicitly delete a particular segment of video (potentially long before it's the oldest video), for example to redact some private event.
Drop ffmpeg's libavformat for RTSP. Use a pure Rust RTSP library instead. None seems to exist today, so probably write one.
Why?
CSeq
and such) may or may not be due to ffmpeg problems; we haven't fully diagnosed them (see eg #114).0xABAC
ONVIF RTP extension and RTCP sender reports.We'll still want ffmpeg's libavcodec for H.264 decoding for on-NVR video analytics, although that could happen in a separate process than the main moonfire-nvr
one.
I want Moonfire to be a good Internet-facing webserver.
In the meantime, we have a guide for setting up a proxy in front: Security Moonfire NVR and exposing it to the Internet.
I want to serve everything over https, ideally automatically setting up new key pairs via letsencrypt + the acme-client crate.
I'd love it if someone were to write a crate (or integrate into some framework like rocket) something that uses acme-client, hyper, and a storage hook just make sure the http port responds to the challenges and the https port uses the certificate it gets. Moonfire NVR would plug in a storage hook that puts stuff in the SQLite database. This would be by far the slickest way to do https.
Consider enabling HTTP Strict Transport Security. Maybe a pref for that.
There's an ffmpeg bug when a camera has audio enabled. I'll quote the troubleshooting guide below. Either we need this ffmpeg bug fixed (and the fixed version bundled with Moonfire NVR) or we need to switch RTSP libraries.
Error: pts not monotonically increasing; got 26615520 then 26539470
If your streams cut out with an error message like this one, there are a couple possibilities.
One is that your camera outputs B frames. If you believe this is the case, file a feature request; Moonfire NVR currently doesn't support B frames. You may be able to configure your camera to disable B frames in the meantime.
A more subtle problem occurs in cameras such as the Dahua Starlight series when the following is true:
Moonfire NVR currently uses the ffmpeg library to talk to the cameras. ffmpeg doesn't properly support this situation. It uses the NTP time to adjust the PTS and DTS, and thus experiences jumps forward and backward. The forward jumps cause one frame to be artificially lengthened. The backward jumps create an impossible situation which causes Moonfire NVR to abort the session and retry.
In the long term, Moonfire NVR will likely implement its own RTSP support.
In the short term, you can use either of two workarounds:
I tried to startup and received the following in the log file:
Oct 22 16:49:50 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loading video sample entries
Oct 22 16:49:50 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loaded 4 video sample entries
Oct 22 16:49:50 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loading cameras
Oct 22 16:49:50 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loaded 4 cameras
Oct 22 16:49:50 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loading recordings for camera Front Left
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loaded 12781 recordings for camera Front Left
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loading recordings for camera Front Right
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loaded 11659 recordings for camera Front Right
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loading recordings for camera Side
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loaded 11527 recordings for camera Side
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loading recordings for camera Back
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::db] Loaded 11908 recordings for camera Back
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: main moonfire_nvr::cmds::run] Database is loaded.
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: thread 'main' panicked at 'unable to read localtime symlink: Error { repr: Os { code: 22, message: "Invalid argument" } }', /checkout/src/libcore/result.rs:906:4
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: stack backtrace:
Oct 22 16:49:51 moonfire moonfire-nvr[27295]: 0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
Oct 22 16:49:52 moonfire moonfire-nvr[27295]: at ./checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
Oct 22 16:49:52 moonfire moonfire-nvr[27295]: 1: std::sys_common::backtrace::_print
Oct 22 16:49:52 moonfire moonfire-nvr[27295]: at ./checkout/src/libstd/sys_common/backtrace.rs:71
It turns out that on my Raspbian Jesse system, /etc/localtime
is a copy of the required file from /usr/share/zoneinfo
and not a symlink to it. Seems to me that the code should be able to handle either scheme.
When I changed the situation, by hand, to be a symlink, startup became possible.
My Dahua Starlight camera has an option called "smart codec" which I haven't ever tried. I'm a little afraid it will enable B-frames (which Moonfire NVR currently doesn't support) or some such. I should try this to see if it actually works.
In order to allow UI development from a system that is not the moonfire-nvr server itself CORS headers would need to be added as appropriately. Sample code for this can be found here in one of the later comments.
At this time it might make sense to simply allow origin "any" or (* in the header) since the API is unsecured anyway. In future we may need to think about this more.
Without this support, running the ui code from, let's say localhost:3000 will not allow API access and, effectively, makes development hard. It is possible, in Safari for example, to disable cross domain policy enforcement through the develop menu, but that disables it across the board, which is rather unsafe if you forget to put it back, or browse dangerous sites in the meanwhile.
Moonfire NVR is supposed to minimize the number of flushes of the (on-SSD) SQLite3 database. The stream
table has the flush_if_sec
field to support deferring flushes after completing a recording, in the hopes that some other stream flushes in the meantime and the two flushes can be coalesced.
-- Flush the database when the first instant of completed recording is this
-- many seconds old. A value of 0 means that every completed recording will
-- cause an immediate flush. Higher values may allow flushes to be combined,
-- reducing SSD write cycles. For example, if all streams have a flush_if_sec
-- >= x sec, there will be:
--
-- * at most one flush per x sec in total
-- * at most x sec of completed but unflushed recordings per stream.
-- * at most x completed but unflushed recordings per stream, in the worst
-- case where a recording instantly fails, waits the 1-second retry delay,
-- then fails again, forever.
flush_if_sec integer not null,
For the most part, this works. But see this log snippet:
Jan 04 05:45:21 odroid.home.slamb.org moonfire-nvr[2005]: sync-/var/lib/moonfire-nvr/sample-8tb moonfire_db::db] Flush (why: 10 sec after start of 1 minute driveway-main recording): added 2 recordings, deleted 1, marked 3 files GCed.
Jan 04 05:45:26 odroid.home.slamb.org moonfire-nvr[2005]: sync-/var/lib/moonfire-nvr/sample-6tb moonfire_db::db] Flush (why: 180 sec after start of 59 seconds garage-main recording): added 1 recordings, deleted 0, marked 1 files GCed.
The second line's why
doesn't make sense. The recording it's referring to should have already been added in the previous flush (if not before). The problem is that I have two sample file dirs, therefore two syncers. Each syncer independently computes next_flush
and doesn't update it when something else causes a flush. This was fine when there was only syncer but not anymore.
Hi,
I attempted a fresh install on a new Ubuntu 18.04 environment from the master branch. script/build.sh went fine until this:
./scripts/script-functions.sh: line 292: /home/kristopher/code/moonfire-nvr/src/schema.sql: No such file or directory
and during startup:
Apr 30 08:23:16 Sal systemd[1]: Started Moonfire NVR.
Apr 30 08:23:16 Sal moonfire-nvr[16201]: main moonfire_nvr] SqliteFailure(Error { code: CannotOpen, extended_code: 14 }, Some("unable to open database file"))
Apr 30 08:23:16 Sal moonfire-nvr[16201]: stack backtrace:
I saw that schema.sql was removed from src, so I ran this command:
sudo -u moonfire-nvr sqlite3 ~moonfire-nvr/db/db < ~/code/moonfire-nvr/db/schema.sql
After which, the syslog returned:
Apr 30 08:29:08 Sal systemd[1]: Started Moonfire NVR.
Apr 30 08:29:08 Sal moonfire-nvr[17050]: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: QueryReturnedNoRows
Apr 30 08:29:08 Sal moonfire-nvr[17050]: stack backtrace:
Apr 30 08:29:08 Sal moonfire-nvr[17050]: 0: 0x55f82da4626e - backtrace::backtrace::libunwind::trace::hd98210360bf7305b
Attempting to run the config yeilds:
kristopher@Sal:~/code/moonfire-nvr$ sudo -u moonfire-nvr moonfire-nvr config
E0430 084330.569 main moonfire_nvr] QueryReturnedNoRows
Unfortunately I am stuck here and cannot get the NVR to load. Please advise. Thanks!
Dolf pointed out that a misconfiguration would be easier to diagnose this way; systemctl status would immediately reveal the problem.
Compiling Rust code on ARM is really really slow. I've seen cases where my Pi2 simply can't do it due to lack of RAM. Figure out how to cross-compile Moonfire NVR from x86-64 to ARM and write up instructions.
I've done some work / wrote down some notes in a Google doc but haven't gotten a fully working setup.
Hello Scott,
How to get the live stream of the video on the web browser form all the camera that are configured.
Current status: functional but some features missing:
moonfire-nvr config
for usersmoonfire-nvr login
command to make a new session from the CLI (mostly for tools to use)Varies: cookie
or whatever headers to ensure authenticated and unauthenticated requests don't get mixed up in caches.__Host
+ SameSite=strict
) when using tls. currently it uses Secure; SameSite=Lax
. (Update: I'm happy with the status quo.)--trust-forward-hdrs
are working together properly.yarn start
) but shouldn't ever be served in production. Maybe restrict via the Host
header.Original issue text:
I want proper user authentication; this (along with some manner of https) is a precondition of exposing Moonfire NVR to the Internet.
As @dolfs said, a temporary measure could be to do basic HTTP with a apache/nginx frontend. But I think it shouldn't be too bad to do a proper built-in thing.
Here's my proposal.
https is a prerequisite. (either built-in or through a proxy.)
You can create/delete/modify users through moonfire-nvr config
.
Creating a session could be simply password-based. Some things that I consider out of scope:
Sessions could simply be a long random number, stored as a hash for the same reason people hash passwords: so a database leak doesn't trivially compromise the credentials. (They should need to edit the database for to gain access, which may be harder to do than getting an old backup, and which leaves more evidence behind.)
Straw man schema:
create table users (
id integer primary key,
username unique not null,
-- If set, a hash for password authentication, as generated by `libpasta::hash_password`.
password_hash text,
password_id integer not null default 0, -- increasing with password sets/clears.
password_failure_count integer not null, -- updated lazily; reset when password_id incremented.
-- If set, a Unix UID that is accepted for authentication when using HTTP over
-- a Unix domain socket. (Additionally, the UID running Moonfire NVR can authenticate
-- as anyone; there's no point in trying to do otherwise.) This might be an easy
-- bootstrap method once configuration happens through a web UI rather than text UI.
unix_uid integer
);
create table user_sessions (
user_id integer references user (id),
hashed_session_id blob unique not null, -- hash function TBD
creation_password_id integer not null, -- the id it was created from
creation_peer_addr blob not null, -- IPv4 or IPv6 address
creation_time integer not null, -- sec since epoch
creation_user_agent text,
revocation_time integer, -- likewise
description text, -- probably a device name
last_use_time integer, -- updated lazily on flush
use_count not null -- likewise
);
Typical sessions should probably be represented as cookies with the HttpOnly
flag set (meaning not accessible to Javascript). If a hit on /api/...
lacks the cookie, it should return a HTTP 401 which the Javascript knows means to redirect the browser to /login
, a simple HTML login form which on success sets the cookie and redirects back.
The cookies should also be secure
(meaning only sent over https, not http).
There should also be a way of getting a session id for use by some automated thing. Example: a program that dumps events into the database based on my Elk security system's zone status. Something you can paste into its config file. Better to have separate, high-entropy credentials where possible so you can see what was compromised and disable it independently of the others.
I briefly examined the actual H.264 bytestream via aizvorski/h264bitstream and found some suspect things. I believe the video samples I store and the .mp4
s I serve include sps/pps information, for example, even though this is redundant with the video_sample_entry
.
It's a small thing, but I keep lots of Chrome tabs open and have trouble finding the Moonfire one because there's no favicon. Make one. Probably red (to match the name moonfire) and some fitting imagery, such as:
It'd be nice to have a larger logo as well for display on the UI, the main page, maybe in the future an icon for phone apps. But better to have a just a favicon for now than nothing.
Using web pack, as we do, it is easy to generate duplicates of various bundles that are gzip-ed and have a name that is identical except for an additional suffix of .gz.
If a request comes in that contains the "Accept-Encoding: gzip" header, it would be nice if we would serve up any .gz version of a resource, if it exists. This does not require building on-the-fly gzip capability into the server.
It would come at the cost of an extra stat call to see if the gz resource exists unless we also have the server build a resource map at startup. Probably not important enough performance wise for now.
If one of the sample file dirs is on a completely full filesystem, currently Moonfire NVR will fail to start, as it's not able to write a new meta.tmp
file (and then rename it to meta
).
A couple scenarios for how this can happen:
moonfire-nvr
to just recover with no additional manual work. It almost does except for this meta.tmp
write failure. (If you manually garbage-collect a single recording, it can write the new meta and recover.)moonfire-nvr config
and shrink it.I have a few ideas for how to improve this.
garbage
database table, and any files for each stream with recording_id >= stream.next_recording_id
are already allowed to be gone, so they could be deleted before updating the open
for the database or the directory.meta.tmp
file. Maybe as a final step of the open process, a new meta.tmp
file can be created with padding, so that if the disk later fills, truncating this allows a new one to be opened. This would be sort of best-effort (if the disk fills at just the wrong moment, it can't be written, so it doesn't help) but would make the problem much less likely.meta.tmp
file. Instead, assume overwriting a single block is atomic. (I believe this is true, but I'd like to find a good reference first. There's some discussion on this stackoverflow thread but it doesn't look conclusive/authoritative.) Maybe alter the metadata format to have a length prefix, then the serialized DirMeta
message, then padding up to 512 bytes.Here's an example failure, on a system running commit 95a8c2e or so.
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: main moonfire_nvr] IoError(Os { code: 28, kind: Other, message: "No space left on device" })
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: stack backtrace:
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 0: failure::backtrace::internal::InternalBacktrace::new::h66f8c54ff6056b4a (0x8e656b)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/internal.rs:44
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 1: failure::backtrace::Backtrace::new::h876f056a50fcd631 (0x8e6863)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/mod.rs:111
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: <failure::backtrace::Backtrace as core::default::Default>::default::h40dae9253a7b436e
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/mod.rs:125
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 2: <failure::error::error_impl::ErrorImpl as core::convert::From<F>>::from::h6e632e49444aaccb (0x606cab)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/error/error_impl.rs:19
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: <failure::error::Error as core::convert::From<F>>::from::he33a5f69ebf4c896
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/error/mod.rs:36
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: moonfire_db::dir::write_meta::hb48f16c36842bd03
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at db/dir.rs:168
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 3: moonfire_db::dir::SampleFileDir::write_meta::h3b85e404c7496dd7 (0x607217)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at db/dir.rs:265
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: moonfire_db::dir::SampleFileDir::open::h5aac33e4d93872e9
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at db/dir.rs:190
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 4: moonfire_db::db::LockedDatabase::open_sample_file_dirs::h22ab4350ae969510 (0x5e2097)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at db/db.rs:1009
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 5: moonfire_nvr::cmds::run::run::h81b1d3717bd60175 (0x4c8557)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/cmds/run.rs:183
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 6: moonfire_nvr::cmds::Command::run::h0abbf4ae1ce453a0 (0x4e1a1f)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/cmds/mod.rs:62
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 7: moonfire_nvr::main::h44bb0b191820bbe6 (0x48f727)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/main.rs:108
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 8: std::rt::lang_start::{{closure}}::h5016b2e0fefece16 (0x458b4b)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at /rustc/4a45578bc58ff262864f72680cc02e83f5d2f5b3/src/libstd/rt.rs:74
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 9: std::rt::lang_start_internal::{{closure}}::h506a35c73ad6511f (0x9053b3)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/libstd/rt.rs:59
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: std::panicking::try::do_call::hae1763164ad427b9
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/libstd/panicking.rs:306
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 10: __rust_maybe_catch_panic (0x90f04f)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/libpanic_unwind/lib.rs:102
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 11: std::panicking::try::h1a3656077a003cfd (0x905d43)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/libstd/panicking.rs:285
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: std::panic::catch_unwind::h96042a7830ee1a37
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/libstd/panic.rs:398
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: std::rt::lang_start_internal::h383433ce5e1a9852
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: at src/libstd/rt.rs:58
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 12: main (0x48fb5b)
Jan 28 06:02:14 odroid.home.slamb.org moonfire-nvr[935]: 13: __libc_start_main (0xb58d6fe5)
When I set up multiple sample file dirs, I started getting errors like the one below in which:
This happens when there's no flush between Writer::collect_garbage
completing and starting again. Its call to delete_garbage
doesn't immediately remove it from garbage
(not until the next flush). So the next call tries to unlink it again (which fails) and then calls delete_garbage
on it again (which will eventually result in the transaction failing because the second delete
reports the row doesn't exist).
collect_garbage
happens in the post-flush notification, so there usually is a flush between each call. But the notification is asynchronous via a channel so this isn't actually guaranteed when other syncers can also fire flushes at a time it's not expecting.
The solution is pretty simple: make delete_garbage
immediately remove it from garbage
. Currently there's a garbage
(everything in the garbage row) and a to_gc
(things that should be removed from it on the next transaction). Instead, do a garbage_needs_unlink
and a garbage_unlinked
which are mutually exclusive.
Nov 28 14:57:26 ...: sync-/var/lib/moonfire-nvr/sample-6tb moonfire_db::writer] 6: deleting 30070712 bytes in 1 recordings (18927767 bytes needed)
Nov 28 14:57:50 ...: sync-/var/lib/moonfire-nvr/sample-6tb moonfire_db::db] Flush (why: 90 sec after start of 1 minute 5 seconds garage-main recording): added 5 recordings, deleted 1, marked 0 files GCed.
Nov 28 14:57:50 ...: sync-/var/lib/moonfire-nvr/sample-8tb moonfire_db::db] Flush (why: 90 sec after start of 1 minute 20 seconds courtyard-sub recording): added 0 recordings, deleted 0, marked 0 files GCed.
Nov 28 14:57:50 ...: sync-/var/lib/moonfire-nvr/sample-6tb moonfire_db::writer] dir: recording 6/622053 already deleted!
Nov 28 14:57:52 ...: sync-/var/lib/moonfire-nvr/sample-8tb moonfire_db::writer] 11: deleting 5348864 bytes in 1 recordings (4447102 bytes needed)
Nov 28 14:57:53 ...: sync-/var/lib/moonfire-nvr/sample-8tb moonfire_db::writer] flush failure on save for reason 90 sec after start of 1 minute 32 seconds driveway-sub recording; will retry after PT60S: ErrorMessage { msg: "no garbage row for 6/622053" }
Nov 28 14:57:53 ...: stack backtrace:
Nov 28 14:57:53 ...: 0: 0x81398f - backtrace::backtrace::libunwind::trace::h3efbb541b1fd4a89
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/libunwind.rs:53
Nov 28 14:57:53 ...: - backtrace::backtrace::trace::he86533e63137b32d
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/mod.rs:42
Nov 28 14:57:53 ...: 1: 0x812f1f - backtrace::capture::Backtrace::new_unresolved::h1e0ea6bd8272aa64
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/capture.rs:88
Nov 28 14:57:53 ...: 2: 0x812747 - failure::backtrace::internal::InternalBacktrace::new::hf30e7136ac39a801
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/internal.rs:44
Nov 28 14:57:53 ...: 3: 0x812a2b - failure::backtrace::Backtrace::new::hbe74d198a344a1b6
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/mod.rs:111
Nov 28 14:57:53 ...: - <failure::backtrace::Backtrace as core::default::Default>::default::h74085fe416c7ca1f
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/mod.rs:125
Nov 28 14:57:53 ...: 4: 0x812a43 - failure::backtrace::Backtrace::new::hbe74d198a344a1b6
Nov 28 14:57:53 ...: 5: 0x5b918b - <failure::error::error_impl::ErrorImpl as core::convert::From<F>>::from::hf5461434cf9cbad6
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/error/error_impl.rs:19
Nov 28 14:57:53 ...: - <failure::error::Error as core::convert::From<F>>::from::h9373489268132011
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/error/mod.rs:36
Nov 28 14:57:53 ...: - failure::error_message::err_msg::ha9648b9e3acef653
Nov 28 14:57:53 ...: at /home/slamb/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/error_message.rs:12
Nov 28 14:57:53 ...: - moonfire_db::raw::mark_sample_files_deleted::hd912400c9861c3a1
Nov 28 14:57:53 ...: at db/raw.rs:297
Nov 28 14:57:53 ...: 6: 0x4b829b - moonfire_db::db::LockedDatabase::flush::h3dc2c842b26129c2
Nov 28 14:57:53 ...: at /home/slamb/git/moonfire-nvr/db/db.rs:850
Nov 28 14:57:53 ...: 7: 0x509c67 - <moonfire_db::db::DatabaseGuard<'db, C>>::flush::h7b1c01d01aa74d02
Nov 28 14:57:53 ...: at /home/slamb/git/moonfire-nvr/db/db.rs:1883
Nov 28 14:57:53 ...: - <moonfire_db::writer::Syncer<C, D>>::flush::h3b5933ac754e19e8
Nov 28 14:57:53 ...: at /home/slamb/git/moonfire-nvr/db/writer.rs:454
Nov 28 14:57:53 ...: - <moonfire_db::writer::Syncer<C, D>>::run::h65b427485c2a355b
Nov 28 14:57:53 ...: at /home/slamb/git/moonfire-nvr/db/writer.rs:365
Nov 28 14:57:53 ...: 8: 0x4a32bf - moonfire_db::writer::start_syncer::{{closure}}::h8d8d9817454357db
Nov 28 14:57:53 ...: at /home/slamb/git/moonfire-nvr/db/writer.rs:147
Nov 28 14:57:53 ...: - std::sys_common::backtrace::__rust_begin_short_backtrace::h478cfad5bec097cb
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/sys_common/backtrace.rs:136
Nov 28 14:57:53 ...: 9: 0x47a023 - std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}}::h0bcfd3639b5817f7
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/thread/mod.rs:477
Nov 28 14:57:53 ...: - <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hf8f01a225dda73a6
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/panic.rs:319
Nov 28 14:57:53 ...: - std::panicking::try::do_call::h6661548dfb451858
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/panicking.rs:310
Nov 28 14:57:53 ...: 10: 0x8e220b - __rust_maybe_catch_panic
Nov 28 14:57:53 ...: at src/libpanic_unwind/lib.rs:102
Nov 28 14:57:53 ...: 11: 0x44fd3b - std::panicking::try::h5b49cbb90fd9a1f2
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/panicking.rs:289
Nov 28 14:57:53 ...: - std::panic::catch_unwind::hdb03e368bff69de4
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/panic.rs:398
Nov 28 14:57:53 ...: - std::thread::Builder::spawn_unchecked::{{closure}}::h5c6ba7cb08b38b14
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/libstd/thread/mod.rs:476
Nov 28 14:57:53 ...: - <F as alloc::boxed::FnBox<A>>::call_box::h97a0e387b9befaf7
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/liballoc/boxed.rs:673
Nov 28 14:57:53 ...: 12: 0x8dbe6f - <alloc::boxed::Box<(dyn alloc::boxed::FnBox<A, Output=R> + 'a)> as core::ops::function::FnOnce<A>>::call_once::hd1734190ba15b47e
Nov 28 14:57:53 ...: at /rustc/400c2bc5ed292f77c49693320f4eda37bb375e90/src/liballoc/boxed.rs:683
Nov 28 14:57:53 ...: - std::sys_common::thread::start_thread::h30eac6e77e888779
Nov 28 14:57:53 ...: at src/libstd/sys_common/thread.rs:24
Nov 28 14:57:53 ...: - std::sys::unix::thread::Thread::new::thread_start::h6b3c4b2ce6075f65
Nov 28 14:57:53 ...: at src/libstd/sys/unix/thread.rs:90
Building/installing the latest version (ignoring 4 test errors reported in another issue) results in operative UI, but no recordings being made. Relevant portion of the log file:
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: avcodec compiled=56.60.100 running=56.1.0
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: avformat compiled=56.40.101 running=56.1.0
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: avutil compiled=54.31.100 running=54.3.0
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Front Left moonfire_nvr::streamer] Front Left: Opening input: rtsp://admin:[email protected]/Streaming/Channels/1
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Back moonfire_nvr::streamer] Back: Opening input: rtsp://admin:[email protected]/Streaming/Channels/1
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: main moonfire_nvr::cmds::run] Ready to serve HTTP requests
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Front Right moonfire_nvr::streamer] Front Right: Opening input: rtsp://admin:[email protected]/Streaming/Channels/1
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Side moonfire_nvr::streamer] Side: Opening input: rtsp://admin:[email protected]/Streaming/Channels/1
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Front Left moonfire_nvr::stream] While opening URL rtsp://admin:[email protected]/Streaming/Channels/1, some options were not understood: user-agent=moonfire-nvr, stimeout=10000000
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Front Right moonfire_nvr::stream] While opening URL rtsp://admin:[email protected]/Streaming/Channels/1, some options were not understood: user-agent=moonfire-nvr, stimeout=10000000
Oct 22 17:03:15 moonfire moonfire-nvr[27442]: stream-Back moonfire_nvr::stream] While opening URL rtsp://admin:[email protected]/Streaming/Channels/1, some options were not understood: user-agent=moonfire-nvr, stimeout=10000000
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: stream-Side moonfire_nvr::stream] While opening URL rtsp://admin:[email protected]/Streaming/Channels/1, some options were not understood: user-agent=moonfire-nvr, stimeout=10000000
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: [rtsp @ 0x72e19000] Estimating duration from bitrate, this may be inaccurate
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: stream-Front Right moonfire_nvr::streamer] Front Right: sleeping for Duration { secs: 1, nanos: 0 } after error: Error: ffmpeg: Unknown error -1
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: cause: Some(Error(1))
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: [rtsp @ 0x73019000] Estimating duration from bitrate, this may be inaccurate
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: stream-Back moonfire_nvr::streamer] Back: sleeping for Duration { secs: 1, nanos: 0 } after error: Error: ffmpeg: Unknown error -1
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: cause: Some(Error(1))
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: [rtsp @ 0x73419000] Estimating duration from bitrate, this may be inaccurate
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: stream-Front Left moonfire_nvr::streamer] Front Left: sleeping for Duration { secs: 1, nanos: 0 } after error: Error: ffmpeg: Unknown error -1
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: cause: Some(Error(1))
Oct 22 17:03:16 moonfire moonfire-nvr[27442]: [rtsp @ 0x72c19000] Estimating duration from bitrate, this may be inaccurate
Oct 22 17:03:17 moonfire moonfire-nvr[27442]: stream-Side moonfire_nvr::streamer] Side: sleeping for Duration { secs: 1, nanos: 0 } after error: Error: ffmpeg: Unknown error -1
Oct 22 17:03:17 moonfire moonfire-nvr[27442]: cause: Some(Error(1))
Notice that several URLs are logging without redacting the username/password (I redacted manually to list password "dolf----" above, but original output showed full password).
I'd like to have an API endpoint which streams events as they happen, such as:
With this, the frontend UI could update itself without requiring the user to hit refresh.
It could be a WebSockets stream (like the live view) of JSON events that happened in the current "open", each with a sequence number.multipart/mixed
Other API calls like /api/?days=true
or /api/camera/<uuid>/<stream>/recordings
would have a HTTP header showing the matching sequence number. The frontend could use those together to compute the contents at any later point.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.