Search in sources :

Example 31 with Assertions.checkState

use of com.google.android.exoplayer2.util.Assertions.checkState in project ExoPlayer by google.

the class CronetDataSource method open.

@Override
public long open(DataSpec dataSpec) throws HttpDataSourceException {
    Assertions.checkNotNull(dataSpec);
    Assertions.checkState(!opened);
    operation.close();
    resetConnectTimeout();
    currentDataSpec = dataSpec;
    UrlRequest urlRequest;
    try {
        urlRequest = buildRequestBuilder(dataSpec).build();
        currentUrlRequest = urlRequest;
    } catch (IOException e) {
        if (e instanceof HttpDataSourceException) {
            throw (HttpDataSourceException) e;
        } else {
            throw new OpenException(e, dataSpec, PlaybackException.ERROR_CODE_IO_UNSPECIFIED, Status.IDLE);
        }
    }
    urlRequest.start();
    transferInitializing(dataSpec);
    try {
        boolean connectionOpened = blockUntilConnectTimeout();
        @Nullable IOException connectionOpenException = exception;
        if (connectionOpenException != null) {
            @Nullable String message = connectionOpenException.getMessage();
            if (message != null && Ascii.toLowerCase(message).contains("err_cleartext_not_permitted")) {
                throw new CleartextNotPermittedException(connectionOpenException, dataSpec);
            }
            throw new OpenException(connectionOpenException, dataSpec, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, getStatus(urlRequest));
        } else if (!connectionOpened) {
            // The timeout was reached before the connection was opened.
            throw new OpenException(new SocketTimeoutException(), dataSpec, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT, getStatus(urlRequest));
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        // is failing to swallow the interruption, which makes us enter an invalid state.
        throw new OpenException(new InterruptedIOException(), dataSpec, PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK, Status.INVALID);
    }
    // Check for a valid response code.
    UrlResponseInfo responseInfo = Assertions.checkNotNull(this.responseInfo);
    int responseCode = responseInfo.getHttpStatusCode();
    Map<String, List<String>> responseHeaders = responseInfo.getAllHeaders();
    if (responseCode < 200 || responseCode > 299) {
        if (responseCode == 416) {
            long documentSize = HttpUtil.getDocumentSize(getFirstHeader(responseHeaders, HttpHeaders.CONTENT_RANGE));
            if (dataSpec.position == documentSize) {
                opened = true;
                transferStarted(dataSpec);
                return dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : 0;
            }
        }
        byte[] responseBody;
        try {
            responseBody = readResponseBody();
        } catch (IOException e) {
            responseBody = Util.EMPTY_BYTE_ARRAY;
        }
        @Nullable IOException cause = responseCode == 416 ? new DataSourceException(PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE) : null;
        throw new InvalidResponseCodeException(responseCode, responseInfo.getHttpStatusText(), cause, responseHeaders, dataSpec, responseBody);
    }
    // Check for a valid content type.
    Predicate<String> contentTypePredicate = this.contentTypePredicate;
    if (contentTypePredicate != null) {
        @Nullable String contentType = getFirstHeader(responseHeaders, HttpHeaders.CONTENT_TYPE);
        if (contentType != null && !contentTypePredicate.apply(contentType)) {
            throw new InvalidContentTypeException(contentType, dataSpec);
        }
    }
    // If we requested a range starting from a non-zero position and received a 200 rather than a
    // 206, then the server does not support partial requests. We'll need to manually skip to the
    // requested position.
    long bytesToSkip = responseCode == 200 && dataSpec.position != 0 ? dataSpec.position : 0;
    // Calculate the content length.
    if (!isCompressed(responseInfo)) {
        if (dataSpec.length != C.LENGTH_UNSET) {
            bytesRemaining = dataSpec.length;
        } else {
            long contentLength = HttpUtil.getContentLength(getFirstHeader(responseHeaders, HttpHeaders.CONTENT_LENGTH), getFirstHeader(responseHeaders, HttpHeaders.CONTENT_RANGE));
            bytesRemaining = contentLength != C.LENGTH_UNSET ? (contentLength - bytesToSkip) : C.LENGTH_UNSET;
        }
    } else {
        // If the response is compressed then the content length will be that of the compressed data
        // which isn't what we want. Always use the dataSpec length in this case.
        bytesRemaining = dataSpec.length;
    }
    opened = true;
    transferStarted(dataSpec);
    skipFully(bytesToSkip, dataSpec);
    return bytesRemaining;
}
Also used : InterruptedIOException(java.io.InterruptedIOException) UrlRequest(org.chromium.net.UrlRequest) UrlResponseInfo(org.chromium.net.UrlResponseInfo) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) SocketTimeoutException(java.net.SocketTimeoutException) DataSourceException(com.google.android.exoplayer2.upstream.DataSourceException) List(java.util.List) Nullable(androidx.annotation.Nullable)

