Add support for media recorders in Camera1Capturer.

BUG=b/36684011

Review-Url: https://codereview.webrtc.org/2861893003
Cr-Commit-Position: refs/heads/master@{#18024}
This commit is contained in:
sakal
2017-05-05 01:48:48 -07:00
committed by Commit bot
parent ea12f4c5e8
commit bac4c8013f
5 changed files with 61 additions and 27 deletions

View File

@ -28,11 +28,8 @@ public class Camera1Capturer extends CameraCapturer {
CameraSession.Events events, Context applicationContext, CameraSession.Events events, Context applicationContext,
SurfaceTextureHelper surfaceTextureHelper, MediaRecorder mediaRecorder, String cameraName, SurfaceTextureHelper surfaceTextureHelper, MediaRecorder mediaRecorder, String cameraName,
int width, int height, int framerate) { int width, int height, int framerate) {
if (mediaRecorder != null) { Camera1Session.create(createSessionCallback, events,
throw new RuntimeException("MediaRecoder is not supported for camera 1."); captureToTexture || (mediaRecorder != null), applicationContext, surfaceTextureHelper,
} mediaRecorder, Camera1Enumerator.getCameraIndex(cameraName), width, height, framerate);
Camera1Session.create(createSessionCallback, events, captureToTexture, applicationContext,
surfaceTextureHelper, Camera1Enumerator.getCameraIndex(cameraName), width, height,
framerate);
} }
} }

View File

@ -15,6 +15,7 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest; import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest; import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest;
import java.io.IOException;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -120,6 +121,12 @@ public class Camera1CapturerUsingByteBufferTest {
fixtures.cameraEventsInvoked(); fixtures.cameraEventsInvoked();
} }
@Test
@MediumTest
public void testUpdateMediaRecorder() throws InterruptedException, IOException {
fixtures.updateMediaRecorder(false /* useSurfaceCapture */);
}
// Test what happens when attempting to call e.g. switchCamera() after camera has been stopped. // Test what happens when attempting to call e.g. switchCamera() after camera has been stopped.
@Test @Test
@MediumTest @MediumTest

View File

@ -15,6 +15,7 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest; import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest; import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest;
import java.io.IOException;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -115,6 +116,12 @@ public class Camera1CapturerUsingTextureTest {
fixtures.cameraEventsInvoked(); fixtures.cameraEventsInvoked();
} }
@Test
@MediumTest
public void testUpdateMediaRecorder() throws InterruptedException, IOException {
fixtures.updateMediaRecorder(false /* useSurfaceCapture */);
}
// Test what happens when attempting to call e.g. switchCamera() after camera has been stopped. // Test what happens when attempting to call e.g. switchCamera() after camera has been stopped.
@Test @Test
@MediumTest @MediumTest

View File

@ -509,20 +509,8 @@ class CameraVideoCapturerTestFixtures {
} }
@TargetApi(21) @TargetApi(21)
public void updateMediaRecorder(boolean useSurfaceCapture) private static void prepareMediaRecorderForTests(
throws InterruptedException, IOException { MediaRecorder mediaRecorder, File outputFile, boolean useSurfaceCapture) throws IOException {
final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
final VideoTrackWithRenderer videoTrackWithRenderer =
createVideoTrackWithRenderer(capturerInstance.capturer);
// Wait for the camera to start so we can add and remove MediaRecorder.
assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
final String videoOutPath = Environment.getExternalStorageDirectory().getPath()
+ "/chromium_tests_root/testmediarecorder.mp4";
File outputFile = new File(videoOutPath);
// Create MediaRecorder object
MediaRecorder mediaRecorder = new MediaRecorder();
mediaRecorder.setVideoSource( mediaRecorder.setVideoSource(
useSurfaceCapture ? MediaRecorder.VideoSource.SURFACE : MediaRecorder.VideoSource.CAMERA); useSurfaceCapture ? MediaRecorder.VideoSource.SURFACE : MediaRecorder.VideoSource.CAMERA);
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P); CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
@ -537,6 +525,28 @@ class CameraVideoCapturerTestFixtures {
mediaRecorder.setVideoEncoder(profile.videoCodec); mediaRecorder.setVideoEncoder(profile.videoCodec);
mediaRecorder.setOutputFile(outputFile.getPath()); mediaRecorder.setOutputFile(outputFile.getPath());
mediaRecorder.prepare(); mediaRecorder.prepare();
}
@TargetApi(21)
public void updateMediaRecorder(boolean useSurfaceCapture)
throws InterruptedException, IOException {
final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
final VideoTrackWithRenderer videoTrackWithRenderer =
createVideoTrackWithRenderer(capturerInstance.capturer);
// Wait for the camera to start so we can add and remove MediaRecorder.
assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
final String videoOutPath = Environment.getExternalStorageDirectory().getPath()
+ "/chromium_tests_root/testmediarecorder.mp4";
File outputFile = new File(videoOutPath);
// Create MediaRecorder object
MediaRecorder mediaRecorder = new MediaRecorder();
if (useSurfaceCapture) {
// When using using surface capture, media recorder has to be prepared before adding it to the
// camera.
prepareMediaRecorderForTests(mediaRecorder, outputFile, useSurfaceCapture);
}
// Add MediaRecorder to camera pipeline. // Add MediaRecorder to camera pipeline.
final boolean[] addMediaRecorderSuccessful = new boolean[1]; final boolean[] addMediaRecorderSuccessful = new boolean[1];
@ -550,6 +560,7 @@ class CameraVideoCapturerTestFixtures {
} }
@Override @Override
public void onMediaRecorderError(String errorDescription) { public void onMediaRecorderError(String errorDescription) {
Logging.e(TAG, errorDescription);
addMediaRecorderSuccessful[0] = false; addMediaRecorderSuccessful[0] = false;
addBarrier.countDown(); addBarrier.countDown();
} }
@ -561,6 +572,11 @@ class CameraVideoCapturerTestFixtures {
assertTrue(addMediaRecorderSuccessful[0]); assertTrue(addMediaRecorderSuccessful[0]);
// Start MediaRecorder and wait for a few frames to capture. // Start MediaRecorder and wait for a few frames to capture.
if (!useSurfaceCapture) {
// When using using camera capture, media recorder has to be prepared after adding it to the
// camera.
prepareMediaRecorderForTests(mediaRecorder, outputFile, useSurfaceCapture);
}
mediaRecorder.start(); mediaRecorder.start();
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0); assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);

View File

@ -11,6 +11,7 @@
package org.webrtc; package org.webrtc;
import android.content.Context; import android.content.Context;
import android.media.MediaRecorder;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.view.Surface; import android.view.Surface;
@ -52,8 +53,8 @@ class Camera1Session implements CameraSession {
public static void create(final CreateSessionCallback callback, final Events events, public static void create(final CreateSessionCallback callback, final Events events,
final boolean captureToTexture, final Context applicationContext, final boolean captureToTexture, final Context applicationContext,
final SurfaceTextureHelper surfaceTextureHelper, final int cameraId, final int width, final SurfaceTextureHelper surfaceTextureHelper, final MediaRecorder mediaRecorder,
final int height, final int framerate) { final int cameraId, final int width, final int height, final int framerate) {
final long constructionTimeNs = System.nanoTime(); final long constructionTimeNs = System.nanoTime();
Logging.d(TAG, "Open camera " + cameraId); Logging.d(TAG, "Open camera " + cameraId);
events.onCameraOpening(); events.onCameraOpening();
@ -96,8 +97,9 @@ class Camera1Session implements CameraSession {
// Calculate orientation manually and send it as CVO insted. // Calculate orientation manually and send it as CVO insted.
camera.setDisplayOrientation(0 /* degrees */); camera.setDisplayOrientation(0 /* degrees */);
callback.onDone(new Camera1Session(events, captureToTexture, applicationContext, callback.onDone(
surfaceTextureHelper, cameraId, camera, info, captureFormat, constructionTimeNs)); new Camera1Session(events, captureToTexture, applicationContext, surfaceTextureHelper,
mediaRecorder, cameraId, camera, info, captureFormat, constructionTimeNs));
} }
private static void updateCameraParameters(android.hardware.Camera camera, private static void updateCameraParameters(android.hardware.Camera camera,
@ -145,9 +147,9 @@ class Camera1Session implements CameraSession {
} }
private Camera1Session(Events events, boolean captureToTexture, Context applicationContext, private Camera1Session(Events events, boolean captureToTexture, Context applicationContext,
SurfaceTextureHelper surfaceTextureHelper, int cameraId, android.hardware.Camera camera, SurfaceTextureHelper surfaceTextureHelper, MediaRecorder mediaRecorder, int cameraId,
android.hardware.Camera.CameraInfo info, CaptureFormat captureFormat, android.hardware.Camera camera, android.hardware.Camera.CameraInfo info,
long constructionTimeNs) { CaptureFormat captureFormat, long constructionTimeNs) {
Logging.d(TAG, "Create new camera1 session on camera " + cameraId); Logging.d(TAG, "Create new camera1 session on camera " + cameraId);
this.cameraThreadHandler = new Handler(); this.cameraThreadHandler = new Handler();
@ -162,6 +164,11 @@ class Camera1Session implements CameraSession {
this.constructionTimeNs = constructionTimeNs; this.constructionTimeNs = constructionTimeNs;
startCapturing(); startCapturing();
if (mediaRecorder != null) {
camera.unlock();
mediaRecorder.setCamera(camera);
}
} }
@Override @Override