Skip to content

Commit

Permalink
Add an extractor flag for ignoring edit lists
Browse files Browse the repository at this point in the history
Issue: #3358

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=172464053
  • Loading branch information
andrewlewis authored and ojw28 committed Oct 17, 2017
1 parent 2c10e6f commit f9249d2
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
}

private @MatroskaExtractor.Flags int matroskaFlags;
private @Mp4Extractor.Flags int mp4Flags;
private @FragmentedMp4Extractor.Flags int fragmentedMp4Flags;
private @Mp3Extractor.Flags int mp3Flags;
private @TsExtractor.Mode int tsMode;
Expand All @@ -89,6 +90,18 @@ public synchronized DefaultExtractorsFactory setMatroskaExtractorFlags(
return this;
}

/**
* Sets flags for {@link Mp4Extractor} instances created by the factory.
*
* @see Mp4Extractor#Mp4Extractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setMp4ExtractorFlags(@Mp4Extractor.Flags int flags) {
this.mp4Flags = flags;
return this;
}

/**
* Sets flags for {@link FragmentedMp4Extractor} instances created by the factory.
*
Expand Down Expand Up @@ -145,7 +158,7 @@ public synchronized Extractor[] createExtractors() {
Extractor[] extractors = new Extractor[FLAC_EXTRACTOR_CONSTRUCTOR == null ? 11 : 12];
extractors[0] = new MatroskaExtractor(matroskaFlags);
extractors[1] = new FragmentedMp4Extractor(fragmentedMp4Flags);
extractors[2] = new Mp4Extractor();
extractors[2] = new Mp4Extractor(mp4Flags);
extractors[3] = new Mp3Extractor(mp3Flags);
extractors[4] = new AdtsExtractor();
extractors[5] = new Ac3Extractor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@
* @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 drmInitData {@link DrmInitData} to be included in the format.
* @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.
*/
public static Track parseTrak(Atom.ContainerAtom trak, Atom.LeafAtom mvhd, long duration,
DrmInitData drmInitData, boolean isQuickTime) throws ParserException {
DrmInitData drmInitData, boolean ignoreEditLists, boolean isQuickTime)
throws ParserException {
Atom.ContainerAtom mdia = trak.getContainerAtomOfType(Atom.TYPE_mdia);
int trackType = parseHdlr(mdia.getLeafAtomOfType(Atom.TYPE_hdlr).data);
if (trackType == C.TRACK_TYPE_UNKNOWN) {
Expand All @@ -88,11 +90,17 @@ public static Track parseTrak(Atom.ContainerAtom trak, Atom.LeafAtom mvhd, long
Pair<Long, String> mdhdData = parseMdhd(mdia.getLeafAtomOfType(Atom.TYPE_mdhd).data);
StsdData stsdData = parseStsd(stbl.getLeafAtomOfType(Atom.TYPE_stsd).data, tkhdData.id,
tkhdData.rotationDegrees, mdhdData.second, drmInitData, isQuickTime);
Pair<long[], long[]> edtsData = parseEdts(trak.getContainerAtomOfType(Atom.TYPE_edts));
long[] editListDurations = null;
long[] editListMediaTimes = null;
if (!ignoreEditLists) {
Pair<long[], long[]> edtsData = parseEdts(trak.getContainerAtomOfType(Atom.TYPE_edts));
editListDurations = edtsData.first;
editListMediaTimes = edtsData.second;
}
return stsdData.format == null ? null
: new Track(tkhdData.id, trackType, mdhdData.first, movieTimescale, durationUs,
stsdData.format, stsdData.requiredSampleTransformation, stsdData.trackEncryptionBoxes,
stsdData.nalUnitLengthFieldLength, edtsData.first, edtsData.second);
stsdData.nalUnitLengthFieldLength, editListDurations, editListMediaTimes);
}

/**
Expand Down Expand Up @@ -783,7 +791,7 @@ private static void parseVideoSampleEntry(ParsableByteArray parent, int atomType
*
* @param edtsAtom edts (edit box) atom to decode.
* @return Pair of edit list durations and edit list media times, or a pair of nulls if they are
* not present.
* not present.
*/
private static Pair<long[], long[]> parseEdts(Atom.ContainerAtom edtsAtom) {
Atom.LeafAtom elst;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public Extractor[] createExtractors() {
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME,
FLAG_WORKAROUND_IGNORE_TFDT_BOX, FLAG_ENABLE_EMSG_TRACK, FLAG_ENABLE_CEA608_TRACK,
FLAG_SIDELOADED})
FLAG_SIDELOADED, FLAG_WORKAROUND_IGNORE_EDIT_LISTS})
public @interface Flags {}
/**
* Flag to work around an issue in some video streams where every frame is marked as a sync frame.
Expand Down Expand Up @@ -103,6 +103,10 @@ public Extractor[] createExtractors() {
* container.
*/
private static final int FLAG_SIDELOADED = 16;
/**
* Flag to ignore any edit lists in the stream.
*/
public static final int FLAG_WORKAROUND_IGNORE_EDIT_LISTS = 32;