Example 32 with Assertions.checkState

use of com.google.android.exoplayer2.util.Assertions.checkState in project ExoPlayer by google.

the class MediaCodecRenderer method onInputFormatChanged.

/**
 * Called when a new {@link Format} is read from the upstream {@link MediaPeriod}.
 *
 * @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
 * @throws ExoPlaybackException If an error occurs re-initializing the {@link MediaCodec}.
 * @return The result of the evaluation to determine whether the existing decoder instance can be
 *     reused for the new format, or {@code null} if the renderer did not have a decoder.
 */
@CallSuper
@Nullable
protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
    waitingForFirstSampleInFormat = true;
    Format newFormat = checkNotNull(formatHolder.format);
    if (newFormat.sampleMimeType == null) {
        throw createRendererException(new IllegalArgumentException(), newFormat, PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
    }
    setSourceDrmSession(formatHolder.drmSession);
    inputFormat = newFormat;
    if (bypassEnabled) {
        bypassDrainAndReinitialize = true;
        // Need to drain batch buffer first.
        return null;
    }
    if (codec == null) {
        availableCodecInfos = null;
        maybeInitCodecOrBypass();
        return null;
    }
    // We have an existing codec that we may need to reconfigure, re-initialize, or release to
    // switch to bypass. If the existing codec instance is kept then its operating rate and DRM
    // session may need to be updated.
    // Copy the current codec and codecInfo to local variables so they remain accessible if the
    // member variables are updated during the logic below.
    MediaCodecAdapter codec = this.codec;
    MediaCodecInfo codecInfo = this.codecInfo;
    Format oldFormat = codecInputFormat;
    if (drmNeedsCodecReinitialization(codecInfo, newFormat, codecDrmSession, sourceDrmSession)) {
        drainAndReinitializeCodec();
        return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, REUSE_RESULT_NO, DISCARD_REASON_DRM_SESSION_CHANGED);
    }
    boolean drainAndUpdateCodecDrmSession = sourceDrmSession != codecDrmSession;
    Assertions.checkState(!drainAndUpdateCodecDrmSession || Util.SDK_INT >= 23);
    DecoderReuseEvaluation evaluation = canReuseCodec(codecInfo, oldFormat, newFormat);
    @DecoderDiscardReasons int overridingDiscardReasons = 0;
    switch(evaluation.result) {
        case REUSE_RESULT_NO:
            drainAndReinitializeCodec();
            break;
        case REUSE_RESULT_YES_WITH_FLUSH:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession) {
                    if (!drainAndUpdateCodecDrmSessionV23()) {
                        overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                    }
                } else if (!drainAndFlushCodec()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        case REUSE_RESULT_YES_WITH_RECONFIGURATION:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecReconfigured = true;
                codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
                codecNeedsAdaptationWorkaroundBuffer = codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_ALWAYS || (codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION && newFormat.width == oldFormat.width && newFormat.height == oldFormat.height);
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession && !drainAndUpdateCodecDrmSessionV23()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        case REUSE_RESULT_YES_WITHOUT_RECONFIGURATION:
            if (!updateCodecOperatingRate(newFormat)) {
                overridingDiscardReasons |= DISCARD_REASON_OPERATING_RATE_CHANGED;
            } else {
                codecInputFormat = newFormat;
                if (drainAndUpdateCodecDrmSession && !drainAndUpdateCodecDrmSessionV23()) {
                    overridingDiscardReasons |= DISCARD_REASON_WORKAROUND;
                }
            }
            break;
        default:
            // Never happens.
            throw new IllegalStateException();
    }
    if (evaluation.result != REUSE_RESULT_NO && (this.codec != codec || codecDrainAction == DRAIN_ACTION_REINITIALIZE)) {
        // The reasons are indicated by overridingDiscardReasons.
        return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, REUSE_RESULT_NO, overridingDiscardReasons);
    }
    return evaluation;
}
Also used : Format(com.google.android.exoplayer2.Format) MediaFormat(android.media.MediaFormat) DecoderReuseEvaluation(com.google.android.exoplayer2.decoder.DecoderReuseEvaluation) DecoderDiscardReasons(com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DecoderDiscardReasons) CallSuper(androidx.annotation.CallSuper) Nullable(androidx.annotation.Nullable)

