diff --git a/demo/assets/ic_launcher.svg b/demo/assets/ic_launcher.svg
new file mode 100644
index 0000000000..5486b27e29
--- /dev/null
+++ b/demo/assets/ic_launcher.svg
@@ -0,0 +1,660 @@
+
+
diff --git a/demo/assets/ic_launcher.svg~ b/demo/assets/ic_launcher.svg~
new file mode 100644
index 0000000000..c01934f697
--- /dev/null
+++ b/demo/assets/ic_launcher.svg~
@@ -0,0 +1,665 @@
+
+
+
+
diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml
index ee2f978324..ff3821f8fb 100644
--- a/demo/src/main/AndroidManifest.xml
+++ b/demo/src/main/AndroidManifest.xml
@@ -29,6 +29,7 @@
diff --git a/demo/src/main/res/drawable-hdpi/ic_launcher.png b/demo/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..3e5716b8ad
Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-mdpi/ic_launcher.png b/demo/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..a5d2a53b13
Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-xhdpi/ic_launcher.png b/demo/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..1d00268635
Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-xxhdpi/ic_launcher.png b/demo/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..ef2f312fd4
Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-xxxhdpi/ic_launcher.png b/demo/src/main/res/drawable-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..0acebb43c1
Binary files /dev/null and b/demo/src/main/res/drawable-xxxhdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/layout/player_activity_full.xml b/demo/src/main/res/layout/player_activity_full.xml
index d2e069620f..21fe68e5da 100644
--- a/demo/src/main/res/layout/player_activity_full.xml
+++ b/demo/src/main/res/layout/player_activity_full.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
+ android:textSize="10sp"
+ tools:ignore="SmallSp"/>
+ android:textSize="10sp"
+ tools:ignore="SmallSp"/>
();
this.rendererEnabledFlags = new boolean[rendererCount];
diff --git a/library/src/main/java/com/google/android/exoplayer/MediaFormat.java b/library/src/main/java/com/google/android/exoplayer/MediaFormat.java
index 18f47bf8b0..5d1bf3945b 100644
--- a/library/src/main/java/com/google/android/exoplayer/MediaFormat.java
+++ b/library/src/main/java/com/google/android/exoplayer/MediaFormat.java
@@ -164,7 +164,7 @@ public class MediaFormat {
public int hashCode() {
if (hashCode == 0) {
int result = 17;
- result = 31 * result + mimeType == null ? 0 : mimeType.hashCode();
+ result = 31 * result + (mimeType == null ? 0 : mimeType.hashCode());
result = 31 * result + maxInputSize;
result = 31 * result + width;
result = 31 * result + height;
diff --git a/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java b/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java
index 2b109e79d3..52602e1483 100644
--- a/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java
+++ b/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java
@@ -310,8 +310,8 @@ public final class AudioTrack {
// TODO: Does channelConfig determine channelCount?
boolean isAc3 = encoding == AudioFormat.ENCODING_AC3 || encoding == AudioFormat.ENCODING_E_AC3;
- if (audioTrack != null && this.sampleRate == sampleRate
- && this.channelConfig == channelConfig && !this.isAc3 && !isAc3) {
+ if (isInitialized() && this.sampleRate == sampleRate && this.channelConfig == channelConfig
+ && !this.isAc3 && !isAc3) {
// We already have an existing audio track with the correct sample rate and channel config.
return;
}
@@ -450,7 +450,7 @@ public final class AudioTrack {
/** Returns whether the audio track has more data pending that will be played back. */
public boolean hasPendingData() {
- return audioTrack != null && bytesToFrames(submittedBytes) > getPlaybackPositionFrames();
+ return isInitialized() && bytesToFrames(submittedBytes) > getPlaybackPositionFrames();
}
/** Returns whether enough data has been supplied via {@link #handleBuffer} to begin playback. */
@@ -461,7 +461,7 @@ public final class AudioTrack {
/** Sets the playback volume. */
public void setVolume(float volume) {
this.volume = volume;
- if (audioTrack != null) {
+ if (isInitialized()) {
if (Util.SDK_INT >= 21) {
setVolumeV21(audioTrack, volume);
} else {
@@ -482,7 +482,7 @@ public final class AudioTrack {
/** Pauses playback. */
public void pause() {
- if (audioTrack != null) {
+ if (isInitialized()) {
resetSyncParams();
audioTrack.pause();
}
@@ -494,7 +494,7 @@ public final class AudioTrack {
* after resetting.
*/
public void reset() {
- if (audioTrack != null) {
+ if (isInitialized()) {
submittedBytes = 0;
temporaryBufferSize = 0;
lastRawPlaybackHeadPosition = 0;
diff --git a/library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java b/library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
index 9a2341e904..36383dcea1 100644
--- a/library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
+++ b/library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
@@ -80,9 +80,11 @@ import java.util.ArrayList;
public final static class ContainerAtom extends Atom {
public final ArrayList children;
+ public final int endByteOffset;
- public ContainerAtom(int type) {
+ public ContainerAtom(int type, int endByteOffset) {
super(type);
+ this.endByteOffset = endByteOffset;
children = new ArrayList();
}
diff --git a/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java b/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
index 52fe8a94a1..599d0b0eab 100644
--- a/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
+++ b/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
@@ -139,7 +139,6 @@ public final class FragmentedMp4Extractor implements Extractor {
private final ParsableByteArray atomHeader;
private final byte[] extendedTypeScratch;
private final Stack containerAtoms;
- private final Stack containerAtomEndPoints;
private final TrackFragment fragmentRun;
private int parserState;
@@ -174,7 +173,6 @@ public final class FragmentedMp4Extractor implements Extractor {
atomHeader = new ParsableByteArray(ATOM_HEADER_SIZE);
extendedTypeScratch = new byte[16];
containerAtoms = new Stack();
- containerAtomEndPoints = new Stack();
fragmentRun = new TrackFragment();
psshData = new HashMap();
}
@@ -258,7 +256,6 @@ public final class FragmentedMp4Extractor implements Extractor {
}
}
containerAtoms.clear();
- containerAtomEndPoints.clear();
enterState(STATE_READING_ATOM_HEADER);
return true;
}
@@ -267,7 +264,7 @@ public final class FragmentedMp4Extractor implements Extractor {
switch (state) {
case STATE_READING_ATOM_HEADER:
atomBytesRead = 0;
- if (containerAtomEndPoints.isEmpty()) {
+ if (containerAtoms.isEmpty()) {
rootAtomBytesRead = 0;
}
break;
@@ -300,11 +297,12 @@ public final class FragmentedMp4Extractor implements Extractor {
return 0;
}
- if (PARSED_ATOMS.contains(atomType)) {
- if (CONTAINER_TYPES.contains(atomType)) {
+ Integer atomTypeInteger = atomType; // Avoids boxing atomType twice.
+ if (PARSED_ATOMS.contains(atomTypeInteger)) {
+ if (CONTAINER_TYPES.contains(atomTypeInteger)) {
enterState(STATE_READING_ATOM_HEADER);
- containerAtoms.add(new ContainerAtom(atomType));
- containerAtomEndPoints.add(rootAtomBytesRead + atomSize - ATOM_HEADER_SIZE);
+ containerAtoms.add(new ContainerAtom(atomType,
+ rootAtomBytesRead + atomSize - ATOM_HEADER_SIZE));
} else {
atomData = new ParsableByteArray(atomSize);
System.arraycopy(atomHeader.data, 0, atomData.data, 0, ATOM_HEADER_SIZE);
@@ -339,9 +337,7 @@ public final class FragmentedMp4Extractor implements Extractor {
results |= onLeafAtomRead(new LeafAtom(atomType, atomData));
}
- while (!containerAtomEndPoints.isEmpty()
- && containerAtomEndPoints.peek() == rootAtomBytesRead) {
- containerAtomEndPoints.pop();
+ while (!containerAtoms.isEmpty() && containerAtoms.peek().endByteOffset == rootAtomBytesRead) {
results |= onContainerAtomRead(containerAtoms.pop());
}
diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
index 0bc36a0b8b..dfd7b9f3c1 100644
--- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
+++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
@@ -343,8 +343,8 @@ public class SmoothStreamingChunkSource implements ChunkSource {
TrackElement trackElement = streamElement.tracks[trackIndex];
String mimeType = trackElement.mimeType;
if (streamElement.type == StreamElement.TYPE_VIDEO) {
- MediaFormat format = MediaFormat.createVideoFormat(mimeType, -1, trackElement.maxWidth,
- trackElement.maxHeight, Arrays.asList(trackElement.csd));
+ MediaFormat format = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE,
+ trackElement.maxWidth, trackElement.maxHeight, Arrays.asList(trackElement.csd));
format.setMaxVideoDimensions(streamElement.maxWidth, streamElement.maxHeight);
return format;
} else if (streamElement.type == StreamElement.TYPE_AUDIO) {
@@ -355,8 +355,8 @@ public class SmoothStreamingChunkSource implements ChunkSource {
csd = Collections.singletonList(CodecSpecificDataUtil.buildAudioSpecificConfig(
trackElement.sampleRate, trackElement.numChannels));
}
- MediaFormat format = MediaFormat.createAudioFormat(mimeType, -1, trackElement.numChannels,
- trackElement.sampleRate, csd);
+ MediaFormat format = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE,
+ trackElement.numChannels, trackElement.sampleRate, csd);
return format;
} else if (streamElement.type == StreamElement.TYPE_TEXT) {
return MediaFormat.createFormatForMimeType(streamElement.tracks[trackIndex].mimeType);
diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifest.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifest.java
index 7a6a32e44a..d7e6ee1358 100644
--- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifest.java
+++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifest.java
@@ -273,7 +273,7 @@ public class SmoothStreamingManifest {
Assertions.checkState(chunkIndex < chunkStartTimes.size());
String chunkUrl = chunkTemplate
.replace(URL_PLACEHOLDER_BITRATE, Integer.toString(tracks[track].bitrate))
- .replace(URL_PLACEHOLDER_START_TIME, Long.toString(chunkStartTimes.get(chunkIndex)));
+ .replace(URL_PLACEHOLDER_START_TIME, chunkStartTimes.get(chunkIndex).toString());
return Util.getMergedUri(baseUri, chunkUrl);
}
diff --git a/library/src/main/java/com/google/android/exoplayer/text/SubtitleView.java b/library/src/main/java/com/google/android/exoplayer/text/SubtitleView.java
index 7b2ecf5494..6ff3015afa 100644
--- a/library/src/main/java/com/google/android/exoplayer/text/SubtitleView.java
+++ b/library/src/main/java/com/google/android/exoplayer/text/SubtitleView.java
@@ -97,7 +97,7 @@ public class SubtitleView extends View {
Resources resources = getContext().getResources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
- int twoDpInPx = Math.round((2 * displayMetrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT);
+ int twoDpInPx = Math.round((2f * displayMetrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT);
cornerRadius = twoDpInPx;
outlineWidth = twoDpInPx;
shadowRadius = twoDpInPx;
diff --git a/library/src/main/java/com/google/android/exoplayer/upstream/NetworkLock.java b/library/src/main/java/com/google/android/exoplayer/upstream/NetworkLock.java
index 26df7db5c4..2576fff1cd 100644
--- a/library/src/main/java/com/google/android/exoplayer/upstream/NetworkLock.java
+++ b/library/src/main/java/com/google/android/exoplayer/upstream/NetworkLock.java
@@ -53,10 +53,17 @@ public final class NetworkLock {
*/
public static final int DOWNLOAD_PRIORITY = 10;
+ private final Object lock = new Object();
+
+ /** Guarded by {@link #lock}. */
private final PriorityQueue queue;
+ /** Guarded by {@link #lock}. */
+ private int highestPriority;
+
private NetworkLock() {
queue = new PriorityQueue();
+ highestPriority = Integer.MAX_VALUE;
}
/**
@@ -64,9 +71,11 @@ public final class NetworkLock {
*
* @param priority The priority of the task that would like to proceed.
*/
- public synchronized void proceed(int priority) throws InterruptedException {
- while (queue.peek() < priority) {
- wait();
+ public void proceed(int priority) throws InterruptedException {
+ synchronized (lock) {
+ while (highestPriority < priority) {
+ lock.wait();
+ }
}
}
@@ -76,8 +85,10 @@ public final class NetworkLock {
* @param priority The priority of the task that would like to proceed.
* @return Whether the passed priority is allowed to proceed.
*/
- public synchronized boolean proceedNonBlocking(int priority) {
- return queue.peek() >= priority;
+ public boolean proceedNonBlocking(int priority) {
+ synchronized (lock) {
+ return highestPriority >= priority;
+ }
}
/**
@@ -86,10 +97,11 @@ public final class NetworkLock {
* @param priority The priority of the task that would like to proceed.
* @throws PriorityTooLowException If the passed priority is not high enough to proceed.
*/
- public synchronized void proceedOrThrow(int priority) throws PriorityTooLowException {
- int highestPriority = queue.peek();
- if (highestPriority < priority) {
- throw new PriorityTooLowException(priority, highestPriority);
+ public void proceedOrThrow(int priority) throws PriorityTooLowException {
+ synchronized (lock) {
+ if (highestPriority < priority) {
+ throw new PriorityTooLowException(priority, highestPriority);
+ }
}
}
@@ -100,8 +112,11 @@ public final class NetworkLock {
*
* @param priority The priority of the task.
*/
- public synchronized void add(int priority) {
- queue.add(priority);
+ public void add(int priority) {
+ synchronized (lock) {
+ queue.add(priority);
+ highestPriority = Math.min(highestPriority, priority);
+ }
}
/**
@@ -109,9 +124,12 @@ public final class NetworkLock {
*
* @param priority The priority of the task.
*/
- public synchronized void remove(int priority) {
- queue.remove(priority);
- notifyAll();
+ public void remove(int priority) {
+ synchronized (lock) {
+ queue.remove(priority);
+ highestPriority = queue.isEmpty() ? Integer.MAX_VALUE : queue.peek();
+ lock.notifyAll();
+ }
}
}
diff --git a/library/src/main/java/com/google/android/exoplayer/util/Util.java b/library/src/main/java/com/google/android/exoplayer/util/Util.java
index 4d51fda9b0..ae2e014f0d 100644
--- a/library/src/main/java/com/google/android/exoplayer/util/Util.java
+++ b/library/src/main/java/com/google/android/exoplayer/util/Util.java
@@ -317,8 +317,8 @@ public final class Util {
} else if (matcher.group(9).equalsIgnoreCase("Z")) {
timezoneShift = 0;
} else {
- timezoneShift = ((Integer.valueOf(matcher.group(12)) * 60
- + Integer.valueOf(matcher.group(13))));
+ timezoneShift = ((Integer.parseInt(matcher.group(12)) * 60
+ + Integer.parseInt(matcher.group(13))));
if (matcher.group(11).equals("-")) {
timezoneShift *= -1;
}
@@ -328,12 +328,12 @@ public final class Util {
dateTime.clear();
// Note: The month value is 0-based, hence the -1 on group(2)
- dateTime.set(Integer.valueOf(matcher.group(1)),
- Integer.valueOf(matcher.group(2)) - 1,
- Integer.valueOf(matcher.group(3)),
- Integer.valueOf(matcher.group(4)),
- Integer.valueOf(matcher.group(5)),
- Integer.valueOf(matcher.group(6)));
+ dateTime.set(Integer.parseInt(matcher.group(1)),
+ Integer.parseInt(matcher.group(2)) - 1,
+ Integer.parseInt(matcher.group(3)),
+ Integer.parseInt(matcher.group(4)),
+ Integer.parseInt(matcher.group(5)),
+ Integer.parseInt(matcher.group(6)));
if (!TextUtils.isEmpty(matcher.group(8))) {
final BigDecimal bd = new BigDecimal("0." + matcher.group(8));
// we care only for milliseconds, so movePointRight(3)