@@ -118,12 +118,16 @@ class AtomToken {
118118 );
119119 }
120120
121- final extendedLength = readUint64Be (bytes, 8 );
122- if (extendedLength > 0x7FFFFFFF ) {
121+ final extendedLength = _readUint64BeAsBigInt (bytes, 8 );
122+ if (extendedLength > BigInt . from ( 0x7FFFFFFF ) ) {
123123 throw Mp4ContentError ('Atom too large for parser: $extendedLength bytes' );
124124 }
125125
126- return AtomHeader (length: extendedLength, name: name, headerLength: 16 );
126+ return AtomHeader (
127+ length: extendedLength.toInt (),
128+ name: name,
129+ headerLength: 16 ,
130+ );
127131 }
128132
129133 static List <String > parseFtypBrands (List <int > bytes) {
@@ -150,15 +154,15 @@ class AtomToken {
150154 if (bytes.length < 32 ) {
151155 throw Mp4ContentError ('mvhd version 1 payload too short' );
152156 }
153- final creation = readUint64Be (bytes, 4 );
154- final modification = readUint64Be (bytes, 12 );
157+ final creation = _readUint64BeAsBigInt (bytes, 4 );
158+ final modification = _readUint64BeAsBigInt (bytes, 12 );
155159 final timeScale = readUint32Be (bytes, 20 );
156- final duration = readUint64Be (bytes, 24 );
160+ final duration = _readUint64BeAsBigInt (bytes, 24 );
157161 return MvhdAtomData (
158- creationTime: _macEpochToDate (creation),
159- modificationTime: _macEpochToDate (modification),
162+ creationTime: _macEpochToDateBigInt (creation),
163+ modificationTime: _macEpochToDateBigInt (modification),
160164 timeScale: timeScale,
161- duration: duration,
165+ duration: duration. toInt () ,
162166 );
163167 }
164168
@@ -167,8 +171,8 @@ class AtomToken {
167171 final timeScale = readUint32Be (bytes, 12 );
168172 final duration = readUint32Be (bytes, 16 );
169173 return MvhdAtomData (
170- creationTime: _macEpochToDate (creation),
171- modificationTime: _macEpochToDate (modification),
174+ creationTime: _macEpochToDateInt (creation),
175+ modificationTime: _macEpochToDateInt (modification),
172176 timeScale: timeScale,
173177 duration: duration,
174178 );
@@ -186,7 +190,7 @@ class AtomToken {
186190 }
187191 return MdhdAtomData (
188192 timeScale: readUint32Be (bytes, 20 ),
189- duration: readUint64Be (bytes, 24 ),
193+ duration: _readUint64BeAsBigInt (bytes, 24 ). toInt ( ),
190194 );
191195 }
192196
@@ -381,27 +385,55 @@ class AtomToken {
381385 }
382386
383387 static int readUint64Be (List <int > bytes, int offset) {
388+ final value = _readUint64BeAsBigInt (bytes, offset);
389+ if (value > BigInt .from (0x7FFFFFFFFFFFFFFF )) {
390+ throw Mp4ContentError ('64-bit integer overflow for parser runtime' );
391+ }
392+ return value.toInt ();
393+ }
394+
395+ static BigInt _readUint64BeAsBigInt (List <int > bytes, int offset) {
384396 _ensureRange (bytes, offset, 8 );
385- final value =
386- (BigInt .from (bytes[offset]) << 56 ) |
397+ return (BigInt .from (bytes[offset]) << 56 ) |
387398 (BigInt .from (bytes[offset + 1 ]) << 48 ) |
388399 (BigInt .from (bytes[offset + 2 ]) << 40 ) |
389400 (BigInt .from (bytes[offset + 3 ]) << 32 ) |
390401 (BigInt .from (bytes[offset + 4 ]) << 24 ) |
391402 (BigInt .from (bytes[offset + 5 ]) << 16 ) |
392403 (BigInt .from (bytes[offset + 6 ]) << 8 ) |
393404 BigInt .from (bytes[offset + 7 ]);
394- // Dart int is 64-bit on native platforms, allow full signed 64-bit range
395- if (value > BigInt .from (0x7FFFFFFFFFFFFFFF )) {
396- throw Mp4ContentError ('64-bit integer overflow for parser runtime' );
397- }
398- return value.toInt ();
399405 }
400406
401- static DateTime _macEpochToDate (int secondsSinceMacEpoch) {
407+ static DateTime _macEpochToDateInt (int secondsSinceMacEpoch) {
408+ return _macEpochToDateBigInt (BigInt .from (secondsSinceMacEpoch));
409+ }
410+
411+ static DateTime _macEpochToDateBigInt (BigInt secondsSinceMacEpoch) {
402412 const macToUnixEpochSeconds = 2082844800 ;
403- final unixSeconds = secondsSinceMacEpoch - macToUnixEpochSeconds;
404- return DateTime .fromMillisecondsSinceEpoch (unixSeconds * 1000 , isUtc: true );
413+ const maxDateTimeMilliseconds = 8640000000000000 ;
414+ const minDateTimeMilliseconds = - 8640000000000000 ;
415+ final unixSeconds =
416+ secondsSinceMacEpoch - BigInt .from (macToUnixEpochSeconds);
417+ final milliseconds = unixSeconds * BigInt .from (1000 );
418+
419+ if (milliseconds > BigInt .from (maxDateTimeMilliseconds)) {
420+ return DateTime .fromMillisecondsSinceEpoch (
421+ maxDateTimeMilliseconds,
422+ isUtc: true ,
423+ );
424+ }
425+
426+ if (milliseconds < BigInt .from (minDateTimeMilliseconds)) {
427+ return DateTime .fromMillisecondsSinceEpoch (
428+ minDateTimeMilliseconds,
429+ isUtc: true ,
430+ );
431+ }
432+
433+ return DateTime .fromMillisecondsSinceEpoch (
434+ milliseconds.toInt (),
435+ isUtc: true ,
436+ );
405437 }
406438
407439 static void _ensureRange (List <int > bytes, int offset, int length) {
0 commit comments