mirror of
https://github.com/samsonjs/media.git
synced 2026-03-31 10:25:48 +00:00
Enable seamless rejoing for Vp9 extension.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=123982330
This commit is contained in:
parent
afa1ad1a6a
commit
c622483f79
3 changed files with 60 additions and 24 deletions
|
|
@ -88,7 +88,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
|||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
LibvpxVideoTrackRenderer videoRenderer = new LibvpxVideoTrackRenderer(true);
|
||||
LibvpxVideoTrackRenderer videoRenderer = new LibvpxVideoTrackRenderer(true, 0);
|
||||
DefaultTrackSelector trackSelector = new DefaultTrackSelector(
|
||||
new DefaultTrackSelectionPolicy(), null);
|
||||
player = ExoPlayerFactory.newInstance(new TrackRenderer[] {videoRenderer}, trackSelector);
|
||||
|
|
|
|||
|
|
@ -58,8 +58,9 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
public final CodecCounters codecCounters = new CodecCounters();
|
||||
|
||||
private final boolean scaleToFit;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final long allowedJoiningTimeMs;
|
||||
private final int maxDroppedFrameCountToNotify;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final FormatHolder formatHolder;
|
||||
|
||||
private Format format;
|
||||
|
|
@ -71,6 +72,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
private Bitmap bitmap;
|
||||
private boolean drawnToSurface;
|
||||
private boolean renderedFirstFrame;
|
||||
private long joiningDeadlineMs;
|
||||
private Surface surface;
|
||||
private VpxOutputBufferRenderer outputBufferRenderer;
|
||||
private int outputMode;
|
||||
|
|
@ -85,26 +87,31 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
private int consecutiveDroppedFrameCount;
|
||||
|
||||
/**
|
||||
* @param scaleToFit Boolean that indicates if video frames should be scaled to fit when
|
||||
* rendering.
|
||||
* @param scaleToFit Whether video frames should be scaled to fit when rendering.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
*/
|
||||
public LibvpxVideoTrackRenderer(boolean scaleToFit) {
|
||||
this(scaleToFit, null, null, 0);
|
||||
public LibvpxVideoTrackRenderer(boolean scaleToFit, long allowedJoiningTimeMs) {
|
||||
this(scaleToFit, allowedJoiningTimeMs, null, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scaleToFit Boolean that indicates if video frames should be scaled to fit when
|
||||
* rendering.
|
||||
* @param scaleToFit Whether video frames should be scaled to fit when rendering.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param maxDroppedFrameCountToNotify The maximum number of frames that can be dropped between
|
||||
* invocations of {@link VideoTrackRendererEventListener#onDroppedFrames(int, long)}.
|
||||
*/
|
||||
public LibvpxVideoTrackRenderer(boolean scaleToFit, Handler eventHandler,
|
||||
VideoTrackRendererEventListener eventListener, int maxDroppedFrameCountToNotify) {
|
||||
public LibvpxVideoTrackRenderer(boolean scaleToFit, long allowedJoiningTimeMs,
|
||||
Handler eventHandler, VideoTrackRendererEventListener eventListener,
|
||||
int maxDroppedFrameCountToNotify) {
|
||||
this.scaleToFit = scaleToFit;
|
||||
this.allowedJoiningTimeMs = allowedJoiningTimeMs;
|
||||
this.maxDroppedFrameCountToNotify = maxDroppedFrameCountToNotify;
|
||||
joiningDeadlineMs = -1;
|
||||
previousWidth = -1;
|
||||
previousHeight = -1;
|
||||
formatHolder = new FormatHolder();
|
||||
|
|
@ -202,10 +209,11 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Drop frame only if we have the next frame and that's also late, otherwise render whatever we
|
||||
// have.
|
||||
if (nextOutputBuffer != null && nextOutputBuffer.timestampUs < positionUs) {
|
||||
// Drop frame if we are too late.
|
||||
// Drop the frame if we're joining and are more than 30ms late, or if we have the next frame
|
||||
// and that's also late. Else we'll render what we have.
|
||||
if ((joiningDeadlineMs != -1 && outputBuffer.timestampUs < positionUs - 30000)
|
||||
|| (nextOutputBuffer != null && !nextOutputBuffer.isEndOfStream()
|
||||
&& nextOutputBuffer.timestampUs < positionUs)) {
|
||||
codecCounters.droppedOutputBufferCount++;
|
||||
droppedFrameCount++;
|
||||
consecutiveDroppedFrameCount++;
|
||||
|
|
@ -322,7 +330,21 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
|
||||
@Override
|
||||
protected boolean isReady() {
|
||||
return format != null && (isSourceReady() || outputBuffer != null) && renderedFirstFrame;
|
||||
if (format != null && (isSourceReady() || outputBuffer != null) && renderedFirstFrame) {
|
||||
// Ready. If we were joining then we've now joined, so clear the joining deadline.
|
||||
joiningDeadlineMs = -1;
|
||||
return true;
|
||||
} else if (joiningDeadlineMs == -1) {
|
||||
// Not joining.
|
||||
return false;
|
||||
} else if (SystemClock.elapsedRealtime() < joiningDeadlineMs) {
|
||||
// Joining and still within the joining deadline.
|
||||
return true;
|
||||
} else {
|
||||
// The joining deadline has been exceeded. Give up and clear the deadline.
|
||||
joiningDeadlineMs = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -340,6 +362,8 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
if (decoder != null) {
|
||||
flushDecoder();
|
||||
}
|
||||
joiningDeadlineMs = joining && allowedJoiningTimeMs > 0
|
||||
? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -350,6 +374,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||
|
||||
@Override
|
||||
protected void onStopped() {
|
||||
joiningDeadlineMs = -1;
|
||||
maybeNotifyDroppedFrameCount();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
}
|
||||
|
||||
private static final String TAG = "SimpleExoPlayer";
|
||||
private static final long ALLOWED_VIDEO_JOINING_TIME_MS = 5000;
|
||||
private static final int MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY = 50;
|
||||
|
||||
private final ExoPlayer player;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
|
|
@ -381,8 +383,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
private void buildRenderers(Context context, DrmSessionManager drmSessionManager,
|
||||
ArrayList<TrackRenderer> renderersList) {
|
||||
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context,
|
||||
MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000,
|
||||
drmSessionManager, false, mainHandler, componentListener, 50);
|
||||
MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT,
|
||||
ALLOWED_VIDEO_JOINING_TIME_MS, drmSessionManager, false, mainHandler, componentListener,
|
||||
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
||||
renderersList.add(videoRenderer);
|
||||
|
||||
TrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(MediaCodecSelector.DEFAULT,
|
||||
|
|
@ -405,13 +408,15 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
try {
|
||||
Class<?> clazz =
|
||||
Class.forName("com.google.android.exoplayer.ext.vp9.LibvpxVideoTrackRenderer");
|
||||
Constructor<?> constructor = clazz.getConstructor(boolean.class, Handler.class,
|
||||
Constructor<?> constructor = clazz.getConstructor(boolean.class, long.class, Handler.class,
|
||||
VideoTrackRendererEventListener.class, int.class);
|
||||
renderersList.add((TrackRenderer) constructor.newInstance(true, mainHandler,
|
||||
componentListener, 50));
|
||||
renderersList.add((TrackRenderer) constructor.newInstance(true, ALLOWED_VIDEO_JOINING_TIME_MS,
|
||||
mainHandler, componentListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY));
|
||||
Log.i(TAG, "Loaded LibvpxVideoTrackRenderer.");
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Expected if the app was built without the extension.
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -421,8 +426,10 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
AudioTrackRendererEventListener.class);
|
||||
renderersList.add((TrackRenderer) constructor.newInstance(mainHandler, componentListener));
|
||||
Log.i(TAG, "Loaded LibopusAudioTrackRenderer.");
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Expected if the app was built without the extension.
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -432,8 +439,10 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
AudioTrackRendererEventListener.class);
|
||||
renderersList.add((TrackRenderer) constructor.newInstance(mainHandler, componentListener));
|
||||
Log.i(TAG, "Loaded LibflacAudioTrackRenderer.");
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Expected if the app was built without the extension.
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -443,8 +452,10 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
AudioTrackRendererEventListener.class);
|
||||
renderersList.add((TrackRenderer) constructor.newInstance(mainHandler, componentListener));
|
||||
Log.i(TAG, "Loaded FfmpegAudioTrackRenderer.");
|
||||
} catch (Exception e) {
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Expected if the app was built without the extension.
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue