Add dependency on nullness annotations and add missing annotations for DASH.

This includes only the (hopefully) non-debatable changes for the DASH module
and all needed changes for call into the core library.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=195097791
This commit is contained in:
tonihei 2018-05-02 08:47:52 -07:00 committed by Oliver Woodman
parent c466fabb1c
commit 7799e8fd5e
19 changed files with 363 additions and 184 deletions

View File

@ -2,6 +2,7 @@
### dev-v2 (not yet released) ###
* Added dependency on checkerframework annotations for static code analysis.
* Optimize seeking in FMP4 by enabling seeking to the nearest sync sample within
a fragment. This benefits standalone FMP4 playbacks, DASH and SmoothStreaming.
* Moved initial bitrate estimate from `AdaptiveTrackSelection` to

View File

@ -31,6 +31,7 @@ project.ext {
junitVersion = '4.12'
truthVersion = '0.39'
robolectricVersion = '3.7.1'
checkerframeworkVersion = '2.5.0'
modulePrefix = ':'
if (gradle.ext.has('exoplayerModulePrefix')) {
modulePrefix += gradle.ext.exoplayerModulePrefix

View File

@ -46,6 +46,7 @@ android {
dependencies {
implementation 'com.android.support:support-annotations:' + supportLibraryVersion
implementation 'org.checkerframework:checker-qual:' + checkerframeworkVersion
androidTestImplementation 'com.google.dexmaker:dexmaker:' + dexmakerVersion
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:' + dexmakerVersion
androidTestImplementation 'com.google.truth:truth:' + truthVersion

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.util.MimeTypes;
@ -43,29 +44,21 @@ public final class Format implements Parcelable {
*/
public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
/**
* An identifier for the format, or null if unknown or not applicable.
*/
public final String id;
/** An identifier for the format, or null if unknown or not applicable. */
public final @Nullable String id;
/**
* The average bandwidth in bits per second, or {@link #NO_VALUE} if unknown or not applicable.
*/
public final int bitrate;
/**
* Codecs of the format as described in RFC 6381, or null if unknown or not applicable.
*/
public final String codecs;
/**
* Metadata, or null if unknown or not applicable.
*/
public final Metadata metadata;
/** Codecs of the format as described in RFC 6381, or null if unknown or not applicable. */
public final @Nullable String codecs;
/** Metadata, or null if unknown or not applicable. */
public final @Nullable Metadata metadata;
// Container specific.
/**
* The mime type of the container, or null if unknown or not applicable.
*/
public final String containerMimeType;
/** The mime type of the container, or null if unknown or not applicable. */
public final @Nullable String containerMimeType;
// Elementary stream specific.
@ -73,7 +66,7 @@ public final class Format implements Parcelable {
* The mime type of the elementary stream (i.e. the individual samples), or null if unknown or not
* applicable.
*/
public final String sampleMimeType;
public final @Nullable String sampleMimeType;
/**
* The maximum size of a buffer of data (typically one sample), or {@link #NO_VALUE} if unknown or
* not applicable.
@ -84,10 +77,8 @@ public final class Format implements Parcelable {
* if initialization data is not required.
*/
public final List<byte[]> initializationData;
/**
* DRM initialization data if the stream is protected, or null otherwise.
*/
public final DrmInitData drmInitData;
/** DRM initialization data if the stream is protected, or null otherwise. */
public final @Nullable DrmInitData drmInitData;
// Video specific.
@ -117,14 +108,10 @@ public final class Format implements Parcelable {
*/
@C.StereoMode
public final int stereoMode;
/**
* The projection data for 360/VR video, or null if not applicable.
*/
public final byte[] projectionData;
/**
* The color metadata associated with the video, helps with accurate color reproduction.
*/
public final ColorInfo colorInfo;
/** The projection data for 360/VR video, or null if not applicable. */
public final @Nullable byte[] projectionData;
/** The color metadata associated with the video, helps with accurate color reproduction. */
public final @Nullable ColorInfo colorInfo;
// Audio specific.
@ -171,10 +158,8 @@ public final class Format implements Parcelable {
@C.SelectionFlags
public final int selectionFlags;
/**
* The language, or null if unknown or not applicable.
*/
public final String language;
/** The language, or null if unknown or not applicable. */
public final @Nullable String language;
/**
* The Accessibility channel, or {@link #NO_VALUE} if not known or applicable.
@ -186,36 +171,72 @@ public final class Format implements Parcelable {
// Video.
public static Format createVideoContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, int width, int height,
float frameRate, List<byte[]> initializationData, @C.SelectionFlags int selectionFlags) {
public static Format createVideoContainerFormat(
@Nullable String id,
@Nullable String containerMimeType,
String sampleMimeType,
String codecs,
int bitrate,
int width,
int height,
float frameRate,
List<byte[]> initializationData,
@C.SelectionFlags int selectionFlags) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, width,
height, frameRate, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, selectionFlags, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
initializationData, null, null);
}
public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int width, int height, float frameRate,
List<byte[]> initializationData, DrmInitData drmInitData) {
public static Format createVideoSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int width,
int height,
float frameRate,
List<byte[]> initializationData,
@Nullable DrmInitData drmInitData) {
return createVideoSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, initializationData, NO_VALUE, NO_VALUE, drmInitData);
}
public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int width, int height, float frameRate,
List<byte[]> initializationData, int rotationDegrees, float pixelWidthHeightRatio,
DrmInitData drmInitData) {
public static Format createVideoSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int width,
int height,
float frameRate,
List<byte[]> initializationData,
int rotationDegrees,
float pixelWidthHeightRatio,
@Nullable DrmInitData drmInitData) {
return createVideoSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, initializationData, rotationDegrees, pixelWidthHeightRatio, null,
NO_VALUE, null, drmInitData);
}
public static Format createVideoSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int width, int height, float frameRate,
List<byte[]> initializationData, int rotationDegrees, float pixelWidthHeightRatio,
byte[] projectionData, @C.StereoMode int stereoMode, ColorInfo colorInfo,
DrmInitData drmInitData) {
public static Format createVideoSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int width,
int height,
float frameRate,
List<byte[]> initializationData,
int rotationDegrees,
float pixelWidthHeightRatio,
byte[] projectionData,
@C.StereoMode int stereoMode,
@Nullable ColorInfo colorInfo,
@Nullable DrmInitData drmInitData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, width, height,
frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
colorInfo, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, 0, null, NO_VALUE,
@ -224,37 +245,73 @@ public final class Format implements Parcelable {
// Audio.
public static Format createAudioContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, int channelCount, int sampleRate,
List<byte[]> initializationData, @C.SelectionFlags int selectionFlags, String language) {
public static Format createAudioContainerFormat(
@Nullable String id,
@Nullable String containerMimeType,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int channelCount,
int sampleRate,
List<byte[]> initializationData,
@C.SelectionFlags int selectionFlags,
@Nullable 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, null, channelCount, sampleRate,
NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
initializationData, null, null);
}
public static Format createAudioSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int channelCount, int sampleRate,
List<byte[]> initializationData, DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags, String language) {
public static Format createAudioSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int channelCount,
int sampleRate,
List<byte[]> initializationData,
@Nullable DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags,
@Nullable 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,
@C.PcmEncoding int pcmEncoding, List<byte[]> initializationData, DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags, String language) {
public static Format createAudioSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int channelCount,
int sampleRate,
@C.PcmEncoding int pcmEncoding,
List<byte[]> initializationData,
@Nullable DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags,
@Nullable String language) {
return createAudioSampleFormat(id, sampleMimeType, codecs, bitrate, maxInputSize, channelCount,
sampleRate, pcmEncoding, NO_VALUE, NO_VALUE, initializationData, drmInitData,
selectionFlags, language, null);
}
public static Format createAudioSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, int maxInputSize, int channelCount, int sampleRate,
@C.PcmEncoding int pcmEncoding, int encoderDelay, int encoderPadding,
List<byte[]> initializationData, DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags, String language, Metadata metadata) {
public static Format createAudioSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int channelCount,
int sampleRate,
@C.PcmEncoding int pcmEncoding,
int encoderDelay,
int encoderPadding,
List<byte[]> initializationData,
@Nullable DrmInitData drmInitData,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
@Nullable Metadata metadata) {
return new Format(id, null, sampleMimeType, codecs, bitrate, maxInputSize, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, channelCount, sampleRate, pcmEncoding,
encoderDelay, encoderPadding, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE,
@ -263,50 +320,87 @@ public final class Format implements Parcelable {
// Text.
public static Format createTextContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags,
String language) {
public static Format createTextContainerFormat(
@Nullable String id,
@Nullable String containerMimeType,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable String language) {
return createTextContainerFormat(id, containerMimeType, sampleMimeType, codecs, bitrate,
selectionFlags, language, NO_VALUE);
}
public static Format createTextContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags,
String language, int accessibilityChannel) {
public static Format createTextContainerFormat(
@Nullable String id,
@Nullable String containerMimeType,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
int accessibilityChannel) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, selectionFlags, language, accessibilityChannel,
OFFSET_SAMPLE_RELATIVE, null, null, null);
}
public static Format createTextSampleFormat(String id, String sampleMimeType,
@C.SelectionFlags int selectionFlags, String language) {
public static Format createTextSampleFormat(
@Nullable String id,
String sampleMimeType,
@C.SelectionFlags int selectionFlags,
@Nullable String language) {
return createTextSampleFormat(id, sampleMimeType, selectionFlags, language, null);
}
public static Format createTextSampleFormat(String id, String sampleMimeType,
@C.SelectionFlags int selectionFlags, String language, DrmInitData drmInitData) {
public static Format createTextSampleFormat(
@Nullable String id,
String sampleMimeType,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
@Nullable DrmInitData drmInitData) {
return createTextSampleFormat(id, sampleMimeType, null, NO_VALUE, selectionFlags, language,
NO_VALUE, drmInitData, OFFSET_SAMPLE_RELATIVE, Collections.<byte[]>emptyList());
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language, int accessibilityChannel,
DrmInitData drmInitData) {
public static Format createTextSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
int accessibilityChannel,
@Nullable DrmInitData drmInitData) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language,
accessibilityChannel, drmInitData, OFFSET_SAMPLE_RELATIVE, Collections.<byte[]>emptyList());
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language, DrmInitData drmInitData,
public static Format createTextSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
@Nullable DrmInitData drmInitData,
long subsampleOffsetUs) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language,
NO_VALUE, drmInitData, subsampleOffsetUs, Collections.<byte[]>emptyList());
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs,
public static Format createTextSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
int accessibilityChannel,
@Nullable DrmInitData drmInitData,
long subsampleOffsetUs,
List<byte[]> initializationData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
@ -317,14 +411,14 @@ public final class Format implements Parcelable {
// Image.
public static Format createImageSampleFormat(
String id,
String sampleMimeType,
String codecs,
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
List<byte[]> initializationData,
String language,
DrmInitData drmInitData) {
@Nullable String language,
@Nullable DrmInitData drmInitData) {
return new Format(
id,
null,
@ -356,36 +450,65 @@ public final class Format implements Parcelable {
// Generic.
public static Format createContainerFormat(String id, String containerMimeType,
String sampleMimeType, String codecs, int bitrate, @C.SelectionFlags int selectionFlags,
String language) {
public static Format createContainerFormat(
@Nullable String id,
@Nullable String containerMimeType,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable 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, null, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, selectionFlags, language, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, null,
null);
}
public static Format createSampleFormat(String id, String sampleMimeType,
long subsampleOffsetUs) {
public static Format createSampleFormat(
@Nullable String id, @Nullable String sampleMimeType, long subsampleOffsetUs) {
return new Format(id, null, sampleMimeType, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, 0, null, NO_VALUE, subsampleOffsetUs, null, null, null);
}
public static Format createSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, DrmInitData drmInitData) {
public static Format createSampleFormat(
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@Nullable DrmInitData drmInitData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, 0, null, NO_VALUE, OFFSET_SAMPLE_RELATIVE, null, drmInitData, null);
}
/* 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, @C.StereoMode int stereoMode,
ColorInfo colorInfo, int channelCount, int sampleRate, @C.PcmEncoding int pcmEncoding,
int encoderDelay, int encoderPadding, @C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, long subsampleOffsetUs, List<byte[]> initializationData,
DrmInitData drmInitData, Metadata metadata) {
/* package */ Format(
@Nullable String id,
@Nullable String containerMimeType,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int maxInputSize,
int width,
int height,
float frameRate,
int rotationDegrees,
float pixelWidthHeightRatio,
@Nullable byte[] projectionData,
@C.StereoMode int stereoMode,
@Nullable ColorInfo colorInfo,
int channelCount,
int sampleRate,
@C.PcmEncoding int pcmEncoding,
int encoderDelay,
int encoderPadding,
@C.SelectionFlags int selectionFlags,
@Nullable String language,
int accessibilityChannel,
long subsampleOffsetUs,
@Nullable List<byte[]> initializationData,
@Nullable DrmInitData drmInitData,
@Nullable Metadata metadata) {
this.id = id;
this.containerMimeType = containerMimeType;
this.sampleMimeType = sampleMimeType;
@ -468,14 +591,14 @@ public final class Format implements Parcelable {
}
public Format copyWithContainerInfo(
String id,
String sampleMimeType,
String codecs,
@Nullable String id,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
int width,
int height,
@C.SelectionFlags int selectionFlags,
String language) {
@Nullable String language) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
@ -512,7 +635,7 @@ public final class Format implements Parcelable {
drmInitData, metadata);
}
public Format copyWithDrmInitData(DrmInitData drmInitData) {
public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
@ -520,7 +643,7 @@ public final class Format implements Parcelable {
drmInitData, metadata);
}
public Format copyWithMetadata(Metadata metadata) {
public Format copyWithMetadata(@Nullable Metadata metadata) {
return new Format(id, containerMimeType, sampleMimeType, codecs, bitrate, maxInputSize, width,
height, frameRate, rotationDegrees, pixelWidthHeightRatio, projectionData, stereoMode,
colorInfo, channelCount, sampleRate, pcmEncoding, encoderDelay, encoderPadding,
@ -574,7 +697,7 @@ public final class Format implements Parcelable {
}
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}

View File

@ -121,11 +121,11 @@ public final class FragmentedMp4Extractor implements Extractor {
// Workarounds.
@Flags private final int flags;
private final Track sideloadedTrack;
private final @Nullable Track sideloadedTrack;
// Sideloaded data.
private final List<Format> closedCaptionFormats;
private final DrmInitData sideloadedDrmInitData;
private final @Nullable DrmInitData sideloadedDrmInitData;
// Track-linked data bundle, accessible as a whole through trackID.
private final SparseArray<TrackBundle> trackBundles;
@ -136,7 +136,7 @@ public final class FragmentedMp4Extractor implements Extractor {
private final ParsableByteArray nalBuffer;
// Adjusts sample timestamps.
private final TimestampAdjuster timestampAdjuster;
private final @Nullable TimestampAdjuster timestampAdjuster;
// Parser state.
private final ParsableByteArray atomHeader;
@ -185,20 +185,23 @@ public final class FragmentedMp4Extractor implements Extractor {
* @param flags Flags that control the extractor's behavior.
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
*/
public FragmentedMp4Extractor(@Flags int flags, TimestampAdjuster timestampAdjuster) {
public FragmentedMp4Extractor(@Flags int flags, @Nullable TimestampAdjuster timestampAdjuster) {
this(flags, timestampAdjuster, null, null);
}
/**
* @param flags Flags that control the extractor's behavior.
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor
* will not receive a moov box in the input data. Null if a moov box is expected.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor will not
* receive a moov box in the input data. Null if a moov box is expected.
* @param sideloadedDrmInitData The {@link DrmInitData} to use for encrypted tracks. If null, the
* pssh boxes (if present) will be used.
*/
public FragmentedMp4Extractor(@Flags int flags, TimestampAdjuster timestampAdjuster,
Track sideloadedTrack, DrmInitData sideloadedDrmInitData) {
public FragmentedMp4Extractor(
@Flags int flags,
@Nullable TimestampAdjuster timestampAdjuster,
@Nullable Track sideloadedTrack,
@Nullable DrmInitData sideloadedDrmInitData) {
this(flags, timestampAdjuster, sideloadedTrack, sideloadedDrmInitData,
Collections.<Format>emptyList());
}
@ -206,15 +209,19 @@ public final class FragmentedMp4Extractor implements Extractor {
/**
* @param flags Flags that control the extractor's behavior.
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor
* will not receive a moov box in the input data. Null if a moov box is expected.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor will not
* receive a moov box in the input data. Null if a moov box is expected.
* @param sideloadedDrmInitData The {@link DrmInitData} to use for encrypted tracks. If null, the
* pssh boxes (if present) will be used.
* @param closedCaptionFormats For tracks that contain SEI messages, the formats of the closed
* caption channels to expose.
*/
public FragmentedMp4Extractor(@Flags int flags, TimestampAdjuster timestampAdjuster,
Track sideloadedTrack, DrmInitData sideloadedDrmInitData, List<Format> closedCaptionFormats) {
public FragmentedMp4Extractor(
@Flags int flags,
@Nullable TimestampAdjuster timestampAdjuster,
@Nullable Track sideloadedTrack,
@Nullable DrmInitData sideloadedDrmInitData,
List<Format> closedCaptionFormats) {
this(flags, timestampAdjuster, sideloadedTrack, sideloadedDrmInitData,
closedCaptionFormats, null);
}
@ -222,8 +229,8 @@ public final class FragmentedMp4Extractor implements Extractor {
/**
* @param flags Flags that control the extractor's behavior.
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor
* will not receive a moov box in the input data. Null if a moov box is expected.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor will not
* receive a moov box in the input data. Null if a moov box is expected.
* @param sideloadedDrmInitData The {@link DrmInitData} to use for encrypted tracks. If null, the
* pssh boxes (if present) will be used.
* @param closedCaptionFormats For tracks that contain SEI messages, the formats of the closed
@ -232,8 +239,12 @@ public final class FragmentedMp4Extractor implements Extractor {
* targeting the player, even if {@link #FLAG_ENABLE_EMSG_TRACK} is not set. Null if special
* handling of emsg messages for players is not required.
*/
public FragmentedMp4Extractor(@Flags int flags, TimestampAdjuster timestampAdjuster,
Track sideloadedTrack, DrmInitData sideloadedDrmInitData, List<Format> closedCaptionFormats,
public FragmentedMp4Extractor(
@Flags int flags,
@Nullable TimestampAdjuster timestampAdjuster,
@Nullable Track sideloadedTrack,
@Nullable DrmInitData sideloadedDrmInitData,
List<Format> closedCaptionFormats,
@Nullable TrackOutput additionalEmsgTrackOutput) {
this.flags = flags | (sideloadedTrack != null ? FLAG_SIDELOADED : 0);
this.timestampAdjuster = timestampAdjuster;

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.extractor.mp4;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.exoplayer2.util.ParsableByteArray;
import java.nio.ByteBuffer;
@ -36,7 +37,7 @@ public final class PsshAtomUtil {
* @param data The scheme specific data.
* @return The PSSH atom.
*/
public static byte[] buildPsshAtom(UUID systemId, byte[] data) {
public static byte[] buildPsshAtom(UUID systemId, @Nullable byte[] data) {
return buildPsshAtom(systemId, null, data);
}
@ -48,7 +49,8 @@ public final class PsshAtomUtil {
* @param data The scheme specific data.
* @return The PSSH atom.
*/
public static byte[] buildPsshAtom(UUID systemId, UUID[] keyIds, byte[] data) {
public static byte[] buildPsshAtom(
UUID systemId, @Nullable UUID[] keyIds, @Nullable byte[] data) {
boolean buildV1Atom = keyIds != null;
int dataLength = data != null ? data.length : 0;
int psshBoxLength = Atom.FULL_HEADER_SIZE + 16 /* SystemId */ + 4 /* DataSize */ + dataLength;
@ -77,14 +79,14 @@ public final class PsshAtomUtil {
/**
* Parses the UUID from a PSSH atom. Version 0 and 1 PSSH atoms are supported.
* <p>
* The UUID is only parsed if the data is a valid PSSH atom.
*
* <p>The UUID is only parsed if the data is a valid PSSH atom.
*
* @param atom The atom to parse.
* @return The parsed UUID. Null if the input is not a valid PSSH atom, or if the PSSH atom has
* an unsupported version.
* @return The parsed UUID. Null if the input is not a valid PSSH atom, or if the PSSH atom has an
* unsupported version.
*/
public static UUID parseUuid(byte[] atom) {
public static @Nullable UUID parseUuid(byte[] atom) {
PsshAtom parsedAtom = parsePsshAtom(atom);
if (parsedAtom == null) {
return null;
@ -111,8 +113,8 @@ public final class PsshAtomUtil {
/**
* Parses the scheme specific data from a PSSH atom. Version 0 and 1 PSSH atoms are supported.
* <p>
* The scheme specific data is only parsed if the data is a valid PSSH atom matching the given
*
* <p>The scheme specific data is only parsed if the data is a valid PSSH atom matching the given
* UUID, or if the data is a valid PSSH atom of any type in the case that the passed UUID is null.
*
* @param atom The atom to parse.
@ -120,7 +122,7 @@ public final class PsshAtomUtil {
* @return The parsed scheme specific data. Null if the input is not a valid PSSH atom, or if the
* PSSH atom has an unsupported version, or if the PSSH atom does not match the passed UUID.
*/
public static byte[] parseSchemeSpecificData(byte[] atom, UUID uuid) {
public static @Nullable byte[] parseSchemeSpecificData(byte[] atom, UUID uuid) {
PsshAtom parsedAtom = parsePsshAtom(atom);
if (parsedAtom == null) {
return null;
@ -140,7 +142,7 @@ public final class PsshAtomUtil {
* has an unsupported version.
*/
// TODO: Support parsing of the key ids for version 1 PSSH atoms.
private static PsshAtom parsePsshAtom(byte[] atom) {
private static @Nullable PsshAtom parsePsshAtom(byte[] atom) {
ParsableByteArray atomData = new ParsableByteArray(atom);
if (atomData.limit() < Atom.FULL_HEADER_SIZE + 16 /* UUID */ + 4 /* DataSize */) {
// Data too short.

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.chunk;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.upstream.DataSource;
@ -51,7 +52,7 @@ public abstract class Chunk implements Loadable {
* Optional data associated with the selection of the track to which this chunk belongs. Null if
* the chunk does not belong to a track.
*/
public final Object trackSelectionData;
public final @Nullable Object trackSelectionData;
/**
* The start time of the media contained by the chunk, or {@link C#TIME_UNSET} if the data
* being loaded does not contain media samples.
@ -75,8 +76,15 @@ public abstract class Chunk implements Loadable {
* @param startTimeUs See {@link #startTimeUs}.
* @param endTimeUs See {@link #endTimeUs}.
*/
public Chunk(DataSource dataSource, DataSpec dataSpec, int type, Format trackFormat,
int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs) {
public Chunk(
DataSource dataSource,
DataSpec dataSpec,
int type,
Format trackFormat,
int trackSelectionReason,
@Nullable Object trackSelectionData,
long startTimeUs,
long endTimeUs) {
this.dataSource = Assertions.checkNotNull(dataSource);
this.dataSpec = Assertions.checkNotNull(dataSpec);
this.type = type;

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.chunk;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
@ -44,8 +45,12 @@ public final class InitializationChunk extends Chunk {
* @param trackSelectionData See {@link #trackSelectionData}.
* @param extractorWrapper A wrapped extractor to use for parsing the initialization data.
*/
public InitializationChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat,
int trackSelectionReason, Object trackSelectionData,
public InitializationChunk(
DataSource dataSource,
DataSpec dataSpec,
Format trackFormat,
int trackSelectionReason,
@Nullable Object trackSelectionData,
ChunkExtractorWrapper extractorWrapper) {
super(dataSource, dataSpec, C.DATA_TYPE_MEDIA_INITIALIZATION, trackFormat, trackSelectionReason,
trackSelectionData, C.TIME_UNSET, C.TIME_UNSET);

View File

@ -16,8 +16,10 @@
package com.google.android.exoplayer2.util;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
/**
* Provides methods for asserting the truth of expressions and properties.
@ -102,7 +104,8 @@ public final class Assertions {
* @return The non-null reference that was validated.
* @throws NullPointerException If {@code reference} is null.
*/
public static <T> T checkNotNull(T reference) {
@EnsuresNonNull({"#1"})
public static <T> T checkNotNull(@Nullable T reference) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) {
throw new NullPointerException();
}
@ -119,7 +122,8 @@ public final class Assertions {
* @return The non-null reference that was validated.
* @throws NullPointerException If {@code reference} is null.
*/
public static <T> T checkNotNull(T reference, Object errorMessage) {
@EnsuresNonNull({"#1"})
public static <T> T checkNotNull(@Nullable T reference, Object errorMessage) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
@ -133,7 +137,8 @@ public final class Assertions {
* @return The non-null, non-empty string that was validated.
* @throws IllegalArgumentException If {@code string} is null or 0-length.
*/
public static String checkNotEmpty(String string) {
@EnsuresNonNull({"#1"})
public static String checkNotEmpty(@Nullable String string) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) {
throw new IllegalArgumentException();
}
@ -149,7 +154,8 @@ public final class Assertions {
* @return The non-null, non-empty string that was validated.
* @throws IllegalArgumentException If {@code string} is null or 0-length.
*/
public static String checkNotEmpty(String string, Object errorMessage) {
@EnsuresNonNull({"#1"})
public static String checkNotEmpty(@Nullable String string, Object errorMessage) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}

View File

@ -134,14 +134,13 @@ public final class MimeTypes {
return BASE_TYPE_APPLICATION.equals(getTopLevelType(mimeType));
}
/**
* Derives a video sample mimeType from a codecs attribute.
*
* @param codecs The codecs attribute.
* @return The derived video mimeType, or null if it could not be derived.
*/
public static String getVideoMediaMimeType(String codecs) {
public static @Nullable String getVideoMediaMimeType(@Nullable String codecs) {
if (codecs == null) {
return null;
}
@ -161,7 +160,7 @@ public final class MimeTypes {
* @param codecs The codecs attribute.
* @return The derived audio mimeType, or null if it could not be derived.
*/
public static String getAudioMediaMimeType(String codecs) {
public static @Nullable String getAudioMediaMimeType(@Nullable String codecs) {
if (codecs == null) {
return null;
}
@ -181,7 +180,7 @@ public final class MimeTypes {
* @param codec The codec identifier to derive.
* @return The mimeType, or null if it could not be derived.
*/
public static String getMediaMimeType(String codec) {
public static @Nullable String getMediaMimeType(@Nullable String codec) {
if (codec == null) {
return null;
}
@ -345,7 +344,7 @@ public final class MimeTypes {
* @param mimeType The mimeType whose top-level type is required.
* @return The top-level type, or null if the mimeType is null.
*/
private static String getTopLevelType(String mimeType) {
private static @Nullable String getTopLevelType(@Nullable String mimeType) {
if (mimeType == null) {
return null;
}

View File

@ -29,6 +29,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Parcel;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
@ -190,7 +191,7 @@ public final class Util {
* @param o2 The second object.
* @return {@code o1 == null ? o2 == null : o1.equals(o2)}.
*/
public static boolean areEqual(Object o1, Object o2) {
public static boolean areEqual(@Nullable Object o1, @Nullable Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
@ -224,6 +225,20 @@ public final class Util {
list.subList(fromIndex, toIndex).clear();
}
/**
* Copies and optionally truncates an array. Prevents null array elements created by {@link
* Arrays#copyOf(Object[], int)} by ensuring the new length does not exceed the current length.
*
* @param input The input array.
* @param length The output array length. Must be less or equal to the length of the input array.
* @return The copied array.
*/
@SuppressWarnings("nullness:assignment.type.incompatible")
public static <T> T[] nullSafeArrayCopy(T[] input, int length) {
Assertions.checkArgument(length <= input.length);
return Arrays.copyOf(input, length);
}
/**
* Instantiates a new single threaded executor whose thread has the specified name.
*

View File

@ -34,6 +34,8 @@ android {
dependencies {
implementation project(modulePrefix + 'library-core')
implementation 'org.checkerframework:checker-qual:' + checkerframeworkVersion
implementation 'org.checkerframework:checker-compat-qual:' + checkerframeworkVersion
implementation 'com.android.support:support-annotations:' + supportLibraryVersion
testImplementation project(modulePrefix + 'testutils-robolectric')
}

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.dash;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmInitData;
@ -65,7 +66,7 @@ public final class DashUtil {
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
public static @Nullable DrmInitData loadDrmInitData(DataSource dataSource, Period period)
throws IOException, InterruptedException {
int primaryTrackType = C.TRACK_TYPE_VIDEO;
Representation representation = getFirstRepresentation(period, primaryTrackType);
@ -87,15 +88,16 @@ public final class DashUtil {
* Loads initialization data for the {@code representation} and returns the sample {@link Format}.
*
* @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param trackType The type of the representation. Typically one of the {@link
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to.
* @return the sample {@link Format} of the given representation.
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
public static Format loadSampleFormat(DataSource dataSource, int trackType,
Representation representation) throws IOException, InterruptedException {
public static @Nullable Format loadSampleFormat(
DataSource dataSource, int trackType, Representation representation)
throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
representation, false);
return extractorWrapper == null ? null : extractorWrapper.getSampleFormats()[0];
@ -106,28 +108,29 @@ public final class DashUtil {
* ChunkIndex}.
*
* @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param trackType The type of the representation. Typically one of the {@link
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to.
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
* index data exists.
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
public static ChunkIndex loadChunkIndex(DataSource dataSource, int trackType,
Representation representation) throws IOException, InterruptedException {
public static @Nullable ChunkIndex loadChunkIndex(
DataSource dataSource, int trackType, Representation representation)
throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
representation, true);
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
}
/**
* Loads initialization data for the {@code representation} and optionally index data then
* returns a {@link ChunkExtractorWrapper} which contains the output.
* Loads initialization data for the {@code representation} and optionally index data then returns
* a {@link ChunkExtractorWrapper} which contains the output.
*
* @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param trackType The type of the representation. Typically one of the {@link
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to.
* @param loadIndex Whether to load index data too.
* @return A {@link ChunkExtractorWrapper} for the {@code representation}, or null if no
@ -135,8 +138,9 @@ public final class DashUtil {
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
private static ChunkExtractorWrapper loadInitializationData(DataSource dataSource, int trackType,
Representation representation, boolean loadIndex) throws IOException, InterruptedException {
private static @Nullable ChunkExtractorWrapper loadInitializationData(
DataSource dataSource, int trackType, Representation representation, boolean loadIndex)
throws IOException, InterruptedException {
RangedUri initializationUri = representation.getInitializationUri();
if (initializationUri == null) {
return null;
@ -181,7 +185,7 @@ public final class DashUtil {
return new ChunkExtractorWrapper(extractor, trackType, format);
}
private static Representation getFirstRepresentation(Period period, int type) {
private static @Nullable Representation getFirstRepresentation(Period period, int type) {
int index = period.getAdaptationSetIndex(type);
if (index == C.INDEX_UNSET) {
return null;

View File

@ -45,8 +45,10 @@ import java.io.IOException;
EventSampleStream(EventStream eventStream, Format upstreamFormat, boolean eventStreamUpdatable) {
this.upstreamFormat = upstreamFormat;
this.eventStream = eventStream;
eventMessageEncoder = new EventMessageEncoder();
pendingSeekPositionUs = C.TIME_UNSET;
eventTimesUs = eventStream.presentationTimesUs;
updateEventStream(eventStream, eventStreamUpdatable);
}

View File

@ -100,6 +100,7 @@ public final class PlayerEmsgHandler implements Handler.Callback {
* messages that generate DASH media source events.
* @param allocator An {@link Allocator} from which allocations can be obtained.
*/
@SuppressWarnings("nullness")
public PlayerEmsgHandler(
DashManifest manifest, PlayerEmsgCallback playerEmsgCallback, Allocator allocator) {
this.manifest = manifest;
@ -237,11 +238,10 @@ public final class PlayerEmsgHandler implements Handler.Callback {
// Internal methods.
private void handleManifestExpiredMessage(long eventTimeUs, long manifestPublishTimeMsInEmsg) {
if (!manifestPublishTimeToExpiryTimeUs.containsKey(manifestPublishTimeMsInEmsg)) {
Long previousExpiryTimeUs = manifestPublishTimeToExpiryTimeUs.get(manifestPublishTimeMsInEmsg);
if (previousExpiryTimeUs == null) {
manifestPublishTimeToExpiryTimeUs.put(manifestPublishTimeMsInEmsg, eventTimeUs);
} else {
long previousExpiryTimeUs =
manifestPublishTimeToExpiryTimeUs.get(manifestPublishTimeMsInEmsg);
if (previousExpiryTimeUs > eventTimeUs) {
manifestPublishTimeToExpiryTimeUs.put(manifestPublishTimeMsInEmsg, eventTimeUs);
}
@ -253,10 +253,7 @@ public final class PlayerEmsgHandler implements Handler.Callback {
notifySourceMediaPresentationEnded();
}
private Map.Entry<Long, Long> ceilingExpiryEntryForPublishTime(long publishTimeMs) {
if (manifestPublishTimeToExpiryTimeUs.isEmpty()) {
return null;
}
private @Nullable Map.Entry<Long, Long> ceilingExpiryEntryForPublishTime(long publishTimeMs) {
return manifestPublishTimeToExpiryTimeUs.ceilingEntry(publishTimeMs);
}

View File

@ -49,7 +49,7 @@ public final class Descriptor {
}
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.dash.manifest;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.UriUtil;
@ -46,7 +47,7 @@ public final class RangedUri {
* @param length The length of the range, or {@link C#LENGTH_UNSET} to indicate that the range is
* unbounded.
*/
public RangedUri(String referenceUri, long start, long length) {
public RangedUri(@Nullable String referenceUri, long start, long length) {
this.referenceUri = referenceUri == null ? "" : referenceUri;
this.start = start;
this.length = length;
@ -74,18 +75,18 @@ public final class RangedUri {
/**
* Attempts to merge this {@link RangedUri} with another and an optional common base uri.
* <p>
* A merge is successful if both instances define the same {@link Uri} after resolution with the
* base uri, and if one starts the byte after the other ends, forming a contiguous region with
*
* <p>A merge is successful if both instances define the same {@link Uri} after resolution with
* the base uri, and if one starts the byte after the other ends, forming a contiguous region with
* no overlap.
* <p>
* If {@code other} is null then the merge is considered unsuccessful, and null is returned.
*
* <p>If {@code other} is null then the merge is considered unsuccessful, and null is returned.
*
* @param other The {@link RangedUri} to merge.
* @param baseUri The optional base Uri.
* @return The merged {@link RangedUri} if the merge was successful. Null otherwise.
*/
public RangedUri attemptMerge(RangedUri other, String baseUri) {
public @Nullable RangedUri attemptMerge(@Nullable RangedUri other, String baseUri) {
final String resolvedUri = resolveUriString(baseUri);
if (other == null || !resolvedUri.equals(other.resolveUriString(baseUri))) {
return null;
@ -113,7 +114,7 @@ public final class RangedUri {
}
@Override
public boolean equals(Object obj) {
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.source.dash.manifest;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
* Uniquely identifies a {@link Representation} in a {@link DashManifest}.
@ -81,7 +82,7 @@ public final class RepresentationKey implements Parcelable, Comparable<Represent
}
@Override
public boolean equals(Object o) {
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}

View File

@ -151,7 +151,7 @@ public final class DashDownloader extends SegmentDownloader<DashManifest, Repres
out.add(new Segment(startTimeUs, dataSpec));
}
private static DashSegmentIndex getSegmentIndex(
private static @Nullable DashSegmentIndex getSegmentIndex(
DataSource dataSource, int trackType, Representation representation)
throws IOException, InterruptedException {
DashSegmentIndex index = representation.getIndex();