Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[camera] Fix: use legacy profiles when list is empty #6867

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ TheOneWithTheBraid <the-one@with-the-braid.cf>
Rulong Chen(陈汝龙) <rulong.crl@alibaba-inc.com>
Hwanseok Kang <tttkhs96@gmail.com>
Twin Sun, LLC <google-contrib@twinsunsolutions.com>
Mikhail Zotyev <mbixjkee1392@gmail.com>
4 changes: 2 additions & 2 deletions packages/camera/camera/example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 31
compileSdkVersion 33

lintOptions {
disable 'InvalidPackage'
Expand All @@ -34,7 +34,7 @@ android {
defaultConfig {
applicationId "io.flutter.plugins.cameraexample"
minSdkVersion 21
targetSdkVersion 28
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
android:launchMode="singleTop"
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_android/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ project.getTasks().withType(JavaCompile){
apply plugin: 'com.android.library'

android {
compileSdkVersion 31
compileSdk 31

defaultConfig {
targetSdkVersion 31
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,22 @@ static Size computeBestPreviewSize(int cameraId, ResolutionPreset preset)
if (preset.ordinal() > ResolutionPreset.high.ordinal()) {
preset = ResolutionPreset.high;
}

if (Build.VERSION.SDK_INT >= 31) {
EncoderProfiles profile =
getBestAvailableCamcorderProfileForResolutionPreset(cameraId, preset);
getBestAvailableCamcorderProfileForResolutionPreset(cameraId, preset);
List<EncoderProfiles.VideoProfile> videoProfiles = profile.getVideoProfiles();
EncoderProfiles.VideoProfile defaultVideoProfile = videoProfiles.get(0);

return new Size(defaultVideoProfile.getWidth(), defaultVideoProfile.getHeight());
} else {
@SuppressWarnings("deprecation")
CamcorderProfile profile =
getBestAvailableCamcorderProfileForResolutionPresetLegacy(cameraId, preset);
return new Size(profile.videoFrameWidth, profile.videoFrameHeight);
if (defaultVideoProfile != null) {
return new Size(defaultVideoProfile.getWidth(), defaultVideoProfile.getHeight());
}
}

@SuppressWarnings("deprecation")
CamcorderProfile profile =
getBestAvailableCamcorderProfileForResolutionPresetLegacy(cameraId, preset);
return new Size(profile.videoFrameWidth, profile.videoFrameHeight);
}

/**
Expand Down Expand Up @@ -235,20 +238,25 @@ private void configureResolution(ResolutionPreset resolutionPreset, int cameraId
return;
}

captureSize = null;

if (Build.VERSION.SDK_INT >= 31) {
recordingProfile =
getBestAvailableCamcorderProfileForResolutionPreset(cameraId, resolutionPreset);
getBestAvailableCamcorderProfileForResolutionPreset(cameraId, resolutionPreset);
List<EncoderProfiles.VideoProfile> videoProfiles = recordingProfile.getVideoProfiles();

EncoderProfiles.VideoProfile defaultVideoProfile = videoProfiles.get(0);
captureSize = new Size(defaultVideoProfile.getWidth(), defaultVideoProfile.getHeight());
} else {
if (defaultVideoProfile != null) {
captureSize = new Size(defaultVideoProfile.getWidth(), defaultVideoProfile.getHeight());
}
}

if (captureSize == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a follow up to the comment I left below with regards to constructing MediaRecorderBuilder properly, you may want to ensure that either recordingProfile and recordingProfileLegacy is null. It may be easier to tell based on this whether CamcorderProfile or EncoderProfiles is being used as a result.

@SuppressWarnings("deprecation")
CamcorderProfile camcorderProfile =
getBestAvailableCamcorderProfileForResolutionPresetLegacy(cameraId, resolutionPreset);
getBestAvailableCamcorderProfileForResolutionPresetLegacy(cameraId, resolutionPreset);
recordingProfileLegacy = camcorderProfile;
captureSize =
new Size(recordingProfileLegacy.videoFrameWidth, recordingProfileLegacy.videoFrameHeight);
captureSize = new Size(recordingProfileLegacy.videoFrameWidth, recordingProfileLegacy.videoFrameHeight);
}

previewSize = computeBestPreviewSize(cameraId, resolutionPreset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,33 +75,48 @@ public MediaRecorder build() throws IOException, NullPointerException, IndexOutO
if (enableAudio) mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

if (Build.VERSION.SDK_INT >= 31) {
boolean isFormatNeedSetup = true;
boolean isAudioNeedSetup = enableAudio;
boolean isVideoNeedSetup = true;

if (Build.VERSION.SDK_INT >= 31 && encoderProfiles != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes here seem to suggest that there may be a case where one of videoProfile or audioProfile may be null but not the other. This does not seem to be true according to the docs.

Thus, you could add a check here for if (Build.VERSION.SDK_INT >= 31 && encoderProfiles != null) to use the non-deprecated code versus just if (Build.VERSION.SDK_INT >= 31) and alleviate the need for the isXsetup type of checks.

In order for that to work (and I think the code you have here, as well, since one of encoderProfiles and camcorderProfile will always be null), we'll need to handle using the correct MediaRecorderBuilder constructor at the Camera.java level:

if (Build.VERSION.SDK_INT >= 31) {
mediaRecorderBuilder = new MediaRecorderBuilder(getRecordingProfile(), outputFilePath);
} else {
mediaRecorderBuilder = new MediaRecorderBuilder(getRecordingProfileLegacy(), outputFilePath);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a comment above in ResolutionFeature.java that may help determine which constructor to use here.

EncoderProfiles.VideoProfile videoProfile = encoderProfiles.getVideoProfiles().get(0);
EncoderProfiles.AudioProfile audioProfile = encoderProfiles.getAudioProfiles().get(0);

mediaRecorder.setOutputFormat(encoderProfiles.getRecommendedFileFormat());
if (enableAudio) {
isFormatNeedSetup = false;

if (isAudioNeedSetup && audioProfile != null) {
mediaRecorder.setAudioEncoder(audioProfile.getCodec());
mediaRecorder.setAudioEncodingBitRate(audioProfile.getBitrate());
mediaRecorder.setAudioSamplingRate(audioProfile.getSampleRate());
isAudioNeedSetup = false;
}
mediaRecorder.setVideoEncoder(videoProfile.getCodec());
mediaRecorder.setVideoEncodingBitRate(videoProfile.getBitrate());
mediaRecorder.setVideoFrameRate(videoProfile.getFrameRate());
mediaRecorder.setVideoSize(videoProfile.getWidth(), videoProfile.getHeight());
mediaRecorder.setVideoSize(videoProfile.getWidth(), videoProfile.getHeight());
} else {
mediaRecorder.setOutputFormat(camcorderProfile.fileFormat);
if (enableAudio) {
mediaRecorder.setAudioEncoder(camcorderProfile.audioCodec);
mediaRecorder.setAudioEncodingBitRate(camcorderProfile.audioBitRate);
mediaRecorder.setAudioSamplingRate(camcorderProfile.audioSampleRate);
if (videoProfile != null) {
mediaRecorder.setVideoEncoder(videoProfile.getCodec());
mediaRecorder.setVideoEncodingBitRate(videoProfile.getBitrate());
mediaRecorder.setVideoFrameRate(videoProfile.getFrameRate());
mediaRecorder.setVideoSize(videoProfile.getWidth(), videoProfile.getHeight());
mediaRecorder.setVideoSize(videoProfile.getWidth(), videoProfile.getHeight());
isVideoNeedSetup = false;
}
}

if (isFormatNeedSetup && camcorderProfile != null) {
mediaRecorder.setOutputFormat(camcorderProfile.fileFormat);
}

if (isAudioNeedSetup && camcorderProfile != null) {
mediaRecorder.setAudioEncoder(camcorderProfile.audioCodec);
mediaRecorder.setAudioEncodingBitRate(camcorderProfile.audioBitRate);
mediaRecorder.setAudioSamplingRate(camcorderProfile.audioSampleRate);
}

if (isVideoNeedSetup && camcorderProfile != null) {
mediaRecorder.setVideoEncoder(camcorderProfile.videoCodec);
mediaRecorder.setVideoEncodingBitRate(camcorderProfile.videoBitRate);
mediaRecorder.setVideoFrameRate(camcorderProfile.videoFrameRate);
mediaRecorder.setVideoSize(
camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
mediaRecorder.setVideoSize(camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
}

mediaRecorder.setOutputFile(outputFilePath);
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: camera_android
description: Android implementation of the camera plugin.
repository: https://github.com/flutter/plugins/tree/main/packages/camera/camera_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.10.1
version: 0.10.2

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down