private static final String TAG = "FragmentedMp4Extractor";
private static final int SAMPLE_GROUP_TYPE_seig = Util.getIntegerCodeForString("seig");
Expand Down Expand Up @@ -432,7 +436,7 @@ private void onMoovContainerAtomRead(ContainerAtom moov) throws ParserException
Atom.ContainerAtom atom = moov.containerChildren.get(i);
if (atom.type == Atom.TYPE_trak) {
Track track = AtomParsers.parseTrak(atom, moov.getLeafAtomOfType(Atom.TYPE_mvhd), duration,
drmInitData, false);
drmInitData, (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0, false);
if (track != null) {
tracks.put(track.id, track);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom;
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor.Flags;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.NalUnitUtil;
Expand Down Expand Up @@ -57,6 +58,17 @@ public Extractor[] createExtractors() {

};

/**
* Flags controlling the behavior of the extractor.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {FLAG_WORKAROUND_IGNORE_EDIT_LISTS})
public @interface Flags {}
/**
* Flag to ignore any edit lists in the stream.
*/
public static final int FLAG_WORKAROUND_IGNORE_EDIT_LISTS = 1;

/**
* Parser states.
*/
Expand All @@ -76,6 +88,8 @@ public Extractor[] createExtractors() {
*/
private static final long RELOAD_MINIMUM_SEEK_DISTANCE = 256 * 1024;

private final @Flags int flags;

// Temporary arrays.
private final ParsableByteArray nalStartCode;
private final ParsableByteArray nalLength;
Expand All @@ -98,7 +112,21 @@ public Extractor[] createExtractors() {
private long durationUs;
private boolean isQuickTime;

/**
* Creates a new extractor for unfragmented MP4 streams.
*/
public Mp4Extractor() {
this(0);
}

/**
* Creates a new extractor for unfragmented MP4 streams, using the specified flags to control the
* extractor's behavior.
*
* @param flags Flags that control the extractor's behavior.
*/
public Mp4Extractor(@Flags int flags) {
this.flags = flags;
atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE);
containerAtoms = new Stack<>();
nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE);
Expand Down Expand Up @@ -345,7 +373,7 @@ private void processMoovAtom(ContainerAtom moov) throws ParserException {
}

Track track = AtomParsers.parseTrak(atom, moov.getLeafAtomOfType(Atom.TYPE_mvhd),
C.TIME_UNSET, null, isQuickTime);
C.TIME_UNSET, null, (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0, isQuickTime);
if (track == null) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ public final class Track {
/**
* Durations of edit list segments in the movie timescale. Null if there is no edit list.
*/
public final long[] editListDurations;
@Nullable public final long[] editListDurations;

/**
* Media times for edit list segments in the track timescale. Null if there is no edit list.
*/
public final long[] editListMediaTimes;
@Nullable public final long[] editListMediaTimes;

/**
* For H264 video tracks, the length in bytes of the NALUnitLength field in each sample. 0 for
Expand All @@ -99,7 +99,7 @@ public final class Track {
public Track(int id, int type, long timescale, long movieTimescale, long durationUs,
Format format, @Transformation int sampleTransformation,
@Nullable TrackEncryptionBox[] sampleDescriptionEncryptionBoxes, int nalUnitLengthFieldLength,
long[] editListDurations, long[] editListMediaTimes) {
@Nullable long[] editListDurations, @Nullable long[] editListMediaTimes) {
this.id = id;
this.type = type;
this.timescale = timescale;
Expand Down

0 comments on commit f9249d2

Please sign in to comment.