From 84482cb5eabfc368db2b70392552efe3ceefed0a Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:24:15 +0200 Subject: [PATCH] Minor touchups --- README.md | 12 +++++++++--- build/mp4-muxer.d.ts | 2 +- src/box.ts | 5 +++-- src/misc.ts | 8 +++++--- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7b2edca..5a6b975 100644 --- a/README.md +++ b/README.md @@ -243,7 +243,7 @@ set explicitly: - Use `'offset'` to offset the timestamp of each track by that track's first chunk's timestamp. This way, it starts at 0. - Use `'cross-track-offset'` to offset the timestamp of each track by the _minimum of all tracks' first chunk timestamp_. -This works like `'offset'`, but should be used when the all tracks use the same timebase. +This works like `'offset'`, but should be used when the all tracks use the same clock. ### Muxing media chunks Then, with VideoEncoder and AudioEncoder set up, send encoded chunks to the muxer using the following methods: @@ -251,7 +251,8 @@ Then, with VideoEncoder and AudioEncoder set up, send encoded chunks to the muxe addVideoChunk( chunk: EncodedVideoChunk, meta?: EncodedVideoChunkMetadata, - timestamp?: number + timestamp?: number, + compositionTimeOffset?: number ): void; addAudioChunk( @@ -274,6 +275,11 @@ let videoEncoder = new VideoEncoder({ videoEncoder.configure(/* ... */); ``` +The optional field `compositionTimeOffset` can be used when the decode time of the chunk doesn't equal its presentation +time; this is the case when [B-frames](https://en.wikipedia.org/wiki/Video_compression_picture_types) are present. +B-frames don't occur when using the WebCodecs API for encoding. The decode time is calculated by subtracting +`compositionTimeOffset` from `timestamp`, meaning `timestamp` dictates the presentation time. + Should you have obtained your encoded media data from a source other than the WebCodecs API, you can use these following methods to directly send your raw data to the muxer: ```ts @@ -283,7 +289,7 @@ addVideoChunkRaw( timestamp: number, // in microseconds duration: number, // in microseconds meta?: EncodedVideoChunkMetadata, - compositionTimeOffset: number // in microseconds + compositionTimeOffset?: number // in microseconds ): void; addAudioChunkRaw( diff --git a/build/mp4-muxer.d.ts b/build/mp4-muxer.d.ts index b2bf2e1..303f545 100644 --- a/build/mp4-muxer.d.ts +++ b/build/mp4-muxer.d.ts @@ -173,7 +173,7 @@ declare class Muxer { * @param data The raw data of the video chunk. * @param type Whether the video chunk is a keyframe or delta frame. * @param timestamp The timestamp of the video chunk. - * @param duration The duration of the video chunk (typically 0). + * @param duration The duration of the video chunk. * @param meta Optionally, any encoder metadata. * @param compositionTimeOffset The composition time offset (i.e. presentation timestamp minus decode timestamp) of * the video chunk. diff --git a/src/box.ts b/src/box.ts index 1804329..e6dba05 100644 --- a/src/box.ts +++ b/src/box.ts @@ -277,8 +277,9 @@ export const url = () => fullBox('url ', 0, 1); // Self-reference flag enabled * also indicates how to interpret the sample (for example, whether to decompress the video data and, if so, how). */ export const stbl = (track: Track) => { - const needsCTTS = track.compositionTimeOffsetTable.length > 1 || + const needsCtts = track.compositionTimeOffsetTable.length > 1 || track.compositionTimeOffsetTable.some((x) => x.sampleCompositionTimeOffset !== 0); + return box('stbl', null, [ stsd(track), stts(track), @@ -286,7 +287,7 @@ export const stbl = (track: Track) => { stsc(track), stsz(track), stco(track), - needsCTTS ? ctts(track) : null + needsCtts ? ctts(track) : null ]); }; diff --git a/src/misc.ts b/src/misc.ts index f4d4875..f08fa96 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -65,11 +65,13 @@ export const last = (arr: T[]) => { export const lastPresentedSample = (samples: Sample[]): Sample | undefined => { let result: Sample | undefined = undefined; - for (const s of samples) { - if (!result || s.presentationTimestamp > result.presentationTimestamp) { - result = s; + + for (let sample of samples) { + if (!result || sample.presentationTimestamp > result.presentationTimestamp) { + result = sample; } } + return result; };