forked from flutter/packages
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[camerax] Use
AspectRatioStrategy
to help automatic selection of ex…
…pected resolution (flutter#6357) Defines `AspectRatioStategy`s that will help CameraX select the resolution we expect. Fixes flutter/flutter#144363.
- Loading branch information
Showing
22 changed files
with
1,431 additions
and
428 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
...camerax/android/src/main/java/io/flutter/plugins/camerax/ResolutionFilterHostApiImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright 2013 The Flutter 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.camerax; | ||
|
||
import android.util.Size; | ||
import androidx.annotation.NonNull; | ||
import androidx.annotation.VisibleForTesting; | ||
import androidx.camera.core.resolutionselector.ResolutionFilter; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionFilterHostApi; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo; | ||
import java.util.List; | ||
|
||
/** | ||
* Host API implementation for {@link ResolutionFilter}. | ||
* | ||
* <p>This class handles instantiating and adding native object instances that are attached to a | ||
* Dart instance or handle method calls on the associated native class or an instance of the class. | ||
*/ | ||
public class ResolutionFilterHostApiImpl implements ResolutionFilterHostApi { | ||
private final InstanceManager instanceManager; | ||
private final ResolutionFilterFactory resolutionFilterFactory; | ||
|
||
/** | ||
* Proxy for constructing {@link ResolutionFilter}s with particular attributes, as detailed by | ||
* documentation below. | ||
*/ | ||
@VisibleForTesting | ||
public static class ResolutionFilterFactory { | ||
/** | ||
* Creates an instance of {@link ResolutionFilter} that moves the {@code preferredSize} to the | ||
* front of the list of supported resolutions so that it can be prioritized by CameraX. | ||
* | ||
* <p>If the preferred {@code Size} is not found, then this creates a {@link ResolutionFilter} | ||
* that leaves the priority of supported resolutions unadjusted. | ||
*/ | ||
@NonNull | ||
public ResolutionFilter createWithOnePreferredSize(@NonNull Size preferredSize) { | ||
return new ResolutionFilter() { | ||
@Override | ||
@NonNull | ||
public List<Size> filter(@NonNull List<Size> supportedSizes, int rotationDegrees) { | ||
int preferredSizeIndex = supportedSizes.indexOf(preferredSize); | ||
|
||
if (preferredSizeIndex > -1) { | ||
supportedSizes.remove(preferredSizeIndex); | ||
supportedSizes.add(0, preferredSize); | ||
} | ||
|
||
return supportedSizes; | ||
} | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* Constructs a {@link ResolutionFilterHostApiImpl}. | ||
* | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
*/ | ||
public ResolutionFilterHostApiImpl(@NonNull InstanceManager instanceManager) { | ||
this(instanceManager, new ResolutionFilterFactory()); | ||
} | ||
|
||
/** | ||
* Constructs a {@link ResolutionFilterHostApiImpl}. | ||
* | ||
* @param instanceManager maintains instances stored to communicate with attached Dart objects | ||
* @param resolutionFilterFactory proxy for constructing different kinds of {@link | ||
* ResolutionFilter}s | ||
*/ | ||
@VisibleForTesting | ||
ResolutionFilterHostApiImpl( | ||
@NonNull InstanceManager instanceManager, | ||
@NonNull ResolutionFilterFactory resolutionFilterFactory) { | ||
this.instanceManager = instanceManager; | ||
this.resolutionFilterFactory = resolutionFilterFactory; | ||
} | ||
|
||
/** | ||
* Creates a {@link ResolutionFilter} that prioritizes the specified {@code preferredResolution} | ||
* over all other resolutions. | ||
*/ | ||
@Override | ||
public void createWithOnePreferredSize( | ||
@NonNull Long identifier, @NonNull ResolutionInfo preferredResolution) { | ||
Size preferredSize = | ||
new Size( | ||
preferredResolution.getWidth().intValue(), preferredResolution.getHeight().intValue()); | ||
instanceManager.addDartCreatedInstance( | ||
resolutionFilterFactory.createWithOnePreferredSize(preferredSize), identifier); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
...ndroid_camerax/android/src/test/java/io/flutter/plugins/camerax/ResolutionFilterTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2013 The Flutter 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.camerax; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
import android.util.Size; | ||
import androidx.camera.core.resolutionselector.ResolutionFilter; | ||
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ResolutionInfo; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.mockito.junit.MockitoJUnit; | ||
import org.mockito.junit.MockitoRule; | ||
import org.robolectric.RobolectricTestRunner; | ||
|
||
@RunWith(RobolectricTestRunner.class) | ||
public class ResolutionFilterTest { | ||
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); | ||
|
||
InstanceManager instanceManager; | ||
|
||
@Before | ||
public void setUp() { | ||
instanceManager = InstanceManager.create(identifier -> {}); | ||
} | ||
|
||
@After | ||
public void tearDown() { | ||
instanceManager.stopFinalizationListener(); | ||
} | ||
|
||
@Test | ||
public void hostApiCreateWithOnePreferredSize_createsExpectedResolutionFilterInstance() { | ||
final ResolutionFilterHostApiImpl hostApi = new ResolutionFilterHostApiImpl(instanceManager); | ||
final long instanceIdentifier = 50; | ||
final long preferredResolutionWidth = 20; | ||
final long preferredResolutionHeight = 80; | ||
final ResolutionInfo preferredResolution = | ||
new ResolutionInfo.Builder() | ||
.setWidth(preferredResolutionWidth) | ||
.setHeight(preferredResolutionHeight) | ||
.build(); | ||
|
||
hostApi.createWithOnePreferredSize(instanceIdentifier, preferredResolution); | ||
|
||
// Test that instance filters supported resolutions as expected. | ||
final ResolutionFilter resolutionFilter = instanceManager.getInstance(instanceIdentifier); | ||
final Size fakeSupportedSize1 = new Size(720, 480); | ||
final Size fakeSupportedSize2 = new Size(20, 80); | ||
final Size fakeSupportedSize3 = new Size(2, 8); | ||
final Size preferredSize = | ||
new Size((int) preferredResolutionWidth, (int) preferredResolutionHeight); | ||
|
||
final ArrayList<Size> fakeSupportedSizes = new ArrayList<Size>(); | ||
fakeSupportedSizes.add(fakeSupportedSize1); | ||
fakeSupportedSizes.add(fakeSupportedSize2); | ||
fakeSupportedSizes.add(preferredSize); | ||
fakeSupportedSizes.add(fakeSupportedSize3); | ||
|
||
// Test the case where preferred resolution is supported. | ||
List<Size> filteredSizes = resolutionFilter.filter(fakeSupportedSizes, 90); | ||
assertEquals(filteredSizes.get(0), preferredSize); | ||
|
||
// Test the case where preferred resolution is not supported. | ||
fakeSupportedSizes.remove(0); | ||
filteredSizes = resolutionFilter.filter(fakeSupportedSizes, 90); | ||
assertEquals(filteredSizes, fakeSupportedSizes); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.