@Override protected void onEnabled(int track, long positionUs, boolean joining) throws ExoPlaybackException { super.onEnabled(track, positionUs, joining); if (joining && allowedJoiningTimeUs > 0) { joiningDeadlineUs = SystemClock.elapsedRealtime() * 1000L + allowedJoiningTimeUs; } frameReleaseTimeHelper.enable(); }
@Override protected void onDisabled() throws ExoPlaybackException { currentWidth = -1; currentHeight = -1; currentPixelWidthHeightRatio = -1; pendingPixelWidthHeightRatio = -1; lastReportedWidth = -1; lastReportedHeight = -1; lastReportedPixelWidthHeightRatio = -1; frameReleaseTimeHelper.disable(); super.onDisabled(); }
@Override protected boolean processOutputBuffer( long positionUs, long elapsedRealtimeUs, MediaCodec codec, ByteBuffer buffer, MediaCodec.BufferInfo bufferInfo, int bufferIndex, boolean shouldSkip) { if (shouldSkip) { skipOutputBuffer(codec, bufferIndex); consecutiveDroppedFrameCount = 0; return true; } if (!renderedFirstFrame) { if (Util.SDK_INT >= 21) { renderOutputBufferV21(codec, bufferIndex, System.nanoTime()); } else { renderOutputBuffer(codec, bufferIndex); } consecutiveDroppedFrameCount = 0; return true; } if (getState() != TrackRenderer.STATE_STARTED) { return false; } // Compute how many microseconds it is until the buffer's presentation time. long elapsedSinceStartOfLoopUs = (SystemClock.elapsedRealtime() * 1000) - elapsedRealtimeUs; long earlyUs = bufferInfo.presentationTimeUs - positionUs - elapsedSinceStartOfLoopUs; // Compute the buffer's desired release time in nanoseconds. long systemTimeNs = System.nanoTime(); long unadjustedFrameReleaseTimeNs = systemTimeNs + (earlyUs * 1000); // Apply a timestamp adjustment, if there is one. long adjustedReleaseTimeNs = frameReleaseTimeHelper.adjustReleaseTime( bufferInfo.presentationTimeUs, unadjustedFrameReleaseTimeNs); earlyUs = (adjustedReleaseTimeNs - systemTimeNs) / 1000; if (earlyUs < -30000) { // We're more than 30ms late rendering the frame. dropOutputBuffer(codec, bufferIndex); return true; } if (Util.SDK_INT >= 21) { // Let the underlying framework time the release. if (earlyUs < 50000) { renderOutputBufferV21(codec, bufferIndex, adjustedReleaseTimeNs); consecutiveDroppedFrameCount = 0; return true; } } else { // We need to time the release ourselves. if (earlyUs < 30000) { if (earlyUs > 11000) { // We're a little too early to render the frame. Sleep until the frame can be rendered. // Note: The 11ms threshold was chosen fairly arbitrarily. try { // Subtracting 10000 rather than 11000 ensures the sleep time will be at least 1ms. Thread.sleep((earlyUs - 10000) / 1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } renderOutputBuffer(codec, bufferIndex); consecutiveDroppedFrameCount = 0; return true; } } // We're either not playing, or it's not time to render the frame yet. return false; }