mirror of
https://github.com/samsonjs/media.git
synced 2026-04-05 11:15:46 +00:00
Apply Android studio code analysis suggestions.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=120326293
This commit is contained in:
parent
48bc98f1ed
commit
2e0518f47b
92 changed files with 368 additions and 622 deletions
|
|
@ -16,7 +16,6 @@
|
|||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import com.google.android.exoplayer.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer.DefaultTrackSelector.TrackInfo;
|
||||
import com.google.android.exoplayer.ExoPlaybackException;
|
||||
import com.google.android.exoplayer.ExoPlayer;
|
||||
|
|
@ -106,7 +105,6 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
|
||||
private DataSourceFactory dataSourceFactory;
|
||||
private DemoPlayer player;
|
||||
private DefaultTrackSelector trackSelector;
|
||||
private TrackSelectionHelper trackSelectionHelper;
|
||||
private DebugTextViewHelper debugViewHelper;
|
||||
private boolean playerNeedsSource;
|
||||
|
|
@ -137,11 +135,8 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
root.setOnKeyListener(new OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE
|
||||
|| keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
return false;
|
||||
}
|
||||
return mediaController.dispatchKeyEvent(event);
|
||||
return keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_ESCAPE
|
||||
&& keyCode != KeyEvent.KEYCODE_MENU && mediaController.dispatchKeyEvent(event);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -287,8 +282,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
player.setCaptionListener(this);
|
||||
player.setMetadataListener(this);
|
||||
player.seekTo(playerPosition);
|
||||
trackSelector = player.getTrackSelector();
|
||||
trackSelectionHelper = new TrackSelectionHelper(trackSelector);
|
||||
trackSelectionHelper = new TrackSelectionHelper(player.getTrackSelector());
|
||||
playerNeedsSource = true;
|
||||
mediaController.setMediaPlayer(player.getPlayerControl());
|
||||
mediaController.setEnabled(true);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -108,9 +108,7 @@ import java.util.List;
|
|||
// Read the channel mapping.
|
||||
numStreams = headerBytes[19] & 0xFF;
|
||||
numCoupled = headerBytes[20] & 0xFF;
|
||||
for (int i = 0; i < channelCount; i++) {
|
||||
streamMap[i] = headerBytes[21 + i];
|
||||
}
|
||||
System.arraycopy(headerBytes, 21, streamMap, 0, channelCount);
|
||||
}
|
||||
if (initializationData.size() == 3) {
|
||||
if (initializationData.get(1).length != 8 || initializationData.get(2).length != 8) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer.ext.vp9;
|
||||
|
||||
import com.google.android.exoplayer.CodecCounters;
|
||||
import com.google.android.exoplayer.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer.ExoPlaybackException;
|
||||
import com.google.android.exoplayer.ExoPlayer;
|
||||
import com.google.android.exoplayer.Format;
|
||||
|
|
@ -121,7 +122,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
|
||||
private Format format;
|
||||
private VpxDecoder decoder;
|
||||
private VpxInputBuffer inputBuffer;
|
||||
private DecoderInputBuffer inputBuffer;
|
||||
private VpxOutputBuffer outputBuffer;
|
||||
private VpxOutputBuffer nextOutputBuffer;
|
||||
|
||||
|
|
@ -335,9 +336,6 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
}
|
||||
if (inputBuffer.isEndOfStream()) {
|
||||
inputStreamEnded = true;
|
||||
} else {
|
||||
inputBuffer.width = format.width;
|
||||
inputBuffer.height = format.height;
|
||||
}
|
||||
decoder.queueInputBuffer(inputBuffer);
|
||||
inputBuffer = null;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer.ext.vp9;
|
||||
|
||||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer.util.extensions.SimpleDecoder;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -24,7 +25,7 @@ import java.nio.ByteBuffer;
|
|||
* JNI wrapper for the libvpx VP9 decoder.
|
||||
*/
|
||||
/* 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_YUV = 0;
|
||||
|
|
@ -65,7 +66,7 @@ import java.nio.ByteBuffer;
|
|||
*/
|
||||
public VpxDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize)
|
||||
throws VpxDecoderException {
|
||||
super(new VpxInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]);
|
||||
super(new DecoderInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]);
|
||||
vpxDecContext = vpxInit();
|
||||
if (vpxDecContext == 0) {
|
||||
throw new VpxDecoderException("Failed to initialize decoder");
|
||||
|
|
@ -84,8 +85,8 @@ import java.nio.ByteBuffer;
|
|||
}
|
||||
|
||||
@Override
|
||||
protected VpxInputBuffer createInputBuffer() {
|
||||
return new VpxInputBuffer();
|
||||
protected DecoderInputBuffer createInputBuffer() {
|
||||
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -99,7 +100,7 @@ import java.nio.ByteBuffer;
|
|||
}
|
||||
|
||||
@Override
|
||||
protected VpxDecoderException decode(VpxInputBuffer inputBuffer, VpxOutputBuffer outputBuffer,
|
||||
protected VpxDecoderException decode(DecoderInputBuffer inputBuffer, VpxOutputBuffer outputBuffer,
|
||||
boolean reset) {
|
||||
outputBuffer.timestampUs = inputBuffer.timeUs;
|
||||
inputBuffer.data.position(inputBuffer.data.position() - inputBuffer.size);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -78,7 +78,6 @@ import javax.microedition.khronos.opengles.GL10;
|
|||
private int program;
|
||||
private int texLocation;
|
||||
private int colorMatrixLocation;
|
||||
private FloatBuffer textureCoords;
|
||||
private int previousWidth;
|
||||
private int previousStride;
|
||||
|
||||
|
|
@ -171,7 +170,7 @@ import javax.microedition.khronos.opengles.GL10;
|
|||
// Set cropping of stride if either width or stride has changed.
|
||||
if (previousWidth != outputBuffer.width || previousStride != outputBuffer.yuvStrides[0]) {
|
||||
float crop = (float) outputBuffer.width / outputBuffer.yuvStrides[0];
|
||||
textureCoords = nativeFloatBuffer(
|
||||
FloatBuffer textureCoords = nativeFloatBuffer(
|
||||
0.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
crop, 0.0f,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import com.android.builder.core.BuilderConstants
|
||||
|
||||
// Copyright (C) 2014 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -48,7 +50,7 @@ dependencies {
|
|||
|
||||
android.libraryVariants.all { variant ->
|
||||
def name = variant.buildType.name
|
||||
if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) {
|
||||
if (name.equals(BuilderConstants.DEBUG)) {
|
||||
return; // Skip debug builds.
|
||||
}
|
||||
def task = project.tasks.create "jar${name.capitalize()}", Jar
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import junit.framework.TestCase;
|
|||
public class CTest extends TestCase {
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
public static final void testContants() {
|
||||
public static void testConstants() {
|
||||
// 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_END_OF_STREAM, C.BUFFER_FLAG_END_OF_STREAM);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import junit.framework.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}.
|
||||
assertEquals(C.RESULT_END_OF_INPUT, Extractor.RESULT_END_OF_INPUT);
|
||||
// Sanity check that the other constant values don't overlap.
|
||||
|
|
|
|||
|
|
@ -794,15 +794,8 @@ public final class MatroskaExtractorTest extends InstrumentationTestCase {
|
|||
output.assertSample(index, expectedMedia, timeUs, flags, encryptionKey);
|
||||
}
|
||||
|
||||
private byte[] getVorbisCodecPrivate() {
|
||||
byte[] codecPrivate = new byte[4207];
|
||||
try {
|
||||
getInstrumentation().getContext().getResources().getAssets().open(TEST_VORBIS_CODEC_PRIVATE)
|
||||
.read(codecPrivate);
|
||||
} catch (IOException e) {
|
||||
fail(); // should never happen
|
||||
}
|
||||
return codecPrivate;
|
||||
private byte[] getVorbisCodecPrivate() throws IOException {
|
||||
return TestUtil.getByteArray(getInstrumentation(), TEST_VORBIS_CODEC_PRIVATE);
|
||||
}
|
||||
|
||||
private static byte[] createFrameData(int size) {
|
||||
|
|
|
|||
|
|
@ -65,10 +65,11 @@ import java.util.List;
|
|||
|
||||
private static final int NO_VALUE = -1;
|
||||
|
||||
private final List<EbmlElement> trackEntries;
|
||||
private final List<EbmlElement> mediaSegments;
|
||||
|
||||
private EbmlElement header;
|
||||
private EbmlElement info;
|
||||
private List<EbmlElement> trackEntries;
|
||||
private List<EbmlElement> mediaSegments;
|
||||
|
||||
public StreamBuilder() {
|
||||
trackEntries = new LinkedList<>();
|
||||
|
|
@ -185,13 +186,13 @@ import java.util.List;
|
|||
Assertions.checkNotNull(header);
|
||||
Assertions.checkNotNull(info);
|
||||
|
||||
EbmlElement tracks = element(0x1654AE6B, trackEntries.toArray(new EbmlElement[0]));
|
||||
EbmlElement tracks = element(0x1654AE6B,
|
||||
trackEntries.toArray(new EbmlElement[trackEntries.size()]));
|
||||
EbmlElement[] children;
|
||||
|
||||
if (cuePointCount == 0) {
|
||||
children = new EbmlElement[2 + mediaSegments.size()];
|
||||
System.arraycopy(mediaSegments.toArray(new EbmlElement[0]), 0, children, 2,
|
||||
mediaSegments.size());
|
||||
System.arraycopy(mediaSegments.toArray(), 0, children, 2, mediaSegments.size());
|
||||
children[0] = info;
|
||||
children[1] = tracks;
|
||||
} else {
|
||||
|
|
@ -211,8 +212,7 @@ import java.util.List;
|
|||
|
||||
// Build the top-level segment element.
|
||||
children = new EbmlElement[3 + mediaSegments.size()];
|
||||
System.arraycopy(mediaSegments.toArray(new EbmlElement[0]), 0, children, 3,
|
||||
mediaSegments.size());
|
||||
System.arraycopy(mediaSegments.toArray(), 0, children, 3, mediaSegments.size());
|
||||
children[0] = info;
|
||||
children[1] = tracks;
|
||||
children[2] = cues;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public final class Mp4ExtractorTest extends TestCase {
|
|||
/** Video frame timestamps in time units. */
|
||||
private static final int[] SAMPLE_TIMESTAMPS = {0, 2, 3, 5, 6, 7};
|
||||
/** 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. */
|
||||
private static final boolean[] SAMPLE_IS_SYNC = {true, false, false, false, true, true};
|
||||
/** Indices of video frame chunk offsets. */
|
||||
|
|
@ -260,8 +260,8 @@ public final class Mp4ExtractorTest extends TestCase {
|
|||
|
||||
private static byte[] getStss() {
|
||||
int synchronizationSampleCount = 0;
|
||||
for (int i = 0; i < SAMPLE_IS_SYNC.length; i++) {
|
||||
if (SAMPLE_IS_SYNC[i]) {
|
||||
for (boolean sampleIsSync : SAMPLE_IS_SYNC) {
|
||||
if (sampleIsSync) {
|
||||
synchronizationSampleCount++;
|
||||
}
|
||||
}
|
||||
|
|
@ -364,7 +364,7 @@ public final class Mp4ExtractorTest extends TestCase {
|
|||
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)
|
||||
: getTestMp4FileWithoutSynchronizationData(mp4vFormat);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import java.util.Random;
|
|||
*/
|
||||
public final class OggUtilTest extends TestCase {
|
||||
|
||||
private Random random = new Random(0);
|
||||
private final Random random = new Random(0);
|
||||
|
||||
public void testReadBits() throws Exception {
|
||||
assertEquals(0, OggUtil.readBits((byte) 0x00, 2, 2));
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import com.google.android.exoplayer.testutil.TestUtil;
|
|||
0x4F, 0x67, 0x67, 0x53, // Oggs.
|
||||
0x00, // Stream revision.
|
||||
headerType,
|
||||
(int) (granule >> 0) & 0xFF,
|
||||
(int) (granule) & 0xFF,
|
||||
(int) (granule >> 8) & 0xFF,
|
||||
(int) (granule >> 16) & 0xFF,
|
||||
(int) (granule >> 24) & 0xFF,
|
||||
|
|
@ -46,7 +46,7 @@ import com.google.android.exoplayer.testutil.TestUtil;
|
|||
0x10,
|
||||
0x00,
|
||||
0x00, // MSB of data serial number.
|
||||
(pageSequenceCounter >> 0) & 0xFF,
|
||||
(pageSequenceCounter) & 0xFF,
|
||||
(pageSequenceCounter >> 8) & 0xFF,
|
||||
(pageSequenceCounter >> 16) & 0xFF,
|
||||
(pageSequenceCounter >> 24) & 0xFF,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public final class FakeDataSource implements DataSource {
|
|||
totalLength += segment.length;
|
||||
}
|
||||
this.totalLength = totalLength;
|
||||
openedDataSpecs = new ArrayList<DataSpec>();
|
||||
openedDataSpecs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public final class Mp4WebvttParserTest extends TestCase {
|
|||
|
||||
public void testNoCueSample() throws IOException {
|
||||
Subtitle result = parser.decode(NO_CUE_SAMPLE, NO_CUE_SAMPLE.length);
|
||||
assertMp4WebvttSubtitleEquals(result, new Cue[] {});
|
||||
assertMp4WebvttSubtitleEquals(result, new Cue[0]);
|
||||
}
|
||||
|
||||
// Negative tests.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.google.android.exoplayer.text.Cue;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -32,37 +33,38 @@ public class WebvttSubtitleTest extends TestCase {
|
|||
private static final String FIRST_AND_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);
|
||||
simpleSubtitleCues.add(firstCue);
|
||||
|
||||
WebvttCue secondCue = new WebvttCue(3000000, 4000000, SECOND_SUBTITLE_STRING);
|
||||
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);
|
||||
overlappingSubtitleCues.add(firstCue);
|
||||
|
||||
WebvttCue secondCue = new WebvttCue(2000000, 4000000, SECOND_SUBTITLE_STRING);
|
||||
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);
|
||||
nestedSubtitleCues.add(firstCue);
|
||||
|
||||
WebvttCue secondCue = new WebvttCue(2000000, 3000000, SECOND_SUBTITLE_STRING);
|
||||
nestedSubtitleCues.add(secondCue);
|
||||
nestedSubtitle = new WebvttSubtitle(nestedSubtitleCues);
|
||||
}
|
||||
private WebvttSubtitle nestedSubtitle = new WebvttSubtitle(nestedSubtitleCues);
|
||||
|
||||
public void testEventCount() {
|
||||
assertEquals(0, emptySubtitle.getEventTimeCount());
|
||||
|
|
@ -71,13 +73,6 @@ public class WebvttSubtitleTest extends TestCase {
|
|||
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() {
|
||||
testSubtitleEventTimesHelper(simpleSubtitle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,4 @@ public final class BehindLiveWindowException extends IOException {
|
|||
super();
|
||||
}
|
||||
|
||||
public BehindLiveWindowException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,17 +46,15 @@ public final class CodecCounters {
|
|||
|
||||
public String getDebugString() {
|
||||
ensureUpdated();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("cic:").append(codecInitCount);
|
||||
builder.append(" crc:").append(codecReleaseCount);
|
||||
builder.append(" ibc:").append(inputBufferCount);
|
||||
builder.append(" ofc:").append(outputFormatChangedCount);
|
||||
builder.append(" obc:").append(outputBuffersChangedCount);
|
||||
builder.append(" ren:").append(renderedOutputBufferCount);
|
||||
builder.append(" sob:").append(skippedOutputBufferCount);
|
||||
builder.append(" dob:").append(droppedOutputBufferCount);
|
||||
builder.append(" mcdob:").append(maxConsecutiveDroppedOutputBufferCount);
|
||||
return builder.toString();
|
||||
return "cic:" + codecInitCount
|
||||
+ " crc:" + codecReleaseCount
|
||||
+ " ibc:" + inputBufferCount
|
||||
+ " ofc:" + outputFormatChangedCount
|
||||
+ " obc:" + outputBuffersChangedCount
|
||||
+ " ren:" + renderedOutputBufferCount
|
||||
+ " sob:" + skippedOutputBufferCount
|
||||
+ " dob:" + droppedOutputBufferCount
|
||||
+ " mcdob:" + maxConsecutiveDroppedOutputBufferCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,11 +148,7 @@ public final class DecoderInfo {
|
|||
}
|
||||
|
||||
private static boolean isAdaptive(CodecCapabilities capabilities) {
|
||||
if (Util.SDK_INT >= 19) {
|
||||
return isAdaptiveV19(capabilities);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return Util.SDK_INT >= 19 && isAdaptiveV19(capabilities);
|
||||
}
|
||||
|
||||
@TargetApi(19)
|
||||
|
|
|
|||
|
|
@ -503,12 +503,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
if (renderer.getState() == TrackRenderer.STATE_ENABLED) {
|
||||
renderer.disable();
|
||||
}
|
||||
} catch (ExoPlaybackException e) {
|
||||
} catch (ExoPlaybackException | RuntimeException e) {
|
||||
// There's nothing we can do.
|
||||
Log.e(TAG, "Stop failed.", e);
|
||||
} catch (RuntimeException e) {
|
||||
// Ditto.
|
||||
Log.e(TAG, "Stop failed.", e);
|
||||
}
|
||||
}
|
||||
if (source != null) {
|
||||
|
|
|
|||
|
|
@ -403,24 +403,21 @@ public final class Format {
|
|||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private static final void maybeSetStringV16(MediaFormat format, String key,
|
||||
String value) {
|
||||
private static void maybeSetStringV16(MediaFormat format, String key, String value) {
|
||||
if (value != null) {
|
||||
format.setString(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private static final void maybeSetIntegerV16(MediaFormat format, String key,
|
||||
int value) {
|
||||
private static void maybeSetIntegerV16(MediaFormat format, String key, int value) {
|
||||
if (value != NO_VALUE) {
|
||||
format.setInteger(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private static final void maybeSetFloatV16(MediaFormat format, String key,
|
||||
float value) {
|
||||
private static void maybeSetFloatV16(MediaFormat format, String key, float value) {
|
||||
if (value != NO_VALUE) {
|
||||
format.setFloat(key, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||
fileDescriptor = null;
|
||||
fileDescriptorOffset = 0;
|
||||
fileDescriptorLength = 0;
|
||||
durationUs = C.UNSET_TIME_US;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,6 +118,7 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||
context = null;
|
||||
uri = null;
|
||||
headers = null;
|
||||
durationUs = C.UNSET_TIME_US;
|
||||
}
|
||||
|
||||
// SampleSource implementation.
|
||||
|
|
@ -132,7 +134,6 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||
} else {
|
||||
extractor.setDataSource(fileDescriptor, fileDescriptorOffset, fileDescriptorLength);
|
||||
}
|
||||
durationUs = C.UNSET_TIME_US;
|
||||
trackStates = new int[extractor.getTrackCount()];
|
||||
pendingResets = new boolean[trackStates.length];
|
||||
TrackGroup[] trackArray = new TrackGroup[trackStates.length];
|
||||
|
|
@ -150,7 +151,7 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||
|
||||
@Override
|
||||
public long getDurationUs() {
|
||||
return C.UNSET_TIME_US;
|
||||
return durationUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -667,11 +667,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||
if (drmManagerState == DrmSessionManager.STATE_ERROR) {
|
||||
throw ExoPlaybackException.createForRenderer(drmSessionManager.getError(), getIndex());
|
||||
}
|
||||
if (drmManagerState != DrmSessionManager.STATE_OPENED_WITH_KEYS &&
|
||||
(bufferEncrypted || !playClearSamplesWithoutKeys)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return drmManagerState != DrmSessionManager.STATE_OPENED_WITH_KEYS
|
||||
&& (bufferEncrypted || !playClearSamplesWithoutKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -840,10 +837,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||
|
||||
/**
|
||||
* 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();
|
||||
if (codecNeedsMonoChannelCountWorkaround) {
|
||||
format.setInteger(android.media.MediaFormat.KEY_CHANNEL_COUNT, 1);
|
||||
|
|
@ -917,7 +912,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||
private int getDecodeOnlyIndex(long presentationTimeUs) {
|
||||
final int size = decodeOnlyPresentationTimestamps.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (decodeOnlyPresentationTimestamps.get(i).longValue() == presentationTimeUs) {
|
||||
if (decodeOnlyPresentationTimestamps.get(i) == presentationTimeUs) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,8 +126,7 @@ public final class MediaCodecUtil {
|
|||
String codecName = info.getName();
|
||||
if (isCodecUsableDecoder(info, codecName, secureDecodersExplicit)) {
|
||||
String[] supportedTypes = info.getSupportedTypes();
|
||||
for (int j = 0; j < supportedTypes.length; j++) {
|
||||
String supportedType = supportedTypes[j];
|
||||
for (String supportedType : supportedTypes) {
|
||||
if (supportedType.equalsIgnoreCase(mimeType)) {
|
||||
CodecCapabilities capabilities = info.getCapabilitiesForType(supportedType);
|
||||
boolean secure = mediaCodecList.isSecurePlaybackSupported(key.mimeType, capabilities);
|
||||
|
|
@ -291,25 +290,25 @@ public final class MediaCodecUtil {
|
|||
/**
|
||||
* The number of codecs in the list.
|
||||
*/
|
||||
public int getCodecCount();
|
||||
int getCodecCount();
|
||||
|
||||
/**
|
||||
* The info at the specified index in the list.
|
||||
*
|
||||
* @param index The index.
|
||||
*/
|
||||
public MediaCodecInfo getCodecInfoAt(int index);
|
||||
MediaCodecInfo getCodecInfoAt(int index);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* have been obtained from a {@link MediaCodecInfo} obtained from this list.
|
||||
*/
|
||||
public boolean isSecurePlaybackSupported(String mimeType, CodecCapabilities capabilities);
|
||||
boolean isSecurePlaybackSupported(String mimeType, CodecCapabilities capabilities);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,10 +192,10 @@ public final class MultiSampleSource implements SampleSource {
|
|||
|
||||
private Pair<SampleSource, Integer> getSourceAndGroup(int group) {
|
||||
int totalTrackGroupCount = 0;
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
int sourceTrackGroupCount = sources[i].getTrackGroups().length;
|
||||
for (SampleSource source : sources) {
|
||||
int sourceTrackGroupCount = source.getTrackGroups().length;
|
||||
if (group < totalTrackGroupCount + sourceTrackGroupCount) {
|
||||
return Pair.create(sources[i], group - totalTrackGroupCount);
|
||||
return Pair.create(source, group - totalTrackGroupCount);
|
||||
}
|
||||
totalTrackGroupCount += sourceTrackGroupCount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,7 +227,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||
long resetPositionUs = stream.readReset();
|
||||
if (resetPositionUs != C.UNSET_TIME_US) {
|
||||
reset(resetPositionUs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
|
|||
|
||||
private final ChunkExtractorWrapper extractorWrapper;
|
||||
private final long sampleOffsetUs;
|
||||
private final Format sampleFormat;
|
||||
|
||||
private volatile DrmInitData drmInitData;
|
||||
private volatile Format sampleFormat;
|
||||
private volatile int bytesLoaded;
|
||||
private volatile boolean loadCanceled;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public interface FormatEvaluator {
|
|||
/**
|
||||
* A format evaluation.
|
||||
*/
|
||||
public static final class Evaluation {
|
||||
final class Evaluation {
|
||||
|
||||
/**
|
||||
* The selected format.
|
||||
|
|
@ -99,7 +99,7 @@ public interface FormatEvaluator {
|
|||
/**
|
||||
* 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;
|
||||
|
||||
|
|
@ -131,8 +131,8 @@ public interface FormatEvaluator {
|
|||
Evaluation evaluation) {
|
||||
// Count the number of non-blacklisted formats.
|
||||
int nonBlacklistedFormatCount = 0;
|
||||
for (int i = 0; i < blacklistFlags.length; i++) {
|
||||
if (!blacklistFlags[i]) {
|
||||
for (boolean blacklistFlag : blacklistFlags) {
|
||||
if (!blacklistFlag) {
|
||||
nonBlacklistedFormatCount++;
|
||||
}
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ public interface FormatEvaluator {
|
|||
* reference implementation only. It is recommended that application developers implement their
|
||||
* 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -371,7 +371,6 @@ public class DashChunkSource implements ChunkSource {
|
|||
}
|
||||
} catch (BehindLiveWindowException e) {
|
||||
fatalError = e;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,8 +90,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||
// MPD parsing.
|
||||
|
||||
@Override
|
||||
public MediaPresentationDescription parse(Uri uri, InputStream inputStream)
|
||||
throws IOException, ParserException {
|
||||
public MediaPresentationDescription parse(Uri uri, InputStream inputStream) throws IOException {
|
||||
try {
|
||||
XmlPullParser xpp = xmlParserFactory.newPullParser();
|
||||
xpp.setInput(inputStream, null);
|
||||
|
|
@ -101,9 +100,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||
"inputStream does not contain a valid media presentation description");
|
||||
}
|
||||
return parseMediaPresentationDescription(xpp, uri.toString());
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new ParserException(e);
|
||||
} catch (ParseException e) {
|
||||
} catch (XmlPullParserException | ParseException e) {
|
||||
throw new ParserException(e);
|
||||
}
|
||||
}
|
||||
|
|
@ -114,7 +111,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||
long durationMs = parseDuration(xpp, "mediaPresentationDuration", -1);
|
||||
long minBufferTimeMs = parseDuration(xpp, "minBufferTime", -1);
|
||||
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 timeShiftBufferDepthMs = (dynamic) ? parseDuration(xpp, "timeShiftBufferDepth", -1) : -1;
|
||||
UtcTimingElement utcTiming = null;
|
||||
|
|
@ -372,7 +369,6 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||
float frameRate = parseFrameRate(xpp, adaptationSetFrameRate);
|
||||
int audioChannels = adaptationSetAudioChannels;
|
||||
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
|
||||
String language = adaptationSetLanguage;
|
||||
|
||||
boolean seenFirstBaseUrl = false;
|
||||
do {
|
||||
|
|
@ -399,7 +395,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||
} while (!ParserUtil.isEndTag(xpp, "Representation"));
|
||||
|
||||
Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels,
|
||||
audioSamplingRate, bandwidth, language, codecs);
|
||||
audioSamplingRate, bandwidth, adaptationSetLanguage, codecs);
|
||||
return buildRepresentation(contentId, -1, format,
|
||||
segmentBase != null ? segmentBase : new SingleSegmentBase(baseUrl));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ public abstract class Representation {
|
|||
/**
|
||||
* Identifies the piece of content to which this {@link Representation} belongs.
|
||||
* <p>
|
||||
* For example, all {@link Representation}s belonging to a video should have the same
|
||||
* {@link #contentId}, which should uniquely identify that video.
|
||||
* For example, all {@link Representation}s belonging to a video should have the same content
|
||||
* identifier that uniquely identifies that video.
|
||||
*/
|
||||
public final String contentId;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ public abstract class SegmentBase {
|
|||
|
||||
@Override
|
||||
public RangedUri getSegmentUrl(Representation representation, int sequenceNumber) {
|
||||
long time = 0;
|
||||
long time;
|
||||
if (segmentTimeline != null) {
|
||||
time = segmentTimeline.get(sequenceNumber - startNumber).startTime;
|
||||
} else {
|
||||
|
|
@ -357,8 +357,8 @@ public abstract class SegmentBase {
|
|||
*/
|
||||
public static class SegmentTimelineElement {
|
||||
|
||||
/* package */ long startTime;
|
||||
/* package */ long duration;
|
||||
/* package */ final long startTime;
|
||||
/* package */ final long duration;
|
||||
|
||||
/**
|
||||
* @param startTime The start time of the element. The value in seconds is the division of this
|
||||
|
|
|
|||
|
|
@ -144,14 +144,18 @@ public final class UrlTemplate {
|
|||
}
|
||||
identifier = identifier.substring(0, formatTagIndex);
|
||||
}
|
||||
if (identifier.equals(NUMBER)) {
|
||||
identifiers[identifierCount] = NUMBER_ID;
|
||||
} else if (identifier.equals(BANDWIDTH)) {
|
||||
identifiers[identifierCount] = BANDWIDTH_ID;
|
||||
} else if (identifier.equals(TIME)) {
|
||||
identifiers[identifierCount] = TIME_ID;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid template: " + template);
|
||||
switch (identifier) {
|
||||
case NUMBER:
|
||||
identifiers[identifierCount] = NUMBER_ID;
|
||||
break;
|
||||
case BANDWIDTH:
|
||||
identifiers[identifierCount] = BANDWIDTH_ID;
|
||||
break;
|
||||
case TIME:
|
||||
identifiers[identifierCount] = TIME_ID;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid template: " + template);
|
||||
}
|
||||
identifierFormatTags[identifierCount] = formatTag;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
|
|||
private static class XsDateTimeParser implements UriLoadable.Parser<Long> {
|
||||
|
||||
@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();
|
||||
try {
|
||||
return Util.parseXsDateTime(firstLine);
|
||||
|
|
@ -168,7 +168,7 @@ public final class UtcTimingElementResolver implements Loader.Callback {
|
|||
private static class Iso8601Parser implements UriLoadable.Parser<Long> {
|
||||
|
||||
@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();
|
||||
try {
|
||||
// TODO: It may be necessary to handle timestamp offsets from UTC.
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@ public interface DrmInitData {
|
|||
* @param schemeUuid The DRM scheme's UUID.
|
||||
* @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.
|
||||
*/
|
||||
public static final class Mapped implements DrmInitData {
|
||||
final class Mapped implements DrmInitData {
|
||||
|
||||
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.
|
||||
*/
|
||||
public static final class Universal implements DrmInitData {
|
||||
final class Universal implements DrmInitData {
|
||||
|
||||
private SchemeInitData data;
|
||||
private final SchemeInitData data;
|
||||
|
||||
public Universal(SchemeInitData data) {
|
||||
this.data = data;
|
||||
|
|
@ -86,7 +86,7 @@ public interface DrmInitData {
|
|||
/**
|
||||
* Scheme initialization data.
|
||||
*/
|
||||
public static final class SchemeInitData {
|
||||
final class SchemeInitData {
|
||||
|
||||
/**
|
||||
* The mimeType of {@link #data}.
|
||||
|
|
|
|||
|
|
@ -27,24 +27,24 @@ public interface DrmSessionManager {
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
public static final int STATE_OPENED = 3;
|
||||
int STATE_OPENED = 3;
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -29,18 +29,18 @@ public interface Extractor {
|
|||
* to the next {@link #read(ExtractorInput, PositionHolder)} is required to provide data
|
||||
* 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
|
||||
* to the next {@link #read(ExtractorInput, PositionHolder)} is required to provide data starting
|
||||
* 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
|
||||
* {@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}.
|
||||
|
|
|
|||
|
|
@ -315,9 +315,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
|||
for (int i = 0; i < extractors.length; i++) {
|
||||
try {
|
||||
extractors[i] = DEFAULT_EXTRACTOR_CLASSES.get(i).newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalStateException("Unexpected error creating default extractor", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
} catch (Exception 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.
|
||||
boolean seekInsideBuffer = !isPendingReset();
|
||||
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 (!seekInsideBuffer) {
|
||||
|
|
@ -827,7 +825,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
|||
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||
*/
|
||||
public Extractor selectExtractor(ExtractorInput input)
|
||||
throws UnrecognizedInputFormatException, IOException, InterruptedException {
|
||||
throws IOException, InterruptedException {
|
||||
if (extractor != null) {
|
||||
return extractor;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,10 +137,8 @@ import java.util.List;
|
|||
* Builds initialization data for a {@link Format} from H.264 (AVC) codec private data.
|
||||
*
|
||||
* @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)
|
||||
throws ParserException {
|
||||
private AvcSequenceHeaderData parseAvcCodecPrivate(ParsableByteArray buffer) {
|
||||
// TODO: Deduplicate with AtomParsers.parseAvcCFromParent.
|
||||
buffer.setPosition(4);
|
||||
int nalUnitLengthFieldLength = (buffer.readUnsignedByte() & 0x03) + 1;
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ import java.util.Stack;
|
|||
* @throws IOException If an error occurs reading from the input.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws EOFException,
|
||||
IOException, InterruptedException {
|
||||
private long maybeResyncToNextLevel1Element(ExtractorInput input) throws IOException,
|
||||
InterruptedException {
|
||||
input.resetPeekPosition();
|
||||
while (true) {
|
||||
input.peekFully(scratch, 0, MAX_ID_BYTES);
|
||||
|
|
|
|||
|
|
@ -32,34 +32,34 @@ import java.io.IOException;
|
|||
/**
|
||||
* Type for unknown elements.
|
||||
*/
|
||||
public static final int TYPE_UNKNOWN = 0;
|
||||
int TYPE_UNKNOWN = 0;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static final int TYPE_UNSIGNED_INT = 2;
|
||||
int TYPE_UNSIGNED_INT = 2;
|
||||
/**
|
||||
* Type for string elements.
|
||||
*/
|
||||
public static final int TYPE_STRING = 3;
|
||||
int TYPE_STRING = 3;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static final int TYPE_FLOAT = 5;
|
||||
int TYPE_FLOAT = 5;
|
||||
|
||||
/**
|
||||
* Initializes the extractor with an {@link EbmlReaderOutput}.
|
||||
*
|
||||
* @param output An {@link EbmlReaderOutput} to receive events.
|
||||
*/
|
||||
public void init(EbmlReaderOutput output);
|
||||
void init(EbmlReaderOutput output);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* from scratch.
|
||||
*/
|
||||
public void reset();
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* 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 InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
public boolean read(ExtractorInput input) throws ParserException, IOException,
|
||||
InterruptedException;
|
||||
boolean read(ExtractorInput input) throws IOException, InterruptedException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,6 @@ import java.io.IOException;
|
|||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
void binaryElement(int id, int contentsSize, ExtractorInput input)
|
||||
throws ParserException, IOException, InterruptedException;
|
||||
throws IOException, InterruptedException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ import java.nio.charset.Charset;
|
|||
if (extendedHeaderSize > frame.bytesLeft()) {
|
||||
return null;
|
||||
}
|
||||
int paddingSize = 0;
|
||||
int paddingSize;
|
||||
if (extendedHeaderSize >= 6) {
|
||||
frame.skipBytes(2); // extended flags
|
||||
paddingSize = frame.readUnsignedIntToInt();
|
||||
|
|
|
|||
|
|
@ -260,8 +260,8 @@ import java.util.List;
|
|||
@Override
|
||||
public String toString() {
|
||||
return getAtomTypeString(type)
|
||||
+ " leaves: " + Arrays.toString(leafChildren.toArray(new LeafAtom[0]))
|
||||
+ " containers: " + Arrays.toString(containerChildren.toArray(new ContainerAtom[0]));
|
||||
+ " leaves: " + Arrays.toString(leafChildren.toArray())
|
||||
+ " containers: " + Arrays.toString(containerChildren.toArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||
private int atomHeaderBytesRead;
|
||||
private ParsableByteArray atomData;
|
||||
|
||||
private int sampleSize;
|
||||
private int sampleBytesWritten;
|
||||
private int sampleCurrentNalBytesRemaining;
|
||||
|
||||
|
|
@ -341,7 +340,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||
}
|
||||
}
|
||||
this.durationUs = durationUs;
|
||||
this.tracks = tracks.toArray(new Mp4Track[0]);
|
||||
this.tracks = tracks.toArray(new Mp4Track[tracks.size()]);
|
||||
extractorOutput.endTracks();
|
||||
extractorOutput.seekMap(this);
|
||||
}
|
||||
|
|
@ -378,7 +377,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||
return RESULT_SEEK;
|
||||
}
|
||||
input.skipFully((int) skipAmount);
|
||||
sampleSize = track.sampleTable.sizes[sampleIndex];
|
||||
int sampleSize = track.sampleTable.sizes[sampleIndex];
|
||||
if (track.track.nalUnitLengthFieldLength != -1) {
|
||||
// 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.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ import com.google.android.exoplayer.util.Assertions;
|
|||
/* package */ final class VorbisBitArray {
|
||||
|
||||
public final byte[] data;
|
||||
private int limit;
|
||||
|
||||
private final int limit;
|
||||
|
||||
private int byteOffset;
|
||||
private int bitOffset;
|
||||
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ import java.util.Arrays;
|
|||
bitArray.skipBits(headerData.getPosition() * 8);
|
||||
|
||||
for (int i = 0; i < numberOfBooks; i++) {
|
||||
readBook(bitArray);
|
||||
skipBook(bitArray);
|
||||
}
|
||||
|
||||
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) {
|
||||
throw new ParserException("expected code book to start with [0x56, 0x43, 0x42] at "
|
||||
+ bitArray.getPosition());
|
||||
|
|
@ -393,7 +393,6 @@ import java.util.Arrays;
|
|||
// discard (no decoding required yet)
|
||||
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));
|
||||
}
|
||||
|
||||
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 final String vendor;
|
||||
|
|
|
|||
|
|
@ -85,71 +85,69 @@ import java.util.Collections;
|
|||
|
||||
@Override
|
||||
public void consume(ParsableByteArray data) {
|
||||
while (data.bytesLeft() > 0) {
|
||||
int offset = data.getPosition();
|
||||
int limit = data.limit();
|
||||
byte[] dataArray = data.data;
|
||||
int offset = data.getPosition();
|
||||
int limit = data.limit();
|
||||
byte[] dataArray = data.data;
|
||||
|
||||
// Append the data to the buffer.
|
||||
totalBytesWritten += data.bytesLeft();
|
||||
output.sampleData(data, data.bytesLeft());
|
||||
// Append the data to the buffer.
|
||||
totalBytesWritten += data.bytesLeft();
|
||||
output.sampleData(data, data.bytesLeft());
|
||||
|
||||
int searchOffset = offset;
|
||||
while (true) {
|
||||
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;
|
||||
int searchOffset = offset;
|
||||
while (true) {
|
||||
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) {
|
||||
// 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;
|
||||
}
|
||||
csdBuffer.onData(dataArray, offset, limit);
|
||||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,46 +94,44 @@ import java.util.List;
|
|||
|
||||
@Override
|
||||
public void consume(ParsableByteArray data) {
|
||||
while (data.bytesLeft() > 0) {
|
||||
int offset = data.getPosition();
|
||||
int limit = data.limit();
|
||||
byte[] dataArray = data.data;
|
||||
int offset = data.getPosition();
|
||||
int limit = data.limit();
|
||||
byte[] dataArray = data.data;
|
||||
|
||||
// Append the data to the buffer.
|
||||
totalBytesWritten += data.bytesLeft();
|
||||
output.sampleData(data, data.bytesLeft());
|
||||
// Append the data to the buffer.
|
||||
totalBytesWritten += data.bytesLeft();
|
||||
output.sampleData(data, data.bytesLeft());
|
||||
|
||||
// Scan the appended data, processing NAL units as they are encountered
|
||||
while (true) {
|
||||
int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);
|
||||
// Scan the appended data, processing NAL units as they are encountered
|
||||
while (true) {
|
||||
int nalUnitOffset = NalUnitUtil.findNalUnit(dataArray, offset, limit, prefixFlags);
|
||||
|
||||
if (nalUnitOffset == limit) {
|
||||
// We've scanned to the end of the data without finding the start of another NAL unit.
|
||||
nalUnitData(dataArray, offset, limit);
|
||||
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;
|
||||
if (nalUnitOffset == limit) {
|
||||
// We've scanned to the end of the data without finding the start of another NAL unit.
|
||||
nalUnitData(dataArray, offset, limit);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -342,8 +342,8 @@ import java.util.Collections;
|
|||
private static void skipShortTermRefPicSets(ParsableNalUnitBitArray bitArray) {
|
||||
int numShortTermRefPicSets = bitArray.readUnsignedExpGolombCodedInt();
|
||||
boolean interRefPicSetPredictionFlag = false;
|
||||
int numNegativePics = 0;
|
||||
int numPositivePics = 0;
|
||||
int numNegativePics;
|
||||
int numPositivePics;
|
||||
// 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.
|
||||
// RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1) and delta_idx_minus1 is always zero in SPS.
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ public final class PsExtractor implements Extractor {
|
|||
input.readFully(psPacketBuffer.data, 0, pesLength);
|
||||
psPacketBuffer.setPosition(6);
|
||||
psPacketBuffer.setLimit(pesLength);
|
||||
payloadReader.consume(psPacketBuffer, output);
|
||||
payloadReader.consume(psPacketBuffer);
|
||||
psPacketBuffer.setLimit(psPacketBuffer.capacity());
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +253,8 @@ public final class PsExtractor implements Extractor {
|
|||
* Notifies the reader that a seek has occurred.
|
||||
* <p>
|
||||
* Following a call to this method, the data passed to the next invocation of
|
||||
* {@link #consume(ParsableByteArray, ExtractorOutput)} will not be a continuation of
|
||||
* the data that was previously passed. Hence the reader should reset any internal state.
|
||||
* {@link #consume(ParsableByteArray)} will not be a continuation of the data that was
|
||||
* previously passed. Hence the reader should reset any internal state.
|
||||
*/
|
||||
public void seek() {
|
||||
seenFirstDts = false;
|
||||
|
|
@ -265,9 +265,8 @@ public final class PsExtractor implements Extractor {
|
|||
* Consumes the payload of a PS packet.
|
||||
*
|
||||
* @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);
|
||||
pesScratch.setPosition(0);
|
||||
parseHeader();
|
||||
|
|
|
|||
|
|
@ -39,14 +39,13 @@ import java.io.IOException;
|
|||
* Peeks and returns a {@code WavHeader}.
|
||||
*
|
||||
* @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 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
|
||||
* supported WAV format.
|
||||
*/
|
||||
public static WavHeader peek(ExtractorInput input)
|
||||
throws IOException, InterruptedException, ParserException {
|
||||
public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException {
|
||||
Assertions.checkNotNull(input);
|
||||
|
||||
// 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
|
||||
* a valid chunk header.
|
||||
* @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 InterruptedException If interrupted while reading from input.
|
||||
* @throws ParserException If an error occurs parsing chunks.
|
||||
*/
|
||||
public static void skipToData(ExtractorInput input, WavHeader wavHeader)
|
||||
throws IOException, InterruptedException, ParserException {
|
||||
throws IOException, InterruptedException {
|
||||
Assertions.checkNotNull(input);
|
||||
Assertions.checkNotNull(wavHeader);
|
||||
|
||||
|
|
|
|||
|
|
@ -68,9 +68,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||
Cipher cipher;
|
||||
try {
|
||||
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
|
@ -79,9 +77,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherIV);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -663,8 +663,8 @@ public class HlsChunkSource {
|
|||
}
|
||||
|
||||
private boolean allEnabledVariantsBlacklisted() {
|
||||
for (int i = 0; i < enabledVariantBlacklistFlags.length; i++) {
|
||||
if (!enabledVariantBlacklistFlags[i]) {
|
||||
for (boolean enabledVariantBlacklistFlag : enabledVariantBlacklistFlags) {
|
||||
if (!enabledVariantBlacklistFlag) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
|
|||
|
||||
private final Loader loader;
|
||||
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 int bufferSizeContribution;
|
||||
private final ChunkHolder nextChunkHolder;
|
||||
|
|
@ -262,13 +262,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
|
|||
|
||||
/* package */ boolean isReady(int group) {
|
||||
Assertions.checkState(groupEnabledStates[group]);
|
||||
if (loadingFinished) {
|
||||
return true;
|
||||
}
|
||||
if (isPendingReset()) {
|
||||
return false;
|
||||
}
|
||||
return !sampleQueues[group].isEmpty();
|
||||
return loadingFinished || (!isPendingReset() && !sampleQueues[group].isEmpty());
|
||||
}
|
||||
|
||||
/* package */ void maybeThrowError() throws IOException {
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
/* package */ final class HlsParserUtil {
|
||||
|
||||
private static final String BOOLEAN_YES = "YES";
|
||||
private static final String BOOLEAN_NO = "NO";
|
||||
|
||||
private HlsParserUtil() {}
|
||||
|
||||
public static String parseStringAttr(String line, Pattern pattern, String tag)
|
||||
|
|
@ -57,16 +54,4 @@ import java.util.regex.Pattern;
|
|||
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 + ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
|
|||
// HlsParserUtil.compileBooleanAttrPattern(DEFAULT_ATTR);
|
||||
|
||||
@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));
|
||||
Queue<String> extraLines = new LinkedList<>();
|
||||
String line;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public interface MetadataParser<T> {
|
|||
* @param mimeType A metadata mime type.
|
||||
* @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.
|
||||
|
|
@ -40,6 +40,6 @@ public interface MetadataParser<T> {
|
|||
* @return @return A parsed metadata object of type <T>.
|
||||
* @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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,10 +266,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
|||
int manifestTrackIndex = getManifestTrackIndex(streamElement, selectedFormat);
|
||||
Uri uri = streamElement.buildRequestUri(manifestTrackIndex, chunkIndex);
|
||||
|
||||
Chunk mediaChunk = newMediaChunk(selectedFormat, dataSource, uri, null,
|
||||
currentAbsoluteChunkIndex, chunkStartTimeUs, chunkEndTimeUs, evaluation.trigger,
|
||||
extractorWrapper, drmInitData, selectedFormat);
|
||||
out.chunk = mediaChunk;
|
||||
out.chunk = newMediaChunk(selectedFormat, dataSource, uri, null, currentAbsoluteChunkIndex,
|
||||
chunkStartTimeUs, chunkEndTimeUs, evaluation.trigger, extractorWrapper, drmInitData,
|
||||
selectedFormat);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -63,8 +63,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
|||
}
|
||||
|
||||
@Override
|
||||
public SmoothStreamingManifest parse(Uri uri, InputStream inputStream)
|
||||
throws IOException, ParserException {
|
||||
public SmoothStreamingManifest parse(Uri uri, InputStream inputStream) throws IOException {
|
||||
try {
|
||||
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
||||
xmlParser.setInput(inputStream, null);
|
||||
|
|
@ -105,8 +104,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
|||
this.normalizedAttributes = new LinkedList<>();
|
||||
}
|
||||
|
||||
public final Object parse(XmlPullParser xmlParser) throws XmlPullParserException, IOException,
|
||||
ParserException {
|
||||
public final Object parse(XmlPullParser xmlParser) throws XmlPullParserException, IOException {
|
||||
String tagName;
|
||||
boolean foundStartTag = false;
|
||||
int skippingElementDepth = 0;
|
||||
|
|
@ -224,17 +222,15 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
|||
|
||||
/**
|
||||
* @param xmlParser The underlying {@link XmlPullParser}
|
||||
* @throws ParserException
|
||||
*/
|
||||
protected void parseText(XmlPullParser xmlParser) throws ParserException {
|
||||
protected void parseText(XmlPullParser xmlParser) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param xmlParser The underlying {@link XmlPullParser}
|
||||
* @throws ParserException
|
||||
*/
|
||||
protected void parseEndTag(XmlPullParser xmlParser) throws ParserException {
|
||||
protected void parseEndTag(XmlPullParser xmlParser) {
|
||||
// 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_IS_LIVE = "IsLive";
|
||||
|
||||
private final List<StreamElement> streamElements;
|
||||
|
||||
private int majorVersion;
|
||||
private int minorVersion;
|
||||
private long timescale;
|
||||
|
|
@ -343,7 +341,6 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
|||
private int lookAheadCount;
|
||||
private boolean isLive;
|
||||
private ProtectionElement protectionElement;
|
||||
private List<StreamElement> streamElements;
|
||||
|
||||
public SmoothStreamMediaParser(ElementParser parent, String baseUri) {
|
||||
super(parent, baseUri, TAG);
|
||||
|
|
|
|||
|
|
@ -233,7 +233,6 @@ import android.util.Log;
|
|||
}
|
||||
|
||||
int textTop;
|
||||
int textBottom;
|
||||
if (cueLine != Cue.DIMEN_UNSET) {
|
||||
int anchorPosition;
|
||||
if (cueLineType == Cue.LINE_TYPE_FRACTION) {
|
||||
|
|
@ -250,17 +249,13 @@ import android.util.Log;
|
|||
textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight
|
||||
: cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2
|
||||
: anchorPosition;
|
||||
textBottom = textTop + textHeight;
|
||||
if (textBottom > parentBottom) {
|
||||
if (textTop + textHeight > parentBottom) {
|
||||
textTop = parentBottom - textHeight;
|
||||
textBottom = parentBottom;
|
||||
} else if (textTop < parentTop) {
|
||||
textTop = parentTop;
|
||||
textBottom = parentTop + textHeight;
|
||||
}
|
||||
} else {
|
||||
textTop = parentBottom - textHeight - (int) (parentHeight * bottomPaddingFraction);
|
||||
textBottom = textTop + textHeight;
|
||||
}
|
||||
|
||||
textWidth = textRight - textLeft;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public interface Subtitle {
|
|||
* @param timeUs The time in microseconds.
|
||||
* @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
|
||||
|
|
@ -36,7 +36,7 @@ public interface Subtitle {
|
|||
*
|
||||
* @return The number of event times.
|
||||
*/
|
||||
public int getEventTimeCount();
|
||||
int getEventTimeCount();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @return The event time in microseconds.
|
||||
*/
|
||||
public 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();
|
||||
long getEventTime(int index);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @return A list of cues that should be displayed, possibly empty.
|
||||
*/
|
||||
public List<Cue> getCues(long timeUs);
|
||||
List<Cue> getCues(long timeUs);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,11 +51,6 @@ import java.util.List;
|
|||
return subtitle.getEventTime(index) + offsetUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastEventTime() {
|
||||
return subtitle.getLastEventTime() + offsetUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextEventTimeIndex(long timeUs) {
|
||||
return subtitle.getNextEventTimeIndex(timeUs - offsetUs);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public interface SubtitleParserFactory {
|
|||
* <li>TX3G ({@link com.google.android.exoplayer.text.tx3g.Tx3gParser})</li>
|
||||
* </ul>
|
||||
*/
|
||||
final SubtitleParserFactory DEFAULT = new SubtitleParserFactory() {
|
||||
SubtitleParserFactory DEFAULT = new SubtitleParserFactory() {
|
||||
|
||||
@Override
|
||||
public boolean supportsFormat(Format format) {
|
||||
|
|
@ -68,7 +68,7 @@ public interface SubtitleParserFactory {
|
|||
throw new IllegalArgumentException("Attempted to create parser for unsupported format");
|
||||
}
|
||||
return clazz.asSubclass(SubtitleParser.class).newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Unexpected error instantiating parser", e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,11 +140,10 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback {
|
|||
}
|
||||
|
||||
boolean textRendererNeedsUpdate = false;
|
||||
long subtitleNextEventTimeUs = Long.MAX_VALUE;
|
||||
if (subtitle != null) {
|
||||
// We're iterating through the events in a subtitle. Set textRendererNeedsUpdate if we
|
||||
// advance to the next event.
|
||||
subtitleNextEventTimeUs = getNextEventTime();
|
||||
long subtitleNextEventTimeUs = getNextEventTime();
|
||||
while (subtitleNextEventTimeUs <= positionUs) {
|
||||
nextSubtitleEventIndex++;
|
||||
subtitleNextEventTimeUs = getNextEventTime();
|
||||
|
|
|
|||
|
|
@ -18,38 +18,36 @@ package com.google.android.exoplayer.text.eia608;
|
|||
/* package */ final class ClosedCaptionCtrl extends ClosedCaption {
|
||||
|
||||
/**
|
||||
* The receipt of the {@link #RESUME_CAPTION_LOADING} command initiates pop-on style captioning.
|
||||
* Subsequent data should be loaded into a non-displayed memory and held there until the
|
||||
* {@link #END_OF_CAPTION} command is received, at which point the non-displayed memory becomes
|
||||
* the displayed memory (and vice versa).
|
||||
* Command initiating pop-on style captioning. Subsequent data should be loaded into a
|
||||
* non-displayed memory and held there until the {@link #END_OF_CAPTION} command is received, at
|
||||
* which point the non-displayed memory becomes the displayed memory (and vice versa).
|
||||
*/
|
||||
public static final byte RESUME_CAPTION_LOADING = 0x20;
|
||||
/**
|
||||
* The receipt of the {@link #ROLL_UP_CAPTIONS_2_ROWS} command initiates roll-up style
|
||||
* captioning, with the maximum of 2 rows displayed simultaneously.
|
||||
* Command initiating roll-up style captioning, with the maximum of 2 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
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
|
||||
* captioning, with the maximum of 3 rows displayed simultaneously.
|
||||
* Command initiating roll-up style captioning, with the maximum of 3 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
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
|
||||
* captioning, with the maximum of 4 rows displayed simultaneously.
|
||||
* Command initiating roll-up style captioning, with the maximum of 4 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
public static final byte ROLL_UP_CAPTIONS_4_ROWS = 0x27;
|
||||
/**
|
||||
* The receipt of the {@link #RESUME_DIRECT_CAPTIONING} command initiates paint-on style
|
||||
* captioning. Subsequent data should be addressed immediately to displayed memory without need
|
||||
* for the {@link #RESUME_CAPTION_LOADING} command.
|
||||
* Command initiating paint-on style captioning. Subsequent data should be addressed immediately
|
||||
* to displayed memory without need for the {@link #RESUME_CAPTION_LOADING} command.
|
||||
*/
|
||||
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,
|
||||
* at this point already loaded in non-displayed memory caption should become the displayed
|
||||
* memory (and vice versa). If no {@link #RESUME_CAPTION_LOADING} command has been received,
|
||||
* {@link #END_OF_CAPTION} command forces the receiver into pop-on style.
|
||||
* Command indicating the end of a pop-on style caption. At this point the caption loaded in
|
||||
* non-displayed memory should be swapped with the one in displayed memory. If no
|
||||
* {@link #RESUME_CAPTION_LOADING} command has been received, this command forces the receiver
|
||||
* into pop-on style.
|
||||
*/
|
||||
public static final byte END_OF_CAPTION = 0x2F;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,20 +58,12 @@ import java.util.List;
|
|||
return cueTimesUs[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastEventTime() {
|
||||
if (getEventTimeCount() == 0) {
|
||||
return -1;
|
||||
}
|
||||
return cueTimesUs[cueTimesUs.length - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cue> getCues(long timeUs) {
|
||||
int index = Util.binarySearchFloor(cueTimesUs, timeUs, true, false);
|
||||
if (index == -1 || cues[index] == null) {
|
||||
// timeUs is earlier than the start of the first cue, or we have an empty cue.
|
||||
return Collections.<Cue>emptyList();
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return Collections.singletonList(cues[index]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ import java.util.TreeSet;
|
|||
public final long startTimeUs;
|
||||
public final long endTimeUs;
|
||||
public final TtmlStyle style;
|
||||
private String[] styleIds;
|
||||
private final String[] styleIds;
|
||||
|
||||
private List<TtmlNode> children;
|
||||
private int start;
|
||||
|
|
|
|||
|
|
@ -280,23 +280,29 @@ public final class TtmlParser extends SubtitleParser {
|
|||
for (int i = 0; i < attributeCount; i++) {
|
||||
String attr = ParserUtil.removeNamespacePrefix(parser.getAttributeName(i));
|
||||
String value = parser.getAttributeValue(i);
|
||||
if (attr.equals(ATTR_BEGIN)) {
|
||||
startTime = parseTimeExpression(value,
|
||||
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
|
||||
} else if (attr.equals(ATTR_END)) {
|
||||
endTime = parseTimeExpression(value,
|
||||
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
|
||||
} else if (attr.equals(ATTR_DURATION)) {
|
||||
duration = parseTimeExpression(value,
|
||||
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
|
||||
} else if (attr.equals(ATTR_STYLE)) {
|
||||
// IDREFS: potentially multiple space delimited ids
|
||||
String[] ids = parseStyleIds(value);
|
||||
if (ids.length > 0) {
|
||||
styleIds = ids;
|
||||
}
|
||||
} else {
|
||||
// Do nothing.
|
||||
switch (attr) {
|
||||
case ATTR_BEGIN:
|
||||
startTime = parseTimeExpression(value,
|
||||
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
|
||||
break;
|
||||
case ATTR_END:
|
||||
endTime = parseTimeExpression(value,
|
||||
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
|
||||
break;
|
||||
case ATTR_DURATION:
|
||||
duration = parseTimeExpression(value,
|
||||
DEFAULT_FRAMERATE, DEFAULT_SUBFRAMERATE, DEFAULT_TICKRATE);
|
||||
break;
|
||||
case ATTR_STYLE:
|
||||
// IDREFS: potentially multiple space delimited ids
|
||||
String[] ids = parseStyleIds(value);
|
||||
if (ids.length > 0) {
|
||||
styleIds = ids;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parent != null && parent.startTimeUs != TtmlNode.UNDEFINED_TIME) {
|
||||
|
|
@ -320,7 +326,7 @@ public final class TtmlParser extends SubtitleParser {
|
|||
}
|
||||
|
||||
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_BODY)
|
||||
|| tag.equals(TtmlNode.TAG_DIV)
|
||||
|
|
@ -334,10 +340,7 @@ public final class TtmlParser extends SubtitleParser {
|
|||
|| tag.equals(TtmlNode.TAG_METADATA)
|
||||
|| tag.equals(TtmlNode.TAG_SMPTE_IMAGE)
|
||||
|| tag.equals(TtmlNode.TAG_SMPTE_DATA)
|
||||
|| tag.equals(TtmlNode.TAG_SMPTE_INFORMATION)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|| tag.equals(TtmlNode.TAG_SMPTE_INFORMATION);
|
||||
}
|
||||
|
||||
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);
|
||||
double offsetSeconds = Double.parseDouble(timeValue);
|
||||
String unit = matcher.group(2);
|
||||
if (unit.equals("h")) {
|
||||
offsetSeconds *= 3600;
|
||||
} else if (unit.equals("m")) {
|
||||
offsetSeconds *= 60;
|
||||
} else if (unit.equals("s")) {
|
||||
// Do nothing.
|
||||
} else if (unit.equals("ms")) {
|
||||
offsetSeconds /= 1000;
|
||||
} else if (unit.equals("f")) {
|
||||
offsetSeconds /= frameRate;
|
||||
} else if (unit.equals("t")) {
|
||||
offsetSeconds /= tickRate;
|
||||
switch (unit) {
|
||||
case "h":
|
||||
offsetSeconds *= 3600;
|
||||
break;
|
||||
case "m":
|
||||
offsetSeconds *= 60;
|
||||
break;
|
||||
case "s":
|
||||
// Do nothing.
|
||||
break;
|
||||
case "ms":
|
||||
offsetSeconds /= 1000;
|
||||
break;
|
||||
case "f":
|
||||
offsetSeconds /= frameRate;
|
||||
break;
|
||||
case "t":
|
||||
offsetSeconds /= tickRate;
|
||||
break;
|
||||
}
|
||||
return (long) (offsetSeconds * C.MICROS_PER_SECOND);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,11 +55,6 @@ public final class TtmlSubtitle implements Subtitle {
|
|||
return eventTimesUs[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastEventTime() {
|
||||
return (eventTimesUs.length == 0 ? -1 : eventTimesUs[eventTimesUs.length - 1]);
|
||||
}
|
||||
|
||||
/* @VisibleForTesting */
|
||||
/* package */ TtmlNode getRoot() {
|
||||
return root;
|
||||
|
|
@ -69,7 +64,7 @@ public final class TtmlSubtitle implements Subtitle {
|
|||
public List<Cue> getCues(long timeUs) {
|
||||
CharSequence cueText = root.getText(timeUs, globalStyles);
|
||||
if (cueText == null) {
|
||||
return Collections.<Cue>emptyList();
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
Cue cue = new Cue(cueText);
|
||||
return Collections.singletonList(cue);
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ import java.util.List;
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastEventTime() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cue> getCues(long timeUs) {
|
||||
return timeUs >= 0 ? cues : Collections.<Cue>emptyList();
|
||||
|
|
|
|||
|
|
@ -286,10 +286,6 @@ import java.util.Map;
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean commentEndsInPosition(byte[] data, int pos) {
|
||||
return data[pos] == '/' && data[pos - 1] == '*';
|
||||
}
|
||||
|
||||
private static String parseIdentifier(ParsableByteArray input, StringBuilder stringBuilder) {
|
||||
stringBuilder.setLength(0);
|
||||
int position = input.getPosition();
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ import java.util.List;
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastEventTime() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cue> getCues(long timeUs) {
|
||||
return timeUs >= 0 ? cues : Collections.<Cue>emptyList();
|
||||
|
|
|
|||
|
|
@ -72,14 +72,6 @@ public final class WebvttSubtitle implements Subtitle {
|
|||
return sortedCueTimesUs[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastEventTime() {
|
||||
if (getEventTimeCount() == 0) {
|
||||
return -1;
|
||||
}
|
||||
return sortedCueTimesUs[sortedCueTimesUs.length - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cue> getCues(long timeUs) {
|
||||
ArrayList<Cue> list = null;
|
||||
|
|
@ -120,7 +112,7 @@ public final class WebvttSubtitle implements Subtitle {
|
|||
if (list != null) {
|
||||
return list;
|
||||
} else {
|
||||
return Collections.<Cue>emptyList();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public final class AssetDataSource implements DataSource {
|
|||
if (bytesRemaining == 0) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
} else {
|
||||
int bytesRead = 0;
|
||||
int bytesRead;
|
||||
try {
|
||||
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
|
||||
: (int) Math.min(bytesRemaining, readLength);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public interface BandwidthMeter extends TransferListener {
|
|||
/**
|
||||
* 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.
|
||||
|
|
@ -40,7 +40,7 @@ public interface BandwidthMeter extends TransferListener {
|
|||
/**
|
||||
* Indicates no bandwidth estimate is available.
|
||||
*/
|
||||
final long NO_ESTIMATE = -1;
|
||||
long NO_ESTIMATE = -1;
|
||||
|
||||
/**
|
||||
* Gets the estimated bandwidth, in bits/sec.
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public final class ContentDataSource implements DataSource {
|
|||
if (bytesRemaining == 0) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
} else {
|
||||
int bytesRead = 0;
|
||||
int bytesRead;
|
||||
try {
|
||||
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
|
||||
: (int) Math.min(bytesRemaining, readLength);
|
||||
|
|
|
|||
|
|
@ -23,21 +23,20 @@ import java.io.IOException;
|
|||
public interface DataSink {
|
||||
|
||||
/**
|
||||
* Opens the {@link DataSink} to consume the specified data. Calls to {@link #open(DataSpec)} and
|
||||
* {@link #close()} must be balanced.
|
||||
* Opens the {@link DataSink} to consume the specified data.
|
||||
*
|
||||
* @param dataSpec Defines the data to be consumed.
|
||||
* @return This {@link DataSink}, for convenience.
|
||||
* @throws IOException
|
||||
*/
|
||||
public DataSink open(DataSpec dataSpec) throws IOException;
|
||||
DataSink open(DataSpec dataSpec) throws IOException;
|
||||
|
||||
/**
|
||||
* Closes the {@link DataSink}.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void close() throws IOException;
|
||||
void close() throws IOException;
|
||||
|
||||
/**
|
||||
* Consumes the provided data.
|
||||
|
|
@ -47,6 +46,6 @@ public interface DataSink {
|
|||
* @param length The length of the data to consume, in bytes.
|
||||
* @throws IOException
|
||||
*/
|
||||
public void write(byte[] buffer, int offset, int length) throws IOException;
|
||||
void write(byte[] buffer, int offset, int length) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,13 +27,11 @@ import java.io.IOException;
|
|||
public interface DataSource {
|
||||
|
||||
/**
|
||||
* Opens the {@link DataSource} to read the specified data. Calls to {@link #open(DataSpec)} and
|
||||
* {@link #close()} must be balanced.
|
||||
* Opens the {@link DataSource} to read the specified data.
|
||||
* <p>
|
||||
* Note: If {@link #open(DataSpec)} throws an {@link IOException}, callers must still call
|
||||
* {@link #close()} to ensure that any partial effects of the {@link #open(DataSpec)} invocation
|
||||
* are cleaned up. Implementations of this class can assume that callers will call
|
||||
* {@link #close()} in this case.
|
||||
* Note: If an {@link IOException} is thrown, callers must still call {@link #close()} to ensure
|
||||
* that any partial effects of the invocation are cleaned up. Implementations of this class can
|
||||
* assume that callers will call {@link #close()} in this case.
|
||||
*
|
||||
* @param dataSpec Defines the data to be read.
|
||||
* @throws IOException If an error occurs opening the source.
|
||||
|
|
|
|||
|
|
@ -339,9 +339,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
|||
if (!allowCrossProtocolRedirects) {
|
||||
// HttpURLConnection disallows cross-protocol redirects, but otherwise performs redirection
|
||||
// automatically. This is the behavior we want, so use it.
|
||||
HttpURLConnection connection = makeConnection(
|
||||
url, postBody, position, length, allowGzip, true /* followRedirects */);
|
||||
return connection;
|
||||
return makeConnection(url, postBody, position, length, allowGzip, true /* followRedirects */);
|
||||
}
|
||||
|
||||
// We need to handle redirects ourselves to allow cross-protocol redirects.
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public final class FileDataSource implements DataSource {
|
|||
if (bytesRemaining == 0) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
} else {
|
||||
int bytesRead = 0;
|
||||
int bytesRead;
|
||||
try {
|
||||
bytesRead = file.read(buffer, offset, (int) Math.min(bytesRemaining, readLength));
|
||||
} catch (IOException e) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public interface HttpDataSource extends DataSource {
|
|||
/**
|
||||
* 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
|
||||
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}.
|
||||
*/
|
||||
public static class HttpDataSourceException extends IOException {
|
||||
class HttpDataSourceException extends IOException {
|
||||
|
||||
/*
|
||||
* The {@link DataSpec} associated with the current connection.
|
||||
|
|
@ -79,7 +79,7 @@ public interface HttpDataSource extends DataSource {
|
|||
/**
|
||||
* Thrown when the content type is invalid.
|
||||
*/
|
||||
public static final class InvalidContentTypeException extends HttpDataSourceException {
|
||||
final class InvalidContentTypeException extends HttpDataSourceException {
|
||||
|
||||
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.
|
||||
*/
|
||||
public static final class InvalidResponseCodeException extends HttpDataSourceException {
|
||||
final class InvalidResponseCodeException extends HttpDataSourceException {
|
||||
|
||||
/**
|
||||
* The response code that was outside of the 2xx range.
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ public final class UdpDataSource implements DataSource {
|
|||
*/
|
||||
public static final class UdpDataSourceException extends IOException {
|
||||
|
||||
public UdpDataSourceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UdpDataSourceException(IOException cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
|
@ -58,8 +54,9 @@ public final class UdpDataSource implements DataSource {
|
|||
public static final int DEAFULT_SOCKET_TIMEOUT_MILLIS = 8 * 1000;
|
||||
|
||||
private final TransferListener listener;
|
||||
private final DatagramPacket packet;
|
||||
private final int socketTimeoutMillis;
|
||||
private final byte[] packetBuffer;
|
||||
private final DatagramPacket packet;
|
||||
|
||||
private Uri uri;
|
||||
private DatagramSocket socket;
|
||||
|
|
@ -68,7 +65,6 @@ public final class UdpDataSource implements DataSource {
|
|||
private InetSocketAddress socketAddress;
|
||||
private boolean opened;
|
||||
|
||||
private byte[] packetBuffer;
|
||||
private int packetRemaining;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public final class UriLoadable<T> implements Loadable {
|
|||
* @throws ParserException If an error occurs parsing the data.
|
||||
* @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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public interface Cache {
|
|||
/**
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -359,9 +359,7 @@ public final class SimpleCache implements Cache {
|
|||
// floorSpan covers the queried region.
|
||||
return true;
|
||||
}
|
||||
Iterator<CacheSpan> iterator = entries.tailSet(floorSpan, false).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CacheSpan next = iterator.next();
|
||||
for (CacheSpan next : entries.tailSet(floorSpan, false)) {
|
||||
if (next.position > currentEndPosition) {
|
||||
// There's a hole in the cache within the queried region.
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ public final class CodecSpecificDataUtil {
|
|||
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.
|
||||
private static final int AUDIO_OBJECT_TYPE_SBR = 5;
|
||||
// Error Resilient Bit-Sliced Arithmetic Coding.
|
||||
|
|
@ -136,33 +134,6 @@ public final class CodecSpecificDataUtil {
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@ public class ManifestFetcher<T> implements Loader.Callback {
|
|||
*/
|
||||
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
|
||||
* continue using the current {@link Uri}.
|
||||
*/
|
||||
public Uri getNextManifestUri();
|
||||
Uri getNextManifestUri();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ public final class UriUtil {
|
|||
int segmentStart = offset;
|
||||
int i = offset;
|
||||
while (i <= limit) {
|
||||
int nextSegmentStart = -1;
|
||||
int nextSegmentStart;
|
||||
if (i == limit) {
|
||||
nextSegmentStart = i;
|
||||
} else if (uri.charAt(i) == '/') {
|
||||
|
|
|
|||
|
|
@ -384,20 +384,6 @@ public final class Util {
|
|||
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.
|
||||
*
|
||||
|
|
@ -876,8 +862,8 @@ public final class Util {
|
|||
* <p>See {@link #escapeFileName(String)} for more information.
|
||||
*
|
||||
* @param fileName File name to be unescaped.
|
||||
* @return The original value of the file name before it was escaped,
|
||||
* or null if the escaped fileName seems invalid.
|
||||
* @return The original value of the file name before it was escaped, or null if the escaped
|
||||
* fileName seems invalid.
|
||||
*/
|
||||
public static String unescapeFileName(String fileName) {
|
||||
int length = fileName.length();
|
||||
|
|
|
|||
Loading…
Reference in a new issue