@remotion/media-parser 4.0.301 → 4.0.303

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.
Files changed (94) hide show
  1. package/dist/check-if-done.js +4 -0
  2. package/dist/containers/aac/parse-aac.js +1 -0
  3. package/dist/containers/avc/key.d.ts +1 -1
  4. package/dist/containers/avc/key.js +5 -1
  5. package/dist/containers/avc/max-buffer-size.d.ts +3 -0
  6. package/dist/containers/avc/max-buffer-size.js +40 -0
  7. package/dist/containers/avc/parse-avc.d.ts +6 -7
  8. package/dist/containers/avc/parse-avc.js +83 -7
  9. package/dist/containers/flac/parse-streaminfo.js +1 -0
  10. package/dist/containers/iso-base-media/base-media-box.d.ts +2 -1
  11. package/dist/containers/iso-base-media/elst.d.ts +19 -0
  12. package/dist/containers/iso-base-media/elst.js +33 -0
  13. package/dist/containers/iso-base-media/find-keyframe-before-time.d.ts +2 -1
  14. package/dist/containers/iso-base-media/find-keyframe-before-time.js +3 -3
  15. package/dist/containers/iso-base-media/get-moov-atom.js +1 -0
  16. package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +1 -0
  17. package/dist/containers/iso-base-media/get-seeking-byte.js +1 -0
  18. package/dist/containers/iso-base-media/make-track.d.ts +1 -1
  19. package/dist/containers/iso-base-media/make-track.js +4 -1
  20. package/dist/containers/iso-base-media/mdat/get-editlist.d.ts +5 -0
  21. package/dist/containers/iso-base-media/mdat/get-editlist.js +21 -0
  22. package/dist/containers/iso-base-media/mdat/mdat.js +8 -5
  23. package/dist/containers/iso-base-media/parse-boxes.js +1 -0
  24. package/dist/containers/iso-base-media/process-box.d.ts +2 -0
  25. package/dist/containers/iso-base-media/process-box.js +31 -4
  26. package/dist/containers/iso-base-media/traversal.d.ts +2 -0
  27. package/dist/containers/iso-base-media/traversal.js +10 -1
  28. package/dist/containers/mp3/parse-mpeg-header.js +1 -0
  29. package/dist/containers/riff/convert-queued-sample-to-mediaparser-sample.d.ts +14 -0
  30. package/dist/containers/riff/convert-queued-sample-to-mediaparser-sample.js +55 -0
  31. package/dist/containers/riff/get-seeking-byte.d.ts +3 -1
  32. package/dist/containers/riff/get-seeking-byte.js +5 -1
  33. package/dist/containers/riff/get-strh-for-index.d.ts +2 -0
  34. package/dist/containers/riff/get-strh-for-index.js +17 -0
  35. package/dist/containers/riff/get-tracks-from-avi.js +2 -0
  36. package/dist/containers/riff/parse-movi.js +51 -44
  37. package/dist/containers/riff/parse-riff-body.js +8 -0
  38. package/dist/containers/transport-stream/handle-aac-packet.js +1 -0
  39. package/dist/containers/transport-stream/handle-avc-packet.d.ts +3 -1
  40. package/dist/containers/transport-stream/handle-avc-packet.js +4 -3
  41. package/dist/containers/transport-stream/parse-transport-stream.js +1 -0
  42. package/dist/containers/transport-stream/process-audio.d.ts +3 -1
  43. package/dist/containers/transport-stream/process-audio.js +2 -1
  44. package/dist/containers/transport-stream/process-sample-if-possible.js +2 -0
  45. package/dist/containers/transport-stream/process-stream-buffers.d.ts +5 -2
  46. package/dist/containers/transport-stream/process-stream-buffers.js +4 -2
  47. package/dist/containers/transport-stream/process-video.d.ts +3 -1
  48. package/dist/containers/transport-stream/process-video.js +2 -1
  49. package/dist/containers/wav/parse-fmt.js +1 -0
  50. package/dist/containers/webm/get-sample-from-block.d.ts +3 -1
  51. package/dist/containers/webm/get-sample-from-block.js +4 -3
  52. package/dist/containers/webm/make-track.js +2 -0
  53. package/dist/containers/webm/parse-ebml.d.ts +1 -1
  54. package/dist/containers/webm/parse-ebml.js +3 -1
  55. package/dist/containers/webm/state-for-processing.d.ts +3 -1
  56. package/dist/containers/webm/state-for-processing.js +2 -1
  57. package/dist/convert-audio-or-video-sample.js +1 -0
  58. package/dist/esm/index.mjs +597 -127
  59. package/dist/esm/universal.mjs +9 -8
  60. package/dist/esm/web.mjs +9 -8
  61. package/dist/esm/worker-server-entry.mjs +596 -126
  62. package/dist/esm/worker-web-entry.mjs +596 -126
  63. package/dist/get-seeking-byte.d.ts +3 -1
  64. package/dist/get-seeking-byte.js +2 -1
  65. package/dist/get-tracks.d.ts +3 -0
  66. package/dist/get-tracks.js +10 -1
  67. package/dist/index.d.ts +34 -3
  68. package/dist/readers/from-fetch.js +2 -1
  69. package/dist/run-parse-iteration.js +0 -3
  70. package/dist/state/avc/avc-state.d.ts +12 -0
  71. package/dist/state/avc/avc-state.js +44 -0
  72. package/dist/state/iso-base-media/iso-state.d.ts +4 -0
  73. package/dist/state/iso-base-media/iso-state.js +2 -0
  74. package/dist/state/iso-base-media/timescale-state.d.ts +5 -0
  75. package/dist/state/iso-base-media/timescale-state.js +13 -0
  76. package/dist/state/parser-state.d.ts +34 -3
  77. package/dist/state/parser-state.js +3 -0
  78. package/dist/state/riff/queued-b-frames.d.ts +9 -0
  79. package/dist/state/riff/queued-b-frames.js +47 -0
  80. package/dist/state/riff/queued-frames.d.ts +9 -0
  81. package/dist/state/riff/queued-frames.js +39 -0
  82. package/dist/state/riff/riff-keyframes.js +1 -0
  83. package/dist/state/riff/sample-counter.d.ts +13 -2
  84. package/dist/state/riff/sample-counter.js +34 -7
  85. package/dist/state/riff.d.ts +19 -2
  86. package/dist/state/riff.js +3 -0
  87. package/dist/state/transport-stream/last-emitted-sample.d.ts +1 -1
  88. package/dist/state/transport-stream/transport-stream.d.ts +1 -1
  89. package/dist/version.d.ts +1 -1
  90. package/dist/version.js +1 -1
  91. package/dist/webcodec-sample-types.d.ts +11 -0
  92. package/dist/work-on-seek-request.d.ts +2 -0
  93. package/dist/work-on-seek-request.js +5 -2
  94. package/package.json +3 -3
