Distinguish dense vs sparse tracks for buffering purposes

- For audio/video, we should report the minimum largest
  queued timestamp. This ensures that buffering continues
  rather than stops in the case of bad sample interleaving.
- If there are "sparse" tracks then they should be ignored
  for this calculation, otherwise the buffered position can
  end up getting stuck at some small value (e.g. if there's
  a text track containing a single sample with a small
  timestamp).
- In the edge case that there are only "sparse" tracks, we
  probably want to take the maximum largest queued time
  instead.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130094266
This commit is contained in:
olly 2016-08-12 06:27:17 -07:00 committed by Oliver Woodman
parent c380ba2dc1
commit d04fde1a53

View File

@ -41,6 +41,7 @@ import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.Loadable; import com.google.android.exoplayer2.upstream.Loader.Loadable;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.ConditionVariable;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
@ -130,6 +131,8 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
private int enabledTrackCount; private int enabledTrackCount;
private DefaultTrackOutput[] sampleQueues; private DefaultTrackOutput[] sampleQueues;
private TrackGroupArray tracks; private TrackGroupArray tracks;
private boolean[] tracksAreAudioVideoFlags;
private boolean haveAudioVideoTracks;
private long durationUs; private long durationUs;
private boolean[] trackEnabledStates; private boolean[] trackEnabledStates;
private long length; private long length;
@ -504,10 +507,16 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
loadCondition.close(); loadCondition.close();
int trackCount = sampleQueues.length; int trackCount = sampleQueues.length;
TrackGroup[] trackArray = new TrackGroup[trackCount]; TrackGroup[] trackArray = new TrackGroup[trackCount];
tracksAreAudioVideoFlags = new boolean[trackCount];
trackEnabledStates = new boolean[trackCount]; trackEnabledStates = new boolean[trackCount];
durationUs = seekMap.getDurationUs(); durationUs = seekMap.getDurationUs();
for (int i = 0; i < trackCount; i++) { for (int i = 0; i < trackCount; i++) {
trackArray[i] = new TrackGroup(sampleQueues[i].getUpstreamFormat()); Format format = sampleQueues[i].getUpstreamFormat();
trackArray[i] = new TrackGroup(format);
String sampleMimeType = format.sampleMimeType;
tracksAreAudioVideoFlags[i] = MimeTypes.isVideo(sampleMimeType)
|| MimeTypes.isAudio(sampleMimeType);
haveAudioVideoTracks |= tracksAreAudioVideoFlags[i];
} }
tracks = new TrackGroupArray(trackArray); tracks = new TrackGroupArray(trackArray);
prepared = true; prepared = true;
@ -578,12 +587,14 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
} }
private long getLargestQueuedTimestampUs() { private long getLargestQueuedTimestampUs() {
long largestQueuedTimestampUs = Long.MIN_VALUE; long largestQueuedTimestampUs = Long.MAX_VALUE;
for (DefaultTrackOutput sampleQueue : sampleQueues) { for (int i = 0; i < sampleQueues.length; i++) {
largestQueuedTimestampUs = Math.max(largestQueuedTimestampUs, if (tracksAreAudioVideoFlags[i] || !haveAudioVideoTracks) {
sampleQueue.getLargestQueuedTimestampUs()); largestQueuedTimestampUs = Math.min(largestQueuedTimestampUs,
sampleQueues[i].getLargestQueuedTimestampUs());
} }
return largestQueuedTimestampUs; }
return largestQueuedTimestampUs == Long.MAX_VALUE ? Long.MIN_VALUE : largestQueuedTimestampUs;
} }
private boolean isPendingReset() { private boolean isPendingReset() {