Apply Android studio code analysis suggestions.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=120326293
This commit is contained in:
olly 2016-04-20 05:09:37 -07:00 committed by Oliver Woodman
parent 48bc98f1ed
commit 2e0518f47b
92 changed files with 368 additions and 622 deletions

View file

@ -16,7 +16,6 @@
package com.google.android.exoplayer.demo; package com.google.android.exoplayer.demo;
import com.google.android.exoplayer.AspectRatioFrameLayout; import com.google.android.exoplayer.AspectRatioFrameLayout;
import com.google.android.exoplayer.DefaultTrackSelector;
import com.google.android.exoplayer.DefaultTrackSelector.TrackInfo; import com.google.android.exoplayer.DefaultTrackSelector.TrackInfo;
import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
@ -106,7 +105,6 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
private DataSourceFactory dataSourceFactory; private DataSourceFactory dataSourceFactory;
private DemoPlayer player; private DemoPlayer player;
private DefaultTrackSelector trackSelector;
private TrackSelectionHelper trackSelectionHelper; private TrackSelectionHelper trackSelectionHelper;
private DebugTextViewHelper debugViewHelper; private DebugTextViewHelper debugViewHelper;
private boolean playerNeedsSource; private boolean playerNeedsSource;
@ -137,11 +135,8 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
root.setOnKeyListener(new OnKeyListener() { root.setOnKeyListener(new OnKeyListener() {
@Override @Override
public boolean onKey(View v, int keyCode, KeyEvent event) { public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE return keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_ESCAPE
|| keyCode == KeyEvent.KEYCODE_MENU) { && keyCode != KeyEvent.KEYCODE_MENU && mediaController.dispatchKeyEvent(event);
return false;
}
return mediaController.dispatchKeyEvent(event);
} }
}); });
@ -287,8 +282,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
player.setCaptionListener(this); player.setCaptionListener(this);
player.setMetadataListener(this); player.setMetadataListener(this);
player.seekTo(playerPosition); player.seekTo(playerPosition);
trackSelector = player.getTrackSelector(); trackSelectionHelper = new TrackSelectionHelper(player.getTrackSelector());
trackSelectionHelper = new TrackSelectionHelper(trackSelector);
playerNeedsSource = true; playerNeedsSource = true;
mediaController.setMediaPlayer(player.getPlayerControl()); mediaController.setMediaPlayer(player.getPlayerControl());
mediaController.setEnabled(true); mediaController.setEnabled(true);

View file

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 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.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The minimum subtitle font size. -->
<dimen name="subtitle_minimum_font_size">13sp</dimen>
</resources>

View file

