Use @IntDef for some more int-based enumerations

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188853170
This commit is contained in:
andrewlewis 2018-03-13 03:54:48 -07:00 committed by Oliver Woodman
parent 4f56636328
commit 07f898d441
19 changed files with 298 additions and 230 deletions

View File

@ -15,21 +15,29 @@
*/ */
package com.google.android.exoplayer2; package com.google.android.exoplayer2;
import android.support.annotation.IntDef;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** /**
* Renders media read from a {@link SampleStream}. * Renders media read from a {@link SampleStream}.
* *
* <p>Internally, a renderer's lifecycle is managed by the owning {@link ExoPlayer}. The renderer is * <p>Internally, a renderer's lifecycle is managed by the owning {@link ExoPlayer}. The renderer is
* transitioned through various states as the overall playback state changes. The valid state * transitioned through various states as the overall playback state and enabled tracks change. The
* transitions are shown below, annotated with the methods that are called during each transition. * valid state transitions are shown below, annotated with the methods that are called during each
* transition.
* *
* <p align="center"><img src="doc-files/renderer-states.svg" alt="Renderer state transitions"> * <p align="center"><img src="doc-files/renderer-states.svg" alt="Renderer state transitions">
*/ */
public interface Renderer extends PlayerMessage.Target { public interface Renderer extends PlayerMessage.Target {
/** The renderer states. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({STATE_DISABLED, STATE_ENABLED, STATE_STARTED})
@interface State {}
/** /**
* The renderer is disabled. * The renderer is disabled.
*/ */
@ -80,8 +88,10 @@ public interface Renderer extends PlayerMessage.Target {
/** /**
* Returns the current state of the renderer. * Returns the current state of the renderer.
* *
* @return The current state (one of the {@code STATE_*} constants). * @return The current state. One of {@link #STATE_DISABLED}, {@link #STATE_ENABLED} and {@link
* #STATE_STARTED}.
*/ */
@State
int getState(); int getState();
/** /**

View File

@ -15,41 +15,35 @@
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.audio.Ac3Util.Ac3SyncFrameInfo.STREAM_TYPE_TYPE0; import android.support.annotation.IntDef;
import static com.google.android.exoplayer2.audio.Ac3Util.Ac3SyncFrameInfo.STREAM_TYPE_TYPE1;
import static com.google.android.exoplayer2.audio.Ac3Util.Ac3SyncFrameInfo.STREAM_TYPE_UNDEFINED;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.audio.Ac3Util.SyncFrameInfo.StreamType;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** Utility methods for parsing Dolby TrueHD and (E-)AC3 syncframes. */ /** Utility methods for parsing Dolby TrueHD and (E-)AC3 syncframes. */
public final class Ac3Util { public final class Ac3Util {
/** /** Holds sample format information as presented by a syncframe header. */
* Holds sample format information as presented by a syncframe header. public static final class SyncFrameInfo {
*/
public static final class Ac3SyncFrameInfo {
/** /** AC3 stream types. See also ETSI TS 102 366 E.1.3.1.1. */
* Undefined AC3 stream type. @Retention(RetentionPolicy.SOURCE)
*/ @IntDef({STREAM_TYPE_UNDEFINED, STREAM_TYPE_TYPE0, STREAM_TYPE_TYPE1, STREAM_TYPE_TYPE2})
public @interface StreamType {}
/** Undefined AC3 stream type. */
public static final int STREAM_TYPE_UNDEFINED = -1; public static final int STREAM_TYPE_UNDEFINED = -1;
/** /** Type 0 AC3 stream type. */
* Type 0 AC3 stream type. See ETSI TS 102 366 E.1.3.1.1.
*/
public static final int STREAM_TYPE_TYPE0 = 0; public static final int STREAM_TYPE_TYPE0 = 0;
/** /** Type 1 AC3 stream type. */
* Type 1 AC3 stream type. See ETSI TS 102 366 E.1.3.1.1.
*/
public static final int STREAM_TYPE_TYPE1 = 1; public static final int STREAM_TYPE_TYPE1 = 1;
/** /** Type 2 AC3 stream type. */
* Type 2 AC3 stream type. See ETSI TS 102 366 E.1.3.1.1.
*/
public static final int STREAM_TYPE_TYPE2 = 2; public static final int STREAM_TYPE_TYPE2 = 2;
/** /**
@ -58,10 +52,10 @@ public final class Ac3Util {
*/ */
public final String mimeType; public final String mimeType;
/** /**
* The type of the stream if {@link #mimeType} is {@link MimeTypes#AUDIO_E_AC3}, or * The type of the stream if {@link #mimeType} is {@link MimeTypes#AUDIO_E_AC3}, or {@link
* {@link #STREAM_TYPE_UNDEFINED} otherwise. * #STREAM_TYPE_UNDEFINED} otherwise.
*/ */
public final int streamType; public final @StreamType int streamType;
/** /**
* The audio sampling rate in Hz. * The audio sampling rate in Hz.
*/ */
@ -79,8 +73,13 @@ public final class Ac3Util {
*/ */
public final int sampleCount; public final int sampleCount;
private Ac3SyncFrameInfo(String mimeType, int streamType, int channelCount, int sampleRate, private SyncFrameInfo(
int frameSize, int sampleCount) { String mimeType,
@StreamType int streamType,
int channelCount,
int sampleRate,
int frameSize,
int sampleCount) {
this.mimeType = mimeType; this.mimeType = mimeType;
this.streamType = streamType; this.streamType = streamType;
this.channelCount = channelCount; this.channelCount = channelCount;
@ -212,13 +211,13 @@ public final class Ac3Util {
* @param data The data to parse, positioned at the start of the syncframe. * @param data The data to parse, positioned at the start of the syncframe.
* @return The (E-)AC-3 format data parsed from the header. * @return The (E-)AC-3 format data parsed from the header.
*/ */
public static Ac3SyncFrameInfo parseAc3SyncframeInfo(ParsableBitArray data) { public static SyncFrameInfo parseAc3SyncframeInfo(ParsableBitArray data) {
int initialPosition = data.getPosition(); int initialPosition = data.getPosition();
data.skipBits(40); data.skipBits(40);
boolean isEac3 = data.readBits(5) == 16; boolean isEac3 = data.readBits(5) == 16;
data.setPosition(initialPosition); data.setPosition(initialPosition);
String mimeType; String mimeType;
int streamType = STREAM_TYPE_UNDEFINED; @StreamType int streamType = SyncFrameInfo.STREAM_TYPE_UNDEFINED;
int sampleRate; int sampleRate;
int acmod; int acmod;
int frameSize; int frameSize;
@ -228,7 +227,20 @@ public final class Ac3Util {
if (isEac3) { if (isEac3) {
// Syntax from ETSI TS 102 366 V1.2.1 subsections E.1.2.1 and E.1.2.2. // Syntax from ETSI TS 102 366 V1.2.1 subsections E.1.2.1 and E.1.2.2.
data.skipBits(16); // syncword data.skipBits(16); // syncword
streamType = data.readBits(2); switch (data.readBits(2)) { // strmtyp
case 0:
streamType = SyncFrameInfo.STREAM_TYPE_TYPE0;
break;
case 1:
streamType = SyncFrameInfo.STREAM_TYPE_TYPE1;
break;
case 2:
streamType = SyncFrameInfo.STREAM_TYPE_TYPE2;
break;
default:
streamType = SyncFrameInfo.STREAM_TYPE_UNDEFINED;
break;
}
data.skipBits(3); // substreamid data.skipBits(3); // substreamid
frameSize = (data.readBits(11) + 1) * 2; frameSize = (data.readBits(11) + 1) * 2;
int fscod = data.readBits(2); int fscod = data.readBits(2);
@ -257,7 +269,7 @@ public final class Ac3Util {
data.skipBits(8); // compr2 data.skipBits(8); // compr2
} }
} }
if (streamType == STREAM_TYPE_TYPE1 && data.readBit()) { // chanmape if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE1 && data.readBit()) { // chanmape
data.skipBits(16); // chanmap data.skipBits(16); // chanmap
} }
if (data.readBit()) { // mixmdate if (data.readBit()) { // mixmdate
@ -273,7 +285,7 @@ public final class Ac3Util {
if (lfeon && data.readBit()) { // lfemixlevcode if (lfeon && data.readBit()) { // lfemixlevcode
data.skipBits(5); // lfemixlevcod data.skipBits(5); // lfemixlevcod
} }
if (streamType == STREAM_TYPE_TYPE0) { if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE0) {
if (data.readBit()) { // pgmscle if (data.readBit()) { // pgmscle
data.skipBits(6); //pgmscl data.skipBits(6); //pgmscl
} }
@ -375,10 +387,11 @@ public final class Ac3Util {
data.skipBit(); // sourcefscod data.skipBit(); // sourcefscod
} }
} }
if (streamType == 0 && numblkscod != 3) { if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE0 && numblkscod != 3) {
data.skipBit(); // convsync data.skipBit(); // convsync
} }
if (streamType == 2 && (numblkscod == 3 || data.readBit())) { // blkid if (streamType == SyncFrameInfo.STREAM_TYPE_TYPE2
&& (numblkscod == 3 || data.readBit())) { // blkid
data.skipBits(6); // frmsizecod data.skipBits(6); // frmsizecod
} }
mimeType = MimeTypes.AUDIO_E_AC3; mimeType = MimeTypes.AUDIO_E_AC3;
@ -410,8 +423,8 @@ public final class Ac3Util {
lfeon = data.readBit(); lfeon = data.readBit();
channelCount = CHANNEL_COUNT_BY_ACMOD[acmod] + (lfeon ? 1 : 0); channelCount = CHANNEL_COUNT_BY_ACMOD[acmod] + (lfeon ? 1 : 0);
} }
return new Ac3SyncFrameInfo(mimeType, streamType, channelCount, sampleRate, frameSize, return new SyncFrameInfo(
sampleCount); mimeType, streamType, channelCount, sampleRate, frameSize, sampleCount);
} }
/** /**

View File

@ -80,6 +80,10 @@ public final class DefaultAudioSink implements AudioSink {
*/ */
private static final int BUFFER_MULTIPLICATION_FACTOR = 4; private static final int BUFFER_MULTIPLICATION_FACTOR = 4;
/** {@link AudioTrack} playback states. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({PLAYSTATE_STOPPED, PLAYSTATE_PAUSED, PLAYSTATE_PLAYING})
private @interface PlayState {}
/** /**
* @see AudioTrack#PLAYSTATE_STOPPED * @see AudioTrack#PLAYSTATE_STOPPED
*/ */
@ -965,8 +969,7 @@ public final class DefaultAudioSink implements AudioSink {
startMediaTimeState = START_NOT_SET; startMediaTimeState = START_NOT_SET;
latencyUs = 0; latencyUs = 0;
resetSyncParams(); resetSyncParams();
int playState = audioTrack.getPlayState(); if (audioTrack.getPlayState() == PLAYSTATE_PLAYING) {
if (playState == PLAYSTATE_PLAYING) {
audioTrack.pause(); audioTrack.pause();
} }
// AudioTrack.release can take some time, so we call it on a background thread. // AudioTrack.release can take some time, so we call it on a background thread.
@ -1426,8 +1429,8 @@ public final class DefaultAudioSink implements AudioSink {
return Math.min(endPlaybackHeadPosition, stopPlaybackHeadPosition + framesSinceStop); return Math.min(endPlaybackHeadPosition, stopPlaybackHeadPosition + framesSinceStop);
} }
int state = audioTrack.getPlayState(); @PlayState int playState = audioTrack.getPlayState();
if (state == PLAYSTATE_STOPPED) { if (playState == PLAYSTATE_STOPPED) {
// The audio track hasn't been started. // The audio track hasn't been started.
return 0; return 0;
} }
@ -1437,15 +1440,16 @@ public final class DefaultAudioSink implements AudioSink {
// Work around an issue with passthrough/direct AudioTracks on platform API versions 21/22 // Work around an issue with passthrough/direct AudioTracks on platform API versions 21/22
// where the playback head position jumps back to zero on paused passthrough/direct audio // where the playback head position jumps back to zero on paused passthrough/direct audio
// tracks. See [Internal: b/19187573]. // tracks. See [Internal: b/19187573].
if (state == PLAYSTATE_PAUSED && rawPlaybackHeadPosition == 0) { if (playState == PLAYSTATE_PAUSED && rawPlaybackHeadPosition == 0) {
passthroughWorkaroundPauseOffset = lastRawPlaybackHeadPosition; passthroughWorkaroundPauseOffset = lastRawPlaybackHeadPosition;
} }
rawPlaybackHeadPosition += passthroughWorkaroundPauseOffset; rawPlaybackHeadPosition += passthroughWorkaroundPauseOffset;
} }
if (Util.SDK_INT <= 28) { if (Util.SDK_INT <= 28) {
if (rawPlaybackHeadPosition == 0 && lastRawPlaybackHeadPosition > 0 if (rawPlaybackHeadPosition == 0
&& state == PLAYSTATE_PLAYING) { && lastRawPlaybackHeadPosition > 0
&& playState == PLAYSTATE_PLAYING) {
// If connecting a Bluetooth audio device fails, the AudioTrack may be left in a state // If connecting a Bluetooth audio device fails, the AudioTrack may be left in a state
// where its Java API is in the playing state, but the native track is stopped. When this // where its Java API is in the playing state, but the native track is stopped. When this
// happens the playback head position gets stuck at zero. In this case, return the old // happens the playback head position gets stuck at zero. In this case, return the old

View File

@ -15,12 +15,15 @@
*/ */
package com.google.android.exoplayer2.extractor.mkv; package com.google.android.exoplayer2.extractor.mkv;
import android.support.annotation.IntDef;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Stack; import java.util.Stack;
/** /**
@ -28,6 +31,10 @@ import java.util.Stack;
*/ */
/* package */ final class DefaultEbmlReader implements EbmlReader { /* package */ final class DefaultEbmlReader implements EbmlReader {
@Retention(RetentionPolicy.SOURCE)
@IntDef({ELEMENT_STATE_READ_ID, ELEMENT_STATE_READ_CONTENT_SIZE, ELEMENT_STATE_READ_CONTENT})
private @interface ElementState {}
private static final int ELEMENT_STATE_READ_ID = 0; private static final int ELEMENT_STATE_READ_ID = 0;
private static final int ELEMENT_STATE_READ_CONTENT_SIZE = 1; private static final int ELEMENT_STATE_READ_CONTENT_SIZE = 1;
private static final int ELEMENT_STATE_READ_CONTENT = 2; private static final int ELEMENT_STATE_READ_CONTENT = 2;
@ -44,7 +51,7 @@ import java.util.Stack;
private final VarintReader varintReader = new VarintReader(); private final VarintReader varintReader = new VarintReader();
private EbmlReaderOutput output; private EbmlReaderOutput output;
private int elementState; private @ElementState int elementState;
private int elementId; private int elementId;
private long elementContentSize; private long elementContentSize;
@ -88,23 +95,23 @@ import java.util.Stack;
elementState = ELEMENT_STATE_READ_CONTENT; elementState = ELEMENT_STATE_READ_CONTENT;
} }
int type = output.getElementType(elementId); @EbmlReaderOutput.ElementType int type = output.getElementType(elementId);
switch (type) { switch (type) {
case TYPE_MASTER: case EbmlReaderOutput.TYPE_MASTER:
long elementContentPosition = input.getPosition(); long elementContentPosition = input.getPosition();
long elementEndPosition = elementContentPosition + elementContentSize; long elementEndPosition = elementContentPosition + elementContentSize;
masterElementsStack.add(new MasterElement(elementId, elementEndPosition)); masterElementsStack.add(new MasterElement(elementId, elementEndPosition));
output.startMasterElement(elementId, elementContentPosition, elementContentSize); output.startMasterElement(elementId, elementContentPosition, elementContentSize);
elementState = ELEMENT_STATE_READ_ID; elementState = ELEMENT_STATE_READ_ID;
return true; return true;
case TYPE_UNSIGNED_INT: case EbmlReaderOutput.TYPE_UNSIGNED_INT:
if (elementContentSize > MAX_INTEGER_ELEMENT_SIZE_BYTES) { if (elementContentSize > MAX_INTEGER_ELEMENT_SIZE_BYTES) {
throw new ParserException("Invalid integer size: " + elementContentSize); throw new ParserException("Invalid integer size: " + elementContentSize);
} }
output.integerElement(elementId, readInteger(input, (int) elementContentSize)); output.integerElement(elementId, readInteger(input, (int) elementContentSize));
elementState = ELEMENT_STATE_READ_ID; elementState = ELEMENT_STATE_READ_ID;
return true; return true;
case TYPE_FLOAT: case EbmlReaderOutput.TYPE_FLOAT:
if (elementContentSize != VALID_FLOAT32_ELEMENT_SIZE_BYTES if (elementContentSize != VALID_FLOAT32_ELEMENT_SIZE_BYTES
&& elementContentSize != VALID_FLOAT64_ELEMENT_SIZE_BYTES) { && elementContentSize != VALID_FLOAT64_ELEMENT_SIZE_BYTES) {
throw new ParserException("Invalid float size: " + elementContentSize); throw new ParserException("Invalid float size: " + elementContentSize);
@ -112,18 +119,18 @@ import java.util.Stack;
output.floatElement(elementId, readFloat(input, (int) elementContentSize)); output.floatElement(elementId, readFloat(input, (int) elementContentSize));
elementState = ELEMENT_STATE_READ_ID; elementState = ELEMENT_STATE_READ_ID;
return true; return true;
case TYPE_STRING: case EbmlReaderOutput.TYPE_STRING:
if (elementContentSize > Integer.MAX_VALUE) { if (elementContentSize > Integer.MAX_VALUE) {
throw new ParserException("String element size: " + elementContentSize); throw new ParserException("String element size: " + elementContentSize);
} }
output.stringElement(elementId, readString(input, (int) elementContentSize)); output.stringElement(elementId, readString(input, (int) elementContentSize));
elementState = ELEMENT_STATE_READ_ID; elementState = ELEMENT_STATE_READ_ID;
return true; return true;
case TYPE_BINARY: case EbmlReaderOutput.TYPE_BINARY:
output.binaryElement(elementId, (int) elementContentSize, input); output.binaryElement(elementId, (int) elementContentSize, input);
elementState = ELEMENT_STATE_READ_ID; elementState = ELEMENT_STATE_READ_ID;
return true; return true;
case TYPE_UNKNOWN: case EbmlReaderOutput.TYPE_UNKNOWN:
input.skipFully((int) elementContentSize); input.skipFully((int) elementContentSize);
elementState = ELEMENT_STATE_READ_ID; elementState = ELEMENT_STATE_READ_ID;
break; break;

View File

@ -28,31 +28,6 @@ import java.io.IOException;
*/ */
/* package */ interface EbmlReader { /* package */ interface EbmlReader {
/**
* Type for unknown elements.
*/
int TYPE_UNKNOWN = 0;
/**
* Type for elements that contain child elements.
*/
int TYPE_MASTER = 1;
/**
* Type for integer value elements of up to 8 bytes.
*/
int TYPE_UNSIGNED_INT = 2;
/**
* Type for string elements.
*/
int TYPE_STRING = 3;
/**
* Type for binary elements.
*/
int TYPE_BINARY = 4;
/**
* Type for IEEE floating point value elements of either 4 or 8 bytes.
*/
int TYPE_FLOAT = 5;
/** /**
* Initializes the extractor with an {@link EbmlReaderOutput}. * Initializes the extractor with an {@link EbmlReaderOutput}.
* *

View File

@ -15,24 +15,46 @@
*/ */
package com.google.android.exoplayer2.extractor.mkv; package com.google.android.exoplayer2.extractor.mkv;
import android.support.annotation.IntDef;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** /**
* Defines EBML element IDs/types and reacts to events. * Defines EBML element IDs/types and reacts to events.
*/ */
/* package */ interface EbmlReaderOutput { /* package */ interface EbmlReaderOutput {
/** EBML element types. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_UNKNOWN, TYPE_MASTER, TYPE_UNSIGNED_INT, TYPE_STRING, TYPE_BINARY, TYPE_FLOAT})
@interface ElementType {}
/** Type for unknown elements. */
int TYPE_UNKNOWN = 0;
/** Type for elements that contain child elements. */
int TYPE_MASTER = 1;
/** Type for integer value elements of up to 8 bytes. */
int TYPE_UNSIGNED_INT = 2;
/** Type for string elements. */
int TYPE_STRING = 3;
/** Type for binary elements. */
int TYPE_BINARY = 4;
/** Type for IEEE floating point value elements of either 4 or 8 bytes. */
int TYPE_FLOAT = 5;
/** /**
* Maps an element ID to a corresponding type. * Maps an element ID to a corresponding type.
* <p> *
* If {@link EbmlReader#TYPE_UNKNOWN} is returned then the element is skipped. Note that all * <p>If {@link #TYPE_UNKNOWN} is returned then the element is skipped. Note that all children of
* children of a skipped element are also skipped. * a skipped element are also skipped.
* *
* @param id The element ID to map. * @param id The element ID to map.
* @return One of the {@code TYPE_} constants defined in {@link EbmlReader}. * @return One of {@link #TYPE_UNKNOWN}, {@link #TYPE_MASTER}, {@link #TYPE_UNSIGNED_INT}, {@link
* #TYPE_STRING}, {@link #TYPE_BINARY} and {@link #TYPE_FLOAT}.
*/ */
@ElementType
int getElementType(int id); int getElementType(int id);
/** /**

View File

@ -448,100 +448,6 @@ public final class MatroskaExtractor implements Extractor {
return Extractor.RESULT_CONTINUE; return Extractor.RESULT_CONTINUE;
} }
/* package */ int getElementType(int id) {
switch (id) {
case ID_EBML:
case ID_SEGMENT:
case ID_SEEK_HEAD:
case ID_SEEK:
case ID_INFO:
case ID_CLUSTER:
case ID_TRACKS:
case ID_TRACK_ENTRY:
case ID_AUDIO:
case ID_VIDEO:
case ID_CONTENT_ENCODINGS:
case ID_CONTENT_ENCODING:
case ID_CONTENT_COMPRESSION:
case ID_CONTENT_ENCRYPTION:
case ID_CONTENT_ENCRYPTION_AES_SETTINGS:
case ID_CUES:
case ID_CUE_POINT:
case ID_CUE_TRACK_POSITIONS:
case ID_BLOCK_GROUP:
case ID_PROJECTION:
case ID_COLOUR:
case ID_MASTERING_METADATA:
return EbmlReader.TYPE_MASTER;
case ID_EBML_READ_VERSION:
case ID_DOC_TYPE_READ_VERSION:
case ID_SEEK_POSITION:
case ID_TIMECODE_SCALE:
case ID_TIME_CODE:
case ID_BLOCK_DURATION:
case ID_PIXEL_WIDTH:
case ID_PIXEL_HEIGHT:
case ID_DISPLAY_WIDTH:
case ID_DISPLAY_HEIGHT:
case ID_DISPLAY_UNIT:
case ID_TRACK_NUMBER:
case ID_TRACK_TYPE:
case ID_FLAG_DEFAULT:
case ID_FLAG_FORCED:
case ID_DEFAULT_DURATION:
case ID_CODEC_DELAY:
case ID_SEEK_PRE_ROLL:
case ID_CHANNELS:
case ID_AUDIO_BIT_DEPTH:
case ID_CONTENT_ENCODING_ORDER:
case ID_CONTENT_ENCODING_SCOPE:
case ID_CONTENT_COMPRESSION_ALGORITHM:
case ID_CONTENT_ENCRYPTION_ALGORITHM:
case ID_CONTENT_ENCRYPTION_AES_SETTINGS_CIPHER_MODE:
case ID_CUE_TIME:
case ID_CUE_CLUSTER_POSITION:
case ID_REFERENCE_BLOCK:
case ID_STEREO_MODE:
case ID_COLOUR_RANGE:
case ID_COLOUR_TRANSFER:
case ID_COLOUR_PRIMARIES:
case ID_MAX_CLL:
case ID_MAX_FALL:
return EbmlReader.TYPE_UNSIGNED_INT;
case ID_DOC_TYPE:
case ID_CODEC_ID:
case ID_LANGUAGE:
return EbmlReader.TYPE_STRING;
case ID_SEEK_ID:
case ID_CONTENT_COMPRESSION_SETTINGS:
case ID_CONTENT_ENCRYPTION_KEY_ID:
case ID_SIMPLE_BLOCK:
case ID_BLOCK:
case ID_CODEC_PRIVATE:
case ID_PROJECTION_PRIVATE:
return EbmlReader.TYPE_BINARY;
case ID_DURATION:
case ID_SAMPLING_FREQUENCY:
case ID_PRIMARY_R_CHROMATICITY_X:
case ID_PRIMARY_R_CHROMATICITY_Y:
case ID_PRIMARY_G_CHROMATICITY_X:
case ID_PRIMARY_G_CHROMATICITY_Y:
case ID_PRIMARY_B_CHROMATICITY_X:
case ID_PRIMARY_B_CHROMATICITY_Y:
case ID_WHITE_POINT_CHROMATICITY_X:
case ID_WHITE_POINT_CHROMATICITY_Y:
case ID_LUMNINANCE_MAX:
case ID_LUMNINANCE_MIN:
return EbmlReader.TYPE_FLOAT;
default:
return EbmlReader.TYPE_UNKNOWN;
}
}
/* package */ boolean isLevel1Element(int id) {
return id == ID_SEGMENT_INFO || id == ID_CLUSTER || id == ID_CUES || id == ID_TRACKS;
}
/* package */ void startMasterElement(int id, long contentPosition, long contentSize) /* package */ void startMasterElement(int id, long contentPosition, long contentSize)
throws ParserException { throws ParserException {
switch (id) { switch (id) {
@ -1501,12 +1407,98 @@ public final class MatroskaExtractor implements Extractor {
@Override @Override
public int getElementType(int id) { public int getElementType(int id) {
return MatroskaExtractor.this.getElementType(id); switch (id) {
case ID_EBML:
case ID_SEGMENT:
case ID_SEEK_HEAD:
case ID_SEEK:
case ID_INFO:
case ID_CLUSTER:
case ID_TRACKS:
case ID_TRACK_ENTRY:
case ID_AUDIO:
case ID_VIDEO:
case ID_CONTENT_ENCODINGS:
case ID_CONTENT_ENCODING:
case ID_CONTENT_COMPRESSION:
case ID_CONTENT_ENCRYPTION:
case ID_CONTENT_ENCRYPTION_AES_SETTINGS:
case ID_CUES:
case ID_CUE_POINT:
case ID_CUE_TRACK_POSITIONS:
case ID_BLOCK_GROUP:
case ID_PROJECTION:
case ID_COLOUR:
case ID_MASTERING_METADATA:
return TYPE_MASTER;
case ID_EBML_READ_VERSION:
case ID_DOC_TYPE_READ_VERSION:
case ID_SEEK_POSITION:
case ID_TIMECODE_SCALE:
case ID_TIME_CODE:
case ID_BLOCK_DURATION:
case ID_PIXEL_WIDTH:
case ID_PIXEL_HEIGHT:
case ID_DISPLAY_WIDTH:
case ID_DISPLAY_HEIGHT:
case ID_DISPLAY_UNIT:
case ID_TRACK_NUMBER:
case ID_TRACK_TYPE:
case ID_FLAG_DEFAULT:
case ID_FLAG_FORCED:
case ID_DEFAULT_DURATION:
case ID_CODEC_DELAY:
case ID_SEEK_PRE_ROLL:
case ID_CHANNELS:
case ID_AUDIO_BIT_DEPTH:
case ID_CONTENT_ENCODING_ORDER:
case ID_CONTENT_ENCODING_SCOPE:
case ID_CONTENT_COMPRESSION_ALGORITHM:
case ID_CONTENT_ENCRYPTION_ALGORITHM:
case ID_CONTENT_ENCRYPTION_AES_SETTINGS_CIPHER_MODE:
case ID_CUE_TIME:
case ID_CUE_CLUSTER_POSITION:
case ID_REFERENCE_BLOCK:
case ID_STEREO_MODE:
case ID_COLOUR_RANGE:
case ID_COLOUR_TRANSFER:
case ID_COLOUR_PRIMARIES:
case ID_MAX_CLL:
case ID_MAX_FALL:
return TYPE_UNSIGNED_INT;
case ID_DOC_TYPE:
case ID_CODEC_ID:
case ID_LANGUAGE:
return TYPE_STRING;
case ID_SEEK_ID:
case ID_CONTENT_COMPRESSION_SETTINGS:
case ID_CONTENT_ENCRYPTION_KEY_ID:
case ID_SIMPLE_BLOCK:
case ID_BLOCK:
case ID_CODEC_PRIVATE:
case ID_PROJECTION_PRIVATE:
return TYPE_BINARY;
case ID_DURATION:
case ID_SAMPLING_FREQUENCY:
case ID_PRIMARY_R_CHROMATICITY_X:
case ID_PRIMARY_R_CHROMATICITY_Y:
case ID_PRIMARY_G_CHROMATICITY_X:
case ID_PRIMARY_G_CHROMATICITY_Y:
case ID_PRIMARY_B_CHROMATICITY_X:
case ID_PRIMARY_B_CHROMATICITY_Y:
case ID_WHITE_POINT_CHROMATICITY_X:
case ID_WHITE_POINT_CHROMATICITY_Y:
case ID_LUMNINANCE_MAX:
case ID_LUMNINANCE_MIN:
return TYPE_FLOAT;
default:
return TYPE_UNKNOWN;
}
} }
@Override @Override
public boolean isLevel1Element(int id) { public boolean isLevel1Element(int id) {
return MatroskaExtractor.this.isLevel1Element(id); return id == ID_SEGMENT_INFO || id == ID_CLUSTER || id == ID_CUES || id == ID_TRACKS;
} }
@Override @Override

View File

@ -19,6 +19,7 @@ import android.support.annotation.IntDef;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.audio.Ac3Util; import com.google.android.exoplayer2.audio.Ac3Util;
import com.google.android.exoplayer2.audio.Ac3Util.SyncFrameInfo;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator;
@ -187,7 +188,7 @@ public final class Ac3Reader implements ElementaryStreamReader {
@SuppressWarnings("ReferenceEquality") @SuppressWarnings("ReferenceEquality")
private void parseHeader() { private void parseHeader() {
headerScratchBits.setPosition(0); headerScratchBits.setPosition(0);
Ac3Util.Ac3SyncFrameInfo frameInfo = Ac3Util.parseAc3SyncframeInfo(headerScratchBits); SyncFrameInfo frameInfo = Ac3Util.parseAc3SyncframeInfo(headerScratchBits);
if (format == null || frameInfo.channelCount != format.channelCount if (format == null || frameInfo.channelCount != format.channelCount
|| frameInfo.sampleRate != format.sampleRate || frameInfo.sampleRate != format.sampleRate
|| frameInfo.mimeType != format.sampleMimeType) { || frameInfo.mimeType != format.sampleMimeType) {

View File

@ -524,8 +524,8 @@ import java.util.Arrays;
} }
@Override @Override
public int onLoadError(ExtractingLoadable loadable, long elapsedRealtimeMs, public @Loader.RetryAction int onLoadError(
long loadDurationMs, IOException error) { ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
boolean isErrorFatal = isLoadableExceptionFatal(error); boolean isErrorFatal = isLoadableExceptionFatal(error);
eventDispatcher.loadError( eventDispatcher.loadError(
loadable.dataSpec, loadable.dataSpec,

View File

@ -221,8 +221,8 @@ import java.util.Arrays;
} }
@Override @Override
public int onLoadError(SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, public @Loader.RetryAction int onLoadError(
IOException error) { SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
errorCount++; errorCount++;
boolean cancel = treatLoadErrorsAsEndOfStream && errorCount >= minLoadableRetryCount; boolean cancel = treatLoadErrorsAsEndOfStream && errorCount >= minLoadableRetryCount;
eventDispatcher.loadError( eventDispatcher.loadError(

View File

@ -409,8 +409,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
@Override @Override
public int onLoadError(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, public @Loader.RetryAction int onLoadError(
IOException error) { Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
long bytesLoaded = loadable.bytesLoaded(); long bytesLoaded = loadable.bytesLoaded();
boolean isMediaChunk = isMediaChunk(loadable); boolean isMediaChunk = isMediaChunk(loadable);
int lastChunkIndex = mediaChunks.size() - 1; int lastChunkIndex = mediaChunks.size() - 1;

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.trackselection; package com.google.android.exoplayer2.trackselection;
import android.content.Context; import android.content.Context;
import android.support.annotation.IntDef;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
@ -27,6 +28,8 @@ import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -81,22 +84,25 @@ public abstract class MappingTrackSelector extends TrackSelector {
*/ */
public static final class MappedTrackInfo { public static final class MappedTrackInfo {
/** /** Levels of renderer support. Higher numerical values indicate higher levels of support. */
* The renderer does not have any associated tracks. @Retention(RetentionPolicy.SOURCE)
*/ @IntDef({
RENDERER_SUPPORT_NO_TRACKS,
RENDERER_SUPPORT_UNSUPPORTED_TRACKS,
RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS,
RENDERER_SUPPORT_PLAYABLE_TRACKS
})
@interface RendererSupport {}
/** The renderer does not have any associated tracks. */
public static final int RENDERER_SUPPORT_NO_TRACKS = 0; public static final int RENDERER_SUPPORT_NO_TRACKS = 0;
/** /** The renderer has associated tracks, but all are of unsupported types. */
* The renderer has associated tracks, but all are of unsupported types.
*/
public static final int RENDERER_SUPPORT_UNSUPPORTED_TRACKS = 1; public static final int RENDERER_SUPPORT_UNSUPPORTED_TRACKS = 1;
/** /**
* The renderer has associated tracks and at least one is of a supported type, but all of the * The renderer has associated tracks and at least one is of a supported type, but all of the
* tracks whose types are supported exceed the renderer's capabilities. * tracks whose types are supported exceed the renderer's capabilities.
*/ */
public static final int RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS = 2; public static final int RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS = 2;
/** /** The renderer has associated tracks and can play at least one of them. */
* The renderer has associated tracks and can play at least one of them.
*/
public static final int RENDERER_SUPPORT_PLAYABLE_TRACKS = 3; public static final int RENDERER_SUPPORT_PLAYABLE_TRACKS = 3;
/** /**
@ -145,11 +151,11 @@ public abstract class MappingTrackSelector extends TrackSelector {
* Returns the extent to which a renderer can play the tracks in the track groups mapped to it. * Returns the extent to which a renderer can play the tracks in the track groups mapped to it.
* *
* @param rendererIndex The renderer index. * @param rendererIndex The renderer index.
* @return One of {@link #RENDERER_SUPPORT_PLAYABLE_TRACKS}, * @return One of {@link #RENDERER_SUPPORT_PLAYABLE_TRACKS}, {@link
* {@link #RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS}, * #RENDERER_SUPPORT_EXCEEDS_CAPABILITIES_TRACKS}, {@link
* {@link #RENDERER_SUPPORT_UNSUPPORTED_TRACKS} and {@link #RENDERER_SUPPORT_NO_TRACKS}. * #RENDERER_SUPPORT_UNSUPPORTED_TRACKS} and {@link #RENDERER_SUPPORT_NO_TRACKS}.
*/ */
public int getRendererSupport(int rendererIndex) { public @RendererSupport int getRendererSupport(int rendererIndex) {
int bestRendererSupport = RENDERER_SUPPORT_NO_TRACKS; int bestRendererSupport = RENDERER_SUPPORT_NO_TRACKS;
int[][] rendererFormatSupport = formatSupport[rendererIndex]; int[][] rendererFormatSupport = formatSupport[rendererIndex];
for (int i = 0; i < rendererFormatSupport.length; i++) { for (int i = 0; i < rendererFormatSupport.length; i++) {

View File

@ -20,12 +20,15 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
/** /**
@ -104,20 +107,20 @@ public final class Loader implements LoaderErrorThrower {
/** /**
* Called when a load encounters an error. * Called when a load encounters an error.
* <p> *
* Note: There is guaranteed to be a memory barrier between {@link Loadable#load()} exiting and * <p>Note: There is guaranteed to be a memory barrier between {@link Loadable#load()} exiting
* this callback being called. * and this callback being called.
* *
* @param loadable The loadable whose load has encountered an error. * @param loadable The loadable whose load has encountered an error.
* @param elapsedRealtimeMs {@link SystemClock#elapsedRealtime} when the error occurred. * @param elapsedRealtimeMs {@link SystemClock#elapsedRealtime} when the error occurred.
* @param loadDurationMs The duration of the load up to the point at which the error occurred. * @param loadDurationMs The duration of the load up to the point at which the error occurred.
* @param error The load error. * @param error The load error.
* @return The desired retry action. One of {@link Loader#RETRY}, * @return The desired retry action. One of {@link Loader#RETRY}, {@link
* {@link Loader#RETRY_RESET_ERROR_COUNT}, {@link Loader#DONT_RETRY} and * Loader#RETRY_RESET_ERROR_COUNT}, {@link Loader#DONT_RETRY} and {@link
* {@link Loader#DONT_RETRY_FATAL}. * Loader#DONT_RETRY_FATAL}.
*/ */
@RetryAction
int onLoadError(T loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error); int onLoadError(T loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error);
} }
/** /**
@ -132,6 +135,11 @@ public final class Loader implements LoaderErrorThrower {
} }
/** Actions that can be taken in response to a load error. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({RETRY, RETRY_RESET_ERROR_COUNT, DONT_RETRY, DONT_RETRY_FATAL})
public @interface RetryAction {}
public static final int RETRY = 0; public static final int RETRY = 0;
public static final int RETRY_RESET_ERROR_COUNT = 1; public static final int RETRY_RESET_ERROR_COUNT = 1;
public static final int DONT_RETRY = 2; public static final int DONT_RETRY = 2;

View File

@ -375,7 +375,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// We only need to update the codec if the surface has changed. // We only need to update the codec if the surface has changed.
if (this.surface != surface) { if (this.surface != surface) {
this.surface = surface; this.surface = surface;
int state = getState(); @State int state = getState();
if (state == STATE_ENABLED || state == STATE_STARTED) { if (state == STATE_ENABLED || state == STATE_STARTED) {
MediaCodec codec = getCodec(); MediaCodec codec = getCodec();
if (Util.SDK_INT >= 23 && codec != null && surface != null if (Util.SDK_INT >= 23 && codec != null && surface != null

View File

@ -174,22 +174,22 @@ public class DefaultEbmlReaderTest {
private final List<String> events = new ArrayList<>(); private final List<String> events = new ArrayList<>();
@Override @Override
public int getElementType(int id) { public @ElementType int getElementType(int id) {
switch (id) { switch (id) {
case ID_EBML: case ID_EBML:
case ID_SEGMENT: case ID_SEGMENT:
return EbmlReader.TYPE_MASTER; return TYPE_MASTER;
case ID_EBML_READ_VERSION: case ID_EBML_READ_VERSION:
case ID_DOC_TYPE_READ_VERSION: case ID_DOC_TYPE_READ_VERSION:
return EbmlReader.TYPE_UNSIGNED_INT; return TYPE_UNSIGNED_INT;
case ID_DOC_TYPE: case ID_DOC_TYPE:
return EbmlReader.TYPE_STRING; return TYPE_STRING;
case ID_SIMPLE_BLOCK: case ID_SIMPLE_BLOCK:
return EbmlReader.TYPE_BINARY; return TYPE_BINARY;
case ID_DURATION: case ID_DURATION:
return EbmlReader.TYPE_FLOAT; return TYPE_FLOAT;
default: default:
return EbmlReader.TYPE_UNKNOWN; return TYPE_UNKNOWN;
} }
} }

View File

@ -692,8 +692,12 @@ public final class DashMediaSource extends BaseMediaSource {
} }
} }
/* package */ int onManifestLoadError(ParsingLoadable<DashManifest> loadable, /* package */ @Loader.RetryAction
long elapsedRealtimeMs, long loadDurationMs, IOException error) { int onManifestLoadError(
ParsingLoadable<DashManifest> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
boolean isFatal = error instanceof ParserException; boolean isFatal = error instanceof ParserException;
manifestEventDispatcher.loadError( manifestEventDispatcher.loadError(
loadable.dataSpec, loadable.dataSpec,
@ -717,8 +721,12 @@ public final class DashMediaSource extends BaseMediaSource {
onUtcTimestampResolved(loadable.getResult() - elapsedRealtimeMs); onUtcTimestampResolved(loadable.getResult() - elapsedRealtimeMs);
} }
/* package */ int onUtcTimestampLoadError(ParsingLoadable<Long> loadable, long elapsedRealtimeMs, /* package */ @Loader.RetryAction
long loadDurationMs, IOException error) { int onUtcTimestampLoadError(
ParsingLoadable<Long> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
manifestEventDispatcher.loadError( manifestEventDispatcher.loadError(
loadable.dataSpec, loadable.dataSpec,
loadable.type, loadable.type,
@ -1114,8 +1122,11 @@ public final class DashMediaSource extends BaseMediaSource {
} }
@Override @Override
public int onLoadError(ParsingLoadable<DashManifest> loadable, public @Loader.RetryAction int onLoadError(
long elapsedRealtimeMs, long loadDurationMs, IOException error) { ParsingLoadable<DashManifest> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
return onManifestLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error); return onManifestLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error);
} }
@ -1136,8 +1147,11 @@ public final class DashMediaSource extends BaseMediaSource {
} }
@Override @Override
public int onLoadError(ParsingLoadable<Long> loadable, long elapsedRealtimeMs, public @Loader.RetryAction int onLoadError(
long loadDurationMs, IOException error) { ParsingLoadable<Long> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
return onUtcTimestampLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error); return onUtcTimestampLoadError(loadable, elapsedRealtimeMs, loadDurationMs, error);
} }

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.hls; package com.google.android.exoplayer2.source.hls;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.IntDef;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
@ -43,6 +44,8 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -73,6 +76,10 @@ import java.util.Arrays;
private static final String TAG = "HlsSampleStreamWrapper"; private static final String TAG = "HlsSampleStreamWrapper";
@Retention(RetentionPolicy.SOURCE)
@IntDef({PRIMARY_TYPE_NONE, PRIMARY_TYPE_TEXT, PRIMARY_TYPE_AUDIO, PRIMARY_TYPE_VIDEO})
private @interface PrimaryTrackType {}
private static final int PRIMARY_TYPE_NONE = 0; private static final int PRIMARY_TYPE_NONE = 0;
private static final int PRIMARY_TYPE_TEXT = 1; private static final int PRIMARY_TYPE_TEXT = 1;
private static final int PRIMARY_TYPE_AUDIO = 2; private static final int PRIMARY_TYPE_AUDIO = 2;
@ -583,8 +590,8 @@ import java.util.Arrays;
} }
@Override @Override
public int onLoadError(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, public @Loader.RetryAction int onLoadError(
IOException error) { Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
long bytesLoaded = loadable.bytesLoaded(); long bytesLoaded = loadable.bytesLoaded();
boolean isMediaChunk = isMediaChunk(loadable); boolean isMediaChunk = isMediaChunk(loadable);
boolean cancelable = !isMediaChunk || bytesLoaded == 0; boolean cancelable = !isMediaChunk || bytesLoaded == 0;
@ -826,12 +833,12 @@ import java.util.Arrays;
private void buildTracks() { private void buildTracks() {
// Iterate through the extractor tracks to discover the "primary" track type, and the index // Iterate through the extractor tracks to discover the "primary" track type, and the index
// of the single track of this type. // of the single track of this type.
int primaryExtractorTrackType = PRIMARY_TYPE_NONE; @PrimaryTrackType int primaryExtractorTrackType = PRIMARY_TYPE_NONE;
int primaryExtractorTrackIndex = C.INDEX_UNSET; int primaryExtractorTrackIndex = C.INDEX_UNSET;
int extractorTrackCount = sampleQueues.length; int extractorTrackCount = sampleQueues.length;
for (int i = 0; i < extractorTrackCount; i++) { for (int i = 0; i < extractorTrackCount; i++) {
String sampleMimeType = sampleQueues[i].getUpstreamFormat().sampleMimeType; String sampleMimeType = sampleQueues[i].getUpstreamFormat().sampleMimeType;
int trackType; @PrimaryTrackType int trackType;
if (MimeTypes.isVideo(sampleMimeType)) { if (MimeTypes.isVideo(sampleMimeType)) {
trackType = PRIMARY_TYPE_VIDEO; trackType = PRIMARY_TYPE_VIDEO;
} else if (MimeTypes.isAudio(sampleMimeType)) { } else if (MimeTypes.isAudio(sampleMimeType)) {

View File

@ -320,8 +320,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
} }
@Override @Override
public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, public @Loader.RetryAction int onLoadError(
long loadDurationMs, IOException error) { ParsingLoadable<HlsPlaylist> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
boolean isFatal = error instanceof ParserException; boolean isFatal = error instanceof ParserException;
eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
loadDurationMs, loadable.bytesLoaded(), error, isFatal); loadDurationMs, loadable.bytesLoaded(), error, isFatal);
@ -554,8 +557,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
} }
@Override @Override
public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, public @Loader.RetryAction int onLoadError(
long loadDurationMs, IOException error) { ParsingLoadable<HlsPlaylist> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
boolean isFatal = error instanceof ParserException; boolean isFatal = error instanceof ParserException;
eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs,
loadDurationMs, loadable.bytesLoaded(), error, isFatal); loadDurationMs, loadable.bytesLoaded(), error, isFatal);

View File

@ -518,8 +518,11 @@ public final class SsMediaSource extends BaseMediaSource
} }
@Override @Override
public int onLoadError(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, public @Loader.RetryAction int onLoadError(
long loadDurationMs, IOException error) { ParsingLoadable<SsManifest> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
IOException error) {
boolean isFatal = error instanceof ParserException; boolean isFatal = error instanceof ParserException;
manifestEventDispatcher.loadError( manifestEventDispatcher.loadError(
loadable.dataSpec, loadable.dataSpec,