@bubo-squared/gyroview 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +35 -15
- package/dist/index.d.ts +21 -2
- package/dist/index.js +2 -2
- package/dist/packages/adapters/fetch/src/HttpByteStream.js +174 -0
- package/dist/packages/adapters/fetch/src/HttpRangeSource.js +14 -170
- package/dist/packages/adapters/fetch/src/HttpResource.js +192 -0
- package/dist/packages/adapters/fetch/src/contentRange.js +15 -0
- package/dist/packages/adapters/fetch/src/httpRequest.js +5 -3
- package/dist/packages/adapters/fetch/src/index.js +3 -1
- package/dist/packages/adapters/fetch/src/passingFailures.js +24 -0
- package/dist/packages/adapters/fetch/src/rangeFailures.js +17 -0
- package/dist/packages/adapters/fetch/src/recordingVersion.js +37 -0
- package/dist/packages/adapters/mediabunny/src/MediabunnyAudioPackager.js +129 -0
- package/dist/packages/adapters/mediabunny/src/MediabunnyCodecReader.js +80 -0
- package/dist/packages/adapters/mediabunny/src/SegmentChannel.js +58 -6
- package/dist/packages/adapters/mediabunny/src/decoderConfigurations.js +28 -0
- package/dist/packages/adapters/mediabunny/src/index.js +3 -2
- package/dist/packages/adapters/webcodecs/src/WebCodecsVideoDecoderPort.js +12 -3
- package/dist/packages/core/src/application/download/BlockStore.js +97 -0
- package/dist/packages/core/src/application/download/DownloadedAudioSamples.js +50 -0
- package/dist/packages/core/src/application/download/DownloadedVideoTrack.js +122 -0
- package/dist/packages/core/src/application/download/FileDownload.js +183 -0
- package/dist/packages/core/src/application/download/RecordingBuffer.js +22 -0
- package/dist/packages/core/src/application/download/SampleCursor.js +88 -0
- package/dist/packages/core/src/application/download/SourceByteStream.js +46 -0
- package/dist/packages/core/src/application/download/Transfers.js +75 -0
- package/dist/packages/core/src/application/download/startFileDownload.js +37 -0
- package/dist/packages/core/src/application/playback/Buffering.js +53 -0
- package/dist/packages/core/src/application/playback/DecodePipeline.js +11 -7
- package/dist/packages/core/src/application/playback/DecodeRun.js +15 -0
- package/dist/packages/core/src/application/playback/PlaybackSession.js +18 -27
- package/dist/packages/core/src/application/playback/keyframeTimeAt.js +1 -1
- package/dist/packages/core/src/application/playback/probeDecoding.js +17 -3
- package/dist/packages/core/src/application/recording/readSampleTable.js +27 -0
- package/dist/packages/core/src/application/recording/timeRecording.js +3 -3
- package/dist/packages/core/src/domain/container/KeyframeRule.js +7 -0
- package/dist/packages/core/src/domain/container/SampleTable.js +29 -0
- package/dist/packages/core/src/domain/container/TrackSampleTable.js +96 -0
- package/dist/packages/core/src/domain/container/presentationOrder.js +10 -0
- package/dist/packages/core/src/domain/download/DownloadPolicy.js +41 -0
- package/dist/packages/core/src/domain/download/isReadyToResume.js +27 -0
- package/dist/packages/core/src/domain/download/planDownloads.js +175 -0
- package/dist/packages/core/src/domain/download/trackNeeds.js +32 -0
- package/dist/packages/core/src/domain/format/boxes/boxHeader.js +44 -0
- package/dist/packages/core/src/domain/format/boxes/scanBoxes.js +7 -34
- package/dist/packages/core/src/domain/format/mp4/keyframeRules.js +81 -0
- package/dist/packages/core/src/domain/format/mp4/movieBoxes.js +52 -0
- package/dist/packages/core/src/domain/format/mp4/mp4BoxTypes.js +46 -0
- package/dist/packages/core/src/domain/format/mp4/mp4Layouts.js +183 -0
- package/dist/packages/core/src/domain/format/mp4/parseMovie.js +67 -0
- package/dist/packages/core/src/domain/format/mp4/readTable.js +31 -0
- package/dist/packages/core/src/domain/format/mp4/sampleLocations.js +69 -0
- package/dist/packages/core/src/domain/format/mp4/sampleTiming.js +109 -0
- package/dist/packages/core/src/domain/format/mp4/trackHeaders.js +75 -0
- package/dist/packages/core/src/index.js +10 -2
- package/dist/packages/core/src/shared/async/iteration.js +24 -0
- package/dist/packages/core/src/shared/binary/ByteRange.js +12 -0
- package/dist/packages/core/src/shared/binary/ByteRangeSet.js +85 -0
- package/dist/packages/core/src/shared/binary/ByteReader.js +21 -3
- package/dist/packages/core/src/shared/binary/concatenated.js +15 -0
- package/dist/packages/core/src/shared/errors/GyroViewError.js +56 -3
- package/dist/packages/core/src/shared/math/countAtOrBelow.js +17 -0
- package/dist/packages/player/src/composition/browserPorts.js +23 -4
- package/dist/packages/player/src/composition/buildPipeline.js +15 -3
- package/dist/packages/player/src/composition/openInputs.js +51 -107
- package/dist/packages/player/src/composition/readInputs.js +111 -0
- package/dist/packages/player/src/controls/messages.js +3 -1
- package/dist/packages/player/src/inspectRecording.js +1 -1
- package/dist/standalone.js +58 -58
- package/package.json +1 -1
- package/dist/packages/adapters/mediabunny/src/MediabunnyAudioSegments.js +0 -133
- package/dist/packages/adapters/mediabunny/src/MediabunnyDemuxer.js +0 -63
- package/dist/packages/adapters/mediabunny/src/MediabunnyVideoTrackReader.js +0 -84
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ensureInvariant, hasErrorCode } from "../../../core/src/shared/errors/GyroViewError.js";
|
|
2
|
+
import { readRecording } from "../../../core/src/application/recording/readRecording.js";
|
|
3
|
+
import { readSampleTable } from "../../../core/src/application/recording/readSampleTable.js";
|
|
4
|
+
import { detectLensLayout } from "../../../core/src/domain/format/layout/detectLensLayout.js";
|
|
5
|
+
import "../../../core/src/index.js";
|
|
6
|
+
import { inputName } from "../PlayerSource.js";
|
|
7
|
+
//#region ../../packages/player/src/composition/readInputs.ts
|
|
8
|
+
/**
|
|
9
|
+
* Reads the given inputs, and the other lens file an info record declares, as one recording: its
|
|
10
|
+
* metadata from the input that carries the trailer, and every input's sample table and codecs.
|
|
11
|
+
*/
|
|
12
|
+
async function readInputs(inputs, attempt) {
|
|
13
|
+
const { ports, signal } = attempt;
|
|
14
|
+
const given = inputs.map((input) => ({
|
|
15
|
+
input,
|
|
16
|
+
opened: ports.sources.open(input, signal)
|
|
17
|
+
}));
|
|
18
|
+
const recording = await readRecordingOf(given, ports);
|
|
19
|
+
signal.throwIfAborted();
|
|
20
|
+
const openings = [...given, ...await declaredSecond(given, recording, attempt)];
|
|
21
|
+
const read = await Promise.all(openings.map((opening) => readInput(opening, ports)));
|
|
22
|
+
signal.throwIfAborted();
|
|
23
|
+
return {
|
|
24
|
+
recording,
|
|
25
|
+
inputs: read
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function describedInput(read) {
|
|
29
|
+
const videoTracks = read.codecs.video.map(({ description }) => ({ description }));
|
|
30
|
+
return {
|
|
31
|
+
name: inputName(read.input),
|
|
32
|
+
videoTracks
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function readInput(opening, ports) {
|
|
36
|
+
const { source } = opening.opened;
|
|
37
|
+
const { table, movieBytes } = await readSampleTable(source);
|
|
38
|
+
const codecs = await ports.codecReader.read(movieBytes);
|
|
39
|
+
return {
|
|
40
|
+
...opening,
|
|
41
|
+
table,
|
|
42
|
+
codecs,
|
|
43
|
+
size: await source.size()
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The other lens file a lone file's info record says the recording is split into, when the
|
|
48
|
+
* server has it: found before the lone file's tracks are read, which finding it only once they
|
|
49
|
+
* fell short would read twice. A file that does not say so still gets its sibling looked for
|
|
50
|
+
* once its tracks fall short (see openRecording).
|
|
51
|
+
*/
|
|
52
|
+
async function declaredSecond(given, recording, attempt) {
|
|
53
|
+
if (!(given.length === 1 && recording.info.fileLayout === "split-files") || !attempt.findSecondFile) return [];
|
|
54
|
+
const input = await attempt.findSecondFile();
|
|
55
|
+
attempt.signal.throwIfAborted();
|
|
56
|
+
return input === void 0 ? [] : [{
|
|
57
|
+
input,
|
|
58
|
+
opened: attempt.ports.sources.open(input, attempt.signal)
|
|
59
|
+
}];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The layout hints of a file without an info record: the tracks alone decide.
|
|
63
|
+
*/
|
|
64
|
+
var NO_HINTS = {
|
|
65
|
+
fileLayout: void 0,
|
|
66
|
+
trackOrder: void 0
|
|
67
|
+
};
|
|
68
|
+
async function readRecordingOf(openings, ports) {
|
|
69
|
+
try {
|
|
70
|
+
return await readTrailerCarrier(openings.map(({ opened }) => opened.source));
|
|
71
|
+
} catch (error) {
|
|
72
|
+
const [only] = openings;
|
|
73
|
+
if (openings.length === 1 && hasErrorCode(error, "invalid-trailer") && only) await refuseAsLoneHalf(only, ports);
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A file without a trailer may be the _10_ half of an older camera's pair, which writes the
|
|
79
|
+
* trailer to _00_ alone: its one square track tells, and the refusal asks for the other file
|
|
80
|
+
* instead of calling it damaged. Anything else leaves the trailer's own refusal standing.
|
|
81
|
+
*/
|
|
82
|
+
async function refuseAsLoneHalf(opening, ports) {
|
|
83
|
+
let read;
|
|
84
|
+
try {
|
|
85
|
+
read = await readInput(opening, ports);
|
|
86
|
+
} catch {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
detectLensLayout([describedInput(read)], NO_HINTS);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (hasErrorCode(error, "missing-second-file")) throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The recording read from the input that carries the trailer: the first, or the second when the
|
|
97
|
+
* first has none, as the _10_ file of an older camera's pair, which writes it to _00_ alone,
|
|
98
|
+
* when the pair is given the other way round.
|
|
99
|
+
*/
|
|
100
|
+
async function readTrailerCarrier(sources) {
|
|
101
|
+
const [first, second] = sources;
|
|
102
|
+
ensureInvariant(first !== void 0, "a recording needs at least one input");
|
|
103
|
+
try {
|
|
104
|
+
return await readRecording(first);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
if (second === void 0 || !hasErrorCode(error, "invalid-trailer")) throw error;
|
|
107
|
+
return readRecording(second);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { describedInput, readInputs };
|
|
@@ -71,13 +71,15 @@ var DEFAULT_MESSAGES = {
|
|
|
71
71
|
"playback-blocked": FAILED,
|
|
72
72
|
"range-unsupported": UNREACHABLE,
|
|
73
73
|
"render-unavailable": UNSUPPORTED_BROWSER,
|
|
74
|
+
"source-changed": "The video was replaced while it played.",
|
|
74
75
|
"source-truncated": UNREACHABLE,
|
|
75
76
|
"source-unreadable": UNREACHABLE,
|
|
76
77
|
"unsupported-calibration": UNREADABLE,
|
|
77
78
|
"unsupported-container": UNREADABLE,
|
|
78
79
|
"unsupported-gyro-record": UNREADABLE,
|
|
79
80
|
"unsupported-info-format": UNREADABLE,
|
|
80
|
-
"unsupported-layout": UNREADABLE
|
|
81
|
+
"unsupported-layout": UNREADABLE,
|
|
82
|
+
"webcodecs-unavailable": UNSUPPORTED_BROWSER
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
85
|
/**
|
|
@@ -9,7 +9,7 @@ import { browserSources } from "./composition/browserPorts.js";
|
|
|
9
9
|
*/
|
|
10
10
|
function inspectRecording(recording, options = {}) {
|
|
11
11
|
const signal = options.signal ?? new AbortController().signal;
|
|
12
|
-
const source = browserSources(options.http ?? {}).open(inputOf(recording), signal);
|
|
12
|
+
const { source } = browserSources(options.http ?? {}).open(inputOf(recording), signal);
|
|
13
13
|
return inspectRecording$1(source);
|
|
14
14
|
}
|
|
15
15
|
function inputOf(recording) {
|