@ -108,9 +108,7 @@ import java.util.List;
// Read the channel mapping. // Read the channel mapping.
numStreams = headerBytes[19] & 0xFF; numStreams = headerBytes[19] & 0xFF;
numCoupled = headerBytes[20] & 0xFF; numCoupled = headerBytes[20] & 0xFF;
for (int i = 0; i < channelCount; i++) { System.arraycopy(headerBytes, 21, streamMap, 0, channelCount);
streamMap[i] = headerBytes[21 + i];
}
} }
if (initializationData.size() == 3) { if (initializationData.size() == 3) {
if (initializationData.get(1).length != 8 || initializationData.get(2).length != 8) { if (initializationData.get(1).length != 8 || initializationData.get(2).length != 8) {

View file

@ -16,6 +16,7 @@
package com.google.android.exoplayer.ext.vp9; package com.google.android.exoplayer.ext.vp9;
import com.google.android.exoplayer.CodecCounters; import com.google.android.exoplayer.CodecCounters;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.Format; import com.google.android.exoplayer.Format;
@ -121,7 +122,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
private Format format; private Format format;
private VpxDecoder decoder; private VpxDecoder decoder;
private VpxInputBuffer inputBuffer; private DecoderInputBuffer inputBuffer;
private VpxOutputBuffer outputBuffer; private VpxOutputBuffer outputBuffer;
private VpxOutputBuffer nextOutputBuffer; private VpxOutputBuffer nextOutputBuffer;
@ -335,9 +336,6 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
} }
if (inputBuffer.isEndOfStream()) { if (inputBuffer.isEndOfStream()) {
inputStreamEnded = true; inputStreamEnded = true;
} else {
inputBuffer.width = format.width;
inputBuffer.height = format.height;
} }
decoder.queueInputBuffer(inputBuffer); decoder.queueInputBuffer(inputBuffer);
inputBuffer = null; inputBuffer = null;

View file

@ -16,6 +16,7 @@
package com.google.android.exoplayer.ext.vp9; package com.google.android.exoplayer.ext.vp9;
import com.google.android.exoplayer.C; import com.google.android.exoplayer.C;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.util.extensions.SimpleDecoder; import com.google.android.exoplayer.util.extensions.SimpleDecoder;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -24,7 +25,7 @@ import java.nio.ByteBuffer;
* JNI wrapper for the libvpx VP9 decoder. * JNI wrapper for the libvpx VP9 decoder.
*/ */
/* package */ final class VpxDecoder extends /* package */ final class VpxDecoder extends
SimpleDecoder<VpxInputBuffer, VpxOutputBuffer, VpxDecoderException> { SimpleDecoder<DecoderInputBuffer, VpxOutputBuffer, VpxDecoderException> {
public static final int OUTPUT_MODE_UNKNOWN = -1; public static final int OUTPUT_MODE_UNKNOWN = -1;
public static final int OUTPUT_MODE_YUV = 0; public static final int OUTPUT_MODE_YUV = 0;
@ -65,7 +66,7 @@ import java.nio.ByteBuffer;
*/ */
public VpxDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize) public VpxDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize)
throws VpxDecoderException { throws VpxDecoderException {
super(new VpxInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]); super(new DecoderInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]);
vpxDecContext = vpxInit(); vpxDecContext = vpxInit();
if (vpxDecContext == 0) { if (vpxDecContext == 0) {
throw new VpxDecoderException("Failed to initialize decoder"); throw new VpxDecoderException("Failed to initialize decoder");
@ -84,8 +85,8 @@ import java.nio.ByteBuffer;
} }
@Override @Override
protected VpxInputBuffer createInputBuffer() { protected DecoderInputBuffer createInputBuffer() {
return new VpxInputBuffer(); return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
} }
@Override @Override
@ -99,7 +100,7 @@ import java.nio.ByteBuffer;
} }
@Override @Override
protected VpxDecoderException decode(VpxInputBuffer inputBuffer, VpxOutputBuffer outputBuffer, protected VpxDecoderException decode(DecoderInputBuffer inputBuffer, VpxOutputBuffer outputBuffer,
boolean reset) { boolean reset) {
outputBuffer.timestampUs = inputBuffer.timeUs; outputBuffer.timestampUs = inputBuffer.timeUs;
inputBuffer.data.position(inputBuffer.data.position() - inputBuffer.size); inputBuffer.data.position(inputBuffer.data.position() - inputBuffer.size);

View file

@ -1,31 +0,0 @@
/*
* Copyright (C) 2014 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.ext.vp9;
import com.google.android.exoplayer.DecoderInputBuffer;
/**
* Input buffer to a {@link VpxDecoder}.
*/
/* package */ final class VpxInputBuffer extends DecoderInputBuffer {
public int width;
public int height;
public VpxInputBuffer() {
super(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
}
}

View file

@ -78,7 +78,6 @@ import javax.microedition.khronos.opengles.GL10;
private int program; private int program;
private int texLocation; private int texLocation;
private int colorMatrixLocation; private int colorMatrixLocation;
private FloatBuffer textureCoords;
private int previousWidth; private int previousWidth;
private int previousStride; private int previousStride;
@ -171,7 +170,7 @@ import javax.microedition.khronos.opengles.GL10;
// Set cropping of stride if either width or stride has changed. // Set cropping of stride if either width or stride has changed.
if (previousWidth != outputBuffer.width || previousStride != outputBuffer.yuvStrides[0]) { if (previousWidth != outputBuffer.width || previousStride != outputBuffer.yuvStrides[0]) {
float crop = (float) outputBuffer.width / outputBuffer.yuvStrides[0]; float crop = (float) outputBuffer.width / outputBuffer.yuvStrides[0];
textureCoords = nativeFloatBuffer( FloatBuffer textureCoords = nativeFloatBuffer(
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f,
crop, 0.0f, crop, 0.0f,

View file

@ -1,3 +1,5 @@
import com.android.builder.core.BuilderConstants
// Copyright (C) 2014 The Android Open Source Project // Copyright (C) 2014 The Android Open Source Project
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
@ -48,7 +50,7 @@ dependencies {
android.libraryVariants.all { variant -> android.libraryVariants.all { variant ->
def name = variant.buildType.name def name = variant.buildType.name
if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) { if (name.equals(BuilderConstants.DEBUG)) {
return; // Skip debug builds. return; // Skip debug builds.
} }
def task = project.tasks.create "jar${name.capitalize()}", Jar def task = project.tasks.create "jar${name.capitalize()}", Jar

View file

@ -26,7 +26,7 @@ import junit.framework.TestCase;
public class CTest extends TestCase { public class CTest extends TestCase {
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
public static final void testContants() { public static void testConstants() {
// Sanity check that constant values match those defined by the platform. // Sanity check that constant values match those defined by the platform.
assertEquals(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.BUFFER_FLAG_KEY_FRAME); assertEquals(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.BUFFER_FLAG_KEY_FRAME);
assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.BUFFER_FLAG_END_OF_STREAM); assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.BUFFER_FLAG_END_OF_STREAM);

View file

@ -24,7 +24,7 @@ import junit.framework.TestCase;
*/ */
public class ExtractorTest extends TestCase { public class ExtractorTest extends TestCase {
public static final void testContants() { public static void testContants() {
// Sanity check that constant values match those defined by {@link C}. // Sanity check that constant values match those defined by {@link C}.
assertEquals(C.RESULT_END_OF_INPUT, Extractor.RESULT_END_OF_INPUT); assertEquals(C.RESULT_END_OF_INPUT, Extractor.RESULT_END_OF_INPUT);
// Sanity check that the other constant values don't overlap. // Sanity check that the other constant values don't overlap.

View file

@ -794,15 +794,8 @@ public final class MatroskaExtractorTest extends InstrumentationTestCase {
output.assertSample(index, expectedMedia, timeUs, flags, encryptionKey); output.assertSample(index, expectedMedia, timeUs, flags, encryptionKey);
} }
private byte[] getVorbisCodecPrivate() { private byte[] getVorbisCodecPrivate() throws IOException {
byte[] codecPrivate = new byte[4207]; return TestUtil.getByteArray(getInstrumentation(), TEST_VORBIS_CODEC_PRIVATE);
try {
getInstrumentation().getContext().getResources().getAssets().open(TEST_VORBIS_CODEC_PRIVATE)
.read(codecPrivate);
} catch (IOException e) {
fail(); // should never happen
}
return codecPrivate;
} }
private static byte[] createFrameData(int size) { private static byte[] createFrameData(int size) {

View file

@ -65,10 +65,11 @@ import java.util.List;
private static final int NO_VALUE = -1; private static final int NO_VALUE = -1;
private final List<EbmlElement> trackEntries;
private final List<EbmlElement> mediaSegments;
private EbmlElement header; private EbmlElement header;
private EbmlElement info; private EbmlElement info;
private List<EbmlElement> trackEntries;
private List<EbmlElement> mediaSegments;
public StreamBuilder() { public StreamBuilder() {
trackEntries = new LinkedList<>(); trackEntries = new LinkedList<>();
@ -185,13 +186,13 @@ import java.util.List;
Assertions.checkNotNull(header); Assertions.checkNotNull(header);
Assertions.checkNotNull(info); Assertions.checkNotNull(info);
EbmlElement tracks = element(0x1654AE6B, trackEntries.toArray(new EbmlElement[0])); EbmlElement tracks = element(0x1654AE6B,
trackEntries.toArray(new EbmlElement[trackEntries.size()]));
EbmlElement[] children; EbmlElement[] children;
if (cuePointCount == 0) { if (cuePointCount == 0) {
children = new EbmlElement[2 + mediaSegments.size()]; children = new EbmlElement[2 + mediaSegments.size()];
System.arraycopy(mediaSegments.toArray(new EbmlElement[0]), 0, children, 2, System.arraycopy(mediaSegments.toArray(), 0, children, 2, mediaSegments.size());
mediaSegments.size());
children[0] = info; children[0] = info;
children[1] = tracks; children[1] = tracks;
} else { } else {
@ -211,8 +212,7 @@ import java.util.List;
// Build the top-level segment element. // Build the top-level segment element.
children = new EbmlElement[3 + mediaSegments.size()]; children = new EbmlElement[3 + mediaSegments.size()];
System.arraycopy(mediaSegments.toArray(new EbmlElement[0]), 0, children, 3, System.arraycopy(mediaSegments.toArray(), 0, children, 3, mediaSegments.size());
mediaSegments.size());
children[0] = info; children[0] = info;
children[1] = tracks; children[1] = tracks;
children[2] = cues; children[2] = cues;

View file

@ -88,7 +88,7 @@ public final class Mp4ExtractorTest extends TestCase {
/** Video frame timestamps in time units. */ /** Video frame timestamps in time units. */
private static final int[] SAMPLE_TIMESTAMPS = {0, 2, 3, 5, 6, 7}; private static final int[] SAMPLE_TIMESTAMPS = {0, 2, 3, 5, 6, 7};
/** Video frame sizes in bytes, including a very large sample. */ /** Video frame sizes in bytes, including a very large sample. */
private static final int[] SAMPLE_SIZES = {100, 20, 20, 44, 100, 1 * 1024 * 1024}; private static final int[] SAMPLE_SIZES = {100, 20, 20, 44, 100, 1024 * 1024};
/** Indices of key-frames. */ /** Indices of key-frames. */
private static final boolean[] SAMPLE_IS_SYNC = {true, false, false, false, true, true}; private static final boolean[] SAMPLE_IS_SYNC = {true, false, false, false, true, true};
/** Indices of video frame chunk offsets. */ /** Indices of video frame chunk offsets. */
@ -260,8 +260,8 @@ public final class Mp4ExtractorTest extends TestCase {
private static byte[] getStss() { private static byte[] getStss() {
int synchronizationSampleCount = 0; int synchronizationSampleCount = 0;
for (int i = 0; i < SAMPLE_IS_SYNC.length; i++) { for (boolean sampleIsSync : SAMPLE_IS_SYNC) {
if (SAMPLE_IS_SYNC[i]) { if (sampleIsSync) {
synchronizationSampleCount++; synchronizationSampleCount++;
} }
} }
@ -364,7 +364,7 @@ public final class Mp4ExtractorTest extends TestCase {
return CHUNK_OFFSETS[chunkIndex] + offsetInChunk; return CHUNK_OFFSETS[chunkIndex] + offsetInChunk;
} }
private static final byte[] getTestInputData(boolean includeStss, boolean mp4vFormat) { private static byte[] getTestInputData(boolean includeStss, boolean mp4vFormat) {
return includeStss ? getTestMp4File(mp4vFormat) return includeStss ? getTestMp4File(mp4vFormat)
: getTestMp4FileWithoutSynchronizationData(mp4vFormat); : getTestMp4FileWithoutSynchronizationData(mp4vFormat);
} }

View file

@ -32,7 +32,7 @@ import java.util.Random;
*/ */
public final class OggUtilTest extends TestCase { public final class OggUtilTest extends TestCase {
private Random random = new Random(0); private final Random random = new Random(0);
public void testReadBits() throws Exception { public void testReadBits() throws Exception {
assertEquals(0, OggUtil.readBits((byte) 0x00, 2, 2)); assertEquals(0, OggUtil.readBits((byte) 0x00, 2, 2));

View file

@ -34,7 +34,7 @@ import com.google.android.exoplayer.testutil.TestUtil;
0x4F, 0x67, 0x67, 0x53, // Oggs. 0x4F, 0x67, 0x67, 0x53, // Oggs.
0x00, // Stream revision. 0x00, // Stream revision.
headerType, headerType,
(int) (granule >> 0) & 0xFF, (int) (granule) & 0xFF,
(int) (granule >> 8) & 0xFF, (int) (granule >> 8) & 0xFF,
(int) (granule >> 16) & 0xFF, (int) (granule >> 16) & 0xFF,
(int) (granule >> 24) & 0xFF, (int) (granule >> 24) & 0xFF,
@ -46,7 +46,7 @@ import com.google.android.exoplayer.testutil.TestUtil;
0x10, 0x10,
0x00, 0x00,
0x00, // MSB of data serial number. 0x00, // MSB of data serial number.
(pageSequenceCounter >> 0) & 0xFF, (pageSequenceCounter) & 0xFF,
(pageSequenceCounter >> 8) & 0xFF, (pageSequenceCounter >> 8) & 0xFF,
(pageSequenceCounter >> 16) & 0xFF, (pageSequenceCounter >> 16) & 0xFF,
(pageSequenceCounter >> 24) & 0xFF, (pageSequenceCounter >> 24) & 0xFF,

View file

@ -60,7 +60,7 @@ public final class FakeDataSource implements DataSource {
totalLength += segment.length; totalLength += segment.length;
} }
this.totalLength = totalLength; this.totalLength = totalLength;
openedDataSpecs = new ArrayList<DataSpec>(); openedDataSpecs = new ArrayList<>();
} }
@Override @Override

View file

@ -105,7 +105,7 @@ public final class Mp4WebvttParserTest extends TestCase {
public void testNoCueSample() throws IOException { public void testNoCueSample() throws IOException {
Subtitle result = parser.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length); Subtitle result = parser.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length);
assertMp4WebvttSubtitleEquals(result, new Cue[] {}); assertMp4WebvttSubtitleEquals(result, new Cue[0]);
} }
// Negative tests. // Negative tests.

View file

@ -20,6 +20,7 @@ import com.google.android.exoplayer.text.Cue;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -32,37 +33,38 @@ public class WebvttSubtitleTest extends TestCase {
private static final String FIRST_AND_SECOND_SUBTITLE_STRING = private static final String FIRST_AND_SECOND_SUBTITLE_STRING =
FIRST_SUBTITLE_STRING + "\n" + SECOND_SUBTITLE_STRING; FIRST_SUBTITLE_STRING + "\n" + SECOND_SUBTITLE_STRING;
private WebvttSubtitle emptySubtitle = new WebvttSubtitle(new ArrayList<WebvttCue>()); private static final WebvttSubtitle emptySubtitle = new WebvttSubtitle(
Collections.<WebvttCue>emptyList());
private ArrayList<WebvttCue> simpleSubtitleCues = new ArrayList<>(); private static final WebvttSubtitle simpleSubtitle;
{ static {
ArrayList<WebvttCue> simpleSubtitleCues = new ArrayList<>();
WebvttCue firstCue = new WebvttCue(1000000, 2000000, FIRST_SUBTITLE_STRING); WebvttCue firstCue = new WebvttCue(1000000, 2000000, FIRST_SUBTITLE_STRING);
simpleSubtitleCues.add(firstCue); simpleSubtitleCues.add(firstCue);
WebvttCue secondCue = new WebvttCue(3000000, 4000000, SECOND_SUBTITLE_STRING); WebvttCue secondCue = new WebvttCue(3000000, 4000000, SECOND_SUBTITLE_STRING);
simpleSubtitleCues.add(secondCue); simpleSubtitleCues.add(secondCue);
simpleSubtitle = new WebvttSubtitle(simpleSubtitleCues);
} }
private WebvttSubtitle simpleSubtitle = new WebvttSubtitle(simpleSubtitleCues);
private ArrayList<WebvttCue> overlappingSubtitleCues = new ArrayList<>(); private static final WebvttSubtitle overlappingSubtitle;
{ static {
ArrayList<WebvttCue> overlappingSubtitleCues = new ArrayList<>();
WebvttCue firstCue = new WebvttCue(1000000, 3000000, FIRST_SUBTITLE_STRING); WebvttCue firstCue = new WebvttCue(1000000, 3000000, FIRST_SUBTITLE_STRING);
overlappingSubtitleCues.add(firstCue); overlappingSubtitleCues.add(firstCue);
WebvttCue secondCue = new WebvttCue(2000000, 4000000, SECOND_SUBTITLE_STRING); WebvttCue secondCue = new WebvttCue(2000000, 4000000, SECOND_SUBTITLE_STRING);
overlappingSubtitleCues.add(secondCue); overlappingSubtitleCues.add(secondCue);
overlappingSubtitle = new WebvttSubtitle(overlappingSubtitleCues);
} }
private WebvttSubtitle overlappingSubtitle = new WebvttSubtitle(overlappingSubtitleCues);
private ArrayList<WebvttCue> nestedSubtitleCues = new ArrayList<>(); private static final WebvttSubtitle nestedSubtitle;
{ static {
ArrayList<WebvttCue> nestedSubtitleCues = new ArrayList<>();
WebvttCue firstCue = new WebvttCue(1000000, 4000000, FIRST_SUBTITLE_STRING); WebvttCue firstCue = new WebvttCue(1000000, 4000000, FIRST_SUBTITLE_STRING);
nestedSubtitleCues.add(firstCue); nestedSubtitleCues.add(firstCue);
WebvttCue secondCue = new WebvttCue(2000000, 3000000, SECOND_SUBTITLE_STRING); WebvttCue secondCue = new WebvttCue(2000000, 3000000, SECOND_SUBTITLE_STRING);
nestedSubtitleCues.add(secondCue); nestedSubtitleCues.add(secondCue);
nestedSubtitle = new WebvttSubtitle(nestedSubtitleCues);
} }
private WebvttSubtitle nestedSubtitle = new WebvttSubtitle(nestedSubtitleCues);
public void testEventCount() { public void testEventCount() {
assertEquals(0, emptySubtitle.getEventTimeCount()); assertEquals(0, emptySubtitle.getEventTimeCount());
@ -71,13 +73,6 @@ public class WebvttSubtitleTest extends TestCase {
assertEquals(4, nestedSubtitle.getEventTimeCount()); assertEquals(4, nestedSubtitle.getEventTimeCount());
} }
public void testLastEventTime() {
assertEquals(-1, emptySubtitle.getLastEventTime());
assertEquals(4000000, simpleSubtitle.getLastEventTime());
assertEquals(4000000, overlappingSubtitle.getLastEventTime());
assertEquals(4000000, nestedSubtitle.getLastEventTime());
}
public void testSimpleSubtitleEventTimes() { public void testSimpleSubtitleEventTimes() {
testSubtitleEventTimesHelper(simpleSubtitle); testSubtitleEventTimesHelper(simpleSubtitle);
} }

View file

@ -26,8 +26,4 @@ public final class BehindLiveWindowException extends IOException {
super(); super();
} }
public BehindLiveWindowException(String message) {
super(message);
}
} }

View file

@ -46,17 +46,15 @@ public final class CodecCounters {
public String getDebugString() { public String getDebugString() {
ensureUpdated(); ensureUpdated();
StringBuilder builder = new StringBuilder(); return "cic:" + codecInitCount
builder.append("cic:").append(codecInitCount); + " crc:" + codecReleaseCount
builder.append(" crc:").append(codecReleaseCount); + " ibc:" + inputBufferCount
builder.append(" ibc:").append(inputBufferCount); + " ofc:" + outputFormatChangedCount
builder.append(" ofc:").append(outputFormatChangedCount); + " obc:" + outputBuffersChangedCount
builder.append(" obc:").append(outputBuffersChangedCount); + " ren:" + renderedOutputBufferCount
builder.append(" ren:").append(renderedOutputBufferCount); + " sob:" + skippedOutputBufferCount
builder.append(" sob:").append(skippedOutputBufferCount); + " dob:" + droppedOutputBufferCount
builder.append(" dob:").append(droppedOutputBufferCount); + " mcdob:" + maxConsecutiveDroppedOutputBufferCount;
builder.append(" mcdob:").append(maxConsecutiveDroppedOutputBufferCount);
return builder.toString();
} }
} }

View file

@ -148,11 +148,7 @@ public final class DecoderInfo {
} }
private static boolean isAdaptive(CodecCapabilities capabilities) { private static boolean isAdaptive(CodecCapabilities capabilities) {
if (Util.SDK_INT >= 19) { return Util.SDK_INT >= 19 && isAdaptiveV19(capabilities);
return isAdaptiveV19(capabilities);
} else {
return false;
}
} }
@TargetApi(19) @TargetApi(19)

View file

@ -503,12 +503,9 @@ import java.util.concurrent.atomic.AtomicInteger;
if (renderer.getState() == TrackRenderer.STATE_ENABLED) { if (renderer.getState() == TrackRenderer.STATE_ENABLED) {
renderer.disable(); renderer.disable();
} }
} catch (ExoPlaybackException e) { } catch (ExoPlaybackException | RuntimeException e) {
// There's nothing we can do. // There's nothing we can do.
Log.e(TAG, "Stop failed.", e); Log.e(TAG, "Stop failed.", e);
} catch (RuntimeException e) {
// Ditto.
Log.e(TAG, "Stop failed.", e);
} }
} }
if (source != null) { if (source != null) {

View file

@ -403,24 +403,21 @@ public final class Format {
} }
@TargetApi(16) @TargetApi(16)
private static final void maybeSetStringV16(MediaFormat format, String key, private static void maybeSetStringV16(MediaFormat format, String key, String value) {
String value) {
if (value != null) { if (value != null) {
format.setString(key, value); format.setString(key, value);
} }
} }
@TargetApi(16) @TargetApi(16)
private static final void maybeSetIntegerV16(MediaFormat format, String key, private static void maybeSetIntegerV16(MediaFormat format, String key, int value) {
int value) {
if (value != NO_VALUE) { if (value != NO_VALUE) {
format.setInteger(key, value); format.setInteger(key, value);
} }
} }
@TargetApi(16) @TargetApi(16)
private static final void maybeSetFloatV16(MediaFormat format, String key, private static void maybeSetFloatV16(MediaFormat format, String key, float value) {
float value) {
if (value != NO_VALUE) { if (value != NO_VALUE) {
format.setFloat(key, value); format.setFloat(key, value);
} }

View file

@ -98,6 +98,7 @@ public final class FrameworkSampleSource implements SampleSource {
fileDescriptor = null; fileDescriptor = null;
fileDescriptorOffset = 0; fileDescriptorOffset = 0;
fileDescriptorLength = 0; fileDescriptorLength = 0;
durationUs = C.UNSET_TIME_US;
} }
/** /**
@ -117,6 +118,7 @@ public final class FrameworkSampleSource implements SampleSource {
context = null; context = null;
uri = null; uri = null;
headers = null; headers = null;
durationUs = C.UNSET_TIME_US;
} }
// SampleSource implementation. // SampleSource implementation.
@ -132,7 +134,6 @@ public final class FrameworkSampleSource implements SampleSource {
} else { } else {
extractor.setDataSource(fileDescriptor, fileDescriptorOffset, fileDescriptorLength); extractor.setDataSource(fileDescriptor, fileDescriptorOffset, fileDescriptorLength);
} }
durationUs = C.UNSET_TIME_US;
trackStates = new int[extractor.getTrackCount()]; trackStates = new int[extractor.getTrackCount()];
pendingResets = new boolean[trackStates.length]; pendingResets = new boolean[trackStates.length];
TrackGroup[] trackArray = new TrackGroup[trackStates.length]; TrackGroup[] trackArray = new TrackGroup[trackStates.length];
@ -150,7 +151,7 @@ public final class FrameworkSampleSource implements SampleSource {
@Override @Override
public long getDurationUs() { public long getDurationUs() {
return C.UNSET_TIME_US; return durationUs;
} }
@Override @Override

View file

@ -667,11 +667,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
if (drmManagerState == DrmSessionManager.STATE_ERROR) { if (drmManagerState == DrmSessionManager.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSessionManager.getError(), getIndex()); throw ExoPlaybackException.createForRenderer(drmSessionManager.getError(), getIndex());
} }
if (drmManagerState != DrmSessionManager.STATE_OPENED_WITH_KEYS && return drmManagerState != DrmSessionManager.STATE_OPENED_WITH_KEYS
(bufferEncrypted || !playClearSamplesWithoutKeys)) { && (bufferEncrypted || !playClearSamplesWithoutKeys);
return true;
}
return false;
} }
/** /**
@ -840,10 +837,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
/** /**
* Processes a new output format. * Processes a new output format.
*
* @throws ExoPlaybackException If an error occurs processing the output format.
*/ */
private void processOutputFormat() throws ExoPlaybackException { private void processOutputFormat() {
android.media.MediaFormat format = codec.getOutputFormat(); android.media.MediaFormat format = codec.getOutputFormat();
if (codecNeedsMonoChannelCountWorkaround) { if (codecNeedsMonoChannelCountWorkaround) {
format.setInteger(android.media.MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(android.media.MediaFormat.KEY_CHANNEL_COUNT, 1);
@ -917,7 +912,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
private int getDecodeOnlyIndex(long presentationTimeUs) { private int getDecodeOnlyIndex(long presentationTimeUs) {
final int size = decodeOnlyPresentationTimestamps.size(); final int size = decodeOnlyPresentationTimestamps.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
if (decodeOnlyPresentationTimestamps.get(i).longValue() == presentationTimeUs) { if (decodeOnlyPresentationTimestamps.get(i) == presentationTimeUs) {
return i; return i;
} }
} }

View file

@ -126,8 +126,7 @@ public final class MediaCodecUtil {
String codecName = info.getName(); String codecName = info.getName();
if (isCodecUsableDecoder(info, codecName, secureDecodersExplicit)) { if (isCodecUsableDecoder(info, codecName, secureDecodersExplicit)) {
String[] supportedTypes = info.getSupportedTypes(); String[] supportedTypes = info.getSupportedTypes();
for (int j = 0; j < supportedTypes.length; j++) { for (String supportedType : supportedTypes) {
String supportedType = supportedTypes[j];
if (supportedType.equalsIgnoreCase(mimeType)) { if (supportedType.equalsIgnoreCase(mimeType)) {
CodecCapabilities capabilities = info.getCapabilitiesForType(supportedType); CodecCapabilities capabilities = info.getCapabilitiesForType(supportedType);
boolean secure = mediaCodecList.isSecurePlaybackSupported(key.mimeType, capabilities); boolean secure = mediaCodecList.isSecurePlaybackSupported(key.mimeType, capabilities);
@ -291,25 +290,25 @@ public final class MediaCodecUtil {
/** /**
* The number of codecs in the list. * The number of codecs in the list.
*/ */
public int getCodecCount(); int getCodecCount();
/** /**
* The info at the specified index in the list. * The info at the specified index in the list.
* *
* @param index The index. * @param index The index.
*/ */
public MediaCodecInfo getCodecInfoAt(int index); MediaCodecInfo getCodecInfoAt(int index);
/** /**
* @return Returns whether secure decoders are explicitly listed, if present. * @return Returns whether secure decoders are explicitly listed, if present.
*/ */
public boolean secureDecodersExplicit(); boolean secureDecodersExplicit();
/** /**
* Whether secure playback is supported for the given {@link CodecCapabilities}, which should * Whether secure playback is supported for the given {@link CodecCapabilities}, which should
* have been obtained from a {@link MediaCodecInfo} obtained from this list. * have been obtained from a {@link MediaCodecInfo} obtained from this list.
*/ */
public boolean isSecurePlaybackSupported(String mimeType, CodecCapabilities capabilities); boolean isSecurePlaybackSupported(String mimeType, CodecCapabilities capabilities);
} }

View file

@ -192,10 +192,10 @@ public final class MultiSampleSource implements SampleSource {
private Pair<SampleSource, Integer> getSourceAndGroup(int group) { private Pair<SampleSource, Integer> getSourceAndGroup(int group) {
int totalTrackGroupCount = 0; int totalTrackGroupCount = 0;
for (int i = 0; i < sources.length; i++) { for (SampleSource source : sources) {
int sourceTrackGroupCount = sources[i].getTrackGroups().length; int sourceTrackGroupCount = source.getTrackGroups().length;
if (group < totalTrackGroupCount + sourceTrackGroupCount) { if (group < totalTrackGroupCount + sourceTrackGroupCount) {
return Pair.create(sources[i], group - totalTrackGroupCount); return Pair.create(source, group - totalTrackGroupCount);
} }
totalTrackGroupCount += sourceTrackGroupCount; totalTrackGroupCount += sourceTrackGroupCount;
} }

View file

@ -227,7 +227,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
long resetPositionUs = stream.readReset(); long resetPositionUs = stream.readReset();
if (resetPositionUs != C.UNSET_TIME_US) { if (resetPositionUs != C.UNSET_TIME_US) {
reset(resetPositionUs); reset(resetPositionUs);
return;
} }
} }

View file

@ -36,9 +36,9 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
private final ChunkExtractorWrapper extractorWrapper; private final ChunkExtractorWrapper extractorWrapper;
private final long sampleOffsetUs; private final long sampleOffsetUs;
private final Format sampleFormat;
private volatile DrmInitData drmInitData; private volatile DrmInitData drmInitData;
private volatile Format sampleFormat;
private volatile int bytesLoaded; private volatile int bytesLoaded;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;

View file

@ -70,7 +70,7 @@ public interface FormatEvaluator {
/** /**
* A format evaluation. * A format evaluation.
*/ */
public static final class Evaluation { final class Evaluation {
/** /**
* The selected format. * The selected format.
@ -99,7 +99,7 @@ public interface FormatEvaluator {
/** /**
* Selects randomly between the available formats, excluding those that are blacklisted. * Selects randomly between the available formats, excluding those that are blacklisted.
*/ */
public static final class RandomEvaluator implements FormatEvaluator { final class RandomEvaluator implements FormatEvaluator {
private final Random random; private final Random random;
@ -131,8 +131,8 @@ public interface FormatEvaluator {
Evaluation evaluation) { Evaluation evaluation) {
// Count the number of non-blacklisted formats. // Count the number of non-blacklisted formats.
int nonBlacklistedFormatCount = 0; int nonBlacklistedFormatCount = 0;
for (int i = 0; i < blacklistFlags.length; i++) { for (boolean blacklistFlag : blacklistFlags) {
if (!blacklistFlags[i]) { if (!blacklistFlag) {
nonBlacklistedFormatCount++; nonBlacklistedFormatCount++;
} }
} }
@ -171,7 +171,7 @@ public interface FormatEvaluator {
* reference implementation only. It is recommended that application developers implement their * reference implementation only. It is recommended that application developers implement their
* own adaptive evaluator to more precisely suit their use case. * own adaptive evaluator to more precisely suit their use case.
*/ */
public static final class AdaptiveEvaluator implements FormatEvaluator { final class AdaptiveEvaluator implements FormatEvaluator {
public static final int DEFAULT_MAX_INITIAL_BITRATE = 800000; public static final int DEFAULT_MAX_INITIAL_BITRATE = 800000;

View file

@ -371,7 +371,6 @@ public class DashChunkSource implements ChunkSource {
} }
} catch (BehindLiveWindowException e) { } catch (BehindLiveWindowException e) {
fatalError = e; fatalError = e;
return;
} }
} }

View file

@ -90,8 +90,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
// MPD parsing. // MPD parsing.
@Override @Override
public MediaPresentationDescription parse(Uri uri, InputStream inputStream) public MediaPresentationDescription parse(Uri uri, InputStream inputStream) throws IOException {
throws IOException, ParserException {
try { try {
XmlPullParser xpp = xmlParserFactory.newPullParser(); XmlPullParser xpp = xmlParserFactory.newPullParser();
xpp.setInput(inputStream, null); xpp.setInput(inputStream, null);
@ -101,9 +100,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
"inputStream does not contain a valid media presentation description"); "inputStream does not contain a valid media presentation description");
} }
return parseMediaPresentationDescription(xpp, uri.toString()); return parseMediaPresentationDescription(xpp, uri.toString());
} catch (XmlPullParserException e) { } catch (XmlPullParserException | ParseException e) {
throw new ParserException(e);
} catch (ParseException e) {
throw new ParserException(e); throw new ParserException(e);
} }
} }
@ -114,7 +111,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
long durationMs = parseDuration(xpp, "mediaPresentationDuration", -1); long durationMs = parseDuration(xpp, "mediaPresentationDuration", -1);
long minBufferTimeMs = parseDuration(xpp, "minBufferTime", -1); long minBufferTimeMs = parseDuration(xpp, "minBufferTime", -1);
String typeString = xpp.getAttributeValue(null, "type"); String typeString = xpp.getAttributeValue(null, "type");
boolean dynamic = (typeString != null) ? typeString.equals("dynamic") : false; boolean dynamic = typeString != null && typeString.equals("dynamic");
long minUpdateTimeMs = (dynamic) ? parseDuration(xpp, "minimumUpdatePeriod", -1) : -1; long minUpdateTimeMs = (dynamic) ? parseDuration(xpp, "minimumUpdatePeriod", -1) : -1;
long timeShiftBufferDepthMs = (dynamic) ? parseDuration(xpp, "timeShiftBufferDepth", -1) : -1; long timeShiftBufferDepthMs = (dynamic) ? parseDuration(xpp, "timeShiftBufferDepth", -1) : -1;
UtcTimingElement utcTiming = null; UtcTimingElement utcTiming = null;
@ -372,7 +369,6 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
float frameRate = parseFrameRate(xpp, adaptationSetFrameRate); float frameRate = parseFrameRate(xpp, adaptationSetFrameRate);
int audioChannels = adaptationSetAudioChannels; int audioChannels = adaptationSetAudioChannels;
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate); int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
String language = adaptationSetLanguage;
boolean seenFirstBaseUrl = false; boolean seenFirstBaseUrl = false;
do { do {
@ -399,7 +395,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
} while (!ParserUtil.isEndTag(xpp, "Representation")); } while (!ParserUtil.isEndTag(xpp, "Representation"));
Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels, Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels,
audioSamplingRate, bandwidth, language, codecs); audioSamplingRate, bandwidth, adaptationSetLanguage, codecs);
return buildRepresentation(contentId, -1, format, return buildRepresentation(contentId, -1, format,
segmentBase != null ? segmentBase : new SingleSegmentBase(baseUrl)); segmentBase != null ? segmentBase : new SingleSegmentBase(baseUrl));
} }

View file

@ -30,8 +30,8 @@ public abstract class Representation {
/** /**
* Identifies the piece of content to which this {@link Representation} belongs. * Identifies the piece of content to which this {@link Representation} belongs.
* <p> * <p>
* For example, all {@link Representation}s belonging to a video should have the same * For example, all {@link Representation}s belonging to a video should have the same content
* {@link #contentId}, which should uniquely identify that video. * identifier that uniquely identifies that video.
*/ */
public final String contentId; public final String contentId;
/** /**

View file

@ -327,7 +327,7 @@ public abstract class SegmentBase {
@Override @Override
public RangedUri getSegmentUrl(Representation representation, int sequenceNumber) { public RangedUri getSegmentUrl(Representation representation, int sequenceNumber) {
long time = 0; long time;
if (segmentTimeline != null) { if (segmentTimeline != null) {
time = segmentTimeline.get(sequenceNumber - startNumber).startTime; time = segmentTimeline.get(sequenceNumber - startNumber).startTime;
} else { } else {
@ -357,8 +357,8 @@ public abstract class SegmentBase {
*/ */
public static class SegmentTimelineElement { public static class SegmentTimelineElement {
/* package */ long startTime; /* package */ final long startTime;
/* package */ long duration; /* package */ final long duration;
/** /**
* @param startTime The start time of the element. The value in seconds is the division of this * @param startTime The start time of the element. The value in seconds is the division of this

View file

@ -144,14 +144,18 @@ public final class UrlTemplate {
} }
identifier = identifier.substring(0, formatTagIndex); identifier = identifier.substring(0, formatTagIndex);
} }
if (identifier.equals(NUMBER)) { switch (identifier) {
identifiers[identifierCount] = NUMBER_ID; case NUMBER:
} else if (identifier.equals(BANDWIDTH)) { identifiers[identifierCount] = NUMBER_ID;
identifiers[identifierCount] = BANDWIDTH_ID; break;
} else if (identifier.equals(TIME)) { case BANDWIDTH:
identifiers[identifierCount] = TIME_ID; identifiers[identifierCount] = BANDWIDTH_ID;
} else { break;
throw new IllegalArgumentException("Invalid template: " + template); case TIME:
identifiers[identifierCount] = TIME_ID;
break;
default:
throw new IllegalArgumentException("Invalid template: " + template);
} }
identifierFormatTags[identifierCount] = formatTag; identifierFormatTags[identifierCount] = formatTag;
} }

View file

@ -154,7 +154,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
private static class XsDateTimeParser implements UriLoadable.Parser<Long> { private static class XsDateTimeParser implements UriLoadable.Parser<Long> {
@Override @Override
public Long parse(Uri uri, InputStream inputStream) throws ParserException, IOException { public Long parse(Uri uri, InputStream inputStream) throws IOException {
String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine(); String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine();
try { try {
return Util.parseXsDateTime(firstLine); return Util.parseXsDateTime(firstLine);
@ -168,7 +168,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
private static class Iso8601Parser implements UriLoadable.Parser<Long> { private static class Iso8601Parser implements UriLoadable.Parser<Long> {
@Override @Override
public Long parse(Uri uri, InputStream inputStream) throws ParserException, IOException { public Long parse(Uri uri, InputStream inputStream) throws IOException {
String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine(); String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine();
try { try {
// TODO: It may be necessary to handle timestamp offsets from UTC. // TODO: It may be necessary to handle timestamp offsets from UTC.

View file

@ -35,12 +35,12 @@ public interface DrmInitData {
* @param schemeUuid The DRM scheme's UUID. * @param schemeUuid The DRM scheme's UUID.
* @return The initialization data for the scheme, or null if the scheme is not supported. * @return The initialization data for the scheme, or null if the scheme is not supported.
*/ */
public abstract SchemeInitData get(UUID schemeUuid); SchemeInitData get(UUID schemeUuid);
/** /**
* A {@link DrmInitData} implementation that maps UUID onto scheme specific data. * A {@link DrmInitData} implementation that maps UUID onto scheme specific data.
*/ */
public static final class Mapped implements DrmInitData { final class Mapped implements DrmInitData {
private final Map<UUID, SchemeInitData> schemeData; private final Map<UUID, SchemeInitData> schemeData;
@ -68,9 +68,9 @@ public interface DrmInitData {
/** /**
* A {@link DrmInitData} implementation that returns the same initialization data for all schemes. * A {@link DrmInitData} implementation that returns the same initialization data for all schemes.
*/ */
public static final class Universal implements DrmInitData { final class Universal implements DrmInitData {
private SchemeInitData data; private final SchemeInitData data;
public Universal(SchemeInitData data) { public Universal(SchemeInitData data) {
this.data = data; this.data = data;
@ -86,7 +86,7 @@ public interface DrmInitData {
/** /**
* Scheme initialization data. * Scheme initialization data.
*/ */
public static final class SchemeInitData { final class SchemeInitData {
/** /**
* The mimeType of {@link #data}. * The mimeType of {@link #data}.

View file

@ -27,24 +27,24 @@ public interface DrmSessionManager {
/** /**
* The error state. {@link #getError()} can be used to retrieve the cause. * The error state. {@link #getError()} can be used to retrieve the cause.
*/ */
public static final int STATE_ERROR = 0; int STATE_ERROR = 0;
/** /**
* The session is closed. * The session is closed.
*/ */
public static final int STATE_CLOSED = 1; int STATE_CLOSED = 1;
/** /**
* The session is being opened (i.e. {@link #open(DrmInitData)} has been called, but the session * The session is being opened (i.e. {@link #open(DrmInitData)} has been called, but the session
* is not yet open). * is not yet open).
*/ */
public static final int STATE_OPENING = 2; int STATE_OPENING = 2;
/** /**
* The session is open, but does not yet have the keys required for decryption. * The session is open, but does not yet have the keys required for decryption.
*/ */
public static final int STATE_OPENED = 3; int STATE_OPENED = 3;
/** /**
* The session is open and has the keys required for decryption. * The session is open and has the keys required for decryption.
*/ */
public static final int STATE_OPENED_WITH_KEYS = 4; int STATE_OPENED_WITH_KEYS = 4;
/** /**
* Opens the session, possibly asynchronously. * Opens the session, possibly asynchronously.

View file

@ -29,18 +29,18 @@ public interface Extractor {
* to the next {@link #read(ExtractorInput, PositionHolder)} is required to provide data * to the next {@link #read(ExtractorInput, PositionHolder)} is required to provide data
* continuing from the position in the stream reached by the returning call. * continuing from the position in the stream reached by the returning call.
*/ */
public static final int RESULT_CONTINUE = 0; int RESULT_CONTINUE = 0;
/** /**
* Returned by {@link #read(ExtractorInput, PositionHolder)} if the {@link ExtractorInput} passed * Returned by {@link #read(ExtractorInput, PositionHolder)} if the {@link ExtractorInput} passed
* to the next {@link #read(ExtractorInput, PositionHolder)} is required to provide data starting * to the next {@link #read(ExtractorInput, PositionHolder)} is required to provide data starting
* from a specified position in the stream. * from a specified position in the stream.
*/ */
public static final int RESULT_SEEK = 1; int RESULT_SEEK = 1;
/** /**
* Returned by {@link #read(ExtractorInput, PositionHolder)} if the end of the * Returned by {@link #read(ExtractorInput, PositionHolder)} if the end of the
* {@link ExtractorInput} was reached. Equal to {@link C#RESULT_END_OF_INPUT}. * {@link ExtractorInput} was reached. Equal to {@link C#RESULT_END_OF_INPUT}.
*/ */
public static final int RESULT_END_OF_INPUT = C.RESULT_END_OF_INPUT; int RESULT_END_OF_INPUT = C.RESULT_END_OF_INPUT;
/** /**
* Initializes the extractor with an {@link ExtractorOutput}. * Initializes the extractor with an {@link ExtractorOutput}.

View file

@ -315,9 +315,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
for (int i = 0; i < extractors.length; i++) { for (int i = 0; i < extractors.length; i++) {
try { try {
extractors[i] = DEFAULT_EXTRACTOR_CLASSES.get(i).newInstance(); extractors[i] = DEFAULT_EXTRACTOR_CLASSES.get(i).newInstance();
} catch (InstantiationException e) { } catch (Exception e) {
throw new IllegalStateException("Unexpected error creating default extractor", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected error creating default extractor", e); throw new IllegalStateException("Unexpected error creating default extractor", e);
} }
} }
@ -569,7 +567,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
// If we're not pending a reset, see if we can seek within the sample queues. // If we're not pending a reset, see if we can seek within the sample queues.
boolean seekInsideBuffer = !isPendingReset(); boolean seekInsideBuffer = !isPendingReset();
for (int i = 0; seekInsideBuffer && i < sampleQueues.length; i++) { for (int i = 0; seekInsideBuffer && i < sampleQueues.length; i++) {
seekInsideBuffer &= sampleQueues[i].skipToKeyframeBefore(positionUs); seekInsideBuffer = sampleQueues[i].skipToKeyframeBefore(positionUs);
} }
// If we failed to seek within the sample queues, we need to restart. // If we failed to seek within the sample queues, we need to restart.
if (!seekInsideBuffer) { if (!seekInsideBuffer) {
@ -827,7 +825,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
* @throws InterruptedException Thrown if the thread was interrupted. * @throws InterruptedException Thrown if the thread was interrupted.
*/ */
public Extractor selectExtractor(ExtractorInput input) public Extractor selectExtractor(ExtractorInput input)
throws UnrecognizedInputFormatException, IOException, InterruptedException { throws IOException, InterruptedException {
if (extractor != null) { if (extractor != null) {
return extractor; return extractor;
} }

View file

@ -137,10 +137,8 @@ import java.util.List;
* Builds initialization data for a {@link Format} from H.264 (AVC) codec private data. * Builds initialization data for a {@link Format} from H.264 (AVC) codec private data.
* *
* @return The AvcSequenceHeader data needed to initialize the video codec. * @return The AvcSequenceHeader data needed to initialize the video codec.
* @throws ParserException If the initialization data could not be built.
*/ */
private AvcSequenceHeaderData parseAvcCodecPrivate(ParsableByteArray buffer) private AvcSequenceHeaderData parseAvcCodecPrivate(ParsableByteArray buffer) {
throws ParserException {
// TODO: Deduplicate with AtomParsers.parseAvcCFromParent. // TODO: Deduplicate with AtomParsers.parseAvcCFromParent.
buffer.setPosition(4); buffer.setPosition(4);
int nalUnitLengthFieldLength = (buffer.readUnsignedByte() & 0x03) + 1; int nalUnitLengthFieldLength = (buffer.readUnsignedByte() & 0x03) + 1;

View file

@ -145,8 +145,8 @@ import java.util.Stack;
* @throws IOException If an error occurs reading from the input. * @throws IOException If an error occurs reading from the input.
* @throws InterruptedException If the thread is interrupted. * @throws InterruptedException If the thread is interrupted.
*/ */
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws EOFException, private long maybeResyncToNextLevel1Element(ExtractorInput input) throws IOException,
IOException, InterruptedException { InterruptedException {
input.resetPeekPosition(); input.resetPeekPosition();
while (true) { while (true) {
input.peekFully(scratch, 0, MAX_ID_BYTES); input.peekFully(scratch, 0, MAX_ID_BYTES);

View file

@ -32,34 +32,34 @@ import java.io.IOException;
/** /**
* Type for unknown elements. * Type for unknown elements.
*/ */
public static final int TYPE_UNKNOWN = 0; int TYPE_UNKNOWN = 0;
/** /**
* Type for elements that contain child elements. * Type for elements that contain child elements.
*/ */
public static final int TYPE_MASTER = 1; int TYPE_MASTER = 1;
/** /**
* Type for integer value elements of up to 8 bytes. * Type for integer value elements of up to 8 bytes.
*/ */
public static final int TYPE_UNSIGNED_INT = 2; int TYPE_UNSIGNED_INT = 2;
/** /**
* Type for string elements. * Type for string elements.
*/ */
public static final int TYPE_STRING = 3; int TYPE_STRING = 3;
/** /**
* Type for binary elements. * Type for binary elements.
*/ */
public static final int TYPE_BINARY = 4; int TYPE_BINARY = 4;
/** /**
* Type for IEEE floating point value elements of either 4 or 8 bytes. * Type for IEEE floating point value elements of either 4 or 8 bytes.
*/ */
public static final int TYPE_FLOAT = 5; int TYPE_FLOAT = 5;
/** /**
* Initializes the extractor with an {@link EbmlReaderOutput}. * Initializes the extractor with an {@link EbmlReaderOutput}.
* *
* @param output An {@link EbmlReaderOutput} to receive events. * @param output An {@link EbmlReaderOutput} to receive events.
*/ */
public void init(EbmlReaderOutput output); void init(EbmlReaderOutput output);
/** /**
* Resets the state of the reader. * Resets the state of the reader.
@ -67,7 +67,7 @@ import java.io.IOException;
* Subsequent calls to {@link #read(ExtractorInput)} will start reading a new EBML structure * Subsequent calls to {@link #read(ExtractorInput)} will start reading a new EBML structure
* from scratch. * from scratch.
*/ */
public void reset(); void reset();
/** /**
* Reads from an {@link ExtractorInput}, invoking an event callback if possible. * Reads from an {@link ExtractorInput}, invoking an event callback if possible.
@ -78,7 +78,6 @@ import java.io.IOException;
* @throws IOException If an error occurs reading from the input. * @throws IOException If an error occurs reading from the input.
* @throws InterruptedException If the thread is interrupted. * @throws InterruptedException If the thread is interrupted.
*/ */
public boolean read(ExtractorInput input) throws ParserException, IOException, boolean read(ExtractorInput input) throws IOException, InterruptedException;
InterruptedException;
} }

View file

@ -112,6 +112,6 @@ import java.io.IOException;
* @throws InterruptedException If the thread is interrupted. * @throws InterruptedException If the thread is interrupted.
*/ */
void binaryElement(int id, int contentsSize, ExtractorInput input) void binaryElement(int id, int contentsSize, ExtractorInput input)
throws ParserException, IOException, InterruptedException; throws IOException, InterruptedException;
} }

View file

@ -100,7 +100,7 @@ import java.nio.charset.Charset;
if (extendedHeaderSize > frame.bytesLeft()) { if (extendedHeaderSize > frame.bytesLeft()) {
return null; return null;
} }
int paddingSize = 0; int paddingSize;
if (extendedHeaderSize >= 6) { if (extendedHeaderSize >= 6) {
frame.skipBytes(2); // extended flags frame.skipBytes(2); // extended flags
paddingSize = frame.readUnsignedIntToInt(); paddingSize = frame.readUnsignedIntToInt();

View file

@ -260,8 +260,8 @@ import java.util.List;
@Override @Override
public String toString() { public String toString() {
return getAtomTypeString(type) return getAtomTypeString(type)
+ " leaves: " + Arrays.toString(leafChildren.toArray(new LeafAtom[0])) + " leaves: " + Arrays.toString(leafChildren.toArray())
+ " containers: " + Arrays.toString(containerChildren.toArray(new ContainerAtom[0])); + " containers: " + Arrays.toString(containerChildren.toArray());
} }
} }

View file

@ -69,7 +69,6 @@ public final class Mp4Extractor implements Extractor, SeekMap {
private int atomHeaderBytesRead; private int atomHeaderBytesRead;
private ParsableByteArray atomData; private ParsableByteArray atomData;
private int sampleSize;
private int sampleBytesWritten; private int sampleBytesWritten;
private int sampleCurrentNalBytesRemaining; private int sampleCurrentNalBytesRemaining;
@ -341,7 +340,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
} }
} }
this.durationUs = durationUs; this.durationUs = durationUs;
this.tracks = tracks.toArray(new Mp4Track[0]); this.tracks = tracks.toArray(new Mp4Track[tracks.size()]);
extractorOutput.endTracks(); extractorOutput.endTracks();
extractorOutput.seekMap(this); extractorOutput.seekMap(this);
} }
@ -378,7 +377,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
return RESULT_SEEK; return RESULT_SEEK;
} }
input.skipFully((int) skipAmount); input.skipFully((int) skipAmount);
sampleSize = track.sampleTable.sizes[sampleIndex]; int sampleSize = track.sampleTable.sizes[sampleIndex];
if (track.track.nalUnitLengthFieldLength != -1) { if (track.track.nalUnitLengthFieldLength != -1) {
// Zero the top three bytes of the array that we'll use to parse nal unit lengths, in case // Zero the top three bytes of the array that we'll use to parse nal unit lengths, in case
// they're only 1 or 2 bytes long. // they're only 1 or 2 bytes long.

View file

@ -26,7 +26,9 @@ import com.google.android.exoplayer.util.Assertions;
/* package */ final class VorbisBitArray { /* package */ final class VorbisBitArray {
public final byte[] data; public final byte[] data;
private int limit;
private final int limit;
private int byteOffset; private int byteOffset;
private int bitOffset; private int bitOffset;

View file

@ -174,7 +174,7 @@ import java.util.Arrays;
bitArray.skipBits(headerData.getPosition() * 8); bitArray.skipBits(headerData.getPosition() * 8);
for (int i = 0; i < numberOfBooks; i++) { for (int i = 0; i < numberOfBooks; i++) {
readBook(bitArray); skipBook(bitArray);
} }
int timeCount = bitArray.readBits(6) + 1; int timeCount = bitArray.readBits(6) + 1;
@ -336,7 +336,7 @@ import java.util.Arrays;
} }
} }
private static CodeBook readBook(VorbisBitArray bitArray) throws ParserException { private static void skipBook(VorbisBitArray bitArray) throws ParserException {
if (bitArray.readBits(24) != 0x564342) { if (bitArray.readBits(24) != 0x564342) {
throw new ParserException("expected code book to start with [0x56, 0x43, 0x42] at " throw new ParserException("expected code book to start with [0x56, 0x43, 0x42] at "
+ bitArray.getPosition()); + bitArray.getPosition());
@ -393,7 +393,6 @@ import java.util.Arrays;
// discard (no decoding required yet) // discard (no decoding required yet)
bitArray.skipBits((int) (lookupValuesCount * valueBits)); bitArray.skipBits((int) (lookupValuesCount * valueBits));
} }
return new CodeBook(dimensions, entries, lengthMap, lookupType, isOrdered);
} }
/** /**
@ -403,25 +402,6 @@ import java.util.Arrays;
return (long) Math.floor(Math.pow(entries, 1.d / dimension)); return (long) Math.floor(Math.pow(entries, 1.d / dimension));
} }
public static final class CodeBook {
public final int dimensions;
public final int entries;
public final long[] lengthMap;
public final int lookupType;
public final boolean isOrdered;
public CodeBook(int dimensions, int entries, long[] lengthMap, int lookupType,
boolean isOrdered) {
this.dimensions = dimensions;
this.entries = entries;
this.lengthMap = lengthMap;
this.lookupType = lookupType;
this.isOrdered = isOrdered;
}
}
public static final class CommentHeader { public static final class CommentHeader {
public final String vendor; public final String vendor;

View file

@ -85,71 +85,69 @@ import java.util.Collections;
@Override @Override
public void consume(ParsableByteArray data) { public void consume(ParsableByteArray data) {
while (data.bytesLeft() > 0) { int offset = data.getPosition();
int offset = data.getPosition(); int limit = data.limit();
int limit = data.limit(); byte[] dataArray = data.data;
byte[] dataArray = data.data;
// Append the data to the buffer. // Append the data to the buffer.
totalBytesWritten += data.bytesLeft(); totalBytesWritten += data.bytesLeft();
output.sampleData(data, data.bytesLeft()); output.sampleData(data, data.bytesLeft());
int searchOffset = offset; int searchOffset = offset;
while (true) { while (true) {
int startCodeOffset = NalUnitUtil.findNalUnit(dataArray, searchOffset, limit, prefixFlags); int startCodeOffset = NalUnitUtil.findNalUnit(dataArray, searchOffset, limit, prefixFlags);
if (startCodeOffset == limit) {
// We've scanned to the end of the data without finding another start code.
if (!hasOutputFormat) {
csdBuffer.onData(dataArray, offset, limit);
}
return;
}
// We've found a start code with the following value.
int startCodeValue = data.data[startCodeOffset + 3] & 0xFF;
if (startCodeOffset == limit) {
// We've scanned to the end of the data without finding another start code.
if (!hasOutputFormat) { if (!hasOutputFormat) {
// This is the number of bytes from the current offset to the start of the next start csdBuffer.onData(dataArray, offset, limit);
// code. It may be negative if the start code started in the previously consumed data.
int lengthToStartCode = startCodeOffset - offset;
if (lengthToStartCode > 0) {
csdBuffer.onData(dataArray, offset, startCodeOffset);
}
// This is the number of bytes belonging to the next start code that have already been
// passed to csdDataTargetBuffer.
int bytesAlreadyPassed = lengthToStartCode < 0 ? -lengthToStartCode : 0;
if (csdBuffer.onStartCode(startCodeValue, bytesAlreadyPassed)) {
// The csd data is complete, so we can parse and output the media format.
Pair<Format, Long> result = parseCsdBuffer(csdBuffer);
output.format(result.first);
frameDurationUs = result.second;
hasOutputFormat = true;
}
} }
return;
if (hasOutputFormat && (startCodeValue == START_GROUP || startCodeValue == START_PICTURE)) {
int bytesWrittenPastStartCode = limit - startCodeOffset;
if (foundFirstFrameInGroup) {
int flags = isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (totalBytesWritten - framePosition) - bytesWrittenPastStartCode;
output.sampleMetadata(frameTimeUs, flags, size, bytesWrittenPastStartCode, null);
isKeyframe = false;
}
if (startCodeValue == START_GROUP) {
foundFirstFrameInGroup = false;
isKeyframe = true;
} else /* startCode == START_PICTURE */ {
frameTimeUs = pesPtsUsAvailable ? pesTimeUs : (frameTimeUs + frameDurationUs);
framePosition = totalBytesWritten - bytesWrittenPastStartCode;
pesPtsUsAvailable = false;
foundFirstFrameInGroup = true;
}
}
offset = startCodeOffset;
searchOffset = offset + 3;
} }
// We've found a start code with the following value.
int startCodeValue = data.data[startCodeOffset + 3] & 0xFF;
if (!hasOutputFormat) {
// This is the number of bytes from the current offset to the start of the next start
// code. It may be negative if the start code started in the previously consumed data.
int lengthToStartCode = startCodeOffset - offset;
if (lengthToStartCode > 0) {
csdBuffer.onData(dataArray, offset, startCodeOffset);
}
// This is the number of bytes belonging to the next start code that have already been
// passed to csdDataTargetBuffer.
int bytesAlreadyPassed = lengthToStartCode < 0 ? -lengthToStartCode : 0;
if (csdBuffer.onStartCode(startCodeValue, bytesAlreadyPassed)) {
// The csd data is complete, so we can parse and output the media format.
Pair<Format, Long> result = parseCsdBuffer(csdBuffer);
output.format(result.first);
frameDurationUs = result.second;
hasOutputFormat = true;
}
}
if (hasOutputFormat && (startCodeValue == START_GROUP || startCodeValue == START_PICTURE)) {
int bytesWrittenPastStartCode = limit - startCodeOffset;
if (foundFirstFrameInGroup) {
int flags = isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (totalBytesWritten - framePosition) - bytesWrittenPastStartCode;
output.sampleMetadata(frameTimeUs, flags, size, bytesWrittenPastStartCode, null);
isKeyframe = false;
}
if (startCodeValue == START_GROUP) {
foundFirstFrameInGroup = false;
isKeyframe = true;
} else /* startCode == START_PICTURE */ {
frameTimeUs = pesPtsUsAvailable ? pesTimeUs : (frameTimeUs + frameDurationUs);
framePosition = totalBytesWritten - bytesWrittenPastStartCode;
pesPtsUsAvailable = false;
foundFirstFrameInGroup = true;
}
}
offset = startCodeOffset;
searchOffset = offset + 3;
} }
} }

View file

@ -94,46 +94,44 @@ import java.util.List;
@Override @Override
public void consume(ParsableByteArray data) { public void consume(ParsableByteArray data) {
while (data.bytesLeft() > 0) { int offset = data.getPosition();
int offset = data.getPosition(); int limit = data.limit();
int limit = data.limit(); byte[] dataArray = data.data;
byte[] dataArray = data.data;
// Append the data to the buffer. // Append the data to the buffer.
totalBytesWritten += data.bytesLeft(); totalBytesWritten += data.bytesLeft();
output.sampleData(data, data.bytesLeft()); output.sampleData(data, data.bytesLeft());
// Scan the appended data, processing NAL units as they are encountered // Scan the appended data, processing NAL units as they are encountered
while (true) { while (true) {
int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags); int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);
if (nalUnitOffset == limit) { if (nalUnitOffset == limit) {
// We've scanned to the end of the data without finding the start of another NAL unit. // We've scanned to the end of the data without finding the start of another NAL unit.
nalUnitData(dataArray, offset, limit); nalUnitData(dataArray, offset, limit);
return; return;
}
// We've seen the start of a NAL unit of the following type.
int nalUnitType = NalUnitUtil.getNalUnitType(dataArray, nalUnitOffset);
// This is the number of bytes from the current offset to the start of the next NAL unit.
// It may be negative if the NAL unit started in the previously consumed data.
int lengthToNalUnit = nalUnitOffset - offset;
if (lengthToNalUnit > 0) {
nalUnitData(dataArray, offset, nalUnitOffset);
}
int bytesWrittenPastPosition = limit - nalUnitOffset;
long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
// Indicate the end of the previous NAL unit. If the length to the start of the next unit
// is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
// when notifying that the unit has ended.
endNalUnit(absolutePosition, bytesWrittenPastPosition,
lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
// Indicate the start of the next NAL unit.
startNalUnit(absolutePosition, nalUnitType, pesTimeUs);
// Continue scanning the data.
offset = nalUnitOffset + 3;
} }
// We've seen the start of a NAL unit of the following type.
int nalUnitType = NalUnitUtil.getNalUnitType(dataArray, nalUnitOffset);
// This is the number of bytes from the current offset to the start of the next NAL unit.
// It may be negative if the NAL unit started in the previously consumed data.
int lengthToNalUnit = nalUnitOffset - offset;
if (lengthToNalUnit > 0) {
nalUnitData(dataArray, offset, nalUnitOffset);
}
int bytesWrittenPastPosition = limit - nalUnitOffset;
long absolutePosition = totalBytesWritten - bytesWrittenPastPosition;
// Indicate the end of the previous NAL unit. If the length to the start of the next unit
// is negative then we wrote too many bytes to the NAL buffers. Discard the excess bytes
// when notifying that the unit has ended.
endNalUnit(absolutePosition, bytesWrittenPastPosition,
lengthToNalUnit < 0 ? -lengthToNalUnit : 0, pesTimeUs);
// Indicate the start of the next NAL unit.
startNalUnit(absolutePosition, nalUnitType, pesTimeUs);
// Continue scanning the data.
offset = nalUnitOffset + 3;
} }
} }

View file

@ -342,8 +342,8 @@ import java.util.Collections;
private static void skipShortTermRefPicSets(ParsableNalUnitBitArray bitArray) { private static void skipShortTermRefPicSets(ParsableNalUnitBitArray bitArray) {
int numShortTermRefPicSets = bitArray.readUnsignedExpGolombCodedInt(); int numShortTermRefPicSets = bitArray.readUnsignedExpGolombCodedInt();
boolean interRefPicSetPredictionFlag = false; boolean interRefPicSetPredictionFlag = false;
int numNegativePics = 0; int numNegativePics;
int numPositivePics = 0; int numPositivePics;
// As this method applies in a SPS, the only element of NumDeltaPocs accessed is the previous // As this method applies in a SPS, the only element of NumDeltaPocs accessed is the previous
// one, so we just keep track of that rather than storing the whole array. // one, so we just keep track of that rather than storing the whole array.
// RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1) and delta_idx_minus1 is always zero in SPS. // RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1) and delta_idx_minus1 is always zero in SPS.

View file

@ -216,7 +216,7 @@ public final class PsExtractor implements Extractor {
input.readFully(psPacketBuffer.data, 0, pesLength); input.readFully(psPacketBuffer.data, 0, pesLength);
psPacketBuffer.setPosition(6); psPacketBuffer.setPosition(6);
psPacketBuffer.setLimit(pesLength); psPacketBuffer.setLimit(pesLength);
payloadReader.consume(psPacketBuffer, output); payloadReader.consume(psPacketBuffer);
psPacketBuffer.setLimit(psPacketBuffer.capacity()); psPacketBuffer.setLimit(psPacketBuffer.capacity());
} }
@ -253,8 +253,8 @@ public final class PsExtractor implements Extractor {
* Notifies the reader that a seek has occurred. * Notifies the reader that a seek has occurred.
* <p> * <p>
* Following a call to this method, the data passed to the next invocation of * Following a call to this method, the data passed to the next invocation of
* {@link #consume(ParsableByteArray, ExtractorOutput)} will not be a continuation of * {@link #consume(ParsableByteArray)} will not be a continuation of the data that was
* the data that was previously passed. Hence the reader should reset any internal state. * previously passed. Hence the reader should reset any internal state.
*/ */
public void seek() { public void seek() {
seenFirstDts = false; seenFirstDts = false;
@ -265,9 +265,8 @@ public final class PsExtractor implements Extractor {
* Consumes the payload of a PS packet. * Consumes the payload of a PS packet.
* *
* @param data The PES packet. The position will be set to the start of the payload. * @param data The PES packet. The position will be set to the start of the payload.
* @param output The output to which parsed data should be written.
*/ */
public void consume(ParsableByteArray data, ExtractorOutput output) { public void consume(ParsableByteArray data) {
data.readBytes(pesScratch.data, 0, 3); data.readBytes(pesScratch.data, 0, 3);
pesScratch.setPosition(0); pesScratch.setPosition(0);
parseHeader(); parseHeader();

View file

@ -39,14 +39,13 @@ import java.io.IOException;
* Peeks and returns a {@code WavHeader}. * Peeks and returns a {@code WavHeader}.
* *
* @param input Input stream to peek the WAV header from. * @param input Input stream to peek the WAV header from.
* @throws ParserException If the input file is an incorrect RIFF WAV.
* @throws IOException If peeking from the input fails. * @throws IOException If peeking from the input fails.
* @throws InterruptedException If interrupted while peeking from input. * @throws InterruptedException If interrupted while peeking from input.
* @throws ParserException If the input file is an incorrect RIFF WAV.
* @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a * @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a
* supported WAV format. * supported WAV format.
*/ */
public static WavHeader peek(ExtractorInput input) public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException {
throws IOException, InterruptedException, ParserException {
Assertions.checkNotNull(input); Assertions.checkNotNull(input);
// Allocate a scratch buffer large enough to store the format chunk. // Allocate a scratch buffer large enough to store the format chunk.
@ -117,12 +116,12 @@ import java.io.IOException;
* @param input Input stream to skip to the data chunk in. Its peek position must be pointing to * @param input Input stream to skip to the data chunk in. Its peek position must be pointing to
* a valid chunk header. * a valid chunk header.
* @param wavHeader WAV header to populate with data bounds. * @param wavHeader WAV header to populate with data bounds.
* @throws ParserException If an error occurs parsing chunks.
* @throws IOException If reading from the input fails. * @throws IOException If reading from the input fails.
* @throws InterruptedException If interrupted while reading from input. * @throws InterruptedException If interrupted while reading from input.
* @throws ParserException If an error occurs parsing chunks.
*/ */
public static void skipToData(ExtractorInput input, WavHeader wavHeader) public static void skipToData(ExtractorInput input, WavHeader wavHeader)
throws IOException, InterruptedException, ParserException { throws IOException, InterruptedException {
Assertions.checkNotNull(input); Assertions.checkNotNull(input);
Assertions.checkNotNull(wavHeader); Assertions.checkNotNull(wavHeader);

View file

@ -68,9 +68,7 @@ import javax.crypto.spec.SecretKeySpec;
Cipher cipher; Cipher cipher;
try { try {
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -79,9 +77,7 @@ import javax.crypto.spec.SecretKeySpec;
try { try {
cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherIV); cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherIV);
} catch (InvalidKeyException e) { } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -663,8 +663,8 @@ public class HlsChunkSource {
} }
private boolean allEnabledVariantsBlacklisted() { private boolean allEnabledVariantsBlacklisted() {
for (int i = 0; i < enabledVariantBlacklistFlags.length; i++) { for (boolean enabledVariantBlacklistFlag : enabledVariantBlacklistFlags) {
if (!enabledVariantBlacklistFlags[i]) { if (!enabledVariantBlacklistFlag) {
return false; return false;
} }
} }

View file

@ -60,7 +60,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
private final Loader loader; private final Loader loader;
private final HlsChunkSource chunkSource; private final HlsChunkSource chunkSource;
private final LinkedList<HlsMediaChunk> mediaChunks = new LinkedList<HlsMediaChunk>(); private final LinkedList<HlsMediaChunk> mediaChunks = new LinkedList<>();
private final HlsOutput output; private final HlsOutput output;
private final int bufferSizeContribution; private final int bufferSizeContribution;
private final ChunkHolder nextChunkHolder; private final ChunkHolder nextChunkHolder;
@ -262,13 +262,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
/* package */ boolean isReady(int group) { /* package */ boolean isReady(int group) {
Assertions.checkState(groupEnabledStates[group]); Assertions.checkState(groupEnabledStates[group]);
if (loadingFinished) { return loadingFinished || (!isPendingReset() && !sampleQueues[group].isEmpty());
return true;
}
if (isPendingReset()) {
return false;
}
return !sampleQueues[group].isEmpty();
} }
/* package */ void maybeThrowError() throws IOException { /* package */ void maybeThrowError() throws IOException {

View file

@ -25,9 +25,6 @@ import java.util.regex.Pattern;
*/ */
/* package */ final class HlsParserUtil { /* package */ final class HlsParserUtil {
private static final String BOOLEAN_YES = "YES";
private static final String BOOLEAN_NO = "NO";
private HlsParserUtil() {} private HlsParserUtil() {}
public static String parseStringAttr(String line, Pattern pattern, String tag) public static String parseStringAttr(String line, Pattern pattern, String tag)
@ -57,16 +54,4 @@ import java.util.regex.Pattern;
return null; return null;
} }
public static boolean parseOptionalBooleanAttr(String line, Pattern pattern) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
return BOOLEAN_YES.equals(matcher.group(1));
}
return false;
}
public static Pattern compileBooleanAttrPattern(String attrName) {
return Pattern.compile(attrName + "=(" + BOOLEAN_YES + "|" + BOOLEAN_NO + ")");
}
} }

View file

@ -109,7 +109,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
// HlsParserUtil.compileBooleanAttrPattern(DEFAULT_ATTR); // HlsParserUtil.compileBooleanAttrPattern(DEFAULT_ATTR);
@Override @Override
public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException, ParserException { public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
Queue<String> extraLines = new LinkedList<>(); Queue<String> extraLines = new LinkedList<>();
String line; String line;

View file

@ -30,7 +30,7 @@ public interface MetadataParser<T> {
* @param mimeType A metadata mime type. * @param mimeType A metadata mime type.
* @return Whether the mime type is supported. * @return Whether the mime type is supported.
*/ */
public boolean canParse(String mimeType); boolean canParse(String mimeType);
/** /**
* Parses metadata objects of type <T> from the provided binary data. * Parses metadata objects of type <T> from the provided binary data.
@ -40,6 +40,6 @@ public interface MetadataParser<T> {
* @return @return A parsed metadata object of type <T>. * @return @return A parsed metadata object of type <T>.
* @throws IOException If a problem occurred parsing the data. * @throws IOException If a problem occurred parsing the data.
*/ */
public T parse(byte[] data, int size) throws IOException; T parse(byte[] data, int size) throws IOException;
} }

View file

@ -266,10 +266,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
int manifestTrackIndex = getManifestTrackIndex(streamElement, selectedFormat); int manifestTrackIndex = getManifestTrackIndex(streamElement, selectedFormat);
Uri uri = streamElement.buildRequestUri(manifestTrackIndex, chunkIndex); Uri uri = streamElement.buildRequestUri(manifestTrackIndex, chunkIndex);
Chunk mediaChunk = newMediaChunk(selectedFormat, dataSource, uri, null, out.chunk = newMediaChunk(selectedFormat, dataSource, uri, null, currentAbsoluteChunkIndex,
currentAbsoluteChunkIndex, chunkStartTimeUs, chunkEndTimeUs, evaluation.trigger, chunkStartTimeUs, chunkEndTimeUs, evaluation.trigger, extractorWrapper, drmInitData,
extractorWrapper, drmInitData, selectedFormat); selectedFormat);
out.chunk = mediaChunk;
} }
@Override @Override

View file

@ -63,8 +63,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
} }
@Override @Override
public SmoothStreamingManifest parse(Uri uri, InputStream inputStream) public SmoothStreamingManifest parse(Uri uri, InputStream inputStream) throws IOException {
throws IOException, ParserException {
try { try {
XmlPullParser xmlParser = xmlParserFactory.newPullParser(); XmlPullParser xmlParser = xmlParserFactory.newPullParser();
xmlParser.setInput(inputStream, null); xmlParser.setInput(inputStream, null);
@ -105,8 +104,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
this.normalizedAttributes = new LinkedList<>(); this.normalizedAttributes = new LinkedList<>();
} }
public final Object parse(XmlPullParser xmlParser) throws XmlPullParserException, IOException, public final Object parse(XmlPullParser xmlParser) throws XmlPullParserException, IOException {
ParserException {
String tagName; String tagName;
boolean foundStartTag = false; boolean foundStartTag = false;
int skippingElementDepth = 0; int skippingElementDepth = 0;
@ -224,17 +222,15 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
/** /**
* @param xmlParser The underlying {@link XmlPullParser} * @param xmlParser The underlying {@link XmlPullParser}
* @throws ParserException
*/ */
protected void parseText(XmlPullParser xmlParser) throws ParserException { protected void parseText(XmlPullParser xmlParser) {
// Do nothing. // Do nothing.
} }
/** /**
* @param xmlParser The underlying {@link XmlPullParser} * @param xmlParser The underlying {@link XmlPullParser}
* @throws ParserException
*/ */
protected void parseEndTag(XmlPullParser xmlParser) throws ParserException { protected void parseEndTag(XmlPullParser xmlParser) {
// Do nothing. // Do nothing.
} }
@ -335,6 +331,8 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
private static final String KEY_LOOKAHEAD_COUNT = "LookaheadCount"; private static final String KEY_LOOKAHEAD_COUNT = "LookaheadCount";
private static final String KEY_IS_LIVE = "IsLive"; private static final String KEY_IS_LIVE = "IsLive";
private final List<StreamElement> streamElements;
private int majorVersion; private int majorVersion;
private int minorVersion; private int minorVersion;
private long timescale; private long timescale;
@ -343,7 +341,6 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
private int lookAheadCount; private int lookAheadCount;
private boolean isLive; private boolean isLive;
private ProtectionElement protectionElement; private ProtectionElement protectionElement;
private List<StreamElement> streamElements;
public SmoothStreamMediaParser(ElementParser parent, String baseUri) { public SmoothStreamMediaParser(ElementParser parent, String baseUri) {
super(parent, baseUri, TAG); super(parent, baseUri, TAG);

View file

@ -233,7 +233,6 @@ import android.util.Log;
} }
int textTop; int textTop;
int textBottom;
if (cueLine != Cue.DIMEN_UNSET) { if (cueLine != Cue.DIMEN_UNSET) {
int anchorPosition; int anchorPosition;
if (cueLineType == Cue.LINE_TYPE_FRACTION) { if (cueLineType == Cue.LINE_TYPE_FRACTION) {
@ -250,17 +249,13 @@ import android.util.Log;
textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight
: cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2 : cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2
: anchorPosition; : anchorPosition;
textBottom = textTop + textHeight; if (textTop + textHeight > parentBottom) {
if (textBottom > parentBottom) {
textTop = parentBottom - textHeight; textTop = parentBottom - textHeight;
textBottom = parentBottom;
} else if (textTop < parentTop) { } else if (textTop < parentTop) {
textTop = parentTop; textTop = parentTop;
textBottom = parentTop + textHeight;
} }
} else { } else {
textTop = parentBottom - textHeight - (int) (parentHeight * bottomPaddingFraction); textTop = parentBottom - textHeight - (int) (parentHeight * bottomPaddingFraction);
textBottom = textTop + textHeight;
} }
textWidth = textRight - textLeft; textWidth = textRight - textLeft;

View file

@ -28,7 +28,7 @@ public interface Subtitle {
* @param timeUs The time in microseconds. * @param timeUs The time in microseconds.
* @return The index of the next event, or -1 if there are no events after the specified time. * @return The index of the next event, or -1 if there are no events after the specified time.
*/ */
public int getNextEventTimeIndex(long timeUs); int getNextEventTimeIndex(long timeUs);
/** /**
* Gets the number of event times, where events are defined as points in time at which the cues * Gets the number of event times, where events are defined as points in time at which the cues
@ -36,7 +36,7 @@ public interface Subtitle {
* *
* @return The number of event times. * @return The number of event times.
*/ */
public int getEventTimeCount(); int getEventTimeCount();
/** /**
* Gets the event time at a specified index. * Gets the event time at a specified index.
@ -44,14 +44,7 @@ public interface Subtitle {
* @param index The index of the event time to obtain. * @param index The index of the event time to obtain.
* @return The event time in microseconds. * @return The event time in microseconds.
*/ */
public long getEventTime(int index); long getEventTime(int index);
/**
* Convenience method for obtaining the last event time.
*
* @return The time of the last event in microseconds, or -1 if {@code getEventTimeCount() == 0}.
*/
public long getLastEventTime();
/** /**
* Retrieve the subtitle cues that should be displayed at a given time. * Retrieve the subtitle cues that should be displayed at a given time.
@ -59,6 +52,6 @@ public interface Subtitle {
* @param timeUs The time in microseconds. * @param timeUs The time in microseconds.
* @return A list of cues that should be displayed, possibly empty. * @return A list of cues that should be displayed, possibly empty.
*/ */
public List<Cue> getCues(long timeUs); List<Cue> getCues(long timeUs);
} }

View file

@ -51,11 +51,6 @@ import java.util.List;
return subtitle.getEventTime(index) + offsetUs; return subtitle.getEventTime(index) + offsetUs;
} }
@Override
public long getLastEventTime() {
return subtitle.getLastEventTime() + offsetUs;
}
@Override @Override
public int getNextEventTimeIndex(long timeUs) { public int getNextEventTimeIndex(long timeUs) {
return subtitle.getNextEventTimeIndex(timeUs - offsetUs); return subtitle.getNextEventTimeIndex(timeUs - offsetUs);

View file

@ -53,7 +53,7 @@ public interface SubtitleParserFactory {
* <li>TX3G ({@link com.google.android.exoplayer.text.tx3g.Tx3gParser})</li> * <li>TX3G ({@link com.google.android.exoplayer.text.tx3g.Tx3gParser})</li>
* </ul> * </ul>
*/ */
final SubtitleParserFactory DEFAULT = new SubtitleParserFactory() { SubtitleParserFactory DEFAULT = new SubtitleParserFactory() {
@Override @Override
public boolean supportsFormat(Format format) { public boolean supportsFormat(Format format) {
@ -68,7 +68,7 @@ public interface SubtitleParserFactory {
throw new IllegalArgumentException("Attempted to create parser for unsupported format"); throw new IllegalArgumentException("Attempted to create parser for unsupported format");
} }
return clazz.asSubclass(SubtitleParser.class).newInstance(); return clazz.asSubclass(SubtitleParser.class).newInstance();
} catch (InstantiationException | IllegalAccessException e) { } catch (Exception e) {
throw new IllegalStateException("Unexpected error instantiating parser", e); throw new IllegalStateException("Unexpected error instantiating parser", e);
} }
} }

View file

@ -140,11 +140,10 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback {
} }
boolean textRendererNeedsUpdate = false; boolean textRendererNeedsUpdate = false;
long subtitleNextEventTimeUs = Long.MAX_VALUE;
if (subtitle != null) { if (subtitle != null) {
// We're iterating through the events in a subtitle. Set textRendererNeedsUpdate if we // We're iterating through the events in a subtitle. Set textRendererNeedsUpdate if we
// advance to the next event. // advance to the next event.
subtitleNextEventTimeUs = getNextEventTime(); long subtitleNextEventTimeUs = getNextEventTime();
while (subtitleNextEventTimeUs <= positionUs) { while (subtitleNextEventTimeUs <= positionUs) {
nextSubtitleEventIndex++; nextSubtitleEventIndex++;
subtitleNextEventTimeUs = getNextEventTime(); subtitleNextEventTimeUs = getNextEventTime();

View file

@ -18,38 +18,36 @@ package com.google.android.exoplayer.text.eia608;
/* package */ final class ClosedCaptionCtrl extends ClosedCaption { /* package */ final class ClosedCaptionCtrl extends ClosedCaption {
/** /**
* The receipt of the {@link #RESUME_CAPTION_LOADING} command initiates pop-on style captioning. * Command initiating pop-on style captioning. Subsequent data should be loaded into a
* Subsequent data should be loaded into a non-displayed memory and held there until the * non-displayed memory and held there until the {@link #END_OF_CAPTION} command is received, at
* {@link #END_OF_CAPTION} command is received, at which point the non-displayed memory becomes * which point the non-displayed memory becomes the displayed memory (and vice versa).
* the displayed memory (and vice versa).
*/ */
public static final byte RESUME_CAPTION_LOADING = 0x20; public static final byte RESUME_CAPTION_LOADING = 0x20;
/** /**
* The receipt of the {@link #ROLL_UP_CAPTIONS_2_ROWS} command initiates roll-up style * Command initiating roll-up style captioning, with the maximum of 2 rows displayed
* captioning, with the maximum of 2 rows displayed simultaneously. * simultaneously.
*/ */
public static final byte ROLL_UP_CAPTIONS_2_ROWS = 0x25; public static final byte ROLL_UP_CAPTIONS_2_ROWS = 0x25;
/** /**
* The receipt of the {@link #ROLL_UP_CAPTIONS_3_ROWS} command initiates roll-up style * Command initiating roll-up style captioning, with the maximum of 3 rows displayed
* captioning, with the maximum of 3 rows displayed simultaneously. * simultaneously.
*/ */
public static final byte ROLL_UP_CAPTIONS_3_ROWS = 0x26; public static final byte ROLL_UP_CAPTIONS_3_ROWS = 0x26;
/** /**
* The receipt of the {@link #ROLL_UP_CAPTIONS_4_ROWS} command initiates roll-up style * Command initiating roll-up style captioning, with the maximum of 4 rows displayed
* captioning, with the maximum of 4 rows displayed simultaneously. * simultaneously.
*/ */
public static final byte ROLL_UP_CAPTIONS_4_ROWS = 0x27; public static final byte ROLL_UP_CAPTIONS_4_ROWS = 0x27;
/** /**
* The receipt of the {@link #RESUME_DIRECT_CAPTIONING} command initiates paint-on style * Command initiating paint-on style captioning. Subsequent data should be addressed immediately
* captioning. Subsequent data should be addressed immediately to displayed memory without need * to displayed memory without need for the {@link #RESUME_CAPTION_LOADING} command.
* for the {@link #RESUME_CAPTION_LOADING} command.
*/ */
public static final byte RESUME_DIRECT_CAPTIONING = 0x29; public static final byte RESUME_DIRECT_CAPTIONING = 0x29;
/** /**
* The receipt of the {@link #END_OF_CAPTION} command indicates the end of pop-on style caption, * Command indicating the end of a pop-on style caption. At this point the caption loaded in
* at this point already loaded in non-displayed memory caption should become the displayed * non-displayed memory should be swapped with the one in displayed memory. If no
* memory (and vice versa). If no {@link #RESUME_CAPTION_LOADING} command has been received, * {@link #RESUME_CAPTION_LOADING} command has been received, this command forces the receiver
* {@link #END_OF_CAPTION} command forces the receiver into pop-on style. * into pop-on style.
*/ */
public static final byte END_OF_CAPTION = 0x2F; public static final byte END_OF_CAPTION = 0x2F;

View file

@ -58,20 +58,12 @@ import java.util.List;
return cueTimesUs[index]; return cueTimesUs[index];
} }
@Override
public long getLastEventTime() {
if (getEventTimeCount() == 0) {
return -1;
}
return cueTimesUs[cueTimesUs.length - 1];
}
@Override @Override
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
int index = Util.binarySearchFloor(cueTimesUs, timeUs, true, false); int index = Util.binarySearchFloor(cueTimesUs, timeUs, true, false);
if (index == -1 || cues[index] == null) { if (index == -1 || cues[index] == null) {
// timeUs is earlier than the start of the first cue, or we have an empty cue. // timeUs is earlier than the start of the first cue, or we have an empty cue.
return Collections.<Cue>emptyList(); return Collections.emptyList();
} else { } else {
return Collections.singletonList(cues[index]); return Collections.singletonList(cues[index]);
} }

View file

@ -74,7 +74,7 @@ import java.util.TreeSet;
public final long startTimeUs; public final long startTimeUs;
public final long endTimeUs; public final long endTimeUs;
public final TtmlStyle style; public final TtmlStyle style;
private String[] styleIds; private final String[] styleIds;
private List<TtmlNode> children; private List<TtmlNode> children;
private int start; private int start;

View file

@ -280,23 +280,29 @@ public final class TtmlParser extends SubtitleParser {
for (int i = 0; i < attributeCount; i++) { for (int i = 0; i < attributeCount; i++) {
String attr = ParserUtil.removeNamespacePrefix(parser.getAttributeName(i)); String attr = ParserUtil.removeNamespacePrefix(parser.getAttributeName(i));
String value = parser.getAttributeValue(i); String value = parser.getAttributeValue(i);
if (attr.equals(ATTR_BEGIN)) { switch (attr) {
startTime = parseTimeExpression(value, case ATTR_BEGIN:
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE); startTime = parseTimeExpression(value,
} else if (attr.equals(ATTR_END)) { DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
endTime = parseTimeExpression(value, break;
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE); case ATTR_END:
} else if (attr.equals(ATTR_DURATION)) { endTime = parseTimeExpression(value,
duration = parseTimeExpression(value, DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE); break;
} else if (attr.equals(ATTR_STYLE)) { case ATTR_DURATION:
// IDREFS: potentially multiple space delimited ids duration = parseTimeExpression(value,
String[] ids = parseStyleIds(value); DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
if (ids.length > 0) { break;
styleIds = ids; case ATTR_STYLE:
} // IDREFS: potentially multiple space delimited ids
} else { String[] ids = parseStyleIds(value);
// Do nothing. if (ids.length > 0) {
styleIds = ids;
}
break;
default:
// Do nothing.
break;
} }
} }
if (parent != null && parent.startTimeUs != TtmlNode.UNDEFINED_TIME) { if (parent != null && parent.startTimeUs != TtmlNode.UNDEFINED_TIME) {
@ -320,7 +326,7 @@ public final class TtmlParser extends SubtitleParser {
} }
private static boolean isSupportedTag(String tag) { private static boolean isSupportedTag(String tag) {
if (tag.equals(TtmlNode.TAG_TT) return tag.equals(TtmlNode.TAG_TT)
|| tag.equals(TtmlNode.TAG_HEAD) || tag.equals(TtmlNode.TAG_HEAD)
|| tag.equals(TtmlNode.TAG_BODY) || tag.equals(TtmlNode.TAG_BODY)
|| tag.equals(TtmlNode.TAG_DIV) || tag.equals(TtmlNode.TAG_DIV)
@ -334,10 +340,7 @@ public final class TtmlParser extends SubtitleParser {
|| tag.equals(TtmlNode.TAG_METADATA) || tag.equals(TtmlNode.TAG_METADATA)
|| tag.equals(TtmlNode.TAG_SMPTE_IMAGE) || tag.equals(TtmlNode.TAG_SMPTE_IMAGE)
|| tag.equals(TtmlNode.TAG_SMPTE_DATA) || tag.equals(TtmlNode.TAG_SMPTE_DATA)
|| tag.equals(TtmlNode.TAG_SMPTE_INFORMATION)) { || tag.equals(TtmlNode.TAG_SMPTE_INFORMATION);
return true;
}
return false;
} }
private static void parseFontSize(String expression, TtmlStyle out) throws ParserException { private static void parseFontSize(String expression, TtmlStyle out) throws ParserException {
@ -411,18 +414,25 @@ public final class TtmlParser extends SubtitleParser {
String timeValue = matcher.group(1); String timeValue = matcher.group(1);
double offsetSeconds = Double.parseDouble(timeValue); double offsetSeconds = Double.parseDouble(timeValue);
String unit = matcher.group(2); String unit = matcher.group(2);
if (unit.equals("h")) { switch (unit) {
offsetSeconds *= 3600; case "h":
} else if (unit.equals("m")) { offsetSeconds *= 3600;
offsetSeconds *= 60; break;
} else if (unit.equals("s")) { case "m":
// Do nothing. offsetSeconds *= 60;
} else if (unit.equals("ms")) { break;
offsetSeconds /= 1000; case "s":
} else if (unit.equals("f")) { // Do nothing.
offsetSeconds /= frameRate; break;
} else if (unit.equals("t")) { case "ms":
offsetSeconds /= tickRate; offsetSeconds /= 1000;
break;
case "f":
offsetSeconds /= frameRate;
break;
case "t":
offsetSeconds /= tickRate;
break;
} }
return (long) (offsetSeconds * C.MICROS_PER_SECOND); return (long) (offsetSeconds * C.MICROS_PER_SECOND);
} }

View file

@ -55,11 +55,6 @@ public final class TtmlSubtitle implements Subtitle {
return eventTimesUs[index]; return eventTimesUs[index];
} }
@Override
public long getLastEventTime() {
return (eventTimesUs.length == 0 ? -1 : eventTimesUs[eventTimesUs.length - 1]);
}
/* @VisibleForTesting */ /* @VisibleForTesting */
/* package */ TtmlNode getRoot() { /* package */ TtmlNode getRoot() {
return root; return root;
@ -69,7 +64,7 @@ public final class TtmlSubtitle implements Subtitle {
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
CharSequence cueText = root.getText(timeUs, globalStyles); CharSequence cueText = root.getText(timeUs, globalStyles);
if (cueText == null) { if (cueText == null) {
return Collections.<Cue>emptyList(); return Collections.emptyList();
} else { } else {
Cue cue = new Cue(cueText); Cue cue = new Cue(cueText);
return Collections.singletonList(cue); return Collections.singletonList(cue);

View file

@ -49,11 +49,6 @@ import java.util.List;
return 0; return 0;
} }
@Override
public long getLastEventTime() {
return 0;
}
@Override @Override
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
return timeUs >= 0 ? cues : Collections.<Cue>emptyList(); return timeUs >= 0 ? cues : Collections.<Cue>emptyList();

View file

@ -286,10 +286,6 @@ import java.util.Map;
return false; return false;
} }
boolean commentEndsInPosition(byte[] data, int pos) {
return data[pos] == '/' && data[pos - 1] == '*';
}
private static String parseIdentifier(ParsableByteArray input, StringBuilder stringBuilder) { private static String parseIdentifier(ParsableByteArray input, StringBuilder stringBuilder) {
stringBuilder.setLength(0); stringBuilder.setLength(0);
int position = input.getPosition(); int position = input.getPosition();

View file

@ -49,11 +49,6 @@ import java.util.List;
return 0; return 0;
} }
@Override
public long getLastEventTime() {
return 0;
}
@Override @Override
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
return timeUs >= 0 ? cues : Collections.<Cue>emptyList(); return timeUs >= 0 ? cues : Collections.<Cue>emptyList();

View file

@ -72,14 +72,6 @@ public final class WebvttSubtitle implements Subtitle {
return sortedCueTimesUs[index]; return sortedCueTimesUs[index];
} }
@Override
public long getLastEventTime() {
if (getEventTimeCount() == 0) {
return -1;
}
return sortedCueTimesUs[sortedCueTimesUs.length - 1];
}
@Override @Override
public List<Cue> getCues(long timeUs) { public List<Cue> getCues(long timeUs) {
ArrayList<Cue> list = null; ArrayList<Cue> list = null;
@ -120,7 +112,7 @@ public final class WebvttSubtitle implements Subtitle {
if (list != null) { if (list != null) {
return list; return list;
} else { } else {
return Collections.<Cue>emptyList(); return Collections.emptyList();
} }
} }

View file

@ -110,7 +110,7 @@ public final class AssetDataSource implements DataSource {
if (bytesRemaining == 0) { if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} else { } else {
int bytesRead = 0; int bytesRead;
try { try {
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
: (int) Math.min(bytesRemaining, readLength); : (int) Math.min(bytesRemaining, readLength);

View file

@ -23,7 +23,7 @@ public interface BandwidthMeter extends TransferListener {
/** /**
* Interface definition for a callback to be notified of {@link BandwidthMeter} events. * Interface definition for a callback to be notified of {@link BandwidthMeter} events.
*/ */
public interface EventListener { interface EventListener {
/** /**
* Invoked periodically to indicate that bytes have been transferred. * Invoked periodically to indicate that bytes have been transferred.
@ -40,7 +40,7 @@ public interface BandwidthMeter extends TransferListener {
/** /**
* Indicates no bandwidth estimate is available. * Indicates no bandwidth estimate is available.
*/ */
final long NO_ESTIMATE = -1; long NO_ESTIMATE = -1;
/** /**
* Gets the estimated bandwidth, in bits/sec. * Gets the estimated bandwidth, in bits/sec.

View file

@ -108,7 +108,7 @@ public final class ContentDataSource implements DataSource {
if (bytesRemaining == 0) { if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} else { } else {
int bytesRead = 0; int bytesRead;
try { try {
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
: (int) Math.min(bytesRemaining, readLength); : (int) Math.min(bytesRemaining, readLength);

View file

@ -23,21 +23,20 @@ import java.io.IOException;
public interface DataSink { public interface DataSink {
/** /**
* Opens the {@link DataSink} to consume the specified data. Calls to {@link #open(DataSpec)} and * Opens the {@link DataSink} to consume the specified data.
* {@link #close()} must be balanced.
* *
* @param dataSpec Defines the data to be consumed. * @param dataSpec Defines the data to be consumed.
* @return This {@link DataSink}, for convenience. * @return This {@link DataSink}, for convenience.
* @throws IOException * @throws IOException
*/ */
public DataSink open(DataSpec dataSpec) throws IOException; DataSink open(DataSpec dataSpec) throws IOException;
/** /**
* Closes the {@link DataSink}. * Closes the {@link DataSink}.
* *
* @throws IOException * @throws IOException
*/ */
public void close() throws IOException; void close() throws IOException;
/** /**
* Consumes the provided data. * Consumes the provided data.
@ -47,6 +46,6 @@ public interface DataSink {
* @param length The length of the data to consume, in bytes. * @param length The length of the data to consume, in bytes.
* @throws IOException * @throws IOException
*/ */
public void write(byte[] buffer, int offset, int length) throws IOException; void write(byte[] buffer, int offset, int length) throws IOException;
} }

View file

@ -27,13 +27,11 @@ import java.io.IOException;
public interface DataSource { public interface DataSource {
/** /**
* Opens the {@link DataSource} to read the specified data. Calls to {@link #open(DataSpec)} and * Opens the {@link DataSource} to read the specified data.
* {@link #close()} must be balanced.
* <p> * <p>
* Note: If {@link #open(DataSpec)} throws an {@link IOException}, callers must still call * Note: If an {@link IOException} is thrown, callers must still call {@link #close()} to ensure
* {@link #close()} to ensure that any partial effects of the {@link #open(DataSpec)} invocation * that any partial effects of the invocation are cleaned up. Implementations of this class can
* are cleaned up. Implementations of this class can assume that callers will call * assume that callers will call {@link #close()} in this case.
* {@link #close()} in this case.
* *
* @param dataSpec Defines the data to be read. * @param dataSpec Defines the data to be read.
* @throws IOException If an error occurs opening the source. * @throws IOException If an error occurs opening the source.

View file

@ -339,9 +339,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
if (!allowCrossProtocolRedirects) { if (!allowCrossProtocolRedirects) {
// HttpURLConnection disallows cross-protocol redirects, but otherwise performs redirection // HttpURLConnection disallows cross-protocol redirects, but otherwise performs redirection
// automatically. This is the behavior we want, so use it. // automatically. This is the behavior we want, so use it.
HttpURLConnection connection = makeConnection( return makeConnection(url, postBody, position, length, allowGzip, true /* followRedirects */);
url, postBody, position, length, allowGzip, true /* followRedirects */);
return connection;
} }
// We need to handle redirects ourselves to allow cross-protocol redirects. // We need to handle redirects ourselves to allow cross-protocol redirects.

View file

@ -90,7 +90,7 @@ public final class FileDataSource implements DataSource {
if (bytesRemaining == 0) { if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} else { } else {
int bytesRead = 0; int bytesRead;
try { try {
bytesRead = file.read(buffer, offset, (int) Math.min(bytesRemaining, readLength)); bytesRead = file.read(buffer, offset, (int) Math.min(bytesRemaining, readLength));
} catch (IOException e) { } catch (IOException e) {

View file

@ -32,7 +32,7 @@ public interface HttpDataSource extends DataSource {
/** /**
* A {@link Predicate} that rejects content types often used for pay-walls. * A {@link Predicate} that rejects content types often used for pay-walls.
*/ */
public static final Predicate<String> REJECT_PAYWALL_TYPES = new Predicate<String>() { Predicate<String> REJECT_PAYWALL_TYPES = new Predicate<String>() {
@Override @Override
public boolean evaluate(String contentType) { public boolean evaluate(String contentType) {
@ -47,7 +47,7 @@ public interface HttpDataSource extends DataSource {
/** /**
* Thrown when an error is encountered when trying to read from a {@link HttpDataSource}. * Thrown when an error is encountered when trying to read from a {@link HttpDataSource}.
*/ */
public static class HttpDataSourceException extends IOException { class HttpDataSourceException extends IOException {
/* /*
* The {@link DataSpec} associated with the current connection. * The {@link DataSpec} associated with the current connection.
@ -79,7 +79,7 @@ public interface HttpDataSource extends DataSource {
/** /**
* Thrown when the content type is invalid. * Thrown when the content type is invalid.
*/ */
public static final class InvalidContentTypeException extends HttpDataSourceException { final class InvalidContentTypeException extends HttpDataSourceException {
public final String contentType; public final String contentType;
@ -93,7 +93,7 @@ public interface HttpDataSource extends DataSource {
/** /**
* Thrown when an attempt to open a connection results in a response code not in the 2xx range. * Thrown when an attempt to open a connection results in a response code not in the 2xx range.
*/ */
public static final class InvalidResponseCodeException extends HttpDataSourceException { final class InvalidResponseCodeException extends HttpDataSourceException {
/** /**
* The response code that was outside of the 2xx range. * The response code that was outside of the 2xx range.

View file

@ -37,10 +37,6 @@ public final class UdpDataSource implements DataSource {
*/ */
public static final class UdpDataSourceException extends IOException { public static final class UdpDataSourceException extends IOException {
public UdpDataSourceException(String message) {
super(message);
}
public UdpDataSourceException(IOException cause) { public UdpDataSourceException(IOException cause) {
super(cause); super(cause);
} }
@ -58,8 +54,9 @@ public final class UdpDataSource implements DataSource {
public static final int DEAFULT_SOCKET_TIMEOUT_MILLIS = 8 * 1000; public static final int DEAFULT_SOCKET_TIMEOUT_MILLIS = 8 * 1000;
private final TransferListener listener; private final TransferListener listener;
private final DatagramPacket packet;
private final int socketTimeoutMillis; private final int socketTimeoutMillis;
private final byte[] packetBuffer;
private final DatagramPacket packet;
private Uri uri; private Uri uri;
private DatagramSocket socket; private DatagramSocket socket;
@ -68,7 +65,6 @@ public final class UdpDataSource implements DataSource {
private InetSocketAddress socketAddress; private InetSocketAddress socketAddress;
private boolean opened; private boolean opened;
private byte[] packetBuffer;
private int packetRemaining; private int packetRemaining;
/** /**

View file

@ -44,7 +44,7 @@ public final class UriLoadable<T> implements Loadable {
* @throws ParserException If an error occurs parsing the data. * @throws ParserException If an error occurs parsing the data.
* @throws IOException If an error occurs reading data from the stream. * @throws IOException If an error occurs reading data from the stream.
*/ */
T parse(Uri uri, InputStream inputStream) throws ParserException, IOException; T parse(Uri uri, InputStream inputStream) throws IOException;
} }

View file

@ -27,7 +27,7 @@ public interface Cache {
/** /**
* Interface definition for a callback to be notified of {@link Cache} events. * Interface definition for a callback to be notified of {@link Cache} events.
*/ */
public interface Listener { interface Listener {
/** /**
* Invoked when a {@link CacheSpan} is added to the cache. * Invoked when a {@link CacheSpan} is added to the cache.

View file

@ -359,9 +359,7 @@ public final class SimpleCache implements Cache {
// floorSpan covers the queried region. // floorSpan covers the queried region.
return true; return true;
} }
Iterator<CacheSpan> iterator = entries.tailSet(floorSpan, false).iterator(); for (CacheSpan next : entries.tailSet(floorSpan, false)) {
while (iterator.hasNext()) {
CacheSpan next = iterator.next();
if (next.position > currentEndPosition) { if (next.position > currentEndPosition) {
// There's a hole in the cache within the queried region. // There's a hole in the cache within the queried region.
return false; return false;

View file

@ -67,8 +67,6 @@ public final class CodecSpecificDataUtil {
AUDIO_SPECIFIC_CONFIG_CHANNEL_CONFIGURATION_INVALID AUDIO_SPECIFIC_CONFIG_CHANNEL_CONFIGURATION_INVALID
}; };
// Advanced Audio Coding Low-Complexity profile.
private static final int AUDIO_OBJECT_TYPE_AAC_LC = 2;
// Spectral Band Replication. // Spectral Band Replication.
private static final int AUDIO_OBJECT_TYPE_SBR = 5; private static final int AUDIO_OBJECT_TYPE_SBR = 5;
// Error Resilient Bit-Sliced Arithmetic Coding. // Error Resilient Bit-Sliced Arithmetic Coding.
@ -136,33 +134,6 @@ public final class CodecSpecificDataUtil {
return audioSpecificConfig; return audioSpecificConfig;
} }
/**
* Builds a simple HE-AAC LC AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1
*
* @param sampleRate The sample rate in Hz.
* @param numChannels The number of channels.
* @return The AudioSpecificConfig.
*/
public static byte[] buildAacAudioSpecificConfig(int sampleRate, int numChannels) {
int sampleRateIndex = -1;
for (int i = 0; i < AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE.length; ++i) {
if (sampleRate == AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE[i]) {
sampleRateIndex = i;
}
}
int channelConfig = -1;
for (int i = 0; i < AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE.length; ++i) {
if (numChannels == AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE[i]) {
channelConfig = i;
}
}
// The full specification for AudioSpecificConfig is stated in ISO 14496-3 Section 1.6.2.1
byte[] csd = new byte[2];
csd[0] = (byte) ((AUDIO_OBJECT_TYPE_AAC_LC << 3) | (sampleRateIndex >> 1));
csd[1] = (byte) (((sampleRateIndex & 0x1) << 7) | (channelConfig << 3));
return csd;
}
/** /**
* Constructs a NAL unit consisting of the NAL start code followed by the specified data. * Constructs a NAL unit consisting of the NAL start code followed by the specified data.
* *

View file

@ -47,11 +47,11 @@ public class ManifestFetcher<T> implements Loader.Callback {
*/ */
public interface EventListener { public interface EventListener {
public void onManifestRefreshStarted(); void onManifestRefreshStarted();
public void onManifestRefreshed(); void onManifestRefreshed();
public void onManifestError(IOException e); void onManifestError(IOException e);
} }
@ -65,7 +65,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
* Returns the {@link Uri} from which subsequent manifests should be requested, or null to * Returns the {@link Uri} from which subsequent manifests should be requested, or null to
* continue using the current {@link Uri}. * continue using the current {@link Uri}.
*/ */
public Uri getNextManifestUri(); Uri getNextManifestUri();
} }

View file

@ -163,7 +163,7 @@ public final class UriUtil {
int segmentStart = offset; int segmentStart = offset;
int i = offset; int i = offset;
while (i <= limit) { while (i <= limit) {
int nextSegmentStart = -1; int nextSegmentStart;
if (i == limit) { if (i == limit) {
nextSegmentStart = i; nextSegmentStart = i;
} else if (uri.charAt(i) == '/') { } else if (uri.charAt(i) == '/') {

View file

@ -384,20 +384,6 @@ public final class Util {
return stayInBounds ? Math.min(list.size() - 1, index) : index; return stayInBounds ? Math.min(list.size() - 1, index) : index;
} }
/**
* Creates an integer array containing the integers from 0 to {@code length - 1}.
*
* @param length The length of the array.
* @return The array.
*/
public static int[] firstIntegersArray(int length) {
int[] firstIntegers = new int[length];
for (int i = 0; i < length; i++) {
firstIntegers[i] = i;
}
return firstIntegers;
}
/** /**
* Parses an xs:duration attribute value, returning the parsed duration in milliseconds. * Parses an xs:duration attribute value, returning the parsed duration in milliseconds.
* *
@ -876,8 +862,8 @@ public final class Util {
* <p>See {@link #escapeFileName(String)} for more information. * <p>See {@link #escapeFileName(String)} for more information.
* *
* @param fileName File name to be unescaped. * @param fileName File name to be unescaped.
* @return The original value of the file name before it was escaped, * @return The original value of the file name before it was escaped, or null if the escaped
* or null if the escaped fileName seems invalid. * fileName seems invalid.
*/ */
public static String unescapeFileName(String fileName) { public static String unescapeFileName(String fileName) {
int length = fileName.length(); int length = fileName.length();