use of androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy in project media by androidx.
the class DefaultMediaSourceFactory method createMediaSource.
@UnstableApi
@Override
public MediaSource createMediaSource(MediaItem mediaItem) {
Assertions.checkNotNull(mediaItem.localConfiguration);
@Nullable String scheme = mediaItem.localConfiguration.uri.getScheme();
if (scheme != null && scheme.equals(C.SSAI_SCHEME)) {
return checkNotNull(serverSideAdInsertionMediaSourceFactory).createMediaSource(mediaItem);
}
@C.ContentType int type = Util.inferContentTypeForUriAndMimeType(mediaItem.localConfiguration.uri, mediaItem.localConfiguration.mimeType);
@Nullable MediaSource.Factory mediaSourceFactory = delegateFactoryLoader.getMediaSourceFactory(type);
checkStateNotNull(mediaSourceFactory, "No suitable media source factory found for content type: " + type);
MediaItem.LiveConfiguration.Builder liveConfigurationBuilder = mediaItem.liveConfiguration.buildUpon();
if (mediaItem.liveConfiguration.targetOffsetMs == C.TIME_UNSET) {
liveConfigurationBuilder.setTargetOffsetMs(liveTargetOffsetMs);
}
if (mediaItem.liveConfiguration.minPlaybackSpeed == C.RATE_UNSET) {
liveConfigurationBuilder.setMinPlaybackSpeed(liveMinSpeed);
}
if (mediaItem.liveConfiguration.maxPlaybackSpeed == C.RATE_UNSET) {
liveConfigurationBuilder.setMaxPlaybackSpeed(liveMaxSpeed);
}
if (mediaItem.liveConfiguration.minOffsetMs == C.TIME_UNSET) {
liveConfigurationBuilder.setMinOffsetMs(liveMinOffsetMs);
}
if (mediaItem.liveConfiguration.maxOffsetMs == C.TIME_UNSET) {
liveConfigurationBuilder.setMaxOffsetMs(liveMaxOffsetMs);
}
MediaItem.LiveConfiguration liveConfiguration = liveConfigurationBuilder.build();
// Make sure to retain the very same media item instance, if no value needs to be overridden.
if (!liveConfiguration.equals(mediaItem.liveConfiguration)) {
mediaItem = mediaItem.buildUpon().setLiveConfiguration(liveConfiguration).build();
}
MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem);
List<MediaItem.SubtitleConfiguration> subtitleConfigurations = castNonNull(mediaItem.localConfiguration).subtitleConfigurations;
if (!subtitleConfigurations.isEmpty()) {
MediaSource[] mediaSources = new MediaSource[subtitleConfigurations.size() + 1];
mediaSources[0] = mediaSource;
for (int i = 0; i < subtitleConfigurations.size(); i++) {
if (useProgressiveMediaSourceForSubtitles) {
Format format = new Format.Builder().setSampleMimeType(subtitleConfigurations.get(i).mimeType).setLanguage(subtitleConfigurations.get(i).language).setSelectionFlags(subtitleConfigurations.get(i).selectionFlags).setRoleFlags(subtitleConfigurations.get(i).roleFlags).setLabel(subtitleConfigurations.get(i).label).setId(subtitleConfigurations.get(i).id).build();
ExtractorsFactory extractorsFactory = () -> new Extractor[] { SubtitleDecoderFactory.DEFAULT.supportsFormat(format) ? new SubtitleExtractor(SubtitleDecoderFactory.DEFAULT.createDecoder(format), format) : new UnknownSubtitlesExtractor(format) };
mediaSources[i + 1] = new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy).createMediaSource(MediaItem.fromUri(subtitleConfigurations.get(i).uri.toString()));
} else {
mediaSources[i + 1] = new SingleSampleMediaSource.Factory(dataSourceFactory).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy).createMediaSource(subtitleConfigurations.get(i), /* durationUs= */
C.TIME_UNSET);
}
}
mediaSource = new MergingMediaSource(mediaSources);
}
return maybeWrapWithAdsMediaSource(mediaItem, maybeClipMediaSource(mediaItem, mediaSource));
}
use of androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy in project media by androidx.
the class DashMediaSource method createPeriod.
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
int periodIndex = (Integer) id.periodUid - firstPeriodId;
MediaSourceEventListener.EventDispatcher periodEventDispatcher = createEventDispatcher(id, manifest.getPeriod(periodIndex).startMs);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id);
DashMediaPeriod mediaPeriod = new DashMediaPeriod(firstPeriodId + periodIndex, manifest, baseUrlExclusionList, periodIndex, chunkSourceFactory, mediaTransferListener, drmSessionManager, drmEventDispatcher, loadErrorHandlingPolicy, periodEventDispatcher, elapsedRealtimeOffsetMs, manifestLoadErrorThrower, allocator, compositeSequenceableLoaderFactory, playerEmsgCallback, getPlayerId());
periodsById.put(mediaPeriod.id, mediaPeriod);
return mediaPeriod;
}
use of androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy in project media by androidx.
the class DefaultDashChunkSource method onChunkLoadError.
@Override
public boolean onChunkLoadError(Chunk chunk, boolean cancelable, LoadErrorHandlingPolicy.LoadErrorInfo loadErrorInfo, LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
if (!cancelable) {
return false;
}
if (playerTrackEmsgHandler != null && playerTrackEmsgHandler.onChunkLoadError(chunk)) {
return true;
}
// Workaround for missing segment at the end of the period
if (!manifest.dynamic && chunk instanceof MediaChunk && loadErrorInfo.exception instanceof InvalidResponseCodeException && ((InvalidResponseCodeException) loadErrorInfo.exception).responseCode == 404) {
RepresentationHolder representationHolder = representationHolders[trackSelection.indexOf(chunk.trackFormat)];
long segmentCount = representationHolder.getSegmentCount();
if (segmentCount != DashSegmentIndex.INDEX_UNBOUNDED && segmentCount != 0) {
long lastAvailableSegmentNum = representationHolder.getFirstSegmentNum() + segmentCount - 1;
if (((MediaChunk) chunk).getNextChunkIndex() > lastAvailableSegmentNum) {
missingLastSegment = true;
return true;
}
}
}
int trackIndex = trackSelection.indexOf(chunk.trackFormat);
RepresentationHolder representationHolder = representationHolders[trackIndex];
@Nullable BaseUrl newBaseUrl = baseUrlExclusionList.selectBaseUrl(representationHolder.representation.baseUrls);
if (newBaseUrl != null && !representationHolder.selectedBaseUrl.equals(newBaseUrl)) {
// which will use the new base URL.
return true;
}
LoadErrorHandlingPolicy.FallbackOptions fallbackOptions = createFallbackOptions(trackSelection, representationHolder.representation.baseUrls);
if (!fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) && !fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION)) {
return false;
}
@Nullable LoadErrorHandlingPolicy.FallbackSelection fallbackSelection = loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
if (fallbackSelection == null || !fallbackOptions.isFallbackAvailable(fallbackSelection.type)) {
// Policy indicated to not use any fallback or a fallback type that is not available.
return false;
}
boolean cancelLoad = false;
if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK) {
cancelLoad = trackSelection.blacklist(trackSelection.indexOf(chunk.trackFormat), fallbackSelection.exclusionDurationMs);
} else if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION) {
baseUrlExclusionList.exclude(representationHolder.selectedBaseUrl, fallbackSelection.exclusionDurationMs);
cancelLoad = true;
}
return cancelLoad;
}
use of androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy in project media by androidx.
the class SsMediaSource method createPeriod.
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher = createEventDispatcher(id);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id);
SsMediaPeriod period = new SsMediaPeriod(manifest, chunkSourceFactory, mediaTransferListener, compositeSequenceableLoaderFactory, drmSessionManager, drmEventDispatcher, loadErrorHandlingPolicy, mediaSourceEventDispatcher, manifestLoaderErrorThrower, allocator);
mediaPeriods.add(period);
return period;
}
use of androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy in project media by androidx.
the class DashMediaPeriod method buildSampleStream.
private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackGroupInfo trackGroupInfo, ExoTrackSelection selection, long positionUs) {
int embeddedTrackCount = 0;
boolean enableEventMessageTrack = trackGroupInfo.embeddedEventMessageTrackGroupIndex != C.INDEX_UNSET;
TrackGroup embeddedEventMessageTrackGroup = null;
if (enableEventMessageTrack) {
embeddedEventMessageTrackGroup = trackGroups.get(trackGroupInfo.embeddedEventMessageTrackGroupIndex);
embeddedTrackCount++;
}
boolean enableClosedCaptionTrack = trackGroupInfo.embeddedClosedCaptionTrackGroupIndex != C.INDEX_UNSET;
TrackGroup embeddedClosedCaptionTrackGroup = null;
if (enableClosedCaptionTrack) {
embeddedClosedCaptionTrackGroup = trackGroups.get(trackGroupInfo.embeddedClosedCaptionTrackGroupIndex);
embeddedTrackCount += embeddedClosedCaptionTrackGroup.length;
}
Format[] embeddedTrackFormats = new Format[embeddedTrackCount];
int[] embeddedTrackTypes = new int[embeddedTrackCount];
embeddedTrackCount = 0;
if (enableEventMessageTrack) {
embeddedTrackFormats[embeddedTrackCount] = embeddedEventMessageTrackGroup.getFormat(0);
embeddedTrackTypes[embeddedTrackCount] = C.TRACK_TYPE_METADATA;
embeddedTrackCount++;
}
List<Format> embeddedClosedCaptionTrackFormats = new ArrayList<>();
if (enableClosedCaptionTrack) {
for (int i = 0; i < embeddedClosedCaptionTrackGroup.length; i++) {
embeddedTrackFormats[embeddedTrackCount] = embeddedClosedCaptionTrackGroup.getFormat(i);
embeddedTrackTypes[embeddedTrackCount] = C.TRACK_TYPE_TEXT;
embeddedClosedCaptionTrackFormats.add(embeddedTrackFormats[embeddedTrackCount]);
embeddedTrackCount++;
}
}
PlayerTrackEmsgHandler trackPlayerEmsgHandler = manifest.dynamic && enableEventMessageTrack ? playerEmsgHandler.newPlayerTrackEmsgHandler() : null;
DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource(manifestLoaderErrorThrower, manifest, baseUrlExclusionList, periodIndex, trackGroupInfo.adaptationSetIndices, selection, trackGroupInfo.trackType, elapsedRealtimeOffsetMs, enableEventMessageTrack, embeddedClosedCaptionTrackFormats, trackPlayerEmsgHandler, transferListener, playerId);
ChunkSampleStream<DashChunkSource> stream = new ChunkSampleStream<>(trackGroupInfo.trackType, embeddedTrackTypes, embeddedTrackFormats, chunkSource, this, allocator, positionUs, drmSessionManager, drmEventDispatcher, loadErrorHandlingPolicy, mediaSourceEventDispatcher);
synchronized (this) {
// The map is also accessed on the loading thread so synchronize access.
trackEmsgHandlerBySampleStream.put(stream, trackPlayerEmsgHandler);
}
return stream;
}
Aggregations