Example 33 with Assertions.checkState

use of com.google.android.exoplayer2.util.Assertions.checkState in project ExoPlayer by google.

the class StyledPlayerView method setPlayer.

/**
 * Sets the {@link Player} to use.
 *
 * <p>To transition a {@link Player} from targeting one view to another, it's recommended to use
 * {@link #switchTargetView(Player, StyledPlayerView, StyledPlayerView)} rather than this method.
 * If you do wish to use this method directly, be sure to attach the player to the new view
 * <em>before</em> calling {@code setPlayer(null)} to detach it from the old one. This ordering is
 * significantly more efficient and may allow for more seamless transitions.
 *
 * @param player The {@link Player} to use, or {@code null} to detach the current player. Only
 *     players which are accessed on the main thread are supported ({@code
 *     player.getApplicationLooper() == Looper.getMainLooper()}).
 */
public void setPlayer(@Nullable Player player) {
    Assertions.checkState(Looper.myLooper() == Looper.getMainLooper());
    Assertions.checkArgument(player == null || player.getApplicationLooper() == Looper.getMainLooper());
    if (this.player == player) {
        return;
    }
    @Nullable Player oldPlayer = this.player;
    if (oldPlayer != null) {
        oldPlayer.removeListener(componentListener);
        if (surfaceView instanceof TextureView) {
            oldPlayer.clearVideoTextureView((TextureView) surfaceView);
        } else if (surfaceView instanceof SurfaceView) {
            oldPlayer.clearVideoSurfaceView((SurfaceView) surfaceView);
        }
    }
    if (subtitleView != null) {
        subtitleView.setCues(null);
    }
    this.player = player;
    if (useController()) {
        controller.setPlayer(player);
    }
    updateBuffering();
    updateErrorMessage();
    updateForCurrentTrackSelections(/* isNewPlayer= */
    true);
    if (player != null) {
        if (player.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)) {
            if (surfaceView instanceof TextureView) {
                player.setVideoTextureView((TextureView) surfaceView);
            } else if (surfaceView instanceof SurfaceView) {
                player.setVideoSurfaceView((SurfaceView) surfaceView);
            }
            updateAspectRatio();
        }
        if (subtitleView != null && player.isCommandAvailable(COMMAND_GET_TEXT)) {
            subtitleView.setCues(player.getCurrentCues());
        }
        player.addListener(componentListener);
        maybeShowController(false);
    } else {
        hideController();
    }
}
Also used : Player(com.google.android.exoplayer2.Player) TextureView(android.view.TextureView) Nullable(androidx.annotation.Nullable) SurfaceView(android.view.SurfaceView) GLSurfaceView(android.opengl.GLSurfaceView)

Example 34 with Assertions.checkState

use of com.google.android.exoplayer2.util.Assertions.checkState in project ExoPlayer by google.

the class PlayerControlView method updateTimeline.

