Skip to content

Commit fba3e1f

Browse files
nift4rohitjoins
authored andcommitted
Parse metadata from fMP4 files
Issue: #2084
1 parent be6e438 commit fba3e1f

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

libraries/extractor/src/main/java/androidx/media3/extractor/mp4/FragmentedMp4Extractor.java

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import androidx.media3.common.DrmInitData;
3333
import androidx.media3.common.DrmInitData.SchemeData;
3434
import androidx.media3.common.Format;
35+
import androidx.media3.common.Metadata;
3536
import androidx.media3.common.MimeTypes;
3637
import androidx.media3.common.ParserException;
3738
import androidx.media3.common.util.Log;
@@ -499,7 +500,7 @@ public void init(ExtractorOutput output) {
499500
/* duration= */ 0,
500501
/* size= */ 0,
501502
/* flags= */ 0),
502-
getContainerMimeType(sideloadedTrack.format));
503+
sideloadedTrack.format);
503504
trackBundles.put(0, bundle);
504505
extractorOutput.endTracks();
505506
}
@@ -743,11 +744,27 @@ private void onMoovContainerAtomRead(ContainerBox moov) throws ParserException {
743744
}
744745
}
745746

747+
@Nullable Metadata mdtaMetadata = null;
748+
@Nullable Mp4Box.ContainerBox meta = moov.getContainerBoxOfType(Mp4Box.TYPE_meta);
749+
if (meta != null) {
750+
mdtaMetadata = BoxParser.parseMdtaFromMeta(meta);
751+
}
752+
GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
753+
@Nullable Metadata udtaMetadata = null;
754+
@Nullable Mp4Box.LeafBox udta = moov.getLeafBoxOfType(Mp4Box.TYPE_udta);
755+
if (udta != null) {
756+
udtaMetadata = BoxParser.parseUdta(udta);
757+
gaplessInfoHolder.setFromMetadata(udtaMetadata);
758+
}
759+
Metadata mvhdMetadata =
760+
new Metadata(
761+
BoxParser.parseMvhd(checkNotNull(moov.getLeafBoxOfType(Mp4Box.TYPE_mvhd)).data));
762+
746763
// Construction of tracks and sample tables.
747764
List<TrackSampleTable> sampleTables =
748765
parseTraks(
749766
moov,
750-
new GaplessInfoHolder(),
767+
gaplessInfoHolder,
751768
duration,
752769
drmInitData,
753770
/* ignoreEditLists= */ (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0,
@@ -763,12 +780,22 @@ private void onMoovContainerAtomRead(ContainerBox moov) throws ParserException {
763780
Track track = sampleTable.track;
764781
TrackOutput output = extractorOutput.track(i, track.type);
765782
output.durationUs(track.durationUs);
783+
Format.Builder formatBuilder = track.format.buildUpon();
784+
formatBuilder.setContainerMimeType(containerMimeType);
785+
MetadataUtil.setFormatGaplessInfo(track.type, gaplessInfoHolder, formatBuilder);
786+
MetadataUtil.setFormatMetadata(
787+
track.type,
788+
mdtaMetadata,
789+
formatBuilder,
790+
track.format.metadata,
791+
udtaMetadata,
792+
mvhdMetadata);
766793
TrackBundle trackBundle =
767794
new TrackBundle(
768795
output,
769796
sampleTable,
770797
getDefaultSampleValues(defaultSampleValuesArray, track.id),
771-
containerMimeType);
798+
formatBuilder.build());
772799
trackBundles.put(track.id, trackBundle);
773800
durationUs = max(durationUs, track.durationUs);
774801
}
@@ -1900,7 +1927,9 @@ private static boolean shouldParseLeafAtom(int atom) {
19001927
|| atom == Mp4Box.TYPE_sgpd
19011928
|| atom == Mp4Box.TYPE_elst
19021929
|| atom == Mp4Box.TYPE_mehd
1903-
|| atom == Mp4Box.TYPE_emsg;
1930+
|| atom == Mp4Box.TYPE_emsg
1931+
|| atom == Mp4Box.TYPE_udta
1932+
|| atom == Mp4Box.TYPE_ilst;
19041933
}
19051934

19061935
/** Returns whether the extractor should decode a container atom with type {@code atom}. */
@@ -1913,7 +1942,8 @@ private static boolean shouldParseContainerAtom(int atom) {
19131942
|| atom == Mp4Box.TYPE_moof
19141943
|| atom == Mp4Box.TYPE_traf
19151944
|| atom == Mp4Box.TYPE_mvex
1916-
|| atom == Mp4Box.TYPE_edts;
1945+
|| atom == Mp4Box.TYPE_edts
1946+
|| atom == Mp4Box.TYPE_meta;
19171947
}
19181948

19191949
/** Holds data corresponding to a metadata sample. */
@@ -1946,7 +1976,7 @@ private static final class TrackBundle {
19461976
public int currentTrackRunIndex;
19471977
public int firstSampleToOutputIndex;
19481978

1949-
private final String containerMimeType;
1979+
private final Format baseFormat;
19501980
private final ParsableByteArray encryptionSignalByte;
19511981
private final ParsableByteArray defaultInitializationVector;
19521982

@@ -1956,11 +1986,11 @@ public TrackBundle(
19561986
TrackOutput output,
19571987
TrackSampleTable moovSampleTable,
19581988
DefaultSampleValues defaultSampleValues,
1959-
String containerMimeType) {
1989+
Format baseFormat) {
19601990
this.output = output;
19611991
this.moovSampleTable = moovSampleTable;
19621992
this.defaultSampleValues = defaultSampleValues;
1963-
this.containerMimeType = containerMimeType;
1993+
this.baseFormat = baseFormat;
19641994
fragment = new TrackFragment();
19651995
scratch = new ParsableByteArray();
19661996
encryptionSignalByte = new ParsableByteArray(1);
@@ -1971,9 +2001,7 @@ public TrackBundle(
19712001
public void reset(TrackSampleTable moovSampleTable, DefaultSampleValues defaultSampleValues) {
19722002
this.moovSampleTable = moovSampleTable;
19732003
this.defaultSampleValues = defaultSampleValues;
1974-
Format format =
1975-
moovSampleTable.track.format.buildUpon().setContainerMimeType(containerMimeType).build();
1976-
output.format(format);
2004+
output.format(baseFormat);
19772005
resetFragmentInfo();
19782006
}
19792007

@@ -1984,14 +2012,7 @@ public void updateDrmInitData(DrmInitData drmInitData) {
19842012
castNonNull(fragment.header).sampleDescriptionIndex);
19852013
@Nullable String schemeType = encryptionBox != null ? encryptionBox.schemeType : null;
19862014
DrmInitData updatedDrmInitData = drmInitData.copyWithSchemeType(schemeType);
1987-
Format format =
1988-
moovSampleTable
1989-
.track
1990-
.format
1991-
.buildUpon()
1992-
.setContainerMimeType(containerMimeType)
1993-
.setDrmInitData(updatedDrmInitData)
1994-
.build();
2015+
Format format = baseFormat.buildUpon().setDrmInitData(updatedDrmInitData).build();
19952016
output.format(format);
19962017
}
19972018

0 commit comments

Comments
 (0)