Android AppRTCMobile: Transition local render to new VideoSink interface BUG=None Review-Url: https://codereview.webrtc.org/3016443002 Cr-Original-Commit-Position: refs/heads/master@{#19820} Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc Cr-Mirrored-Commit: 4e15e67da8072e8ce7b70c32df3c4be286363ab4
diff --git a/examples/androidapp/src/org/appspot/apprtc/CallActivity.java b/examples/androidapp/src/org/appspot/apprtc/CallActivity.java index 9c3347b..45bc26b 100644 --- a/examples/androidapp/src/org/appspot/apprtc/CallActivity.java +++ b/examples/androidapp/src/org/appspot/apprtc/CallActivity.java
@@ -56,7 +56,9 @@ import org.webrtc.SurfaceViewRenderer; import org.webrtc.VideoCapturer; import org.webrtc.VideoFileRenderer; +import org.webrtc.VideoFrame; import org.webrtc.VideoRenderer; +import org.webrtc.VideoSink; /** * Activity for peer connection call setup, call waiting @@ -137,9 +139,11 @@ // Peer connection statistics callback period in ms. private static final int STAT_CALLBACK_PERIOD = 1000; - private class ProxyRenderer implements VideoRenderer.Callbacks { - private VideoRenderer.Callbacks target; + private class ProxyRenderer<T extends VideoRenderer.Callbacks & VideoSink> + implements VideoRenderer.Callbacks, VideoSink { + private T target; + @Override synchronized public void renderFrame(VideoRenderer.I420Frame frame) { if (target == null) { Logging.d(TAG, "Dropping frame in proxy because target is null."); @@ -150,7 +154,17 @@ target.renderFrame(frame); } - synchronized public void setTarget(VideoRenderer.Callbacks target) { + @Override + synchronized public void onFrame(VideoFrame frame) { + if (target == null) { + Logging.d(TAG, "Dropping frame in proxy because target is null."); + return; + } + + target.onFrame(frame); + } + + synchronized public void setTarget(T target) { this.target = target; } }
diff --git a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java index c9c9a51..e40a17c 100644 --- a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java +++ b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
@@ -52,6 +52,7 @@ import org.webrtc.StatsReport; import org.webrtc.VideoCapturer; import org.webrtc.VideoRenderer; +import org.webrtc.VideoSink; import org.webrtc.VideoSource; import org.webrtc.VideoTrack; import org.webrtc.voiceengine.WebRtcAudioManager; @@ -123,7 +124,7 @@ private boolean videoCapturerStopped; private boolean isError; private Timer statsTimer; - private VideoRenderer.Callbacks localRender; + private VideoSink localRender; private List<VideoRenderer.Callbacks> remoteRenders; private SignalingParameters signalingParameters; private MediaConstraints pcConstraints; @@ -332,13 +333,13 @@ }); } - public void createPeerConnection(final VideoRenderer.Callbacks localRender, + public void createPeerConnection(final VideoSink localRender, final VideoRenderer.Callbacks remoteRender, final VideoCapturer videoCapturer, final SignalingParameters signalingParameters) { createPeerConnection( localRender, Collections.singletonList(remoteRender), videoCapturer, signalingParameters); } - public void createPeerConnection(final VideoRenderer.Callbacks localRender, + public void createPeerConnection(final VideoSink localRender, final List<VideoRenderer.Callbacks> remoteRenders, final VideoCapturer videoCapturer, final SignalingParameters signalingParameters) { if (peerConnectionParameters == null) { @@ -946,7 +947,7 @@ localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource); localVideoTrack.setEnabled(renderVideo); - localVideoTrack.addRenderer(new VideoRenderer(localRender)); + localVideoTrack.addSink(localRender); return localVideoTrack; }
diff --git a/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java b/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java index 08c0242..dda16ad 100644 --- a/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java +++ b/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java
@@ -42,7 +42,9 @@ import org.webrtc.SessionDescription; import org.webrtc.StatsReport; import org.webrtc.VideoCapturer; +import org.webrtc.VideoFrame; import org.webrtc.VideoRenderer; +import org.webrtc.VideoSink; @RunWith(BaseJUnit4ClassRunner.class) public class PeerConnectionClientTest implements PeerConnectionEvents { @@ -126,6 +128,49 @@ } } + // Mock VideoSink implementation. + private static class MockSink implements VideoSink { + // These are protected by 'this' since we gets called from worker threads. + private String rendererName; + private boolean renderFrameCalled = false; + + // Thread-safe in itself. + private CountDownLatch doneRendering; + + public MockSink(int expectedFrames, String rendererName) { + this.rendererName = rendererName; + reset(expectedFrames); + } + + // Resets render to wait for new amount of video frames. + public synchronized void reset(int expectedFrames) { + renderFrameCalled = false; + doneRendering = new CountDownLatch(expectedFrames); + } + + @Override + public synchronized void onFrame(VideoFrame frame) { + if (!renderFrameCalled) { + if (rendererName != null) { + Log.d(TAG, + rendererName + " render frame: " + frame.getRotatedWidth() + " x " + + frame.getRotatedHeight()); + } else { + Log.d(TAG, "Render frame: " + frame.getRotatedWidth() + " x " + frame.getRotatedHeight()); + } + } + renderFrameCalled = true; + doneRendering.countDown(); + } + + // This method shouldn't hold any locks or touch member variables since it + // blocks. + public boolean waitForFramesRendered(int timeoutMs) throws InterruptedException { + doneRendering.await(timeoutMs, TimeUnit.MILLISECONDS); + return (doneRendering.getCount() <= 0); + } + } + // Peer connection events implementation. @Override public void onLocalDescription(SessionDescription sdp) { @@ -236,7 +281,7 @@ } } - PeerConnectionClient createPeerConnectionClient(MockRenderer localRenderer, + PeerConnectionClient createPeerConnectionClient(MockSink localRenderer, MockRenderer remoteRenderer, PeerConnectionParameters peerConnectionParameters, VideoCapturer videoCapturer) { List<PeerConnection.IceServer> iceServers = new LinkedList<PeerConnection.IceServer>(); @@ -333,7 +378,7 @@ @SmallTest public void testSetLocalOfferMakesVideoFlowLocally() throws InterruptedException { Log.d(TAG, "testSetLocalOfferMakesVideoFlowLocally"); - MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); + MockSink localRenderer = new MockSink(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); pcClient = createPeerConnectionClient(localRenderer, new MockRenderer(0, null), createParametersForVideoCall(VIDEO_CODEC_VP8), createCameraCapturer(false /* captureToTexture */)); @@ -355,11 +400,11 @@ private void doLoopbackTest(PeerConnectionParameters parameters, VideoCapturer videoCapturer, boolean decodeToTexture) throws InterruptedException { loopback = true; - MockRenderer localRenderer = null; + MockSink localRenderer = null; MockRenderer remoteRenderer = null; if (parameters.videoCallEnabled) { Log.d(TAG, "testLoopback for video " + parameters.videoCodec); - localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); + localRenderer = new MockSink(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME); } else { Log.d(TAG, "testLoopback for audio."); @@ -494,7 +539,7 @@ Log.d(TAG, "testCameraSwitch"); loopback = true; - MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); + MockSink localRenderer = new MockSink(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME); pcClient = createPeerConnectionClient(localRenderer, remoteRenderer, @@ -542,7 +587,7 @@ Log.d(TAG, "testVideoSourceRestart"); loopback = true; - MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); + MockSink localRenderer = new MockSink(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME); pcClient = createPeerConnectionClient(localRenderer, remoteRenderer, @@ -591,7 +636,7 @@ Log.d(TAG, "testCaptureFormatChange"); loopback = true; - MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); + MockSink localRenderer = new MockSink(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME); pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,