@@ -1,6 +1,7 @@
1
1
  import type { MediaParserLogLevel } from './log';
2
2
  import type { M3uPlaylistContext } from './options';
3
3
  import type { SeekingHints } from './seeking-hints';
4
+ import type { AvcState } from './state/avc/avc-state';
4
5
  import type { IsoBaseMediaState } from './state/iso-base-media/iso-state';
5
6
  import type { M3uState } from './state/m3u-state';
6
7
  import type { WebmState } from './state/matroska/webm';
@@ -9,7 +10,7 @@ import type { StructureState } from './state/structure';
9
10
  import type { TransportStreamState } from './state/transport-stream/transport-stream';
10
11
  import type { MediaSectionState } from './state/video-section';
11
12
  import type { SeekResolution } from './work-on-seek-request';
12
- export declare const getSeekingByte: ({ info, time, logLevel, currentPosition, isoState, transportStream, webmState, mediaSection, m3uPlaylistContext, structure, riffState, m3uState, }: {
13
+ export declare const getSeekingByte: ({ info, time, logLevel, currentPosition, isoState, transportStream, webmState, mediaSection, m3uPlaylistContext, structure, riffState, m3uState, avcState, }: {
13
14
  info: SeekingHints;
14
15
  time: number;
15
16
  logLevel: MediaParserLogLevel;
@@ -22,4 +23,5 @@ export declare const getSeekingByte: ({ info, time, logLevel, currentPosition, i
22
23
  m3uPlaylistContext: M3uPlaylistContext | null;
23
24
  riffState: RiffState;
24
25
  m3uState: M3uState;
26
+ avcState: AvcState;
25
27
  }) => Promise<SeekResolution>;
@@ -10,7 +10,7 @@ const get_seeking_byte_6 = require("./containers/riff/get-seeking-byte");
10
10
  const get_seeking_byte_7 = require("./containers/wav/get-seeking-byte");
11
11
  const get_seeking_byte_8 = require("./containers/webm/seek/get-seeking-byte");
12
12
  const observed_pes_header_1 = require("./state/transport-stream/observed-pes-header");
13
- const getSeekingByte = ({ info, time, logLevel, currentPosition, isoState, transportStream, webmState, mediaSection, m3uPlaylistContext, structure, riffState, m3uState, }) => {
13
+ const getSeekingByte = ({ info, time, logLevel, currentPosition, isoState, transportStream, webmState, mediaSection, m3uPlaylistContext, structure, riffState, m3uState, avcState, }) => {
14
14
  var _a;
15
15
  if (info.type === 'iso-base-media-seeking-hints') {
16
16
  return (0, get_seeking_byte_3.getSeekingByteFromIsoBaseMedia)({
@@ -71,6 +71,7 @@ const getSeekingByte = ({ info, time, logLevel, currentPosition, isoState, trans
71
71
  info,
72
72
  time,
73
73
  riffState,
74
+ avcState,
74
75
  });
75
76
  }
76
77
  if (info.type === 'mp3-seeking-hints') {
@@ -38,6 +38,7 @@ export type MediaParserVideoTrack = {
38
38
  timescale: number;
39
39
  advancedColor: MediaParserAdvancedColor;
40
40
  m3uStreamFormat: 'ts' | 'mp4' | null;
41
+ startInSeconds: number;
41
42
  };
42
43
  export type MediaParserAudioTrack = {
43
44
  codec: string;
@@ -49,12 +50,14 @@ export type MediaParserAudioTrack = {
49
50
  codecEnum: MediaParserAudioCodec;
50
51
  timescale: number;
51
52
  codecData: MediaParserCodecData | null;
53
+ startInSeconds: number;
52
54
  };
53
55
  export type MediaParserOtherTrack = {
54
56
  type: 'other';
55
57
  trackId: number;
56
58
  timescale: number;
57
59
  trakBox: TrakBox | null;
60
+ startInSeconds: number;
58
61
  };
59
62
  export type MediaParserTrack = MediaParserVideoTrack | MediaParserAudioTrack | MediaParserOtherTrack;
60
63
  export declare const getNumberOfTracks: (moovBox: MoovBox) => number;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTracks = exports.defaultHasallTracks = exports.defaultGetTracks = exports.getTracksFromIsoBaseMedia = exports.getTracksFromMoovBox = exports.getHasTracks = exports.isoBaseMediaHasTracks = exports.getNumberOfTracks = void 0;
4
4
  const make_track_1 = require("./containers/iso-base-media/make-track");
5
+ const get_editlist_1 = require("./containers/iso-base-media/mdat/get-editlist");
5
6
  const traversal_1 = require("./containers/iso-base-media/traversal");
6
7
  const get_tracks_from_avi_1 = require("./containers/riff/get-tracks-from-avi");
7
8
  const get_tracks_1 = require("./containers/transport-stream/get-tracks");
@@ -70,7 +71,15 @@ const getTracksFromMoovBox = (moovBox) => {
70
71
  const mediaParserTracks = [];
71
72
  const tracks = (0, traversal_1.getTraks)(moovBox);
72
73
  for (const trakBox of tracks) {
73
- const track = (0, make_track_1.makeBaseMediaTrack)(trakBox);
74
+ const mvhdBox = (0, traversal_1.getMvhdBox)(moovBox);
75
+ if (!mvhdBox) {
76
+ throw new Error('Mvhd box is not found');
77
+ }
78
+ const startTime = (0, get_editlist_1.findTrackStartTimeInSeconds)({
79
+ movieTimeScale: mvhdBox.timeScale,
80
+ trakBox,
81
+ });
82
+ const track = (0, make_track_1.makeBaseMediaTrack)(trakBox, startTime);
74
83
  if (!track) {
75
84
  continue;
76
85
  }
package/dist/index.d.ts CHANGED
@@ -777,6 +777,13 @@ export declare const MediaParserInternals: {
777
777
  onProfile: (profile: import("./state/parser-state").SpsAndPps) => Promise<void>;
778
778
  registerOnAvcProfileCallback: (callback: (profile: import("./state/parser-state").SpsAndPps) => Promise<void>) => void;
779
779
  getNextTrackIndex: () => number;
780
+ queuedBFrames: {
781
+ addFrame: (frame: import("./state/riff/queued-frames").QueuedVideoSample, maxFramesInBuffer: number) => void;
782
+ flush: () => void;
783
+ getReleasedFrame: () => import("./state/riff/queued-frames").QueuedVideoSample | null;
784
+ hasReleasedFrames: () => boolean;
785
+ clear: () => void;
786
+ };
780
787
  incrementNextTrackIndex: () => void;
781
788
  lazyIdx1: {
782
789
  triggerLoad: (position: number) => Promise<{
@@ -799,14 +806,24 @@ export declare const MediaParserInternals: {
799
806
  };
800
807
  sampleCounter: {
801
808
  onAudioSample: (trackId: number, audioSample: import("./webcodec-sample-types").MediaParserAudioSample) => void;
802
- onVideoSample: (trackId: number, videoSample: import("./webcodec-sample-types").MediaParserVideoSample) => void;
803
- getSamplesForTrack: (trackId: number) => number;
809
+ onVideoSample: (videoSample: import("./webcodec-sample-types").MediaParserVideoSample) => void;
810
+ getSampleCountForTrack: ({ trackId }: {
811
+ trackId: number;
812
+ }) => number;
804
813
  setSamplesFromSeek: (samples: Record<number, number>) => void;
805
814
  riffKeys: {
806
815
  addKeyframe: (keyframe: import("./state/riff/riff-keyframes").RiffKeyframe) => void;
807
816
  getKeyframes: () => import("./state/riff/riff-keyframes").RiffKeyframe[];
808
817
  setFromSeekingHints: (keyframesFromHints: import("./state/riff/riff-keyframes").RiffKeyframe[]) => void;
809
818
  };
819
+ setPocAtKeyframeOffset: ({ keyframeOffset, poc, }: {
820
+ keyframeOffset: number;
821
+ poc: number;
822
+ }) => void;
823
+ getPocAtKeyframeOffset: ({ keyframeOffset, }: {
824
+ keyframeOffset: number;
825
+ }) => number[];
826
+ getKeyframeAtOffset: (sample: import("./state/riff/queued-frames").QueuedVideoSample) => number | null;
810
827
  };
811
828
  };
812
829
  transportStream: {
@@ -832,7 +849,7 @@ export declare const MediaParserInternals: {
832
849
  resetBeforeSeek: () => void;
833
850
  lastEmittedSample: {
834
851
  setLastEmittedSample: (sample: import("./webcodec-sample-types").MediaParserAudioSample | import("./webcodec-sample-types").MediaParserVideoSample) => void;
835
- getLastEmittedSample: () => import("./webcodec-sample-types").MediaParserAudioSample | import("./webcodec-sample-types").MediaParserVideoSample | null;
852
+ getLastEmittedSample: () => import("./webcodec-sample-types").MediaParserVideoSample | import("./webcodec-sample-types").MediaParserAudioSample | null;
836
853
  resetLastEmittedSample: () => void;
837
854
  };
838
855
  };
@@ -895,6 +912,10 @@ export declare const MediaParserInternals: {
895
912
  getTfraBoxes: () => import("./containers/iso-base-media/mfra/tfra").TfraBox[];
896
913
  setTfraBoxes: (boxes: import("./containers/iso-base-media/mfra/tfra").TfraBox[]) => void;
897
914
  };
915
+ movieTimeScale: {
916
+ getTrackTimescale: () => number | null;
917
+ setTrackTimescale: (timescale: number) => void;
918
+ };
898
919
  };
899
920
  mp3: {
900
921
  getMp3Info: () => import("./state/mp3").Mp3Info | null;
@@ -1197,6 +1218,16 @@ export declare const MediaParserInternals: {
1197
1218
  };
1198
1219
  makeSamplesStartAtZero: boolean;
1199
1220
  prefetchCache: import("./fetch").PrefetchCache;
1221
+ avc: {
1222
+ getPrevPicOrderCntLsb(): number;
1223
+ getPrevPicOrderCntMsb(): number;
1224
+ setPrevPicOrderCntLsb(value: number): void;
1225
+ setPrevPicOrderCntMsb(value: number): void;
1226
+ setSps(value: import("./containers/avc/parse-avc").SpsInfo): void;
1227
+ getSps(): import("./containers/avc/parse-avc").SpsInfo | null;
1228
+ getMaxFramesInBuffer(): number | null;
1229
+ clear(): void;
1230
+ };
1200
1231
  };
1201
1232
  processSample: ({ iterator, logLevel, contentLength, }: {
1202
1233
  iterator: import("./iterator/buffer-iterator").BufferIterator;
@@ -135,7 +135,7 @@ const fetchReadContent = async ({ src, range, controller, logLevel, prefetchCach
135
135
  throw new Error('src must be a string when using `fetchReader`');
136
136
  }
137
137
  const fallbackName = src.toString().split('/').pop();
138
- const { reader, contentLength, needsContentRange, name, supportsContentRange, contentType, } = await makeFetchRequestOrGetCached({
138
+ const res = makeFetchRequestOrGetCached({
139
139
  range,
140
140
  src,
141
141
  controller,
@@ -144,6 +144,7 @@ const fetchReadContent = async ({ src, range, controller, logLevel, prefetchCach
144
144
  });
145
145
  const key = cacheKey({ src, range });
146
146
  prefetchCache.delete(key);
147
+ const { reader, contentLength, needsContentRange, name, supportsContentRange, contentType, } = await res;
147
148
  if (controller) {
148
149
  controller._internals.signal.addEventListener('abort', () => {
149
150
  reader.reader.cancel().catch(() => {
@@ -17,9 +17,6 @@ const runParseIteration = async ({ state, }) => {
17
17
  if (structure && structure.type === 'm3u') {
18
18
  return (0, parse_m3u_1.parseM3u)({ state });
19
19
  }
20
- if (state.iterator.bytesRemaining() === 0) {
21
- return Promise.reject(new Error('no bytes'));
22
- }
23
20
  if (structure === null) {
24
21
  await (0, init_video_1.initVideo)({
25
22
  state,
@@ -0,0 +1,12 @@
1
+ import type { SpsInfo } from '../../containers/avc/parse-avc';
2
+ export declare const avcState: () => {
3
+ getPrevPicOrderCntLsb(): number;
4
+ getPrevPicOrderCntMsb(): number;
5
+ setPrevPicOrderCntLsb(value: number): void;
6
+ setPrevPicOrderCntMsb(value: number): void;
7
+ setSps(value: SpsInfo): void;
8
+ getSps(): SpsInfo | null;
9
+ getMaxFramesInBuffer(): number | null;
10
+ clear(): void;
11
+ };
12
+ export type AvcState = ReturnType<typeof avcState>;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.avcState = void 0;
4
+ const max_buffer_size_1 = require("../../containers/avc/max-buffer-size");
5
+ const avcState = () => {
6
+ let prevPicOrderCntLsb = 0;
7
+ let prevPicOrderCntMsb = 0;
8
+ let sps = null;
9
+ let maxFramesInBuffer = null;
10
+ return {
11
+ getPrevPicOrderCntLsb() {
12
+ return prevPicOrderCntLsb;
13
+ },
14
+ getPrevPicOrderCntMsb() {
15
+ return prevPicOrderCntMsb;
16
+ },
17
+ setPrevPicOrderCntLsb(value) {
18
+ prevPicOrderCntLsb = value;
19
+ },
20
+ setPrevPicOrderCntMsb(value) {
21
+ prevPicOrderCntMsb = value;
22
+ },
23
+ setSps(value) {
24
+ const macroblockBufferSize = (0, max_buffer_size_1.macroBlocksPerFrame)(value);
25
+ const maxBufferSize = (0, max_buffer_size_1.maxMacroblockBufferSize)(value);
26
+ const maxFrames = Math.min(16, Math.floor(maxBufferSize / macroblockBufferSize));
27
+ maxFramesInBuffer = maxFrames;
28
+ sps = value;
29
+ },
30
+ getSps() {
31
+ return sps;
32
+ },
33
+ getMaxFramesInBuffer() {
34
+ return maxFramesInBuffer;
35
+ },
36
+ clear() {
37
+ maxFramesInBuffer = null;
38
+ sps = null;
39
+ prevPicOrderCntLsb = 0;
40
+ prevPicOrderCntMsb = 0;
41
+ },
42
+ };
43
+ };
44
+ exports.avcState = avcState;
@@ -40,5 +40,9 @@ export declare const isoBaseMediaState: ({ contentLength, controller, readerInte
40
40
  getTfraBoxes: () => import("../../containers/iso-base-media/mfra/tfra").TfraBox[];
41
41
  setTfraBoxes: (boxes: import("../../containers/iso-base-media/mfra/tfra").TfraBox[]) => void;
42
42
  };
43
+ movieTimeScale: {
44
+ getTrackTimescale: () => number | null;
45
+ setTrackTimescale: (timescale: number) => void;
46
+ };
43
47
  };
44
48
  export type IsoBaseMediaState = ReturnType<typeof isoBaseMediaState>;
@@ -6,6 +6,7 @@ const lazy_mfra_load_1 = require("./lazy-mfra-load");
6
6
  const moov_box_1 = require("./moov-box");
7
7
  const precomputed_moof_1 = require("./precomputed-moof");
8
8
  const precomputed_tfra_1 = require("./precomputed-tfra");
9
+ const timescale_state_1 = require("./timescale-state");
9
10
  const isoBaseMediaState = ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }) => {
10
11
  return {
11
12
  flatSamples: (0, cached_sample_positions_1.cachedSamplePositionsState)(),
@@ -20,6 +21,7 @@ const isoBaseMediaState = ({ contentLength, controller, readerInterface, src, lo
20
21
  }),
21
22
  moof: (0, precomputed_moof_1.precomputedMoofState)(),
22
23
  tfra: (0, precomputed_tfra_1.precomputedTfraState)(),
24
+ movieTimeScale: (0, timescale_state_1.movieTimeScaleState)(),
23
25
  };
24
26
  };
25
27
  exports.isoBaseMediaState = isoBaseMediaState;
@@ -0,0 +1,5 @@
1
+ export declare const movieTimeScaleState: () => {
2
+ getTrackTimescale: () => number | null;
3
+ setTrackTimescale: (timescale: number) => void;
4
+ };
5
+ export type MovieTimeScaleState = ReturnType<typeof movieTimeScaleState>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.movieTimeScaleState = void 0;
4
+ const movieTimeScaleState = () => {
5
+ let trackTimescale = null;
6
+ return {
7
+ getTrackTimescale: () => trackTimescale,
8
+ setTrackTimescale: (timescale) => {
9
+ trackTimescale = timescale;
10
+ },
11
+ };
12
+ };
13
+ exports.movieTimeScaleState = movieTimeScaleState;
@@ -45,6 +45,13 @@ export declare const makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHan
45
45
  onProfile: (profile: SpsAndPps) => Promise<void>;
46
46
  registerOnAvcProfileCallback: (callback: (profile: SpsAndPps) => Promise<void>) => void;
47
47
  getNextTrackIndex: () => number;
48
+ queuedBFrames: {
49
+ addFrame: (frame: import("./riff/queued-frames").QueuedVideoSample, maxFramesInBuffer: number) => void;
50
+ flush: () => void;
51
+ getReleasedFrame: () => import("./riff/queued-frames").QueuedVideoSample | null;
52
+ hasReleasedFrames: () => boolean;
53
+ clear: () => void;
54
+ };
48
55
  incrementNextTrackIndex: () => void;
49
56
  lazyIdx1: {
50
57
  triggerLoad: (position: number) => Promise<{
@@ -67,14 +74,24 @@ export declare const makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHan
67
74
  };
68
75
  sampleCounter: {
69
76
  onAudioSample: (trackId: number, audioSample: import("../webcodec-sample-types").MediaParserAudioSample) => void;
70
- onVideoSample: (trackId: number, videoSample: import("../webcodec-sample-types").MediaParserVideoSample) => void;
71
- getSamplesForTrack: (trackId: number) => number;
77
+ onVideoSample: (videoSample: import("../webcodec-sample-types").MediaParserVideoSample) => void;
78
+ getSampleCountForTrack: ({ trackId }: {
79
+ trackId: number;
80
+ }) => number;
72
81
  setSamplesFromSeek: (samples: Record<number, number>) => void;
73
82
  riffKeys: {
74
83
  addKeyframe: (keyframe: import("./riff/riff-keyframes").RiffKeyframe) => void;
75
84
  getKeyframes: () => import("./riff/riff-keyframes").RiffKeyframe[];
76
85
  setFromSeekingHints: (keyframesFromHints: import("./riff/riff-keyframes").RiffKeyframe[]) => void;
77
86
  };
87
+ setPocAtKeyframeOffset: ({ keyframeOffset, poc, }: {
88
+ keyframeOffset: number;
89
+ poc: number;
90
+ }) => void;
91
+ getPocAtKeyframeOffset: ({ keyframeOffset, }: {
92
+ keyframeOffset: number;
93
+ }) => number[];
94
+ getKeyframeAtOffset: (sample: import("./riff/queued-frames").QueuedVideoSample) => number | null;
78
95
  };
79
96
  };
80
97
  transportStream: {
@@ -100,7 +117,7 @@ export declare const makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHan
100
117
  resetBeforeSeek: () => void;
101
118
  lastEmittedSample: {
102
119
  setLastEmittedSample: (sample: import("../webcodec-sample-types").MediaParserAudioSample | import("../webcodec-sample-types").MediaParserVideoSample) => void;
103
- getLastEmittedSample: () => import("../webcodec-sample-types").MediaParserAudioSample | import("../webcodec-sample-types").MediaParserVideoSample | null;
120
+ getLastEmittedSample: () => import("../webcodec-sample-types").MediaParserVideoSample | import("../webcodec-sample-types").MediaParserAudioSample | null;
104
121
  resetLastEmittedSample: () => void;
105
122
  };
106
123
  };
@@ -163,6 +180,10 @@ export declare const makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHan
163
180
  getTfraBoxes: () => import("../containers/iso-base-media/mfra/tfra").TfraBox[];
164
181
  setTfraBoxes: (boxes: import("../containers/iso-base-media/mfra/tfra").TfraBox[]) => void;
165
182
  };
183
+ movieTimeScale: {
184
+ getTrackTimescale: () => number | null;
185
+ setTrackTimescale: (timescale: number) => void;
186
+ };
166
187
  };
167
188
  mp3: {
168
189
  getMp3Info: () => import("./mp3").Mp3Info | null;
@@ -465,5 +486,15 @@ export declare const makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHan
465
486
  };
466
487
  makeSamplesStartAtZero: boolean;
467
488
  prefetchCache: PrefetchCache;
489
+ avc: {
490
+ getPrevPicOrderCntLsb(): number;
491
+ getPrevPicOrderCntMsb(): number;
492
+ setPrevPicOrderCntLsb(value: number): void;
493
+ setPrevPicOrderCntMsb(value: number): void;
494
+ setSps(value: import("../containers/avc/parse-avc").SpsInfo): void;
495
+ getSps(): import("../containers/avc/parse-avc").SpsInfo | null;
496
+ getMaxFramesInBuffer(): number | null;
497
+ clear(): void;
498
+ };
468
499
  };
469
500
  export type ParserState = ReturnType<typeof makeParserState>;
@@ -5,6 +5,7 @@ const get_fields_from_callbacks_1 = require("../get-fields-from-callbacks");
5
5
  const buffer_iterator_1 = require("../iterator/buffer-iterator");
6
6
  const log_1 = require("../log");
7
7
  const aac_state_1 = require("./aac-state");
8
+ const avc_state_1 = require("./avc/avc-state");
8
9
  const current_reader_1 = require("./current-reader");
9
10
  const emitted_fields_1 = require("./emitted-fields");
10
11
  const flac_state_1 = require("./flac-state");
@@ -38,6 +39,7 @@ const makeParserState = ({ hasAudioTrackHandlers, hasVideoTrackHandlers, control
38
39
  const timings = (0, timings_1.timingsState)();
39
40
  const seekInfiniteLoop = (0, seek_infinite_loop_1.seekInfiniteLoopDetectionState)();
40
41
  const currentReaderState = (0, current_reader_1.currentReader)(initialReaderInstance);
42
+ const avc = (0, avc_state_1.avcState)();
41
43
  const errored = null;
42
44
  const discardReadBytes = async (force) => {
43
45
  const { bytesRemoved, removedData } = iterator.removeBytesRead(force, mode);
@@ -135,6 +137,7 @@ const makeParserState = ({ hasAudioTrackHandlers, hasVideoTrackHandlers, control
135
137
  seekInfiniteLoop,
136
138
  makeSamplesStartAtZero,
137
139
  prefetchCache,
140
+ avc,
138
141
  };
139
142
  };
140
143
  exports.makeParserState = makeParserState;
@@ -0,0 +1,9 @@
1
+ import type { MediaParserVideoSample } from '../../webcodec-sample-types';
2
+ export type QueuedVideoSample = Omit<MediaParserVideoSample, 'cts' | 'dts' | 'timestamp'>;
3
+ export declare const queuedBFramesState: () => {
4
+ addFrame: (frame: QueuedVideoSample, maxFramesInBuffer: number) => void;
5
+ flush: () => void;
6
+ getReleasedFrame: () => QueuedVideoSample | null;
7
+ hasReleasedFrames: () => boolean;
8
+ clear: () => void;
9
+ };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queuedBFramesState = void 0;
4
+ const queuedBFramesState = () => {
5
+ const queuedFrames = [];
6
+ const releasedFrames = [];
7
+ const sortFrames = () => {
8
+ queuedFrames.sort((a, b) => {
9
+ if (!a.avc || !b.avc || a.avc.poc === null || b.avc.poc === null) {
10
+ throw new Error('Invalid frame');
11
+ }
12
+ return a.avc.poc - b.avc.poc;
13
+ });
14
+ };
15
+ const flush = () => {
16
+ sortFrames();
17
+ releasedFrames.push(...queuedFrames);
18
+ queuedFrames.length = 0;
19
+ };
20
+ return {
21
+ addFrame: (frame, maxFramesInBuffer) => {
22
+ if (frame.type === 'key') {
23
+ flush();
24
+ }
25
+ queuedFrames.push(frame);
26
+ if (queuedFrames.length > maxFramesInBuffer) {
27
+ sortFrames();
28
+ releasedFrames.push(queuedFrames.shift());
29
+ }
30
+ },
31
+ flush,
32
+ getReleasedFrame: () => {
33
+ if (releasedFrames.length === 0) {
34
+ return null;
35
+ }
36
+ return releasedFrames.shift();
37
+ },
38
+ hasReleasedFrames: () => {
39
+ return releasedFrames.length > 0;
40
+ },
41
+ clear: () => {
42
+ releasedFrames.length = 0;
43
+ queuedFrames.length = 0;
44
+ },
45
+ };
46
+ };
47
+ exports.queuedBFramesState = queuedBFramesState;
@@ -0,0 +1,9 @@
1
+ import type { MediaParserVideoSample } from '../../webcodec-sample-types';
2
+ export type QueuedVideoSample = Omit<MediaParserVideoSample, 'cts' | 'dts' | 'timestamp'>;
3
+ export declare const queuedBFramesState: () => {
4
+ addFrame: (frame: QueuedVideoSample, maxFramesInBuffer: number) => void;
5
+ flush: () => void;
6
+ getReleasedFrame: () => QueuedVideoSample | null;
7
+ hasReleasedFrames: () => boolean;
8
+ clear: () => void;
9
+ };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queuedBFramesState = void 0;
4
+ const queuedBFramesState = () => {
5
+ const queuedFrames = [];
6
+ const releasedFrames = [];
7
+ const flush = () => {
8
+ releasedFrames.push(...queuedFrames);
9
+ queuedFrames.length = 0;
10
+ };
11
+ return {
12
+ addFrame: (frame, maxFramesInBuffer) => {
13
+ if (frame.type === 'key') {
14
+ flush();
15
+ releasedFrames.push(frame);
16
+ return;
17
+ }
18
+ queuedFrames.push(frame);
19
+ if (queuedFrames.length > maxFramesInBuffer) {
20
+ releasedFrames.push(queuedFrames.shift());
21
+ }
22
+ },
23
+ flush,
24
+ getReleasedFrame: () => {
25
+ if (releasedFrames.length === 0) {
26
+ return null;
27
+ }
28
+ return releasedFrames.shift();
29
+ },
30
+ hasReleasedFrames: () => {
31
+ return releasedFrames.length > 0;
32
+ },
33
+ clear: () => {
34
+ releasedFrames.length = 0;
35
+ queuedFrames.length = 0;
36
+ },
37
+ };
38
+ };
39
+ exports.queuedBFramesState = queuedBFramesState;
@@ -8,6 +8,7 @@ const riffKeyframesState = () => {
8
8
  return;
9
9
  }
10
10
  keyframes.push(keyframe);
11
+ keyframes.sort((a, b) => a.positionInBytes - b.positionInBytes);
11
12
  };
12
13
  const getKeyframes = () => {
13
14
  return keyframes;
@@ -1,12 +1,23 @@
1
1
  import type { MediaParserAudioSample, MediaParserVideoSample } from '../../webcodec-sample-types';
2
+ import type { QueuedVideoSample } from './queued-frames';
2
3
  export declare const riffSampleCounter: () => {
3
4
  onAudioSample: (trackId: number, audioSample: MediaParserAudioSample) => void;
4
- onVideoSample: (trackId: number, videoSample: MediaParserVideoSample) => void;
5
- getSamplesForTrack: (trackId: number) => number;
5
+ onVideoSample: (videoSample: MediaParserVideoSample) => void;
6
+ getSampleCountForTrack: ({ trackId }: {
7
+ trackId: number;
8
+ }) => number;
6
9
  setSamplesFromSeek: (samples: Record<number, number>) => void;
7
10
  riffKeys: {
8
11
  addKeyframe: (keyframe: import("./riff-keyframes").RiffKeyframe) => void;
9
12
  getKeyframes: () => import("./riff-keyframes").RiffKeyframe[];
10
13
  setFromSeekingHints: (keyframesFromHints: import("./riff-keyframes").RiffKeyframe[]) => void;
11
14
  };
15
+ setPocAtKeyframeOffset: ({ keyframeOffset, poc, }: {
16
+ keyframeOffset: number;
17
+ poc: number;
18
+ }) => void;
19
+ getPocAtKeyframeOffset: ({ keyframeOffset, }: {
20
+ keyframeOffset: number;
21
+ }) => number[];
22
+ getKeyframeAtOffset: (sample: QueuedVideoSample) => number | null;
12
23
  };
@@ -4,6 +4,8 @@ exports.riffSampleCounter = void 0;
4
4
  const riff_keyframes_1 = require("./riff-keyframes");
5
5
  const riffSampleCounter = () => {
6
6
  const samplesForTrack = {};
7
+ // keyframe offset -> poc[]
8
+ const pocsAtKeyframeOffset = {};
7
9
  const riffKeys = (0, riff_keyframes_1.riffKeyframesState)();
8
10
  const onAudioSample = (trackId, audioSample) => {
9
11
  if (typeof samplesForTrack[trackId] === 'undefined') {
@@ -14,13 +16,13 @@ const riffSampleCounter = () => {
14
16
  }
15
17
  samplesForTrack[trackId]++;
16
18
  };
17
- const onVideoSample = (trackId, videoSample) => {
18
- if (typeof samplesForTrack[trackId] === 'undefined') {
19
- samplesForTrack[trackId] = 0;
19
+ const onVideoSample = (videoSample) => {
20
+ if (typeof samplesForTrack[videoSample.trackId] === 'undefined') {
21
+ samplesForTrack[videoSample.trackId] = 0;
20
22
  }
21
23
  if (videoSample.type === 'key') {
22
24
  riffKeys.addKeyframe({
23
- trackId,
25
+ trackId: videoSample.trackId,
24
26
  decodingTimeInSeconds: videoSample.dts / videoSample.timescale,
25
27
  positionInBytes: videoSample.offset,
26
28
  presentationTimeInSeconds: videoSample.cts / videoSample.timescale,
@@ -29,10 +31,10 @@ const riffSampleCounter = () => {
29
31
  });
30
32
  }
31
33
  if (videoSample.data.length > 0) {
32
- samplesForTrack[trackId]++;
34
+ samplesForTrack[videoSample.trackId]++;
33
35
  }
34
36
  };
35
- const getSamplesForTrack = (trackId) => {
37
+ const getSampleCountForTrack = ({ trackId }) => {
36
38
  var _a;
37
39
  return (_a = samplesForTrack[trackId]) !== null && _a !== void 0 ? _a : 0;
38
40
  };
@@ -41,12 +43,37 @@ const riffSampleCounter = () => {
41
43
  samplesForTrack[trackId] = samples[trackId];
42
44
  }
43
45
  };
46
+ const setPocAtKeyframeOffset = ({ keyframeOffset, poc, }) => {
47
+ if (typeof pocsAtKeyframeOffset[keyframeOffset] === 'undefined') {
48
+ pocsAtKeyframeOffset[keyframeOffset] = [];
49
+ }
50
+ if (pocsAtKeyframeOffset[keyframeOffset].includes(poc)) {
51
+ return;
52
+ }
53
+ pocsAtKeyframeOffset[keyframeOffset].push(poc);
54
+ pocsAtKeyframeOffset[keyframeOffset].sort((a, b) => a - b);
55
+ };
56
+ const getPocAtKeyframeOffset = ({ keyframeOffset, }) => {
57
+ return pocsAtKeyframeOffset[keyframeOffset];
58
+ };
59
+ const getKeyframeAtOffset = (sample) => {
60
+ var _a, _b;
61
+ if (sample.type === 'key') {
62
+ return sample.offset;
63
+ }
64
+ return ((_b = (_a = riffKeys
65
+ .getKeyframes()
66
+ .findLast((k) => k.positionInBytes <= sample.offset)) === null || _a === void 0 ? void 0 : _a.positionInBytes) !== null && _b !== void 0 ? _b : null);
67
+ };
44
68
  return {
45
69
  onAudioSample,
46
70
  onVideoSample,
47
- getSamplesForTrack,
71
+ getSampleCountForTrack,
48
72
  setSamplesFromSeek,
49
73
  riffKeys,
74
+ setPocAtKeyframeOffset,
75
+ getPocAtKeyframeOffset,
76
+ getKeyframeAtOffset,
50
77
  };
51
78
  };
52
79
  exports.riffSampleCounter = riffSampleCounter;