3232import androidx .media3 .common .DrmInitData ;
3333import androidx .media3 .common .DrmInitData .SchemeData ;
3434import androidx .media3 .common .Format ;
35+ import androidx .media3 .common .Metadata ;
3536import androidx .media3 .common .MimeTypes ;
3637import androidx .media3 .common .ParserException ;
3738import androidx .media3 .common .util .Log ;
@@ -483,6 +484,8 @@ public void init(ExtractorOutput output) {
483484 enterReadingAtomHeaderState ();
484485 initExtraTracks ();
485486 if (sideloadedTrack != null ) {
487+ Format .Builder formatBuilder = sideloadedTrack .format .buildUpon ();
488+ formatBuilder .setContainerMimeType (getContainerMimeType (sideloadedTrack .format ));
486489 TrackBundle bundle =
487490 new TrackBundle (
488491 extractorOutput .track (0 , sideloadedTrack .type ),
@@ -499,7 +502,7 @@ public void init(ExtractorOutput output) {
499502 /* duration= */ 0 ,
500503 /* size= */ 0 ,
501504 /* flags= */ 0 ),
502- getContainerMimeType ( sideloadedTrack . format ));
505+ formatBuilder . build ( ));
503506 trackBundles .put (0 , bundle );
504507 extractorOutput .endTracks ();
505508 }
@@ -642,6 +645,9 @@ private boolean readAtomHeader(ExtractorInput input) throws IOException {
642645
643646 if (shouldParseContainerAtom (atomType )) {
644647 long endPosition = input .getPosition () + atomSize - Mp4Box .HEADER_SIZE ;
648+ if (atomSize != atomHeaderBytesRead && atomType == Mp4Box .TYPE_meta ) {
649+ maybeSkipRemainingMetaAtomHeaderBytes (input );
650+ }
645651 containerAtoms .push (new ContainerBox (atomType , endPosition ));
646652 if (atomSize == atomHeaderBytesRead ) {
647653 processAtomEnded (endPosition );
@@ -674,6 +680,14 @@ private boolean readAtomHeader(ExtractorInput input) throws IOException {
674680 return true ;
675681 }
676682
683+ private void maybeSkipRemainingMetaAtomHeaderBytes (ExtractorInput input ) throws IOException {
684+ scratch .reset (Mp4Box .HEADER_SIZE );
685+ input .peekFully (scratch .getData (), 0 , Mp4Box .HEADER_SIZE );
686+ BoxParser .maybeSkipRemainingMetaBoxHeaderBytes (scratch );
687+ input .skipFully (scratch .getPosition ());
688+ input .resetPeekPosition ();
689+ }
690+
677691 private void readAtomPayload (ExtractorInput input ) throws IOException {
678692 int atomPayloadSize = (int ) (atomSize - atomHeaderBytesRead );
679693 @ Nullable ParsableByteArray atomData = this .atomData ;
@@ -743,11 +757,27 @@ private void onMoovContainerAtomRead(ContainerBox moov) throws ParserException {
743757 }
744758 }
745759
760+ @ Nullable Metadata mdtaMetadata = null ;
761+ @ Nullable Mp4Box .ContainerBox meta = moov .getContainerBoxOfType (Mp4Box .TYPE_meta );
762+ if (meta != null ) {
763+ mdtaMetadata = BoxParser .parseMdtaFromMeta (meta );
764+ }
765+ GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder ();
766+ @ Nullable Metadata udtaMetadata = null ;
767+ @ Nullable Mp4Box .LeafBox udta = moov .getLeafBoxOfType (Mp4Box .TYPE_udta );
768+ if (udta != null ) {
769+ udtaMetadata = BoxParser .parseUdta (udta );
770+ gaplessInfoHolder .setFromMetadata (udtaMetadata );
771+ }
772+ Metadata mvhdMetadata =
773+ new Metadata (
774+ BoxParser .parseMvhd (checkNotNull (moov .getLeafBoxOfType (Mp4Box .TYPE_mvhd )).data ));
775+
746776 // Construction of tracks and sample tables.
747777 List <TrackSampleTable > sampleTables =
748778 parseTraks (
749779 moov ,
750- new GaplessInfoHolder () ,
780+ gaplessInfoHolder ,
751781 duration ,
752782 drmInitData ,
753783 /* ignoreEditLists= */ (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS ) != 0 ,
@@ -763,12 +793,22 @@ private void onMoovContainerAtomRead(ContainerBox moov) throws ParserException {
763793 Track track = sampleTable .track ;
764794 TrackOutput output = extractorOutput .track (i , track .type );
765795 output .durationUs (track .durationUs );
796+ Format .Builder formatBuilder = track .format .buildUpon ();
797+ formatBuilder .setContainerMimeType (containerMimeType );
798+ MetadataUtil .setFormatGaplessInfo (track .type , gaplessInfoHolder , formatBuilder );
799+ MetadataUtil .setFormatMetadata (
800+ track .type ,
801+ mdtaMetadata ,
802+ formatBuilder ,
803+ track .format .metadata ,
804+ udtaMetadata ,
805+ mvhdMetadata );
766806 TrackBundle trackBundle =
767807 new TrackBundle (
768808 output ,
769809 sampleTable ,
770810 getDefaultSampleValues (defaultSampleValuesArray , track .id ),
771- containerMimeType );
811+ formatBuilder . build () );
772812 trackBundles .put (track .id , trackBundle );
773813 durationUs = max (durationUs , track .durationUs );
774814 }
@@ -1900,7 +1940,10 @@ private static boolean shouldParseLeafAtom(int atom) {
19001940 || atom == Mp4Box .TYPE_sgpd
19011941 || atom == Mp4Box .TYPE_elst
19021942 || atom == Mp4Box .TYPE_mehd
1903- || atom == Mp4Box .TYPE_emsg ;
1943+ || atom == Mp4Box .TYPE_emsg
1944+ || atom == Mp4Box .TYPE_udta
1945+ || atom == Mp4Box .TYPE_keys
1946+ || atom == Mp4Box .TYPE_ilst ;
19041947 }
19051948
19061949 /** Returns whether the extractor should decode a container atom with type {@code atom}. */
@@ -1913,7 +1956,8 @@ private static boolean shouldParseContainerAtom(int atom) {
19131956 || atom == Mp4Box .TYPE_moof
19141957 || atom == Mp4Box .TYPE_traf
19151958 || atom == Mp4Box .TYPE_mvex
1916- || atom == Mp4Box .TYPE_edts ;
1959+ || atom == Mp4Box .TYPE_edts
1960+ || atom == Mp4Box .TYPE_meta ;
19171961 }
19181962
19191963 /** Holds data corresponding to a metadata sample. */
@@ -1946,7 +1990,7 @@ private static final class TrackBundle {
19461990 public int currentTrackRunIndex ;
19471991 public int firstSampleToOutputIndex ;
19481992
1949- private final String containerMimeType ;
1993+ private final Format baseFormat ;
19501994 private final ParsableByteArray encryptionSignalByte ;
19511995 private final ParsableByteArray defaultInitializationVector ;
19521996
@@ -1956,11 +2000,11 @@ public TrackBundle(
19562000 TrackOutput output ,
19572001 TrackSampleTable moovSampleTable ,
19582002 DefaultSampleValues defaultSampleValues ,
1959- String containerMimeType ) {
2003+ Format baseFormat ) {
19602004 this .output = output ;
19612005 this .moovSampleTable = moovSampleTable ;
19622006 this .defaultSampleValues = defaultSampleValues ;
1963- this .containerMimeType = containerMimeType ;
2007+ this .baseFormat = baseFormat ;
19642008 fragment = new TrackFragment ();
19652009 scratch = new ParsableByteArray ();
19662010 encryptionSignalByte = new ParsableByteArray (1 );
@@ -1971,9 +2015,7 @@ public TrackBundle(
19712015 public void reset (TrackSampleTable moovSampleTable , DefaultSampleValues defaultSampleValues ) {
19722016 this .moovSampleTable = moovSampleTable ;
19732017 this .defaultSampleValues = defaultSampleValues ;
1974- Format format =
1975- moovSampleTable .track .format .buildUpon ().setContainerMimeType (containerMimeType ).build ();
1976- output .format (format );
2018+ output .format (baseFormat );
19772019 resetFragmentInfo ();
19782020 }
19792021
@@ -1984,14 +2026,7 @@ public void updateDrmInitData(DrmInitData drmInitData) {
19842026 castNonNull (fragment .header ).sampleDescriptionIndex );
19852027 @ Nullable String schemeType = encryptionBox != null ? encryptionBox .schemeType : null ;
19862028 DrmInitData updatedDrmInitData = drmInitData .copyWithSchemeType (schemeType );
1987- Format format =
1988- moovSampleTable
1989- .track
1990- .format
1991- .buildUpon ()
1992- .setContainerMimeType (containerMimeType )
1993- .setDrmInitData (updatedDrmInitData )
1994- .build ();
2029+ Format format = baseFormat .buildUpon ().setDrmInitData (updatedDrmInitData ).build ();
19952030 output .format (format );
19962031 }
19972032
0 commit comments