mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
commit
9f9e432d52
66 changed files with 262 additions and 169 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
org.eclipse.jdt.core.compiler.source=1.6
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ public class SmoothStreamingTestMediaDrmCallback implements MediaDrmCallback {
|
||||||
"http://playready.directtaps.net/pr/svc/rightsmanager.asmx";
|
"http://playready.directtaps.net/pr/svc/rightsmanager.asmx";
|
||||||
private static final Map<String, String> KEY_REQUEST_PROPERTIES;
|
private static final Map<String, String> KEY_REQUEST_PROPERTIES;
|
||||||
static {
|
static {
|
||||||
HashMap<String, String> keyRequestProperties = new HashMap<String, String>();
|
HashMap<String, String> keyRequestProperties = new HashMap<>();
|
||||||
keyRequestProperties.put("Content-Type", "text/xml");
|
keyRequestProperties.put("Content-Type", "text/xml");
|
||||||
keyRequestProperties.put("SOAPAction",
|
keyRequestProperties.put("SOAPAction",
|
||||||
"http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense");
|
"http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense");
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,7 @@ public class DashRendererBuilder implements RendererBuilder,
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
|
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
|
||||||
manifestDataSource = new DefaultUriDataSource(context, userAgent);
|
manifestDataSource = new DefaultUriDataSource(context, userAgent);
|
||||||
manifestFetcher = new ManifestFetcher<MediaPresentationDescription>(url, manifestDataSource,
|
manifestFetcher = new ManifestFetcher<>(url, manifestDataSource, parser);
|
||||||
parser);
|
|
||||||
manifestFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
manifestFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,13 +246,13 @@ public class DashRendererBuilder implements RendererBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the audio chunk sources.
|
// Build the audio chunk sources.
|
||||||
List<ChunkSource> audioChunkSourceList = new ArrayList<ChunkSource>();
|
List<ChunkSource> audioChunkSourceList = new ArrayList<>();
|
||||||
List<String> audioTrackNameList = new ArrayList<String>();
|
List<String> audioTrackNameList = new ArrayList<>();
|
||||||
if (audioAdaptationSet != null) {
|
if (audioAdaptationSet != null) {
|
||||||
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||||
FormatEvaluator audioEvaluator = new FormatEvaluator.FixedEvaluator();
|
FormatEvaluator audioEvaluator = new FormatEvaluator.FixedEvaluator();
|
||||||
List<Representation> audioRepresentations = audioAdaptationSet.representations;
|
List<Representation> audioRepresentations = audioAdaptationSet.representations;
|
||||||
List<String> codecs = new ArrayList<String>();
|
List<String> codecs = new ArrayList<>();
|
||||||
for (int i = 0; i < audioRepresentations.size(); i++) {
|
for (int i = 0; i < audioRepresentations.size(); i++) {
|
||||||
Format format = audioRepresentations.get(i).format;
|
Format format = audioRepresentations.get(i).format;
|
||||||
audioTrackNameList.add(format.id + " (" + format.numChannels + "ch, " +
|
audioTrackNameList.add(format.id + " (" + format.numChannels + "ch, " +
|
||||||
|
|
@ -307,8 +306,8 @@ public class DashRendererBuilder implements RendererBuilder,
|
||||||
// Build the text chunk sources.
|
// Build the text chunk sources.
|
||||||
DataSource textDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
DataSource textDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||||
FormatEvaluator textEvaluator = new FormatEvaluator.FixedEvaluator();
|
FormatEvaluator textEvaluator = new FormatEvaluator.FixedEvaluator();
|
||||||
List<ChunkSource> textChunkSourceList = new ArrayList<ChunkSource>();
|
List<ChunkSource> textChunkSourceList = new ArrayList<>();
|
||||||
List<String> textTrackNameList = new ArrayList<String>();
|
List<String> textTrackNameList = new ArrayList<>();
|
||||||
for (int i = 0; i < period.adaptationSets.size(); i++) {
|
for (int i = 0; i < period.adaptationSets.size(); i++) {
|
||||||
AdaptationSet adaptationSet = period.adaptationSets.get(i);
|
AdaptationSet adaptationSet = period.adaptationSets.get(i);
|
||||||
if (adaptationSet.type == AdaptationSet.TYPE_TEXT) {
|
if (adaptationSet.type == AdaptationSet.TYPE_TEXT) {
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
||||||
player.addListener(this);
|
player.addListener(this);
|
||||||
playerControl = new PlayerControl(player);
|
playerControl = new PlayerControl(player);
|
||||||
mainHandler = new Handler();
|
mainHandler = new Handler();
|
||||||
listeners = new CopyOnWriteArrayList<Listener>();
|
listeners = new CopyOnWriteArrayList<>();
|
||||||
lastReportedPlaybackState = STATE_IDLE;
|
lastReportedPlaybackState = STATE_IDLE;
|
||||||
rendererBuildingState = RENDERER_BUILDING_STATE_IDLE;
|
rendererBuildingState = RENDERER_BUILDING_STATE_IDLE;
|
||||||
selectedTracks = new int[RENDERER_COUNT];
|
selectedTracks = new int[RENDERER_COUNT];
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
HlsPlaylistParser parser = new HlsPlaylistParser();
|
HlsPlaylistParser parser = new HlsPlaylistParser();
|
||||||
ManifestFetcher<HlsPlaylist> playlistFetcher = new ManifestFetcher<HlsPlaylist>(url,
|
ManifestFetcher<HlsPlaylist> playlistFetcher = new ManifestFetcher<>(url,
|
||||||
new DefaultUriDataSource(context, userAgent), parser);
|
new DefaultUriDataSource(context, userAgent), parser);
|
||||||
playlistFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
playlistFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +113,7 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
|
||||||
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
|
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
|
||||||
|
|
||||||
MetadataTrackRenderer<Map<String, Object>> id3Renderer =
|
MetadataTrackRenderer<Map<String, Object>> id3Renderer =
|
||||||
new MetadataTrackRenderer<Map<String, Object>>(sampleSource, new Id3Parser(),
|
new MetadataTrackRenderer<>(sampleSource, new Id3Parser(),
|
||||||
player.getId3MetadataRenderer(), mainHandler.getLooper());
|
player.getId3MetadataRenderer(), mainHandler.getLooper());
|
||||||
|
|
||||||
Eia608TrackRenderer closedCaptionRenderer = new Eia608TrackRenderer(sampleSource, player,
|
Eia608TrackRenderer closedCaptionRenderer = new Eia608TrackRenderer(sampleSource, player,
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
|
||||||
manifestUrl += "/Manifest";
|
manifestUrl += "/Manifest";
|
||||||
}
|
}
|
||||||
SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser();
|
SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser();
|
||||||
manifestFetcher = new ManifestFetcher<SmoothStreamingManifest>(manifestUrl,
|
manifestFetcher = new ManifestFetcher<>(manifestUrl,
|
||||||
new DefaultHttpDataSource(userAgent, null), parser);
|
new DefaultHttpDataSource(userAgent, null), parser);
|
||||||
manifestFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
manifestFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,19 @@ android {
|
||||||
lintOptions {
|
lintOptions {
|
||||||
abortOnError false
|
abortOnError false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
androidTest {
|
||||||
|
assets.srcDirs = ['src/test/assets']
|
||||||
|
java.srcDirs = ['src/test/java']
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
|
||||||
|
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
|
||||||
|
androidTestCompile 'org.mockito:mockito-core:1.9.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
android.libraryVariants.all { variant ->
|
android.libraryVariants.all { variant ->
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
org.eclipse.jdt.core.compiler.source=1.6
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,22 @@ public final class C {
|
||||||
*/
|
*/
|
||||||
public static final int RESULT_END_OF_INPUT = -1;
|
public static final int RESULT_END_OF_INPUT = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A prefix for custom ExoPlayer WebVTT headers.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String WEBVTT_EXO_HEADER = "EXO-HEADER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An element of a custom ExoPlayer WebVTT header. An {@code WEBVTT_OFFSET + value} element can
|
||||||
|
* be added to a custom ExoPlayer WebVTT header to specify an offset time (in microseconds) that
|
||||||
|
* should be subtracted from the embedded MPEGTS value.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String WEBVTT_EXO_HEADER_OFFSET = "OFFSET:";
|
||||||
|
|
||||||
private C() {}
|
private C() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,8 @@ public class DefaultLoadControl implements LoadControl {
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
this.eventHandler = eventHandler;
|
this.eventHandler = eventHandler;
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.loaders = new ArrayList<Object>();
|
this.loaders = new ArrayList<>();
|
||||||
this.loaderStates = new HashMap<Object, LoaderState>();
|
this.loaderStates = new HashMap<>();
|
||||||
this.lowWatermarkUs = lowWatermarkMs * 1000L;
|
this.lowWatermarkUs = lowWatermarkMs * 1000L;
|
||||||
this.highWatermarkUs = highWatermarkMs * 1000L;
|
this.highWatermarkUs = highWatermarkMs * 1000L;
|
||||||
this.lowBufferLoad = lowBufferLoad;
|
this.lowBufferLoad = lowBufferLoad;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
Log.i(TAG, "Init " + ExoPlayerLibraryInfo.VERSION);
|
Log.i(TAG, "Init " + ExoPlayerLibraryInfo.VERSION);
|
||||||
this.playWhenReady = false;
|
this.playWhenReady = false;
|
||||||
this.playbackState = STATE_IDLE;
|
this.playbackState = STATE_IDLE;
|
||||||
this.listeners = new CopyOnWriteArraySet<Listener>();
|
this.listeners = new CopyOnWriteArraySet<>();
|
||||||
this.rendererEnabledFlags = new boolean[rendererCount];
|
this.rendererEnabledFlags = new boolean[rendererCount];
|
||||||
for (int i = 0; i < rendererEnabledFlags.length; i++) {
|
for (int i = 0; i < rendererEnabledFlags.length; i++) {
|
||||||
rendererEnabledFlags[i] = true;
|
rendererEnabledFlags[i] = true;
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ import java.util.List;
|
||||||
this.bufferedPositionUs = TrackRenderer.UNKNOWN_TIME_US;
|
this.bufferedPositionUs = TrackRenderer.UNKNOWN_TIME_US;
|
||||||
|
|
||||||
mediaClock = new MediaClock();
|
mediaClock = new MediaClock();
|
||||||
enabledRenderers = new ArrayList<TrackRenderer>(rendererEnabledFlags.length);
|
enabledRenderers = new ArrayList<>(rendererEnabledFlags.length);
|
||||||
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
||||||
// not normally change to this priority" is incorrect.
|
// not normally change to this priority" is incorrect.
|
||||||
internalPlaybackThread = new PriorityHandlerThread(getClass().getSimpleName() + ":Handler",
|
internalPlaybackThread = new PriorityHandlerThread(getClass().getSimpleName() + ":Handler",
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
||||||
codecCounters = new CodecCounters();
|
codecCounters = new CodecCounters();
|
||||||
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
|
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
|
||||||
formatHolder = new MediaFormatHolder();
|
formatHolder = new MediaFormatHolder();
|
||||||
decodeOnlyPresentationTimestamps = new ArrayList<Long>();
|
decodeOnlyPresentationTimestamps = new ArrayList<>();
|
||||||
outputBufferInfo = new MediaCodec.BufferInfo();
|
outputBufferInfo = new MediaCodec.BufferInfo();
|
||||||
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
|
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
|
||||||
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,7 @@ public class MediaCodecUtil {
|
||||||
|
|
||||||
private static final String TAG = "MediaCodecUtil";
|
private static final String TAG = "MediaCodecUtil";
|
||||||
|
|
||||||
private static final HashMap<CodecKey, Pair<String, CodecCapabilities>> codecs =
|
private static final HashMap<CodecKey, Pair<String, CodecCapabilities>> codecs = new HashMap<>();
|
||||||
new HashMap<CodecKey, Pair<String, CodecCapabilities>>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about the decoder that will be used for a given mime type.
|
* Get information about the decoder that will be used for a given mime type.
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ public class MediaFormat {
|
||||||
channelCount = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_CHANNEL_COUNT);
|
channelCount = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_CHANNEL_COUNT);
|
||||||
sampleRate = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_SAMPLE_RATE);
|
sampleRate = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_SAMPLE_RATE);
|
||||||
pixelWidthHeightRatio = getOptionalFloatV16(format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
|
pixelWidthHeightRatio = getOptionalFloatV16(format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
|
||||||
initializationData = new ArrayList<byte[]>();
|
initializationData = new ArrayList<>();
|
||||||
for (int i = 0; format.containsKey("csd-" + i); i++) {
|
for (int i = 0; format.containsKey("csd-" + i); i++) {
|
||||||
ByteBuffer buffer = format.getByteBuffer("csd-" + i);
|
ByteBuffer buffer = format.getByteBuffer("csd-" + i);
|
||||||
byte[] data = new byte[buffer.limit()];
|
byte[] data = new byte[buffer.limit()];
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
|
||||||
this.eventSourceId = eventSourceId;
|
this.eventSourceId = eventSourceId;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
currentLoadableHolder = new ChunkOperationHolder();
|
currentLoadableHolder = new ChunkOperationHolder();
|
||||||
mediaChunks = new LinkedList<BaseMediaChunk>();
|
mediaChunks = new LinkedList<>();
|
||||||
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
|
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
|
||||||
sampleQueue = new DefaultTrackOutput(loadControl.getAllocator());
|
sampleQueue = new DefaultTrackOutput(loadControl.getAllocator());
|
||||||
state = STATE_UNPREPARED;
|
state = STATE_UNPREPARED;
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ public final class VideoFormatSelectorUtil {
|
||||||
String[] allowedContainerMimeTypes, boolean filterHdFormats, boolean orientationMayChange,
|
String[] allowedContainerMimeTypes, boolean filterHdFormats, boolean orientationMayChange,
|
||||||
int viewportWidth, int viewportHeight) throws DecoderQueryException {
|
int viewportWidth, int viewportHeight) throws DecoderQueryException {
|
||||||
int maxVideoPixelsToRetain = Integer.MAX_VALUE;
|
int maxVideoPixelsToRetain = Integer.MAX_VALUE;
|
||||||
ArrayList<Integer> selectedIndexList = new ArrayList<Integer>();
|
ArrayList<Integer> selectedIndexList = new ArrayList<>();
|
||||||
int maxDecodableFrameSize = MediaCodecUtil.maxH264DecodableFrameSize();
|
int maxDecodableFrameSize = MediaCodecUtil.maxH264DecodableFrameSize();
|
||||||
|
|
||||||
// First pass to filter out formats that individually fail to meet the selection criteria.
|
// First pass to filter out formats that individually fail to meet the selection criteria.
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
package com.google.android.exoplayer.dash;
|
package com.google.android.exoplayer.dash;
|
||||||
|
|
||||||
import com.google.android.exoplayer.BehindLiveWindowException;
|
import com.google.android.exoplayer.BehindLiveWindowException;
|
||||||
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.MediaFormat;
|
import com.google.android.exoplayer.MediaFormat;
|
||||||
import com.google.android.exoplayer.TimeRange;
|
import com.google.android.exoplayer.TimeRange;
|
||||||
import com.google.android.exoplayer.TrackInfo;
|
import com.google.android.exoplayer.TrackInfo;
|
||||||
|
|
@ -43,7 +44,6 @@ import com.google.android.exoplayer.extractor.ChunkIndex;
|
||||||
import com.google.android.exoplayer.extractor.Extractor;
|
import com.google.android.exoplayer.extractor.Extractor;
|
||||||
import com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor;
|
import com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor;
|
||||||
import com.google.android.exoplayer.extractor.webm.WebmExtractor;
|
import com.google.android.exoplayer.extractor.webm.WebmExtractor;
|
||||||
import com.google.android.exoplayer.text.webvtt.WebvttParser;
|
|
||||||
import com.google.android.exoplayer.upstream.DataSource;
|
import com.google.android.exoplayer.upstream.DataSource;
|
||||||
import com.google.android.exoplayer.upstream.DataSpec;
|
import com.google.android.exoplayer.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer.util.Clock;
|
import com.google.android.exoplayer.util.Clock;
|
||||||
|
|
@ -101,7 +101,7 @@ public class DashChunkSource implements ChunkSource {
|
||||||
|
|
||||||
private final TrackInfo trackInfo;
|
private final TrackInfo trackInfo;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final FormatEvaluator evaluator;
|
private final FormatEvaluator formatEvaluator;
|
||||||
private final Evaluation evaluation;
|
private final Evaluation evaluation;
|
||||||
private final Clock systemClock;
|
private final Clock systemClock;
|
||||||
private final StringBuilder headerBuilder;
|
private final StringBuilder headerBuilder;
|
||||||
|
|
@ -117,13 +117,14 @@ public class DashChunkSource implements ChunkSource {
|
||||||
private final int adaptationSetIndex;
|
private final int adaptationSetIndex;
|
||||||
private final int[] representationIndices;
|
private final int[] representationIndices;
|
||||||
|
|
||||||
private DrmInitData drmInitData;
|
|
||||||
private MediaPresentationDescription currentManifest;
|
private MediaPresentationDescription currentManifest;
|
||||||
|
private boolean finishedCurrentManifest;
|
||||||
|
|
||||||
|
private DrmInitData drmInitData;
|
||||||
private TimeRange seekRange;
|
private TimeRange seekRange;
|
||||||
private long[] seekRangeValues;
|
private long[] seekRangeValues;
|
||||||
private int firstAvailableSegmentNum;
|
private int firstAvailableSegmentNum;
|
||||||
private int lastAvailableSegmentNum;
|
private int lastAvailableSegmentNum;
|
||||||
private boolean finishedCurrentManifest;
|
|
||||||
|
|
||||||
private boolean lastChunkWasInitialization;
|
private boolean lastChunkWasInitialization;
|
||||||
private IOException fatalError;
|
private IOException fatalError;
|
||||||
|
|
@ -214,7 +215,7 @@ public class DashChunkSource implements ChunkSource {
|
||||||
this.adaptationSetIndex = adaptationSetIndex;
|
this.adaptationSetIndex = adaptationSetIndex;
|
||||||
this.representationIndices = representationIndices;
|
this.representationIndices = representationIndices;
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.evaluator = formatEvaluator;
|
this.formatEvaluator = formatEvaluator;
|
||||||
this.systemClock = systemClock;
|
this.systemClock = systemClock;
|
||||||
this.liveEdgeLatencyUs = liveEdgeLatencyUs;
|
this.liveEdgeLatencyUs = liveEdgeLatencyUs;
|
||||||
this.elapsedRealtimeOffsetUs = elapsedRealtimeOffsetUs;
|
this.elapsedRealtimeOffsetUs = elapsedRealtimeOffsetUs;
|
||||||
|
|
@ -232,7 +233,7 @@ public class DashChunkSource implements ChunkSource {
|
||||||
this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs);
|
this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs);
|
||||||
|
|
||||||
this.formats = new Format[representations.length];
|
this.formats = new Format[representations.length];
|
||||||
this.representationHolders = new HashMap<String, RepresentationHolder>();
|
this.representationHolders = new HashMap<>();
|
||||||
int maxWidth = 0;
|
int maxWidth = 0;
|
||||||
int maxHeight = 0;
|
int maxHeight = 0;
|
||||||
for (int i = 0; i < representations.length; i++) {
|
for (int i = 0; i < representations.length; i++) {
|
||||||
|
|
@ -268,7 +269,8 @@ public class DashChunkSource implements ChunkSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enable() {
|
public void enable() {
|
||||||
evaluator.enable();
|
fatalError = null;
|
||||||
|
formatEvaluator.enable();
|
||||||
if (manifestFetcher != null) {
|
if (manifestFetcher != null) {
|
||||||
manifestFetcher.enable();
|
manifestFetcher.enable();
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +288,7 @@ public class DashChunkSource implements ChunkSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable(List<? extends MediaChunk> queue) {
|
public void disable(List<? extends MediaChunk> queue) {
|
||||||
evaluator.disable();
|
formatEvaluator.disable();
|
||||||
if (manifestFetcher != null) {
|
if (manifestFetcher != null) {
|
||||||
manifestFetcher.disable();
|
manifestFetcher.disable();
|
||||||
}
|
}
|
||||||
|
|
@ -347,7 +349,7 @@ public class DashChunkSource implements ChunkSource {
|
||||||
|
|
||||||
evaluation.queueSize = queue.size();
|
evaluation.queueSize = queue.size();
|
||||||
if (evaluation.format == null || !lastChunkWasInitialization) {
|
if (evaluation.format == null || !lastChunkWasInitialization) {
|
||||||
evaluator.evaluate(queue, playbackPositionUs, formats, evaluation);
|
formatEvaluator.evaluate(queue, playbackPositionUs, formats, evaluation);
|
||||||
}
|
}
|
||||||
Format selectedFormat = evaluation.format;
|
Format selectedFormat = evaluation.format;
|
||||||
out.queueSize = evaluation.queueSize;
|
out.queueSize = evaluation.queueSize;
|
||||||
|
|
@ -362,6 +364,9 @@ public class DashChunkSource implements ChunkSource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In all cases where we return before instantiating a new chunk, we want out.chunk to be null.
|
||||||
|
out.chunk = null;
|
||||||
|
|
||||||
RepresentationHolder representationHolder = representationHolders.get(selectedFormat.id);
|
RepresentationHolder representationHolder = representationHolders.get(selectedFormat.id);
|
||||||
Representation selectedRepresentation = representationHolder.representation;
|
Representation selectedRepresentation = representationHolder.representation;
|
||||||
DashSegmentIndex segmentIndex = representationHolder.segmentIndex;
|
DashSegmentIndex segmentIndex = representationHolder.segmentIndex;
|
||||||
|
|
@ -426,7 +431,7 @@ public class DashChunkSource implements ChunkSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segmentNum == -1) {
|
if (segmentNum == -1) {
|
||||||
out.chunk = null;
|
// We've reached the end of the stream.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -566,8 +571,9 @@ public class DashChunkSource implements ChunkSource {
|
||||||
if (representationHolder.vttHeaderOffsetUs != presentationTimeOffsetUs) {
|
if (representationHolder.vttHeaderOffsetUs != presentationTimeOffsetUs) {
|
||||||
// Update the VTT header.
|
// Update the VTT header.
|
||||||
headerBuilder.setLength(0);
|
headerBuilder.setLength(0);
|
||||||
headerBuilder.append(WebvttParser.EXO_HEADER).append("=")
|
headerBuilder.append(C.WEBVTT_EXO_HEADER).append("=")
|
||||||
.append(WebvttParser.OFFSET).append(presentationTimeOffsetUs).append("\n");
|
.append(C.WEBVTT_EXO_HEADER_OFFSET).append(presentationTimeOffsetUs)
|
||||||
|
.append("\n");
|
||||||
representationHolder.vttHeader = headerBuilder.toString().getBytes();
|
representationHolder.vttHeader = headerBuilder.toString().getBytes();
|
||||||
representationHolder.vttHeaderOffsetUs = presentationTimeOffsetUs;
|
representationHolder.vttHeaderOffsetUs = presentationTimeOffsetUs;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
: -1;
|
: -1;
|
||||||
UtcTimingElement utcTiming = null;
|
UtcTimingElement utcTiming = null;
|
||||||
|
|
||||||
List<Period> periods = new ArrayList<Period>();
|
List<Period> periods = new ArrayList<>();
|
||||||
do {
|
do {
|
||||||
xpp.next();
|
xpp.next();
|
||||||
if (isStartTag(xpp, "BaseURL")) {
|
if (isStartTag(xpp, "BaseURL")) {
|
||||||
|
|
@ -152,7 +152,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
long startMs = parseDuration(xpp, "start", 0);
|
long startMs = parseDuration(xpp, "start", 0);
|
||||||
long durationMs = parseDuration(xpp, "duration", mpdDurationMs);
|
long durationMs = parseDuration(xpp, "duration", mpdDurationMs);
|
||||||
SegmentBase segmentBase = null;
|
SegmentBase segmentBase = null;
|
||||||
List<AdaptationSet> adaptationSets = new ArrayList<AdaptationSet>();
|
List<AdaptationSet> adaptationSets = new ArrayList<>();
|
||||||
do {
|
do {
|
||||||
xpp.next();
|
xpp.next();
|
||||||
if (isStartTag(xpp, "BaseURL")) {
|
if (isStartTag(xpp, "BaseURL")) {
|
||||||
|
|
@ -188,7 +188,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
|
|
||||||
int id = -1;
|
int id = -1;
|
||||||
ContentProtectionsBuilder contentProtectionsBuilder = new ContentProtectionsBuilder();
|
ContentProtectionsBuilder contentProtectionsBuilder = new ContentProtectionsBuilder();
|
||||||
List<Representation> representations = new ArrayList<Representation>();
|
List<Representation> representations = new ArrayList<>();
|
||||||
do {
|
do {
|
||||||
xpp.next();
|
xpp.next();
|
||||||
if (isStartTag(xpp, "BaseURL")) {
|
if (isStartTag(xpp, "BaseURL")) {
|
||||||
|
|
@ -432,7 +432,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
timeline = parseSegmentTimeline(xpp);
|
timeline = parseSegmentTimeline(xpp);
|
||||||
} else if (isStartTag(xpp, "SegmentURL")) {
|
} else if (isStartTag(xpp, "SegmentURL")) {
|
||||||
if (segments == null) {
|
if (segments == null) {
|
||||||
segments = new ArrayList<RangedUri>();
|
segments = new ArrayList<>();
|
||||||
}
|
}
|
||||||
segments.add(parseSegmentUrl(xpp, baseUrl));
|
segments.add(parseSegmentUrl(xpp, baseUrl));
|
||||||
}
|
}
|
||||||
|
|
@ -499,7 +499,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
|
|
||||||
protected List<SegmentTimelineElement> parseSegmentTimeline(XmlPullParser xpp)
|
protected List<SegmentTimelineElement> parseSegmentTimeline(XmlPullParser xpp)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
List<SegmentTimelineElement> segmentTimeline = new ArrayList<SegmentTimelineElement>();
|
List<SegmentTimelineElement> segmentTimeline = new ArrayList<>();
|
||||||
long elapsedTime = 0;
|
long elapsedTime = 0;
|
||||||
do {
|
do {
|
||||||
xpp.next();
|
xpp.next();
|
||||||
|
|
@ -642,7 +642,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
*/
|
*/
|
||||||
public void addAdaptationSetProtection(ContentProtection contentProtection) {
|
public void addAdaptationSetProtection(ContentProtection contentProtection) {
|
||||||
if (adaptationSetProtections == null) {
|
if (adaptationSetProtections == null) {
|
||||||
adaptationSetProtections = new ArrayList<ContentProtection>();
|
adaptationSetProtections = new ArrayList<>();
|
||||||
}
|
}
|
||||||
maybeAddContentProtection(adaptationSetProtections, contentProtection);
|
maybeAddContentProtection(adaptationSetProtections, contentProtection);
|
||||||
}
|
}
|
||||||
|
|
@ -654,7 +654,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||||
*/
|
*/
|
||||||
public void addRepresentationProtection(ContentProtection contentProtection) {
|
public void addRepresentationProtection(ContentProtection contentProtection) {
|
||||||
if (currentRepresentationProtections == null) {
|
if (currentRepresentationProtections == null) {
|
||||||
currentRepresentationProtections = new ArrayList<ContentProtection>();
|
currentRepresentationProtections = new ArrayList<>();
|
||||||
}
|
}
|
||||||
maybeAddContentProtection(currentRepresentationProtections, contentProtection);
|
maybeAddContentProtection(currentRepresentationProtections, contentProtection);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ public class UtcTimingElementResolver implements Loader.Callback {
|
||||||
|
|
||||||
private void resolveHttp(UriLoadable.Parser<Long> parser) {
|
private void resolveHttp(UriLoadable.Parser<Long> parser) {
|
||||||
singleUseLoader = new Loader("utctiming");
|
singleUseLoader = new Loader("utctiming");
|
||||||
singleUseLoadable = new UriLoadable<Long>(timingElement.value, uriDataSource, parser);
|
singleUseLoadable = new UriLoadable<>(timingElement.value, uriDataSource, parser);
|
||||||
singleUseLoader.startLoading(singleUseLoadable, this);
|
singleUseLoader.startLoading(singleUseLoadable, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public abstract class DrmInitData {
|
||||||
|
|
||||||
public Mapped(String mimeType) {
|
public Mapped(String mimeType) {
|
||||||
super(mimeType);
|
super(mimeType);
|
||||||
schemeData = new HashMap<UUID, byte[]>();
|
schemeData = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
||||||
EventListener eventListener) throws UnsupportedSchemeException {
|
EventListener eventListener) throws UnsupportedSchemeException {
|
||||||
HashMap<String, String> optionalKeyRequestParameters;
|
HashMap<String, String> optionalKeyRequestParameters;
|
||||||
if (!TextUtils.isEmpty(customData)) {
|
if (!TextUtils.isEmpty(customData)) {
|
||||||
optionalKeyRequestParameters = new HashMap<String, String>();
|
optionalKeyRequestParameters = new HashMap<>();
|
||||||
optionalKeyRequestParameters.put(PLAYREADY_CUSTOM_DATA_KEY, customData);
|
optionalKeyRequestParameters.put(PLAYREADY_CUSTOM_DATA_KEY, customData);
|
||||||
} else {
|
} else {
|
||||||
optionalKeyRequestParameters = null;
|
optionalKeyRequestParameters = null;
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ public class ExtractorSampleSource implements SampleSource, ExtractorOutput, Loa
|
||||||
this.remainingReleaseCount = downstreamRendererCount;
|
this.remainingReleaseCount = downstreamRendererCount;
|
||||||
this.requestedBufferSize = requestedBufferSize;
|
this.requestedBufferSize = requestedBufferSize;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
sampleQueues = new SparseArray<InternalTrackOutput>();
|
sampleQueues = new SparseArray<>();
|
||||||
allocator = new DefaultAllocator(BUFFER_FRAGMENT_LENGTH);
|
allocator = new DefaultAllocator(BUFFER_FRAGMENT_LENGTH);
|
||||||
pendingResetPositionUs = NO_RESET_PENDING;
|
pendingResetPositionUs = NO_RESET_PENDING;
|
||||||
frameAccurateSeeking = true;
|
frameAccurateSeeking = true;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ import java.util.concurrent.LinkedBlockingDeque;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
allocationLength = allocator.getIndividualAllocationLength();
|
allocationLength = allocator.getIndividualAllocationLength();
|
||||||
infoQueue = new InfoQueue();
|
infoQueue = new InfoQueue();
|
||||||
dataQueue = new LinkedBlockingDeque<Allocation>();
|
dataQueue = new LinkedBlockingDeque<>();
|
||||||
extrasHolder = new SampleExtrasHolder();
|
extrasHolder = new SampleExtrasHolder();
|
||||||
scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE);
|
scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE);
|
||||||
lastAllocationOffset = allocationLength;
|
lastAllocationOffset = allocationLength;
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,8 @@ import java.util.List;
|
||||||
public ContainerAtom(int type, long endByteOffset) {
|
public ContainerAtom(int type, long endByteOffset) {
|
||||||
super(type);
|
super(type);
|
||||||
|
|
||||||
leafChildren = new ArrayList<LeafAtom>();
|
leafChildren = new ArrayList<>();
|
||||||
containerChildren = new ArrayList<ContainerAtom>();
|
containerChildren = new ArrayList<>();
|
||||||
this.endByteOffset = endByteOffset;
|
this.endByteOffset = endByteOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ import java.util.List;
|
||||||
if (nalUnitLengthFieldLength == 3) {
|
if (nalUnitLengthFieldLength == 3) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
List<byte[]> initializationData = new ArrayList<byte[]>();
|
List<byte[]> initializationData = new ArrayList<>();
|
||||||
// TODO: We should try and parse these using CodecSpecificDataUtil.parseSpsNalUnit, and
|
// TODO: We should try and parse these using CodecSpecificDataUtil.parseSpsNalUnit, and
|
||||||
// expose the AVC profile and level somewhere useful; Most likely in MediaFormat.
|
// expose the AVC profile and level somewhere useful; Most likely in MediaFormat.
|
||||||
int numSequenceParameterSets = parent.readUnsignedByte() & 0x1F;
|
int numSequenceParameterSets = parent.readUnsignedByte() & 0x1F;
|
||||||
|
|
@ -472,7 +472,7 @@ import java.util.List;
|
||||||
int height = parent.readUnsignedShort();
|
int height = parent.readUnsignedShort();
|
||||||
parent.skipBytes(50);
|
parent.skipBytes(50);
|
||||||
|
|
||||||
List<byte[]> initializationData = new ArrayList<byte[]>(1);
|
List<byte[]> initializationData = new ArrayList<>(1);
|
||||||
int childPosition = parent.getPosition();
|
int childPosition = parent.getPosition();
|
||||||
while (childPosition - position < size) {
|
while (childPosition - position < size) {
|
||||||
parent.setPosition(childPosition);
|
parent.setPosition(childPosition);
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public final class FragmentedMp4Extractor implements Extractor {
|
||||||
nalLength = new ParsableByteArray(4);
|
nalLength = new ParsableByteArray(4);
|
||||||
encryptionSignalByte = new ParsableByteArray(1);
|
encryptionSignalByte = new ParsableByteArray(1);
|
||||||
extendedTypeScratch = new byte[16];
|
extendedTypeScratch = new byte[16];
|
||||||
containerAtoms = new Stack<ContainerAtom>();
|
containerAtoms = new Stack<>();
|
||||||
fragmentRun = new TrackFragment();
|
fragmentRun = new TrackFragment();
|
||||||
parserState = STATE_READING_ATOM_HEADER;
|
parserState = STATE_READING_ATOM_HEADER;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
||||||
|
|
||||||
public Mp4Extractor() {
|
public Mp4Extractor() {
|
||||||
atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE);
|
atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE);
|
||||||
containerAtoms = new Stack<Atom.ContainerAtom>();
|
containerAtoms = new Stack<>();
|
||||||
nalStartCode = new ParsableByteArray(H264Util.NAL_START_CODE);
|
nalStartCode = new ParsableByteArray(H264Util.NAL_START_CODE);
|
||||||
nalLength = new ParsableByteArray(4);
|
nalLength = new ParsableByteArray(4);
|
||||||
parserState = STATE_READING_ATOM_HEADER;
|
parserState = STATE_READING_ATOM_HEADER;
|
||||||
|
|
@ -216,7 +216,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
||||||
|
|
||||||
/** Updates the stored track metadata to reflect the contents of the specified moov atom. */
|
/** Updates the stored track metadata to reflect the contents of the specified moov atom. */
|
||||||
private void processMoovAtom(ContainerAtom moov) {
|
private void processMoovAtom(ContainerAtom moov) {
|
||||||
List<Mp4Track> tracks = new ArrayList<Mp4Track>();
|
List<Mp4Track> tracks = new ArrayList<>();
|
||||||
long earliestSampleOffset = Long.MAX_VALUE;
|
long earliestSampleOffset = Long.MAX_VALUE;
|
||||||
for (int i = 0; i < moov.containerChildren.size(); i++) {
|
for (int i = 0; i < moov.containerChildren.size(); i++) {
|
||||||
Atom.ContainerAtom atom = moov.containerChildren.get(i);
|
Atom.ContainerAtom atom = moov.containerChildren.get(i);
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,7 @@ import java.util.List;
|
||||||
byte[] ppsData = new byte[pps.nalLength];
|
byte[] ppsData = new byte[pps.nalLength];
|
||||||
System.arraycopy(sps.nalData, 0, spsData, 0, sps.nalLength);
|
System.arraycopy(sps.nalData, 0, spsData, 0, sps.nalLength);
|
||||||
System.arraycopy(pps.nalData, 0, ppsData, 0, pps.nalLength);
|
System.arraycopy(pps.nalData, 0, ppsData, 0, pps.nalLength);
|
||||||
List<byte[]> initializationData = new ArrayList<byte[]>();
|
List<byte[]> initializationData = new ArrayList<>();
|
||||||
initializationData.add(spsData);
|
initializationData.add(spsData);
|
||||||
initializationData.add(ppsData);
|
initializationData.add(ppsData);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ public final class TsExtractor implements Extractor, SeekMap {
|
||||||
tsPacketBuffer = new ParsableByteArray(TS_PACKET_SIZE);
|
tsPacketBuffer = new ParsableByteArray(TS_PACKET_SIZE);
|
||||||
streamTypes = new SparseBooleanArray();
|
streamTypes = new SparseBooleanArray();
|
||||||
allowedPassthroughStreamTypes = getPassthroughStreamTypes(audioCapabilities);
|
allowedPassthroughStreamTypes = getPassthroughStreamTypes(audioCapabilities);
|
||||||
tsPayloadReaders = new SparseArray<TsPayloadReader>();
|
tsPayloadReaders = new SparseArray<>();
|
||||||
tsPayloadReaders.put(TS_PAT_PID, new PatReader());
|
tsPayloadReaders.put(TS_PAT_PID, new PatReader());
|
||||||
lastPts = Long.MIN_VALUE;
|
lastPts = Long.MIN_VALUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ import java.util.Stack;
|
||||||
private static final int VALID_FLOAT64_ELEMENT_SIZE_BYTES = 8;
|
private static final int VALID_FLOAT64_ELEMENT_SIZE_BYTES = 8;
|
||||||
|
|
||||||
private final byte[] scratch = new byte[8];
|
private final byte[] scratch = new byte[8];
|
||||||
private final Stack<MasterElement> masterElementsStack = new Stack<MasterElement>();
|
private final Stack<MasterElement> masterElementsStack = new Stack<>();
|
||||||
private final VarintReader varintReader = new VarintReader();
|
private final VarintReader varintReader = new VarintReader();
|
||||||
|
|
||||||
private EbmlReaderOutput output;
|
private EbmlReaderOutput output;
|
||||||
|
|
|
||||||
|
|
@ -665,7 +665,7 @@ public final class WebmExtractor implements Extractor {
|
||||||
durationUs, audioTrackFormat.channelCount, audioTrackFormat.sampleRate,
|
durationUs, audioTrackFormat.channelCount, audioTrackFormat.sampleRate,
|
||||||
parseVorbisCodecPrivate());
|
parseVorbisCodecPrivate());
|
||||||
} else if (audioTrackFormat != null && CODEC_ID_OPUS.equals(audioTrackFormat.codecId)) {
|
} else if (audioTrackFormat != null && CODEC_ID_OPUS.equals(audioTrackFormat.codecId)) {
|
||||||
ArrayList<byte[]> opusInitializationData = new ArrayList<byte[]>(3);
|
ArrayList<byte[]> opusInitializationData = new ArrayList<>(3);
|
||||||
opusInitializationData.add(audioTrackFormat.codecPrivate);
|
opusInitializationData.add(audioTrackFormat.codecPrivate);
|
||||||
opusInitializationData.add(
|
opusInitializationData.add(
|
||||||
ByteBuffer.allocate(Long.SIZE).putLong(audioTrackFormat.codecDelayNs).array());
|
ByteBuffer.allocate(Long.SIZE).putLong(audioTrackFormat.codecDelayNs).array());
|
||||||
|
|
@ -757,7 +757,7 @@ public final class WebmExtractor implements Extractor {
|
||||||
}
|
}
|
||||||
byte[] vorbisBooks = new byte[codecPrivate.length - offset];
|
byte[] vorbisBooks = new byte[codecPrivate.length - offset];
|
||||||
System.arraycopy(codecPrivate, offset, vorbisBooks, 0, codecPrivate.length - offset);
|
System.arraycopy(codecPrivate, offset, vorbisBooks, 0, codecPrivate.length - offset);
|
||||||
ArrayList<byte[]> initializationData = new ArrayList<byte[]>(2);
|
ArrayList<byte[]> initializationData = new ArrayList<>(2);
|
||||||
initializationData.add(vorbisInfo);
|
initializationData.add(vorbisInfo);
|
||||||
initializationData.add(vorbisBooks);
|
initializationData.add(vorbisBooks);
|
||||||
return initializationData;
|
return initializationData;
|
||||||
|
|
|
||||||
|
|
@ -516,7 +516,7 @@ public class HlsChunkSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Format[] buildEnabledFormats(List<Variant> variants, int[] variantIndices) {
|
private static Format[] buildEnabledFormats(List<Variant> variants, int[] variantIndices) {
|
||||||
ArrayList<Variant> enabledVariants = new ArrayList<Variant>();
|
ArrayList<Variant> enabledVariants = new ArrayList<>();
|
||||||
if (variantIndices != null) {
|
if (variantIndices != null) {
|
||||||
for (int i = 0; i < variantIndices.length; i++) {
|
for (int i = 0; i < variantIndices.length; i++) {
|
||||||
enabledVariants.add(variants.get(variantIndices[i]));
|
enabledVariants.add(variants.get(variantIndices[i]));
|
||||||
|
|
@ -526,8 +526,8 @@ public class HlsChunkSource {
|
||||||
enabledVariants.addAll(variants);
|
enabledVariants.addAll(variants);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Variant> definiteVideoVariants = new ArrayList<Variant>();
|
ArrayList<Variant> definiteVideoVariants = new ArrayList<>();
|
||||||
ArrayList<Variant> definiteAudioOnlyVariants = new ArrayList<Variant>();
|
ArrayList<Variant> definiteAudioOnlyVariants = new ArrayList<>();
|
||||||
for (int i = 0; i < enabledVariants.size(); i++) {
|
for (int i = 0; i < enabledVariants.size(); i++) {
|
||||||
Variant variant = enabledVariants.get(i);
|
Variant variant = enabledVariants.get(i);
|
||||||
if (variant.format.height > 0 || variantHasExplicitCodecWithPrefix(variant, "avc")) {
|
if (variant.format.height > 0 || variantHasExplicitCodecWithPrefix(variant, "avc")) {
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
|
||||||
this.startTimeUs = startTimeUs;
|
this.startTimeUs = startTimeUs;
|
||||||
this.extractor = extractor;
|
this.extractor = extractor;
|
||||||
this.shouldSpliceIn = shouldSpliceIn;
|
this.shouldSpliceIn = shouldSpliceIn;
|
||||||
sampleQueues = new SparseArray<DefaultTrackOutput>();
|
sampleQueues = new SparseArray<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -70,7 +70,7 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
|
||||||
*/
|
*/
|
||||||
public void init(Allocator allocator) {
|
public void init(Allocator allocator) {
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
this.extractor.init(this);
|
extractor.init(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
|
||||||
public HlsPlaylist parse(String connectionUrl, InputStream inputStream)
|
public HlsPlaylist parse(String connectionUrl, InputStream inputStream)
|
||||||
throws IOException, ParserException {
|
throws IOException, ParserException {
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
Queue<String> extraLines = new LinkedList<String>();
|
Queue<String> extraLines = new LinkedList<>();
|
||||||
String line;
|
String line;
|
||||||
try {
|
try {
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
|
|
@ -137,8 +137,8 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
|
||||||
|
|
||||||
private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, String baseUri)
|
private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, String baseUri)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ArrayList<Variant> variants = new ArrayList<Variant>();
|
ArrayList<Variant> variants = new ArrayList<>();
|
||||||
ArrayList<Subtitle> subtitles = new ArrayList<Subtitle>();
|
ArrayList<Subtitle> subtitles = new ArrayList<>();
|
||||||
int bitrate = 0;
|
int bitrate = 0;
|
||||||
String codecs = null;
|
String codecs = null;
|
||||||
int width = -1;
|
int width = -1;
|
||||||
|
|
@ -202,7 +202,7 @@ public final class HlsPlaylistParser implements UriLoadable.Parser<HlsPlaylist>
|
||||||
int targetDurationSecs = 0;
|
int targetDurationSecs = 0;
|
||||||
int version = 1; // Default version == 1.
|
int version = 1; // Default version == 1.
|
||||||
boolean live = true;
|
boolean live = true;
|
||||||
List<Segment> segments = new ArrayList<Segment>();
|
List<Segment> segments = new ArrayList<>();
|
||||||
|
|
||||||
double segmentDurationSecs = 0.0;
|
double segmentDurationSecs = 0.0;
|
||||||
boolean segmentDiscontinuity = false;
|
boolean segmentDiscontinuity = false;
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback {
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.eventSourceId = eventSourceId;
|
this.eventSourceId = eventSourceId;
|
||||||
this.pendingResetPositionUs = NO_RESET_PENDING;
|
this.pendingResetPositionUs = NO_RESET_PENDING;
|
||||||
extractors = new LinkedList<HlsExtractorWrapper>();
|
extractors = new LinkedList<>();
|
||||||
allocator = new DefaultAllocator(BUFFER_FRAGMENT_LENGTH);
|
allocator = new DefaultAllocator(BUFFER_FRAGMENT_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public class Id3Parser implements MetadataParser<Map<String, Object>> {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> parse(byte[] data, int size)
|
public Map<String, Object> parse(byte[] data, int size)
|
||||||
throws UnsupportedEncodingException, ParserException {
|
throws UnsupportedEncodingException, ParserException {
|
||||||
Map<String, Object> metadata = new HashMap<String, Object>();
|
Map<String, Object> metadata = new HashMap<>();
|
||||||
ParsableByteArray id3Data = new ParsableByteArray(data, size);
|
ParsableByteArray id3Data = new ParsableByteArray(data, size);
|
||||||
int id3Size = parseId3Header(id3Data);
|
int id3Size = parseId3Header(id3Data);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,14 +59,11 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000;
|
private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000;
|
||||||
private static final int INITIALIZATION_VECTOR_SIZE = 8;
|
private static final int INITIALIZATION_VECTOR_SIZE = 8;
|
||||||
|
|
||||||
private final ManifestFetcher<SmoothStreamingManifest> manifestFetcher;
|
|
||||||
private final int streamElementIndex;
|
|
||||||
private final TrackInfo trackInfo;
|
private final TrackInfo trackInfo;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final FormatEvaluator formatEvaluator;
|
private final FormatEvaluator formatEvaluator;
|
||||||
private final Evaluation evaluation;
|
private final Evaluation evaluation;
|
||||||
private final long liveEdgeLatencyUs;
|
private final long liveEdgeLatencyUs;
|
||||||
|
|
||||||
private final int maxWidth;
|
private final int maxWidth;
|
||||||
private final int maxHeight;
|
private final int maxHeight;
|
||||||
|
|
||||||
|
|
@ -75,6 +72,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
private final DrmInitData drmInitData;
|
private final DrmInitData drmInitData;
|
||||||
private final Format[] formats;
|
private final Format[] formats;
|
||||||
|
|
||||||
|
private final ManifestFetcher<SmoothStreamingManifest> manifestFetcher;
|
||||||
|
private final int streamElementIndex;
|
||||||
|
|
||||||
private SmoothStreamingManifest currentManifest;
|
private SmoothStreamingManifest currentManifest;
|
||||||
private int currentManifestChunkOffset;
|
private int currentManifestChunkOffset;
|
||||||
private boolean finishedCurrentManifest;
|
private boolean finishedCurrentManifest;
|
||||||
|
|
@ -153,8 +153,8 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
|
|
||||||
int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length;
|
int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length;
|
||||||
formats = new Format[trackCount];
|
formats = new Format[trackCount];
|
||||||
extractorWrappers = new SparseArray<ChunkExtractorWrapper>();
|
extractorWrappers = new SparseArray<>();
|
||||||
mediaFormats = new SparseArray<MediaFormat>();
|
mediaFormats = new SparseArray<>();
|
||||||
int maxWidth = 0;
|
int maxWidth = 0;
|
||||||
int maxHeight = 0;
|
int maxHeight = 0;
|
||||||
for (int i = 0; i < trackCount; i++) {
|
for (int i = 0; i < trackCount; i++) {
|
||||||
|
|
@ -174,8 +174,8 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
extractorWrappers.put(trackIndex, new ChunkExtractorWrapper(extractor));
|
extractorWrappers.put(trackIndex, new ChunkExtractorWrapper(extractor));
|
||||||
mediaFormats.put(trackIndex, mediaFormat);
|
mediaFormats.put(trackIndex, mediaFormat);
|
||||||
}
|
}
|
||||||
this.maxHeight = maxHeight;
|
|
||||||
this.maxWidth = maxWidth;
|
this.maxWidth = maxWidth;
|
||||||
|
this.maxHeight = maxHeight;
|
||||||
Arrays.sort(formats, new DecreasingBandwidthComparator());
|
Arrays.sort(formats, new DecreasingBandwidthComparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,6 +194,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
@Override
|
@Override
|
||||||
public void enable() {
|
public void enable() {
|
||||||
fatalError = null;
|
fatalError = null;
|
||||||
|
formatEvaluator.enable();
|
||||||
if (manifestFetcher != null) {
|
if (manifestFetcher != null) {
|
||||||
manifestFetcher.enable();
|
manifestFetcher.enable();
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +202,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable(List<? extends MediaChunk> queue) {
|
public void disable(List<? extends MediaChunk> queue) {
|
||||||
|
formatEvaluator.disable();
|
||||||
if (manifestFetcher != null) {
|
if (manifestFetcher != null) {
|
||||||
manifestFetcher.disable();
|
manifestFetcher.disable();
|
||||||
}
|
}
|
||||||
|
|
@ -248,14 +250,13 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
out.chunk = null;
|
out.chunk = null;
|
||||||
return;
|
return;
|
||||||
} else if (out.queueSize == queue.size() && out.chunk != null
|
} else if (out.queueSize == queue.size() && out.chunk != null
|
||||||
&& out.chunk.format.equals(evaluation.format)) {
|
&& out.chunk.format.equals(selectedFormat)) {
|
||||||
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
// We already have a chunk, and the evaluation hasn't changed either the format or the size
|
||||||
// of the queue. Do nothing.
|
// of the queue. Leave unchanged.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In all cases where we return before instantiating a new chunk at the bottom of this method,
|
// In all cases where we return before instantiating a new chunk, we want out.chunk to be null.
|
||||||
// we want out.chunk to be null.
|
|
||||||
out.chunk = null;
|
out.chunk = null;
|
||||||
|
|
||||||
StreamElement streamElement = getElement(currentManifest);
|
StreamElement streamElement = getElement(currentManifest);
|
||||||
|
|
@ -290,7 +291,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
|
||||||
// but continue to return the final chunk.
|
// but continue to return the final chunk.
|
||||||
finishedCurrentManifest = true;
|
finishedCurrentManifest = true;
|
||||||
}
|
}
|
||||||
} else if (chunkIndex == -1) {
|
}
|
||||||
|
|
||||||
|
if (chunkIndex == -1) {
|
||||||
// We've reached the end of the stream.
|
// We've reached the end of the stream.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.baseUri = baseUri;
|
this.baseUri = baseUri;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.normalizedAttributes = new LinkedList<Pair<String, Object>>();
|
this.normalizedAttributes = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Object parse(XmlPullParser xmlParser) throws XmlPullParserException, IOException,
|
public final Object parse(XmlPullParser xmlParser) throws XmlPullParserException, IOException,
|
||||||
|
|
@ -343,7 +343,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
lookAheadCount = -1;
|
lookAheadCount = -1;
|
||||||
protectionElement = null;
|
protectionElement = null;
|
||||||
streamElements = new LinkedList<StreamElement>();
|
streamElements = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -473,7 +473,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
||||||
public StreamElementParser(ElementParser parent, String baseUri) {
|
public StreamElementParser(ElementParser parent, String baseUri) {
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
this.baseUri = baseUri;
|
this.baseUri = baseUri;
|
||||||
tracks = new LinkedList<TrackElement>();
|
tracks = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -539,7 +539,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
||||||
if (timescale == -1) {
|
if (timescale == -1) {
|
||||||
timescale = (Long) getNormalizedAttribute(KEY_TIME_SCALE);
|
timescale = (Long) getNormalizedAttribute(KEY_TIME_SCALE);
|
||||||
}
|
}
|
||||||
startTimes = new ArrayList<Long>();
|
startTimes = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int parseType(XmlPullParser parser) throws ParserException {
|
private int parseType(XmlPullParser parser) throws ParserException {
|
||||||
|
|
@ -602,7 +602,7 @@ public class SmoothStreamingManifestParser implements UriLoadable.Parser<SmoothS
|
||||||
|
|
||||||
public TrackElementParser(ElementParser parent, String baseUri) {
|
public TrackElementParser(ElementParser parent, String baseUri) {
|
||||||
super(parent, baseUri, TAG);
|
super(parent, baseUri, TAG);
|
||||||
this.csd = new LinkedList<byte[]>();
|
this.csd = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ public final class SubtitleLayout extends ViewGroup {
|
||||||
|
|
||||||
public SubtitleLayout(Context context, AttributeSet attrs) {
|
public SubtitleLayout(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
subtitleViews = new ArrayList<SubtitleView>();
|
subtitleViews = new ArrayList<>();
|
||||||
fontScale = 1;
|
fontScale = 1;
|
||||||
captionStyle = CaptionStyleCompat.DEFAULT;
|
captionStyle = CaptionStyleCompat.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ public class Eia608Parser {
|
||||||
/* package */ Eia608Parser() {
|
/* package */ Eia608Parser() {
|
||||||
seiBuffer = new ParsableBitArray();
|
seiBuffer = new ParsableBitArray();
|
||||||
stringBuilder = new StringBuilder();
|
stringBuilder = new StringBuilder();
|
||||||
captions = new ArrayList<ClosedCaption>();
|
captions = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ boolean canParse(String mimeType) {
|
/* package */ boolean canParse(String mimeType) {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ public class Eia608TrackRenderer extends TrackRenderer implements Callback {
|
||||||
formatHolder = new MediaFormatHolder();
|
formatHolder = new MediaFormatHolder();
|
||||||
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
|
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||||
captionStringBuilder = new StringBuilder();
|
captionStringBuilder = new StringBuilder();
|
||||||
pendingCaptionLists = new TreeSet<ClosedCaptionList>();
|
pendingCaptionLists = new TreeSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -230,8 +230,11 @@ public class Eia608TrackRenderer extends TrackRenderer implements Callback {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeRendererInternal(String cueText) {
|
private void invokeRendererInternal(String cueText) {
|
||||||
Cue cue = new Cue(cueText);
|
if (cueText == null) {
|
||||||
textRenderer.onCues(Collections.singletonList(cue));
|
textRenderer.onCues(Collections.<Cue>emptyList());
|
||||||
|
} else {
|
||||||
|
textRenderer.onCues(Collections.singletonList(new Cue(cueText)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeParsePendingSample() {
|
private void maybeParsePendingSample() {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ import java.util.TreeSet;
|
||||||
|
|
||||||
public void addChild(TtmlNode child) {
|
public void addChild(TtmlNode child) {
|
||||||
if (children == null) {
|
if (children == null) {
|
||||||
children = new ArrayList<TtmlNode>();
|
children = new ArrayList<>();
|
||||||
}
|
}
|
||||||
children.add(child);
|
children.add(child);
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +93,7 @@ import java.util.TreeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long[] getEventTimesUs() {
|
public long[] getEventTimesUs() {
|
||||||
TreeSet<Long> eventTimeSet = new TreeSet<Long>();
|
TreeSet<Long> eventTimeSet = new TreeSet<>();
|
||||||
getEventTimes(eventTimeSet, false);
|
getEventTimes(eventTimeSet, false);
|
||||||
long[] eventTimes = new long[eventTimeSet.size()];
|
long[] eventTimes = new long[eventTimeSet.size()];
|
||||||
Iterator<Long> eventTimeIterator = eventTimeSet.iterator();
|
Iterator<Long> eventTimeIterator = eventTimeSet.iterator();
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ public class TtmlParser implements SubtitleParser {
|
||||||
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
XmlPullParser xmlParser = xmlParserFactory.newPullParser();
|
||||||
xmlParser.setInput(inputStream, inputEncoding);
|
xmlParser.setInput(inputStream, inputEncoding);
|
||||||
TtmlSubtitle ttmlSubtitle = null;
|
TtmlSubtitle ttmlSubtitle = null;
|
||||||
LinkedList<TtmlNode> nodeStack = new LinkedList<TtmlNode>();
|
LinkedList<TtmlNode> nodeStack = new LinkedList<>();
|
||||||
int unsupportedNodeDepth = 0;
|
int unsupportedNodeDepth = 0;
|
||||||
int eventType = xmlParser.getEventType();
|
int eventType = xmlParser.getEventType();
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||||
|
|
|
||||||
|
|
@ -40,22 +40,7 @@ import java.util.regex.Pattern;
|
||||||
*/
|
*/
|
||||||
public class WebvttParser implements SubtitleParser {
|
public class WebvttParser implements SubtitleParser {
|
||||||
|
|
||||||
static final String TAG = "WebvttParser";
|
private static final String TAG = "WebvttParser";
|
||||||
|
|
||||||
/**
|
|
||||||
* This parser allows a custom header to be prepended to the WebVTT data, in the form of a text
|
|
||||||
* line starting with this string.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final String EXO_HEADER = "EXO-HEADER";
|
|
||||||
/**
|
|
||||||
* A {@code OFFSET + value} element can be added to the custom header to specify an offset time
|
|
||||||
* (in microseconds) that should be subtracted from the embedded MPEGTS value.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static final String OFFSET = "OFFSET:";
|
|
||||||
|
|
||||||
private static final long SAMPLING_RATE = 90;
|
private static final long SAMPLING_RATE = 90;
|
||||||
|
|
||||||
|
|
@ -73,7 +58,8 @@ public class WebvttParser implements SubtitleParser {
|
||||||
private static final String WEBVTT_CUE_SETTING_STRING = "\\S*:\\S*";
|
private static final String WEBVTT_CUE_SETTING_STRING = "\\S*:\\S*";
|
||||||
private static final Pattern WEBVTT_CUE_SETTING = Pattern.compile(WEBVTT_CUE_SETTING_STRING);
|
private static final Pattern WEBVTT_CUE_SETTING = Pattern.compile(WEBVTT_CUE_SETTING_STRING);
|
||||||
|
|
||||||
private static final Pattern MEDIA_TIMESTAMP_OFFSET = Pattern.compile(OFFSET + "\\d+");
|
private static final Pattern MEDIA_TIMESTAMP_OFFSET =
|
||||||
|
Pattern.compile(C.WEBVTT_EXO_HEADER_OFFSET + "\\d+");
|
||||||
private static final Pattern MEDIA_TIMESTAMP = Pattern.compile("MPEGTS:\\d+");
|
private static final Pattern MEDIA_TIMESTAMP = Pattern.compile("MPEGTS:\\d+");
|
||||||
|
|
||||||
private static final String NON_NUMERIC_STRING = ".*[^0-9].*";
|
private static final String NON_NUMERIC_STRING = ".*[^0-9].*";
|
||||||
|
|
@ -95,7 +81,7 @@ public class WebvttParser implements SubtitleParser {
|
||||||
@Override
|
@Override
|
||||||
public WebvttSubtitle parse(InputStream inputStream, String inputEncoding, long startTimeUs)
|
public WebvttSubtitle parse(InputStream inputStream, String inputEncoding, long startTimeUs)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ArrayList<WebvttCue> subtitles = new ArrayList<WebvttCue>();
|
ArrayList<WebvttCue> subtitles = new ArrayList<>();
|
||||||
long mediaTimestampUs = startTimeUs;
|
long mediaTimestampUs = startTimeUs;
|
||||||
long mediaTimestampOffsetUs = 0;
|
long mediaTimestampOffsetUs = 0;
|
||||||
|
|
||||||
|
|
@ -108,7 +94,7 @@ public class WebvttParser implements SubtitleParser {
|
||||||
throw new ParserException("Expected WEBVTT or EXO-HEADER. Got null");
|
throw new ParserException("Expected WEBVTT or EXO-HEADER. Got null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.startsWith(EXO_HEADER)) {
|
if (line.startsWith(C.WEBVTT_EXO_HEADER)) {
|
||||||
// parse the timestamp offset, if present
|
// parse the timestamp offset, if present
|
||||||
Matcher matcher = MEDIA_TIMESTAMP_OFFSET.matcher(line);
|
Matcher matcher = MEDIA_TIMESTAMP_OFFSET.matcher(line);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ public class WebvttSubtitle implements Subtitle {
|
||||||
for (int i = 0; i < numCues; i++) {
|
for (int i = 0; i < numCues; i++) {
|
||||||
if ((cueTimesUs[i * 2] <= timeUs) && (timeUs < cueTimesUs[i * 2 + 1])) {
|
if ((cueTimesUs[i * 2] <= timeUs) && (timeUs < cueTimesUs[i * 2 + 1])) {
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new ArrayList<Cue>();
|
list = new ArrayList<>();
|
||||||
}
|
}
|
||||||
WebvttCue cue = cues.get(i);
|
WebvttCue cue = cues.get(i);
|
||||||
if (cue.isNormalCue()) {
|
if (cue.isNormalCue()) {
|
||||||
|
|
|
||||||
|
|
@ -25,41 +25,72 @@ import java.util.Arrays;
|
||||||
*/
|
*/
|
||||||
public final class DefaultAllocator implements Allocator {
|
public final class DefaultAllocator implements Allocator {
|
||||||
|
|
||||||
private static final int INITIAL_RECYCLED_ALLOCATION_CAPACITY = 100;
|
private static final int AVAILABLE_EXTRA_CAPACITY = 100;
|
||||||
|
|
||||||
private final int individualAllocationSize;
|
private final int individualAllocationSize;
|
||||||
|
private final byte[] initialAllocationBlock;
|
||||||
|
|
||||||
private int allocatedCount;
|
private int allocatedCount;
|
||||||
private int recycledCount;
|
private int availableCount;
|
||||||
private Allocation[] recycledAllocations;
|
private Allocation[] availableAllocations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an empty pool.
|
* Constructs an initially empty pool.
|
||||||
*
|
*
|
||||||
* @param individualAllocationSize The length of each individual allocation.
|
* @param individualAllocationSize The length of each individual allocation.
|
||||||
*/
|
*/
|
||||||
public DefaultAllocator(int individualAllocationSize) {
|
public DefaultAllocator(int individualAllocationSize) {
|
||||||
|
this(individualAllocationSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a pool with some {@link Allocation}s created up front.
|
||||||
|
* <p>
|
||||||
|
* Note: Initial {@link Allocation}s will never be discarded by {@link #trim(int)}.
|
||||||
|
*
|
||||||
|
* @param individualAllocationSize The length of each individual allocation.
|
||||||
|
* @param initialAllocationCount The number of allocations to create up front.
|
||||||
|
*/
|
||||||
|
public DefaultAllocator(int individualAllocationSize, int initialAllocationCount) {
|
||||||
Assertions.checkArgument(individualAllocationSize > 0);
|
Assertions.checkArgument(individualAllocationSize > 0);
|
||||||
|
Assertions.checkArgument(initialAllocationCount >= 0);
|
||||||
this.individualAllocationSize = individualAllocationSize;
|
this.individualAllocationSize = individualAllocationSize;
|
||||||
this.recycledAllocations = new Allocation[INITIAL_RECYCLED_ALLOCATION_CAPACITY];
|
this.availableCount = initialAllocationCount;
|
||||||
|
this.availableAllocations = new Allocation[initialAllocationCount + AVAILABLE_EXTRA_CAPACITY];
|
||||||
|
if (initialAllocationCount > 0) {
|
||||||
|
initialAllocationBlock = new byte[initialAllocationCount * individualAllocationSize];
|
||||||
|
for (int i = 0; i < initialAllocationCount; i++) {
|
||||||
|
int allocationOffset = i * individualAllocationSize;
|
||||||
|
availableAllocations[i] = new Allocation(initialAllocationBlock, allocationOffset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
initialAllocationBlock = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Allocation allocate() {
|
public synchronized Allocation allocate() {
|
||||||
allocatedCount++;
|
allocatedCount++;
|
||||||
return recycledCount > 0 ? recycledAllocations[--recycledCount]
|
Allocation allocation;
|
||||||
: new Allocation(new byte[individualAllocationSize], 0);
|
if (availableCount > 0) {
|
||||||
|
allocation = availableAllocations[--availableCount];
|
||||||
|
availableAllocations[availableCount] = null;
|
||||||
|
} else {
|
||||||
|
allocation = new Allocation(new byte[individualAllocationSize], 0);
|
||||||
|
}
|
||||||
|
return allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void release(Allocation allocation) {
|
public synchronized void release(Allocation allocation) {
|
||||||
// Weak sanity check that the allocation probably originated from this pool.
|
// Weak sanity check that the allocation probably originated from this pool.
|
||||||
Assertions.checkArgument(allocation.data.length == individualAllocationSize);
|
Assertions.checkArgument(allocation.data == initialAllocationBlock
|
||||||
|
|| allocation.data.length == individualAllocationSize);
|
||||||
allocatedCount--;
|
allocatedCount--;
|
||||||
if (recycledCount == recycledAllocations.length) {
|
if (availableCount == availableAllocations.length) {
|
||||||
recycledAllocations = Arrays.copyOf(recycledAllocations, recycledAllocations.length * 2);
|
availableAllocations = Arrays.copyOf(availableAllocations, availableAllocations.length * 2);
|
||||||
}
|
}
|
||||||
recycledAllocations[recycledCount++] = allocation;
|
availableAllocations[availableCount++] = allocation;
|
||||||
// Wake up threads waiting for the allocated size to drop.
|
// Wake up threads waiting for the allocated size to drop.
|
||||||
notifyAll();
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
|
@ -67,11 +98,43 @@ public final class DefaultAllocator implements Allocator {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void trim(int targetSize) {
|
public synchronized void trim(int targetSize) {
|
||||||
int targetAllocationCount = Util.ceilDivide(targetSize, individualAllocationSize);
|
int targetAllocationCount = Util.ceilDivide(targetSize, individualAllocationSize);
|
||||||
int targetRecycledAllocationCount = Math.max(0, targetAllocationCount - allocatedCount);
|
int targetAvailableCount = Math.max(0, targetAllocationCount - allocatedCount);
|
||||||
if (targetRecycledAllocationCount < recycledCount) {
|
if (targetAvailableCount >= availableCount) {
|
||||||
Arrays.fill(recycledAllocations, targetRecycledAllocationCount, recycledCount, null);
|
// We're already at or below the target.
|
||||||
recycledCount = targetRecycledAllocationCount;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initialAllocationBlock != null) {
|
||||||
|
// Some allocations are backed by an initial block. We need to make sure that we hold onto all
|
||||||
|
// such allocations. Re-order the available allocations so that the ones backed by the initial
|
||||||
|
// block come first.
|
||||||
|
int lowIndex = 0;
|
||||||
|
int highIndex = availableCount - 1;
|
||||||
|
while (lowIndex <= highIndex) {
|
||||||
|
Allocation lowAllocation = availableAllocations[lowIndex];
|
||||||
|
if (lowAllocation.data == initialAllocationBlock) {
|
||||||
|
lowIndex++;
|
||||||
|
} else {
|
||||||
|
Allocation highAllocation = availableAllocations[lowIndex];
|
||||||
|
if (highAllocation.data != initialAllocationBlock) {
|
||||||
|
highIndex--;
|
||||||
|
} else {
|
||||||
|
availableAllocations[lowIndex++] = highAllocation;
|
||||||
|
availableAllocations[highIndex--] = lowAllocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// lowIndex is the index of the first allocation not backed by an initial block.
|
||||||
|
targetAvailableCount = Math.max(targetAvailableCount, lowIndex);
|
||||||
|
if (targetAvailableCount >= availableCount) {
|
||||||
|
// We're already at or below the target.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard allocations beyond the target.
|
||||||
|
Arrays.fill(availableAllocations, targetAvailableCount, availableCount, null);
|
||||||
|
availableCount = targetAvailableCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||||
private static final String TAG = "HttpDataSource";
|
private static final String TAG = "HttpDataSource";
|
||||||
private static final Pattern CONTENT_RANGE_HEADER =
|
private static final Pattern CONTENT_RANGE_HEADER =
|
||||||
Pattern.compile("^bytes (\\d+)-(\\d+)/(\\d+)$");
|
Pattern.compile("^bytes (\\d+)-(\\d+)/(\\d+)$");
|
||||||
private static final AtomicReference<byte[]> skipBufferReference = new AtomicReference<byte[]>();
|
private static final AtomicReference<byte[]> skipBufferReference = new AtomicReference<>();
|
||||||
|
|
||||||
private final boolean allowCrossProtocolRedirects;
|
private final boolean allowCrossProtocolRedirects;
|
||||||
private final int connectTimeoutMillis;
|
private final int connectTimeoutMillis;
|
||||||
|
|
@ -141,7 +141,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
||||||
this.userAgent = Assertions.checkNotEmpty(userAgent);
|
this.userAgent = Assertions.checkNotEmpty(userAgent);
|
||||||
this.contentTypePredicate = contentTypePredicate;
|
this.contentTypePredicate = contentTypePredicate;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.requestProperties = new HashMap<String, String>();
|
this.requestProperties = new HashMap<>();
|
||||||
this.connectTimeoutMillis = connectTimeoutMillis;
|
this.connectTimeoutMillis = connectTimeoutMillis;
|
||||||
this.readTimeoutMillis = readTimeoutMillis;
|
this.readTimeoutMillis = readTimeoutMillis;
|
||||||
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
|
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ public final class NetworkLock {
|
||||||
private int highestPriority;
|
private int highestPriority;
|
||||||
|
|
||||||
private NetworkLock() {
|
private NetworkLock() {
|
||||||
queue = new PriorityQueue<Integer>();
|
queue = new PriorityQueue<>();
|
||||||
highestPriority = Integer.MAX_VALUE;
|
highestPriority = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,8 @@ public final class CacheSpan implements Comparable<CacheSpan> {
|
||||||
return new CacheSpan(key, position, file.length(), true, lastAccessTimestamp, file);
|
return new CacheSpan(key, position, file.length(), true, lastAccessTimestamp, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CacheSpan(String key, long position, long length, boolean isCached,
|
// Visible for testing.
|
||||||
|
CacheSpan(String key, long position, long length, boolean isCached,
|
||||||
long lastAccessTimestamp, File file) {
|
long lastAccessTimestamp, File file) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public class LeastRecentlyUsedCacheEvictor implements CacheEvictor, Comparator<C
|
||||||
|
|
||||||
public LeastRecentlyUsedCacheEvictor(long maxBytes) {
|
public LeastRecentlyUsedCacheEvictor(long maxBytes) {
|
||||||
this.maxBytes = maxBytes;
|
this.maxBytes = maxBytes;
|
||||||
this.leastRecentlyUsed = new TreeSet<CacheSpan>(this);
|
this.leastRecentlyUsed = new TreeSet<>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,9 @@ public class SimpleCache implements Cache {
|
||||||
public SimpleCache(File cacheDir, CacheEvictor evictor) {
|
public SimpleCache(File cacheDir, CacheEvictor evictor) {
|
||||||
this.cacheDir = cacheDir;
|
this.cacheDir = cacheDir;
|
||||||
this.evictor = evictor;
|
this.evictor = evictor;
|
||||||
this.lockedSpans = new HashMap<String, CacheSpan>();
|
this.lockedSpans = new HashMap<>();
|
||||||
this.cachedSpans = new HashMap<String, TreeSet<CacheSpan>>();
|
this.cachedSpans = new HashMap<>();
|
||||||
this.listeners = new HashMap<String, ArrayList<Listener>>();
|
this.listeners = new HashMap<>();
|
||||||
// Start cache initialization.
|
// Start cache initialization.
|
||||||
final ConditionVariable conditionVariable = new ConditionVariable();
|
final ConditionVariable conditionVariable = new ConditionVariable();
|
||||||
new Thread() {
|
new Thread() {
|
||||||
|
|
@ -71,7 +71,7 @@ public class SimpleCache implements Cache {
|
||||||
public synchronized NavigableSet<CacheSpan> addListener(String key, Listener listener) {
|
public synchronized NavigableSet<CacheSpan> addListener(String key, Listener listener) {
|
||||||
ArrayList<Listener> listenersForKey = listeners.get(key);
|
ArrayList<Listener> listenersForKey = listeners.get(key);
|
||||||
if (listenersForKey == null) {
|
if (listenersForKey == null) {
|
||||||
listenersForKey = new ArrayList<Listener>();
|
listenersForKey = new ArrayList<>();
|
||||||
listeners.put(key, listenersForKey);
|
listeners.put(key, listenersForKey);
|
||||||
}
|
}
|
||||||
listenersForKey.add(listener);
|
listenersForKey.add(listener);
|
||||||
|
|
@ -92,12 +92,12 @@ public class SimpleCache implements Cache {
|
||||||
@Override
|
@Override
|
||||||
public synchronized NavigableSet<CacheSpan> getCachedSpans(String key) {
|
public synchronized NavigableSet<CacheSpan> getCachedSpans(String key) {
|
||||||
TreeSet<CacheSpan> spansForKey = cachedSpans.get(key);
|
TreeSet<CacheSpan> spansForKey = cachedSpans.get(key);
|
||||||
return spansForKey == null ? null : new TreeSet<CacheSpan>(spansForKey);
|
return spansForKey == null ? null : new TreeSet<>(spansForKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Set<String> getKeys() {
|
public synchronized Set<String> getKeys() {
|
||||||
return new HashSet<String>(cachedSpans.keySet());
|
return new HashSet<>(cachedSpans.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -263,7 +263,7 @@ public class SimpleCache implements Cache {
|
||||||
private void addSpan(CacheSpan span) {
|
private void addSpan(CacheSpan span) {
|
||||||
TreeSet<CacheSpan> spansForKey = cachedSpans.get(span.key);
|
TreeSet<CacheSpan> spansForKey = cachedSpans.get(span.key);
|
||||||
if (spansForKey == null) {
|
if (spansForKey == null) {
|
||||||
spansForKey = new TreeSet<CacheSpan>();
|
spansForKey = new TreeSet<>();
|
||||||
cachedSpans.put(span.key, spansForKey);
|
cachedSpans.put(span.key, spansForKey);
|
||||||
}
|
}
|
||||||
spansForKey.add(span);
|
spansForKey.add(span);
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ public final class CodecSpecificDataUtil {
|
||||||
// data does not consist of NAL start code delimited units.
|
// data does not consist of NAL start code delimited units.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<Integer> starts = new ArrayList<Integer>();
|
List<Integer> starts = new ArrayList<>();
|
||||||
int nalUnitIndex = 0;
|
int nalUnitIndex = 0;
|
||||||
do {
|
do {
|
||||||
starts.add(nalUnitIndex);
|
starts.add(nalUnitIndex);
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
|
||||||
*/
|
*/
|
||||||
public void singleLoad(Looper callbackLooper, final ManifestCallback<T> callback) {
|
public void singleLoad(Looper callbackLooper, final ManifestCallback<T> callback) {
|
||||||
SingleFetchHelper fetchHelper = new SingleFetchHelper(
|
SingleFetchHelper fetchHelper = new SingleFetchHelper(
|
||||||
new UriLoadable<T>(manifestUrl, uriDataSource, parser), callbackLooper, callback);
|
new UriLoadable<>(manifestUrl, uriDataSource, parser), callbackLooper, callback);
|
||||||
fetchHelper.startLoading();
|
fetchHelper.startLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ public class ManifestFetcher<T> implements Loader.Callback {
|
||||||
loader = new Loader("manifestLoader");
|
loader = new Loader("manifestLoader");
|
||||||
}
|
}
|
||||||
if (!loader.isLoading()) {
|
if (!loader.isLoading()) {
|
||||||
currentLoadable = new UriLoadable<T>(manifestUrl, uriDataSource, parser);
|
currentLoadable = new UriLoadable<>(manifestUrl, uriDataSource, parser);
|
||||||
loader.startLoading(currentLoadable, this);
|
loader.startLoading(currentLoadable, this);
|
||||||
notifyManifestRefreshStarted();
|
notifyManifestRefreshStarted();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ public class SlidingPercentile {
|
||||||
public SlidingPercentile(int maxWeight) {
|
public SlidingPercentile(int maxWeight) {
|
||||||
this.maxWeight = maxWeight;
|
this.maxWeight = maxWeight;
|
||||||
recycledSamples = new Sample[MAX_RECYCLED_SAMPLES];
|
recycledSamples = new Sample[MAX_RECYCLED_SAMPLES];
|
||||||
samples = new ArrayList<Sample>();
|
samples = new ArrayList<>();
|
||||||
currentSortOrder = SORT_ORDER_NONE;
|
currentSortOrder = SORT_ORDER_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,5 @@
|
||||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/ExoPlayerDemo"/>
|
|
||||||
<classpathentry kind="output" path="bin/classes"/>
|
<classpathentry kind="output" path="bin/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
||||||
4
library/src/test/.settings/org.eclipse.jdt.core.prefs
Normal file
4
library/src/test/.settings/org.eclipse.jdt.core.prefs
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.7
|
||||||
|
|
@ -15,16 +15,19 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.google.android.exoplayer.tests">
|
package="com.google.android.exoplayer.tests">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="22"/>
|
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="22"/>
|
||||||
|
|
||||||
<application>
|
<application android:debuggable="true"
|
||||||
|
android:allowBackup="false"
|
||||||
|
tools:ignore="MissingApplicationIcon,HardcodedDebugMode">
|
||||||
<uses-library android:name="android.test.runner"/>
|
<uses-library android:name="android.test.runner"/>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<instrumentation
|
<instrumentation
|
||||||
android:targetPackage="com.google.android.exoplayer.demo"
|
android:targetPackage="com.google.android.exoplayer.tests"
|
||||||
android:name="android.test.InstrumentationTestRunner"/>
|
android:name="android.test.InstrumentationTestRunner"/>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public class MediaFormatTest extends TestCase {
|
||||||
|
|
||||||
byte[] initData1 = new byte[] {1, 2, 3};
|
byte[] initData1 = new byte[] {1, 2, 3};
|
||||||
byte[] initData2 = new byte[] {4, 5, 6};
|
byte[] initData2 = new byte[] {4, 5, 6};
|
||||||
List<byte[]> initData = new ArrayList<byte[]>();
|
List<byte[]> initData = new ArrayList<>();
|
||||||
initData.add(initData1);
|
initData.add(initData1);
|
||||||
initData.add(initData2);
|
initData.add(initData2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription generateVodMpd() {
|
private static MediaPresentationDescription generateVodMpd() {
|
||||||
List<Representation> representations = new ArrayList<Representation>();
|
List<Representation> representations = new ArrayList<>();
|
||||||
|
|
||||||
SingleSegmentBase segmentBase1 = new SingleSegmentBase("https://example.com/1.mp4");
|
SingleSegmentBase segmentBase1 = new SingleSegmentBase("https://example.com/1.mp4");
|
||||||
Representation representation1 =
|
Representation representation1 =
|
||||||
|
|
@ -399,10 +399,10 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaPresentationDescription generateLiveMpdWithTimeline(long startTime) {
|
private static MediaPresentationDescription generateLiveMpdWithTimeline(long startTime) {
|
||||||
List<Representation> representations = new ArrayList<Representation>();
|
List<Representation> representations = new ArrayList<>();
|
||||||
|
|
||||||
List<SegmentTimelineElement> segmentTimeline = new ArrayList<SegmentTimelineElement>();
|
List<SegmentTimelineElement> segmentTimeline = new ArrayList<>();
|
||||||
List<RangedUri> mediaSegments = new ArrayList<RangedUri>();
|
List<RangedUri> mediaSegments = new ArrayList<>();
|
||||||
long byteStart = 0;
|
long byteStart = 0;
|
||||||
for (int i = 0; i < LIVE_SEGMENT_COUNT; i++) {
|
for (int i = 0; i < LIVE_SEGMENT_COUNT; i++) {
|
||||||
segmentTimeline.add(new SegmentTimelineElement(startTime, LIVE_SEGMENT_DURATION_MS));
|
segmentTimeline.add(new SegmentTimelineElement(startTime, LIVE_SEGMENT_DURATION_MS));
|
||||||
|
|
@ -423,7 +423,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
||||||
|
|
||||||
private static MediaPresentationDescription generateLiveMpdWithTemplate(
|
private static MediaPresentationDescription generateLiveMpdWithTemplate(
|
||||||
boolean limitTimeshiftBuffer) {
|
boolean limitTimeshiftBuffer) {
|
||||||
List<Representation> representations = new ArrayList<Representation>();
|
List<Representation> representations = new ArrayList<>();
|
||||||
|
|
||||||
UrlTemplate initializationTemplate = null;
|
UrlTemplate initializationTemplate = null;
|
||||||
UrlTemplate mediaTemplate = UrlTemplate.compile("$RepresentationID$/$Number$");
|
UrlTemplate mediaTemplate = UrlTemplate.compile("$RepresentationID$/$Number$");
|
||||||
|
|
@ -464,7 +464,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
||||||
long seekPositionMs, long seekRangeStartMs, long seekRangeEndMs, long chunkStartTimeMs,
|
long seekPositionMs, long seekRangeStartMs, long seekRangeEndMs, long chunkStartTimeMs,
|
||||||
long chunkEndTimeMs) {
|
long chunkEndTimeMs) {
|
||||||
DashChunkSource chunkSource = setupLiveEdgeTimelineTest(startTimeMs, liveEdgeLatencyMs);
|
DashChunkSource chunkSource = setupLiveEdgeTimelineTest(startTimeMs, liveEdgeLatencyMs);
|
||||||
List<MediaChunk> queue = new ArrayList<MediaChunk>();
|
List<MediaChunk> queue = new ArrayList<>();
|
||||||
ChunkOperationHolder out = new ChunkOperationHolder();
|
ChunkOperationHolder out = new ChunkOperationHolder();
|
||||||
chunkSource.getChunkOperation(queue, seekPositionMs * 1000, 0, out);
|
chunkSource.getChunkOperation(queue, seekPositionMs * 1000, 0, out);
|
||||||
TimeRange seekRange = chunkSource.getSeekRange();
|
TimeRange seekRange = chunkSource.getSeekRange();
|
||||||
|
|
@ -482,7 +482,7 @@ public class DashChunkSourceTest extends InstrumentationTestCase {
|
||||||
long chunkEndTimeMs, boolean limitTimeshiftBuffer) {
|
long chunkEndTimeMs, boolean limitTimeshiftBuffer) {
|
||||||
DashChunkSource chunkSource = setupLiveEdgeTemplateTest(startTimeMs, liveEdgeLatencyMs,
|
DashChunkSource chunkSource = setupLiveEdgeTemplateTest(startTimeMs, liveEdgeLatencyMs,
|
||||||
limitTimeshiftBuffer);
|
limitTimeshiftBuffer);
|
||||||
List<MediaChunk> queue = new ArrayList<MediaChunk>();
|
List<MediaChunk> queue = new ArrayList<>();
|
||||||
ChunkOperationHolder out = new ChunkOperationHolder();
|
ChunkOperationHolder out = new ChunkOperationHolder();
|
||||||
chunkSource.getChunkOperation(queue, seekPositionMs * 1000, 0, out);
|
chunkSource.getChunkOperation(queue, seekPositionMs * 1000, 0, out);
|
||||||
TimeRange seekRange = chunkSource.getSeekRange();
|
TimeRange seekRange = chunkSource.getSeekRange();
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ public class Mp4ExtractorTest extends TestCase {
|
||||||
|
|
||||||
private static byte[] getStsc() {
|
private static byte[] getStsc() {
|
||||||
int samplesPerChunk = -1;
|
int samplesPerChunk = -1;
|
||||||
List<Integer> samplesInChunkChangeIndices = new ArrayList<Integer>();
|
List<Integer> samplesInChunkChangeIndices = new ArrayList<>();
|
||||||
for (int i = 0; i < SAMPLES_IN_CHUNK.length; i++) {
|
for (int i = 0; i < SAMPLES_IN_CHUNK.length; i++) {
|
||||||
if (SAMPLES_IN_CHUNK[i] != samplesPerChunk) {
|
if (SAMPLES_IN_CHUNK[i] != samplesPerChunk) {
|
||||||
samplesInChunkChangeIndices.add(i);
|
samplesInChunkChangeIndices.add(i);
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ public class DefaultEbmlReaderTest extends TestCase {
|
||||||
private static final int ID_DURATION = 0x4489;
|
private static final int ID_DURATION = 0x4489;
|
||||||
private static final int ID_SIMPLE_BLOCK = 0xA3;
|
private static final int ID_SIMPLE_BLOCK = 0xA3;
|
||||||
|
|
||||||
private final List<String> events = new ArrayList<String>();
|
private final List<String> events = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getElementType(int id) {
|
public int getElementType(int id) {
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ public final class FakeDataSource implements DataSource {
|
||||||
private boolean simulateUnknownLength;
|
private boolean simulateUnknownLength;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
segments = new ArrayList<Segment>();
|
segments = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ public class WebvttSubtitleTest extends TestCase {
|
||||||
|
|
||||||
private WebvttSubtitle emptySubtitle = new WebvttSubtitle(new ArrayList<WebvttCue>(), 0);
|
private WebvttSubtitle emptySubtitle = new WebvttSubtitle(new ArrayList<WebvttCue>(), 0);
|
||||||
|
|
||||||
private ArrayList<WebvttCue> simpleSubtitleCues = new ArrayList<WebvttCue>();
|
private ArrayList<WebvttCue> simpleSubtitleCues = new ArrayList<>();
|
||||||
{
|
{
|
||||||
WebvttCue firstCue = new WebvttCue(1000000, 2000000, FIRST_SUBTITLE_STRING);
|
WebvttCue firstCue = new WebvttCue(1000000, 2000000, FIRST_SUBTITLE_STRING);
|
||||||
simpleSubtitleCues.add(firstCue);
|
simpleSubtitleCues.add(firstCue);
|
||||||
|
|
@ -44,7 +44,7 @@ public class WebvttSubtitleTest extends TestCase {
|
||||||
}
|
}
|
||||||
private WebvttSubtitle simpleSubtitle = new WebvttSubtitle(simpleSubtitleCues, 0);
|
private WebvttSubtitle simpleSubtitle = new WebvttSubtitle(simpleSubtitleCues, 0);
|
||||||
|
|
||||||
private ArrayList<WebvttCue> overlappingSubtitleCues = new ArrayList<WebvttCue>();
|
private ArrayList<WebvttCue> overlappingSubtitleCues = new ArrayList<>();
|
||||||
{
|
{
|
||||||
WebvttCue firstCue = new WebvttCue(1000000, 3000000, FIRST_SUBTITLE_STRING);
|
WebvttCue firstCue = new WebvttCue(1000000, 3000000, FIRST_SUBTITLE_STRING);
|
||||||
overlappingSubtitleCues.add(firstCue);
|
overlappingSubtitleCues.add(firstCue);
|
||||||
|
|
@ -54,7 +54,7 @@ public class WebvttSubtitleTest extends TestCase {
|
||||||
}
|
}
|
||||||
private WebvttSubtitle overlappingSubtitle = new WebvttSubtitle(overlappingSubtitleCues, 0);
|
private WebvttSubtitle overlappingSubtitle = new WebvttSubtitle(overlappingSubtitleCues, 0);
|
||||||
|
|
||||||
private ArrayList<WebvttCue> nestedSubtitleCues = new ArrayList<WebvttCue>();
|
private ArrayList<WebvttCue> nestedSubtitleCues = new ArrayList<>();
|
||||||
{
|
{
|
||||||
WebvttCue firstCue = new WebvttCue(1000000, 4000000, FIRST_SUBTITLE_STRING);
|
WebvttCue firstCue = new WebvttCue(1000000, 4000000, FIRST_SUBTITLE_STRING);
|
||||||
nestedSubtitleCues.add(firstCue);
|
nestedSubtitleCues.add(firstCue);
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ public class UtilTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListBinarySearchFloor() {
|
public void testListBinarySearchFloor() {
|
||||||
List<Integer> values = new ArrayList<Integer>();
|
List<Integer> values = new ArrayList<>();
|
||||||
assertEquals(-1, Util.binarySearchFloor(values, 0, false, false));
|
assertEquals(-1, Util.binarySearchFloor(values, 0, false, false));
|
||||||
assertEquals(0, Util.binarySearchFloor(values, 0, false, true));
|
assertEquals(0, Util.binarySearchFloor(values, 0, false, true));
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ public class UtilTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListBinarySearchCeil() {
|
public void testListBinarySearchCeil() {
|
||||||
List<Integer> values = new ArrayList<Integer>();
|
List<Integer> values = new ArrayList<>();
|
||||||
assertEquals(0, Util.binarySearchCeil(values, 0, false, false));
|
assertEquals(0, Util.binarySearchCeil(values, 0, false, false));
|
||||||
assertEquals(-1, Util.binarySearchCeil(values, 0, false, true));
|
assertEquals(-1, Util.binarySearchCeil(values, 0, false, true));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,4 @@
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-22
|
target=android-22
|
||||||
|
android.library.reference.1=../main
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue