44
55package io .flutter .plugins .camera .features .resolution ;
66
7+ import android .annotation .TargetApi ;
78import android .hardware .camera2 .CaptureRequest ;
89import android .media .CamcorderProfile ;
10+ import android .media .EncoderProfiles ;
11+ import android .os .Build ;
912import android .util .Size ;
1013import androidx .annotation .VisibleForTesting ;
1114import io .flutter .plugins .camera .CameraProperties ;
1215import io .flutter .plugins .camera .features .CameraFeature ;
16+ import java .util .List ;
1317
1418/**
1519 * Controls the resolutions configuration on the {@link android.hardware.camera2} API.
2125public class ResolutionFeature extends CameraFeature <ResolutionPreset > {
2226 private Size captureSize ;
2327 private Size previewSize ;
24- private CamcorderProfile recordingProfile ;
28+ private CamcorderProfile recordingProfileLegacy ;
29+ private EncoderProfiles recordingProfile ;
2530 private ResolutionPreset currentSetting ;
2631 private int cameraId ;
2732
@@ -51,7 +56,11 @@ public ResolutionFeature(
5156 *
5257 * @return Resolution information to configure the {@link android.hardware.camera2} API.
5358 */
54- public CamcorderProfile getRecordingProfile () {
59+ public CamcorderProfile getRecordingProfileLegacy () {
60+ return this .recordingProfileLegacy ;
61+ }
62+
63+ public EncoderProfiles getRecordingProfile () {
5564 return this .recordingProfile ;
5665 }
5766
@@ -100,19 +109,29 @@ public void updateBuilder(CaptureRequest.Builder requestBuilder) {
100109 }
101110
102111 @ VisibleForTesting
103- static Size computeBestPreviewSize (int cameraId , ResolutionPreset preset ) {
112+ static Size computeBestPreviewSize (int cameraId , ResolutionPreset preset )
113+ throws IndexOutOfBoundsException {
104114 if (preset .ordinal () > ResolutionPreset .high .ordinal ()) {
105115 preset = ResolutionPreset .high ;
106116 }
117+ if (Build .VERSION .SDK_INT >= 31 ) {
118+ EncoderProfiles profile =
119+ getBestAvailableCamcorderProfileForResolutionPreset (cameraId , preset );
120+ List <EncoderProfiles .VideoProfile > videoProfiles = profile .getVideoProfiles ();
121+ EncoderProfiles .VideoProfile defaultVideoProfile = videoProfiles .get (0 );
107122
108- CamcorderProfile profile =
109- getBestAvailableCamcorderProfileForResolutionPreset (cameraId , preset );
110- return new Size (profile .videoFrameWidth , profile .videoFrameHeight );
123+ return new Size (defaultVideoProfile .getWidth (), defaultVideoProfile .getHeight ());
124+ } else {
125+ @ SuppressWarnings ("deprecation" )
126+ CamcorderProfile profile =
127+ getBestAvailableCamcorderProfileForResolutionPresetLegacy (cameraId , preset );
128+ return new Size (profile .videoFrameWidth , profile .videoFrameHeight );
129+ }
111130 }
112131
113132 /**
114133 * Gets the best possible {@link android.media.CamcorderProfile} for the supplied {@link
115- * ResolutionPreset}.
134+ * ResolutionPreset}. Supports SDK < 31.
116135 *
117136 * @param cameraId Camera identifier which indicates the device's camera for which to select a
118137 * {@link android.media.CamcorderProfile}.
@@ -121,7 +140,7 @@ static Size computeBestPreviewSize(int cameraId, ResolutionPreset preset) {
121140 * @return The best possible {@link android.media.CamcorderProfile} that matches the supplied
122141 * {@link ResolutionPreset}.
123142 */
124- public static CamcorderProfile getBestAvailableCamcorderProfileForResolutionPreset (
143+ public static CamcorderProfile getBestAvailableCamcorderProfileForResolutionPresetLegacy (
125144 int cameraId , ResolutionPreset preset ) {
126145 if (cameraId < 0 ) {
127146 throw new AssertionError (
@@ -164,13 +183,74 @@ public static CamcorderProfile getBestAvailableCamcorderProfileForResolutionPres
164183 }
165184 }
166185
167- private void configureResolution (ResolutionPreset resolutionPreset , int cameraId ) {
186+ @ TargetApi (Build .VERSION_CODES .S )
187+ public static EncoderProfiles getBestAvailableCamcorderProfileForResolutionPreset (
188+ int cameraId , ResolutionPreset preset ) {
189+ if (cameraId < 0 ) {
190+ throw new AssertionError (
191+ "getBestAvailableCamcorderProfileForResolutionPreset can only be used with valid (>=0) camera identifiers." );
192+ }
193+
194+ String cameraIdString = Integer .toString (cameraId );
195+
196+ switch (preset ) {
197+ // All of these cases deliberately fall through to get the best available profile.
198+ case max :
199+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_HIGH )) {
200+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_HIGH );
201+ }
202+ case ultraHigh :
203+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_2160P )) {
204+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_2160P );
205+ }
206+ case veryHigh :
207+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_1080P )) {
208+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_1080P );
209+ }
210+ case high :
211+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_720P )) {
212+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_720P );
213+ }
214+ case medium :
215+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_480P )) {
216+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_480P );
217+ }
218+ case low :
219+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_QVGA )) {
220+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_QVGA );
221+ }
222+ default :
223+ if (CamcorderProfile .hasProfile (cameraId , CamcorderProfile .QUALITY_LOW )) {
224+ return CamcorderProfile .getAll (cameraIdString , CamcorderProfile .QUALITY_LOW );
225+ }
226+
227+ throw new IllegalArgumentException (
228+ "No capture session available for current capture session." );
229+ }
230+ }
231+
232+ private void configureResolution (ResolutionPreset resolutionPreset , int cameraId )
233+ throws IndexOutOfBoundsException {
168234 if (!checkIsSupported ()) {
169235 return ;
170236 }
171- recordingProfile =
172- getBestAvailableCamcorderProfileForResolutionPreset (cameraId , resolutionPreset );
173- captureSize = new Size (recordingProfile .videoFrameWidth , recordingProfile .videoFrameHeight );
237+
238+ if (Build .VERSION .SDK_INT >= 31 ) {
239+ recordingProfile =
240+ getBestAvailableCamcorderProfileForResolutionPreset (cameraId , resolutionPreset );
241+ List <EncoderProfiles .VideoProfile > videoProfiles = recordingProfile .getVideoProfiles ();
242+
243+ EncoderProfiles .VideoProfile defaultVideoProfile = videoProfiles .get (0 );
244+ captureSize = new Size (defaultVideoProfile .getWidth (), defaultVideoProfile .getHeight ());
245+ } else {
246+ @ SuppressWarnings ("deprecation" )
247+ CamcorderProfile camcorderProfile =
248+ getBestAvailableCamcorderProfileForResolutionPresetLegacy (cameraId , resolutionPreset );
249+ recordingProfileLegacy = camcorderProfile ;
250+ captureSize =
251+ new Size (recordingProfileLegacy .videoFrameWidth , recordingProfileLegacy .videoFrameHeight );
252+ }
253+
174254 previewSize = computeBestPreviewSize (cameraId , resolutionPreset );
175255 }
176256}
0 commit comments