Commit 985160a4 by tonihei Committed by Oliver Woodman

Use BaseDataSource for all internal leaf data sources.

This allows all leaf data sources (i.e. ones which do not forward the requests
to other data sources) to accept multiple listeners.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=203097587
parent e48b712a
...@@ -20,6 +20,8 @@ import android.support.annotation.NonNull; ...@@ -20,6 +20,8 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.upstream.BaseDataSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceException; import com.google.android.exoplayer2.upstream.DataSourceException;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource;
...@@ -42,10 +44,8 @@ import okhttp3.Request; ...@@ -42,10 +44,8 @@ import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
/** /** An {@link HttpDataSource} that delegates to Square's {@link Call.Factory}. */
* An {@link HttpDataSource} that delegates to Square's {@link Call.Factory}. public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
*/
public class OkHttpDataSource implements HttpDataSource {
static { static {
ExoPlayerLibraryInfo.registerModule("goog.exo.okhttp"); ExoPlayerLibraryInfo.registerModule("goog.exo.okhttp");
...@@ -58,7 +58,6 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -58,7 +58,6 @@ public class OkHttpDataSource implements HttpDataSource {
@Nullable private final String userAgent; @Nullable private final String userAgent;
@Nullable private final Predicate<String> contentTypePredicate; @Nullable private final Predicate<String> contentTypePredicate;
@Nullable private final TransferListener<? super OkHttpDataSource> listener;
@Nullable private final CacheControl cacheControl; @Nullable private final CacheControl cacheControl;
@Nullable private final RequestProperties defaultRequestProperties; @Nullable private final RequestProperties defaultRequestProperties;
...@@ -90,13 +89,15 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -90,13 +89,15 @@ public class OkHttpDataSource implements HttpDataSource {
* by the source. * by the source.
* @param userAgent An optional User-Agent string. * @param userAgent An optional User-Agent string.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link InvalidContentTypeException} is thrown from * predicate then a {@link InvalidContentTypeException} is thrown from {@link
* {@link #open(DataSpec)}. * #open(DataSpec)}.
* @param listener An optional listener. * @param listener An optional listener.
*/ */
public OkHttpDataSource(@NonNull Call.Factory callFactory, @Nullable String userAgent, public OkHttpDataSource(
@NonNull Call.Factory callFactory,
@Nullable String userAgent,
@Nullable Predicate<String> contentTypePredicate, @Nullable Predicate<String> contentTypePredicate,
@Nullable TransferListener<? super OkHttpDataSource> listener) { @Nullable TransferListener<? super DataSource> listener) {
this(callFactory, userAgent, contentTypePredicate, listener, null, null); this(callFactory, userAgent, contentTypePredicate, listener, null, null);
} }
...@@ -105,24 +106,30 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -105,24 +106,30 @@ public class OkHttpDataSource implements HttpDataSource {
* by the source. * by the source.
* @param userAgent An optional User-Agent string. * @param userAgent An optional User-Agent string.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link InvalidContentTypeException} is thrown from * predicate then a {@link InvalidContentTypeException} is thrown from {@link
* {@link #open(DataSpec)}. * #open(DataSpec)}.
* @param listener An optional listener. * @param listener An optional listener.
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header. * @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
* @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to * @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to
* the server as HTTP headers on every request. * the server as HTTP headers on every request.
*/ */
public OkHttpDataSource(@NonNull Call.Factory callFactory, @Nullable String userAgent, public OkHttpDataSource(
@NonNull Call.Factory callFactory,
@Nullable String userAgent,
@Nullable Predicate<String> contentTypePredicate, @Nullable Predicate<String> contentTypePredicate,
@Nullable TransferListener<? super OkHttpDataSource> listener, @Nullable TransferListener<? super DataSource> listener,
@Nullable CacheControl cacheControl, @Nullable RequestProperties defaultRequestProperties) { @Nullable CacheControl cacheControl,
@Nullable RequestProperties defaultRequestProperties) {
super(DataSource.TYPE_REMOTE);
this.callFactory = Assertions.checkNotNull(callFactory); this.callFactory = Assertions.checkNotNull(callFactory);
this.userAgent = userAgent; this.userAgent = userAgent;
this.contentTypePredicate = contentTypePredicate; this.contentTypePredicate = contentTypePredicate;
this.listener = listener;
this.cacheControl = cacheControl; this.cacheControl = cacheControl;
this.defaultRequestProperties = defaultRequestProperties; this.defaultRequestProperties = defaultRequestProperties;
this.requestProperties = new RequestProperties(); this.requestProperties = new RequestProperties();
if (listener != null) {
addTransferListener(listener);
}
} }
@Override @Override
...@@ -203,9 +210,7 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -203,9 +210,7 @@ public class OkHttpDataSource implements HttpDataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return bytesToRead; return bytesToRead;
} }
...@@ -224,9 +229,7 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -224,9 +229,7 @@ public class OkHttpDataSource implements HttpDataSource {
public void close() throws HttpDataSourceException { public void close() throws HttpDataSourceException {
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
closeConnectionQuietly(); closeConnectionQuietly();
} }
} }
...@@ -333,9 +336,7 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -333,9 +336,7 @@ public class OkHttpDataSource implements HttpDataSource {
throw new EOFException(); throw new EOFException();
} }
bytesSkipped += read; bytesSkipped += read;
if (listener != null) { bytesTransferred(read);
listener.onBytesTransferred(this, read);
}
} }
// Release the shared skip buffer. // Release the shared skip buffer.
...@@ -378,9 +379,7 @@ public class OkHttpDataSource implements HttpDataSource { ...@@ -378,9 +379,7 @@ public class OkHttpDataSource implements HttpDataSource {
} }
bytesRead += read; bytesRead += read;
if (listener != null) { bytesTransferred(read);
listener.onBytesTransferred(this, read);
}
return read; return read;
} }
......
...@@ -19,6 +19,7 @@ import android.net.Uri; ...@@ -19,6 +19,7 @@ import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.upstream.BaseDataSource;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
...@@ -26,17 +27,13 @@ import java.io.IOException; ...@@ -26,17 +27,13 @@ import java.io.IOException;
import net.butterflytv.rtmp_client.RtmpClient; import net.butterflytv.rtmp_client.RtmpClient;
import net.butterflytv.rtmp_client.RtmpClient.RtmpIOException; import net.butterflytv.rtmp_client.RtmpClient.RtmpIOException;
/** /** A Real-Time Messaging Protocol (RTMP) {@link DataSource}. */
* A Real-Time Messaging Protocol (RTMP) {@link DataSource}. public final class RtmpDataSource extends BaseDataSource {
*/
public final class RtmpDataSource implements DataSource {
static { static {
ExoPlayerLibraryInfo.registerModule("goog.exo.rtmp"); ExoPlayerLibraryInfo.registerModule("goog.exo.rtmp");
} }
@Nullable private final TransferListener<? super RtmpDataSource> listener;
private RtmpClient rtmpClient; private RtmpClient rtmpClient;
private Uri uri; private Uri uri;
...@@ -44,11 +41,12 @@ public final class RtmpDataSource implements DataSource { ...@@ -44,11 +41,12 @@ public final class RtmpDataSource implements DataSource {
this(null); this(null);
} }
/** /** @param listener An optional listener. */
* @param listener An optional listener. public RtmpDataSource(@Nullable TransferListener<? super DataSource> listener) {
*/ super(DataSource.TYPE_REMOTE);
public RtmpDataSource(@Nullable TransferListener<? super RtmpDataSource> listener) { if (listener != null) {
this.listener = listener; addTransferListener(listener);
}
} }
@Override @Override
...@@ -57,9 +55,7 @@ public final class RtmpDataSource implements DataSource { ...@@ -57,9 +55,7 @@ public final class RtmpDataSource implements DataSource {
rtmpClient.open(dataSpec.uri.toString(), false); rtmpClient.open(dataSpec.uri.toString(), false);
this.uri = dataSpec.uri; this.uri = dataSpec.uri;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return C.LENGTH_UNSET; return C.LENGTH_UNSET;
} }
...@@ -69,9 +65,7 @@ public final class RtmpDataSource implements DataSource { ...@@ -69,9 +65,7 @@ public final class RtmpDataSource implements DataSource {
if (bytesRead == -1) { if (bytesRead == -1) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} }
if (listener != null) { bytesTransferred(bytesRead);
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead; return bytesRead;
} }
...@@ -79,9 +73,7 @@ public final class RtmpDataSource implements DataSource { ...@@ -79,9 +73,7 @@ public final class RtmpDataSource implements DataSource {
public void close() { public void close() {
if (uri != null) { if (uri != null) {
uri = null; uri = null;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
if (rtmpClient != null) { if (rtmpClient != null) {
rtmpClient.close(); rtmpClient.close();
......
...@@ -25,17 +25,14 @@ import com.google.android.exoplayer2.upstream.TransferListener; ...@@ -25,17 +25,14 @@ import com.google.android.exoplayer2.upstream.TransferListener;
*/ */
public final class RtmpDataSourceFactory implements DataSource.Factory { public final class RtmpDataSourceFactory implements DataSource.Factory {
@Nullable private final @Nullable TransferListener<? super DataSource> listener;
private final TransferListener<? super RtmpDataSource> listener;
public RtmpDataSourceFactory() { public RtmpDataSourceFactory() {
this(null); this(null);
} }
/** /** @param listener An optional listener. */
* @param listener An optional listener. public RtmpDataSourceFactory(@Nullable TransferListener<? super DataSource> listener) {
*/
public RtmpDataSourceFactory(@Nullable TransferListener<? super RtmpDataSource> listener) {
this.listener = listener; this.listener = listener;
} }
......
...@@ -18,15 +18,14 @@ package com.google.android.exoplayer2.upstream; ...@@ -18,15 +18,14 @@ package com.google.android.exoplayer2.upstream;
import android.content.Context; import android.content.Context;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
/** /** A {@link DataSource} for reading from a local asset. */
* A {@link DataSource} for reading from a local asset. public final class AssetDataSource extends BaseDataSource {
*/
public final class AssetDataSource implements DataSource {
/** /**
* Thrown when an {@link IOException} is encountered reading a local asset. * Thrown when an {@link IOException} is encountered reading a local asset.
...@@ -40,10 +39,9 @@ public final class AssetDataSource implements DataSource { ...@@ -40,10 +39,9 @@ public final class AssetDataSource implements DataSource {
} }
private final AssetManager assetManager; private final AssetManager assetManager;
private final TransferListener<? super AssetDataSource> listener;
private Uri uri; private @Nullable Uri uri;
private InputStream inputStream; private @Nullable InputStream inputStream;
private long bytesRemaining; private long bytesRemaining;
private boolean opened; private boolean opened;
...@@ -58,9 +56,12 @@ public final class AssetDataSource implements DataSource { ...@@ -58,9 +56,12 @@ public final class AssetDataSource implements DataSource {
* @param context A context. * @param context A context.
* @param listener An optional listener. * @param listener An optional listener.
*/ */
public AssetDataSource(Context context, TransferListener<? super AssetDataSource> listener) { public AssetDataSource(Context context, @Nullable TransferListener<? super DataSource> listener) {
super(DataSource.TYPE_LOCAL);
this.assetManager = context.getAssets(); this.assetManager = context.getAssets();
this.listener = listener; if (listener != null) {
addTransferListener(listener);
}
} }
@Override @Override
...@@ -96,9 +97,7 @@ public final class AssetDataSource implements DataSource { ...@@ -96,9 +97,7 @@ public final class AssetDataSource implements DataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return bytesRemaining; return bytesRemaining;
} }
...@@ -129,14 +128,12 @@ public final class AssetDataSource implements DataSource { ...@@ -129,14 +128,12 @@ public final class AssetDataSource implements DataSource {
if (bytesRemaining != C.LENGTH_UNSET) { if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead; bytesRemaining -= bytesRead;
} }
if (listener != null) { bytesTransferred(bytesRead);
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead; return bytesRead;
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return uri; return uri;
} }
...@@ -153,9 +150,7 @@ public final class AssetDataSource implements DataSource { ...@@ -153,9 +150,7 @@ public final class AssetDataSource implements DataSource {
inputStream = null; inputStream = null;
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
} }
} }
......
...@@ -16,25 +16,26 @@ ...@@ -16,25 +16,26 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
/** /** A {@link DataSource} for reading from a byte array. */
* A {@link DataSource} for reading from a byte array. public final class ByteArrayDataSource extends BaseDataSource {
*/
public final class ByteArrayDataSource implements DataSource {
private final byte[] data; private final byte[] data;
private Uri uri; private @Nullable Uri uri;
private int readPosition; private int readPosition;
private int bytesRemaining; private int bytesRemaining;
private boolean opened;
/** /**
* @param data The data to be read. * @param data The data to be read.
*/ */
public ByteArrayDataSource(byte[] data) { public ByteArrayDataSource(byte[] data) {
super(DataSource.TYPE_LOCAL);
Assertions.checkNotNull(data); Assertions.checkNotNull(data);
Assertions.checkArgument(data.length > 0); Assertions.checkArgument(data.length > 0);
this.data = data; this.data = data;
...@@ -50,6 +51,8 @@ public final class ByteArrayDataSource implements DataSource { ...@@ -50,6 +51,8 @@ public final class ByteArrayDataSource implements DataSource {
throw new IOException("Unsatisfiable range: [" + readPosition + ", " + dataSpec.length throw new IOException("Unsatisfiable range: [" + readPosition + ", " + dataSpec.length
+ "], length: " + data.length); + "], length: " + data.length);
} }
opened = true;
transferStarted(dataSpec);
return bytesRemaining; return bytesRemaining;
} }
...@@ -65,16 +68,21 @@ public final class ByteArrayDataSource implements DataSource { ...@@ -65,16 +68,21 @@ public final class ByteArrayDataSource implements DataSource {
System.arraycopy(data, readPosition, buffer, offset, readLength); System.arraycopy(data, readPosition, buffer, offset, readLength);
readPosition += readLength; readPosition += readLength;
bytesRemaining -= readLength; bytesRemaining -= readLength;
bytesTransferred(readLength);
return readLength; return readLength;
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return uri; return uri;
} }
@Override @Override
public void close() throws IOException { public void close() throws IOException {
if (opened) {
opened = false;
transferEnded();
}
uri = null; uri = null;
} }
......
...@@ -19,6 +19,7 @@ import android.content.ContentResolver; ...@@ -19,6 +19,7 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import java.io.EOFException; import java.io.EOFException;
import java.io.FileInputStream; import java.io.FileInputStream;
...@@ -26,10 +27,8 @@ import java.io.FileNotFoundException; ...@@ -26,10 +27,8 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
/** /** A {@link DataSource} for reading from a content URI. */
* A {@link DataSource} for reading from a content URI. public final class ContentDataSource extends BaseDataSource {
*/
public final class ContentDataSource implements DataSource {
/** /**
* Thrown when an {@link IOException} is encountered reading from a content URI. * Thrown when an {@link IOException} is encountered reading from a content URI.
...@@ -43,11 +42,10 @@ public final class ContentDataSource implements DataSource { ...@@ -43,11 +42,10 @@ public final class ContentDataSource implements DataSource {
} }
private final ContentResolver resolver; private final ContentResolver resolver;
private final TransferListener<? super ContentDataSource> listener;
private Uri uri; private @Nullable Uri uri;
private AssetFileDescriptor assetFileDescriptor; private @Nullable AssetFileDescriptor assetFileDescriptor;
private FileInputStream inputStream; private @Nullable FileInputStream inputStream;
private long bytesRemaining; private long bytesRemaining;
private boolean opened; private boolean opened;
...@@ -62,9 +60,13 @@ public final class ContentDataSource implements DataSource { ...@@ -62,9 +60,13 @@ public final class ContentDataSource implements DataSource {
* @param context A context. * @param context A context.
* @param listener An optional listener. * @param listener An optional listener.
*/ */
public ContentDataSource(Context context, TransferListener<? super ContentDataSource> listener) { public ContentDataSource(
Context context, @Nullable TransferListener<? super DataSource> listener) {
super(DataSource.TYPE_LOCAL);
this.resolver = context.getContentResolver(); this.resolver = context.getContentResolver();
this.listener = listener; if (listener != null) {
addTransferListener(listener);
}
} }
@Override @Override
...@@ -102,9 +104,7 @@ public final class ContentDataSource implements DataSource { ...@@ -102,9 +104,7 @@ public final class ContentDataSource implements DataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return bytesRemaining; return bytesRemaining;
} }
...@@ -136,14 +136,12 @@ public final class ContentDataSource implements DataSource { ...@@ -136,14 +136,12 @@ public final class ContentDataSource implements DataSource {
if (bytesRemaining != C.LENGTH_UNSET) { if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead; bytesRemaining -= bytesRead;
} }
if (listener != null) { bytesTransferred(bytesRead);
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead; return bytesRead;
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return uri; return uri;
} }
...@@ -168,9 +166,7 @@ public final class ContentDataSource implements DataSource { ...@@ -168,9 +166,7 @@ public final class ContentDataSource implements DataSource {
assetFileDescriptor = null; assetFileDescriptor = null;
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
} }
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import android.util.Base64; import android.util.Base64;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
...@@ -23,16 +24,18 @@ import com.google.android.exoplayer2.util.Util; ...@@ -23,16 +24,18 @@ import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.net.URLDecoder; import java.net.URLDecoder;
/** /** A {@link DataSource} for reading data URLs, as defined by RFC 2397. */
* A {@link DataSource} for reading data URLs, as defined by RFC 2397. public final class DataSchemeDataSource extends BaseDataSource {
*/
public final class DataSchemeDataSource implements DataSource {
public static final String SCHEME_DATA = "data"; public static final String SCHEME_DATA = "data";
private DataSpec dataSpec; private @Nullable DataSpec dataSpec;
private int bytesRead; private int bytesRead;
private byte[] data; private @Nullable byte[] data;
public DataSchemeDataSource() {
super(DataSource.TYPE_LOCAL);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
...@@ -57,6 +60,7 @@ public final class DataSchemeDataSource implements DataSource { ...@@ -57,6 +60,7 @@ public final class DataSchemeDataSource implements DataSource {
// TODO: Add support for other charsets. // TODO: Add support for other charsets.
data = URLDecoder.decode(dataString, C.ASCII_NAME).getBytes(); data = URLDecoder.decode(dataString, C.ASCII_NAME).getBytes();
} }
transferStarted(dataSpec);
return data.length; return data.length;
} }
...@@ -72,18 +76,22 @@ public final class DataSchemeDataSource implements DataSource { ...@@ -72,18 +76,22 @@ public final class DataSchemeDataSource implements DataSource {
readLength = Math.min(readLength, remainingBytes); readLength = Math.min(readLength, remainingBytes);
System.arraycopy(data, bytesRead, buffer, offset, readLength); System.arraycopy(data, bytesRead, buffer, offset, readLength);
bytesRead += readLength; bytesRead += readLength;
bytesTransferred(readLength);
return readLength; return readLength;
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return dataSpec != null ? dataSpec.uri : null; return dataSpec != null ? dataSpec.uri : null;
} }
@Override @Override
public void close() throws IOException { public void close() throws IOException {
if (data != null) {
data = null;
transferEnded();
}
dataSpec = null; dataSpec = null;
data = null;
} }
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
...@@ -41,13 +42,13 @@ import java.util.regex.Pattern; ...@@ -41,13 +42,13 @@ import java.util.regex.Pattern;
/** /**
* An {@link HttpDataSource} that uses Android's {@link HttpURLConnection}. * An {@link HttpDataSource} that uses Android's {@link HttpURLConnection}.
* <p> *
* By default this implementation will not follow cross-protocol redirects (i.e. redirects from * <p>By default this implementation will not follow cross-protocol redirects (i.e. redirects from
* HTTP to HTTPS or vice versa). Cross-protocol redirects can be enabled by using the * HTTP to HTTPS or vice versa). Cross-protocol redirects can be enabled by using the {@link
* {@link #DefaultHttpDataSource(String, Predicate, TransferListener, int, int, boolean, * #DefaultHttpDataSource(String, Predicate, TransferListener, int, int, boolean,
* RequestProperties)} constructor and passing {@code true} as the second last argument. * RequestProperties)} constructor and passing {@code true} as the second last argument.
*/ */
public class DefaultHttpDataSource implements HttpDataSource { public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSource {
/** /**
* The default connection timeout, in milliseconds. * The default connection timeout, in milliseconds.
...@@ -69,14 +70,13 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -69,14 +70,13 @@ public class DefaultHttpDataSource implements HttpDataSource {
private final int connectTimeoutMillis; private final int connectTimeoutMillis;
private final int readTimeoutMillis; private final int readTimeoutMillis;
private final String userAgent; private final String userAgent;
private final Predicate<String> contentTypePredicate; private final @Nullable Predicate<String> contentTypePredicate;
private final RequestProperties defaultRequestProperties; private final @Nullable RequestProperties defaultRequestProperties;
private final RequestProperties requestProperties; private final RequestProperties requestProperties;
private final TransferListener<? super DefaultHttpDataSource> listener;
private DataSpec dataSpec; private @Nullable DataSpec dataSpec;
private HttpURLConnection connection; private @Nullable HttpURLConnection connection;
private InputStream inputStream; private @Nullable InputStream inputStream;
private boolean opened; private boolean opened;
private long bytesToSkip; private long bytesToSkip;
...@@ -88,22 +88,24 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -88,22 +88,24 @@ public class DefaultHttpDataSource implements HttpDataSource {
/** /**
* @param userAgent The User-Agent string that should be used. * @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from * predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from {@link
* {@link #open(DataSpec)}. * #open(DataSpec)}.
*/ */
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate) { public DefaultHttpDataSource(String userAgent, @Nullable Predicate<String> contentTypePredicate) {
this(userAgent, contentTypePredicate, null); this(userAgent, contentTypePredicate, null);
} }
/** /**
* @param userAgent The User-Agent string that should be used. * @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from * predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from {@link
* {@link #open(DataSpec)}. * #open(DataSpec)}.
* @param listener An optional listener. * @param listener An optional listener.
*/ */
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, public DefaultHttpDataSource(
TransferListener<? super DefaultHttpDataSource> listener) { String userAgent,
@Nullable Predicate<String> contentTypePredicate,
@Nullable TransferListener<? super DataSource> listener) {
this(userAgent, contentTypePredicate, listener, DEFAULT_CONNECT_TIMEOUT_MILLIS, this(userAgent, contentTypePredicate, listener, DEFAULT_CONNECT_TIMEOUT_MILLIS,
DEFAULT_READ_TIMEOUT_MILLIS); DEFAULT_READ_TIMEOUT_MILLIS);
} }
...@@ -111,16 +113,19 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -111,16 +113,19 @@ public class DefaultHttpDataSource implements HttpDataSource {
/** /**
* @param userAgent The User-Agent string that should be used. * @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from * predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from {@link
* {@link #open(DataSpec)}. * #open(DataSpec)}.
* @param listener An optional listener. * @param listener An optional listener.
* @param connectTimeoutMillis The connection timeout, in milliseconds. A timeout of zero is * @param connectTimeoutMillis The connection timeout, in milliseconds. A timeout of zero is
* interpreted as an infinite timeout. * interpreted as an infinite timeout.
* @param readTimeoutMillis The read timeout, in milliseconds. A timeout of zero is interpreted * @param readTimeoutMillis The read timeout, in milliseconds. A timeout of zero is interpreted as
* as an infinite timeout. * an infinite timeout.
*/ */
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, public DefaultHttpDataSource(
TransferListener<? super DefaultHttpDataSource> listener, int connectTimeoutMillis, String userAgent,
@Nullable Predicate<String> contentTypePredicate,
@Nullable TransferListener<? super DataSource> listener,
int connectTimeoutMillis,
int readTimeoutMillis) { int readTimeoutMillis) {
this(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis, false, this(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis, false,
null); null);
...@@ -129,35 +134,42 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -129,35 +134,42 @@ public class DefaultHttpDataSource implements HttpDataSource {
/** /**
* @param userAgent The User-Agent string that should be used. * @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from * predicate then a {@link HttpDataSource.InvalidContentTypeException} is thrown from {@link
* {@link #open(DataSpec)}. * #open(DataSpec)}.
* @param listener An optional listener. * @param listener An optional listener.
* @param connectTimeoutMillis The connection timeout, in milliseconds. A timeout of zero is * @param connectTimeoutMillis The connection timeout, in milliseconds. A timeout of zero is
* interpreted as an infinite timeout. Pass {@link #DEFAULT_CONNECT_TIMEOUT_MILLIS} to use * interpreted as an infinite timeout. Pass {@link #DEFAULT_CONNECT_TIMEOUT_MILLIS} to use the
* the default value. * default value.
* @param readTimeoutMillis The read timeout, in milliseconds. A timeout of zero is interpreted * @param readTimeoutMillis The read timeout, in milliseconds. A timeout of zero is interpreted as
* as an infinite timeout. Pass {@link #DEFAULT_READ_TIMEOUT_MILLIS} to use the default value. * an infinite timeout. Pass {@link #DEFAULT_READ_TIMEOUT_MILLIS} to use the default value.
* @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
* to HTTPS and vice versa) are enabled. * to HTTPS and vice versa) are enabled.
* @param defaultRequestProperties The default request properties to be sent to the server as * @param defaultRequestProperties The default request properties to be sent to the server as HTTP
* HTTP headers or {@code null} if not required. * headers or {@code null} if not required.
*/ */
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, public DefaultHttpDataSource(
TransferListener<? super DefaultHttpDataSource> listener, int connectTimeoutMillis, String userAgent,
int readTimeoutMillis, boolean allowCrossProtocolRedirects, @Nullable Predicate<String> contentTypePredicate,
RequestProperties defaultRequestProperties) { @Nullable TransferListener<? super DataSource> listener,
int connectTimeoutMillis,
int readTimeoutMillis,
boolean allowCrossProtocolRedirects,
@Nullable RequestProperties defaultRequestProperties) {
super(DataSource.TYPE_REMOTE);
this.userAgent = Assertions.checkNotEmpty(userAgent); this.userAgent = Assertions.checkNotEmpty(userAgent);
this.contentTypePredicate = contentTypePredicate; this.contentTypePredicate = contentTypePredicate;
this.listener = listener;
this.requestProperties = new RequestProperties(); this.requestProperties = new RequestProperties();
this.connectTimeoutMillis = connectTimeoutMillis; this.connectTimeoutMillis = connectTimeoutMillis;
this.readTimeoutMillis = readTimeoutMillis; this.readTimeoutMillis = readTimeoutMillis;
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects; this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
this.defaultRequestProperties = defaultRequestProperties; this.defaultRequestProperties = defaultRequestProperties;
if (listener != null) {
addTransferListener(listener);
}
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return connection == null ? null : Uri.parse(connection.getURL().toString()); return connection == null ? null : Uri.parse(connection.getURL().toString());
} }
...@@ -254,9 +266,7 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -254,9 +266,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return bytesToRead; return bytesToRead;
} }
...@@ -287,9 +297,7 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -287,9 +297,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
closeConnectionQuietly(); closeConnectionQuietly();
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
} }
} }
...@@ -534,9 +542,7 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -534,9 +542,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
throw new EOFException(); throw new EOFException();
} }
bytesSkipped += read; bytesSkipped += read;
if (listener != null) { bytesTransferred(read);
listener.onBytesTransferred(this, read);
}
} }
// Release the shared skip buffer. // Release the shared skip buffer.
...@@ -579,9 +585,7 @@ public class DefaultHttpDataSource implements HttpDataSource { ...@@ -579,9 +585,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
} }
bytesRead += read; bytesRead += read;
if (listener != null) { bytesTransferred(read);
listener.onBytesTransferred(this, read);
}
return read; return read;
} }
......
...@@ -16,15 +16,14 @@ ...@@ -16,15 +16,14 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
/** /** A {@link DataSource} for reading local files. */
* A {@link DataSource} for reading local files. public final class FileDataSource extends BaseDataSource {
*/
public final class FileDataSource implements DataSource {
/** /**
* Thrown when IOException is encountered during local file read operation. * Thrown when IOException is encountered during local file read operation.
...@@ -37,10 +36,8 @@ public final class FileDataSource implements DataSource { ...@@ -37,10 +36,8 @@ public final class FileDataSource implements DataSource {
} }
private final TransferListener<? super FileDataSource> listener; private @Nullable RandomAccessFile file;
private @Nullable Uri uri;
private RandomAccessFile file;
private Uri uri;
private long bytesRemaining; private long bytesRemaining;
private boolean opened; private boolean opened;
...@@ -48,11 +45,12 @@ public final class FileDataSource implements DataSource { ...@@ -48,11 +45,12 @@ public final class FileDataSource implements DataSource {
this(null); this(null);
} }
/** /** @param listener An optional listener. */
* @param listener An optional listener. public FileDataSource(@Nullable TransferListener<? super DataSource> listener) {
*/ super(DataSource.TYPE_LOCAL);
public FileDataSource(TransferListener<? super FileDataSource> listener) { if (listener != null) {
this.listener = listener; addTransferListener(listener);
}
} }
@Override @Override
...@@ -71,9 +69,7 @@ public final class FileDataSource implements DataSource { ...@@ -71,9 +69,7 @@ public final class FileDataSource implements DataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return bytesRemaining; return bytesRemaining;
} }
...@@ -94,9 +90,7 @@ public final class FileDataSource implements DataSource { ...@@ -94,9 +90,7 @@ public final class FileDataSource implements DataSource {
if (bytesRead > 0) { if (bytesRead > 0) {
bytesRemaining -= bytesRead; bytesRemaining -= bytesRead;
if (listener != null) { bytesTransferred(bytesRead);
listener.onBytesTransferred(this, bytesRead);
}
} }
return bytesRead; return bytesRead;
...@@ -104,7 +98,7 @@ public final class FileDataSource implements DataSource { ...@@ -104,7 +98,7 @@ public final class FileDataSource implements DataSource {
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return uri; return uri;
} }
...@@ -121,9 +115,7 @@ public final class FileDataSource implements DataSource { ...@@ -121,9 +115,7 @@ public final class FileDataSource implements DataSource {
file = null; file = null;
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
} }
} }
......
...@@ -15,18 +15,20 @@ ...@@ -15,18 +15,20 @@
*/ */
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.support.annotation.Nullable;
/** /**
* A {@link DataSource.Factory} that produces {@link FileDataSource}. * A {@link DataSource.Factory} that produces {@link FileDataSource}.
*/ */
public final class FileDataSourceFactory implements DataSource.Factory { public final class FileDataSourceFactory implements DataSource.Factory {
private final TransferListener<? super FileDataSource> listener; private final @Nullable TransferListener<? super DataSource> listener;
public FileDataSourceFactory() { public FileDataSourceFactory() {
this(null); this(null);
} }
public FileDataSourceFactory(TransferListener<? super FileDataSource> listener) { public FileDataSourceFactory(@Nullable TransferListener<? super DataSource> listener) {
this.listener = listener; this.listener = listener;
} }
......
...@@ -19,6 +19,7 @@ import android.content.Context; ...@@ -19,6 +19,7 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import java.io.EOFException; import java.io.EOFException;
...@@ -28,12 +29,12 @@ import java.io.InputStream; ...@@ -28,12 +29,12 @@ import java.io.InputStream;
/** /**
* A {@link DataSource} for reading a raw resource inside the APK. * A {@link DataSource} for reading a raw resource inside the APK.
* <p> *
* URIs supported by this source are of the form {@code rawresource:///rawResourceId}, where * <p>URIs supported by this source are of the form {@code rawresource:///rawResourceId}, where
* rawResourceId is the integer identifier of a raw resource. {@link #buildRawResourceUri(int)} can * rawResourceId is the integer identifier of a raw resource. {@link #buildRawResourceUri(int)} can
* be used to build {@link Uri}s in this format. * be used to build {@link Uri}s in this format.
*/ */
public final class RawResourceDataSource implements DataSource { public final class RawResourceDataSource extends BaseDataSource {
/** /**
* Thrown when an {@link IOException} is encountered reading from a raw resource. * Thrown when an {@link IOException} is encountered reading from a raw resource.
...@@ -62,11 +63,10 @@ public final class RawResourceDataSource implements DataSource { ...@@ -62,11 +63,10 @@ public final class RawResourceDataSource implements DataSource {
public static final String RAW_RESOURCE_SCHEME = "rawresource"; public static final String RAW_RESOURCE_SCHEME = "rawresource";
private final Resources resources; private final Resources resources;
private final TransferListener<? super RawResourceDataSource> listener;
private Uri uri; private @Nullable Uri uri;
private AssetFileDescriptor assetFileDescriptor; private @Nullable AssetFileDescriptor assetFileDescriptor;
private InputStream inputStream; private @Nullable InputStream inputStream;
private long bytesRemaining; private long bytesRemaining;
private boolean opened; private boolean opened;
...@@ -81,10 +81,13 @@ public final class RawResourceDataSource implements DataSource { ...@@ -81,10 +81,13 @@ public final class RawResourceDataSource implements DataSource {
* @param context A context. * @param context A context.
* @param listener An optional listener. * @param listener An optional listener.
*/ */
public RawResourceDataSource(Context context, public RawResourceDataSource(
TransferListener<? super RawResourceDataSource> listener) { Context context, @Nullable TransferListener<? super DataSource> listener) {
super(DataSource.TYPE_LOCAL);
this.resources = context.getResources(); this.resources = context.getResources();
this.listener = listener; if (listener != null) {
addTransferListener(listener);
}
} }
@Override @Override
...@@ -124,9 +127,7 @@ public final class RawResourceDataSource implements DataSource { ...@@ -124,9 +127,7 @@ public final class RawResourceDataSource implements DataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return bytesRemaining; return bytesRemaining;
} }
...@@ -158,14 +159,12 @@ public final class RawResourceDataSource implements DataSource { ...@@ -158,14 +159,12 @@ public final class RawResourceDataSource implements DataSource {
if (bytesRemaining != C.LENGTH_UNSET) { if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead; bytesRemaining -= bytesRead;
} }
if (listener != null) { bytesTransferred(bytesRead);
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead; return bytesRead;
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return uri; return uri;
} }
...@@ -190,9 +189,7 @@ public final class RawResourceDataSource implements DataSource { ...@@ -190,9 +189,7 @@ public final class RawResourceDataSource implements DataSource {
assetFileDescriptor = null; assetFileDescriptor = null;
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
} }
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import java.io.IOException; import java.io.IOException;
import java.net.DatagramPacket; import java.net.DatagramPacket;
...@@ -25,10 +26,8 @@ import java.net.InetSocketAddress; ...@@ -25,10 +26,8 @@ import java.net.InetSocketAddress;
import java.net.MulticastSocket; import java.net.MulticastSocket;
import java.net.SocketException; import java.net.SocketException;
/** /** A UDP {@link DataSource}. */
* A UDP {@link DataSource}. public final class UdpDataSource extends BaseDataSource {
*/
public final class UdpDataSource implements DataSource {
/** /**
* Thrown when an error is encountered when trying to read from a {@link UdpDataSource}. * Thrown when an error is encountered when trying to read from a {@link UdpDataSource}.
...@@ -51,24 +50,21 @@ public final class UdpDataSource implements DataSource { ...@@ -51,24 +50,21 @@ public final class UdpDataSource implements DataSource {
*/ */
public static final int DEAFULT_SOCKET_TIMEOUT_MILLIS = 8 * 1000; public static final int DEAFULT_SOCKET_TIMEOUT_MILLIS = 8 * 1000;
private final TransferListener<? super UdpDataSource> listener;
private final int socketTimeoutMillis; private final int socketTimeoutMillis;
private final byte[] packetBuffer; private final byte[] packetBuffer;
private final DatagramPacket packet; private final DatagramPacket packet;
private Uri uri; private @Nullable Uri uri;
private DatagramSocket socket; private @Nullable DatagramSocket socket;
private MulticastSocket multicastSocket; private @Nullable MulticastSocket multicastSocket;
private InetAddress address; private @Nullable InetAddress address;
private InetSocketAddress socketAddress; private @Nullable InetSocketAddress socketAddress;
private boolean opened; private boolean opened;
private int packetRemaining; private int packetRemaining;
/** /** @param listener An optional listener. */
* @param listener An optional listener. public UdpDataSource(@Nullable TransferListener<? super DataSource> listener) {
*/
public UdpDataSource(TransferListener<? super UdpDataSource> listener) {
this(listener, DEFAULT_MAX_PACKET_SIZE); this(listener, DEFAULT_MAX_PACKET_SIZE);
} }
...@@ -76,7 +72,7 @@ public final class UdpDataSource implements DataSource { ...@@ -76,7 +72,7 @@ public final class UdpDataSource implements DataSource {
* @param listener An optional listener. * @param listener An optional listener.
* @param maxPacketSize The maximum datagram packet size, in bytes. * @param maxPacketSize The maximum datagram packet size, in bytes.
*/ */
public UdpDataSource(TransferListener<? super UdpDataSource> listener, int maxPacketSize) { public UdpDataSource(@Nullable TransferListener<? super DataSource> listener, int maxPacketSize) {
this(listener, maxPacketSize, DEAFULT_SOCKET_TIMEOUT_MILLIS); this(listener, maxPacketSize, DEAFULT_SOCKET_TIMEOUT_MILLIS);
} }
...@@ -86,12 +82,17 @@ public final class UdpDataSource implements DataSource { ...@@ -86,12 +82,17 @@ public final class UdpDataSource implements DataSource {
* @param socketTimeoutMillis The socket timeout in milliseconds. A timeout of zero is interpreted * @param socketTimeoutMillis The socket timeout in milliseconds. A timeout of zero is interpreted
* as an infinite timeout. * as an infinite timeout.
*/ */
public UdpDataSource(TransferListener<? super UdpDataSource> listener, int maxPacketSize, public UdpDataSource(
@Nullable TransferListener<? super DataSource> listener,
int maxPacketSize,
int socketTimeoutMillis) { int socketTimeoutMillis) {
this.listener = listener; super(DataSource.TYPE_REMOTE);
this.socketTimeoutMillis = socketTimeoutMillis; this.socketTimeoutMillis = socketTimeoutMillis;
packetBuffer = new byte[maxPacketSize]; packetBuffer = new byte[maxPacketSize];
packet = new DatagramPacket(packetBuffer, 0, maxPacketSize); packet = new DatagramPacket(packetBuffer, 0, maxPacketSize);
if (listener != null) {
addTransferListener(listener);
}
} }
@Override @Override
...@@ -121,9 +122,7 @@ public final class UdpDataSource implements DataSource { ...@@ -121,9 +122,7 @@ public final class UdpDataSource implements DataSource {
} }
opened = true; opened = true;
if (listener != null) { transferStarted(dataSpec);
listener.onTransferStart(this, dataSpec);
}
return C.LENGTH_UNSET; return C.LENGTH_UNSET;
} }
...@@ -141,9 +140,7 @@ public final class UdpDataSource implements DataSource { ...@@ -141,9 +140,7 @@ public final class UdpDataSource implements DataSource {
throw new UdpDataSourceException(e); throw new UdpDataSourceException(e);
} }
packetRemaining = packet.getLength(); packetRemaining = packet.getLength();
if (listener != null) { bytesTransferred(packetRemaining);
listener.onBytesTransferred(this, packetRemaining);
}
} }
int packetOffset = packet.getLength() - packetRemaining; int packetOffset = packet.getLength() - packetRemaining;
...@@ -154,7 +151,7 @@ public final class UdpDataSource implements DataSource { ...@@ -154,7 +151,7 @@ public final class UdpDataSource implements DataSource {
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return uri; return uri;
} }
...@@ -178,9 +175,7 @@ public final class UdpDataSource implements DataSource { ...@@ -178,9 +175,7 @@ public final class UdpDataSource implements DataSource {
packetRemaining = 0; packetRemaining = 0;
if (opened) { if (opened) {
opened = false; opened = false;
if (listener != null) { transferEnded();
listener.onTransferEnd(this);
}
} }
} }
......
...@@ -20,6 +20,7 @@ import android.support.annotation.Nullable; ...@@ -20,6 +20,7 @@ import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData; import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment; import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
import com.google.android.exoplayer2.upstream.BaseDataSource;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceException; import com.google.android.exoplayer2.upstream.DataSourceException;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
...@@ -32,18 +33,20 @@ import java.util.ArrayList; ...@@ -32,18 +33,20 @@ import java.util.ArrayList;
* A fake {@link DataSource} capable of simulating various scenarios. It uses a {@link FakeDataSet} * A fake {@link DataSource} capable of simulating various scenarios. It uses a {@link FakeDataSet}
* instance which determines the response to data access calls. * instance which determines the response to data access calls.
*/ */
public class FakeDataSource implements DataSource { public class FakeDataSource extends BaseDataSource {
/** /**
* Factory to create a {@link FakeDataSource}. * Factory to create a {@link FakeDataSource}.
*/ */
public static class Factory implements DataSource.Factory { public static class Factory implements DataSource.Factory {
protected final TransferListener<? super FakeDataSource> transferListener; protected final TransferListener<? super DataSource> transferListener;
protected FakeDataSet fakeDataSet; protected FakeDataSet fakeDataSet;
protected @DataSource.Type int dataSourceType;
public Factory(@Nullable TransferListener<? super FakeDataSource> transferListener) { public Factory(@Nullable TransferListener<? super DataSource> transferListener) {
this.transferListener = transferListener; this.transferListener = transferListener;
this.dataSourceType = DataSource.TYPE_LOCAL;
} }
public final Factory setFakeDataSet(FakeDataSet fakeDataSet) { public final Factory setFakeDataSet(FakeDataSet fakeDataSet) {
...@@ -51,19 +54,23 @@ public class FakeDataSource implements DataSource { ...@@ -51,19 +54,23 @@ public class FakeDataSource implements DataSource {
return this; return this;
} }
public final Factory setDataSourceType(@DataSource.Type int dataSourceType) {
this.dataSourceType = dataSourceType;
return this;
}
@Override @Override
public DataSource createDataSource() { public DataSource createDataSource() {
return new FakeDataSource(fakeDataSet, transferListener); return new FakeDataSource(fakeDataSet, transferListener, dataSourceType);
} }
} }
private final FakeDataSet fakeDataSet; private final FakeDataSet fakeDataSet;
private final TransferListener<? super FakeDataSource> transferListener;
private final ArrayList<DataSpec> openedDataSpecs; private final ArrayList<DataSpec> openedDataSpecs;
private Uri uri; private Uri uri;
private boolean opened; private boolean openCalled;
private boolean sourceOpened;
private FakeData fakeData; private FakeData fakeData;
private int currentSegmentIndex; private int currentSegmentIndex;
private long bytesRemaining; private long bytesRemaining;
...@@ -73,15 +80,20 @@ public class FakeDataSource implements DataSource { ...@@ -73,15 +80,20 @@ public class FakeDataSource implements DataSource {
} }
public FakeDataSource(FakeDataSet fakeDataSet) { public FakeDataSource(FakeDataSet fakeDataSet) {
this(fakeDataSet, null); this(fakeDataSet, null, DataSource.TYPE_LOCAL);
} }
public FakeDataSource(FakeDataSet fakeDataSet, public FakeDataSource(
@Nullable TransferListener<? super FakeDataSource> transferListener) { FakeDataSet fakeDataSet,
@Nullable TransferListener<? super DataSource> transferListener,
@DataSource.Type int dataSourceType) {
super(dataSourceType);
Assertions.checkNotNull(fakeDataSet); Assertions.checkNotNull(fakeDataSet);
this.fakeDataSet = fakeDataSet; this.fakeDataSet = fakeDataSet;
this.transferListener = transferListener;
this.openedDataSpecs = new ArrayList<>(); this.openedDataSpecs = new ArrayList<>();
if (transferListener != null) {
addTransferListener(transferListener);
}
} }
public final FakeDataSet getDataSet() { public final FakeDataSet getDataSet() {
...@@ -90,9 +102,9 @@ public class FakeDataSource implements DataSource { ...@@ -90,9 +102,9 @@ public class FakeDataSource implements DataSource {
@Override @Override
public final long open(DataSpec dataSpec) throws IOException { public final long open(DataSpec dataSpec) throws IOException {
Assertions.checkState(!opened); Assertions.checkState(!openCalled);
openCalled = true;
// DataSpec requires a matching close call even if open fails. // DataSpec requires a matching close call even if open fails.
opened = true;
uri = dataSpec.uri; uri = dataSpec.uri;
openedDataSpecs.add(dataSpec); openedDataSpecs.add(dataSpec);
...@@ -129,9 +141,8 @@ public class FakeDataSource implements DataSource { ...@@ -129,9 +141,8 @@ public class FakeDataSource implements DataSource {
currentSegmentIndex++; currentSegmentIndex++;
} }
} }
if (transferListener != null) { sourceOpened = true;
transferListener.onTransferStart(this, dataSpec); transferStarted(dataSpec);
}
// Configure bytesRemaining, and return. // Configure bytesRemaining, and return.
if (dataSpec.length == C.LENGTH_UNSET) { if (dataSpec.length == C.LENGTH_UNSET) {
bytesRemaining = totalLength - dataSpec.position; bytesRemaining = totalLength - dataSpec.position;
...@@ -144,7 +155,7 @@ public class FakeDataSource implements DataSource { ...@@ -144,7 +155,7 @@ public class FakeDataSource implements DataSource {
@Override @Override
public final int read(byte[] buffer, int offset, int readLength) throws IOException { public final int read(byte[] buffer, int offset, int readLength) throws IOException {
Assertions.checkState(opened); Assertions.checkState(sourceOpened);
while (true) { while (true) {
if (currentSegmentIndex == fakeData.getSegments().size() || bytesRemaining == 0) { if (currentSegmentIndex == fakeData.getSegments().size() || bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
...@@ -171,9 +182,7 @@ public class FakeDataSource implements DataSource { ...@@ -171,9 +182,7 @@ public class FakeDataSource implements DataSource {
System.arraycopy(current.data, current.bytesRead, buffer, offset, readLength); System.arraycopy(current.data, current.bytesRead, buffer, offset, readLength);
} }
onDataRead(readLength); onDataRead(readLength);
if (transferListener != null) { bytesTransferred(readLength);
transferListener.onBytesTransferred(this, readLength);
}
bytesRemaining -= readLength; bytesRemaining -= readLength;
current.bytesRead += readLength; current.bytesRead += readLength;
if (current.bytesRead == current.length) { if (current.bytesRead == current.length) {
...@@ -191,8 +200,8 @@ public class FakeDataSource implements DataSource { ...@@ -191,8 +200,8 @@ public class FakeDataSource implements DataSource {
@Override @Override
public final void close() throws IOException { public final void close() throws IOException {
Assertions.checkState(opened); Assertions.checkState(openCalled);
opened = false; openCalled = false;
uri = null; uri = null;
if (fakeData != null && currentSegmentIndex < fakeData.getSegments().size()) { if (fakeData != null && currentSegmentIndex < fakeData.getSegments().size()) {
Segment current = fakeData.getSegments().get(currentSegmentIndex); Segment current = fakeData.getSegments().get(currentSegmentIndex);
...@@ -200,8 +209,9 @@ public class FakeDataSource implements DataSource { ...@@ -200,8 +209,9 @@ public class FakeDataSource implements DataSource {
current.exceptionCleared = true; current.exceptionCleared = true;
} }
} }
if (transferListener != null) { if (sourceOpened) {
transferListener.onTransferEnd(this); sourceOpened = false;
transferEnded();
} }
fakeData = null; fakeData = null;
} }
...@@ -219,7 +229,7 @@ public class FakeDataSource implements DataSource { ...@@ -219,7 +229,7 @@ public class FakeDataSource implements DataSource {
/** Returns whether the data source is currently opened. */ /** Returns whether the data source is currently opened. */
public final boolean isOpened() { public final boolean isOpened() {
return opened; return sourceOpened;
} }
protected void onDataRead(int bytesRead) throws IOException { protected void onDataRead(int bytesRead) throws IOException {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment