diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java similarity index 97% rename from libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java rename to libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java index 2cec2512fb..a4eb4b5adb 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java @@ -34,6 +34,7 @@ import androidx.media3.common.util.Log; import androidx.media3.common.util.NullableType; import androidx.media3.common.util.ParsableBitArray; import androidx.media3.common.util.ParsableByteArray; +import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.container.Mp4Box; import androidx.media3.container.Mp4Box.LeafBox; @@ -60,11 +61,12 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; -/** Utility methods for parsing MP4 format atom payloads according to ISO/IEC 14496-12. */ +/** Utility methods for parsing MP4 format box payloads according to ISO/IEC 14496-12. */ @SuppressWarnings("ConstantField") -/* package */ final class AtomParsers { +@UnstableApi +public final class BoxParser { - private static final String TAG = "AtomParsers"; + private static final String TAG = "BoxParsers"; @SuppressWarnings("ConstantCaseForConstants") private static final int TYPE_clcp = 0x636c6370; @@ -105,29 +107,29 @@ import java.util.Objects; /** The magic signature for an Opus Identification header, as defined in RFC-7845. */ private static final byte[] opusMagic = Util.getUtf8Bytes("OpusHead"); - /** Parses the version number out of the additional integer component of a full atom. */ - public static int parseFullAtomVersion(int fullAtomInt) { - return 0x000000FF & (fullAtomInt >> 24); + /** Parses the version number out of the additional integer component of a full box. */ + public static int parseFullBoxVersion(int fullBoxInt) { + return 0x000000FF & (fullBoxInt >> 24); } - /** Parses the atom flags out of the additional integer component of a full atom. */ - public static int parseFullAtomFlags(int fullAtomInt) { - return 0x00FFFFFF & fullAtomInt; + /** Parses the box flags out of the additional integer component of a full box. */ + public static int parseFullBoxFlags(int fullBoxInt) { + return 0x00FFFFFF & fullBoxInt; } /** - * Parse the trak atoms in a moov atom (defined in ISO/IEC 14496-12). + * Parse the trak boxes in a moov box (defined in ISO/IEC 14496-12). * - * @param moov Moov atom to decode. + * @param moov Moov box to decode. * @param gaplessInfoHolder Holder to populate with gapless playback information. - * @param duration The duration in units of the timescale declared in the mvhd atom, or {@link - * C#TIME_UNSET} if the duration should be parsed from the tkhd atom. + * @param duration The duration in units of the timescale declared in the mvhd box, or {@link + * C#TIME_UNSET} if the duration should be parsed from the tkhd box. * @param drmInitData {@link DrmInitData} to be included in the format, or {@code null}. * @param ignoreEditLists Whether to ignore any edit lists in the trak boxes. * @param isQuickTime True for QuickTime media. False otherwise. * @param modifyTrackFunction A function to apply to the {@link Track Tracks} in the result. * @return A list of {@link TrackSampleTable} instances. - * @throws ParserException Thrown if the trak atoms can't be parsed. + * @throws ParserException Thrown if the trak boxes can't be parsed. */ public static List parseTraks( Mp4Box.ContainerBox moov, @@ -170,13 +172,13 @@ import java.util.Objects; } /** - * Parses a udta atom. + * Parses a udta box. * - * @param udtaAtom The udta (user data) atom to decode. + * @param udtaBox The udta (user data) box to decode. * @return Parsed metadata. */ - public static Metadata parseUdta(LeafBox udtaAtom) { - ParsableByteArray udtaData = udtaAtom.data; + public static Metadata parseUdta(LeafBox udtaBox) { + ParsableByteArray udtaData = udtaBox.data; udtaData.setPosition(Mp4Box.HEADER_SIZE); Metadata metadata = new Metadata(); while (udtaData.bytesLeft() >= Mp4Box.HEADER_SIZE) { @@ -201,15 +203,15 @@ import java.util.Objects; } /** - * Parses an mvhd atom (defined in ISO/IEC 14496-12). + * Parses an mvhd box (defined in ISO/IEC 14496-12). * - * @param mvhd Contents of the mvhd atom to be parsed. + * @param mvhd Contents of the mvhd box to be parsed. * @return An object containing the parsed data. */ public static Mp4TimestampData parseMvhd(ParsableByteArray mvhd) { mvhd.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = mvhd.readInt(); - int version = parseFullAtomVersion(fullAtom); + int version = parseFullBoxVersion(fullAtom); long creationTimestampSeconds; long modificationTimestampSeconds; if (version == 0) { @@ -225,9 +227,9 @@ import java.util.Objects; } /** - * Parses a metadata meta atom if it contains metadata with handler 'mdta'. + * Parses a metadata meta box if it contains metadata with handler 'mdta'. * - * @param meta The metadata atom to decode. + * @param meta The metadata box to decode. * @return Parsed metadata, or null. */ @Nullable @@ -280,17 +282,17 @@ import java.util.Objects; } /** - * Possibly skips the version and flags fields (1+3 byte) of a full meta atom. + * Possibly skips the version and flags fields (1+3 byte) of a full meta box. * - *

Atoms of type {@link Mp4Box#TYPE_meta} are defined to be full atoms which have four + *

Boxes of type {@link Mp4Box#TYPE_meta} are defined to be full boxes which have four * additional bytes for a version and a flags field (see 4.2 'Object Structure' in ISO/IEC * 14496-12:2005). QuickTime do not have such a full box structure. Since some of these files are * encoded wrongly, we can't rely on the file type though. Instead we must check the 8 bytes after * the common header bytes ourselves. * - * @param meta The 8 or more bytes following the meta atom size and type. + * @param meta The 8 or more bytes following the meta box size and type. */ - public static void maybeSkipRemainingMetaAtomHeaderBytes(ParsableByteArray meta) { + public static void maybeSkipRemainingMetaBoxHeaderBytes(ParsableByteArray meta) { int endPosition = meta.getPosition(); // The next 8 bytes can be either: // (iso) [1 byte version + 3 bytes flags][4 byte size of next atom] @@ -304,20 +306,20 @@ import java.util.Objects; } /** - * Parses a trak atom (defined in ISO/IEC 14496-12). + * Parses a trak box (defined in ISO/IEC 14496-12). * - * @param trak Atom to decode. - * @param mvhd Movie header atom, used to get the timescale. - * @param duration The duration in units of the timescale declared in the mvhd atom, or {@link - * C#TIME_UNSET} if the duration should be parsed from the tkhd atom. + * @param trak Box to decode. + * @param mvhd Movie header box, used to get the timescale. + * @param duration The duration in units of the timescale declared in the mvhd box, or {@link + * C#TIME_UNSET} if the duration should be parsed from the tkhd box. * @param drmInitData {@link DrmInitData} to be included in the format, or {@code null}. * @param ignoreEditLists Whether to ignore any edit lists in the trak box. * @param isQuickTime True for QuickTime media. False otherwise. * @return A {@link Track} instance, or {@code null} if the track's type isn't supported. - * @throws ParserException Thrown if the trak atom can't be parsed. + * @throws ParserException Thrown if the trak box can't be parsed. */ @Nullable - private static Track parseTrak( + public static Track parseTrak( Mp4Box.ContainerBox trak, LeafBox mvhd, long duration, @@ -393,23 +395,23 @@ import java.util.Objects; } /** - * Parses an stbl atom (defined in ISO/IEC 14496-12). + * Parses an stbl box (defined in ISO/IEC 14496-12). * * @param track Track to which this sample table corresponds. - * @param stblAtom stbl (sample table) atom to decode. + * @param stblBox stbl (sample table) box to decode. * @param gaplessInfoHolder Holder to populate with gapless playback information. - * @return Sample table described by the stbl atom. - * @throws ParserException Thrown if the stbl atom can't be parsed. + * @return Sample table described by the stbl box. + * @throws ParserException Thrown if the stbl box can't be parsed. */ - private static TrackSampleTable parseStbl( - Track track, Mp4Box.ContainerBox stblAtom, GaplessInfoHolder gaplessInfoHolder) + public static TrackSampleTable parseStbl( + Track track, Mp4Box.ContainerBox stblBox, GaplessInfoHolder gaplessInfoHolder) throws ParserException { SampleSizeBox sampleSizeBox; - @Nullable LeafBox stszAtom = stblAtom.getLeafBoxOfType(Mp4Box.TYPE_stsz); + @Nullable LeafBox stszAtom = stblBox.getLeafBoxOfType(Mp4Box.TYPE_stsz); if (stszAtom != null) { sampleSizeBox = new StszSampleSizeBox(stszAtom, track.format); } else { - @Nullable LeafBox stz2Atom = stblAtom.getLeafBoxOfType(Mp4Box.TYPE_stz2); + @Nullable LeafBox stz2Atom = stblBox.getLeafBoxOfType(Mp4Box.TYPE_stz2); if (stz2Atom == null) { throw ParserException.createForMalformedContainer( "Track has no sample table size information", /* cause= */ null); @@ -431,21 +433,21 @@ import java.util.Objects; // Entries are byte offsets of chunks. boolean chunkOffsetsAreLongs = false; - @Nullable LeafBox chunkOffsetsAtom = stblAtom.getLeafBoxOfType(Mp4Box.TYPE_stco); + @Nullable LeafBox chunkOffsetsAtom = stblBox.getLeafBoxOfType(Mp4Box.TYPE_stco); if (chunkOffsetsAtom == null) { chunkOffsetsAreLongs = true; - chunkOffsetsAtom = checkNotNull(stblAtom.getLeafBoxOfType(Mp4Box.TYPE_co64)); + chunkOffsetsAtom = checkNotNull(stblBox.getLeafBoxOfType(Mp4Box.TYPE_co64)); } ParsableByteArray chunkOffsets = chunkOffsetsAtom.data; // Entries are (chunk number, number of samples per chunk, sample description index). - ParsableByteArray stsc = checkNotNull(stblAtom.getLeafBoxOfType(Mp4Box.TYPE_stsc)).data; + ParsableByteArray stsc = checkNotNull(stblBox.getLeafBoxOfType(Mp4Box.TYPE_stsc)).data; // Entries are (number of samples, timestamp delta between those samples). - ParsableByteArray stts = checkNotNull(stblAtom.getLeafBoxOfType(Mp4Box.TYPE_stts)).data; + ParsableByteArray stts = checkNotNull(stblBox.getLeafBoxOfType(Mp4Box.TYPE_stts)).data; // Entries are the indices of samples that are synchronization samples. - @Nullable LeafBox stssAtom = stblAtom.getLeafBoxOfType(Mp4Box.TYPE_stss); + @Nullable LeafBox stssAtom = stblBox.getLeafBoxOfType(Mp4Box.TYPE_stss); @Nullable ParsableByteArray stss = stssAtom != null ? stssAtom.data : null; // Entries are (number of samples, timestamp offset). - @Nullable LeafBox cttsAtom = stblAtom.getLeafBoxOfType(Mp4Box.TYPE_ctts); + @Nullable LeafBox cttsAtom = stblBox.getLeafBoxOfType(Mp4Box.TYPE_ctts); @Nullable ParsableByteArray ctts = cttsAtom != null ? cttsAtom.data : null; // Prepare to read chunk information. @@ -794,7 +796,7 @@ import java.util.Objects; @Nullable private static Metadata parseUdtaMeta(ParsableByteArray meta, int limit) { meta.skipBytes(Mp4Box.HEADER_SIZE); - maybeSkipRemainingMetaAtomHeaderBytes(meta); + maybeSkipRemainingMetaBoxHeaderBytes(meta); while (meta.getPosition() < limit) { int atomPosition = meta.getPosition(); int atomSize = meta.readInt(); @@ -851,7 +853,7 @@ import java.util.Objects; private static TkhdData parseTkhd(ParsableByteArray tkhd) { tkhd.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = tkhd.readInt(); - int version = parseFullAtomVersion(fullAtom); + int version = parseFullBoxVersion(fullAtom); tkhd.skipBytes(version == 0 ? 8 : 16); int trackId = tkhd.readInt(); @@ -938,7 +940,7 @@ import java.util.Objects; private static Pair parseMdhd(ParsableByteArray mdhd) { mdhd.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = mdhd.readInt(); - int version = parseFullAtomVersion(fullAtom); + int version = parseFullBoxVersion(fullAtom); mdhd.skipBytes(version == 0 ? 8 : 16); long timescale = mdhd.readUnsignedInt(); mdhd.skipBytes(version == 0 ? 4 : 8); @@ -1647,7 +1649,7 @@ import java.util.Objects; ParsableByteArray elstData = elstAtom.data; elstData.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = elstData.readInt(); - int version = parseFullAtomVersion(fullAtom); + int version = parseFullBoxVersion(fullAtom); int entryCount = elstData.readUnsignedIntToInt(); long[] editListDurations = new long[entryCount]; long[] editListMediaTimes = new long[entryCount]; @@ -2199,7 +2201,7 @@ import java.util.Objects; int childAtomType = parent.readInt(); if (childAtomType == Mp4Box.TYPE_tenc) { int fullAtom = parent.readInt(); - int version = parseFullAtomVersion(fullAtom); + int version = parseFullBoxVersion(fullAtom); parent.skipBytes(1); // reserved = 0. int defaultCryptByteBlock = 0; int defaultSkipByteBlock = 0; @@ -2274,7 +2276,7 @@ import java.util.Objects; && editEndTime <= duration; } - private AtomParsers() { + private BoxParser() { // Prevent instantiation. } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/FragmentedMp4Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/FragmentedMp4Extractor.java index 39c0be79df..3a556970ba 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/FragmentedMp4Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/FragmentedMp4Extractor.java @@ -19,7 +19,7 @@ import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Util.castNonNull; import static androidx.media3.common.util.Util.nullSafeArrayCopy; -import static androidx.media3.extractor.mp4.AtomParsers.parseTraks; +import static androidx.media3.extractor.mp4.BoxParser.parseTraks; import static java.lang.Math.max; import static java.lang.annotation.ElementType.TYPE_USE; @@ -778,7 +778,7 @@ public class FragmentedMp4Extractor implements Extractor { } atom.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = atom.readInt(); - int version = AtomParsers.parseFullAtomVersion(fullAtom); + int version = BoxParser.parseFullBoxVersion(fullAtom); String schemeIdUri; String value; long timescale; @@ -884,7 +884,7 @@ public class FragmentedMp4Extractor implements Extractor { private static long parseMehd(ParsableByteArray mehd) { mehd.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = mehd.readInt(); - int version = AtomParsers.parseFullAtomVersion(fullAtom); + int version = BoxParser.parseFullBoxVersion(fullAtom); return version == 0 ? mehd.readUnsignedInt() : mehd.readUnsignedLongToLong(); } @@ -1006,7 +1006,7 @@ public class FragmentedMp4Extractor implements Extractor { int vectorSize = encryptionBox.perSampleIvSize; saiz.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = saiz.readInt(); - int flags = AtomParsers.parseFullAtomFlags(fullAtom); + int flags = BoxParser.parseFullBoxFlags(fullAtom); if ((flags & 0x01) == 1) { saiz.skipBytes(8); } @@ -1050,7 +1050,7 @@ public class FragmentedMp4Extractor implements Extractor { private static void parseSaio(ParsableByteArray saio, TrackFragment out) throws ParserException { saio.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = saio.readInt(); - int flags = AtomParsers.parseFullAtomFlags(fullAtom); + int flags = BoxParser.parseFullBoxFlags(fullAtom); if ((flags & 0x01) == 1) { saio.skipBytes(8); } @@ -1062,7 +1062,7 @@ public class FragmentedMp4Extractor implements Extractor { "Unexpected saio entry count: " + entryCount, /* cause= */ null); } - int version = AtomParsers.parseFullAtomVersion(fullAtom); + int version = BoxParser.parseFullBoxVersion(fullAtom); out.auxiliaryDataPosition += version == 0 ? saio.readUnsignedInt() : saio.readUnsignedLongToLong(); } @@ -1084,7 +1084,7 @@ public class FragmentedMp4Extractor implements Extractor { ParsableByteArray tfhd, SparseArray trackBundles, boolean haveSideloadedTrack) { tfhd.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = tfhd.readInt(); - int atomFlags = AtomParsers.parseFullAtomFlags(fullAtom); + int atomFlags = BoxParser.parseFullBoxFlags(fullAtom); int trackId = tfhd.readInt(); @Nullable TrackBundle trackBundle = @@ -1133,7 +1133,7 @@ public class FragmentedMp4Extractor implements Extractor { private static long parseTfdt(ParsableByteArray tfdt) { tfdt.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = tfdt.readInt(); - int version = AtomParsers.parseFullAtomVersion(fullAtom); + int version = BoxParser.parseFullBoxVersion(fullAtom); return version == 1 ? tfdt.readUnsignedLongToLong() : tfdt.readUnsignedInt(); } @@ -1176,7 +1176,7 @@ public class FragmentedMp4Extractor implements Extractor { throws ParserException { trun.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = trun.readInt(); - int atomFlags = AtomParsers.parseFullAtomFlags(fullAtom); + int atomFlags = BoxParser.parseFullBoxFlags(fullAtom); Track track = trackBundle.moovSampleTable.track; TrackFragment fragment = trackBundle.fragment; @@ -1287,7 +1287,7 @@ public class FragmentedMp4Extractor implements Extractor { throws ParserException { senc.setPosition(Mp4Box.HEADER_SIZE + offset); int fullAtom = senc.readInt(); - int flags = AtomParsers.parseFullAtomFlags(fullAtom); + int flags = BoxParser.parseFullBoxFlags(fullAtom); if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) { // TODO: Implement this. @@ -1340,7 +1340,7 @@ public class FragmentedMp4Extractor implements Extractor { } sbgp.setPosition(Mp4Box.HEADER_SIZE); - int sbgpVersion = AtomParsers.parseFullAtomVersion(sbgp.readInt()); + int sbgpVersion = BoxParser.parseFullBoxVersion(sbgp.readInt()); sbgp.skipBytes(4); // grouping_type == seig. if (sbgpVersion == 1) { sbgp.skipBytes(4); // grouping_type_parameter. @@ -1351,7 +1351,7 @@ public class FragmentedMp4Extractor implements Extractor { } sgpd.setPosition(Mp4Box.HEADER_SIZE); - int sgpdVersion = AtomParsers.parseFullAtomVersion(sgpd.readInt()); + int sgpdVersion = BoxParser.parseFullBoxVersion(sgpd.readInt()); sgpd.skipBytes(4); // grouping_type == seig. if (sgpdVersion == 1) { if (sgpd.readUnsignedInt() == 0) { @@ -1408,7 +1408,7 @@ public class FragmentedMp4Extractor implements Extractor { throws ParserException { atom.setPosition(Mp4Box.HEADER_SIZE); int fullAtom = atom.readInt(); - int version = AtomParsers.parseFullAtomVersion(fullAtom); + int version = BoxParser.parseFullBoxVersion(fullAtom); atom.skipBytes(4); long timescale = atom.readUnsignedInt(); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/MetadataUtil.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/MetadataUtil.java index 86eccb1367..9d3f13bb66 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/MetadataUtil.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/MetadataUtil.java @@ -372,7 +372,7 @@ import com.google.common.collect.ImmutableList; int atomType = data.readInt(); if (atomType == Mp4Box.TYPE_data) { int fullVersionInt = data.readInt(); - int flags = AtomParsers.parseFullAtomFlags(fullVersionInt); + int flags = BoxParser.parseFullBoxFlags(fullVersionInt); @Nullable String mimeType = flags == 13 ? "image/jpeg" : flags == 14 ? "image/png" : null; if (mimeType == null) { Log.w(TAG, "Unrecognized cover art flags: " + flags); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java index fe64215925..3593c4cba9 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java @@ -28,7 +28,7 @@ import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_INVERS import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_LINEAR; import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_METADATA; import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_SHARP; -import static androidx.media3.extractor.mp4.AtomParsers.parseTraks; +import static androidx.media3.extractor.mp4.BoxParser.parseTraks; import static androidx.media3.extractor.mp4.MetadataUtil.findMdtaMetadataEntryWithKey; import static androidx.media3.extractor.mp4.Sniffer.BRAND_HEIC; import static androidx.media3.extractor.mp4.Sniffer.BRAND_QUICKTIME; @@ -657,7 +657,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { List<@C.AuxiliaryTrackType Integer> auxiliaryTrackTypesForEditableVideoTracks = new ArrayList<>(); if (meta != null) { - mdtaMetadata = AtomParsers.parseMdtaFromMeta(meta); + mdtaMetadata = BoxParser.parseMdtaFromMeta(meta); if (readingEditableVideoTracks) { checkStateNotNull(mdtaMetadata); maybeSetDefaultSampleOffsetForEditableVideoTracks(mdtaMetadata); @@ -678,13 +678,13 @@ public final class Mp4Extractor implements Extractor, SeekMap { @Nullable Metadata udtaMetadata = null; @Nullable Mp4Box.LeafBox udta = moov.getLeafBoxOfType(Mp4Box.TYPE_udta); if (udta != null) { - udtaMetadata = AtomParsers.parseUdta(udta); + udtaMetadata = BoxParser.parseUdta(udta); gaplessInfoHolder.setFromMetadata(udtaMetadata); } Metadata mvhdMetadata = new Metadata( - AtomParsers.parseMvhd(checkNotNull(moov.getLeafBoxOfType(Mp4Box.TYPE_mvhd)).data)); + BoxParser.parseMvhd(checkNotNull(moov.getLeafBoxOfType(Mp4Box.TYPE_mvhd)).data)); boolean ignoreEditLists = (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0; List trackSampleTables = @@ -1056,7 +1056,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { private void maybeSkipRemainingMetaAtomHeaderBytes(ExtractorInput input) throws IOException { scratch.reset(8); input.peekFully(scratch.getData(), 0, 8); - AtomParsers.maybeSkipRemainingMetaAtomHeaderBytes(scratch); + BoxParser.maybeSkipRemainingMetaBoxHeaderBytes(scratch); input.skipFully(scratch.getPosition()); input.resetPeekPosition(); } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/PsshAtomUtil.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/PsshAtomUtil.java index 748822e295..fc4f24ce67 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/PsshAtomUtil.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/PsshAtomUtil.java @@ -176,7 +176,7 @@ public final class PsshAtomUtil { Log.w(TAG, "Atom type is not pssh: " + atomType); return null; } - int atomVersion = AtomParsers.parseFullAtomVersion(atomData.readInt()); + int atomVersion = BoxParser.parseFullBoxVersion(atomData.readInt()); if (atomVersion > 1) { Log.w(TAG, "Unsupported pssh version: " + atomVersion); return null; diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Sniffer.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Sniffer.java index 58f427e0b2..fa7ff35bd3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Sniffer.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Sniffer.java @@ -18,6 +18,7 @@ package androidx.media3.extractor.mp4; import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.util.ParsableByteArray; +import androidx.media3.common.util.UnstableApi; import androidx.media3.container.Mp4Box; import androidx.media3.extractor.ExtractorInput; import androidx.media3.extractor.SniffFailure; @@ -27,7 +28,8 @@ import java.io.IOException; * Provides methods that peek data from an {@link ExtractorInput} and return whether the input * appears to be in MP4 format. */ -/* package */ final class Sniffer { +@UnstableApi +public final class Sniffer { /** Brand stored in the ftyp atom for QuickTime media. */ public static final int BRAND_QUICKTIME = 0x71742020; diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/TrackSampleTable.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/TrackSampleTable.java index 7f2c046865..15c73b8e65 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/TrackSampleTable.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/TrackSampleTable.java @@ -17,10 +17,12 @@ package androidx.media3.extractor.mp4; import androidx.media3.common.C; import androidx.media3.common.util.Assertions; +import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; /** Sample table for a track in an MP4 file. */ -/* package */ final class TrackSampleTable { +@UnstableApi +public final class TrackSampleTable { /** The track corresponding to this sample table. */ public final Track track; diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/AtomParsersTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/BoxParserTest.java similarity index 94% rename from libraries/extractor/src/test/java/androidx/media3/extractor/mp4/AtomParsersTest.java rename to libraries/extractor/src/test/java/androidx/media3/extractor/mp4/BoxParserTest.java index 404e20b196..5a0c694058 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/AtomParsersTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/BoxParserTest.java @@ -26,9 +26,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; -/** Tests for {@link AtomParsers}. */ +/** Tests for {@link BoxParser}. */ @RunWith(AndroidJUnit4.class) -public final class AtomParsersTest { +public final class BoxParserTest { private static final String ATOM_HEADER = "000000000000000000000000"; private static final String SAMPLE_COUNT = "00000004"; @@ -248,7 +248,7 @@ public final class AtomParsersTest { 0, 0, 0, 0, 88, 88, 88, 88 }; // version (1), flags (3), 'xxxx' (4) assertThat( - AtomParsers.parseCommonEncryptionSinfFromParent( + BoxParser.parseCommonEncryptionSinfFromParent( new ParsableByteArray(cencSinf), 0, cencSinf.length)) .isNull(); } @@ -271,17 +271,17 @@ public final class AtomParsersTest { @Test public void vexuParsings() throws ParserException { - AtomParsers.VexuData vexuData = null; + BoxParser.VexuData vexuData = null; assertThat( vexuData = - AtomParsers.parseVideoExtendedUsageBox( + BoxParser.parseVideoExtendedUsageBox( new ParsableByteArray(VEXU_DATA0), 0, VEXU_DATA0.length)) .isNotNull(); assertThat(vexuData).isNotNull(); assertThat(vexuData.hasBothEyeViews()).isTrue(); assertThat( vexuData = - AtomParsers.parseVideoExtendedUsageBox( + BoxParser.parseVideoExtendedUsageBox( new ParsableByteArray(VEXU_DATA1), 0, VEXU_DATA1.length)) .isNotNull(); assertThat(vexuData).isNotNull(); @@ -289,7 +289,7 @@ public final class AtomParsersTest { } private static void verifyStz2Parsing(Mp4Box.LeafBox stz2Atom) { - AtomParsers.Stz2SampleSizeBox box = new AtomParsers.Stz2SampleSizeBox(stz2Atom); + BoxParser.Stz2SampleSizeBox box = new BoxParser.Stz2SampleSizeBox(stz2Atom); assertThat(box.getSampleCount()).isEqualTo(4); assertThat(box.getFixedSampleSize()).isEqualTo(C.LENGTH_UNSET); for (int i = 0; i < box.getSampleCount(); i++) { diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/PsshAtomUtilTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/PsshAtomUtilTest.java index 717158a1a5..593151607e 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/PsshAtomUtilTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/PsshAtomUtilTest.java @@ -17,8 +17,8 @@ package androidx.media3.extractor.mp4; import static androidx.media3.common.C.WIDEVINE_UUID; import static androidx.media3.container.Mp4Box.TYPE_pssh; -import static androidx.media3.extractor.mp4.AtomParsers.parseFullAtomFlags; -import static androidx.media3.extractor.mp4.AtomParsers.parseFullAtomVersion; +import static androidx.media3.extractor.mp4.BoxParser.parseFullBoxFlags; +import static androidx.media3.extractor.mp4.BoxParser.parseFullBoxVersion; import static com.google.common.truth.Truth.assertThat; import androidx.media3.common.C; @@ -42,8 +42,8 @@ public final class PsshAtomUtilTest { assertThat(parsablePsshAtom.readUnsignedIntToInt()).isEqualTo(psshAtom.length); // length assertThat(parsablePsshAtom.readInt()).isEqualTo(TYPE_pssh); // type int fullAtomInt = parsablePsshAtom.readInt(); // version + flags - assertThat(parseFullAtomVersion(fullAtomInt)).isEqualTo(0); - assertThat(parseFullAtomFlags(fullAtomInt)).isEqualTo(0); + assertThat(parseFullBoxVersion(fullAtomInt)).isEqualTo(0); + assertThat(parseFullBoxFlags(fullAtomInt)).isEqualTo(0); UUID systemId = new UUID(parsablePsshAtom.readLong(), parsablePsshAtom.readLong()); assertThat(systemId).isEqualTo(WIDEVINE_UUID); assertThat(parsablePsshAtom.readUnsignedIntToInt()).isEqualTo(schemeData.length); @@ -65,8 +65,8 @@ public final class PsshAtomUtilTest { assertThat(parsablePsshAtom.readUnsignedIntToInt()).isEqualTo(psshAtom.length); assertThat(parsablePsshAtom.readInt()).isEqualTo(TYPE_pssh); // type int fullAtomInt = parsablePsshAtom.readInt(); // version + flags - assertThat(parseFullAtomVersion(fullAtomInt)).isEqualTo(1); - assertThat(parseFullAtomFlags(fullAtomInt)).isEqualTo(0); + assertThat(parseFullBoxVersion(fullAtomInt)).isEqualTo(1); + assertThat(parseFullBoxFlags(fullAtomInt)).isEqualTo(0); UUID systemId = new UUID(parsablePsshAtom.readLong(), parsablePsshAtom.readLong()); assertThat(systemId).isEqualTo(WIDEVINE_UUID); assertThat(parsablePsshAtom.readUnsignedIntToInt()).isEqualTo(2);