UNTESTED: note trailing zeros in /recordings reply

This commit is contained in:
Scott Lamb 2021-10-10 16:13:57 -07:00
parent ecbe86153d
commit ad35a1ca5e
4 changed files with 18 additions and 2 deletions

View File

@ -332,6 +332,13 @@ arbitrary order. Each recording object has the following properties:
* `videoSamples`: the number of samples (aka frames) of video in this * `videoSamples`: the number of samples (aka frames) of video in this
recording. recording.
* `sampleFileBytes`: the number of bytes of video in this recording. * `sampleFileBytes`: the number of bytes of video in this recording.
* `hasTrailingZero`: the final frame of the final recording id described by
this row (`endId` if present, otherwise `startId`) has a duration of 0.
A frame's duration is calculated by subtracting its timestamp from the
following frame's timestamp. When a run ends, there's no following frame
and Moonfire NVR fills in a duration of 0. When using `/view.mp4`, it's
not possible to append additional segments after such frames, as noted
below.
Under the property `videoSampleEntries`, an object mapping ids to objects with Under the property `videoSampleEntries`, an object mapping ids to objects with
the following properties: the following properties:
@ -456,8 +463,9 @@ Bugs and limitations:
* The final recording in every "run" ends with a frame that has duration 0. * The final recording in every "run" ends with a frame that has duration 0.
It's not possible to append additional segments after such a frame; It's not possible to append additional segments after such a frame;
the server will return an error like `Invalid argument: unable to append the server will return an error like `Invalid argument: unable to append
recording 2/16672 after recording 2/16671 with trailing zero`. recording 2/16672 after recording 2/16671 with trailing zero`. See also
(See [#178](https://github.com/scottlamb/moonfire-nvr/issues/178).) `hasTrailingZero` above, and
[#178](https://github.com/scottlamb/moonfire-nvr/issues/178).
### `GET /api/cameras/<uuid>/<stream>/view.mp4.txt` ### `GET /api/cameras/<uuid>/<stream>/view.mp4.txt`

View File

@ -208,6 +208,7 @@ pub struct ListAggregatedRecordingsRow {
pub open_id: u32, pub open_id: u32,
pub first_uncommitted: Option<i32>, pub first_uncommitted: Option<i32>,
pub growing: bool, pub growing: bool,
pub has_trailing_zero: bool,
} }
impl ListAggregatedRecordingsRow { impl ListAggregatedRecordingsRow {
@ -231,6 +232,7 @@ impl ListAggregatedRecordingsRow {
None None
}, },
growing, growing,
has_trailing_zero: (row.flags & RecordingFlags::TrailingZero as i32) != 0,
} }
} }
} }
@ -1352,6 +1354,7 @@ impl LockedDatabase {
let run_start_id = recording_id - row.run_offset; let run_start_id = recording_id - row.run_offset;
let uncommitted = (row.flags & RecordingFlags::Uncommitted as i32) != 0; let uncommitted = (row.flags & RecordingFlags::Uncommitted as i32) != 0;
let growing = (row.flags & RecordingFlags::Growing as i32) != 0; let growing = (row.flags & RecordingFlags::Growing as i32) != 0;
let has_trailing_zero = (row.flags & RecordingFlags::TrailingZero as i32) != 0;
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
match aggs.entry(run_start_id) { match aggs.entry(run_start_id) {
Entry::Occupied(mut e) => { Entry::Occupied(mut e) => {
@ -1396,6 +1399,7 @@ impl LockedDatabase {
a.first_uncommitted = a.first_uncommitted.or(Some(recording_id)); a.first_uncommitted = a.first_uncommitted.or(Some(recording_id));
} }
a.growing = growing; a.growing = growing;
a.has_trailing_zero = has_trailing_zero;
} }
} }
Entry::Vacant(e) => { Entry::Vacant(e) => {

View File

@ -493,6 +493,9 @@ pub struct Recording {
#[serde(skip_serializing_if = "Not::not")] #[serde(skip_serializing_if = "Not::not")]
pub growing: bool, pub growing: bool,
#[serde(skip_serializing_if = "Not::not")]
pub has_trailing_zero: bool,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]

View File

@ -765,6 +765,7 @@ impl Service {
video_samples: row.video_samples, video_samples: row.video_samples,
video_sample_entry_id: row.video_sample_entry_id, video_sample_entry_id: row.video_sample_entry_id,
growing: row.growing, growing: row.growing,
has_trailing_zero: row.has_trailing_zero,
}); });
if !out if !out
.video_sample_entries .video_sample_entries