Android AppRTCMobile: Transition local render to new VideoSink interface
BUG=None Review-Url: https://codereview.webrtc.org/3016443002 Cr-Commit-Position: refs/heads/master@{#19820}
This commit is contained in:
@ -56,7 +56,9 @@ import org.webrtc.StatsReport;
|
|||||||
import org.webrtc.SurfaceViewRenderer;
|
import org.webrtc.SurfaceViewRenderer;
|
||||||
import org.webrtc.VideoCapturer;
|
import org.webrtc.VideoCapturer;
|
||||||
import org.webrtc.VideoFileRenderer;
|
import org.webrtc.VideoFileRenderer;
|
||||||
|
import org.webrtc.VideoFrame;
|
||||||
import org.webrtc.VideoRenderer;
|
import org.webrtc.VideoRenderer;
|
||||||
|
import org.webrtc.VideoSink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity for peer connection call setup, call waiting
|
* Activity for peer connection call setup, call waiting
|
||||||
@ -137,9 +139,11 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
|||||||
// Peer connection statistics callback period in ms.
|
// Peer connection statistics callback period in ms.
|
||||||
private static final int STAT_CALLBACK_PERIOD = 1000;
|
private static final int STAT_CALLBACK_PERIOD = 1000;
|
||||||
|
|
||||||
private class ProxyRenderer implements VideoRenderer.Callbacks {
|
private class ProxyRenderer<T extends VideoRenderer.Callbacks & VideoSink>
|
||||||
private VideoRenderer.Callbacks target;
|
implements VideoRenderer.Callbacks, VideoSink {
|
||||||
|
private T target;
|
||||||
|
|
||||||
|
@Override
|
||||||
synchronized public void renderFrame(VideoRenderer.I420Frame frame) {
|
synchronized public void renderFrame(VideoRenderer.I420Frame frame) {
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
Logging.d(TAG, "Dropping frame in proxy because target is null.");
|
Logging.d(TAG, "Dropping frame in proxy because target is null.");
|
||||||
@ -150,7 +154,17 @@ public class CallActivity extends Activity implements AppRTCClient.SignalingEven
|
|||||||
target.renderFrame(frame);
|
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;
|
this.target = target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,6 +52,7 @@ import org.webrtc.StatsObserver;
|
|||||||
import org.webrtc.StatsReport;
|
import org.webrtc.StatsReport;
|
||||||
import org.webrtc.VideoCapturer;
|
import org.webrtc.VideoCapturer;
|
||||||
import org.webrtc.VideoRenderer;
|
import org.webrtc.VideoRenderer;
|
||||||
|
import org.webrtc.VideoSink;
|
||||||
import org.webrtc.VideoSource;
|
import org.webrtc.VideoSource;
|
||||||
import org.webrtc.VideoTrack;
|
import org.webrtc.VideoTrack;
|
||||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||||
@ -123,7 +124,7 @@ public class PeerConnectionClient {
|
|||||||
private boolean videoCapturerStopped;
|
private boolean videoCapturerStopped;
|
||||||
private boolean isError;
|
private boolean isError;
|
||||||
private Timer statsTimer;
|
private Timer statsTimer;
|
||||||
private VideoRenderer.Callbacks localRender;
|
private VideoSink localRender;
|
||||||
private List<VideoRenderer.Callbacks> remoteRenders;
|
private List<VideoRenderer.Callbacks> remoteRenders;
|
||||||
private SignalingParameters signalingParameters;
|
private SignalingParameters signalingParameters;
|
||||||
private MediaConstraints pcConstraints;
|
private MediaConstraints pcConstraints;
|
||||||
@ -332,13 +333,13 @@ public class PeerConnectionClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createPeerConnection(final VideoRenderer.Callbacks localRender,
|
public void createPeerConnection(final VideoSink localRender,
|
||||||
final VideoRenderer.Callbacks remoteRender, final VideoCapturer videoCapturer,
|
final VideoRenderer.Callbacks remoteRender, final VideoCapturer videoCapturer,
|
||||||
final SignalingParameters signalingParameters) {
|
final SignalingParameters signalingParameters) {
|
||||||
createPeerConnection(
|
createPeerConnection(
|
||||||
localRender, Collections.singletonList(remoteRender), videoCapturer, signalingParameters);
|
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 List<VideoRenderer.Callbacks> remoteRenders, final VideoCapturer videoCapturer,
|
||||||
final SignalingParameters signalingParameters) {
|
final SignalingParameters signalingParameters) {
|
||||||
if (peerConnectionParameters == null) {
|
if (peerConnectionParameters == null) {
|
||||||
@ -946,7 +947,7 @@ public class PeerConnectionClient {
|
|||||||
|
|
||||||
localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource);
|
localVideoTrack = factory.createVideoTrack(VIDEO_TRACK_ID, videoSource);
|
||||||
localVideoTrack.setEnabled(renderVideo);
|
localVideoTrack.setEnabled(renderVideo);
|
||||||
localVideoTrack.addRenderer(new VideoRenderer(localRender));
|
localVideoTrack.addSink(localRender);
|
||||||
return localVideoTrack;
|
return localVideoTrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,9 @@ import org.webrtc.PeerConnectionFactory;
|
|||||||
import org.webrtc.SessionDescription;
|
import org.webrtc.SessionDescription;
|
||||||
import org.webrtc.StatsReport;
|
import org.webrtc.StatsReport;
|
||||||
import org.webrtc.VideoCapturer;
|
import org.webrtc.VideoCapturer;
|
||||||
|
import org.webrtc.VideoFrame;
|
||||||
import org.webrtc.VideoRenderer;
|
import org.webrtc.VideoRenderer;
|
||||||
|
import org.webrtc.VideoSink;
|
||||||
|
|
||||||
@RunWith(BaseJUnit4ClassRunner.class)
|
@RunWith(BaseJUnit4ClassRunner.class)
|
||||||
public class PeerConnectionClientTest implements PeerConnectionEvents {
|
public class PeerConnectionClientTest implements PeerConnectionEvents {
|
||||||
@ -126,6 +128,49 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
// Peer connection events implementation.
|
||||||
@Override
|
@Override
|
||||||
public void onLocalDescription(SessionDescription sdp) {
|
public void onLocalDescription(SessionDescription sdp) {
|
||||||
@ -236,7 +281,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerConnectionClient createPeerConnectionClient(MockRenderer localRenderer,
|
PeerConnectionClient createPeerConnectionClient(MockSink localRenderer,
|
||||||
MockRenderer remoteRenderer, PeerConnectionParameters peerConnectionParameters,
|
MockRenderer remoteRenderer, PeerConnectionParameters peerConnectionParameters,
|
||||||
VideoCapturer videoCapturer) {
|
VideoCapturer videoCapturer) {
|
||||||
List<PeerConnection.IceServer> iceServers = new LinkedList<PeerConnection.IceServer>();
|
List<PeerConnection.IceServer> iceServers = new LinkedList<PeerConnection.IceServer>();
|
||||||
@ -333,7 +378,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
public void testSetLocalOfferMakesVideoFlowLocally() throws InterruptedException {
|
public void testSetLocalOfferMakesVideoFlowLocally() throws InterruptedException {
|
||||||
Log.d(TAG, "testSetLocalOfferMakesVideoFlowLocally");
|
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),
|
pcClient = createPeerConnectionClient(localRenderer, new MockRenderer(0, null),
|
||||||
createParametersForVideoCall(VIDEO_CODEC_VP8),
|
createParametersForVideoCall(VIDEO_CODEC_VP8),
|
||||||
createCameraCapturer(false /* captureToTexture */));
|
createCameraCapturer(false /* captureToTexture */));
|
||||||
@ -355,11 +400,11 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
private void doLoopbackTest(PeerConnectionParameters parameters, VideoCapturer videoCapturer,
|
private void doLoopbackTest(PeerConnectionParameters parameters, VideoCapturer videoCapturer,
|
||||||
boolean decodeToTexture) throws InterruptedException {
|
boolean decodeToTexture) throws InterruptedException {
|
||||||
loopback = true;
|
loopback = true;
|
||||||
MockRenderer localRenderer = null;
|
MockSink localRenderer = null;
|
||||||
MockRenderer remoteRenderer = null;
|
MockRenderer remoteRenderer = null;
|
||||||
if (parameters.videoCallEnabled) {
|
if (parameters.videoCallEnabled) {
|
||||||
Log.d(TAG, "testLoopback for video " + parameters.videoCodec);
|
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);
|
remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "testLoopback for audio.");
|
Log.d(TAG, "testLoopback for audio.");
|
||||||
@ -494,7 +539,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
Log.d(TAG, "testCameraSwitch");
|
Log.d(TAG, "testCameraSwitch");
|
||||||
loopback = true;
|
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);
|
MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);
|
||||||
|
|
||||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
||||||
@ -542,7 +587,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
Log.d(TAG, "testVideoSourceRestart");
|
Log.d(TAG, "testVideoSourceRestart");
|
||||||
loopback = true;
|
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);
|
MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);
|
||||||
|
|
||||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
||||||
@ -591,7 +636,7 @@ public class PeerConnectionClientTest implements PeerConnectionEvents {
|
|||||||
Log.d(TAG, "testCaptureFormatChange");
|
Log.d(TAG, "testCaptureFormatChange");
|
||||||
loopback = true;
|
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);
|
MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME);
|
||||||
|
|
||||||
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
pcClient = createPeerConnectionClient(localRenderer, remoteRenderer,
|
||||||
|
|||||||
Reference in New Issue
Block a user