mirror of
https://github.com/samsonjs/media.git
synced 2026-03-29 10:05:48 +00:00
Fix DASH module API nullability issues and add package-level non-null-by-default
PiperOrigin-RevId: 262123595
This commit is contained in:
parent
79e962c55a
commit
074b6f8ebd
15 changed files with 228 additions and 126 deletions
|
|
@ -41,6 +41,7 @@ android {
|
|||
dependencies {
|
||||
implementation project(modulePrefix + 'library-core')
|
||||
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
|
||||
compileOnly 'org.checkerframework:checker-compat-qual:' + checkerframeworkVersion
|
||||
implementation 'androidx.annotation:annotation:1.1.0'
|
||||
testImplementation project(modulePrefix + 'testutils-robolectric')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import java.util.IdentityHashMap;
|
|||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
|
||||
/** A DASH {@link MediaPeriod}. */
|
||||
/* package */ final class DashMediaPeriod
|
||||
|
|
@ -245,8 +246,12 @@ import java.util.regex.Pattern;
|
|||
}
|
||||
|
||||
@Override
|
||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
||||
public long selectTracks(
|
||||
@NullableType TrackSelection[] selections,
|
||||
boolean[] mayRetainStreamFlags,
|
||||
@NullableType SampleStream[] streams,
|
||||
boolean[] streamResetFlags,
|
||||
long positionUs) {
|
||||
int[] streamIndexToTrackGroupIndex = getStreamIndexToTrackGroupIndex(selections);
|
||||
releaseDisabledStreams(selections, mayRetainStreamFlags, streams);
|
||||
releaseOrphanEmbeddedStreams(selections, streams, streamIndexToTrackGroupIndex);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
* @return This factory, for convenience.
|
||||
* @throws IllegalStateException If one of the {@code create} methods has already been called.
|
||||
*/
|
||||
public Factory setTag(Object tag) {
|
||||
public Factory setTag(@Nullable Object tag) {
|
||||
Assertions.checkState(!isCreateCalled);
|
||||
this.tag = tag;
|
||||
return this;
|
||||
|
|
@ -430,8 +430,8 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
public DashMediaSource(
|
||||
DashManifest manifest,
|
||||
DashChunkSource.Factory chunkSourceFactory,
|
||||
Handler eventHandler,
|
||||
MediaSourceEventListener eventListener) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable MediaSourceEventListener eventListener) {
|
||||
this(
|
||||
manifest,
|
||||
chunkSourceFactory,
|
||||
|
|
@ -455,8 +455,8 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
DashManifest manifest,
|
||||
DashChunkSource.Factory chunkSourceFactory,
|
||||
int minLoadableRetryCount,
|
||||
Handler eventHandler,
|
||||
MediaSourceEventListener eventListener) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable MediaSourceEventListener eventListener) {
|
||||
this(
|
||||
manifest,
|
||||
/* manifestUri= */ null,
|
||||
|
|
@ -492,8 +492,8 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
Uri manifestUri,
|
||||
DataSource.Factory manifestDataSourceFactory,
|
||||
DashChunkSource.Factory chunkSourceFactory,
|
||||
Handler eventHandler,
|
||||
MediaSourceEventListener eventListener) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable MediaSourceEventListener eventListener) {
|
||||
this(
|
||||
manifestUri,
|
||||
manifestDataSourceFactory,
|
||||
|
|
@ -529,8 +529,8 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
DashChunkSource.Factory chunkSourceFactory,
|
||||
int minLoadableRetryCount,
|
||||
long livePresentationDelayMs,
|
||||
Handler eventHandler,
|
||||
MediaSourceEventListener eventListener) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable MediaSourceEventListener eventListener) {
|
||||
this(
|
||||
manifestUri,
|
||||
manifestDataSourceFactory,
|
||||
|
|
@ -569,8 +569,8 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
DashChunkSource.Factory chunkSourceFactory,
|
||||
int minLoadableRetryCount,
|
||||
long livePresentationDelayMs,
|
||||
Handler eventHandler,
|
||||
MediaSourceEventListener eventListener) {
|
||||
@Nullable Handler eventHandler,
|
||||
@Nullable MediaSourceEventListener eventListener) {
|
||||
this(
|
||||
/* manifest= */ null,
|
||||
manifestUri,
|
||||
|
|
@ -591,10 +591,10 @@ public final class DashMediaSource extends BaseMediaSource {
|
|||
}
|
||||
|
||||
private DashMediaSource(
|
||||
DashManifest manifest,
|
||||
Uri manifestUri,
|
||||
DataSource.Factory manifestDataSourceFactory,
|
||||
ParsingLoadable.Parser<? extends DashManifest> manifestParser,
|
||||
@Nullable DashManifest manifest,
|
||||
@Nullable Uri manifestUri,
|
||||
@Nullable DataSource.Factory manifestDataSourceFactory,
|
||||
@Nullable ParsingLoadable.Parser<? extends DashManifest> manifestParser,
|
||||
DashChunkSource.Factory chunkSourceFactory,
|
||||
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
|
||||
DrmSessionManager<?> drmSessionManager,
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ public final class DashUtil {
|
|||
* @throws IOException Thrown when there is an error while loading.
|
||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||
*/
|
||||
public static @Nullable DrmInitData loadDrmInitData(DataSource dataSource, Period period)
|
||||
@Nullable
|
||||
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
|
||||
throws IOException, InterruptedException {
|
||||
int primaryTrackType = C.TRACK_TYPE_VIDEO;
|
||||
Representation representation = getFirstRepresentation(period, primaryTrackType);
|
||||
|
|
@ -95,7 +96,8 @@ public final class DashUtil {
|
|||
* @throws IOException Thrown when there is an error while loading.
|
||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||
*/
|
||||
public static @Nullable Format loadSampleFormat(
|
||||
@Nullable
|
||||
public static Format loadSampleFormat(
|
||||
DataSource dataSource, int trackType, Representation representation)
|
||||
throws IOException, InterruptedException {
|
||||
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
||||
|
|
@ -116,7 +118,8 @@ public final class DashUtil {
|
|||
* @throws IOException Thrown when there is an error while loading.
|
||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||
*/
|
||||
public static @Nullable ChunkIndex loadChunkIndex(
|
||||
@Nullable
|
||||
public static ChunkIndex loadChunkIndex(
|
||||
DataSource dataSource, int trackType, Representation representation)
|
||||
throws IOException, InterruptedException {
|
||||
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
||||
|
|
@ -138,7 +141,8 @@ public final class DashUtil {
|
|||
* @throws IOException Thrown when there is an error while loading.
|
||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||
*/
|
||||
private static @Nullable ChunkExtractorWrapper loadInitializationData(
|
||||
@Nullable
|
||||
private static ChunkExtractorWrapper loadInitializationData(
|
||||
DataSource dataSource, int trackType, Representation representation, boolean loadIndex)
|
||||
throws IOException, InterruptedException {
|
||||
RangedUri initializationUri = representation.getInitializationUri();
|
||||
|
|
@ -187,7 +191,8 @@ public final class DashUtil {
|
|||
return new ChunkExtractorWrapper(extractor, trackType, format);
|
||||
}
|
||||
|
||||
private static @Nullable Representation getFirstRepresentation(Period period, int type) {
|
||||
@Nullable
|
||||
private static Representation getFirstRepresentation(Period period, int type) {
|
||||
int index = period.getAdaptationSetIndex(type);
|
||||
if (index == C.INDEX_UNSET) {
|
||||
return null;
|
||||
|
|
@ -197,5 +202,4 @@ public final class DashUtil {
|
|||
}
|
||||
|
||||
private DashUtil() {}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
private final int maxSegmentsPerLoad;
|
||||
|
||||
public Factory(DataSource.Factory dataSourceFactory) {
|
||||
this(dataSourceFactory, 1);
|
||||
this(dataSourceFactory, /* maxSegmentsPerLoad= */ 1);
|
||||
}
|
||||
|
||||
public Factory(DataSource.Factory dataSourceFactory, int maxSegmentsPerLoad) {
|
||||
|
|
@ -633,7 +633,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
Representation representation,
|
||||
boolean enableEventMessageTrack,
|
||||
List<Format> closedCaptionFormats,
|
||||
TrackOutput playerEmsgTrackOutput) {
|
||||
@Nullable TrackOutput playerEmsgTrackOutput) {
|
||||
this(
|
||||
periodDurationUs,
|
||||
representation,
|
||||
|
|
@ -787,7 +787,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
Representation representation,
|
||||
boolean enableEventMessageTrack,
|
||||
List<Format> closedCaptionFormats,
|
||||
TrackOutput playerEmsgTrackOutput) {
|
||||
@Nullable TrackOutput playerEmsgTrackOutput) {
|
||||
String containerMimeType = representation.format.containerMimeType;
|
||||
if (mimeTypeIsRawText(containerMimeType)) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -80,12 +80,10 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||
* The {@link UtcTimingElement}, or null if not present. Defined in DVB A168:7/2016, Section
|
||||
* 4.7.2.
|
||||
*/
|
||||
public final UtcTimingElement utcTiming;
|
||||
@Nullable public final UtcTimingElement utcTiming;
|
||||
|
||||
/**
|
||||
* The location of this manifest.
|
||||
*/
|
||||
public final Uri location;
|
||||
/** The location of this manifest, or null if not present. */
|
||||
@Nullable public final Uri location;
|
||||
|
||||
/** The {@link ProgramInformation}, or null if not present. */
|
||||
@Nullable public final ProgramInformation programInformation;
|
||||
|
|
@ -106,8 +104,8 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||
long timeShiftBufferDepthMs,
|
||||
long suggestedPresentationDelayMs,
|
||||
long publishTimeMs,
|
||||
UtcTimingElement utcTiming,
|
||||
Uri location,
|
||||
@Nullable UtcTimingElement utcTiming,
|
||||
@Nullable Uri location,
|
||||
List<Period> periods) {
|
||||
this(
|
||||
availabilityStartTimeMs,
|
||||
|
|
@ -134,8 +132,8 @@ public class DashManifest implements FilterableManifest<DashManifest> {
|
|||
long suggestedPresentationDelayMs,
|
||||
long publishTimeMs,
|
||||
@Nullable ProgramInformation programInformation,
|
||||
UtcTimingElement utcTiming,
|
||||
Uri location,
|
||||
@Nullable UtcTimingElement utcTiming,
|
||||
@Nullable Uri location,
|
||||
List<Period> periods) {
|
||||
this.availabilityStartTimeMs = availabilityStartTimeMs;
|
||||
this.durationMs = durationMs;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer2.source.dash.manifest;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Pair;
|
||||
|
|
@ -47,6 +48,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
|
@ -189,9 +191,9 @@ public class DashManifestParser extends DefaultHandler
|
|||
long timeShiftBufferDepthMs,
|
||||
long suggestedPresentationDelayMs,
|
||||
long publishTimeMs,
|
||||
ProgramInformation programInformation,
|
||||
UtcTimingElement utcTiming,
|
||||
Uri location,
|
||||
@Nullable ProgramInformation programInformation,
|
||||
@Nullable UtcTimingElement utcTiming,
|
||||
@Nullable Uri location,
|
||||
List<Period> periods) {
|
||||
return new DashManifest(
|
||||
availabilityStartTime,
|
||||
|
|
@ -259,8 +261,9 @@ public class DashManifestParser extends DefaultHandler
|
|||
|
||||
// AdaptationSet parsing.
|
||||
|
||||
protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, String baseUrl,
|
||||
SegmentBase segmentBase) throws XmlPullParserException, IOException {
|
||||
protected AdaptationSet parseAdaptationSet(
|
||||
XmlPullParser xpp, String baseUrl, @Nullable SegmentBase segmentBase)
|
||||
throws XmlPullParserException, IOException {
|
||||
int id = parseInt(xpp, "id", AdaptationSet.ID_UNSET);
|
||||
int contentType = parseContentType(xpp);
|
||||
|
||||
|
|
@ -394,8 +397,8 @@ public class DashManifestParser extends DefaultHandler
|
|||
* @return The scheme type and/or {@link SchemeData} parsed from the ContentProtection element.
|
||||
* Either or both may be null, depending on the ContentProtection element being parsed.
|
||||
*/
|
||||
protected Pair<String, SchemeData> parseContentProtection(XmlPullParser xpp)
|
||||
throws XmlPullParserException, IOException {
|
||||
protected Pair<@NullableType String, @NullableType SchemeData> parseContentProtection(
|
||||
XmlPullParser xpp) throws XmlPullParserException, IOException {
|
||||
String schemeType = null;
|
||||
String licenseServerUrl = null;
|
||||
byte[] data = null;
|
||||
|
|
@ -477,19 +480,19 @@ public class DashManifestParser extends DefaultHandler
|
|||
protected RepresentationInfo parseRepresentation(
|
||||
XmlPullParser xpp,
|
||||
String baseUrl,
|
||||
String label,
|
||||
String adaptationSetMimeType,
|
||||
String adaptationSetCodecs,
|
||||
@Nullable String label,
|
||||
@Nullable String adaptationSetMimeType,
|
||||
@Nullable String adaptationSetCodecs,
|
||||
int adaptationSetWidth,
|
||||
int adaptationSetHeight,
|
||||
float adaptationSetFrameRate,
|
||||
int adaptationSetAudioChannels,
|
||||
int adaptationSetAudioSamplingRate,
|
||||
String adaptationSetLanguage,
|
||||
@Nullable String adaptationSetLanguage,
|
||||
List<Descriptor> adaptationSetRoleDescriptors,
|
||||
List<Descriptor> adaptationSetAccessibilityDescriptors,
|
||||
List<Descriptor> adaptationSetSupplementalProperties,
|
||||
SegmentBase segmentBase)
|
||||
@Nullable SegmentBase segmentBase)
|
||||
throws XmlPullParserException, IOException {
|
||||
String id = xpp.getAttributeValue(null, "id");
|
||||
int bandwidth = parseInt(xpp, "bandwidth", Format.NO_VALUE);
|
||||
|
|
@ -564,19 +567,19 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
|
||||
protected Format buildFormat(
|
||||
String id,
|
||||
String label,
|
||||
String containerMimeType,
|
||||
@Nullable String id,
|
||||
@Nullable String label,
|
||||
@Nullable String containerMimeType,
|
||||
int width,
|
||||
int height,
|
||||
float frameRate,
|
||||
int audioChannels,
|
||||
int audioSamplingRate,
|
||||
int bitrate,
|
||||
String language,
|
||||
@Nullable String language,
|
||||
List<Descriptor> roleDescriptors,
|
||||
List<Descriptor> accessibilityDescriptors,
|
||||
String codecs,
|
||||
@Nullable String codecs,
|
||||
List<Descriptor> supplementalProperties) {
|
||||
String sampleMimeType = getSampleMimeType(containerMimeType, codecs);
|
||||
@C.SelectionFlags int selectionFlags = parseSelectionFlagsFromRoleDescriptors(roleDescriptors);
|
||||
|
|
@ -650,7 +653,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
|
||||
protected Representation buildRepresentation(
|
||||
RepresentationInfo representationInfo,
|
||||
String extraDrmSchemeType,
|
||||
@Nullable String extraDrmSchemeType,
|
||||
ArrayList<SchemeData> extraDrmSchemeDatas,
|
||||
ArrayList<Descriptor> extraInbandEventStreams) {
|
||||
Format format = representationInfo.format;
|
||||
|
|
@ -675,7 +678,8 @@ public class DashManifestParser extends DefaultHandler
|
|||
|
||||
// SegmentBase, SegmentList and SegmentTemplate parsing.
|
||||
|
||||
protected SingleSegmentBase parseSegmentBase(XmlPullParser xpp, SingleSegmentBase parent)
|
||||
protected SingleSegmentBase parseSegmentBase(
|
||||
XmlPullParser xpp, @Nullable SingleSegmentBase parent)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1);
|
||||
|
|
@ -711,7 +715,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
indexLength);
|
||||
}
|
||||
|
||||
protected SegmentList parseSegmentList(XmlPullParser xpp, SegmentList parent)
|
||||
protected SegmentList parseSegmentList(XmlPullParser xpp, @Nullable SegmentList parent)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1);
|
||||
|
|
@ -756,15 +760,15 @@ public class DashManifestParser extends DefaultHandler
|
|||
long presentationTimeOffset,
|
||||
long startNumber,
|
||||
long duration,
|
||||
List<SegmentTimelineElement> timeline,
|
||||
List<RangedUri> segments) {
|
||||
@Nullable List<SegmentTimelineElement> timeline,
|
||||
@Nullable List<RangedUri> segments) {
|
||||
return new SegmentList(initialization, timescale, presentationTimeOffset,
|
||||
startNumber, duration, timeline, segments);
|
||||
}
|
||||
|
||||
protected SegmentTemplate parseSegmentTemplate(
|
||||
XmlPullParser xpp,
|
||||
SegmentTemplate parent,
|
||||
@Nullable SegmentTemplate parent,
|
||||
List<Descriptor> adaptationSetSupplementalProperties)
|
||||
throws XmlPullParserException, IOException {
|
||||
long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1);
|
||||
|
|
@ -819,8 +823,8 @@ public class DashManifestParser extends DefaultHandler
|
|||
long endNumber,
|
||||
long duration,
|
||||
List<SegmentTimelineElement> timeline,
|
||||
UrlTemplate initializationTemplate,
|
||||
UrlTemplate mediaTemplate) {
|
||||
@Nullable UrlTemplate initializationTemplate,
|
||||
@Nullable UrlTemplate mediaTemplate) {
|
||||
return new SegmentTemplate(
|
||||
initialization,
|
||||
timescale,
|
||||
|
|
@ -1008,8 +1012,9 @@ public class DashManifestParser extends DefaultHandler
|
|||
return new SegmentTimelineElement(elapsedTime, duration);
|
||||
}
|
||||
|
||||
protected UrlTemplate parseUrlTemplate(XmlPullParser xpp, String name,
|
||||
UrlTemplate defaultValue) {
|
||||
@Nullable
|
||||
protected UrlTemplate parseUrlTemplate(
|
||||
XmlPullParser xpp, String name, @Nullable UrlTemplate defaultValue) {
|
||||
String valueString = xpp.getAttributeValue(null, name);
|
||||
if (valueString != null) {
|
||||
return UrlTemplate.compile(valueString);
|
||||
|
|
@ -1126,7 +1131,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
|
||||
@C.RoleFlags
|
||||
protected int parseDashRoleSchemeValue(String value) {
|
||||
protected int parseDashRoleSchemeValue(@Nullable String value) {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1159,7 +1164,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
|
||||
@C.RoleFlags
|
||||
protected int parseTvaAudioPurposeCsValue(String value) {
|
||||
protected int parseTvaAudioPurposeCsValue(@Nullable String value) {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1230,7 +1235,9 @@ public class DashManifestParser extends DefaultHandler
|
|||
* @param codecs The codecs attribute.
|
||||
* @return The derived sample mimeType, or null if it could not be derived.
|
||||
*/
|
||||
private static String getSampleMimeType(String containerMimeType, String codecs) {
|
||||
@Nullable
|
||||
private static String getSampleMimeType(
|
||||
@Nullable String containerMimeType, @Nullable String codecs) {
|
||||
if (MimeTypes.isAudio(containerMimeType)) {
|
||||
return MimeTypes.getAudioMediaMimeType(codecs);
|
||||
} else if (MimeTypes.isVideo(containerMimeType)) {
|
||||
|
|
@ -1264,7 +1271,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
* @param mimeType The mimeType.
|
||||
* @return Whether the mimeType is a text sample mimeType.
|
||||
*/
|
||||
private static boolean mimeTypeIsRawText(String mimeType) {
|
||||
private static boolean mimeTypeIsRawText(@Nullable String mimeType) {
|
||||
return MimeTypes.isText(mimeType)
|
||||
|| MimeTypes.APPLICATION_TTML.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_MP4VTT.equals(mimeType)
|
||||
|
|
@ -1273,16 +1280,18 @@ public class DashManifestParser extends DefaultHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks two languages for consistency, returning the consistent language, or throwing an
|
||||
* {@link IllegalStateException} if the languages are inconsistent.
|
||||
* <p>
|
||||
* Two languages are consistent if they are equal, or if one is null.
|
||||
* Checks two languages for consistency, returning the consistent language, or throwing an {@link
|
||||
* IllegalStateException} if the languages are inconsistent.
|
||||
*
|
||||
* <p>Two languages are consistent if they are equal, or if one is null.
|
||||
*
|
||||
* @param firstLanguage The first language.
|
||||
* @param secondLanguage The second language.
|
||||
* @return The consistent language.
|
||||
*/
|
||||
private static String checkLanguageConsistency(String firstLanguage, String secondLanguage) {
|
||||
@Nullable
|
||||
private static String checkLanguageConsistency(
|
||||
@Nullable String firstLanguage, @Nullable String secondLanguage) {
|
||||
if (firstLanguage == null) {
|
||||
return secondLanguage;
|
||||
} else if (secondLanguage == null) {
|
||||
|
|
@ -1485,14 +1494,19 @@ public class DashManifestParser extends DefaultHandler
|
|||
public final Format format;
|
||||
public final String baseUrl;
|
||||
public final SegmentBase segmentBase;
|
||||
public final String drmSchemeType;
|
||||
@Nullable public final String drmSchemeType;
|
||||
public final ArrayList<SchemeData> drmSchemeDatas;
|
||||
public final ArrayList<Descriptor> inbandEventStreams;
|
||||
public final long revisionId;
|
||||
|
||||
public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase,
|
||||
String drmSchemeType, ArrayList<SchemeData> drmSchemeDatas,
|
||||
ArrayList<Descriptor> inbandEventStreams, long revisionId) {
|
||||
public RepresentationInfo(
|
||||
Format format,
|
||||
String baseUrl,
|
||||
SegmentBase segmentBase,
|
||||
@Nullable String drmSchemeType,
|
||||
ArrayList<SchemeData> drmSchemeDatas,
|
||||
ArrayList<Descriptor> inbandEventStreams,
|
||||
long revisionId) {
|
||||
this.format = format;
|
||||
this.baseUrl = baseUrl;
|
||||
this.segmentBase = segmentBase;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.source.dash.manifest;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
|
|
@ -24,10 +23,8 @@ import com.google.android.exoplayer2.util.Util;
|
|||
*/
|
||||
public final class Descriptor {
|
||||
|
||||
/**
|
||||
* The scheme URI.
|
||||
*/
|
||||
@NonNull public final String schemeIdUri;
|
||||
/** The scheme URI. */
|
||||
public final String schemeIdUri;
|
||||
/**
|
||||
* The value, or null.
|
||||
*/
|
||||
|
|
@ -42,7 +39,7 @@ public final class Descriptor {
|
|||
* @param value The value, or null.
|
||||
* @param id The identifier, or null.
|
||||
*/
|
||||
public Descriptor(@NonNull String schemeIdUri, @Nullable String value, @Nullable String id) {
|
||||
public Descriptor(String schemeIdUri, @Nullable String value, @Nullable String id) {
|
||||
this.schemeIdUri = schemeIdUri;
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
|
|
@ -63,10 +60,9 @@ public final class Descriptor {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (schemeIdUri != null ? schemeIdUri.hashCode() : 0);
|
||||
int result = schemeIdUri.hashCode();
|
||||
result = 31 * result + (value != null ? value.hashCode() : 0);
|
||||
result = 31 * result + (id != null ? id.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,22 +21,26 @@ import com.google.android.exoplayer2.util.Util;
|
|||
/** A parsed program information element. */
|
||||
public class ProgramInformation {
|
||||
/** The title for the media presentation. */
|
||||
public final String title;
|
||||
@Nullable public final String title;
|
||||
|
||||
/** Information about the original source of the media presentation. */
|
||||
public final String source;
|
||||
@Nullable public final String source;
|
||||
|
||||
/** A copyright statement for the media presentation. */
|
||||
public final String copyright;
|
||||
@Nullable public final String copyright;
|
||||
|
||||
/** A URL that provides more information about the media presentation. */
|
||||
public final String moreInformationURL;
|
||||
@Nullable public final String moreInformationURL;
|
||||
|
||||
/** Declares the language code(s) for this ProgramInformation. */
|
||||
public final String lang;
|
||||
@Nullable public final String lang;
|
||||
|
||||
public ProgramInformation(
|
||||
String title, String source, String copyright, String moreInformationURL, String lang) {
|
||||
@Nullable String title,
|
||||
@Nullable String source,
|
||||
@Nullable String copyright,
|
||||
@Nullable String moreInformationURL,
|
||||
@Nullable String lang) {
|
||||
this.title = title;
|
||||
this.source = source;
|
||||
this.copyright = copyright;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public final class RangedUri {
|
|||
* <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.
|
||||
* @param baseUri The base Uri.
|
||||
* @return The merged {@link RangedUri} if the merge was successful. Null otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer2.source.dash.manifest;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
||||
|
|
@ -53,9 +54,7 @@ public abstract class Representation {
|
|||
* The offset of the presentation timestamps in the media stream relative to media time.
|
||||
*/
|
||||
public final long presentationTimeOffsetUs;
|
||||
/**
|
||||
* The in-band event streams in the representation. Never null, but may be empty.
|
||||
*/
|
||||
/** The in-band event streams in the representation. May be empty. */
|
||||
public final List<Descriptor> inbandEventStreams;
|
||||
|
||||
private final RangedUri initializationUri;
|
||||
|
|
@ -71,7 +70,7 @@ public abstract class Representation {
|
|||
*/
|
||||
public static Representation newInstance(
|
||||
long revisionId, Format format, String baseUrl, SegmentBase segmentBase) {
|
||||
return newInstance(revisionId, format, baseUrl, segmentBase, null);
|
||||
return newInstance(revisionId, format, baseUrl, segmentBase, /* inbandEventStreams= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -89,8 +88,9 @@ public abstract class Representation {
|
|||
Format format,
|
||||
String baseUrl,
|
||||
SegmentBase segmentBase,
|
||||
List<Descriptor> inbandEventStreams) {
|
||||
return newInstance(revisionId, format, baseUrl, segmentBase, inbandEventStreams, null);
|
||||
@Nullable List<Descriptor> inbandEventStreams) {
|
||||
return newInstance(
|
||||
revisionId, format, baseUrl, segmentBase, inbandEventStreams, /* cacheKey= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,8 +110,8 @@ public abstract class Representation {
|
|||
Format format,
|
||||
String baseUrl,
|
||||
SegmentBase segmentBase,
|
||||
List<Descriptor> inbandEventStreams,
|
||||
String cacheKey) {
|
||||
@Nullable List<Descriptor> inbandEventStreams,
|
||||
@Nullable String cacheKey) {
|
||||
if (segmentBase instanceof SingleSegmentBase) {
|
||||
return new SingleSegmentRepresentation(
|
||||
revisionId,
|
||||
|
|
@ -135,7 +135,7 @@ public abstract class Representation {
|
|||
Format format,
|
||||
String baseUrl,
|
||||
SegmentBase segmentBase,
|
||||
List<Descriptor> inbandEventStreams) {
|
||||
@Nullable List<Descriptor> inbandEventStreams) {
|
||||
this.revisionId = revisionId;
|
||||
this.format = format;
|
||||
this.baseUrl = baseUrl;
|
||||
|
|
@ -151,6 +151,7 @@ public abstract class Representation {
|
|||
* Returns a {@link RangedUri} defining the location of the representation's initialization data,
|
||||
* or null if no initialization data exists.
|
||||
*/
|
||||
@Nullable
|
||||
public RangedUri getInitializationUri() {
|
||||
return initializationUri;
|
||||
}
|
||||
|
|
@ -159,14 +160,15 @@ public abstract class Representation {
|
|||
* Returns a {@link RangedUri} defining the location of the representation's segment index, or
|
||||
* null if the representation provides an index directly.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract RangedUri getIndexUri();
|
||||
|
||||
/**
|
||||
* Returns an index if the representation provides one directly, or null otherwise.
|
||||
*/
|
||||
/** Returns an index if the representation provides one directly, or null otherwise. */
|
||||
@Nullable
|
||||
public abstract DashSegmentIndex getIndex();
|
||||
|
||||
/** Returns a cache key for the representation if set, or null. */
|
||||
@Nullable
|
||||
public abstract String getCacheKey();
|
||||
|
||||
/**
|
||||
|
|
@ -184,9 +186,9 @@ public abstract class Representation {
|
|||
*/
|
||||
public final long contentLength;
|
||||
|
||||
private final String cacheKey;
|
||||
private final RangedUri indexUri;
|
||||
private final SingleSegmentIndex segmentIndex;
|
||||
@Nullable private final String cacheKey;
|
||||
@Nullable private final RangedUri indexUri;
|
||||
@Nullable private final SingleSegmentIndex segmentIndex;
|
||||
|
||||
/**
|
||||
* @param revisionId Identifies the revision of the content.
|
||||
|
|
@ -209,7 +211,7 @@ public abstract class Representation {
|
|||
long indexStart,
|
||||
long indexEnd,
|
||||
List<Descriptor> inbandEventStreams,
|
||||
String cacheKey,
|
||||
@Nullable String cacheKey,
|
||||
long contentLength) {
|
||||
RangedUri rangedUri = new RangedUri(null, initializationStart,
|
||||
initializationEnd - initializationStart + 1);
|
||||
|
|
@ -233,8 +235,8 @@ public abstract class Representation {
|
|||
Format format,
|
||||
String baseUrl,
|
||||
SingleSegmentBase segmentBase,
|
||||
List<Descriptor> inbandEventStreams,
|
||||
String cacheKey,
|
||||
@Nullable List<Descriptor> inbandEventStreams,
|
||||
@Nullable String cacheKey,
|
||||
long contentLength) {
|
||||
super(revisionId, format, baseUrl, segmentBase, inbandEventStreams);
|
||||
this.uri = Uri.parse(baseUrl);
|
||||
|
|
@ -248,16 +250,19 @@ public abstract class Representation {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RangedUri getIndexUri() {
|
||||
return indexUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DashSegmentIndex getIndex() {
|
||||
return segmentIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getCacheKey() {
|
||||
return cacheKey;
|
||||
}
|
||||
|
|
@ -284,12 +289,13 @@ public abstract class Representation {
|
|||
Format format,
|
||||
String baseUrl,
|
||||
MultiSegmentBase segmentBase,
|
||||
List<Descriptor> inbandEventStreams) {
|
||||
@Nullable List<Descriptor> inbandEventStreams) {
|
||||
super(revisionId, format, baseUrl, segmentBase, inbandEventStreams);
|
||||
this.segmentBase = segmentBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RangedUri getIndexUri() {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -300,6 +306,7 @@ public abstract class Representation {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getCacheKey() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.source.dash.manifest;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
|
@ -25,7 +26,7 @@ import java.util.List;
|
|||
*/
|
||||
public abstract class SegmentBase {
|
||||
|
||||
/* package */ final RangedUri initialization;
|
||||
/* package */ @Nullable final RangedUri initialization;
|
||||
/* package */ final long timescale;
|
||||
/* package */ final long presentationTimeOffset;
|
||||
|
||||
|
|
@ -36,7 +37,8 @@ public abstract class SegmentBase {
|
|||
* @param presentationTimeOffset The presentation time offset. The value in seconds is the
|
||||
* division of this value and {@code timescale}.
|
||||
*/
|
||||
public SegmentBase(RangedUri initialization, long timescale, long presentationTimeOffset) {
|
||||
public SegmentBase(
|
||||
@Nullable RangedUri initialization, long timescale, long presentationTimeOffset) {
|
||||
this.initialization = initialization;
|
||||
this.timescale = timescale;
|
||||
this.presentationTimeOffset = presentationTimeOffset;
|
||||
|
|
@ -49,6 +51,7 @@ public abstract class SegmentBase {
|
|||
* @param representation The {@link Representation} for which initialization data is required.
|
||||
* @return A {@link RangedUri} defining the location of the initialization data, or null.
|
||||
*/
|
||||
@Nullable
|
||||
public RangedUri getInitialization(Representation representation) {
|
||||
return initialization;
|
||||
}
|
||||
|
|
@ -77,19 +80,31 @@ public abstract class SegmentBase {
|
|||
* @param indexStart The byte offset of the index data in the segment.
|
||||
* @param indexLength The length of the index data in bytes.
|
||||
*/
|
||||
public SingleSegmentBase(RangedUri initialization, long timescale, long presentationTimeOffset,
|
||||
long indexStart, long indexLength) {
|
||||
public SingleSegmentBase(
|
||||
@Nullable RangedUri initialization,
|
||||
long timescale,
|
||||
long presentationTimeOffset,
|
||||
long indexStart,
|
||||
long indexLength) {
|
||||
super(initialization, timescale, presentationTimeOffset);
|
||||
this.indexStart = indexStart;
|
||||
this.indexLength = indexLength;
|
||||
}
|
||||
|
||||
public SingleSegmentBase() {
|
||||
this(null, 1, 0, 0, 0);
|
||||
this(
|
||||
/* initialization= */ null,
|
||||
/* timescale= */ 1,
|
||||
/* presentationTimeOffset= */ 0,
|
||||
/* indexStart= */ 0,
|
||||
/* indexLength= */ 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RangedUri getIndex() {
|
||||
return indexLength <= 0 ? null : new RangedUri(null, indexStart, indexLength);
|
||||
return indexLength <= 0
|
||||
? null
|
||||
: new RangedUri(/* referenceUri= */ null, indexStart, indexLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -101,7 +116,7 @@ public abstract class SegmentBase {
|
|||
|
||||
/* package */ final long startNumber;
|
||||
/* package */ final long duration;
|
||||
/* package */ final List<SegmentTimelineElement> segmentTimeline;
|
||||
/* package */ @Nullable final List<SegmentTimelineElement> segmentTimeline;
|
||||
|
||||
/**
|
||||
* @param initialization A {@link RangedUri} corresponding to initialization data, if such data
|
||||
|
|
@ -118,12 +133,12 @@ public abstract class SegmentBase {
|
|||
* parameter.
|
||||
*/
|
||||
public MultiSegmentBase(
|
||||
RangedUri initialization,
|
||||
@Nullable RangedUri initialization,
|
||||
long timescale,
|
||||
long presentationTimeOffset,
|
||||
long startNumber,
|
||||
long duration,
|
||||
List<SegmentTimelineElement> segmentTimeline) {
|
||||
@Nullable List<SegmentTimelineElement> segmentTimeline) {
|
||||
super(initialization, timescale, presentationTimeOffset);
|
||||
this.startNumber = startNumber;
|
||||
this.duration = duration;
|
||||
|
|
@ -223,7 +238,7 @@ public abstract class SegmentBase {
|
|||
*/
|
||||
public static class SegmentList extends MultiSegmentBase {
|
||||
|
||||
/* package */ final List<RangedUri> mediaSegments;
|
||||
/* package */ @Nullable final List<RangedUri> mediaSegments;
|
||||
|
||||
/**
|
||||
* @param initialization A {@link RangedUri} corresponding to initialization data, if such data
|
||||
|
|
@ -246,8 +261,8 @@ public abstract class SegmentBase {
|
|||
long presentationTimeOffset,
|
||||
long startNumber,
|
||||
long duration,
|
||||
List<SegmentTimelineElement> segmentTimeline,
|
||||
List<RangedUri> mediaSegments) {
|
||||
@Nullable List<SegmentTimelineElement> segmentTimeline,
|
||||
@Nullable List<RangedUri> mediaSegments) {
|
||||
super(initialization, timescale, presentationTimeOffset, startNumber, duration,
|
||||
segmentTimeline);
|
||||
this.mediaSegments = mediaSegments;
|
||||
|
|
@ -275,8 +290,8 @@ public abstract class SegmentBase {
|
|||
*/
|
||||
public static class SegmentTemplate extends MultiSegmentBase {
|
||||
|
||||
/* package */ final UrlTemplate initializationTemplate;
|
||||
/* package */ final UrlTemplate mediaTemplate;
|
||||
/* package */ @Nullable final UrlTemplate initializationTemplate;
|
||||
/* package */ @Nullable final UrlTemplate mediaTemplate;
|
||||
/* package */ final long endNumber;
|
||||
|
||||
/**
|
||||
|
|
@ -308,9 +323,9 @@ public abstract class SegmentBase {
|
|||
long startNumber,
|
||||
long endNumber,
|
||||
long duration,
|
||||
List<SegmentTimelineElement> segmentTimeline,
|
||||
UrlTemplate initializationTemplate,
|
||||
UrlTemplate mediaTemplate) {
|
||||
@Nullable List<SegmentTimelineElement> segmentTimeline,
|
||||
@Nullable UrlTemplate initializationTemplate,
|
||||
@Nullable UrlTemplate mediaTemplate) {
|
||||
super(
|
||||
initialization,
|
||||
timescale,
|
||||
|
|
@ -324,6 +339,7 @@ public abstract class SegmentBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RangedUri getInitialization(Representation representation) {
|
||||
if (initializationTemplate != null) {
|
||||
String urlString = initializationTemplate.buildUri(representation.format.id, 0,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@NonNullApi
|
||||
package com.google.android.exoplayer2.source.dash.manifest;
|
||||
|
||||
import com.google.android.exoplayer2.util.NonNullApi;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@NonNullApi
|
||||
package com.google.android.exoplayer2.source.dash.offline;
|
||||
|
||||
import com.google.android.exoplayer2.util.NonNullApi;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@NonNullApi
|
||||
package com.google.android.exoplayer2.source.dash;
|
||||
|
||||
import com.google.android.exoplayer2.util.NonNullApi;
|
||||
Loading…
Reference in a new issue