diff --git a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index eaa4d9971f..0607c296c6 100644 --- a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -316,15 +316,15 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay int type = Util.inferContentType(!TextUtils.isEmpty(overrideExtension) ? "." + overrideExtension : uri.getLastPathSegment()); switch (type) { - case Util.TYPE_SS: + case C.TYPE_SS: return new SsMediaSource(uri, buildDataSourceFactory(false), new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger); - case Util.TYPE_DASH: + case C.TYPE_DASH: return new DashMediaSource(uri, buildDataSourceFactory(false), new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger); - case Util.TYPE_HLS: + case C.TYPE_HLS: return new HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, eventLogger); - case Util.TYPE_OTHER: + case C.TYPE_OTHER: return new ExtractorMediaSource(uri, mediaDataSourceFactory, new DefaultExtractorsFactory(), mainHandler, eventLogger); default: { diff --git a/library/build.gradle b/library/build.gradle index d301e0903e..3c7a633f49 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -55,6 +55,7 @@ dependencies { androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' androidTestCompile 'org.mockito:mockito-core:1.9.5' + compile 'com.android.support:support-annotations:24.2.0' } android.libraryVariants.all { variant -> diff --git a/library/src/main/java/com/google/android/exoplayer2/C.java b/library/src/main/java/com/google/android/exoplayer2/C.java index 85813b391a..8c69524e95 100644 --- a/library/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/src/main/java/com/google/android/exoplayer2/C.java @@ -17,8 +17,11 @@ package com.google.android.exoplayer2; import android.media.AudioFormat; import android.media.MediaCodec; +import android.support.annotation.IntDef; import android.view.Surface; import com.google.android.exoplayer2.util.Util; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.UUID; /** @@ -70,55 +73,79 @@ public final class C { */ public static final String UTF8_NAME = "UTF-8"; + /** + * Crypto modes for a codec. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({CRYPTO_MODE_UNENCRYPTED, CRYPTO_MODE_AES_CTR, CRYPTO_MODE_AES_CBC}) + public @interface CryptoMode {} + /** + * @see MediaCodec#CRYPTO_MODE_UNENCRYPTED + */ + @SuppressWarnings("InlinedApi") + public static final int CRYPTO_MODE_UNENCRYPTED = MediaCodec.CRYPTO_MODE_UNENCRYPTED; /** * @see MediaCodec#CRYPTO_MODE_AES_CTR */ @SuppressWarnings("InlinedApi") public static final int CRYPTO_MODE_AES_CTR = MediaCodec.CRYPTO_MODE_AES_CTR; + /** + * @see MediaCodec#CRYPTO_MODE_AES_CBC + */ + @SuppressWarnings("InlinedApi") + public static final int CRYPTO_MODE_AES_CBC = MediaCodec.CRYPTO_MODE_AES_CBC; + /** + * Represents an audio encoding, or an invalid or unset value. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({Format.NO_VALUE, ENCODING_INVALID, ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, + ENCODING_PCM_24BIT, ENCODING_PCM_32BIT, ENCODING_AC3, ENCODING_E_AC3, ENCODING_DTS, + ENCODING_DTS_HD}) + public @interface Encoding {} + + /** + * Represents a PCM audio encoding, or an invalid or unset value. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({Format.NO_VALUE, ENCODING_INVALID, ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, + ENCODING_PCM_24BIT, ENCODING_PCM_32BIT}) + public @interface PcmEncoding {} /** * @see AudioFormat#ENCODING_INVALID */ public static final int ENCODING_INVALID = AudioFormat.ENCODING_INVALID; - /** * @see AudioFormat#ENCODING_PCM_8BIT */ public static final int ENCODING_PCM_8BIT = AudioFormat.ENCODING_PCM_8BIT; - /** * @see AudioFormat#ENCODING_PCM_16BIT */ public static final int ENCODING_PCM_16BIT = AudioFormat.ENCODING_PCM_16BIT; - /** * PCM encoding with 24 bits per sample. */ public static final int ENCODING_PCM_24BIT = 0x80000000; - /** * PCM encoding with 32 bits per sample. */ public static final int ENCODING_PCM_32BIT = 0x40000000; - /** * @see AudioFormat#ENCODING_AC3 */ @SuppressWarnings("InlinedApi") public static final int ENCODING_AC3 = AudioFormat.ENCODING_AC3; - /** * @see AudioFormat#ENCODING_E_AC3 */ @SuppressWarnings("InlinedApi") public static final int ENCODING_E_AC3 = AudioFormat.ENCODING_E_AC3; - /** * @see AudioFormat#ENCODING_DTS */ @SuppressWarnings("InlinedApi") public static final int ENCODING_DTS = AudioFormat.ENCODING_DTS; - /** * @see AudioFormat#ENCODING_DTS_HD */ @@ -132,48 +159,93 @@ public final class C { public static final int CHANNEL_OUT_7POINT1_SURROUND = Util.SDK_INT < 23 ? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; + /** + * Flags which can apply to a buffer containing a media sample. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {BUFFER_FLAG_KEY_FRAME, BUFFER_FLAG_END_OF_STREAM, + BUFFER_FLAG_ENCRYPTED, BUFFER_FLAG_DECODE_ONLY}) + public @interface BufferFlags {} /** * Indicates that a buffer holds a synchronization sample. */ @SuppressWarnings("InlinedApi") public static final int BUFFER_FLAG_KEY_FRAME = MediaCodec.BUFFER_FLAG_KEY_FRAME; - /** * Flag for empty buffers that signal that the end of the stream was reached. */ @SuppressWarnings("InlinedApi") public static final int BUFFER_FLAG_END_OF_STREAM = MediaCodec.BUFFER_FLAG_END_OF_STREAM; - /** * Indicates that a buffer is (at least partially) encrypted. */ public static final int BUFFER_FLAG_ENCRYPTED = 0x40000000; - /** * Indicates that a buffer should be decoded but not rendered. */ public static final int BUFFER_FLAG_DECODE_ONLY = 0x80000000; + /** + * Track selection flags. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {SELECTION_FLAG_DEFAULT, SELECTION_FLAG_FORCED, + SELECTION_FLAG_AUTOSELECT}) + public @interface SelectionFlags {} + /** + * Indicates that the track should be selected if user preferences do not state otherwise. + */ + public static final int SELECTION_FLAG_DEFAULT = 1; + /** + * Indicates that the track must be displayed. Only applies to text tracks. + */ + public static final int SELECTION_FLAG_FORCED = 2; + /** + * Indicates that the player may choose to play the track in absence of an explicit user + * preference. + */ + public static final int SELECTION_FLAG_AUTOSELECT = 4; + + /** + * Represents a streaming or other media type. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_DASH, TYPE_SS, TYPE_HLS, TYPE_OTHER}) + public @interface ContentType {} + /** + * Value returned by {@link Util#inferContentType(String)} for DASH manifests. + */ + public static final int TYPE_DASH = 0; + /** + * Value returned by {@link Util#inferContentType(String)} for Smooth Streaming manifests. + */ + public static final int TYPE_SS = 1; + /** + * Value returned by {@link Util#inferContentType(String)} for HLS manifests. + */ + public static final int TYPE_HLS = 2; + /** + * Value returned by {@link Util#inferContentType(String)} for files other than DASH, HLS or + * Smooth Streaming manifests. + */ + public static final int TYPE_OTHER = 3; + /** * A return value for methods where the end of an input was encountered. */ public static final int RESULT_END_OF_INPUT = -1; - /** * A return value for methods where the length of parsed data exceeds the maximum length allowed. */ public static final int RESULT_MAX_LENGTH_EXCEEDED = -2; - /** * A return value for methods where nothing was read. */ public static final int RESULT_NOTHING_READ = -3; - /** * A return value for methods where a buffer was read. */ public static final int RESULT_BUFFER_READ = -4; - /** * A return value for methods where a format was read. */ @@ -183,32 +255,26 @@ public final class C { * A data type constant for data of unknown or unspecified type. */ public static final int DATA_TYPE_UNKNOWN = 0; - /** * A data type constant for media, typically containing media samples. */ public static final int DATA_TYPE_MEDIA = 1; - /** * A data type constant for media, typically containing only initialization data. */ public static final int DATA_TYPE_MEDIA_INITIALIZATION = 2; - /** * A data type constant for drm or encryption data. */ public static final int DATA_TYPE_DRM = 3; - /** * A data type constant for a manifest file. */ public static final int DATA_TYPE_MANIFEST = 4; - /** * A data type constant for time synchronization data. */ public static final int DATA_TYPE_TIME_SYNCHRONIZATION = 5; - /** * Applications or extensions may define custom {@code DATA_TYPE_*} constants greater than or * equal to this value. @@ -219,32 +285,26 @@ public final class C { * A type constant for tracks of unknown type. */ public static final int TRACK_TYPE_UNKNOWN = -1; - /** * A type constant for tracks of some default type, where the type itself is unknown. */ public static final int TRACK_TYPE_DEFAULT = 0; - /** * A type constant for audio tracks. */ public static final int TRACK_TYPE_AUDIO = 1; - /** * A type constant for video tracks. */ public static final int TRACK_TYPE_VIDEO = 2; - /** * A type constant for text tracks. */ public static final int TRACK_TYPE_TEXT = 3; - /** * A type constant for metadata tracks. */ public static final int TRACK_TYPE_METADATA = 4; - /** * Applications or extensions may define custom {@code TRACK_TYPE_*} constants greater than or * equal to this value. @@ -255,27 +315,22 @@ public final class C { * A selection reason constant for selections whose reasons are unknown or unspecified. */ public static final int SELECTION_REASON_UNKNOWN = 0; - /** * A selection reason constant for an initial track selection. */ public static final int SELECTION_REASON_INITIAL = 1; - /** * A selection reason constant for an manual (i.e. user initiated) track selection. */ public static final int SELECTION_REASON_MANUAL = 2; - /** * A selection reason constant for an adaptive track selection. */ public static final int SELECTION_REASON_ADAPTIVE = 3; - /** * A selection reason constant for a trick play track selection. */ public static final int SELECTION_REASON_TRICK_PLAY = 4; - /** * Applications or extensions may define custom {@code SELECTION_REASON_*} constants greater than * or equal to this value. @@ -363,16 +418,20 @@ public final class C { */ public static final int MSG_CUSTOM_BASE = 10000; + /** + * The stereo mode for 360/3D/VR videos. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({Format.NO_VALUE, STEREO_MODE_MONO, STEREO_MODE_TOP_BOTTOM, STEREO_MODE_LEFT_RIGHT}) + public @interface StereoMode {} /** * Indicates Monoscopic stereo layout, used with 360/3D/VR videos. */ public static final int STEREO_MODE_MONO = 0; - /** * Indicates Top-Bottom stereo layout, used with 360/3D/VR videos. */ public static final int STEREO_MODE_TOP_BOTTOM = 1; - /** * Indicates Left-Right stereo layout, used with 360/3D/VR videos. */ diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java index 8f55451712..72ac72e981 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java @@ -15,15 +15,24 @@ */ package com.google.android.exoplayer2; +import android.support.annotation.IntDef; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Thrown when a non-recoverable playback failure occurs. */ public final class ExoPlaybackException extends Exception { + /** + * The type of source that produced the error. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_SOURCE, TYPE_RENDERER, TYPE_UNEXPECTED}) + public @interface Type {} /** * The error occurred loading data from a {@link MediaSource}. *

@@ -47,6 +56,7 @@ public final class ExoPlaybackException extends Exception { * The type of the playback failure. One of {@link #TYPE_SOURCE}, {@link #TYPE_RENDERER} and * {@link #TYPE_UNEXPECTED}. */ + @Type public final int type; /** @@ -85,7 +95,8 @@ public final class ExoPlaybackException extends Exception { return new ExoPlaybackException(TYPE_UNEXPECTED, null, cause, C.INDEX_UNSET); } - private ExoPlaybackException(int type, String message, Throwable cause, int rendererIndex) { + private ExoPlaybackException(@Type int type, String message, Throwable cause, + int rendererIndex) { super(message, cause); this.type = type; this.rendererIndex = rendererIndex; diff --git a/library/src/main/java/com/google/android/exoplayer2/Format.java b/library/src/main/java/com/google/android/exoplayer2/Format.java index 9cfe019ef4..50112d5a0a 100644 --- a/library/src/main/java/com/google/android/exoplayer2/Format.java +++ b/library/src/main/java/com/google/android/exoplayer2/Format.java @@ -39,20 +39,6 @@ public final class Format implements Parcelable { */ public static final int NO_VALUE = -1; - /** - * Indicates that the track should be selected if user preferences do not state otherwise. - */ - public static final int SELECTION_FLAG_DEFAULT = 1; - /** - * Indicates that the track must be displayed. Only applies to text tracks. - */ - public static final int SELECTION_FLAG_FORCED = 2; - /** - * Indicates that the player may choose to play the track in absence of an explicit user - * preference. - */ - public static final int SELECTION_FLAG_AUTOSELECT = 4; - /** * A value for {@link #subsampleOffsetUs} to indicate that subsample timestamps are relative to * the timestamps of their parent samples. @@ -131,6 +117,7 @@ public final class Format implements Parcelable { * modes are {@link C#STEREO_MODE_MONO}, {@link C#STEREO_MODE_TOP_BOTTOM}, {@link * C#STEREO_MODE_LEFT_RIGHT}. */ + @C.StereoMode public final int stereoMode; /** * The projection data for 360/VR video, or null if not applicable. @@ -153,6 +140,7 @@ public final class Format implements Parcelable { * {@link C#ENCODING_PCM_24BIT} and {@link C#ENCODING_PCM_32BIT}. Set to {@link #NO_VALUE} for * other media types. */ + @C.PcmEncoding public final int pcmEncoding; /** * The number of samples to trim from the start of the decoded audio stream. @@ -177,6 +165,7 @@ public final class Format implements Parcelable { /** * Track selection flags. */ + @C.SelectionFlags public final int selectionFlags; /** @@ -218,7 +207,7 @@ public final class Format implements Parcelable { public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs, int bitrate, int maxInputSize, int width, int height, float frameRate, List initializationData, int rotationDegrees, float pixelWidthHeightRatio, - byte[] projectionData, int stereoMode, DrmInitData drmInitData) { + byte[] projectionData, @C.StereoMode int stereoMode, DrmInitData drmInitData) { return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, 0, null, OFFSET_SAMPLE_RELATIVE, initializationData, @@ -229,7 +218,7 @@ public final class Format implements Parcelable { public static Format createAudioContainerFormat(String id, String containerMimeType, String sampleMimeType, String codecs, int bitrate, int channelCount, int sampleRate, - List initializationData, int selectionFlags, String language) { + List initializationData, @C.SelectionFlags int selectionFlags, String language) { return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, channelCount, sampleRate, NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, OFFSET_SAMPLE_RELATIVE, initializationData, @@ -238,25 +227,26 @@ public final class Format implements Parcelable { public static Format createAudioSampleFormat(String id, String sampleMimeType, String codecs, int bitrate, int maxInputSize, int channelCount, int sampleRate, - List initializationData, DrmInitData drmInitData, int selectionFlags, - String language) { + List initializationData, DrmInitData drmInitData, + @C.SelectionFlags int selectionFlags, String language) { return createAudioSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, channelCount, sampleRate, NO_VALUE, initializationData, drmInitData, selectionFlags, language); } public static Format createAudioSampleFormat(String id, String sampleMimeType, String codecs, - int bitrate, int maxInputSize, int channelCount, int sampleRate, int pcmEncoding, - List initializationData, DrmInitData drmInitData, int selectionFlags, - String language) { + int bitrate, int maxInputSize, int channelCount, int sampleRate, + @C.PcmEncoding int pcmEncoding, List initializationData, DrmInitData drmInitData, + @C.SelectionFlags int selectionFlags, String language) { return createAudioSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, channelCount, sampleRate, pcmEncoding, NO_VALUE, NO_VALUE, initializationData, drmInitData, selectionFlags, language); } public static Format createAudioSampleFormat(String id, String sampleMimeType, String codecs, - int bitrate, int maxInputSize, int channelCount, int sampleRate, int pcmEncoding, - int encoderDelay, int encoderPadding, List initializationData, - DrmInitData drmInitData, int selectionFlags, String language) { + int bitrate, int maxInputSize, int channelCount, int sampleRate, + @C.PcmEncoding int pcmEncoding, int encoderDelay, int encoderPadding, + List initializationData, DrmInitData drmInitData, + @C.SelectionFlags int selectionFlags, String language) { return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, selectionFlags, language, OFFSET_SAMPLE_RELATIVE, @@ -266,20 +256,21 @@ public final class Format implements Parcelable { // Text. public static Format createTextContainerFormat(String id, String containerMimeType, - String sampleMimeType, String codecs, int bitrate, int selectionFlags, String language) { + String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags, + String language) { return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, OFFSET_SAMPLE_RELATIVE, null, null); } public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs, - int bitrate, int selectionFlags, String language, DrmInitData drmInitData) { + int bitrate, @C.SelectionFlags int selectionFlags, String language, DrmInitData drmInitData) { return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language, drmInitData, OFFSET_SAMPLE_RELATIVE); } public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs, - int bitrate, int selectionFlags, String language, DrmInitData drmInitData, + int bitrate, @C.SelectionFlags int selectionFlags, String language, DrmInitData drmInitData, long subsampleOffsetUs) { return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, @@ -313,10 +304,10 @@ public final class Format implements Parcelable { /* package */ Format(String id, String containerMimeType, String sampleMimeType, String codecs, int bitrate, int maxInputSize, int width, int height, float frameRate, int rotationDegrees, - float pixelWidthHeightRatio, byte[] projectionData, int stereoMode, int channelCount, - int sampleRate, int pcmEncoding, int encoderDelay, int encoderPadding, int selectionFlags, - String language, long subsampleOffsetUs, List initializationData, - DrmInitData drmInitData) { + float pixelWidthHeightRatio, byte[] projectionData, @C.StereoMode int stereoMode, + int channelCount, int sampleRate, @C.PcmEncoding int pcmEncoding, int encoderDelay, + int encoderPadding, @C.SelectionFlags int selectionFlags, String language, + long subsampleOffsetUs, List initializationData, DrmInitData drmInitData) { this.id = id; this.containerMimeType = containerMimeType; this.sampleMimeType = sampleMimeType; @@ -343,6 +334,7 @@ public final class Format implements Parcelable { this.drmInitData = drmInitData; } + @SuppressWarnings("ResourceType") /* package */ Format(Parcel in) { id = in.readString(); containerMimeType = in.readString(); @@ -389,7 +381,7 @@ public final class Format implements Parcelable { } public Format copyWithContainerInfo(String id, int bitrate, int width, int height, - int selectionFlags, String language) { + @C.SelectionFlags int selectionFlags, String language) { return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding, @@ -402,7 +394,7 @@ public final class Format implements Parcelable { String codecs = this.codecs == null ? manifestFormat.codecs : this.codecs; int bitrate = this.bitrate == NO_VALUE ? manifestFormat.bitrate : this.bitrate; float frameRate = this.frameRate == NO_VALUE ? manifestFormat.frameRate : this.frameRate; - int selectionFlags = this.selectionFlags | manifestFormat.selectionFlags; + @C.SelectionFlags int selectionFlags = this.selectionFlags | manifestFormat.selectionFlags; String language = this.language == null ? manifestFormat.language : this.language; DrmInitData drmInitData = (preferManifestDrmInitData && manifestFormat.drmInitData != null) || this.drmInitData == null ? manifestFormat.drmInitData : this.drmInitData; diff --git a/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java b/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java index 02fa2b8f85..87f6546e1f 100644 --- a/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java +++ b/library/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java @@ -208,7 +208,9 @@ public final class AudioTrack { private android.media.AudioTrack audioTrack; private int sampleRate; private int channelConfig; + @C.Encoding private int sourceEncoding; + @C.Encoding private int targetEncoding; private boolean passthrough; private int pcmFrameSize; @@ -348,8 +350,8 @@ public final class AudioTrack { * @param specifiedBufferSize A specific size for the playback buffer in bytes, or 0 to infer a * suitable buffer size automatically. */ - public void configure(String mimeType, int channelCount, int sampleRate, int pcmEncoding, - int specifiedBufferSize) { + public void configure(String mimeType, int channelCount, int sampleRate, + @C.PcmEncoding int pcmEncoding, int specifiedBufferSize) { int channelConfig; switch (channelCount) { case 1: @@ -381,7 +383,7 @@ public final class AudioTrack { } boolean passthrough = !MimeTypes.AUDIO_RAW.equals(mimeType); - int sourceEncoding; + @C.Encoding int sourceEncoding; if (passthrough) { sourceEncoding = getEncodingForMimeType(mimeType); } else if (pcmEncoding == C.ENCODING_PCM_8BIT || pcmEncoding == C.ENCODING_PCM_16BIT @@ -470,7 +472,7 @@ public final class AudioTrack { if (keepSessionIdAudioTrack == null) { int sampleRate = 4000; // Equal to private android.media.AudioTrack.MIN_SAMPLE_RATE. int channelConfig = AudioFormat.CHANNEL_OUT_MONO; - int encoding = C.ENCODING_PCM_16BIT; + @C.PcmEncoding int encoding = C.ENCODING_PCM_16BIT; int bufferSize = 2; // Use a two byte buffer, as it is not actually used for playback. keepSessionIdAudioTrack = new android.media.AudioTrack(streamType, sampleRate, channelConfig, encoding, bufferSize, android.media.AudioTrack.MODE_STATIC, sessionId); @@ -962,7 +964,7 @@ public final class AudioTrack { * @return The 16-bit PCM output. Different to the out parameter if null was passed, or if the * capacity was insufficient for the output. */ - private static ByteBuffer resampleTo16BitPcm(ByteBuffer buffer, int sourceEncoding, + private static ByteBuffer resampleTo16BitPcm(ByteBuffer buffer, @C.PcmEncoding int sourceEncoding, ByteBuffer out) { int offset = buffer.position(); int limit = buffer.limit(); @@ -1023,6 +1025,7 @@ public final class AudioTrack { return resampledBuffer; } + @C.Encoding private static int getEncodingForMimeType(String mimeType) { switch (mimeType) { case MimeTypes.AUDIO_AC3: @@ -1038,7 +1041,7 @@ public final class AudioTrack { } } - private static int getFramesPerEncodedSample(int encoding, ByteBuffer buffer) { + private static int getFramesPerEncodedSample(@C.Encoding int encoding, ByteBuffer buffer) { if (encoding == C.ENCODING_DTS || encoding == C.ENCODING_DTS_HD) { return DtsUtil.parseDtsAudioSampleCount(buffer); } else if (encoding == C.ENCODING_AC3) { diff --git a/library/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java b/library/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java index cb408714f4..773959fbfc 100644 --- a/library/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java +++ b/library/src/main/java/com/google/android/exoplayer2/decoder/Buffer.java @@ -22,6 +22,7 @@ import com.google.android.exoplayer2.C; */ public abstract class Buffer { + @C.BufferFlags private int flags; /** @@ -58,7 +59,7 @@ public abstract class Buffer { * @param flags The flags to set, which should be a combination of the {@code C.BUFFER_FLAG_*} * constants. */ - public final void setFlags(int flags) { + public final void setFlags(@C.BufferFlags int flags) { this.flags = flags; } @@ -68,7 +69,7 @@ public abstract class Buffer { * @param flag The flag to add to this buffer's flags, which should be one of the * {@code C.BUFFER_FLAG_*} constants. */ - public final void addFlag(int flag) { + public final void addFlag(@C.BufferFlags int flag) { flags |= flag; } @@ -77,7 +78,7 @@ public abstract class Buffer { * * @param flag The flag to remove. */ - public final void clearFlag(int flag) { + public final void clearFlag(@C.BufferFlags int flag) { flags &= ~flag; } @@ -87,7 +88,7 @@ public abstract class Buffer { * @param flag The flag to check. * @return Whether the flag is set. */ - protected final boolean getFlag(int flag) { + protected final boolean getFlag(@C.BufferFlags int flag) { return (flags & flag) == flag; } diff --git a/library/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java b/library/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java index bde46738fe..866e421acc 100644 --- a/library/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java +++ b/library/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.decoder; import android.annotation.TargetApi; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Util; /** @@ -34,6 +35,7 @@ public final class CryptoInfo { /** * @see android.media.MediaCodec.CryptoInfo#mode */ + @C.CryptoMode public int mode; /** * @see android.media.MediaCodec.CryptoInfo#numBytesOfClearData @@ -58,7 +60,7 @@ public final class CryptoInfo { * @see android.media.MediaCodec.CryptoInfo#set(int, int[], int[], byte[], byte[], int) */ public void set(int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData, - byte[] key, byte[] iv, int mode) { + byte[] key, byte[] iv, @C.CryptoMode int mode) { this.numSubSamples = numSubSamples; this.numBytesOfClearData = numBytesOfClearData; this.numBytesOfEncryptedData = numBytesOfEncryptedData; diff --git a/library/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java b/library/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java index f34861a0e0..b76f3e8d0c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java +++ b/library/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java @@ -15,7 +15,10 @@ */ package com.google.android.exoplayer2.decoder; +import android.support.annotation.IntDef; import com.google.android.exoplayer2.C; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; /** @@ -23,16 +26,21 @@ import java.nio.ByteBuffer; */ public class DecoderInputBuffer extends Buffer { + /** + * The buffer replacement mode, which may disable replacement. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({BUFFER_REPLACEMENT_MODE_DISABLED, BUFFER_REPLACEMENT_MODE_NORMAL, + BUFFER_REPLACEMENT_MODE_DIRECT}) + public @interface BufferReplacementMode {} /** * Disallows buffer replacement. */ public static final int BUFFER_REPLACEMENT_MODE_DISABLED = 0; - /** * Allows buffer replacement using {@link ByteBuffer#allocate(int)}. */ public static final int BUFFER_REPLACEMENT_MODE_NORMAL = 1; - /** * Allows buffer replacement using {@link ByteBuffer#allocateDirect(int)}. */ @@ -53,6 +61,7 @@ public class DecoderInputBuffer extends Buffer { */ public long timeUs; + @BufferReplacementMode private final int bufferReplacementMode; /** @@ -60,7 +69,7 @@ public class DecoderInputBuffer extends Buffer { * of {@link #BUFFER_REPLACEMENT_MODE_DISABLED}, {@link #BUFFER_REPLACEMENT_MODE_NORMAL} and * {@link #BUFFER_REPLACEMENT_MODE_DIRECT}. */ - public DecoderInputBuffer(int bufferReplacementMode) { + public DecoderInputBuffer(@BufferReplacementMode int bufferReplacementMode) { this.cryptoInfo = new CryptoInfo(); this.bufferReplacementMode = bufferReplacementMode; } diff --git a/library/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java b/library/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java index 8f0ff961a9..6f84395072 100644 --- a/library/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java +++ b/library/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java @@ -16,6 +16,9 @@ package com.google.android.exoplayer2.drm; import android.annotation.TargetApi; +import android.support.annotation.IntDef; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * A DRM session. @@ -23,6 +26,12 @@ import android.annotation.TargetApi; @TargetApi(16) public interface DrmSession { + /** + * The state of the DRM session. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({STATE_ERROR, STATE_CLOSED, STATE_OPENING, STATE_OPENED, STATE_OPENED_WITH_KEYS}) + @interface State {} /** * The session has encountered an error. {@link #getError()} can be used to retrieve the cause. */ @@ -50,6 +59,7 @@ public interface DrmSession { * @return One of {@link #STATE_ERROR}, {@link #STATE_CLOSED}, {@link #STATE_OPENING}, * {@link #STATE_OPENED} and {@link #STATE_OPENED_WITH_KEYS}. */ + @State int getState(); /** diff --git a/library/src/main/java/com/google/android/exoplayer2/drm/StreamingDrmSessionManager.java b/library/src/main/java/com/google/android/exoplayer2/drm/StreamingDrmSessionManager.java index 8428b0cdf9..2882111ac9 100644 --- a/library/src/main/java/com/google/android/exoplayer2/drm/StreamingDrmSessionManager.java +++ b/library/src/main/java/com/google/android/exoplayer2/drm/StreamingDrmSessionManager.java @@ -87,6 +87,7 @@ public class StreamingDrmSessionManager implements Drm private int openCount; private boolean provisioningInProgress; + @DrmSession.State private int state; private T mediaCrypto; private Exception lastException; @@ -291,6 +292,7 @@ public class StreamingDrmSessionManager implements Drm // DrmSession implementation. @Override + @DrmSession.State public final int getState() { return state; } diff --git a/library/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java b/library/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java index d1b70279ce..505750efaa 100644 --- a/library/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java +++ b/library/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java @@ -15,11 +15,21 @@ */ package com.google.android.exoplayer2.drm; +import android.support.annotation.IntDef; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Thrown when the requested DRM scheme is not supported. */ public final class UnsupportedDrmException extends Exception { + /** + * The reason for the exception. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({REASON_UNSUPPORTED_SCHEME, REASON_INSTANTIATION_ERROR}) + public @interface Reason {} /** * The requested DRM scheme is unsupported by the device. */ @@ -33,12 +43,13 @@ public final class UnsupportedDrmException extends Exception { /** * Either {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. */ + @Reason public final int reason; /** * @param reason {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. */ - public UnsupportedDrmException(int reason) { + public UnsupportedDrmException(@Reason int reason) { this.reason = reason; } @@ -46,7 +57,7 @@ public final class UnsupportedDrmException extends Exception { * @param reason {@link #REASON_UNSUPPORTED_SCHEME} or {@link #REASON_INSTANTIATION_ERROR}. * @param cause The cause of this exception. */ - public UnsupportedDrmException(int reason, Exception cause) { + public UnsupportedDrmException(@Reason int reason, Exception cause) { super(cause); this.reason = reason; } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/DefaultTrackOutput.java b/library/src/main/java/com/google/android/exoplayer2/extractor/DefaultTrackOutput.java index f7493a8b8a..cb9e41aa62 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/DefaultTrackOutput.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/DefaultTrackOutput.java @@ -496,7 +496,8 @@ public final class DefaultTrackOutput implements TrackOutput { } @Override - public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { + public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, + byte[] encryptionKey) { if (!startWriteOperation()) { infoQueue.commitSampleTimestamp(timeUs); return; @@ -836,8 +837,8 @@ public final class DefaultTrackOutput implements TrackOutput { } } - public synchronized void commitSample(long timeUs, int sampleFlags, long offset, int size, - byte[] encryptionKey) { + public synchronized void commitSample(long timeUs, @C.BufferFlags int sampleFlags, long offset, + int size, byte[] encryptionKey) { Assertions.checkState(!upstreamFormatRequired); commitSampleTimestamp(timeUs); timesUs[relativeWriteIndex] = timeUs; diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java b/library/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java index e317dd589c..61f97887be 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java @@ -50,7 +50,8 @@ public final class DummyTrackOutput implements TrackOutput { } @Override - public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { + public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, + byte[] encryptionKey) { // Do nothing. } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java b/library/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java index 0ce807ebb1..c4dee4b6a7 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java @@ -72,6 +72,7 @@ public interface TrackOutput { * whose metadata is being passed. * @param encryptionKey The encryption key associated with the sample. May be null. */ - void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey); + void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, + byte[] encryptionKey); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index 917af9c7e1..2d84e73c1e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -264,6 +264,7 @@ public final class MatroskaExtractor implements Extractor { private int[] blockLacingSampleSizes; private int blockTrackNumber; private int blockTrackNumberLength; + @C.BufferFlags private int blockFlags; // Sample reading state. @@ -1314,7 +1315,7 @@ public final class MatroskaExtractor implements Extractor { public void initializeOutput(ExtractorOutput output, int trackId) throws ParserException { String mimeType; int maxInputSize = Format.NO_VALUE; - int pcmEncoding = Format.NO_VALUE; + @C.PcmEncoding int pcmEncoding = Format.NO_VALUE; List initializationData = null; switch (codecId) { case CODEC_ID_VP8: @@ -1429,9 +1430,9 @@ public final class MatroskaExtractor implements Extractor { } Format format; - int selectionFlags = 0; - selectionFlags |= flagDefault ? Format.SELECTION_FLAG_DEFAULT : 0; - selectionFlags |= flagForced ? Format.SELECTION_FLAG_FORCED : 0; + @C.SelectionFlags int selectionFlags = 0; + selectionFlags |= flagDefault ? C.SELECTION_FLAG_DEFAULT : 0; + selectionFlags |= flagForced ? C.SELECTION_FLAG_FORCED : 0; // TODO: Consider reading the name elements of the tracks and, if present, incorporating them // into the trackId passed when creating the formats. if (MimeTypes.isAudio(mimeType)) { diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index 11a25fe419..87be7029c9 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -665,6 +665,7 @@ import java.util.List; List initializationData = null; String mimeType = null; byte[] projectionData = null; + @C.StereoMode int stereoMode = Format.NO_VALUE; while (childPosition - position < size) { parent.setPosition(childPosition); @@ -889,7 +890,7 @@ import java.util.List; if (out.format == null && mimeType != null) { // TODO: Determine the correct PCM encoding. - int pcmEncoding = + @C.PcmEncoding int pcmEncoding = MimeTypes.AUDIO_RAW.equals(mimeType) ? C.ENCODING_PCM_16BIT : Format.NO_VALUE; out.format = Format.createAudioSampleFormat(Integer.toString(trackId), mimeType, null, Format.NO_VALUE, Format.NO_VALUE, channelCount, sampleRate, pcmEncoding, @@ -1169,6 +1170,7 @@ import java.util.List; public Format format; public int nalUnitLengthFieldLength; + @Track.Transformation public int requiredSampleTransformation; public StsdData(int numberOfEntries) { diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index 103acdd6f9..71f9231a31 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; +import android.support.annotation.IntDef; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -38,6 +39,8 @@ import com.google.android.exoplayer2.util.NalUnitUtil; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -64,6 +67,13 @@ public final class FragmentedMp4Extractor implements Extractor { private static final String TAG = "FragmentedMp4Extractor"; private static final int SAMPLE_GROUP_TYPE_seig = Util.getIntegerCodeForString("seig"); + /** + * Flags controlling the behavior of the extractor. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME, + FLAG_WORKAROUND_IGNORE_TFDT_BOX, FLAG_SIDELOADED}) + public @interface Flags {} /** * Flag to work around an issue in some video streams where every frame is marked as a sync frame. * The workaround overrides the sync frame flags in the stream, forcing them to false except for @@ -72,12 +82,10 @@ public final class FragmentedMp4Extractor implements Extractor { * This flag does nothing if the stream is not a video stream. */ public static final int FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME = 1; - /** * Flag to ignore any tfdt boxes in the stream. */ public static final int FLAG_WORKAROUND_IGNORE_TFDT_BOX = 2; - /** * Flag to indicate that the {@link Track} was sideloaded, instead of being declared by the MP4 * container. @@ -95,6 +103,7 @@ public final class FragmentedMp4Extractor implements Extractor { private static final int STATE_READING_SAMPLE_CONTINUE = 4; // Workarounds. + @Flags private final int flags; private final Track sideloadedTrack; @@ -135,18 +144,18 @@ public final class FragmentedMp4Extractor implements Extractor { } /** - * @param flags Flags to allow parsing of faulty streams. + * @param flags Flags that control the extractor's behavior. */ - public FragmentedMp4Extractor(int flags) { + public FragmentedMp4Extractor(@Flags int flags) { this(flags, null); } /** - * @param flags Flags to allow parsing of faulty streams. + * @param flags Flags that control the extractor's behavior. * @param sideloadedTrack Sideloaded track information, in the case that the extractor * will not receive a moov box in the input data. */ - public FragmentedMp4Extractor(int flags, Track sideloadedTrack) { + public FragmentedMp4Extractor(@Flags int flags, Track sideloadedTrack) { this.sideloadedTrack = sideloadedTrack; this.flags = flags | (sideloadedTrack != null ? FLAG_SIDELOADED : 0); atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE); @@ -422,7 +431,7 @@ public final class FragmentedMp4Extractor implements Extractor { } private static void parseMoof(ContainerAtom moof, SparseArray trackBundleArray, - int flags, byte[] extendedTypeScratch) throws ParserException { + @Flags int flags, byte[] extendedTypeScratch) throws ParserException { int moofContainerChildrenSize = moof.containerChildren.size(); for (int i = 0; i < moofContainerChildrenSize; i++) { Atom.ContainerAtom child = moof.containerChildren.get(i); @@ -437,7 +446,7 @@ public final class FragmentedMp4Extractor implements Extractor { * Parses a traf atom (defined in 14496-12). */ private static void parseTraf(ContainerAtom traf, SparseArray trackBundleArray, - int flags, byte[] extendedTypeScratch) throws ParserException { + @Flags int flags, byte[] extendedTypeScratch) throws ParserException { LeafAtom tfhd = traf.getLeafAtomOfType(Atom.TYPE_tfhd); TrackBundle trackBundle = parseTfhd(tfhd.data, trackBundleArray, flags); if (trackBundle == null) { @@ -488,7 +497,7 @@ public final class FragmentedMp4Extractor implements Extractor { } private static void parseTruns(ContainerAtom traf, TrackBundle trackBundle, long decodeTime, - int flags) { + @Flags int flags) { int trunCount = 0; int totalSampleCount = 0; List leafChildren = traf.leafChildren; @@ -643,8 +652,8 @@ public final class FragmentedMp4Extractor implements Extractor { * @param trun The trun atom to decode. * @return The starting position of samples for the next run. */ - private static int parseTrun(TrackBundle trackBundle, int index, long decodeTime, int flags, - ParsableByteArray trun, int trackRunStart) { + private static int parseTrun(TrackBundle trackBundle, int index, long decodeTime, + @Flags int flags, ParsableByteArray trun, int trackRunStart) { trun.setPosition(Atom.HEADER_SIZE); int fullAtom = trun.readInt(); int atomFlags = Atom.parseFullAtomFlags(fullAtom); @@ -994,7 +1003,7 @@ public final class FragmentedMp4Extractor implements Extractor { } long sampleTimeUs = fragment.getSamplePresentationTime(sampleIndex) * 1000L; - int sampleFlags = (fragment.definesEncryptionData ? C.BUFFER_FLAG_ENCRYPTED : 0) + @C.BufferFlags int sampleFlags = (fragment.definesEncryptionData ? C.BUFFER_FLAG_ENCRYPTED : 0) | (fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0); int sampleDescriptionIndex = fragment.header.sampleDescriptionIndex; byte[] encryptionKey = null; diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java index 5d48529794..c723704d37 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java @@ -15,14 +15,23 @@ */ package com.google.android.exoplayer2.extractor.mp4; +import android.support.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Encapsulates information describing an MP4 track. */ public final class Track { + /** + * The transformation to apply to samples in the track, if any. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TRANSFORMATION_NONE, TRANSFORMATION_CEA608_CDAT}) + public @interface Transformation {} /** * A no-op sample transformation. */ @@ -66,6 +75,7 @@ public final class Track { * One of {@code TRANSFORMATION_*}. Defines the transformation to apply before outputting each * sample. */ + @Transformation public final int sampleTransformation; /** @@ -90,7 +100,7 @@ public final class Track { public final int nalUnitLengthFieldLength; public Track(int id, int type, long timescale, long movieTimescale, long durationUs, - Format format, int sampleTransformation, + Format format, @Transformation int sampleTransformation, TrackEncryptionBox[] sampleDescriptionEncryptionBoxes, int nalUnitLengthFieldLength, long[] editListDurations, long[] editListMediaTimes) { this.id = id; diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java index 54e3fcd957..cf479eaf3e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackSampleTable.java @@ -49,7 +49,8 @@ import com.google.android.exoplayer2.util.Util; */ public final int[] flags; - TrackSampleTable(long[] offsets, int[] sizes, int maximumSize, long[] timestampsUs, int[] flags) { + public TrackSampleTable(long[] offsets, int[] sizes, int maximumSize, long[] timestampsUs, + int[] flags) { Assertions.checkArgument(sizes.length == timestampsUs.length); Assertions.checkArgument(offsets.length == timestampsUs.length); Assertions.checkArgument(flags.length == timestampsUs.length); diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java index a898ff598c..f74f771bb7 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java @@ -128,7 +128,7 @@ import java.util.Collections; if (hasOutputFormat && (startCodeValue == START_GROUP || startCodeValue == START_PICTURE)) { int bytesWrittenPastStartCode = limit - startCodeOffset; if (foundFirstFrameInGroup) { - int flags = isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0; + @C.BufferFlags int flags = isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0; int size = (int) (totalBytesWritten - framePosition) - bytesWrittenPastStartCode; output.sampleMetadata(frameTimeUs, flags, size, bytesWrittenPastStartCode, null); isKeyframe = false; diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java index 8bb72f6e79..993ec4f872 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java @@ -420,7 +420,7 @@ import java.util.List; } private void outputSample(int offset) { - int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0; + @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0; int size = (int) (nalUnitStartPosition - samplePosition); output.sampleMetadata(sampleTimeUs, flags, size, offset, null); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java index d6c431edec..e7ca3cc625 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java @@ -471,7 +471,7 @@ import java.util.Collections; } private void outputSample(int offset) { - int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0; + @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0; int size = (int) (nalUnitStartPosition - samplePosition); output.sampleMetadata(sampleTimeUs, flags, size, offset, null); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java index 5c9e8cf673..7c6a13bbff 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ts; +import android.support.annotation.IntDef; import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -32,6 +33,8 @@ import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Facilitates the extraction of data from the MPEG-2 TS container format. @@ -50,6 +53,13 @@ public final class TsExtractor implements Extractor { }; + /** + * Flags controlling what workarounds are enabled for the extractor. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {WORKAROUND_ALLOW_NON_IDR_KEYFRAMES, WORKAROUND_IGNORE_AAC_STREAM, + WORKAROUND_IGNORE_H264_STREAM, WORKAROUND_DETECT_ACCESS_UNITS, WORKAROUND_MAP_BY_TYPE}) + public @interface WorkaroundFlags {} public static final int WORKAROUND_ALLOW_NON_IDR_KEYFRAMES = 1; public static final int WORKAROUND_IGNORE_AAC_STREAM = 2; public static final int WORKAROUND_IGNORE_H264_STREAM = 4; @@ -83,6 +93,7 @@ public final class TsExtractor implements Extractor { private static final int BUFFER_SIZE = TS_PACKET_SIZE * BUFFER_PACKET_COUNT; private final TimestampAdjuster timestampAdjuster; + @WorkaroundFlags private final int workaroundFlags; private final ParsableByteArray tsPacketBuffer; private final ParsableBitArray tsScratch; @@ -103,7 +114,7 @@ public final class TsExtractor implements Extractor { this(timestampAdjuster, 0); } - public TsExtractor(TimestampAdjuster timestampAdjuster, int workaroundFlags) { + public TsExtractor(TimestampAdjuster timestampAdjuster, @WorkaroundFlags int workaroundFlags) { this.timestampAdjuster = timestampAdjuster; this.workaroundFlags = workaroundFlags; tsPacketBuffer = new ParsableByteArray(BUFFER_SIZE); diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java index b5e2268b53..a57060f604 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java @@ -31,6 +31,7 @@ import com.google.android.exoplayer2.C; /** Bits per sample for the audio data. */ private final int bitsPerSample; /** The PCM encoding */ + @C.PcmEncoding private final int encoding; /** Offset to the start of sample data. */ @@ -39,7 +40,7 @@ import com.google.android.exoplayer2.C; private long dataSize; public WavHeader(int numChannels, int sampleRateHz, int averageBytesPerSecond, int blockAlignment, - int bitsPerSample, int encoding) { + int bitsPerSample, @C.PcmEncoding int encoding) { this.numChannels = numChannels; this.sampleRateHz = sampleRateHz; this.averageBytesPerSecond = averageBytesPerSecond; @@ -99,6 +100,7 @@ import com.google.android.exoplayer2.C; } /** Returns the PCM encoding. **/ + @C.PcmEncoding public int getEncoding() { return encoding; } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java index 36fbcf40af..0e99380a1c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java @@ -87,7 +87,7 @@ import java.io.IOException; + blockAlignment); } - int encoding = Util.getPcmEncoding(bitsPerSample); + @C.PcmEncoding int encoding = Util.getPcmEncoding(bitsPerSample); if (encoding == C.ENCODING_INVALID) { Log.e(TAG, "Unsupported WAV bit depth: " + bitsPerSample); return null; diff --git a/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index dfc37f8472..63a77e2215 100644 --- a/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -293,7 +293,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { MediaCrypto mediaCrypto = null; boolean drmSessionRequiresSecureDecoder = false; if (drmSession != null) { - int drmSessionState = drmSession.getState(); + @DrmSession.State int drmSessionState = drmSession.getState(); if (drmSessionState == DrmSession.STATE_ERROR) { throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); } else if (drmSessionState == DrmSession.STATE_OPENED @@ -682,7 +682,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { if (drmSession == null) { return false; } - int drmSessionState = drmSession.getState(); + @DrmSession.State int drmSessionState = drmSession.getState(); if (drmSessionState == DrmSession.STATE_ERROR) { throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java index b213928516..8653a91a6d 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java @@ -15,11 +15,14 @@ */ package com.google.android.exoplayer2.source; +import android.support.annotation.IntDef; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaPeriod.Callback; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; @@ -36,11 +39,16 @@ public final class MergingMediaSource implements MediaSource { */ public static final class IllegalMergeException extends IOException { + /** + * The reason the merge failed. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({REASON_WINDOWS_ARE_DYNAMIC, REASON_PERIOD_COUNT_MISMATCH}) + public @interface Reason {} /** * The merge failed because one of the sources being merged has a dynamic window. */ public static final int REASON_WINDOWS_ARE_DYNAMIC = 0; - /** * The merge failed because the sources have different period counts. */ @@ -50,13 +58,14 @@ public final class MergingMediaSource implements MediaSource { * The reason the merge failed. One of {@link #REASON_WINDOWS_ARE_DYNAMIC} and * {@link #REASON_PERIOD_COUNT_MISMATCH}. */ + @Reason public final int reason; /** * @param reason The reason the merge failed. One of {@link #REASON_WINDOWS_ARE_DYNAMIC} and * {@link #REASON_PERIOD_COUNT_MISMATCH}. */ - public IllegalMergeException(int reason) { + public IllegalMergeException(@Reason int reason) { this.reason = reason; } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java b/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java index e14daf0d20..e316215160 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source.chunk; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.extractor.Extractor; @@ -150,7 +151,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput } @Override - public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { + public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, + byte[] encryptionKey) { trackOutput.sampleMetadata(timeUs, flags, size, offset, encryptionKey); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java b/library/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java index 945a9b7487..388dc63899 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java @@ -111,7 +111,8 @@ public final class InitializationChunk extends Chunk implements SingleTrackMetad } @Override - public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { + public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, + byte[] encryptionKey) { throw new IllegalStateException("Unexpected sample data in initialization chunk"); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index 79205ccbc6..8f2fc5a99b 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -355,7 +355,7 @@ import java.util.Locale; timestampAdjuster = timestampAdjusterProvider.getAdjuster(segment.discontinuitySequenceNumber, startTimeUs); // This flag ensures the change of pid between streams does not affect the sample queues. - int workaroundFlags = TsExtractor.WORKAROUND_MAP_BY_TYPE; + @TsExtractor.WorkaroundFlags int workaroundFlags = TsExtractor.WORKAROUND_MAP_BY_TYPE; String codecs = variants[newVariantIndex].format.codecs; if (!TextUtils.isEmpty(codecs)) { // Sometimes AAC and H264 streams are declared in TS chunks even though they don't really diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java index 98f4b20723..fb62d9978e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java @@ -15,18 +15,29 @@ */ package com.google.android.exoplayer2.source.hls.playlist; +import android.support.annotation.IntDef; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Represents an HLS playlist. */ public abstract class HlsPlaylist { + /** + * The type of playlist. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_MASTER, TYPE_MEDIA}) + public @interface Type {} public static final int TYPE_MASTER = 0; public static final int TYPE_MEDIA = 1; public final String baseUri; + @Type public final int type; - protected HlsPlaylist(String baseUri, int type) { + protected HlsPlaylist(String baseUri, @Type int type) { this.baseUri = baseUri; this.type = type; } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index 96f69b69db..a0757c364a 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -62,7 +62,6 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser{@link #EDGE_TYPE_DEPRESSED} * */ + @EdgeType public final int edgeType; /** @@ -126,8 +133,8 @@ public final class CaptionStyleCompat { * @param edgeColor See {@link #edgeColor}. * @param typeface See {@link #typeface}. */ - public CaptionStyleCompat(int foregroundColor, int backgroundColor, int windowColor, int edgeType, - int edgeColor, Typeface typeface) { + public CaptionStyleCompat(int foregroundColor, int backgroundColor, int windowColor, + @EdgeType int edgeType, int edgeColor, Typeface typeface) { this.foregroundColor = foregroundColor; this.backgroundColor = backgroundColor; this.windowColor = windowColor; @@ -137,6 +144,7 @@ public final class CaptionStyleCompat { } @TargetApi(19) + @SuppressWarnings("ResourceType") private static CaptionStyleCompat createFromCaptionStyleV19( CaptioningManager.CaptionStyle captionStyle) { return new CaptionStyleCompat( @@ -145,6 +153,7 @@ public final class CaptionStyleCompat { } @TargetApi(21) + @SuppressWarnings("ResourceType") private static CaptionStyleCompat createFromCaptionStyleV21( CaptioningManager.CaptionStyle captionStyle) { return new CaptionStyleCompat( diff --git a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java index 01d5b53c86..93b1dc1d9a 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java @@ -15,7 +15,10 @@ */ package com.google.android.exoplayer2.text; +import android.support.annotation.IntDef; import android.text.Layout.Alignment; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Contains information about a specific cue, including textual content and formatting data. @@ -26,6 +29,13 @@ public class Cue { * An unset position or width. */ public static final float DIMEN_UNSET = Float.MIN_VALUE; + + /** + * The type of anchor, which may be unset. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_UNSET, ANCHOR_TYPE_START, ANCHOR_TYPE_MIDDLE, ANCHOR_TYPE_END}) + public @interface AnchorType {} /** * An unset anchor or line type value. */ @@ -44,6 +54,13 @@ public class Cue { * box. */ public static final int ANCHOR_TYPE_END = 2; + + /** + * The type of line, which may be unset. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_UNSET, LINE_TYPE_FRACTION, LINE_TYPE_NUMBER}) + public @interface LineType {} /** * Value for {@link #lineType} when {@link #line} is a fractional position. */ @@ -83,6 +100,7 @@ public class Cue { * -1). For horizontal text the size of the first line of the cue is its height, and the start * and end of the viewport are the top and bottom respectively. */ + @LineType public final int lineType; /** * The cue box anchor positioned by {@link #line}. One of {@link #ANCHOR_TYPE_START}, @@ -92,6 +110,7 @@ public class Cue { * and {@link #ANCHOR_TYPE_END} correspond to the top, middle and bottom of the cue box * respectively. */ + @AnchorType public final int lineAnchor; /** * The fractional position of the {@link #positionAnchor} of the cue box within the viewport in @@ -110,6 +129,7 @@ public class Cue { * and {@link #ANCHOR_TYPE_END} correspond to the left, middle and right of the cue box * respectively. */ + @AnchorType public final int positionAnchor; /** * The size of the cue box in the writing direction specified as a fraction of the viewport size @@ -137,8 +157,8 @@ public class Cue { * @param positionAnchor See {@link #positionAnchor}. * @param size See {@link #size}. */ - public Cue(CharSequence text, Alignment textAlignment, float line, int lineType, int lineAnchor, - float position, int positionAnchor, float size) { + public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, + @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size) { this.text = text; this.textAlignment = textAlignment; this.line = line; diff --git a/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java b/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java index 75fe1154a9..5f30834b4d 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java @@ -24,6 +24,7 @@ import com.google.android.exoplayer2.text.Cue; public final float position; public final float line; + @Cue.LineType public final int lineType; public final float width; @@ -31,7 +32,7 @@ import com.google.android.exoplayer2.text.Cue; this(Cue.DIMEN_UNSET, Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET); } - public TtmlRegion(float position, float line, int lineType, float width) { + public TtmlRegion(float position, float line, @Cue.LineType int lineType, float width) { this.position = position; this.line = line; this.lineType = lineType; diff --git a/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java b/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java index aa87af0e57..e4c36be03a 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java @@ -16,8 +16,11 @@ package com.google.android.exoplayer2.text.ttml; import android.graphics.Typeface; +import android.support.annotation.IntDef; import android.text.Layout; import com.google.android.exoplayer2.util.Assertions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Style object of a TtmlNode @@ -26,15 +29,25 @@ import com.google.android.exoplayer2.util.Assertions; public static final int UNSPECIFIED = -1; + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {UNSPECIFIED, STYLE_NORMAL, STYLE_BOLD, STYLE_ITALIC, + STYLE_BOLD_ITALIC}) + public @interface StyleFlags {} public static final int STYLE_NORMAL = Typeface.NORMAL; public static final int STYLE_BOLD = Typeface.BOLD; public static final int STYLE_ITALIC = Typeface.ITALIC; public static final int STYLE_BOLD_ITALIC = Typeface.BOLD_ITALIC; + @Retention(RetentionPolicy.SOURCE) + @IntDef({UNSPECIFIED, FONT_SIZE_UNIT_PIXEL, FONT_SIZE_UNIT_EM, FONT_SIZE_UNIT_PERCENT}) + public @interface FontSizeUnit {} public static final int FONT_SIZE_UNIT_PIXEL = 1; public static final int FONT_SIZE_UNIT_EM = 2; public static final int FONT_SIZE_UNIT_PERCENT = 3; + @Retention(RetentionPolicy.SOURCE) + @IntDef({UNSPECIFIED, OFF, ON}) + private @interface OptionalBoolean {} private static final int OFF = 0; private static final int ON = 1; @@ -43,10 +56,15 @@ import com.google.android.exoplayer2.util.Assertions; private boolean hasFontColor; private int backgroundColor; private boolean hasBackgroundColor; + @OptionalBoolean private int linethrough; + @OptionalBoolean private int underline; + @OptionalBoolean private int bold; + @OptionalBoolean private int italic; + @FontSizeUnit private int fontSizeUnit; private float fontSize; private String id; @@ -67,12 +85,13 @@ import com.google.android.exoplayer2.util.Assertions; * @return {@link #UNSPECIFIED}, {@link #STYLE_NORMAL}, {@link #STYLE_BOLD}, {@link #STYLE_BOLD} * or {@link #STYLE_BOLD_ITALIC}. */ + @StyleFlags public int getStyle() { if (bold == UNSPECIFIED && italic == UNSPECIFIED) { return UNSPECIFIED; } - return (bold != UNSPECIFIED ? bold : STYLE_NORMAL) - | (italic != UNSPECIFIED ? italic : STYLE_NORMAL); + return (bold == ON ? STYLE_BOLD : STYLE_NORMAL) + | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL); } public boolean isLinethrough() { @@ -95,6 +114,18 @@ import com.google.android.exoplayer2.util.Assertions; return this; } + public TtmlStyle setBold(boolean bold) { + Assertions.checkState(inheritableStyle == null); + this.bold = bold ? ON : OFF; + return this; + } + + public TtmlStyle setItalic(boolean italic) { + Assertions.checkState(inheritableStyle == null); + this.italic = italic ? ON : OFF; + return this; + } + public String getFontFamily() { return fontFamily; } @@ -140,18 +171,6 @@ import com.google.android.exoplayer2.util.Assertions; return hasBackgroundColor; } - public TtmlStyle setBold(boolean isBold) { - Assertions.checkState(inheritableStyle == null); - bold = isBold ? STYLE_BOLD : STYLE_NORMAL; - return this; - } - - public TtmlStyle setItalic(boolean isItalic) { - Assertions.checkState(inheritableStyle == null); - italic = isItalic ? STYLE_ITALIC : STYLE_NORMAL; - return this; - } - /** * Inherits from an ancestor style. Properties like tts:backgroundColor which * are not inheritable are not inherited as well as properties which are already set locally @@ -236,6 +255,7 @@ import com.google.android.exoplayer2.util.Assertions; return this; } + @FontSizeUnit public int getFontSizeUnit() { return fontSizeUnit; } diff --git a/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java b/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java index 169bc6a8bf..157174a8f0 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java @@ -16,8 +16,11 @@ package com.google.android.exoplayer2.text.webvtt; import android.graphics.Typeface; +import android.support.annotation.IntDef; import android.text.Layout; import com.google.android.exoplayer2.util.Util; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -32,15 +35,25 @@ import java.util.List; public static final int UNSPECIFIED = -1; + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {UNSPECIFIED, STYLE_NORMAL, STYLE_BOLD, STYLE_ITALIC, + STYLE_BOLD_ITALIC}) + public @interface StyleFlags {} public static final int STYLE_NORMAL = Typeface.NORMAL; public static final int STYLE_BOLD = Typeface.BOLD; public static final int STYLE_ITALIC = Typeface.ITALIC; public static final int STYLE_BOLD_ITALIC = Typeface.BOLD_ITALIC; + @Retention(RetentionPolicy.SOURCE) + @IntDef({UNSPECIFIED, FONT_SIZE_UNIT_PIXEL, FONT_SIZE_UNIT_EM, FONT_SIZE_UNIT_PERCENT}) + public @interface FontSizeUnit {} public static final int FONT_SIZE_UNIT_PIXEL = 1; public static final int FONT_SIZE_UNIT_EM = 2; public static final int FONT_SIZE_UNIT_PERCENT = 3; + @Retention(RetentionPolicy.SOURCE) + @IntDef({UNSPECIFIED, OFF, ON}) + private @interface OptionalBoolean {} private static final int OFF = 0; private static final int ON = 1; @@ -56,10 +69,15 @@ import java.util.List; private boolean hasFontColor; private int backgroundColor; private boolean hasBackgroundColor; + @OptionalBoolean private int linethrough; + @OptionalBoolean private int underline; + @OptionalBoolean private int bold; + @OptionalBoolean private int italic; + @FontSizeUnit private int fontSizeUnit; private float fontSize; private Layout.Alignment textAlign; @@ -144,12 +162,13 @@ import java.util.List; * @return {@link #UNSPECIFIED}, {@link #STYLE_NORMAL}, {@link #STYLE_BOLD}, {@link #STYLE_BOLD} * or {@link #STYLE_BOLD_ITALIC}. */ + @StyleFlags public int getStyle() { if (bold == UNSPECIFIED && italic == UNSPECIFIED) { return UNSPECIFIED; } - return (bold != UNSPECIFIED ? bold : STYLE_NORMAL) - | (italic != UNSPECIFIED ? italic : STYLE_NORMAL); + return (bold == ON ? STYLE_BOLD : STYLE_NORMAL) + | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL); } public boolean isLinethrough() { @@ -169,6 +188,15 @@ import java.util.List; this.underline = underline ? ON : OFF; return this; } + public WebvttCssStyle setBold(boolean bold) { + this.bold = bold ? ON : OFF; + return this; + } + + public WebvttCssStyle setItalic(boolean italic) { + this.italic = italic ? ON : OFF; + return this; + } public String getFontFamily() { return fontFamily; @@ -213,16 +241,6 @@ import java.util.List; return hasBackgroundColor; } - public WebvttCssStyle setBold(boolean isBold) { - bold = isBold ? STYLE_BOLD : STYLE_NORMAL; - return this; - } - - public WebvttCssStyle setItalic(boolean isItalic) { - italic = isItalic ? STYLE_ITALIC : STYLE_NORMAL; - return this; - } - public Layout.Alignment getTextAlign() { return textAlign; } @@ -242,6 +260,7 @@ import java.util.List; return this; } + @FontSizeUnit public int getFontSizeUnit() { return fontSizeUnit; } diff --git a/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCue.java b/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCue.java index f1ce0e28fc..295fdc656f 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCue.java @@ -37,8 +37,9 @@ import com.google.android.exoplayer2.text.Cue; Cue.DIMEN_UNSET, Cue.TYPE_UNSET, Cue.DIMEN_UNSET); } - public WebvttCue(long startTime, long endTime, CharSequence text, Alignment textAlignment, - float line, int lineType, int lineAnchor, float position, int positionAnchor, float width) { + public WebvttCue(long startTime, long endTime, CharSequence text, Alignment textAlignment, + float line, @Cue.LineType int lineType, @Cue.AnchorType int lineAnchor, float position, + @Cue.AnchorType int positionAnchor, float width) { super(text, textAlignment, line, lineType, lineAnchor, position, positionAnchor, width); this.startTime = startTime; this.endTime = endTime; diff --git a/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index 4f76983d15..2351da716c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -442,7 +442,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { if (isSupported(trackFormatSupport[trackIndex])) { Format format = trackGroup.getFormat(trackIndex); - boolean isDefault = (format.selectionFlags & Format.SELECTION_FLAG_DEFAULT) != 0; + boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; int trackScore; if (formatHasLanguage(format, preferredAudioLanguage)) { if (isDefault) { @@ -480,8 +480,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { if (isSupported(trackFormatSupport[trackIndex])) { Format format = trackGroup.getFormat(trackIndex); - boolean isDefault = (format.selectionFlags & Format.SELECTION_FLAG_DEFAULT) != 0; - boolean isForced = (format.selectionFlags & Format.SELECTION_FLAG_FORCED) != 0; + boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; + boolean isForced = (format.selectionFlags & C.SELECTION_FLAG_FORCED) != 0; int trackScore; if (formatHasLanguage(format, preferredTextLanguage)) { if (isDefault) { @@ -530,7 +530,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { if (isSupported(trackFormatSupport[trackIndex])) { Format format = trackGroup.getFormat(trackIndex); - boolean isDefault = (format.selectionFlags & Format.SELECTION_FLAG_DEFAULT) != 0; + boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; int trackScore = isDefault ? 2 : 1; if (trackScore > selectedTrackScore) { selectedGroup = trackGroup; diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java index cb4eec40f1..8c3ac77cb2 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java @@ -66,9 +66,12 @@ import com.google.android.exoplayer2.util.Util; private CharSequence cueText; private Alignment cueTextAlignment; private float cueLine; + @Cue.LineType private int cueLineType; + @Cue.AnchorType private int cueLineAnchor; private float cuePosition; + @Cue.AnchorType private int cuePositionAnchor; private float cueSize; private boolean applyEmbeddedStyles; @@ -76,6 +79,7 @@ import com.google.android.exoplayer2.util.Util; private int backgroundColor; private int windowColor; private int edgeColor; + @CaptionStyleCompat.EdgeType private int edgeType; private float textSizePx; private float bottomPaddingFraction; diff --git a/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java b/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java index 5a469e1c90..d251446976 100644 --- a/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java +++ b/library/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java @@ -16,8 +16,11 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; +import android.support.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; /** @@ -25,6 +28,12 @@ import java.util.Arrays; */ public final class DataSpec { + /** + * The flags that apply to any request for data. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {FLAG_ALLOW_GZIP}) + public @interface Flags {} /** * Permits an underlying network stack to request that the server use gzip compression. *

@@ -69,6 +78,7 @@ public final class DataSpec { /** * Request flags. Currently {@link #FLAG_ALLOW_GZIP} is the only supported flag. */ + @Flags public final int flags; /** @@ -86,7 +96,7 @@ public final class DataSpec { * @param uri {@link #uri}. * @param flags {@link #flags}. */ - public DataSpec(Uri uri, int flags) { + public DataSpec(Uri uri, @Flags int flags) { this(uri, 0, C.LENGTH_UNSET, null, flags); } @@ -111,7 +121,7 @@ public final class DataSpec { * @param key {@link #key}. * @param flags {@link #flags}. */ - public DataSpec(Uri uri, long absoluteStreamPosition, long length, String key, int flags) { + public DataSpec(Uri uri, long absoluteStreamPosition, long length, String key, @Flags int flags) { this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, flags); } @@ -127,7 +137,7 @@ public final class DataSpec { * @param flags {@link #flags}. */ public DataSpec(Uri uri, long absoluteStreamPosition, long position, long length, String key, - int flags) { + @Flags int flags) { this(uri, null, absoluteStreamPosition, position, length, key, flags); } @@ -144,7 +154,7 @@ public final class DataSpec { * @param flags {@link #flags}. */ public DataSpec(Uri uri, byte[] postBody, long absoluteStreamPosition, long position, long length, - String key, int flags) { + String key, @Flags int flags) { Assertions.checkArgument(absoluteStreamPosition >= 0); Assertions.checkArgument(position >= 0); Assertions.checkArgument(length > 0 || length == C.LENGTH_UNSET); diff --git a/library/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java b/library/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java index b96fe515fc..f915ee4e24 100644 --- a/library/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java @@ -15,10 +15,13 @@ */ package com.google.android.exoplayer2.upstream; +import android.support.annotation.IntDef; import android.text.TextUtils; import com.google.android.exoplayer2.util.Predicate; import com.google.android.exoplayer2.util.Util; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; @@ -57,10 +60,14 @@ public interface HttpDataSource extends DataSource { */ class HttpDataSourceException extends IOException { + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_OPEN, TYPE_READ, TYPE_CLOSE}) + public @interface Type {} public static final int TYPE_OPEN = 1; public static final int TYPE_READ = 2; public static final int TYPE_CLOSE = 3; + @Type public final int type; /** @@ -68,25 +75,26 @@ public interface HttpDataSource extends DataSource { */ public final DataSpec dataSpec; - public HttpDataSourceException(DataSpec dataSpec, int type) { + public HttpDataSourceException(DataSpec dataSpec, @Type int type) { super(); this.dataSpec = dataSpec; this.type = type; } - public HttpDataSourceException(String message, DataSpec dataSpec, int type) { + public HttpDataSourceException(String message, DataSpec dataSpec, @Type int type) { super(message); this.dataSpec = dataSpec; this.type = type; } - public HttpDataSourceException(IOException cause, DataSpec dataSpec, int type) { + public HttpDataSourceException(IOException cause, DataSpec dataSpec, @Type int type) { super(cause); this.dataSpec = dataSpec; this.type = type; } - public HttpDataSourceException(String message, IOException cause, DataSpec dataSpec, int type) { + public HttpDataSourceException(String message, IOException cause, DataSpec dataSpec, + @Type int type) { super(message, cause); this.dataSpec = dataSpec; this.type = type; diff --git a/library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java b/library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java index 0cd7d54564..af2555bfb8 100644 --- a/library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.upstream.cache; import android.net.Uri; +import android.support.annotation.IntDef; import android.util.Log; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSink; @@ -27,6 +28,8 @@ import com.google.android.exoplayer2.upstream.TeeDataSource; import com.google.android.exoplayer2.upstream.cache.CacheDataSink.CacheDataSinkException; import java.io.IOException; import java.io.InterruptedIOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * A {@link DataSource} that reads and writes a {@link Cache}. Requests are fulfilled from the cache @@ -43,6 +46,13 @@ public final class CacheDataSource implements DataSource { */ public static final long DEFAULT_MAX_CACHE_FILE_SIZE = 2 * 1024 * 1024; + /** + * Flags controlling the cache's behavior. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = {FLAG_BLOCK_ON_CACHE, FLAG_IGNORE_CACHE_ON_ERROR, + FLAG_CACHE_UNBOUNDED_REQUESTS}) + public @interface Flags {} /** * A flag indicating whether we will block reads if the cache key is locked. If this flag is * set, then we will read from upstream if the cache key is locked. @@ -106,7 +116,7 @@ public final class CacheDataSource implements DataSource { * Constructs an instance with default {@link DataSource} and {@link DataSink} instances for * reading and writing the cache and with {@link #DEFAULT_MAX_CACHE_FILE_SIZE}. */ - public CacheDataSource(Cache cache, DataSource upstream, int flags) { + public CacheDataSource(Cache cache, DataSource upstream, @Flags int flags) { this(cache, upstream, flags, DEFAULT_MAX_CACHE_FILE_SIZE); } @@ -123,7 +133,8 @@ public final class CacheDataSource implements DataSource { * exceeds this value, then the data will be fragmented into multiple cache files. The * finer-grained this is the finer-grained the eviction policy can be. */ - public CacheDataSource(Cache cache, DataSource upstream, int flags, long maxCacheFileSize) { + public CacheDataSource(Cache cache, DataSource upstream, @Flags int flags, + long maxCacheFileSize) { this(cache, upstream, new FileDataSource(), new CacheDataSink(cache, maxCacheFileSize), flags, null); } @@ -142,7 +153,7 @@ public final class CacheDataSource implements DataSource { * @param eventListener An optional {@link EventListener} to receive events. */ public CacheDataSource(Cache cache, DataSource upstream, DataSource cacheReadDataSource, - DataSink cacheWriteDataSink, int flags, EventListener eventListener) { + DataSink cacheWriteDataSink, @Flags int flags, EventListener eventListener) { this.cache = cache; this.cacheReadDataSource = cacheReadDataSource; this.blockOnCache = (flags & FLAG_BLOCK_ON_CACHE) != 0; diff --git a/library/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/src/main/java/com/google/android/exoplayer2/util/Util.java index 6e11c43db1..c4505fd8b9 100644 --- a/library/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -88,27 +88,6 @@ public final class Util { */ public static final String MODEL = Build.MODEL; - /** - * Value returned by {@link #inferContentType(String)} for DASH manifests. - */ - public static final int TYPE_DASH = 0; - - /** - * Value returned by {@link #inferContentType(String)} for Smooth Streaming manifests. - */ - public static final int TYPE_SS = 1; - - /** - * Value returned by {@link #inferContentType(String)} for HLS manifests. - */ - public static final int TYPE_HLS = 2; - - /** - * Value returned by {@link #inferContentType(String)} for files other than DASH, HLS or Smooth - * Streaming manifests. - */ - public static final int TYPE_OTHER = 3; - private static final String TAG = "Util"; private static final Pattern XS_DATE_TIME_PATTERN = Pattern.compile( "(\\d\\d\\d\\d)\\-(\\d\\d)\\-(\\d\\d)[Tt]" @@ -712,6 +691,7 @@ public final class Util { * {@link C#ENCODING_PCM_32BIT}. If the bit depth is unsupported then * {@link C#ENCODING_INVALID} is returned. */ + @C.PcmEncoding public static int getPcmEncoding(int bitDepth) { switch (bitDepth) { case 8: @@ -731,19 +711,20 @@ public final class Util { * Makes a best guess to infer the type from a file name. * * @param fileName Name of the file. It can include the path of the file. - * @return One of {@link #TYPE_DASH}, {@link #TYPE_SS}, {@link #TYPE_HLS} or {@link #TYPE_OTHER}. + * @return The content type. */ + @C.ContentType public static int inferContentType(String fileName) { if (fileName == null) { - return TYPE_OTHER; + return C.TYPE_OTHER; } else if (fileName.endsWith(".mpd")) { - return TYPE_DASH; + return C.TYPE_DASH; } else if (fileName.endsWith(".ism") || fileName.endsWith(".isml")) { - return TYPE_SS; + return C.TYPE_SS; } else if (fileName.endsWith(".m3u8")) { - return TYPE_HLS; + return C.TYPE_HLS; } else { - return TYPE_OTHER; + return C.TYPE_OTHER; } } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java index a66e13cfd6..b399d79e8d 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java @@ -88,7 +88,8 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable { } @Override - public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { + public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, + byte[] encryptionKey) { sampleTimesUs.add(timeUs); sampleFlags.add(flags); sampleStartOffsets.add(sampleData.length - offset - size);