use of com.google.android.exoplayer2.ExoPlaybackException in project ExoPlayer by google.
the class LibvpxVideoRenderer method render.
@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
if (outputStreamEnded) {
return;
}
if (format == null) {
// We don't have a format yet, so try and read one.
flagsOnlyBuffer.clear();
int result = readSource(formatHolder, flagsOnlyBuffer, true);
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder.format);
} else if (result == C.RESULT_BUFFER_READ) {
// End of stream read having not read a format.
Assertions.checkState(flagsOnlyBuffer.isEndOfStream());
inputStreamEnded = true;
outputStreamEnded = true;
return;
} else {
// We still don't have a format and can't make progress without one.
return;
}
}
if (isRendererAvailable()) {
drmSession = pendingDrmSession;
ExoMediaCrypto mediaCrypto = null;
if (drmSession != null) {
int drmSessionState = drmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
} else if (drmSessionState == DrmSession.STATE_OPENED || drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
mediaCrypto = drmSession.getMediaCrypto();
} else {
// The drm session isn't open yet.
return;
}
}
try {
if (decoder == null) {
// If we don't have a decoder yet, we need to instantiate one.
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createVpxDecoder");
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, mediaCrypto);
decoder.setOutputMode(outputMode);
TraceUtil.endSection();
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp);
decoderCounters.decoderInitCount++;
}
TraceUtil.beginSection("drainAndFeed");
while (drainOutputBuffer(positionUs)) {
}
while (feedInputBuffer()) {
}
TraceUtil.endSection();
} catch (VpxDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
}
} else {
skipToKeyframeBefore(positionUs);
}
decoderCounters.ensureUpdated();
}
use of com.google.android.exoplayer2.ExoPlaybackException in project ExoPlayer by google.
the class PlayerActivity method onPlayerError.
@Override
public void onPlayerError(ExoPlaybackException e) {
String errorString = null;
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
Exception cause = e.getRendererException();
if (cause instanceof DecoderInitializationException) {
// Special case for decoder initialization failures.
DecoderInitializationException decoderInitializationException = (DecoderInitializationException) cause;
if (decoderInitializationException.decoderName == null) {
if (decoderInitializationException.getCause() instanceof DecoderQueryException) {
errorString = getString(R.string.error_querying_decoders);
} else if (decoderInitializationException.secureDecoderRequired) {
errorString = getString(R.string.error_no_secure_decoder, decoderInitializationException.mimeType);
} else {
errorString = getString(R.string.error_no_decoder, decoderInitializationException.mimeType);
}
} else {
errorString = getString(R.string.error_instantiating_decoder, decoderInitializationException.decoderName);
}
}
}
if (errorString != null) {
showToast(errorString);
}
needRetrySource = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
initializePlayer();
} else {
updateResumePosition();
updateButtonVisibilities();
showControls();
}
}
use of com.google.android.exoplayer2.ExoPlaybackException in project ExoPlayer by google.
the class DefaultTrackSelector method selectAdaptiveVideoTrack.
private static TrackSelection selectAdaptiveVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveVideoTrackSelectionFactory) throws ExoPlaybackException {
int requiredAdaptiveSupport = allowNonSeamlessAdaptiveness ? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS) : RendererCapabilities.ADAPTIVE_SEAMLESS;
boolean allowMixedMimeTypes = allowMixedMimeAdaptiveness && (rendererCapabilities.supportsMixedMimeTypeAdaptation() & requiredAdaptiveSupport) != 0;
for (int i = 0; i < groups.length; i++) {
TrackGroup group = groups.get(i);
int[] adaptiveTracks = getAdaptiveTracksForGroup(group, formatSupport[i], allowMixedMimeTypes, requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange);
if (adaptiveTracks.length > 0) {
return adaptiveVideoTrackSelectionFactory.createTrackSelection(group, adaptiveTracks);
}
}
return null;
}
use of com.google.android.exoplayer2.ExoPlaybackException in project ExoPlayer by google.
the class MappingTrackSelector method selectTracks.
// TrackSelector implementation.
@Override
public final TrackSelectorResult selectTracks(RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups) throws ExoPlaybackException {
// Structures into which data will be written during the selection. The extra item at the end
// of each array is to store data associated with track groups that cannot be associated with
// any renderer.
int[] rendererTrackGroupCounts = new int[rendererCapabilities.length + 1];
TrackGroup[][] rendererTrackGroups = new TrackGroup[rendererCapabilities.length + 1][];
int[][][] rendererFormatSupports = new int[rendererCapabilities.length + 1][][];
for (int i = 0; i < rendererTrackGroups.length; i++) {
rendererTrackGroups[i] = new TrackGroup[trackGroups.length];
rendererFormatSupports[i] = new int[trackGroups.length][];
}
// Determine the extent to which each renderer supports mixed mimeType adaptation.
int[] mixedMimeTypeAdaptationSupport = getMixedMimeTypeAdaptationSupport(rendererCapabilities);
// renderer provides for each track in the group.
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
TrackGroup group = trackGroups.get(groupIndex);
// Associate the group to a preferred renderer.
int rendererIndex = findRenderer(rendererCapabilities, group);
// Evaluate the support that the renderer provides for each track in the group.
int[] rendererFormatSupport = rendererIndex == rendererCapabilities.length ? new int[group.length] : getFormatSupport(rendererCapabilities[rendererIndex], group);
// Stash the results.
int rendererTrackGroupCount = rendererTrackGroupCounts[rendererIndex];
rendererTrackGroups[rendererIndex][rendererTrackGroupCount] = group;
rendererFormatSupports[rendererIndex][rendererTrackGroupCount] = rendererFormatSupport;
rendererTrackGroupCounts[rendererIndex]++;
}
// Create a track group array for each renderer, and trim each rendererFormatSupports entry.
TrackGroupArray[] rendererTrackGroupArrays = new TrackGroupArray[rendererCapabilities.length];
int[] rendererTrackTypes = new int[rendererCapabilities.length];
for (int i = 0; i < rendererCapabilities.length; i++) {
int rendererTrackGroupCount = rendererTrackGroupCounts[i];
rendererTrackGroupArrays[i] = new TrackGroupArray(Arrays.copyOf(rendererTrackGroups[i], rendererTrackGroupCount));
rendererFormatSupports[i] = Arrays.copyOf(rendererFormatSupports[i], rendererTrackGroupCount);
rendererTrackTypes[i] = rendererCapabilities[i].getTrackType();
}
// Create a track group array for track groups not associated with a renderer.
int unassociatedTrackGroupCount = rendererTrackGroupCounts[rendererCapabilities.length];
TrackGroupArray unassociatedTrackGroupArray = new TrackGroupArray(Arrays.copyOf(rendererTrackGroups[rendererCapabilities.length], unassociatedTrackGroupCount));
TrackSelection[] trackSelections = selectTracks(rendererCapabilities, rendererTrackGroupArrays, rendererFormatSupports);
// Apply track disabling and overriding.
for (int i = 0; i < rendererCapabilities.length; i++) {
if (rendererDisabledFlags.get(i)) {
trackSelections[i] = null;
} else {
TrackGroupArray rendererTrackGroup = rendererTrackGroupArrays[i];
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(i);
SelectionOverride override = overrides == null ? null : overrides.get(rendererTrackGroup);
if (override != null) {
trackSelections[i] = override.createTrackSelection(rendererTrackGroup);
}
}
}
// Package up the track information and selections.
MappedTrackInfo mappedTrackInfo = new MappedTrackInfo(rendererTrackTypes, rendererTrackGroupArrays, mixedMimeTypeAdaptationSupport, rendererFormatSupports, unassociatedTrackGroupArray);
// Initialize the renderer configurations to the default configuration for all renderers with
// selections, and null otherwise.
RendererConfiguration[] rendererConfigurations = new RendererConfiguration[rendererCapabilities.length];
for (int i = 0; i < rendererCapabilities.length; i++) {
rendererConfigurations[i] = trackSelections[i] != null ? RendererConfiguration.DEFAULT : null;
}
// Configure audio and video renderers to use tunneling if appropriate.
maybeConfigureRenderersForTunneling(rendererCapabilities, rendererTrackGroupArrays, rendererFormatSupports, rendererConfigurations, trackSelections, tunnelingAudioSessionId);
return new TrackSelectorResult(trackGroups, new TrackSelectionArray(trackSelections), mappedTrackInfo, rendererConfigurations);
}
use of com.google.android.exoplayer2.ExoPlaybackException in project ExoPlayer by google.
the class MappingTrackSelector method findRenderer.
/**
* Finds the renderer to which the provided {@link TrackGroup} should be associated.
* <p>
* A {@link TrackGroup} is associated to a renderer that reports
* {@link RendererCapabilities#FORMAT_HANDLED} support for one or more of the tracks in the group,
* or {@link RendererCapabilities#FORMAT_EXCEEDS_CAPABILITIES} if no such renderer exists, or
* {@link RendererCapabilities#FORMAT_UNSUPPORTED_SUBTYPE} if again no such renderer exists. In
* the case that two or more renderers report the same level of support, the renderer with the
* lowest index is associated.
* <p>
* If all renderers report {@link RendererCapabilities#FORMAT_UNSUPPORTED_TYPE} for all of the
* tracks in the group, then {@code renderers.length} is returned to indicate that no association
* was made.
*
* @param rendererCapabilities The {@link RendererCapabilities} of the renderers.
* @param group The {@link TrackGroup} whose associated renderer is to be found.
* @return The index of the associated renderer, or {@code renderers.length} if no
* association was made.
* @throws ExoPlaybackException If an error occurs finding a renderer.
*/
private static int findRenderer(RendererCapabilities[] rendererCapabilities, TrackGroup group) throws ExoPlaybackException {
int bestRendererIndex = rendererCapabilities.length;
int bestFormatSupportLevel = RendererCapabilities.FORMAT_UNSUPPORTED_TYPE;
for (int rendererIndex = 0; rendererIndex < rendererCapabilities.length; rendererIndex++) {
RendererCapabilities rendererCapability = rendererCapabilities[rendererIndex];
for (int trackIndex = 0; trackIndex < group.length; trackIndex++) {
int formatSupportLevel = rendererCapability.supportsFormat(group.getFormat(trackIndex)) & RendererCapabilities.FORMAT_SUPPORT_MASK;
if (formatSupportLevel > bestFormatSupportLevel) {
bestRendererIndex = rendererIndex;
bestFormatSupportLevel = formatSupportLevel;
if (bestFormatSupportLevel == RendererCapabilities.FORMAT_HANDLED) {
// We can't do better.
return bestRendererIndex;
}
}
}
}
return bestRendererIndex;
}
Aggregations