mirror of
https://github.com/samsonjs/media.git
synced 2026-04-24 14:37:45 +00:00
Let DefaultUriDataSource load assets.
This commit is contained in:
parent
f474afbf5e
commit
675c7738c1
7 changed files with 116 additions and 48 deletions
|
|
@ -233,19 +233,19 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
audioCapabilities);
|
||||
case DemoUtil.TYPE_M4A: // There are no file format differences between M4A and MP4.
|
||||
case DemoUtil.TYPE_MP4:
|
||||
return new ExtractorRendererBuilder(userAgent, contentUri, debugTextView,
|
||||
return new ExtractorRendererBuilder(this, userAgent, contentUri, debugTextView,
|
||||
new Mp4Extractor());
|
||||
case DemoUtil.TYPE_MP3:
|
||||
return new ExtractorRendererBuilder(userAgent, contentUri, debugTextView,
|
||||
return new ExtractorRendererBuilder(this, userAgent, contentUri, debugTextView,
|
||||
new Mp3Extractor());
|
||||
case DemoUtil.TYPE_TS:
|
||||
return new ExtractorRendererBuilder(userAgent, contentUri, debugTextView,
|
||||
return new ExtractorRendererBuilder(this, userAgent, contentUri, debugTextView,
|
||||
new TsExtractor(0, audioCapabilities));
|
||||
case DemoUtil.TYPE_AAC:
|
||||
return new ExtractorRendererBuilder(userAgent, contentUri, debugTextView,
|
||||
return new ExtractorRendererBuilder(this, userAgent, contentUri, debugTextView,
|
||||
new AdtsExtractor());
|
||||
case DemoUtil.TYPE_WEBM:
|
||||
return new ExtractorRendererBuilder(userAgent, contentUri, debugTextView,
|
||||
return new ExtractorRendererBuilder(this, userAgent, contentUri, debugTextView,
|
||||
new WebmExtractor());
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported type: " + contentType);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ public class DashRendererBuilder implements RendererBuilder,
|
|||
this.player = player;
|
||||
this.callback = callback;
|
||||
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
|
||||
manifestDataSource = new DefaultUriDataSource(userAgent, null);
|
||||
manifestDataSource = new DefaultUriDataSource(context, userAgent);
|
||||
manifestFetcher = new ManifestFetcher<MediaPresentationDescription>(url, manifestDataSource,
|
||||
parser);
|
||||
manifestFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
||||
|
|
@ -232,10 +232,10 @@ public class DashRendererBuilder implements RendererBuilder,
|
|||
videoRenderer = null;
|
||||
debugRenderer = null;
|
||||
} else {
|
||||
DataSource videoDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
ChunkSource videoChunkSource = new DashChunkSource(manifestFetcher, videoAdaptationSetIndex,
|
||||
videoRepresentationIndices, videoDataSource, new AdaptiveEvaluator(bandwidthMeter),
|
||||
LIVE_EDGE_LATENCY_MS, elapsedRealtimeOffset);
|
||||
DataSource videoDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
ChunkSource videoChunkSource = new DashChunkSource(manifestFetcher,
|
||||
videoAdaptationSetIndex, videoRepresentationIndices, videoDataSource,
|
||||
new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS, elapsedRealtimeOffset);
|
||||
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl,
|
||||
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true, mainHandler, player,
|
||||
DemoPlayer.TYPE_VIDEO);
|
||||
|
|
@ -249,7 +249,7 @@ public class DashRendererBuilder implements RendererBuilder,
|
|||
List<ChunkSource> audioChunkSourceList = new ArrayList<ChunkSource>();
|
||||
List<String> audioTrackNameList = new ArrayList<String>();
|
||||
if (audioAdaptationSet != null) {
|
||||
DataSource audioDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
FormatEvaluator audioEvaluator = new FormatEvaluator.FixedEvaluator();
|
||||
List<Representation> audioRepresentations = audioAdaptationSet.representations;
|
||||
List<String> codecs = new ArrayList<String>();
|
||||
|
|
@ -304,7 +304,7 @@ public class DashRendererBuilder implements RendererBuilder,
|
|||
}
|
||||
|
||||
// Build the text chunk sources.
|
||||
DataSource textDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
DataSource textDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
FormatEvaluator textEvaluator = new FormatEvaluator.FixedEvaluator();
|
||||
List<ChunkSource> textChunkSourceList = new ArrayList<ChunkSource>();
|
||||
List<String> textTrackNameList = new ArrayList<String>();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.google.android.exoplayer.extractor.ExtractorSampleSource;
|
|||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DefaultUriDataSource;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaCodec;
|
||||
import android.net.Uri;
|
||||
import android.widget.TextView;
|
||||
|
|
@ -36,13 +37,15 @@ public class ExtractorRendererBuilder implements RendererBuilder {
|
|||
|
||||
private static final int BUFFER_SIZE = 10 * 1024 * 1024;
|
||||
|
||||
private final Context context;
|
||||
private final String userAgent;
|
||||
private final Uri uri;
|
||||
private final TextView debugTextView;
|
||||
private final Extractor extractor;
|
||||
|
||||
public ExtractorRendererBuilder(String userAgent, Uri uri, TextView debugTextView,
|
||||
Extractor extractor) {
|
||||
public ExtractorRendererBuilder(Context context, String userAgent, Uri uri,
|
||||
TextView debugTextView, Extractor extractor) {
|
||||
this.context = context;
|
||||
this.userAgent = userAgent;
|
||||
this.uri = uri;
|
||||
this.debugTextView = debugTextView;
|
||||
|
|
@ -52,7 +55,7 @@ public class ExtractorRendererBuilder implements RendererBuilder {
|
|||
@Override
|
||||
public void buildRenderers(DemoPlayer player, RendererBuilderCallback callback) {
|
||||
// Build the video and audio renderers.
|
||||
DataSource dataSource = new DefaultUriDataSource(userAgent, null);
|
||||
DataSource dataSource = new DefaultUriDataSource(context, userAgent);
|
||||
ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, extractor, 2,
|
||||
BUFFER_SIZE);
|
||||
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource,
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
|
|||
this.player = player;
|
||||
this.callback = callback;
|
||||
HlsPlaylistParser parser = new HlsPlaylistParser();
|
||||
ManifestFetcher<HlsPlaylist> playlistFetcher =
|
||||
new ManifestFetcher<HlsPlaylist>(url, new DefaultUriDataSource(userAgent, null), parser);
|
||||
ManifestFetcher<HlsPlaylist> playlistFetcher = new ManifestFetcher<HlsPlaylist>(url,
|
||||
new DefaultUriDataSource(context, userAgent), parser);
|
||||
playlistFetcher.singleLoad(player.getMainHandler().getLooper(), this);
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
|
|||
}
|
||||
}
|
||||
|
||||
DataSource dataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
HlsChunkSource chunkSource = new HlsChunkSource(dataSource, url, manifest, bandwidthMeter,
|
||||
variantIndices, HlsChunkSource.ADAPTIVE_MODE_SPLICE, audioCapabilities);
|
||||
HlsSampleSource sampleSource = new HlsSampleSource(chunkSource, true, 3, REQUESTED_BUFFER_SIZE,
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
|
|||
videoRenderer = null;
|
||||
debugRenderer = null;
|
||||
} else {
|
||||
DataSource videoDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
DataSource videoDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
ChunkSource videoChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
|
||||
videoStreamElementIndex, videoTrackIndices, videoDataSource,
|
||||
new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS);
|
||||
|
|
@ -184,7 +184,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
|
|||
} else {
|
||||
audioTrackNames = new String[audioStreamElementCount];
|
||||
ChunkSource[] audioChunkSources = new ChunkSource[audioStreamElementCount];
|
||||
DataSource audioDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
FormatEvaluator audioFormatEvaluator = new FormatEvaluator.FixedEvaluator();
|
||||
audioStreamElementCount = 0;
|
||||
for (int i = 0; i < manifest.streamElements.length; i++) {
|
||||
|
|
@ -215,7 +215,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
|
|||
} else {
|
||||
textTrackNames = new String[textStreamElementCount];
|
||||
ChunkSource[] textChunkSources = new ChunkSource[textStreamElementCount];
|
||||
DataSource ttmlDataSource = new DefaultUriDataSource(userAgent, bandwidthMeter);
|
||||
DataSource ttmlDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
|
||||
FormatEvaluator ttmlFormatEvaluator = new FormatEvaluator.FixedEvaluator();
|
||||
textStreamElementCount = 0;
|
||||
for (int i = 0; i < manifest.streamElements.length; i++) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer.upstream;
|
|||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.util.Assertions;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import java.io.EOFException;
|
||||
|
|
@ -32,7 +33,7 @@ public final class AssetDataSource implements UriDataSource {
|
|||
/**
|
||||
* Thrown when IOException is encountered during local asset read operation.
|
||||
*/
|
||||
public static class AssetDataSourceException extends IOException {
|
||||
public static final class AssetDataSourceException extends IOException {
|
||||
|
||||
public AssetDataSourceException(IOException cause) {
|
||||
super(cause);
|
||||
|
|
@ -51,8 +52,8 @@ public final class AssetDataSource implements UriDataSource {
|
|||
/**
|
||||
* Constructs a new {@link DataSource} that retrieves data from a local asset.
|
||||
*/
|
||||
public AssetDataSource(AssetManager assetManager) {
|
||||
this(assetManager, null);
|
||||
public AssetDataSource(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,8 +61,8 @@ public final class AssetDataSource implements UriDataSource {
|
|||
*
|
||||
* @param listener An optional listener. Specify {@code null} for no listener.
|
||||
*/
|
||||
public AssetDataSource(AssetManager assetManager, TransferListener listener) {
|
||||
this.assetManager = assetManager;
|
||||
public AssetDataSource(Context context, TransferListener listener) {
|
||||
this.assetManager = context.getAssets();
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,17 +17,49 @@ package com.google.android.exoplayer.upstream;
|
|||
|
||||
import com.google.android.exoplayer.util.Assertions;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A data source that fetches data from a local or remote {@link DataSpec}.
|
||||
* A {@link UriDataSource} that supports multiple URI schemes. The supported schemes are:
|
||||
*
|
||||
* <ul>
|
||||
* <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4).
|
||||
* <li>file: For fetching data from a local file (e.g. file:///path/to/media/media.mp4).
|
||||
* <li>asset: For fetching data from an asset in the application's apk (e.g. asset:///media.mp4).
|
||||
* </ul>
|
||||
*/
|
||||
public final class DefaultUriDataSource implements UriDataSource {
|
||||
|
||||
private static final String FILE_URI_SCHEME = "file";
|
||||
/**
|
||||
* Thrown when a {@link DefaultUriDataSource} is opened for a URI with an unsupported scheme.
|
||||
*/
|
||||
public static final class UnsupportedSchemeException extends IOException {
|
||||
|
||||
/**
|
||||
* The unsupported scheme.
|
||||
*/
|
||||
public final String scheme;
|
||||
|
||||
/**
|
||||
* @param scheme The unsupported scheme.
|
||||
*/
|
||||
public UnsupportedSchemeException(String scheme) {
|
||||
super("Unsupported URI scheme: " + scheme);
|
||||
this.scheme = scheme;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String SCHEME_HTTP = "http";
|
||||
private static final String SCHEME_HTTPS = "https";
|
||||
private static final String SCHEME_FILE = "file";
|
||||
private static final String SCHEME_ASSET = "asset";
|
||||
|
||||
private final UriDataSource fileDataSource;
|
||||
private final UriDataSource httpDataSource;
|
||||
private final UriDataSource fileDataSource;
|
||||
private final UriDataSource assetDataSource;
|
||||
|
||||
/**
|
||||
* {@code null} if no data source is open. Otherwise, equal to {@link #fileDataSource} if the open
|
||||
|
|
@ -36,54 +68,86 @@ public final class DefaultUriDataSource implements UriDataSource {
|
|||
private UriDataSource dataSource;
|
||||
|
||||
/**
|
||||
* Constructs a new data source that delegates to a {@link FileDataSource} for file URIs and a
|
||||
* {@link DefaultHttpDataSource} for other URIs.
|
||||
* Constructs a new instance.
|
||||
* <p>
|
||||
* The constructed instance will not follow cross-protocol redirects (i.e. redirects from HTTP to
|
||||
* HTTPS or vice versa) when fetching remote data. Cross-protocol redirects can be enabled by
|
||||
* using the {@link #DefaultUriDataSource(String, TransferListener, boolean)} constructor and
|
||||
* passing {@code true} as the final argument.
|
||||
* using {@link #DefaultUriDataSource(Context, TransferListener, String, boolean)} and passing
|
||||
* {@code true} as the final argument.
|
||||
*
|
||||
* @param context A context.
|
||||
* @param userAgent The User-Agent string that should be used when requesting remote data.
|
||||
* @param transferListener An optional listener.
|
||||
*/
|
||||
public DefaultUriDataSource(String userAgent, TransferListener transferListener) {
|
||||
this(userAgent, transferListener, false);
|
||||
public DefaultUriDataSource(Context context, String userAgent) {
|
||||
this(context, null, userAgent, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new data source that delegates to a {@link FileDataSource} for file URIs and a
|
||||
* {@link DefaultHttpDataSource} for other URIs.
|
||||
* Constructs a new instance.
|
||||
* <p>
|
||||
* The constructed instance will not follow cross-protocol redirects (i.e. redirects from HTTP to
|
||||
* HTTPS or vice versa) when fetching remote data. Cross-protocol redirects can be enabled by
|
||||
* using {@link #DefaultUriDataSource(Context, TransferListener, String, boolean)} and passing
|
||||
* {@code true} as the final argument.
|
||||
*
|
||||
* @param context A context.
|
||||
* @param listener An optional {@link TransferListener}.
|
||||
* @param userAgent The User-Agent string that should be used when requesting remote data.
|
||||
*/
|
||||
public DefaultUriDataSource(Context context, TransferListener listener, String userAgent) {
|
||||
this(context, listener, userAgent, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance, optionally configured to follow cross-protocol redirects.
|
||||
*
|
||||
* @param context A context.
|
||||
* @param listener An optional {@link TransferListener}.
|
||||
* @param userAgent The User-Agent string that should be used when requesting remote data.
|
||||
* @param transferListener An optional listener.
|
||||
* @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
|
||||
* to HTTPS and vice versa) are enabled when fetching remote data..
|
||||
*/
|
||||
public DefaultUriDataSource(String userAgent, TransferListener transferListener,
|
||||
public DefaultUriDataSource(Context context, TransferListener listener, String userAgent,
|
||||
boolean allowCrossProtocolRedirects) {
|
||||
this(new FileDataSource(transferListener),
|
||||
new DefaultHttpDataSource(userAgent, null, transferListener,
|
||||
this(context, listener,
|
||||
new DefaultHttpDataSource(userAgent, null, listener,
|
||||
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
|
||||
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, allowCrossProtocolRedirects));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new data source using {@code fileDataSource} for file URIs, and
|
||||
* {@code httpDataSource} for non-file URIs.
|
||||
* Constructs a new instance, using a provided {@link HttpDataSource} for fetching remote data.
|
||||
*
|
||||
* @param fileDataSource {@link UriDataSource} to use for file URIs.
|
||||
* @param context A context.
|
||||
* @param listener An optional {@link TransferListener}.
|
||||
* @param httpDataSource {@link UriDataSource} to use for non-file URIs.
|
||||
*/
|
||||
public DefaultUriDataSource(UriDataSource fileDataSource, UriDataSource httpDataSource) {
|
||||
this.fileDataSource = Assertions.checkNotNull(fileDataSource);
|
||||
public DefaultUriDataSource(Context context, TransferListener listener,
|
||||
UriDataSource httpDataSource) {
|
||||
this.httpDataSource = Assertions.checkNotNull(httpDataSource);
|
||||
this.fileDataSource = new FileDataSource(listener);
|
||||
this.assetDataSource = new AssetDataSource(context, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long open(DataSpec dataSpec) throws IOException {
|
||||
Assertions.checkState(dataSource == null);
|
||||
dataSource = FILE_URI_SCHEME.equals(dataSpec.uri.getScheme()) ? fileDataSource : httpDataSource;
|
||||
// Choose the correct source for the scheme.
|
||||
String scheme = dataSpec.uri.getScheme();
|
||||
if (SCHEME_HTTP.equals(scheme) || SCHEME_HTTPS.equals(scheme)) {
|
||||
dataSource = httpDataSource;
|
||||
} else if (SCHEME_FILE.equals(scheme)) {
|
||||
if (dataSpec.uri.getPath().startsWith("/android_asset/")) {
|
||||
dataSource = assetDataSource;
|
||||
} else {
|
||||
dataSource = fileDataSource;
|
||||
}
|
||||
} else if (SCHEME_ASSET.equals(scheme)) {
|
||||
dataSource = assetDataSource;
|
||||
} else {
|
||||
throw new UnsupportedSchemeException(scheme);
|
||||
}
|
||||
// Open the source and return.
|
||||
return dataSource.open(dataSpec);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue