mirror of
https://github.com/samsonjs/media.git
synced 2026-04-19 13:35:47 +00:00
Use 4 Byte size field in fMP4 mdat boxes
Since mdat box can be huge so there is a provision to use 64 bit size field. In case of fragmented MP4, individual fragments should not have large mdat box so a 32 bit size field should be sufficient. PiperOrigin-RevId: 599219041
This commit is contained in:
parent
406c0a15be
commit
666685bd85
4 changed files with 21 additions and 17 deletions
|
|
@ -17,6 +17,7 @@ package androidx.media3.muxer;
|
|||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.muxer.Mp4Utils.UNSIGNED_INT_MAX_VALUE;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
|
|
@ -174,13 +175,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
|
||||
private void writeMdatBox() throws IOException {
|
||||
long mdatStartPosition = output.position();
|
||||
// 4 bytes (indicating a 64-bit length field) + 4 bytes (box name) + 8 bytes (the actual length)
|
||||
ByteBuffer header = ByteBuffer.allocate(16);
|
||||
// This 32-bit integer in general contains the total length of the box. Here value 1 indicates
|
||||
// that the actual length is stored as 64-bit integer after the box name.
|
||||
header.putInt(1);
|
||||
int mdatHeaderSize = 8; // 4 bytes (box size) + 4 bytes (box name)
|
||||
ByteBuffer header = ByteBuffer.allocate(mdatHeaderSize);
|
||||
header.putInt(mdatHeaderSize); // The total box size so far.
|
||||
header.put(Util.getUtf8Bytes("mdat"));
|
||||
header.putLong(16); // The total box length so far.
|
||||
header.flip();
|
||||
output.write(header);
|
||||
|
||||
|
|
@ -201,13 +199,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
|
||||
long currentPosition = output.position();
|
||||
|
||||
// Skip 4 bytes (64-bit length indication) + 4 bytes (box name).
|
||||
output.position(mdatStartPosition + 8);
|
||||
ByteBuffer mdatSize = ByteBuffer.allocate(8); // 64-bit length.
|
||||
// Additional 4 bytes (64-bit length indication) + 4 bytes (box name) + 8 bytes (actual length).
|
||||
mdatSize.putLong(bytesWritten + 16);
|
||||
mdatSize.flip();
|
||||
output.write(mdatSize);
|
||||
output.position(mdatStartPosition);
|
||||
ByteBuffer mdatSizeByteBuffer = ByteBuffer.allocate(4);
|
||||
long mdatSize = bytesWritten + mdatHeaderSize;
|
||||
checkArgument(
|
||||
mdatSize <= UNSIGNED_INT_MAX_VALUE,
|
||||
"Only 32-bit long mdat size supported in the fragmented MP4");
|
||||
mdatSizeByteBuffer.putInt((int) mdatSize);
|
||||
mdatSizeByteBuffer.flip();
|
||||
output.write(mdatSizeByteBuffer);
|
||||
output.position(currentPosition);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package androidx.media3.muxer;
|
|||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.muxer.Mp4Utils.UNSIGNED_INT_MAX_VALUE;
|
||||
|
||||
import androidx.media3.container.Mp4Util;
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -61,9 +62,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
}
|
||||
|
||||
public void setModificationTime(long unixTimestampMs) {
|
||||
long maxUnsignedInt = 4294967295L;
|
||||
long timestampSeconds = Mp4Util.unixTimeToMp4TimeSeconds(unixTimestampMs);
|
||||
checkArgument(timestampSeconds <= maxUnsignedInt, "Only 32-bit long timestamp supported");
|
||||
checkArgument(
|
||||
timestampSeconds <= UNSIGNED_INT_MAX_VALUE, "Only 32-bit long timestamp supported");
|
||||
this.modificationTimestampSeconds = (int) timestampSeconds;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ package androidx.media3.muxer;
|
|||
*/
|
||||
public static final int MAX_FIXED_LEAF_BOX_SIZE = 200;
|
||||
|
||||
/** The maximum value of a 32-bit unsigned int. */
|
||||
public static final long UNSIGNED_INT_MAX_VALUE = 4_294_967_295L;
|
||||
|
||||
/**
|
||||
* The per-video timebase, used for durations in MVHD and TKHD even if the per-track timebase is
|
||||
* different (e.g. typically the sample rate for audio).
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ moof (2852 bytes):
|
|||
Data = length 8, hash 94446F03
|
||||
trun (1684 bytes):
|
||||
Data = length 1676, hash 46E974DC
|
||||
mdat (5712395 bytes):
|
||||
mdat (5712387 bytes):
|
||||
Data = length 5712379, hash 86B2819D
|
||||
moof (1220 bytes):
|
||||
mfhd (16 bytes):
|
||||
|
|
@ -86,5 +86,5 @@ moof (1220 bytes):
|
|||
Data = length 8, hash 94446F03
|
||||
trun (688 bytes):
|
||||
Data = length 680, hash 4E3D2F16
|
||||
mdat (2364929 bytes):
|
||||
mdat (2364921 bytes):
|
||||
Data = length 2364913, hash D363A845
|
||||
|
|
|
|||
Loading…
Reference in a new issue