diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java index dcc3ba9e18..1d2410e9ac 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java @@ -299,13 +299,13 @@ import java.util.concurrent.atomic.AtomicInteger; durationUs = source.getDurationUs(); bufferedPositionUs = source.getBufferedPositionUs(); - TrackGroup[] trackGroups = source.getTrackGroups(); + TrackGroupArray trackGroups = source.getTrackGroups(); // The maximum number of tracks that one renderer can support is the total number of tracks in // all groups, plus possibly one adaptive track per group. int maxTrackCount = trackGroups.length; for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { - maxTrackCount += trackGroups[groupIndex].length; + maxTrackCount += trackGroups.get(groupIndex).length; } // Construct tracks for each renderer. Format[][] externalTrackFormats = new Format[renderers.length][]; @@ -316,7 +316,7 @@ import java.util.concurrent.atomic.AtomicInteger; TrackSelection[] rendererTrackSelections = new TrackSelection[maxTrackCount]; Format[][] rendererTrackFormats = new Format[maxTrackCount][]; for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { - TrackGroup trackGroup = trackGroups[groupIndex]; + TrackGroup trackGroup = trackGroups.get(groupIndex); // TODO[REFACTOR]: This should check that the renderer is capable of adaptive playback, in // addition to checking that the group is adaptive. if (trackGroup.adaptive) { diff --git a/library/src/main/java/com/google/android/exoplayer/Format.java b/library/src/main/java/com/google/android/exoplayer/Format.java index f9fa3a9910..39895f78f8 100644 --- a/library/src/main/java/com/google/android/exoplayer/Format.java +++ b/library/src/main/java/com/google/android/exoplayer/Format.java @@ -143,7 +143,7 @@ public final class Format { */ public final String language; - // Lazy-initialized hashcode and framework media format. + // Lazily initialized hashcode and framework media format. private int hashCode; private MediaFormat frameworkMediaFormat; diff --git a/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java index b4fb2117b3..6c472d346e 100644 --- a/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java @@ -75,7 +75,7 @@ public final class FrameworkSampleSource implements SampleSource { private boolean prepared; private long durationUs; private MediaExtractor extractor; - private TrackGroup[] tracks; + private TrackGroupArray tracks; private int[] trackStates; private boolean[] pendingResets; @@ -133,7 +133,7 @@ public final class FrameworkSampleSource implements SampleSource { durationUs = C.UNKNOWN_TIME_US; trackStates = new int[extractor.getTrackCount()]; pendingResets = new boolean[trackStates.length]; - tracks = new TrackGroup[trackStates.length]; + TrackGroup[] tracks = new TrackGroup[trackStates.length]; for (int i = 0; i < trackStates.length; i++) { MediaFormat format = extractor.getTrackFormat(i); if (format.containsKey(MediaFormat.KEY_DURATION)) { @@ -141,6 +141,7 @@ public final class FrameworkSampleSource implements SampleSource { } tracks[i] = new TrackGroup(createFormat(i, format)); } + this.tracks = new TrackGroupArray(tracks); prepared = true; return true; } @@ -156,7 +157,7 @@ public final class FrameworkSampleSource implements SampleSource { } @Override - public TrackGroup[] getTrackGroups() { + public TrackGroupArray getTrackGroups() { return tracks; } @@ -194,7 +195,7 @@ public final class FrameworkSampleSource implements SampleSource { return TrackStream.NOTHING_READ; } if (trackStates[track] != TRACK_STATE_FORMAT_SENT) { - formatHolder.format = tracks[track].getFormat(0); + formatHolder.format = tracks.get(track).getFormat(0); formatHolder.drmInitData = Util.SDK_INT >= 18 ? getDrmInitDataV18() : null; trackStates[track] = TRACK_STATE_FORMAT_SENT; return TrackStream.FORMAT_READ; diff --git a/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java b/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java index 87ce02538e..5d4781dfb6 100644 --- a/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java @@ -28,7 +28,7 @@ public class MultiSampleSource implements SampleSource { private boolean prepared; private long durationUs; - private TrackGroup[] tracks; + private TrackGroupArray trackGroups; public MultiSampleSource(SampleSource... sources) { this.sources = sources; @@ -53,14 +53,15 @@ public class MultiSampleSource implements SampleSource { durationUs = sources[i].getDurationUs(); } } - tracks = new TrackGroup[totalTrackGroupCount]; + TrackGroup[] trackGroups = new TrackGroup[totalTrackGroupCount]; int trackGroupIndex = 0; for (int i = 0; i < sources.length; i++) { int sourceTrackGroupCount = sources[i].getTrackGroups().length; for (int j = 0; j < sourceTrackGroupCount; j++) { - tracks[trackGroupIndex++] = sources[i].getTrackGroups()[j]; + trackGroups[trackGroupIndex++] = sources[i].getTrackGroups().get(j); } } + this.trackGroups = new TrackGroupArray(trackGroups); } return prepared; } @@ -71,8 +72,8 @@ public class MultiSampleSource implements SampleSource { } @Override - public TrackGroup[] getTrackGroups() { - return tracks; + public TrackGroupArray getTrackGroups() { + return trackGroups; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/SampleSource.java b/library/src/main/java/com/google/android/exoplayer/SampleSource.java index 6478ce3af9..1f3d7bd24b 100644 --- a/library/src/main/java/com/google/android/exoplayer/SampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SampleSource.java @@ -58,7 +58,7 @@ public interface SampleSource { * * @return The {@link TrackGroup}s. */ - public TrackGroup[] getTrackGroups(); + public TrackGroupArray getTrackGroups(); /** * Indicates to the source that it should continue buffering data for its enabled tracks. diff --git a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java index e46d0163c8..bf706cc295 100644 --- a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java @@ -52,7 +52,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load private final Format format; private final long durationUs; private final int minLoadableRetryCount; - private final TrackGroup[] trackGroups; + private final TrackGroupArray tracks; private int state; private byte[] sampleData; @@ -75,7 +75,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load this.format = format; this.durationUs = durationUs; this.minLoadableRetryCount = minLoadableRetryCount; - trackGroups = new TrackGroup[] {new TrackGroup(format)}; + tracks = new TrackGroupArray(new TrackGroup(format)); sampleData = new byte[INITIAL_SAMPLE_SIZE]; } @@ -105,8 +105,8 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load } @Override - public TrackGroup[] getTrackGroups() { - return trackGroups; + public TrackGroupArray getTrackGroups() { + return tracks; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/TrackGroup.java b/library/src/main/java/com/google/android/exoplayer/TrackGroup.java index 24b2646dcf..fb9d7f5d49 100644 --- a/library/src/main/java/com/google/android/exoplayer/TrackGroup.java +++ b/library/src/main/java/com/google/android/exoplayer/TrackGroup.java @@ -15,6 +15,10 @@ */ package com.google.android.exoplayer; +import com.google.android.exoplayer.util.Assertions; + +import java.util.Arrays; + /** * Defines a group of tracks exposed by a {@link SampleSource}. *
@@ -26,7 +30,7 @@ package com.google.android.exoplayer;
public final class TrackGroup {
/**
- * The number of tracks in the group.
+ * The number of tracks in the group. Always greater than zero.
*/
public final int length;
/**
@@ -36,18 +40,22 @@ public final class TrackGroup {
private final Format[] formats;
+ // Lazily initialized hashcode.
+ private int hashCode;
+
/**
* @param format The format of the single track.
*/
public TrackGroup(Format format) {
- this(false, format);
+ this(false, Assertions.checkNotNull(format));
}
/**
* @param adaptive Whether it's possible to adapt between multiple tracks in the group.
- * @param formats The track formats.
+ * @param formats The track formats. Must not be null or empty. Must not contain null elements.
*/
public TrackGroup(boolean adaptive, Format... formats) {
+ Assertions.checkState(formats.length > 0);
this.adaptive = adaptive;
this.formats = formats;
length = formats.length;
@@ -63,4 +71,29 @@ public final class TrackGroup {
return formats[index];
}
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = 17;
+ result = 31 * result + (adaptive ? 1231 : 1237);
+ result = 31 * result + Arrays.hashCode(formats);
+ result = 31 * result + length;
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ TrackGroup other = (TrackGroup) obj;
+ return adaptive == other.adaptive && length == other.length
+ && Arrays.equals(formats, other.formats);
+ }
+
}
diff --git a/library/src/main/java/com/google/android/exoplayer/TrackGroupArray.java b/library/src/main/java/com/google/android/exoplayer/TrackGroupArray.java
new file mode 100644
index 0000000000..51f387cd71
--- /dev/null
+++ b/library/src/main/java/com/google/android/exoplayer/TrackGroupArray.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer;
+
+import java.util.Arrays;
+
+/**
+ * An array of {@link TrackGroup}s exposed by a {@link SampleSource}.
+ */
+public final class TrackGroupArray {
+
+ /**
+ * The number of groups in the list. Greater than or equal to zero.
+ */
+ public final int length;
+
+ private final TrackGroup[] trackGroups;
+
+ // Lazily initialized hashcode.
+ private int hashCode;
+
+ /**
+ * @param trackGroups The groups. Must not be null or contain null elements, but may be empty.
+ */
+ public TrackGroupArray(TrackGroup... trackGroups) {
+ this.trackGroups = trackGroups;
+ this.length = trackGroups.length;
+ }
+
+ /**
+ * Gets the group at a given index.
+ *
+ * @param index The index of the group.
+ * @return The group.
+ */
+ public TrackGroup get(int index) {
+ return trackGroups[index];
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = 17;
+ result = 31 * result + Arrays.hashCode(trackGroups);
+ result = 31 * result + length;
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ TrackGroupArray other = (TrackGroupArray) obj;
+ return length == other.length && Arrays.equals(trackGroups, other.trackGroups);
+ }
+
+}
diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
index ed55e4ea2f..0913d838df 100644
--- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
+++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
@@ -22,6 +22,7 @@ import com.google.android.exoplayer.LoadControl;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackGroup;
+import com.google.android.exoplayer.TrackGroupArray;
import com.google.android.exoplayer.TrackSelection;
import com.google.android.exoplayer.TrackStream;
import com.google.android.exoplayer.extractor.DefaultTrackOutput;
@@ -78,7 +79,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
private long lastPerformedBufferOperation;
private boolean pendingReset;
- private TrackGroup[] trackGroups;
+ private TrackGroupArray trackGroups;
private long durationUs;
private Loader loader;
private boolean loadingFinished;
@@ -156,11 +157,11 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
}
durationUs = chunkSource.getDurationUs();
TrackGroup trackGroup = chunkSource.getTracks();
- if (trackGroup.length > 0) {
+ if (trackGroup != null) {
loader = new Loader("Loader:" + trackGroup.getFormat(0).containerMimeType);
- trackGroups = new TrackGroup[] {trackGroup};
+ trackGroups = new TrackGroupArray(trackGroup);
} else {
- trackGroups = new TrackGroup[0];
+ trackGroups = new TrackGroupArray();
}
state = STATE_PREPARED;
return true;
@@ -177,7 +178,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
}
@Override
- public TrackGroup[] getTrackGroups() {
+ public TrackGroupArray getTrackGroups() {
Assertions.checkState(state != STATE_IDLE);
return trackGroups;
}
diff --git a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
index 0a78498d5f..e55d605e00 100644
--- a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
+++ b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
@@ -495,18 +495,20 @@ public class DashChunkSource implements ChunkSource {
for (int i = 0; i < period.adaptationSets.size(); i++) {
AdaptationSet adaptationSet = period.adaptationSets.get(i);
if (adaptationSet.type == adaptationSetType) {
- // We've found an adaptation set of the exposed type.
adaptationSetIndex = i;
List