private void updateTimeline() {
    @Nullable Player player = this.player;
    if (player == null) {
        return;
    }
    multiWindowTimeBar = showMultiWindowTimeBar && canShowMultiWindowTimeBar(player.getCurrentTimeline(), window);
    currentWindowOffset = 0;
    long durationUs = 0;
    int adGroupCount = 0;
    Timeline timeline = player.getCurrentTimeline();
    if (!timeline.isEmpty()) {
        int currentWindowIndex = player.getCurrentMediaItemIndex();
        int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
        int lastWindowIndex = multiWindowTimeBar ? timeline.getWindowCount() - 1 : currentWindowIndex;
        for (int i = firstWindowIndex; i <= lastWindowIndex; i++) {
            if (i == currentWindowIndex) {
                currentWindowOffset = Util.usToMs(durationUs);
            }
            timeline.getWindow(i, window);
            if (window.durationUs == C.TIME_UNSET) {
                Assertions.checkState(!multiWindowTimeBar);
                break;
            }
            for (int j = window.firstPeriodIndex; j <= window.lastPeriodIndex; j++) {
                timeline.getPeriod(j, period);
                int removedGroups = period.getRemovedAdGroupCount();
                int totalGroups = period.getAdGroupCount();
                for (int adGroupIndex = removedGroups; adGroupIndex < totalGroups; adGroupIndex++) {
                    long adGroupTimeInPeriodUs = period.getAdGroupTimeUs(adGroupIndex);
                    if (adGroupTimeInPeriodUs == C.TIME_END_OF_SOURCE) {
                        if (period.durationUs == C.TIME_UNSET) {
                            // Don't show ad markers for postrolls in periods with unknown duration.
                            continue;
                        }
                        adGroupTimeInPeriodUs = period.durationUs;
                    }
                    long adGroupTimeInWindowUs = adGroupTimeInPeriodUs + period.getPositionInWindowUs();
                    if (adGroupTimeInWindowUs >= 0) {
                        if (adGroupCount == adGroupTimesMs.length) {
                            int newLength = adGroupTimesMs.length == 0 ? 1 : adGroupTimesMs.length * 2;
                            adGroupTimesMs = Arrays.copyOf(adGroupTimesMs, newLength);
                            playedAdGroups = Arrays.copyOf(playedAdGroups, newLength);
                        }
                        adGroupTimesMs[adGroupCount] = Util.usToMs(durationUs + adGroupTimeInWindowUs);
                        playedAdGroups[adGroupCount] = period.hasPlayedAdGroup(adGroupIndex);
                        adGroupCount++;
                    }
                }
            }
            durationUs += window.durationUs;
        }
    }
    long durationMs = Util.usToMs(durationUs);
    if (durationView != null) {
        durationView.setText(Util.getStringForTime(formatBuilder, formatter, durationMs));
    }
    if (timeBar != null) {
        timeBar.setDuration(durationMs);
        int extraAdGroupCount = extraAdGroupTimesMs.length;
        int totalAdGroupCount = adGroupCount + extraAdGroupCount;
        if (totalAdGroupCount > adGroupTimesMs.length) {
            adGroupTimesMs = Arrays.copyOf(adGroupTimesMs, totalAdGroupCount);
            playedAdGroups = Arrays.copyOf(playedAdGroups, totalAdGroupCount);
        }
        System.arraycopy(extraAdGroupTimesMs, 0, adGroupTimesMs, adGroupCount, extraAdGroupCount);
        System.arraycopy(extraPlayedAdGroups, 0, playedAdGroups, adGroupCount, extraAdGroupCount);
        timeBar.setAdGroupTimesMs(adGroupTimesMs, playedAdGroups, totalAdGroupCount);
    }
    updateProgress();
}
Also used : Player(com.google.android.exoplayer2.Player) Timeline(com.google.android.exoplayer2.Timeline) Nullable(androidx.annotation.Nullable) SuppressLint(android.annotation.SuppressLint)

Example 35 with Assertions.checkState

use of com.google.android.exoplayer2.util.Assertions.checkState in project ExoPlayer by google.

the class StyledPlayerControlView method updateTimeline.

