mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Make SampleSources reusable and implement SampleSourceProvider.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=126888556
This commit is contained in:
parent
42d78b3559
commit
af3452d231
15 changed files with 354 additions and 273 deletions
|
|
@ -30,18 +30,24 @@ import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
|
||||||
import com.google.android.exoplayer.SampleSourceProvider;
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.SimpleExoPlayer;
|
import com.google.android.exoplayer.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer.TrackGroupArray;
|
import com.google.android.exoplayer.TrackGroupArray;
|
||||||
|
import com.google.android.exoplayer.dash.DashSampleSource;
|
||||||
import com.google.android.exoplayer.drm.DrmSessionManager;
|
import com.google.android.exoplayer.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
|
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
|
||||||
import com.google.android.exoplayer.drm.UnsupportedDrmException;
|
import com.google.android.exoplayer.drm.UnsupportedDrmException;
|
||||||
|
import com.google.android.exoplayer.extractor.DefaultExtractorsFactory;
|
||||||
|
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
|
||||||
|
import com.google.android.exoplayer.hls.HlsSampleSource;
|
||||||
import com.google.android.exoplayer.metadata.id3.ApicFrame;
|
import com.google.android.exoplayer.metadata.id3.ApicFrame;
|
||||||
import com.google.android.exoplayer.metadata.id3.GeobFrame;
|
import com.google.android.exoplayer.metadata.id3.GeobFrame;
|
||||||
import com.google.android.exoplayer.metadata.id3.Id3Frame;
|
import com.google.android.exoplayer.metadata.id3.Id3Frame;
|
||||||
import com.google.android.exoplayer.metadata.id3.PrivFrame;
|
import com.google.android.exoplayer.metadata.id3.PrivFrame;
|
||||||
import com.google.android.exoplayer.metadata.id3.TextInformationFrame;
|
import com.google.android.exoplayer.metadata.id3.TextInformationFrame;
|
||||||
import com.google.android.exoplayer.metadata.id3.TxxxFrame;
|
import com.google.android.exoplayer.metadata.id3.TxxxFrame;
|
||||||
|
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingSampleSource;
|
||||||
import com.google.android.exoplayer.text.CaptionStyleCompat;
|
import com.google.android.exoplayer.text.CaptionStyleCompat;
|
||||||
import com.google.android.exoplayer.text.Cue;
|
import com.google.android.exoplayer.text.Cue;
|
||||||
import com.google.android.exoplayer.text.SubtitleLayout;
|
import com.google.android.exoplayer.text.SubtitleLayout;
|
||||||
|
import com.google.android.exoplayer.upstream.BandwidthMeter;
|
||||||
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
||||||
import com.google.android.exoplayer.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer.upstream.DefaultDataSourceFactory;
|
||||||
import com.google.android.exoplayer.util.DebugTextViewHelper;
|
import com.google.android.exoplayer.util.DebugTextViewHelper;
|
||||||
|
|
@ -57,6 +63,7 @@ import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
@ -126,6 +133,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
private DefaultTrackSelector trackSelector;
|
private DefaultTrackSelector trackSelector;
|
||||||
private TrackSelectionHelper trackSelectionHelper;
|
private TrackSelectionHelper trackSelectionHelper;
|
||||||
private DebugTextViewHelper debugViewHelper;
|
private DebugTextViewHelper debugViewHelper;
|
||||||
|
private BandwidthMeter bandwidthMeter;
|
||||||
private boolean playerNeedsSource;
|
private boolean playerNeedsSource;
|
||||||
|
|
||||||
private long playerPosition;
|
private long playerPosition;
|
||||||
|
|
@ -283,6 +291,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
mediaController.setAnchorView(rootView);
|
mediaController.setAnchorView(rootView);
|
||||||
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
|
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
|
||||||
debugViewHelper.start();
|
debugViewHelper.start();
|
||||||
|
bandwidthMeter = player.getBandwidthMeter();
|
||||||
playerNeedsSource = true;
|
playerNeedsSource = true;
|
||||||
}
|
}
|
||||||
if (playerNeedsSource) {
|
if (playerNeedsSource) {
|
||||||
|
|
@ -311,10 +320,9 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UriSampleSourceProvider[] providers = new UriSampleSourceProvider[uris.length];
|
SampleSourceProvider[] providers = new SampleSourceProvider[uris.length];
|
||||||
for (int i = 0; i < uris.length; i++) {
|
for (int i = 0; i < uris.length; i++) {
|
||||||
providers[i] = new UriSampleSourceProvider(player.getBandwidthMeter(), dataSourceFactory,
|
providers[i] = getSampleSourceProvider(uris[i], extensions[i]);
|
||||||
uris[i], extensions[i], mainHandler, eventLogger);
|
|
||||||
}
|
}
|
||||||
SampleSourceProvider sourceProvider = providers.length == 1 ? providers[0]
|
SampleSourceProvider sourceProvider = providers.length == 1 ? providers[0]
|
||||||
: new ConcatenatingSampleSourceProvider(providers);
|
: new ConcatenatingSampleSourceProvider(providers);
|
||||||
|
|
@ -324,6 +332,28 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SampleSourceProvider getSampleSourceProvider(Uri uri, String overrideExtension) {
|
||||||
|
String lastPathSegment = !TextUtils.isEmpty(overrideExtension) ? "." + overrideExtension
|
||||||
|
: uri.getLastPathSegment();
|
||||||
|
int type = Util.inferContentType(lastPathSegment);
|
||||||
|
switch (type) {
|
||||||
|
case Util.TYPE_SS:
|
||||||
|
return new SmoothStreamingSampleSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||||
|
eventLogger);
|
||||||
|
case Util.TYPE_DASH:
|
||||||
|
return new DashSampleSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||||
|
eventLogger);
|
||||||
|
case Util.TYPE_HLS:
|
||||||
|
return new HlsSampleSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||||
|
eventLogger);
|
||||||
|
case Util.TYPE_OTHER:
|
||||||
|
return new ExtractorSampleSource(uri, dataSourceFactory, bandwidthMeter,
|
||||||
|
new DefaultExtractorsFactory(), mainHandler, eventLogger);
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("Unsupported type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private DrmSessionManager buildDrmSessionManager(UUID uuid, String id, String provider)
|
private DrmSessionManager buildDrmSessionManager(UUID uuid, String id, String provider)
|
||||||
throws UnsupportedDrmException {
|
throws UnsupportedDrmException {
|
||||||
if (Util.SDK_INT < 18) {
|
if (Util.SDK_INT < 18) {
|
||||||
|
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.exoplayer.demo;
|
|
||||||
|
|
||||||
import com.google.android.exoplayer.SampleSource;
|
|
||||||
import com.google.android.exoplayer.SampleSourceProvider;
|
|
||||||
import com.google.android.exoplayer.dash.DashSampleSource;
|
|
||||||
import com.google.android.exoplayer.extractor.DefaultExtractorsFactory;
|
|
||||||
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
|
|
||||||
import com.google.android.exoplayer.hls.HlsSampleSource;
|
|
||||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingSampleSource;
|
|
||||||
import com.google.android.exoplayer.upstream.BandwidthMeter;
|
|
||||||
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
|
||||||
import com.google.android.exoplayer.util.Util;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a {@link SampleSource} to play back media loaded from a {@link Uri}.
|
|
||||||
*/
|
|
||||||
public final class UriSampleSourceProvider implements SampleSourceProvider {
|
|
||||||
|
|
||||||
private final BandwidthMeter bandwidthMeter;
|
|
||||||
private final DataSourceFactory dataSourceFactory;
|
|
||||||
private final Uri uri;
|
|
||||||
private final String overrideExtension;
|
|
||||||
private final Handler handler;
|
|
||||||
private final EventLogger eventLogger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a source provider for {@link SampleSource} to play back media at the specified
|
|
||||||
* URI, using the specified type.
|
|
||||||
*
|
|
||||||
* @param bandwidthMeter A bandwidth meter.
|
|
||||||
* @param dataSourceFactory A data source factory.
|
|
||||||
* @param uri The URI to play back.
|
|
||||||
* @param overrideExtension An overriding file extension used when inferring the source's type,
|
|
||||||
* or {@code null}.
|
|
||||||
* @param handler A handler to use for logging events.
|
|
||||||
* @param eventLogger An event logger.
|
|
||||||
*/
|
|
||||||
public UriSampleSourceProvider(BandwidthMeter bandwidthMeter, DataSourceFactory dataSourceFactory,
|
|
||||||
Uri uri, String overrideExtension, Handler handler, EventLogger eventLogger) {
|
|
||||||
this.bandwidthMeter = bandwidthMeter;
|
|
||||||
this.dataSourceFactory = dataSourceFactory;
|
|
||||||
this.uri = uri;
|
|
||||||
this.overrideExtension = overrideExtension;
|
|
||||||
this.handler = handler;
|
|
||||||
this.eventLogger = eventLogger;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceCount() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SampleSource createSource(int index) {
|
|
||||||
int type = inferContentType(uri, overrideExtension);
|
|
||||||
switch (type) {
|
|
||||||
case Util.TYPE_SS:
|
|
||||||
return new SmoothStreamingSampleSource(uri, dataSourceFactory, bandwidthMeter, handler,
|
|
||||||
eventLogger);
|
|
||||||
case Util.TYPE_DASH:
|
|
||||||
return new DashSampleSource(uri, dataSourceFactory, bandwidthMeter, handler, eventLogger);
|
|
||||||
case Util.TYPE_HLS:
|
|
||||||
return new HlsSampleSource(uri, dataSourceFactory, bandwidthMeter, handler, eventLogger);
|
|
||||||
case Util.TYPE_OTHER:
|
|
||||||
return new ExtractorSampleSource(uri, dataSourceFactory, bandwidthMeter,
|
|
||||||
new DefaultExtractorsFactory(), handler, eventLogger);
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Unsupported type: " + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a best guess to infer the type from a media {@link Uri} and an optional overriding file
|
|
||||||
* extension.
|
|
||||||
*
|
|
||||||
* @param uri The {@link Uri} of the media.
|
|
||||||
* @param fileExtension An overriding file extension.
|
|
||||||
* @return The inferred type.
|
|
||||||
*/
|
|
||||||
private static int inferContentType(Uri uri, String fileExtension) {
|
|
||||||
String lastPathSegment = !TextUtils.isEmpty(fileExtension) ? "." + fileExtension
|
|
||||||
: uri.getLastPathSegment();
|
|
||||||
return Util.inferContentType(lastPathSegment);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -83,7 +83,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
|
||||||
new MatroskaExtractor.Factory(),
|
new MatroskaExtractor.Factory(),
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
player.setSource(sampleSource);
|
player.setSourceProvider(sampleSource);
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
Looper.loop();
|
Looper.loop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
|
||||||
new MatroskaExtractor.Factory(),
|
new MatroskaExtractor.Factory(),
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
player.setSource(sampleSource);
|
player.setSourceProvider(sampleSource);
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
Looper.loop();
|
Looper.loop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
||||||
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
|
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
|
||||||
LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
||||||
new VpxVideoSurfaceView(context)));
|
new VpxVideoSurfaceView(context)));
|
||||||
player.setSource(sampleSource);
|
player.setSourceProvider(sampleSource);
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
Looper.loop();
|
Looper.loop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -235,14 +235,6 @@ public interface ExoPlayer {
|
||||||
*/
|
*/
|
||||||
int getPlaybackState();
|
int getPlaybackState();
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the player's source. The player will transition to {@link #STATE_BUFFERING} until it is
|
|
||||||
* ready to play the new source.
|
|
||||||
*
|
|
||||||
* @param sampleSource The {@link SampleSource} to play.
|
|
||||||
*/
|
|
||||||
void setSource(SampleSource sampleSource);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the player's source provider. The player's position will be reset to the start of the
|
* Sets the player's source provider. The player's position will be reset to the start of the
|
||||||
* first source and the player will transition to {@link #STATE_BUFFERING} until it is ready to
|
* first source and the player will transition to {@link #STATE_BUFFERING} until it is ready to
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,6 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
return playbackState;
|
return playbackState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSource(final SampleSource sampleSource) {
|
|
||||||
setSourceProvider(new SingleSampleSourceProvider(sampleSource));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
||||||
maskingSourceIndex = 0;
|
maskingSourceIndex = 0;
|
||||||
|
|
@ -267,25 +262,4 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SingleSampleSourceProvider implements SampleSourceProvider {
|
|
||||||
|
|
||||||
private final SampleSource sampleSource;
|
|
||||||
|
|
||||||
public SingleSampleSourceProvider(SampleSource sampleSource) {
|
|
||||||
this.sampleSource = sampleSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceCount() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SampleSource createSource(int index) {
|
|
||||||
// The source will only be created once.
|
|
||||||
return sampleSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -313,11 +313,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||||
return player.getPlaybackState();
|
return player.getPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSource(SampleSource sampleSource) {
|
|
||||||
player.setSource(sampleSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
||||||
player.setSourceProvider(sourceProvider);
|
player.setSourceProvider(sourceProvider);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer;
|
||||||
|
|
||||||
import com.google.android.exoplayer.upstream.Allocator;
|
import com.google.android.exoplayer.upstream.Allocator;
|
||||||
import com.google.android.exoplayer.upstream.DataSource;
|
import com.google.android.exoplayer.upstream.DataSource;
|
||||||
|
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
||||||
import com.google.android.exoplayer.upstream.DataSpec;
|
import com.google.android.exoplayer.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer.upstream.Loader;
|
import com.google.android.exoplayer.upstream.Loader;
|
||||||
import com.google.android.exoplayer.upstream.Loader.Loadable;
|
import com.google.android.exoplayer.upstream.Loader.Loadable;
|
||||||
|
|
@ -30,10 +31,11 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SampleSource} that loads the data at a given {@link Uri} as a single sample.
|
* A {@link SampleSource} that loads the data at a given {@link Uri} as a single sample. Also acts
|
||||||
|
* as a {@link SampleSourceProvider} providing {@link SingleSampleSource} instances.
|
||||||
*/
|
*/
|
||||||
public final class SingleSampleSource implements SampleSource, TrackStream,
|
public final class SingleSampleSource implements SampleSource, SampleSourceProvider, TrackStream,
|
||||||
Loader.Callback<SingleSampleSource>, Loadable {
|
Loader.Callback<SingleSampleSource.SourceLoadable> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface definition for a callback to be notified of {@link SingleSampleSource} events.
|
* Interface definition for a callback to be notified of {@link SingleSampleSource} events.
|
||||||
|
|
@ -65,8 +67,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream,
|
||||||
private static final int STREAM_STATE_END_OF_STREAM = 2;
|
private static final int STREAM_STATE_END_OF_STREAM = 2;
|
||||||
|
|
||||||
private final Uri uri;
|
private final Uri uri;
|
||||||
private final DataSource dataSource;
|
private final DataSourceFactory dataSourceFactory;
|
||||||
private final Loader loader;
|
|
||||||
private final Format format;
|
private final Format format;
|
||||||
private final long durationUs;
|
private final long durationUs;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
|
|
@ -75,41 +76,57 @@ public final class SingleSampleSource implements SampleSource, TrackStream,
|
||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
private final int eventSourceId;
|
private final int eventSourceId;
|
||||||
|
|
||||||
|
private Loader loader;
|
||||||
private boolean loadingFinished;
|
private boolean loadingFinished;
|
||||||
|
|
||||||
private int streamState;
|
private int streamState;
|
||||||
private byte[] sampleData;
|
private byte[] sampleData;
|
||||||
private int sampleSize;
|
private int sampleSize;
|
||||||
|
|
||||||
public SingleSampleSource(Uri uri, DataSource dataSource, Format format, long durationUs) {
|
public SingleSampleSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||||
this(uri, dataSource, format, durationUs, DEFAULT_MIN_LOADABLE_RETRY_COUNT);
|
long durationUs) {
|
||||||
|
this(uri, dataSourceFactory, format, durationUs, DEFAULT_MIN_LOADABLE_RETRY_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingleSampleSource(Uri uri, DataSource dataSource, Format format, long durationUs,
|
public SingleSampleSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||||
int minLoadableRetryCount) {
|
long durationUs, int minLoadableRetryCount) {
|
||||||
this(uri, dataSource, format, durationUs, minLoadableRetryCount, null, null, 0);
|
this(uri, dataSourceFactory, format, durationUs, minLoadableRetryCount, null, null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingleSampleSource(Uri uri, DataSource dataSource, Format format, long durationUs,
|
public SingleSampleSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||||
int minLoadableRetryCount, Handler eventHandler, EventListener eventListener,
|
long durationUs, int minLoadableRetryCount, Handler eventHandler, EventListener eventListener,
|
||||||
int eventSourceId) {
|
int eventSourceId) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.dataSource = dataSource;
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.durationUs = durationUs;
|
this.durationUs = durationUs;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
this.eventHandler = eventHandler;
|
this.eventHandler = eventHandler;
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.eventSourceId = eventSourceId;
|
this.eventSourceId = eventSourceId;
|
||||||
loader = new Loader("Loader:SingleSampleSource");
|
|
||||||
tracks = new TrackGroupArray(new TrackGroup(format));
|
tracks = new TrackGroupArray(new TrackGroup(format));
|
||||||
sampleData = new byte[INITIAL_SAMPLE_SIZE];
|
sampleData = new byte[INITIAL_SAMPLE_SIZE];
|
||||||
|
streamState = STREAM_STATE_SEND_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SampleSourceProvider implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSourceCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SampleSource createSource(int index) {
|
||||||
|
Assertions.checkArgument(index == 0);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SampleSource implementation.
|
// SampleSource implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
|
loader = new Loader("Loader:SingleSampleSource");
|
||||||
callback.onSourcePrepared(this);
|
callback.onSourcePrepared(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,7 +164,8 @@ public final class SingleSampleSource implements SampleSource, TrackStream,
|
||||||
if (loadingFinished || loader.isLoading()) {
|
if (loadingFinished || loader.isLoading()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loader.startLoading(this, this, minLoadableRetryCount);
|
loader.startLoading(new SourceLoadable(uri, dataSourceFactory.createDataSource()), this,
|
||||||
|
minLoadableRetryCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,8 +189,14 @@ public final class SingleSampleSource implements SampleSource, TrackStream,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
|
if (loader != null) {
|
||||||
|
loader.release();
|
||||||
|
loader = null;
|
||||||
|
}
|
||||||
|
loadingFinished = false;
|
||||||
|
streamState = STREAM_STATE_SEND_FORMAT;
|
||||||
sampleData = null;
|
sampleData = null;
|
||||||
loader.release();
|
sampleSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackStream implementation.
|
// TrackStream implementation.
|
||||||
|
|
@ -219,57 +243,26 @@ public final class SingleSampleSource implements SampleSource, TrackStream,
|
||||||
// Loader.Callback implementation.
|
// Loader.Callback implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadCompleted(SingleSampleSource loadable, long elapsedRealtimeMs,
|
public void onLoadCompleted(SourceLoadable loadable, long elapsedRealtimeMs,
|
||||||
long loadDurationMs) {
|
long loadDurationMs) {
|
||||||
|
sampleSize = loadable.sampleSize;
|
||||||
|
sampleData = loadable.sampleData;
|
||||||
loadingFinished = true;
|
loadingFinished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadCanceled(SingleSampleSource loadable, long elapsedRealtimeMs,
|
public void onLoadCanceled(SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs,
|
||||||
long loadDurationMs, boolean released) {
|
boolean released) {
|
||||||
// Never happens.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onLoadError(SingleSampleSource loadable, long elapsedRealtimeMs,
|
public int onLoadError(SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs,
|
||||||
long loadDurationMs, IOException error) {
|
IOException error) {
|
||||||
notifyLoadError(error);
|
notifyLoadError(error);
|
||||||
return Loader.RETRY;
|
return Loader.RETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loadable implementation.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelLoad() {
|
|
||||||
// Never happens.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoadCanceled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load() throws IOException, InterruptedException {
|
|
||||||
// We always load from the beginning, so reset the sampleSize to 0.
|
|
||||||
sampleSize = 0;
|
|
||||||
try {
|
|
||||||
// Create and open the input.
|
|
||||||
dataSource.open(new DataSpec(uri));
|
|
||||||
// Load the sample data.
|
|
||||||
int result = 0;
|
|
||||||
while (result != C.RESULT_END_OF_INPUT) {
|
|
||||||
sampleSize += result;
|
|
||||||
if (sampleSize == sampleData.length) {
|
|
||||||
sampleData = Arrays.copyOf(sampleData, sampleData.length * 2);
|
|
||||||
}
|
|
||||||
result = dataSource.read(sampleData, sampleSize, sampleData.length - sampleSize);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
dataSource.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private void notifyLoadError(final IOException e) {
|
private void notifyLoadError(final IOException e) {
|
||||||
|
|
@ -283,4 +276,50 @@ public final class SingleSampleSource implements SampleSource, TrackStream,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ static final class SourceLoadable implements Loadable {
|
||||||
|
|
||||||
|
private final Uri uri;
|
||||||
|
private final DataSource dataSource;
|
||||||
|
|
||||||
|
private int sampleSize;
|
||||||
|
private byte[] sampleData;
|
||||||
|
|
||||||
|
public SourceLoadable(Uri uri, DataSource dataSource) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelLoad() {
|
||||||
|
// Never happens.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoadCanceled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() throws IOException, InterruptedException {
|
||||||
|
// We always load from the beginning, so reset the sampleSize to 0.
|
||||||
|
sampleSize = 0;
|
||||||
|
try {
|
||||||
|
// Create and open the input.
|
||||||
|
dataSource.open(new DataSpec(uri));
|
||||||
|
// Load the sample data.
|
||||||
|
int result = 0;
|
||||||
|
while (result != C.RESULT_END_OF_INPUT) {
|
||||||
|
sampleSize += result;
|
||||||
|
if (sampleSize == sampleData.length) {
|
||||||
|
sampleData = Arrays.copyOf(sampleData, sampleData.length * 2);
|
||||||
|
}
|
||||||
|
result = dataSource.read(sampleData, sampleSize, sampleData.length - sampleSize);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
dataSource.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.google.android.exoplayer.CompositeSequenceableLoader;
|
||||||
import com.google.android.exoplayer.Format;
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.SequenceableLoader;
|
import com.google.android.exoplayer.SequenceableLoader;
|
||||||
import com.google.android.exoplayer.TrackGroup;
|
import com.google.android.exoplayer.TrackGroup;
|
||||||
import com.google.android.exoplayer.TrackGroupArray;
|
import com.google.android.exoplayer.TrackGroupArray;
|
||||||
|
|
@ -42,6 +43,7 @@ import com.google.android.exoplayer.upstream.DataSource;
|
||||||
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
||||||
import com.google.android.exoplayer.upstream.Loader;
|
import com.google.android.exoplayer.upstream.Loader;
|
||||||
import com.google.android.exoplayer.upstream.ParsingLoadable;
|
import com.google.android.exoplayer.upstream.ParsingLoadable;
|
||||||
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -61,9 +63,10 @@ import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SampleSource} for DASH media.
|
* A {@link SampleSource} for DASH media. Also acts as a {@link SampleSourceProvider} providing
|
||||||
|
* {@link DashSampleSource} instances.
|
||||||
*/
|
*/
|
||||||
public final class DashSampleSource implements SampleSource,
|
public final class DashSampleSource implements SampleSource, SampleSourceProvider,
|
||||||
SequenceableLoader.Callback<ChunkTrackStream<DashChunkSource>> {
|
SequenceableLoader.Callback<ChunkTrackStream<DashChunkSource>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -77,11 +80,14 @@ public final class DashSampleSource implements SampleSource,
|
||||||
private final BandwidthMeter bandwidthMeter;
|
private final BandwidthMeter bandwidthMeter;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final Loader loader;
|
|
||||||
private final DataSource dataSource;
|
|
||||||
private final MediaPresentationDescriptionParser manifestParser;
|
private final MediaPresentationDescriptionParser manifestParser;
|
||||||
private final ManifestCallback manifestCallback;
|
private final ManifestCallback manifestCallback;
|
||||||
|
|
||||||
|
private DataSource dataSource;
|
||||||
|
private Loader loader;
|
||||||
|
private ChunkTrackStream<DashChunkSource>[] trackStreams;
|
||||||
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
|
|
||||||
private Uri manifestUri;
|
private Uri manifestUri;
|
||||||
private long manifestLoadStartTimestamp;
|
private long manifestLoadStartTimestamp;
|
||||||
private long manifestLoadEndTimestamp;
|
private long manifestLoadEndTimestamp;
|
||||||
|
|
@ -96,9 +102,6 @@ public final class DashSampleSource implements SampleSource,
|
||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private int[] trackGroupAdaptationSetIndices;
|
private int[] trackGroupAdaptationSetIndices;
|
||||||
|
|
||||||
private ChunkTrackStream<DashChunkSource>[] trackStreams;
|
|
||||||
private CompositeSequenceableLoader sequenceableLoader;
|
|
||||||
|
|
||||||
public DashSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
public DashSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||||
AdaptiveSourceEventListener eventListener) {
|
AdaptiveSourceEventListener eventListener) {
|
||||||
|
|
@ -114,18 +117,33 @@ public final class DashSampleSource implements SampleSource,
|
||||||
this.bandwidthMeter = bandwidthMeter;
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
dataSource = dataSourceFactory.createDataSource();
|
|
||||||
loader = new Loader("Loader:DashSampleSource");
|
|
||||||
manifestParser = new MediaPresentationDescriptionParser();
|
manifestParser = new MediaPresentationDescriptionParser();
|
||||||
manifestCallback = new ManifestCallback();
|
manifestCallback = new ManifestCallback();
|
||||||
trackStreams = newTrackStreamArray(0);
|
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SampleSourceProvider implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSourceCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SampleSource createSource(int index) {
|
||||||
|
Assertions.checkArgument(index == 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SampleSource implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
|
trackStreams = newTrackStreamArray(0);
|
||||||
|
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
||||||
|
dataSource = dataSourceFactory.createDataSource();
|
||||||
|
loader = new Loader("Loader:DashSampleSource");
|
||||||
manifestRefreshHandler = new Handler();
|
manifestRefreshHandler = new Handler();
|
||||||
startLoadingManifest();
|
startLoadingManifest();
|
||||||
}
|
}
|
||||||
|
|
@ -212,14 +230,32 @@ public final class DashSampleSource implements SampleSource,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
|
dataSource = null;
|
||||||
|
if (loader != null) {
|
||||||
|
loader.release();
|
||||||
|
loader = null;
|
||||||
|
}
|
||||||
|
if (trackStreams != null) {
|
||||||
|
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
||||||
|
trackStream.release();
|
||||||
|
}
|
||||||
|
trackStreams = null;
|
||||||
|
}
|
||||||
|
sequenceableLoader = null;
|
||||||
|
manifestLoadStartTimestamp = 0;
|
||||||
|
manifestLoadEndTimestamp = 0;
|
||||||
|
manifest = null;
|
||||||
|
callback = null;
|
||||||
|
allocator = null;
|
||||||
if (manifestRefreshHandler != null) {
|
if (manifestRefreshHandler != null) {
|
||||||
manifestRefreshHandler.removeCallbacksAndMessages(null);
|
manifestRefreshHandler.removeCallbacksAndMessages(null);
|
||||||
manifestRefreshHandler = null;
|
manifestRefreshHandler = null;
|
||||||
}
|
}
|
||||||
loader.release();
|
prepared = false;
|
||||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
durationUs = 0;
|
||||||
trackStream.release();
|
elapsedRealtimeOffset = 0;
|
||||||
}
|
trackGroups = null;
|
||||||
|
trackGroupAdaptationSetIndices = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SequenceableLoader.Callback implementation.
|
// SequenceableLoader.Callback implementation.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.FormatHolder;
|
import com.google.android.exoplayer.FormatHolder;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.SequenceableLoader;
|
import com.google.android.exoplayer.SequenceableLoader;
|
||||||
import com.google.android.exoplayer.TrackGroup;
|
import com.google.android.exoplayer.TrackGroup;
|
||||||
import com.google.android.exoplayer.TrackGroupArray;
|
import com.google.android.exoplayer.TrackGroupArray;
|
||||||
|
|
@ -47,7 +48,8 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SampleSource} that extracts sample data using an {@link Extractor}.
|
* A {@link SampleSource} that extracts sample data using an {@link Extractor}. Also acts as a
|
||||||
|
* {@link SampleSourceProvider} providing {@link ExtractorSampleSource} instances.
|
||||||
*
|
*
|
||||||
* <p>If the possible input stream container formats are known, pass a factory that instantiates
|
* <p>If the possible input stream container formats are known, pass a factory that instantiates
|
||||||
* extractors for them to the constructor. Otherwise, pass a {@link DefaultExtractorsFactory} to
|
* extractors for them to the constructor. Otherwise, pass a {@link DefaultExtractorsFactory} to
|
||||||
|
|
@ -57,8 +59,8 @@ import java.util.List;
|
||||||
*
|
*
|
||||||
* <p>Note that the built-in extractors for AAC, MPEG TS and FLV streams do not support seeking.
|
* <p>Note that the built-in extractors for AAC, MPEG TS and FLV streams do not support seeking.
|
||||||
*/
|
*/
|
||||||
public final class ExtractorSampleSource implements SampleSource, ExtractorOutput,
|
public final class ExtractorSampleSource implements SampleSource, SampleSourceProvider,
|
||||||
Loader.Callback<ExtractorSampleSource.ExtractingLoadable>,
|
ExtractorOutput, Loader.Callback<ExtractorSampleSource.ExtractingLoadable>,
|
||||||
UpstreamFormatChangedListener {
|
UpstreamFormatChangedListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -106,13 +108,17 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
||||||
private static final long DEFAULT_LAST_SAMPLE_DURATION_US = 10000;
|
private static final long DEFAULT_LAST_SAMPLE_DURATION_US = 10000;
|
||||||
|
|
||||||
private final Uri uri;
|
private final Uri uri;
|
||||||
|
private final DataSourceFactory dataSourceFactory;
|
||||||
|
private final BandwidthMeter bandwidthMeter;
|
||||||
|
private final ExtractorsFactory extractorsFactory;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final Handler eventHandler;
|
private final Handler eventHandler;
|
||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
private final DataSource dataSource;
|
|
||||||
private final ConditionVariable loadCondition;
|
private DataSource dataSource;
|
||||||
private final ExtractorHolder extractorHolder;
|
private ExtractorHolder extractorHolder;
|
||||||
private final Loader loader;
|
private Loader loader;
|
||||||
|
private ConditionVariable loadCondition;
|
||||||
|
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private Allocator allocator;
|
private Allocator allocator;
|
||||||
|
|
@ -166,16 +172,25 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
||||||
BandwidthMeter bandwidthMeter, ExtractorsFactory extractorsFactory, int minLoadableRetryCount,
|
BandwidthMeter bandwidthMeter, ExtractorsFactory extractorsFactory, int minLoadableRetryCount,
|
||||||
Handler eventHandler, EventListener eventListener) {
|
Handler eventHandler, EventListener eventListener) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
|
this.extractorsFactory = extractorsFactory;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
this.eventListener = eventListener;
|
|
||||||
this.eventHandler = eventHandler;
|
this.eventHandler = eventHandler;
|
||||||
dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
this.eventListener = eventListener;
|
||||||
loadCondition = new ConditionVariable();
|
}
|
||||||
extractorHolder = new ExtractorHolder(extractorsFactory.createExtractors(), this);
|
|
||||||
loader = new Loader("Loader:ExtractorSampleSource", extractorHolder);
|
// SampleSourceProvider implementation.
|
||||||
pendingResetPositionUs = C.UNSET_TIME_US;
|
|
||||||
sampleQueues = new DefaultTrackOutput[0];
|
@Override
|
||||||
length = C.LENGTH_UNBOUNDED;
|
public int getSourceCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SampleSource createSource(int index) {
|
||||||
|
Assertions.checkArgument(index == 0);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SampleSource implementation.
|
// SampleSource implementation.
|
||||||
|
|
@ -184,6 +199,15 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
|
|
||||||
|
dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||||
|
extractorHolder = new ExtractorHolder(extractorsFactory.createExtractors(), this);
|
||||||
|
loader = new Loader("Loader:ExtractorSampleSource", extractorHolder);
|
||||||
|
loadCondition = new ConditionVariable();
|
||||||
|
pendingResetPositionUs = C.UNSET_TIME_US;
|
||||||
|
sampleQueues = new DefaultTrackOutput[0];
|
||||||
|
length = C.LENGTH_UNBOUNDED;
|
||||||
|
|
||||||
loadCondition.open();
|
loadCondition.open();
|
||||||
startLoading();
|
startLoading();
|
||||||
}
|
}
|
||||||
|
|
@ -318,10 +342,35 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
for (DefaultTrackOutput sampleQueue : sampleQueues) {
|
dataSource = null;
|
||||||
sampleQueue.disable();
|
extractorHolder = null;
|
||||||
|
if (loader != null) {
|
||||||
|
loader.release(); // Releases extractorHolder via its own reference on the loader's thread.
|
||||||
|
loader = null;
|
||||||
}
|
}
|
||||||
loader.release();
|
loadCondition = null;
|
||||||
|
callback = null;
|
||||||
|
allocator = null;
|
||||||
|
seekMap = null;
|
||||||
|
tracksBuilt = false;
|
||||||
|
prepared = false;
|
||||||
|
seenFirstTrackSelection = false;
|
||||||
|
notifyReset = false;
|
||||||
|
enabledTrackCount = 0;
|
||||||
|
if (sampleQueues != null) {
|
||||||
|
for (DefaultTrackOutput sampleQueue : sampleQueues) {
|
||||||
|
sampleQueue.disable();
|
||||||
|
}
|
||||||
|
sampleQueues = null;
|
||||||
|
}
|
||||||
|
tracks = null;
|
||||||
|
durationUs = 0;
|
||||||
|
trackEnabledStates = null;
|
||||||
|
length = 0;
|
||||||
|
lastSeekPositionUs = 0;
|
||||||
|
pendingResetPositionUs = 0;
|
||||||
|
extractedSamplesCountAtStartOfLoad = 0;
|
||||||
|
loadingFinished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackStream methods.
|
// TrackStream methods.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.google.android.exoplayer.CompositeSequenceableLoader;
|
||||||
import com.google.android.exoplayer.Format;
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.TrackGroup;
|
import com.google.android.exoplayer.TrackGroup;
|
||||||
import com.google.android.exoplayer.TrackGroupArray;
|
import com.google.android.exoplayer.TrackGroupArray;
|
||||||
import com.google.android.exoplayer.TrackSelection;
|
import com.google.android.exoplayer.TrackSelection;
|
||||||
|
|
@ -38,6 +39,7 @@ import com.google.android.exoplayer.upstream.DataSource;
|
||||||
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
||||||
import com.google.android.exoplayer.upstream.Loader;
|
import com.google.android.exoplayer.upstream.Loader;
|
||||||
import com.google.android.exoplayer.upstream.ParsingLoadable;
|
import com.google.android.exoplayer.upstream.ParsingLoadable;
|
||||||
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -51,9 +53,10 @@ import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SampleSource} for HLS streams.
|
* A {@link SampleSource} for HLS streams. Also acts as a {@link SampleSourceProvider} providing
|
||||||
|
* {@link HlsSampleSource} instances.
|
||||||
*/
|
*/
|
||||||
public final class HlsSampleSource implements SampleSource,
|
public final class HlsSampleSource implements SampleSource, SampleSourceProvider,
|
||||||
Loader.Callback<ParsingLoadable<HlsPlaylist>>, HlsTrackStreamWrapper.Callback {
|
Loader.Callback<ParsingLoadable<HlsPlaylist>>, HlsTrackStreamWrapper.Callback {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -68,10 +71,11 @@ public final class HlsSampleSource implements SampleSource,
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final IdentityHashMap<TrackStream, HlsTrackStreamWrapper> trackStreamSources;
|
private final IdentityHashMap<TrackStream, HlsTrackStreamWrapper> trackStreamSources;
|
||||||
private final PtsTimestampAdjusterProvider timestampAdjusterProvider;
|
private final PtsTimestampAdjusterProvider timestampAdjusterProvider;
|
||||||
private final Loader manifestFetcher;
|
|
||||||
private final DataSource manifestDataSource;
|
|
||||||
private final HlsPlaylistParser manifestParser;
|
private final HlsPlaylistParser manifestParser;
|
||||||
|
|
||||||
|
private DataSource manifestDataSource;
|
||||||
|
private Loader manifestFetcher;
|
||||||
|
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private Allocator allocator;
|
private Allocator allocator;
|
||||||
private long preparePositionUs;
|
private long preparePositionUs;
|
||||||
|
|
@ -100,25 +104,38 @@ public final class HlsSampleSource implements SampleSource,
|
||||||
this.dataSourceFactory = dataSourceFactory;
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
this.bandwidthMeter = bandwidthMeter;
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
|
|
||||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
timestampAdjusterProvider = new PtsTimestampAdjusterProvider();
|
|
||||||
trackStreamSources = new IdentityHashMap<>();
|
|
||||||
|
|
||||||
manifestDataSource = dataSourceFactory.createDataSource();
|
trackStreamSources = new IdentityHashMap<>();
|
||||||
|
timestampAdjusterProvider = new PtsTimestampAdjusterProvider();
|
||||||
manifestParser = new HlsPlaylistParser();
|
manifestParser = new HlsPlaylistParser();
|
||||||
manifestFetcher = new Loader("Loader:ManifestFetcher");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SampleSourceProvider implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSourceCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SampleSource createSource(int index) {
|
||||||
|
Assertions.checkArgument(index == 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SampleSource implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
this.preparePositionUs = positionUs;
|
preparePositionUs = positionUs;
|
||||||
ParsingLoadable<HlsPlaylist> loadable = new ParsingLoadable<>(manifestDataSource,
|
manifestDataSource = dataSourceFactory.createDataSource();
|
||||||
manifestUri, C.DATA_TYPE_MANIFEST, manifestParser);
|
manifestFetcher = new Loader("Loader:ManifestFetcher");
|
||||||
long elapsedRealtimeMs = manifestFetcher.startLoading(loadable, this,
|
ParsingLoadable<HlsPlaylist> loadable = new ParsingLoadable<>(manifestDataSource, manifestUri,
|
||||||
minLoadableRetryCount);
|
C.DATA_TYPE_MANIFEST, manifestParser);
|
||||||
|
long elapsedRealtimeMs = manifestFetcher.startLoading(loadable, this, minLoadableRetryCount);
|
||||||
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
|
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,12 +229,30 @@ public final class HlsSampleSource implements SampleSource,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
manifestFetcher.release();
|
trackStreamSources.clear();
|
||||||
|
timestampAdjusterProvider.reset();
|
||||||
|
manifestDataSource = null;
|
||||||
|
if (manifestFetcher != null) {
|
||||||
|
manifestFetcher.release();
|
||||||
|
manifestFetcher = null;
|
||||||
|
}
|
||||||
|
callback = null;
|
||||||
|
allocator = null;
|
||||||
|
preparePositionUs = 0;
|
||||||
|
pendingPrepareCount = 0;
|
||||||
|
seenFirstTrackSelection = false;
|
||||||
|
durationUs = 0;
|
||||||
|
isLive = false;
|
||||||
|
trackGroups = null;
|
||||||
|
selectedTrackCounts = null;
|
||||||
if (trackStreamWrappers != null) {
|
if (trackStreamWrappers != null) {
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
||||||
trackStreamWrapper.release();
|
trackStreamWrapper.release();
|
||||||
}
|
}
|
||||||
|
trackStreamWrappers = null;
|
||||||
}
|
}
|
||||||
|
enabledTrackStreamWrappers = null;
|
||||||
|
sequenceableLoader = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loader.Callback implementation.
|
// Loader.Callback implementation.
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.google.android.exoplayer.CompositeSequenceableLoader;
|
||||||
import com.google.android.exoplayer.Format;
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSource;
|
||||||
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.SequenceableLoader;
|
import com.google.android.exoplayer.SequenceableLoader;
|
||||||
import com.google.android.exoplayer.TrackGroup;
|
import com.google.android.exoplayer.TrackGroup;
|
||||||
import com.google.android.exoplayer.TrackGroupArray;
|
import com.google.android.exoplayer.TrackGroupArray;
|
||||||
|
|
@ -39,6 +40,7 @@ import com.google.android.exoplayer.upstream.DataSource;
|
||||||
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
import com.google.android.exoplayer.upstream.DataSourceFactory;
|
||||||
import com.google.android.exoplayer.upstream.Loader;
|
import com.google.android.exoplayer.upstream.Loader;
|
||||||
import com.google.android.exoplayer.upstream.ParsingLoadable;
|
import com.google.android.exoplayer.upstream.ParsingLoadable;
|
||||||
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -51,9 +53,10 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SampleSource} for SmoothStreaming media.
|
* A {@link SampleSource} for SmoothStreaming media. Also acts as a {@link SampleSourceProvider}
|
||||||
|
* providing {@link SmoothStreamingSampleSource} instances.
|
||||||
*/
|
*/
|
||||||
public final class SmoothStreamingSampleSource implements SampleSource,
|
public final class SmoothStreamingSampleSource implements SampleSource, SampleSourceProvider,
|
||||||
SequenceableLoader.Callback<ChunkTrackStream<SmoothStreamingChunkSource>>,
|
SequenceableLoader.Callback<ChunkTrackStream<SmoothStreamingChunkSource>>,
|
||||||
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
|
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
|
||||||
|
|
||||||
|
|
@ -70,10 +73,13 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||||
private final BandwidthMeter bandwidthMeter;
|
private final BandwidthMeter bandwidthMeter;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final Loader manifestLoader;
|
|
||||||
private final DataSource manifestDataSource;
|
|
||||||
private final SmoothStreamingManifestParser manifestParser;
|
private final SmoothStreamingManifestParser manifestParser;
|
||||||
|
|
||||||
|
private DataSource manifestDataSource;
|
||||||
|
private Loader manifestLoader;
|
||||||
|
private ChunkTrackStream<SmoothStreamingChunkSource>[] trackStreams;
|
||||||
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
|
|
||||||
private long manifestLoadStartTimestamp;
|
private long manifestLoadStartTimestamp;
|
||||||
private SmoothStreamingManifest manifest;
|
private SmoothStreamingManifest manifest;
|
||||||
|
|
||||||
|
|
@ -86,9 +92,6 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private int[] trackGroupElementIndices;
|
private int[] trackGroupElementIndices;
|
||||||
|
|
||||||
private ChunkTrackStream<SmoothStreamingChunkSource>[] trackStreams;
|
|
||||||
private CompositeSequenceableLoader sequenceableLoader;
|
|
||||||
|
|
||||||
public SmoothStreamingSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
public SmoothStreamingSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||||
AdaptiveSourceEventListener eventListener) {
|
AdaptiveSourceEventListener eventListener) {
|
||||||
|
|
@ -105,17 +108,32 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||||
this.bandwidthMeter = bandwidthMeter;
|
this.bandwidthMeter = bandwidthMeter;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
trackStreams = newTrackStreamArray(0);
|
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
|
||||||
manifestDataSource = dataSourceFactory.createDataSource();
|
|
||||||
manifestParser = new SmoothStreamingManifestParser();
|
manifestParser = new SmoothStreamingManifestParser();
|
||||||
manifestLoader = new Loader("Loader:Manifest");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SampleSourceProvider implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSourceCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SampleSource createSource(int index) {
|
||||||
|
Assertions.checkArgument(index == 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SampleSource implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
|
trackStreams = newTrackStreamArray(0);
|
||||||
|
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
||||||
|
manifestDataSource = dataSourceFactory.createDataSource();
|
||||||
|
manifestLoader = new Loader("Loader:Manifest");
|
||||||
manifestRefreshHandler = new Handler();
|
manifestRefreshHandler = new Handler();
|
||||||
startLoadingManifest();
|
startLoadingManifest();
|
||||||
}
|
}
|
||||||
|
|
@ -202,14 +220,31 @@ public final class SmoothStreamingSampleSource implements SampleSource,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
|
manifestDataSource = null;
|
||||||
|
if (manifestLoader != null) {
|
||||||
|
manifestLoader.release();
|
||||||
|
manifestLoader = null;
|
||||||
|
}
|
||||||
|
if (trackStreams != null) {
|
||||||
|
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||||
|
trackStream.release();
|
||||||
|
}
|
||||||
|
trackStreams = null;
|
||||||
|
}
|
||||||
|
sequenceableLoader = null;
|
||||||
|
manifestLoadStartTimestamp = 0;
|
||||||
|
manifest = null;
|
||||||
|
callback = null;
|
||||||
|
allocator = null;
|
||||||
if (manifestRefreshHandler != null) {
|
if (manifestRefreshHandler != null) {
|
||||||
manifestRefreshHandler.removeCallbacksAndMessages(null);
|
manifestRefreshHandler.removeCallbacksAndMessages(null);
|
||||||
manifestRefreshHandler = null;
|
manifestRefreshHandler = null;
|
||||||
}
|
}
|
||||||
manifestLoader.release();
|
prepared = false;
|
||||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
durationUs = 0;
|
||||||
trackStream.release();
|
trackEncryptionBoxes = null;
|
||||||
}
|
trackGroups = null;
|
||||||
|
trackGroupElementIndices = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SequenceableLoader.Callback implementation
|
// SequenceableLoader.Callback implementation
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import com.google.android.exoplayer.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer.ExoPlayer;
|
import com.google.android.exoplayer.ExoPlayer;
|
||||||
import com.google.android.exoplayer.MediaCodecUtil;
|
import com.google.android.exoplayer.MediaCodecUtil;
|
||||||
import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
|
import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.TrackGroup;
|
import com.google.android.exoplayer.TrackGroup;
|
||||||
import com.google.android.exoplayer.TrackGroupArray;
|
import com.google.android.exoplayer.TrackGroupArray;
|
||||||
import com.google.android.exoplayer.TrackRenderer;
|
import com.google.android.exoplayer.TrackRenderer;
|
||||||
|
|
@ -44,6 +44,7 @@ import android.annotation.TargetApi;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -418,7 +419,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SampleSource buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
public SampleSourceProvider buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
||||||
BandwidthMeter bandwidthMeter) {
|
BandwidthMeter bandwidthMeter) {
|
||||||
return new DashSampleSource(manifestUri, dataSourceFactory, bandwidthMeter,
|
return new DashSampleSource(manifestUri, dataSourceFactory, bandwidthMeter,
|
||||||
MIN_LOADABLE_RETRY_COUNT, null, null);
|
MIN_LOADABLE_RETRY_COUNT, null, null);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import com.google.android.exoplayer.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer.ExoPlayer;
|
import com.google.android.exoplayer.ExoPlayer;
|
||||||
import com.google.android.exoplayer.ExoPlayerFactory;
|
import com.google.android.exoplayer.ExoPlayerFactory;
|
||||||
import com.google.android.exoplayer.Format;
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.SampleSource;
|
import com.google.android.exoplayer.SampleSourceProvider;
|
||||||
import com.google.android.exoplayer.SimpleExoPlayer;
|
import com.google.android.exoplayer.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer.TrackSelectionPolicy;
|
import com.google.android.exoplayer.TrackSelectionPolicy;
|
||||||
import com.google.android.exoplayer.audio.AudioTrack;
|
import com.google.android.exoplayer.audio.AudioTrack;
|
||||||
|
|
@ -129,7 +129,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
||||||
player = buildExoPlayer(host, surface, trackSelector);
|
player = buildExoPlayer(host, surface, trackSelector);
|
||||||
DataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(host, Util
|
DataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(host, Util
|
||||||
.getUserAgent(host, "ExoPlayerPlaybackTests"));
|
.getUserAgent(host, "ExoPlayerPlaybackTests"));
|
||||||
player.setSource(buildSource(host, dataSourceFactory, player.getBandwidthMeter()));
|
player.setSourceProvider(buildSource(host, dataSourceFactory, player.getBandwidthMeter()));
|
||||||
player.addListener(this);
|
player.addListener(this);
|
||||||
player.setDebugListener(this);
|
player.setDebugListener(this);
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
|
|
@ -288,7 +288,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
protected abstract SampleSource buildSource(HostActivity host,
|
protected abstract SampleSourceProvider buildSource(HostActivity host,
|
||||||
DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter);
|
DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter);
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue