From be2534971c35fdbd8b51f01343fb4f327470e4b9 Mon Sep 17 00:00:00 2001 From: Chris Phillips Date: Mon, 16 Dec 2019 14:09:13 -0800 Subject: [PATCH 1/6] Set encoding bitrate to recording bitrate --- .../android/src/main/java/io/flutter/plugins/camera/Camera.java | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 0fcda278d836..1f35200ebcfa 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -125,6 +125,7 @@ private void prepareMediaRecorder(String outputFilePath) throws IOException { // There's a specific order that mediaRecorder expects. Do not change the order // of these function calls. if (enableAudio) mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); + if (enableAudio) mediaRecorder.setAudioEncodingBitRate(recordingProfile.audioBitRate); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setOutputFormat(recordingProfile.fileFormat); if (enableAudio) mediaRecorder.setAudioEncoder(recordingProfile.audioCodec); From 518431277ee82987f314af6976ad9a4b6f2610ed Mon Sep 17 00:00:00 2001 From: Chris Phillips Date: Mon, 16 Dec 2019 14:23:07 -0800 Subject: [PATCH 2/6] Updated version and changlog --- packages/camera/CHANGELOG.md | 4 ++++ packages/camera/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md index 474dec281906..5d16952eac56 100644 --- a/packages/camera/CHANGELOG.md +++ b/packages/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.7+3 + +* Fixed garbled audio (in video) by setting audio encoding bitrate. + ## 0.5.7+2 * Remove the deprecated `author:` field from pubspec.yaml diff --git a/packages/camera/pubspec.yaml b/packages/camera/pubspec.yaml index c45ea86245f4..2e8d1cba8a93 100644 --- a/packages/camera/pubspec.yaml +++ b/packages/camera/pubspec.yaml @@ -2,7 +2,7 @@ name: camera description: A Flutter plugin for getting information about and controlling the camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video, and streaming image buffers to dart. -version: 0.5.7+2 +version: 0.5.7+3 homepage: https://github.com/flutter/plugins/tree/master/packages/camera From c4e09bdf77d0da0b420a0418874e636848b2dcaa Mon Sep 17 00:00:00 2001 From: Chris Phillips Date: Thu, 1 Oct 2020 17:41:04 -0700 Subject: [PATCH 3/6] Updated version to update PR --- packages/camera/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/pubspec.yaml b/packages/camera/pubspec.yaml index cbe1b1b6d9dd..64cae9be5ae3 100644 --- a/packages/camera/pubspec.yaml +++ b/packages/camera/pubspec.yaml @@ -2,7 +2,7 @@ name: camera description: A Flutter plugin for getting information about and controlling the camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video, and streaming image buffers to dart. -version: 0.5.8+7 +version: 0.5.8+8 homepage: https://github.com/flutter/plugins/tree/master/packages/camera From 8c09aa066f61391b6921952a660e657f50aef1d5 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 8 Oct 2020 11:53:48 +0200 Subject: [PATCH 4/6] Extracted logic to create MediaRecord and test it. --- packages/camera/android/build.gradle | 3 +- .../io/flutter/plugins/camera/Camera.java | 37 ++---- .../camera/media/MediaRecorderBuilder.java | 74 +++++++++++ .../plugins/camera/DartMessengerTest.java | 1 + .../media/MediaRecorderBuilderTest.java | 116 ++++++++++++++++++ 5 files changed, 205 insertions(+), 26 deletions(-) create mode 100644 packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java create mode 100644 packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java diff --git a/packages/camera/android/build.gradle b/packages/camera/android/build.gradle index 3ff98a8d7f47..247dd24a37b0 100644 --- a/packages/camera/android/build.gradle +++ b/packages/camera/android/build.gradle @@ -1,6 +1,6 @@ group 'io.flutter.plugins.camera' version '1.0-SNAPSHOT' -def args = ["-Xlint:deprecation","-Xlint:unchecked","-Werror"] +def args = ["-Xlint:deprecation","-Xlint:unchecked"] buildscript { repositories { @@ -51,4 +51,5 @@ android { dependencies { testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:3.5.13' } diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 1f35200ebcfa..86542e85e3e2 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -28,6 +28,7 @@ import androidx.annotation.NonNull; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugins.camera.media.MediaRecorderBuilder; import io.flutter.view.TextureRegistry.SurfaceTextureEntry; import java.io.File; import java.io.FileOutputStream; @@ -72,17 +73,16 @@ public enum ResolutionPreset { } public Camera( - final Activity activity, - final SurfaceTextureEntry flutterTexture, - final DartMessenger dartMessenger, - final String cameraName, - final String resolutionPreset, - final boolean enableAudio) + final Activity activity, + final SurfaceTextureEntry flutterTexture, + final DartMessenger dartMessenger, + final String cameraName, + final String resolutionPreset, + final boolean enableAudio) throws CameraAccessException { if (activity == null) { throw new IllegalStateException("No activity available!"); } - this.cameraName = cameraName; this.enableAudio = enableAudio; this.flutterTexture = flutterTexture; @@ -120,24 +120,11 @@ private void prepareMediaRecorder(String outputFilePath) throws IOException { if (mediaRecorder != null) { mediaRecorder.release(); } - mediaRecorder = new MediaRecorder(); - - // There's a specific order that mediaRecorder expects. Do not change the order - // of these function calls. - if (enableAudio) mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); - if (enableAudio) mediaRecorder.setAudioEncodingBitRate(recordingProfile.audioBitRate); - mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); - mediaRecorder.setOutputFormat(recordingProfile.fileFormat); - if (enableAudio) mediaRecorder.setAudioEncoder(recordingProfile.audioCodec); - mediaRecorder.setVideoEncoder(recordingProfile.videoCodec); - mediaRecorder.setVideoEncodingBitRate(recordingProfile.videoBitRate); - if (enableAudio) mediaRecorder.setAudioSamplingRate(recordingProfile.audioSampleRate); - mediaRecorder.setVideoFrameRate(recordingProfile.videoFrameRate); - mediaRecorder.setVideoSize(recordingProfile.videoFrameWidth, recordingProfile.videoFrameHeight); - mediaRecorder.setOutputFile(outputFilePath); - mediaRecorder.setOrientationHint(getMediaOrientation()); - - mediaRecorder.prepare(); + + mediaRecorder = new MediaRecorderBuilder(recordingProfile, outputFilePath) + .setEnableAudio(enableAudio) + .setMediaOrientation(getMediaOrientation()) + .build(); } @SuppressLint("MissingPermission") diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java new file mode 100644 index 000000000000..28ed76e8a9cd --- /dev/null +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java @@ -0,0 +1,74 @@ +package io.flutter.plugins.camera.media; + +import android.media.CamcorderProfile; +import android.media.MediaRecorder; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import java.io.IOException; + +public class MediaRecorderBuilder { + static class MediaRecorderFactory { + MediaRecorder makeMediaRecorder() { + return new MediaRecorder(); + } + } + + private final String outputFilePath; + private final CamcorderProfile recordingProfile; + private final MediaRecorderFactory recorderFactory; + + private boolean enableAudio; + private int mediaOrientation; + + public MediaRecorderBuilder( + @NonNull CamcorderProfile recordingProfile, + @NonNull String outputFilePath) { + this( recordingProfile, outputFilePath, new MediaRecorderFactory()); + } + + MediaRecorderBuilder( + @NonNull CamcorderProfile recordingProfile, + @NonNull String outputFilePath, + MediaRecorderFactory helper) { + this.outputFilePath = outputFilePath; + this.recordingProfile = recordingProfile; + this.recorderFactory = helper; + } + + + public MediaRecorderBuilder setEnableAudio(boolean enableAudio) { + this.enableAudio = enableAudio; + return this; + } + + public MediaRecorderBuilder setMediaOrientation(int orientation) { + this.mediaOrientation = orientation; + return this; + } + + public MediaRecorder build() throws IOException { + MediaRecorder mediaRecorder = recorderFactory.makeMediaRecorder(); + + // There's a specific order that mediaRecorder expects. Do not change the order + // of these function calls. + if (enableAudio) { + mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); + mediaRecorder.setAudioEncodingBitRate(recordingProfile.audioBitRate); + } + mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); + mediaRecorder.setOutputFormat(recordingProfile.fileFormat); + if (enableAudio) mediaRecorder.setAudioEncoder(recordingProfile.audioCodec); + mediaRecorder.setVideoEncoder(recordingProfile.videoCodec); + mediaRecorder.setVideoEncodingBitRate(recordingProfile.videoBitRate); + if (enableAudio) mediaRecorder.setAudioSamplingRate(recordingProfile.audioSampleRate); + mediaRecorder.setVideoFrameRate(recordingProfile.videoFrameRate); + mediaRecorder.setVideoSize(recordingProfile.videoFrameWidth, recordingProfile.videoFrameHeight); + mediaRecorder.setOutputFile(outputFilePath); + mediaRecorder.setOrientationHint(this.mediaOrientation); + + mediaRecorder.prepare(); + + return mediaRecorder; + } +} diff --git a/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java b/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java index db89eb279f41..c5ea83aa058a 100644 --- a/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java +++ b/packages/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java @@ -95,6 +95,7 @@ public void sendCameraClosingEvent() { private Map decodeSentMessage(ByteBuffer sentMessage) { sentMessage.position(0); + //noinspection unchecked return (Map) StandardMethodCodec.INSTANCE.decodeEnvelope(sentMessage); } diff --git a/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java b/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java new file mode 100644 index 000000000000..c4044ec18167 --- /dev/null +++ b/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java @@ -0,0 +1,116 @@ +package io.flutter.plugins.camera.media; + +import android.media.CamcorderProfile; +import android.media.MediaRecorder; +import org.junit.Test; +import org.mockito.InOrder; + +import java.io.IOException; +import java.lang.reflect.Constructor; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.*; + +public class MediaRecorderBuilderTest { + @Test + public void ctor_test() { + MediaRecorderBuilder builder = new MediaRecorderBuilder( + CamcorderProfile.get(CamcorderProfile.QUALITY_1080P), + ""); + + assertNotNull(builder); + } + + @Test + public void build_Should_set_values_in_correct_order_When_audio_is_disabled() throws IOException { + CamcorderProfile recorderProfile = getEmptyCamcorderProfile(); + MediaRecorderBuilder.MediaRecorderFactory mockFactory = mock(MediaRecorderBuilder.MediaRecorderFactory.class); + MediaRecorder mockMediaRecorder = mock(MediaRecorder.class); + String outputFilePath = "mock_video_file_path"; + int mediaOrientation = 1; + MediaRecorderBuilder builder = new MediaRecorderBuilder( + recorderProfile, + outputFilePath, + mockFactory) + .setEnableAudio(false) + .setMediaOrientation(mediaOrientation); + + when(mockFactory.makeMediaRecorder()) + .thenReturn(mockMediaRecorder); + + MediaRecorder recorder = builder.build(); + + InOrder inOrder = inOrder(recorder); + inOrder.verify(recorder).setVideoSource(MediaRecorder.VideoSource.SURFACE); + inOrder.verify(recorder).setOutputFormat(recorderProfile.fileFormat); + inOrder.verify(recorder).setVideoEncoder(recorderProfile.videoCodec); + inOrder.verify(recorder).setVideoEncodingBitRate(recorderProfile.videoBitRate); + inOrder.verify(recorder).setVideoFrameRate(recorderProfile.videoFrameRate); + inOrder.verify(recorder).setVideoSize(recorderProfile.videoFrameWidth, recorderProfile.videoFrameHeight); + inOrder.verify(recorder).setOutputFile(outputFilePath); + inOrder.verify(recorder).setOrientationHint(mediaOrientation); + inOrder.verify(recorder).prepare(); + } + + @Test + public void build_Should_set_values_in_correct_order_When_audio_is_enabled() throws IOException { + CamcorderProfile recorderProfile = getEmptyCamcorderProfile(); + MediaRecorderBuilder.MediaRecorderFactory mockFactory = mock(MediaRecorderBuilder.MediaRecorderFactory.class); + MediaRecorder mockMediaRecorder = mock(MediaRecorder.class); + String outputFilePath = "mock_video_file_path"; + int mediaOrientation = 1; + MediaRecorderBuilder builder = new MediaRecorderBuilder( + recorderProfile, + outputFilePath, + mockFactory) + .setEnableAudio(true) + .setMediaOrientation(mediaOrientation); + + when(mockFactory.makeMediaRecorder()) + .thenReturn(mockMediaRecorder); + + MediaRecorder recorder = builder.build(); + + InOrder inOrder = inOrder(recorder); + inOrder.verify(recorder).setAudioSource(MediaRecorder.AudioSource.MIC); + inOrder.verify(recorder).setAudioEncodingBitRate(recorderProfile.audioBitRate); + inOrder.verify(recorder).setVideoSource(MediaRecorder.VideoSource.SURFACE); + inOrder.verify(recorder).setOutputFormat(recorderProfile.fileFormat); + inOrder.verify(recorder).setAudioEncoder(recorderProfile.audioCodec); + inOrder.verify(recorder).setVideoEncoder(recorderProfile.videoCodec); + inOrder.verify(recorder).setVideoEncodingBitRate(recorderProfile.videoBitRate); + inOrder.verify(recorder).setAudioSamplingRate(recorderProfile.audioSampleRate); + inOrder.verify(recorder).setVideoFrameRate(recorderProfile.videoFrameRate); + inOrder.verify(recorder).setVideoSize(recorderProfile.videoFrameWidth, recorderProfile.videoFrameHeight); + inOrder.verify(recorder).setOutputFile(outputFilePath); + inOrder.verify(recorder).setOrientationHint(mediaOrientation); + inOrder.verify(recorder).prepare(); + } + + private CamcorderProfile getEmptyCamcorderProfile() { + try { + Constructor constructor = + CamcorderProfile.class.getDeclaredConstructor( + int.class, + int.class, + int.class, + int.class, + int.class, + int.class, + int.class, + int.class, + int.class, + int.class, + int.class, + int.class); + + constructor.setAccessible(true); + return constructor.newInstance(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } catch (Exception ignored) { + } + + return null; + } + + +} From fdf2674b0bd2e056e17a6ba74a01a0d9c96d5a5d Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 8 Oct 2020 14:11:55 +0200 Subject: [PATCH 5/6] Fixed JAVA formatting --- .../io/flutter/plugins/camera/Camera.java | 15 +- .../camera/media/MediaRecorderBuilder.java | 104 +++++----- .../media/MediaRecorderBuilderTest.java | 196 ++++++++---------- 3 files changed, 149 insertions(+), 166 deletions(-) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 86542e85e3e2..63e4d03e982a 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -73,12 +73,12 @@ public enum ResolutionPreset { } public Camera( - final Activity activity, - final SurfaceTextureEntry flutterTexture, - final DartMessenger dartMessenger, - final String cameraName, - final String resolutionPreset, - final boolean enableAudio) + final Activity activity, + final SurfaceTextureEntry flutterTexture, + final DartMessenger dartMessenger, + final String cameraName, + final String resolutionPreset, + final boolean enableAudio) throws CameraAccessException { if (activity == null) { throw new IllegalStateException("No activity available!"); @@ -121,7 +121,8 @@ private void prepareMediaRecorder(String outputFilePath) throws IOException { mediaRecorder.release(); } - mediaRecorder = new MediaRecorderBuilder(recordingProfile, outputFilePath) + mediaRecorder = + new MediaRecorderBuilder(recordingProfile, outputFilePath) .setEnableAudio(enableAudio) .setMediaOrientation(getMediaOrientation()) .build(); diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java index 28ed76e8a9cd..f1628d9f5fd7 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java @@ -3,72 +3,68 @@ import android.media.CamcorderProfile; import android.media.MediaRecorder; import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; - import java.io.IOException; public class MediaRecorderBuilder { - static class MediaRecorderFactory { - MediaRecorder makeMediaRecorder() { - return new MediaRecorder(); - } + static class MediaRecorderFactory { + MediaRecorder makeMediaRecorder() { + return new MediaRecorder(); } + } - private final String outputFilePath; - private final CamcorderProfile recordingProfile; - private final MediaRecorderFactory recorderFactory; - - private boolean enableAudio; - private int mediaOrientation; + private final String outputFilePath; + private final CamcorderProfile recordingProfile; + private final MediaRecorderFactory recorderFactory; - public MediaRecorderBuilder( - @NonNull CamcorderProfile recordingProfile, - @NonNull String outputFilePath) { - this( recordingProfile, outputFilePath, new MediaRecorderFactory()); - } + private boolean enableAudio; + private int mediaOrientation; - MediaRecorderBuilder( - @NonNull CamcorderProfile recordingProfile, - @NonNull String outputFilePath, - MediaRecorderFactory helper) { - this.outputFilePath = outputFilePath; - this.recordingProfile = recordingProfile; - this.recorderFactory = helper; - } + public MediaRecorderBuilder( + @NonNull CamcorderProfile recordingProfile, @NonNull String outputFilePath) { + this(recordingProfile, outputFilePath, new MediaRecorderFactory()); + } + MediaRecorderBuilder( + @NonNull CamcorderProfile recordingProfile, + @NonNull String outputFilePath, + MediaRecorderFactory helper) { + this.outputFilePath = outputFilePath; + this.recordingProfile = recordingProfile; + this.recorderFactory = helper; + } - public MediaRecorderBuilder setEnableAudio(boolean enableAudio) { - this.enableAudio = enableAudio; - return this; - } + public MediaRecorderBuilder setEnableAudio(boolean enableAudio) { + this.enableAudio = enableAudio; + return this; + } - public MediaRecorderBuilder setMediaOrientation(int orientation) { - this.mediaOrientation = orientation; - return this; - } + public MediaRecorderBuilder setMediaOrientation(int orientation) { + this.mediaOrientation = orientation; + return this; + } - public MediaRecorder build() throws IOException { - MediaRecorder mediaRecorder = recorderFactory.makeMediaRecorder(); + public MediaRecorder build() throws IOException { + MediaRecorder mediaRecorder = recorderFactory.makeMediaRecorder(); - // There's a specific order that mediaRecorder expects. Do not change the order - // of these function calls. - if (enableAudio) { - mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); - mediaRecorder.setAudioEncodingBitRate(recordingProfile.audioBitRate); - } - mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); - mediaRecorder.setOutputFormat(recordingProfile.fileFormat); - if (enableAudio) mediaRecorder.setAudioEncoder(recordingProfile.audioCodec); - mediaRecorder.setVideoEncoder(recordingProfile.videoCodec); - mediaRecorder.setVideoEncodingBitRate(recordingProfile.videoBitRate); - if (enableAudio) mediaRecorder.setAudioSamplingRate(recordingProfile.audioSampleRate); - mediaRecorder.setVideoFrameRate(recordingProfile.videoFrameRate); - mediaRecorder.setVideoSize(recordingProfile.videoFrameWidth, recordingProfile.videoFrameHeight); - mediaRecorder.setOutputFile(outputFilePath); - mediaRecorder.setOrientationHint(this.mediaOrientation); + // There's a specific order that mediaRecorder expects. Do not change the order + // of these function calls. + if (enableAudio) { + mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); + mediaRecorder.setAudioEncodingBitRate(recordingProfile.audioBitRate); + } + mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); + mediaRecorder.setOutputFormat(recordingProfile.fileFormat); + if (enableAudio) mediaRecorder.setAudioEncoder(recordingProfile.audioCodec); + mediaRecorder.setVideoEncoder(recordingProfile.videoCodec); + mediaRecorder.setVideoEncodingBitRate(recordingProfile.videoBitRate); + if (enableAudio) mediaRecorder.setAudioSamplingRate(recordingProfile.audioSampleRate); + mediaRecorder.setVideoFrameRate(recordingProfile.videoFrameRate); + mediaRecorder.setVideoSize(recordingProfile.videoFrameWidth, recordingProfile.videoFrameHeight); + mediaRecorder.setOutputFile(outputFilePath); + mediaRecorder.setOrientationHint(this.mediaOrientation); - mediaRecorder.prepare(); + mediaRecorder.prepare(); - return mediaRecorder; - } + return mediaRecorder; + } } diff --git a/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java b/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java index c4044ec18167..f60e85de3903 100644 --- a/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java +++ b/packages/camera/android/src/test/java/io/flutter/plugins/camera/media/MediaRecorderBuilderTest.java @@ -1,116 +1,102 @@ package io.flutter.plugins.camera.media; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.*; + import android.media.CamcorderProfile; import android.media.MediaRecorder; -import org.junit.Test; -import org.mockito.InOrder; - import java.io.IOException; import java.lang.reflect.Constructor; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.*; +import org.junit.Test; +import org.mockito.InOrder; public class MediaRecorderBuilderTest { - @Test - public void ctor_test() { - MediaRecorderBuilder builder = new MediaRecorderBuilder( - CamcorderProfile.get(CamcorderProfile.QUALITY_1080P), - ""); - - assertNotNull(builder); + @Test + public void ctor_test() { + MediaRecorderBuilder builder = + new MediaRecorderBuilder(CamcorderProfile.get(CamcorderProfile.QUALITY_1080P), ""); + + assertNotNull(builder); + } + + @Test + public void build_Should_set_values_in_correct_order_When_audio_is_disabled() throws IOException { + CamcorderProfile recorderProfile = getEmptyCamcorderProfile(); + MediaRecorderBuilder.MediaRecorderFactory mockFactory = + mock(MediaRecorderBuilder.MediaRecorderFactory.class); + MediaRecorder mockMediaRecorder = mock(MediaRecorder.class); + String outputFilePath = "mock_video_file_path"; + int mediaOrientation = 1; + MediaRecorderBuilder builder = + new MediaRecorderBuilder(recorderProfile, outputFilePath, mockFactory) + .setEnableAudio(false) + .setMediaOrientation(mediaOrientation); + + when(mockFactory.makeMediaRecorder()).thenReturn(mockMediaRecorder); + + MediaRecorder recorder = builder.build(); + + InOrder inOrder = inOrder(recorder); + inOrder.verify(recorder).setVideoSource(MediaRecorder.VideoSource.SURFACE); + inOrder.verify(recorder).setOutputFormat(recorderProfile.fileFormat); + inOrder.verify(recorder).setVideoEncoder(recorderProfile.videoCodec); + inOrder.verify(recorder).setVideoEncodingBitRate(recorderProfile.videoBitRate); + inOrder.verify(recorder).setVideoFrameRate(recorderProfile.videoFrameRate); + inOrder + .verify(recorder) + .setVideoSize(recorderProfile.videoFrameWidth, recorderProfile.videoFrameHeight); + inOrder.verify(recorder).setOutputFile(outputFilePath); + inOrder.verify(recorder).setOrientationHint(mediaOrientation); + inOrder.verify(recorder).prepare(); + } + + @Test + public void build_Should_set_values_in_correct_order_When_audio_is_enabled() throws IOException { + CamcorderProfile recorderProfile = getEmptyCamcorderProfile(); + MediaRecorderBuilder.MediaRecorderFactory mockFactory = + mock(MediaRecorderBuilder.MediaRecorderFactory.class); + MediaRecorder mockMediaRecorder = mock(MediaRecorder.class); + String outputFilePath = "mock_video_file_path"; + int mediaOrientation = 1; + MediaRecorderBuilder builder = + new MediaRecorderBuilder(recorderProfile, outputFilePath, mockFactory) + .setEnableAudio(true) + .setMediaOrientation(mediaOrientation); + + when(mockFactory.makeMediaRecorder()).thenReturn(mockMediaRecorder); + + MediaRecorder recorder = builder.build(); + + InOrder inOrder = inOrder(recorder); + inOrder.verify(recorder).setAudioSource(MediaRecorder.AudioSource.MIC); + inOrder.verify(recorder).setAudioEncodingBitRate(recorderProfile.audioBitRate); + inOrder.verify(recorder).setVideoSource(MediaRecorder.VideoSource.SURFACE); + inOrder.verify(recorder).setOutputFormat(recorderProfile.fileFormat); + inOrder.verify(recorder).setAudioEncoder(recorderProfile.audioCodec); + inOrder.verify(recorder).setVideoEncoder(recorderProfile.videoCodec); + inOrder.verify(recorder).setVideoEncodingBitRate(recorderProfile.videoBitRate); + inOrder.verify(recorder).setAudioSamplingRate(recorderProfile.audioSampleRate); + inOrder.verify(recorder).setVideoFrameRate(recorderProfile.videoFrameRate); + inOrder + .verify(recorder) + .setVideoSize(recorderProfile.videoFrameWidth, recorderProfile.videoFrameHeight); + inOrder.verify(recorder).setOutputFile(outputFilePath); + inOrder.verify(recorder).setOrientationHint(mediaOrientation); + inOrder.verify(recorder).prepare(); + } + + private CamcorderProfile getEmptyCamcorderProfile() { + try { + Constructor constructor = + CamcorderProfile.class.getDeclaredConstructor( + int.class, int.class, int.class, int.class, int.class, int.class, int.class, + int.class, int.class, int.class, int.class, int.class); + + constructor.setAccessible(true); + return constructor.newInstance(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } catch (Exception ignored) { } - @Test - public void build_Should_set_values_in_correct_order_When_audio_is_disabled() throws IOException { - CamcorderProfile recorderProfile = getEmptyCamcorderProfile(); - MediaRecorderBuilder.MediaRecorderFactory mockFactory = mock(MediaRecorderBuilder.MediaRecorderFactory.class); - MediaRecorder mockMediaRecorder = mock(MediaRecorder.class); - String outputFilePath = "mock_video_file_path"; - int mediaOrientation = 1; - MediaRecorderBuilder builder = new MediaRecorderBuilder( - recorderProfile, - outputFilePath, - mockFactory) - .setEnableAudio(false) - .setMediaOrientation(mediaOrientation); - - when(mockFactory.makeMediaRecorder()) - .thenReturn(mockMediaRecorder); - - MediaRecorder recorder = builder.build(); - - InOrder inOrder = inOrder(recorder); - inOrder.verify(recorder).setVideoSource(MediaRecorder.VideoSource.SURFACE); - inOrder.verify(recorder).setOutputFormat(recorderProfile.fileFormat); - inOrder.verify(recorder).setVideoEncoder(recorderProfile.videoCodec); - inOrder.verify(recorder).setVideoEncodingBitRate(recorderProfile.videoBitRate); - inOrder.verify(recorder).setVideoFrameRate(recorderProfile.videoFrameRate); - inOrder.verify(recorder).setVideoSize(recorderProfile.videoFrameWidth, recorderProfile.videoFrameHeight); - inOrder.verify(recorder).setOutputFile(outputFilePath); - inOrder.verify(recorder).setOrientationHint(mediaOrientation); - inOrder.verify(recorder).prepare(); - } - - @Test - public void build_Should_set_values_in_correct_order_When_audio_is_enabled() throws IOException { - CamcorderProfile recorderProfile = getEmptyCamcorderProfile(); - MediaRecorderBuilder.MediaRecorderFactory mockFactory = mock(MediaRecorderBuilder.MediaRecorderFactory.class); - MediaRecorder mockMediaRecorder = mock(MediaRecorder.class); - String outputFilePath = "mock_video_file_path"; - int mediaOrientation = 1; - MediaRecorderBuilder builder = new MediaRecorderBuilder( - recorderProfile, - outputFilePath, - mockFactory) - .setEnableAudio(true) - .setMediaOrientation(mediaOrientation); - - when(mockFactory.makeMediaRecorder()) - .thenReturn(mockMediaRecorder); - - MediaRecorder recorder = builder.build(); - - InOrder inOrder = inOrder(recorder); - inOrder.verify(recorder).setAudioSource(MediaRecorder.AudioSource.MIC); - inOrder.verify(recorder).setAudioEncodingBitRate(recorderProfile.audioBitRate); - inOrder.verify(recorder).setVideoSource(MediaRecorder.VideoSource.SURFACE); - inOrder.verify(recorder).setOutputFormat(recorderProfile.fileFormat); - inOrder.verify(recorder).setAudioEncoder(recorderProfile.audioCodec); - inOrder.verify(recorder).setVideoEncoder(recorderProfile.videoCodec); - inOrder.verify(recorder).setVideoEncodingBitRate(recorderProfile.videoBitRate); - inOrder.verify(recorder).setAudioSamplingRate(recorderProfile.audioSampleRate); - inOrder.verify(recorder).setVideoFrameRate(recorderProfile.videoFrameRate); - inOrder.verify(recorder).setVideoSize(recorderProfile.videoFrameWidth, recorderProfile.videoFrameHeight); - inOrder.verify(recorder).setOutputFile(outputFilePath); - inOrder.verify(recorder).setOrientationHint(mediaOrientation); - inOrder.verify(recorder).prepare(); - } - - private CamcorderProfile getEmptyCamcorderProfile() { - try { - Constructor constructor = - CamcorderProfile.class.getDeclaredConstructor( - int.class, - int.class, - int.class, - int.class, - int.class, - int.class, - int.class, - int.class, - int.class, - int.class, - int.class, - int.class); - - constructor.setAccessible(true); - return constructor.newInstance(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } catch (Exception ignored) { - } - - return null; - } - - + return null; + } } From 76c59ac8e75e7714732d50783cb928f6140626b3 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 8 Oct 2020 21:45:15 +0200 Subject: [PATCH 6/6] Fixed feedback --- packages/camera/android/build.gradle | 2 +- .../io/flutter/plugins/camera/media/MediaRecorderBuilder.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/camera/android/build.gradle b/packages/camera/android/build.gradle index 247dd24a37b0..13495b2bd29d 100644 --- a/packages/camera/android/build.gradle +++ b/packages/camera/android/build.gradle @@ -1,6 +1,6 @@ group 'io.flutter.plugins.camera' version '1.0-SNAPSHOT' -def args = ["-Xlint:deprecation","-Xlint:unchecked"] +def args = ["-Xlint:deprecation","-Xlint:unchecked","-Werror"] buildscript { repositories { diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java index f1628d9f5fd7..57dc6e633408 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/media/MediaRecorderBuilder.java @@ -1,3 +1,6 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. package io.flutter.plugins.camera.media; import android.media.CamcorderProfile;