private void updateTimeline() {
    @Nullable Player player = this.player;
    if (player == null) {
        return;
    }
    multiWindowTimeBar = showMultiWindowTimeBar && canShowMultiWindowTimeBar(player.getCurrentTimeline(), window);
    currentWindowOffset = 0;
    long durationUs = 0;
    int adGroupCount = 0;
    Timeline timeline = player.getCurrentTimeline();
    if (!timeline.isEmpty()) {
        int currentWindowIndex = player.getCurrentMediaItemIndex();
        int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
        int lastWindowIndex = multiWindowTimeBar ? timeline.getWindowCount() - 1 : currentWindowIndex;
        for (int i = firstWindowIndex; i <= lastWindowIndex; i++) {
            if (i == currentWindowIndex) {
                currentWindowOffset = Util.usToMs(durationUs);
            }
            timeline.getWindow(i, window);
            if (window.durationUs == C.TIME_UNSET) {
                Assertions.checkState(!multiWindowTimeBar);
                break;
            }
            for (int j = window.firstPeriodIndex; j <= window.lastPeriodIndex; j++) {
                timeline.getPeriod(j, period);
                int removedGroups = period.getRemovedAdGroupCount();
                int totalGroups = period.getAdGroupCount();
                for (int adGroupIndex = removedGroups; adGroupIndex < totalGroups; adGroupIndex++) {
                    long adGroupTimeInPeriodUs = period.getAdGroupTimeUs(adGroupIndex);
                    if (adGroupTimeInPeriodUs == C.TIME_END_OF_SOURCE) {
                        if (period.durationUs == C.TIME_UNSET) {
                            // Don't show ad markers for postrolls in periods with unknown duration.
                            continue;
                        }
                        adGroupTimeInPeriodUs = period.durationUs;
                    }
                    long adGroupTimeInWindowUs = adGroupTimeInPeriodUs + period.getPositionInWindowUs();
                    if (adGroupTimeInWindowUs >= 0) {
                        if (adGroupCount == adGroupTimesMs.length) {
                            int newLength = adGroupTimesMs.length == 0 ? 1 : adGroupTimesMs.length * 2;
                            adGroupTimesMs = Arrays.copyOf(adGroupTimesMs, newLength);
                            playedAdGroups = Arrays.copyOf(playedAdGroups, newLength);
                        }
                        adGroupTimesMs[adGroupCount] = Util.usToMs(durationUs + adGroupTimeInWindowUs);
                        playedAdGroups[adGroupCount] = period.hasPlayedAdGroup(adGroupIndex);
                        adGroupCount++;
                    }
                }
            }
            durationUs += window.durationUs;
        }
    }
    long durationMs = Util.usToMs(durationUs);
    if (durationView != null) {
        durationView.setText(Util.getStringForTime(formatBuilder, formatter, durationMs));
    }
    if (timeBar != null) {
        timeBar.setDuration(durationMs);
        int extraAdGroupCount = extraAdGroupTimesMs.length;
        int totalAdGroupCount = adGroupCount + extraAdGroupCount;
        if (totalAdGroupCount > adGroupTimesMs.length) {
            adGroupTimesMs = Arrays.copyOf(adGroupTimesMs, totalAdGroupCount);
            playedAdGroups = Arrays.copyOf(playedAdGroups, totalAdGroupCount);
        }
        System.arraycopy(extraAdGroupTimesMs, 0, adGroupTimesMs, adGroupCount, extraAdGroupCount);
        System.arraycopy(extraPlayedAdGroups, 0, playedAdGroups, adGroupCount, extraAdGroupCount);
        timeBar.setAdGroupTimesMs(adGroupTimesMs, playedAdGroups, totalAdGroupCount);
    }
    updateProgress();
}
Also used : Player(com.google.android.exoplayer2.Player) ForwardingPlayer(com.google.android.exoplayer2.ForwardingPlayer) Timeline(com.google.android.exoplayer2.Timeline) Nullable(androidx.annotation.Nullable) SuppressLint(android.annotation.SuppressLint)

Aggregations

Nullable (androidx.annotation.Nullable)12 Format (com.google.android.exoplayer2.Format)4 Player (com.google.android.exoplayer2.Player)4 FormatHolder (com.google.android.exoplayer2.FormatHolder)3 Timeline (com.google.android.exoplayer2.Timeline)3 LoadEventInfo (com.google.android.exoplayer2.source.LoadEventInfo)3 ReadDataResult (com.google.android.exoplayer2.source.SampleStream.ReadDataResult)3 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)3 Segment (com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment)3 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)3 TrackSelection (com.google.android.exoplayer2.trackselection.TrackSelection)3 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)3 SuppressLint (android.annotation.SuppressLint)2 Uri (android.net.Uri)2 GLSurfaceView (android.opengl.GLSurfaceView)2 SurfaceView (android.view.SurfaceView)2 TextureView (android.view.TextureView)2 DecoderException (com.google.android.exoplayer2.decoder.DecoderException)2 SchemeData (com.google.android.exoplayer2.drm.DrmInitData.SchemeData)2 Extractor (com.google.android.exoplayer2.extractor.Extractor)2