summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-06-23 07:34:55 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-06-23 07:34:55 +0000
commit90c905e5c83b63f6d45ea7066502da0e6423305e (patch)
tree9e811a75ce6b97fb44a49f2c6006c9fc5e6d301e
parent2cdbec4b18e31bd81327936630eef9bdc7660c04 (diff)
parentbbc34be67f4b7c4f71036b5d686c34861955f3fb (diff)
downloadex-busytown-mac-infra-release.tar.gz
Merge "Snap for 11992377 from e288e7780dfdd5bb593d3de8271272b758e072c6 to busytown-mac-infra-release" into busytown-mac-infra-releasebusytown-mac-infra-release
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java2
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java17
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java106
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java14
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java115
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java21
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java5
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java35
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java10
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java16
-rw-r--r--camera2/extensions/eyesFreeVidSample/Android.bp3
-rw-r--r--camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java216
-rw-r--r--camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java206
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java20
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java6
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java6
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java6
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java14
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java7
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java6
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java5
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java6
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java10
-rw-r--r--camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java16
-rw-r--r--common/tests/Android.bp7
-rw-r--r--common/tests/src/com/android/common/OperationSchedulerTest.java5
-rw-r--r--common/tests/src/com/android/common/Rfc822ValidatorTest.java2
-rw-r--r--common/tests/src/com/android/common/widget/CompositeCursorAdapterTest.java3
-rw-r--r--framesequence/jni/Android.bp31
-rw-r--r--framesequence/jni/BitmapDecoderJNI.cpp30
-rw-r--r--framesequence/jni/Color.h31
-rw-r--r--framesequence/jni/FrameSequence.cpp35
-rw-r--r--framesequence/jni/FrameSequence.h57
-rw-r--r--framesequence/jni/FrameSequenceJNI.cpp192
-rw-r--r--framesequence/jni/FrameSequenceJNI.h24
-rw-r--r--framesequence/jni/FrameSequence_gif.cpp362
-rw-r--r--framesequence/jni/FrameSequence_gif.h93
-rw-r--r--framesequence/jni/FrameSequence_webp.cpp405
-rw-r--r--framesequence/jni/FrameSequence_webp.h106
-rw-r--r--framesequence/jni/JNIHelpers.cpp33
-rw-r--r--framesequence/jni/JNIHelpers.h29
-rw-r--r--framesequence/jni/Registry.cpp59
-rw-r--r--framesequence/jni/Registry.h53
-rw-r--r--framesequence/jni/Stream.cpp156
-rw-r--r--framesequence/jni/Stream.h94
-rw-r--r--framesequence/jni/utils/log.h288
-rw-r--r--framesequence/jni/utils/math.h30
-rw-r--r--framesequence/samples/FrameSequenceSamples/Android.bp39
-rw-r--r--framesequence/samples/FrameSequenceSamples/AndroidManifest.xml26
-rw-r--r--framesequence/samples/FrameSequenceSamples/build.xml99
-rw-r--r--framesequence/samples/FrameSequenceSamples/proguard.flags3
-rw-r--r--framesequence/samples/FrameSequenceSamples/project.properties14
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/drawable-hdpi/ic_launcher.pngbin9397 -> 0 bytes
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/drawable-mdpi/ic_launcher.pngbin5237 -> 0 bytes
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/drawable-xhdpi/ic_launcher.pngbin14383 -> 0 bytes
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/layout/basic_test_activity.xml42
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/raw/animated_gif.gifbin34978 -> 0 bytes
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/raw/animated_webp.webpbin380850 -> 0 bytes
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/values/strings.xml16
-rw-r--r--framesequence/samples/FrameSequenceSamples/res/values/styles.xml7
-rw-r--r--framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/FrameSequenceTest.java127
-rw-r--r--framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/SamplesList.java68
-rw-r--r--framesequence/src/android/support/rastermill/FrameSequence.java124
-rw-r--r--framesequence/src/android/support/rastermill/FrameSequenceDrawable.java436
64 files changed, 816 insertions, 3178 deletions
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
index 1f285720..2723c41f 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
@@ -29,7 +29,7 @@ import android.util.Log;
*/
public class ExtensionVersionImpl {
private static final String TAG = "ExtenderVersionImpl";
- private static final String VERSION = "1.4.0";
+ private static final String VERSION = "1.5.0";
/**
* @hide
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
index abcbf5fd..821b11fe 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -216,4 +217,20 @@ public interface AdvancedExtenderImpl {
* @since 1.4
*/
boolean isPostviewAvailable();
+
+ /**
+ * Returns a list of {@link CameraCharacteristics} key/value pairs for apps to use when
+ * querying the Extensions specific {@link CameraCharacteristics}.
+ *
+ * <p>To ensure the correct {@link CameraCharacteristics} are used when an extension is
+ * enabled, an application should prioritize the value returned from the list if the
+ * {@link CameraCharacteristics} key is present. If the key doesn't exist in the returned list,
+ * then the application should query the value using
+ * {@link CameraCharacteristics#get(CameraCharacteristics.Key)}.
+ *
+ * <p>For example, an extension may limit the zoom ratio range. In this case, an OEM can return
+ * a new zoom ratio range for the key {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
+ * @since 1.5
+ */
+ List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues();
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
index 00b57058..b97fdbda 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
@@ -26,11 +26,13 @@ import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
+import android.hardware.DataSpace;
import android.media.Image;
import android.media.Image.Plane;
import android.media.ImageWriter;
@@ -112,7 +114,8 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
@Override
public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(String cameraId) {
- return filterOutputResolutions(Arrays.asList(ImageFormat.JPEG, ImageFormat.YUV_420_888));
+ return filterOutputResolutions(Arrays.asList(ImageFormat.JPEG, ImageFormat.YUV_420_888,
+ ImageFormat.JPEG_R));
}
@Override
@@ -157,6 +160,8 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
protected AtomicInteger mNextCaptureSequenceId = new AtomicInteger(1);
+ protected boolean mProcessCapture = true;
+
protected void appendTag(String tag) {
TAG += tag;
}
@@ -192,17 +197,33 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
// Image Capture
if (mCaptureOutputSurfaceConfig.getSurface() != null) {
- Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
- captureOutputConfigBuilder =
- Camera2OutputConfigImplBuilder.newImageReaderConfig(
- mCaptureOutputSurfaceConfig.getSize(),
- ImageFormat.YUV_420_888,
- BASIC_CAPTURE_PROCESS_MAX_IMAGES);
+ // For this sample, JPEG_R will not be processed
+ if (isJpegR(mCaptureOutputSurfaceConfig)) {
+ Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
+
+ captureOutputConfigBuilder =
+ Camera2OutputConfigImplBuilder.newSurfaceConfig(
+ mCaptureOutputSurfaceConfig.getSurface());
+
+ mCaptureOutputConfig = captureOutputConfigBuilder.build();
+
+ builder.addOutputConfig(mCaptureOutputConfig);
+ mProcessCapture = false;
+ } else {
+ Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
+
+ captureOutputConfigBuilder =
+ Camera2OutputConfigImplBuilder.newImageReaderConfig(
+ mCaptureOutputSurfaceConfig.getSize(),
+ ImageFormat.YUV_420_888,
+ BASIC_CAPTURE_PROCESS_MAX_IMAGES,
+ mCaptureOutputSurfaceConfig.getUsage());
- mCaptureOutputConfig = captureOutputConfigBuilder.build();
+ mCaptureOutputConfig = captureOutputConfigBuilder.build();
- builder.addOutputConfig(mCaptureOutputConfig);
+ builder.addOutputConfig(mCaptureOutputConfig);
+ }
}
addSessionParameter(builder);
@@ -263,6 +284,19 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
}
}
+ protected boolean isJpegR(OutputSurfaceImpl surfaceConfig) {
+ // The surface configuration format for JPEG_R can be specified in either format.
+ // Camera2 uses HAL_PIXEL_FORMAT_BLOB and CameraX uses ImageFormat.JPEG_R.
+ return ((surfaceConfig.getImageFormat() == JpegEncoder.HAL_PIXEL_FORMAT_BLOB) &&
+ (surfaceConfig.getDataspace() == DataSpace.DATASPACE_JPEG_R)) ||
+ (surfaceConfig.getImageFormat() == ImageFormat.JPEG_R);
+ }
+
+ protected boolean isJpeg(OutputSurfaceImpl surfaceConfig) {
+ return (JpegEncoder.imageFormatToPublic(surfaceConfig.getImageFormat()) ==
+ ImageFormat.JPEG) || (surfaceConfig.getImageFormat() == ImageFormat.JPEG);
+ }
+
protected void addTriggerRequestKeys(RequestBuilder builder,
Map<CaptureRequest.Key<?>, Object> triggers) {
HashSet<CaptureRequest.Key> supportedCaptureRequestKeys =
@@ -309,13 +343,13 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
@Override
public void onCaptureFailed(RequestProcessorImpl.Request request,
CaptureFailure captureFailure) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, captureFailure.getReason());
}
@Override
public void onCaptureBufferLost(RequestProcessorImpl.Request request,
long frameNumber, int outputStreamId) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, CaptureFailure.REASON_ERROR);
}
@Override
@@ -340,16 +374,21 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
if (mCaptureOutputSurfaceConfig.getSurface() != null) {
synchronized (mLockCaptureSurfaceImageWriter) {
- if (JpegEncoder.imageFormatToPublic(mCaptureOutputSurfaceConfig
- .getImageFormat()) == ImageFormat.JPEG) {
+ if (isJpegR(mCaptureOutputSurfaceConfig)) {
+ return;
+ }
+
+ if (isJpeg(mCaptureOutputSurfaceConfig)) {
mCaptureSurfaceImageWriter = new ImageWriter
.Builder(mCaptureOutputSurfaceConfig.getSurface())
.setImageFormat(ImageFormat.JPEG)
.setMaxImages(MAX_NUM_IMAGES)
// For JPEG format, width x height should be set to (w*h) x 1
// since the JPEG image is returned as a 1D byte array
- .setWidthAndHeight(mCaptureOutputSurfaceConfig.getSize().getWidth()
- * mCaptureOutputSurfaceConfig.getSize().getHeight(), 1)
+ .setWidthAndHeight(
+ mCaptureOutputSurfaceConfig.getSize().getWidth()
+ * mCaptureOutputSurfaceConfig.getSize().getHeight(),
+ 1)
.build();
} else {
mCaptureSurfaceImageWriter = new ImageWriter
@@ -402,13 +441,13 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
@Override
public void onCaptureFailed(RequestProcessorImpl.Request request,
CaptureFailure captureFailure) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, captureFailure.getReason());
}
@Override
public void onCaptureBufferLost(RequestProcessorImpl.Request request,
long frameNumber, int outputStreamId) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, CaptureFailure.REASON_ERROR);
}
@Override
@@ -490,21 +529,25 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
- mImageCaptureCaptureResultImageMatcher.setCameraCaptureCallback(
- totalCaptureResult,
- requestProcessorRequest.getCaptureStageId());
+ if (!mProcessCapture) {
+ captureCallback.onCaptureProcessStarted(seqId);
+ } else {
+ mImageCaptureCaptureResultImageMatcher.setCameraCaptureCallback(
+ totalCaptureResult,
+ requestProcessorRequest.getCaptureStageId());
+ }
}
@Override
public void onCaptureFailed(RequestProcessorImpl.Request request,
CaptureFailure captureFailure) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, captureFailure.getReason());
}
@Override
public void onCaptureBufferLost(RequestProcessorImpl.Request request,
long frameNumber, int outputStreamId) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, CaptureFailure.REASON_ERROR);
}
@Override
@@ -523,7 +566,7 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
mRequestProcessor.submit(requestList, callback);
- if (mCaptureOutputSurfaceConfig.getSurface() != null) {
+ if (mCaptureOutputSurfaceConfig.getSurface() != null && mProcessCapture) {
mRequestProcessor.setImageProcessor(mCaptureOutputConfig.getId(),
new ImageProcessorImpl() {
@Override
@@ -696,4 +739,21 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isPostviewAvailable() {
return false;
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+ Range<Float> zoomRange = mCameraCharacteristics
+ .get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
+ float zoomRangeLower = Math.max(1f, zoomRange.getLower());
+ float zoomRangeUpper = Math.min(10f, zoomRange.getUpper());
+ return Arrays.asList(
+ Pair.create(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE,
+ Range.create(zoomRangeLower, zoomRangeUpper)),
+ Pair.create(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES,
+ new int[]{
+ CameraMetadata.CONTROL_AF_MODE_OFF,
+ CameraMetadata.CONTROL_AF_MODE_AUTO
+ })
+ );
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
index 868be834..9ae5f838 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
@@ -49,9 +49,9 @@ public class Camera2OutputConfigImplBuilder {
* with the given parameters.
*/
public static Camera2OutputConfigImplBuilder newImageReaderConfig(
- Size size, int imageFormat, int maxImages) {
+ Size size, int imageFormat, int maxImages, long usage) {
return new Camera2OutputConfigImplBuilder(
- new ImageReaderOutputConfigImplImpl(size, imageFormat, maxImages));
+ new ImageReaderOutputConfigImplImpl(size, imageFormat, maxImages, usage));
}
/**
@@ -181,11 +181,14 @@ public class Camera2OutputConfigImplBuilder {
private Size mSize;
private int mImageFormat;
private int mMaxImages;
+ private long mUsage;
- ImageReaderOutputConfigImplImpl(Size size, int imageFormat, int maxImages) {
+ ImageReaderOutputConfigImplImpl(Size size, int imageFormat, int maxImages,
+ long usage) {
mSize = size;
mImageFormat = imageFormat;
mMaxImages = maxImages;
+ mUsage = usage;
}
@Override
@@ -202,6 +205,11 @@ public class Camera2OutputConfigImplBuilder {
public int getMaxImages() {
return mMaxImages;
}
+
+ @Override
+ public long getUsage() {
+ return mUsage;
+ }
}
private static class MultiResolutionImageReaderOutputConfigImplImpl extends OutputConfigImplImpl
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java
new file mode 100644
index 00000000..2f6d1cf9
--- /dev/null
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stub advanced extender implementation for eyes free videography.
+ *
+ * <p>This class should be implemented by OEM and deployed to the target devices.
+ *
+ * @since 1.5
+ */
+@SuppressLint("UnknownNullness")
+public class EyesFreeVideographyAdvancedExtenderImpl implements AdvancedExtenderImpl {
+ public EyesFreeVideographyAdvancedExtenderImpl() {
+ }
+
+ @Override
+ public boolean isExtensionAvailable(String cameraId,
+ Map<String, CameraCharacteristics> characteristicsMap) {
+ return false;
+ }
+
+ @Override
+ public void init(String cameraId,
+ Map<String, CameraCharacteristics> characteristicsMap) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public Range<Long> getEstimatedCaptureLatencyRange(
+ String cameraId, Size size, int imageFormat) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+ String cameraId) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+
+ @Override
+ public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+ String cameraId) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public Map<Integer, List<Size>> getSupportedPostviewResolutions(
+ Size captureSize) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public List<Size> getSupportedYuvAnalysisResolutions(
+ String cameraId) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public SessionProcessorImpl createSessionProcessor() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public boolean isCaptureProcessProgressAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public boolean isPostviewAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>>
+ getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
index d8b99289..68a84b7a 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
@@ -129,7 +129,11 @@ public class HdrAdvancedExtenderImpl extends BaseAdvancedExtenderImpl {
@Override
public int startCapture(@NonNull CaptureCallback captureCallback) {
List<RequestProcessorImpl.Request> requestList = new ArrayList<>();
- addCaptureRequestParameters(requestList);
+ if (mProcessCapture) {
+ addCaptureRequestParameters(requestList);
+ } else {
+ super.addCaptureRequestParameters(requestList);
+ }
final int seqId = mNextCaptureSequenceId.getAndIncrement();
RequestProcessorImpl.Callback callback = new RequestProcessorImpl.Callback() {
@@ -138,7 +142,7 @@ public class HdrAdvancedExtenderImpl extends BaseAdvancedExtenderImpl {
@Override
public void onCaptureStarted(RequestProcessorImpl.Request request,
long frameNumber, long timestamp) {
- if (!mCaptureStarted) {
+ if (!mCaptureStarted || !mProcessCapture) {
mCaptureStarted = true;
captureCallback.onCaptureStarted(seqId, timestamp);
}
@@ -156,9 +160,14 @@ public class HdrAdvancedExtenderImpl extends BaseAdvancedExtenderImpl {
RequestBuilder.RequestProcessorRequest requestProcessorRequest =
(RequestBuilder.RequestProcessorRequest) request;
- mImageCaptureCaptureResultImageMatcher.setCameraCaptureCallback(
- totalCaptureResult,
- requestProcessorRequest.getCaptureStageId());
+ if (!mProcessCapture) {
+ captureCallback.onCaptureProcessStarted(seqId);
+ addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
+ } else {
+ mImageCaptureCaptureResultImageMatcher.setCameraCaptureCallback(
+ totalCaptureResult,
+ requestProcessorRequest.getCaptureStageId());
+ }
}
@Override
@@ -189,7 +198,7 @@ public class HdrAdvancedExtenderImpl extends BaseAdvancedExtenderImpl {
mRequestProcessor.submit(requestList, callback);
- if (mCaptureOutputSurfaceConfig.getSurface() != null) {
+ if (mCaptureOutputSurfaceConfig.getSurface() != null && mProcessCapture) {
mRequestProcessor.setImageProcessor(mCaptureOutputConfig.getId(),
new ImageProcessorImpl() {
boolean mCaptureStarted = false;
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
index ca4dcafa..8ce2733c 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
@@ -38,4 +38,9 @@ public interface ImageReaderOutputConfigImpl extends Camera2OutputConfigImpl {
* Gets the capacity for TYPE_IMAGEREADER.
*/
int getMaxImages();
+
+ /**
+ * Get the surface usage bits.
+ */
+ long getUsage();
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
index 82940635..ba4ea4ca 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
@@ -105,7 +105,8 @@ public class NightAdvancedExtenderImpl extends BaseAdvancedExtenderImpl {
Camera2OutputConfigImplBuilder.newImageReaderConfig(
mPreviewOutputSurfaceConfig.getSize(),
ImageFormat.YUV_420_888,
- BASIC_CAPTURE_PROCESS_MAX_IMAGES);
+ BASIC_CAPTURE_PROCESS_MAX_IMAGES,
+ mPreviewOutputSurfaceConfig.getUsage());
mPreviewOutputConfig = previewOutputConfigBuilder.build();
@@ -114,17 +115,33 @@ public class NightAdvancedExtenderImpl extends BaseAdvancedExtenderImpl {
// Image Capture
if (mCaptureOutputSurfaceConfig.getSurface() != null) {
- Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
- captureOutputConfigBuilder =
- Camera2OutputConfigImplBuilder.newImageReaderConfig(
- mCaptureOutputSurfaceConfig.getSize(),
- ImageFormat.YUV_420_888,
- BASIC_CAPTURE_PROCESS_MAX_IMAGES);
+ // For this sample, JPEG_R will not be processed
+ if (isJpegR(mCaptureOutputSurfaceConfig)) {
+ Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
+
+ captureOutputConfigBuilder =
+ Camera2OutputConfigImplBuilder.newSurfaceConfig(
+ mCaptureOutputSurfaceConfig.getSurface());
+
+ mCaptureOutputConfig = captureOutputConfigBuilder.build();
- mCaptureOutputConfig = captureOutputConfigBuilder.build();
+ builder.addOutputConfig(mCaptureOutputConfig);
+ mProcessCapture = false;
+ } else {
+ Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
- builder.addOutputConfig(mCaptureOutputConfig);
+ captureOutputConfigBuilder =
+ Camera2OutputConfigImplBuilder.newImageReaderConfig(
+ mCaptureOutputSurfaceConfig.getSize(),
+ ImageFormat.YUV_420_888,
+ BASIC_CAPTURE_PROCESS_MAX_IMAGES,
+ mCaptureOutputSurfaceConfig.getUsage());
+
+ mCaptureOutputConfig = captureOutputConfigBuilder.build();
+
+ builder.addOutputConfig(mCaptureOutputConfig);
+ }
}
addSessionParameter(builder);
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
index f6920296..f173c1b7 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
@@ -39,4 +39,14 @@ public interface OutputSurfaceImpl {
* Gets the image format.
*/
int getImageFormat();
+
+ /**
+ * Gets the dataspace.
+ */
+ int getDataspace();
+
+ /**
+ * Get the surface usage bits.
+ */
+ long getUsage();
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
index d18aa926..c9eca432 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
@@ -19,6 +19,7 @@ package androidx.camera.extensions.impl.advanced;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.util.Pair;
@@ -390,5 +391,20 @@ public interface SessionProcessorImpl {
* @since 1.4
*/
void onCaptureProcessProgressed(int progress);
+
+ /**
+ * This method is called instead of
+ * {@link #onCaptureProcessStarted} when the camera device failed
+ * to produce the required input for the device-specific extension. The
+ * cause could be a failed camera capture request, a failed
+ * capture result or dropped camera frame.
+ * The callback allows clients to be notified
+ * about failure reason.
+ *
+ * @param captureSequenceId id of the current capture sequence
+ * @param reason The capture failure reason @see CaptureFailure#FailureReason
+ * @since 1.5
+ */
+ void onCaptureFailed(int captureSequenceId, int reason);
}
}
diff --git a/camera2/extensions/eyesFreeVidSample/Android.bp b/camera2/extensions/eyesFreeVidSample/Android.bp
index 64709bdc..3d9567e8 100644
--- a/camera2/extensions/eyesFreeVidSample/Android.bp
+++ b/camera2/extensions/eyesFreeVidSample/Android.bp
@@ -22,5 +22,6 @@ android_app {
static_libs: [
"androidx.annotation_annotation"
],
- platform_apis: true
+ platform_apis: true,
+ system_ext_specific: true
}
diff --git a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java
index cf669c7a..d175c1a6 100644
--- a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java
+++ b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java
@@ -16,6 +16,7 @@
package android.camera.extensions.impl.service;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -26,15 +27,23 @@ import java.util.Set;
import android.annotation.FlaggedApi;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraExtensionCharacteristics;
import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.ExtensionCaptureRequest;
+import android.hardware.camera2.ExtensionCaptureResult;
import android.hardware.camera2.extension.AdvancedExtender;
import android.hardware.camera2.extension.CameraExtensionService;
import android.hardware.camera2.extension.CharacteristicsMap;
import android.hardware.camera2.extension.SessionProcessor;
+import android.hardware.camera2.params.StreamConfiguration;
+import android.hardware.camera2.params.StreamConfigurationDuration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.IBinder;
+import android.util.Pair;
+import android.util.Range;
import android.util.Size;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
@@ -75,7 +84,13 @@ public class EyesFreeVidService extends CameraExtensionService {
@Override
public AdvancedExtender onInitializeAdvancedExtension(int extensionType) {
mCameraManager = getSystemService(CameraManager.class);
- return new AdvancedExtenderEyesFreeImpl(mCameraManager);
+
+ switch (extensionType) {
+ case CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY:
+ return new AdvancedExtenderEyesFreeImpl(mCameraManager);
+ default:
+ return new AdvancedExtenderImpl(mCameraManager);
+ }
}
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@@ -96,7 +111,7 @@ public class EyesFreeVidService extends CameraExtensionService {
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@Override
- public void init(String cameraId, CharacteristicsMap map) {
+ public void initialize(String cameraId, CharacteristicsMap map) {
mCameraCharacteristics = map.get(cameraId);
}
@@ -125,6 +140,10 @@ public class EyesFreeVidService extends CameraExtensionService {
return formatResolutions;
}
+ protected CameraCharacteristics getCameraCharacteristics() {
+ return mCameraCharacteristics;
+ }
+
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@Override
public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
@@ -146,7 +165,12 @@ public class EyesFreeVidService extends CameraExtensionService {
final CaptureRequest.Key [] CAPTURE_REQUEST_SET = {CaptureRequest.CONTROL_ZOOM_RATIO,
CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_REGIONS,
CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.JPEG_QUALITY,
- CaptureRequest.JPEG_ORIENTATION};
+ CaptureRequest.JPEG_ORIENTATION, ExtensionCaptureRequest.EFV_PADDING_ZOOM_FACTOR,
+ ExtensionCaptureRequest.EFV_AUTO_ZOOM,
+ ExtensionCaptureRequest.EFV_MAX_PADDING_ZOOM_FACTOR,
+ ExtensionCaptureRequest.EFV_STABILIZATION_MODE,
+ ExtensionCaptureRequest.EFV_TRANSLATE_VIEWPORT,
+ ExtensionCaptureRequest.EFV_ROTATE_VIEWPORT};
return Arrays.asList(CAPTURE_REQUEST_SET);
}
@@ -157,8 +181,192 @@ public class EyesFreeVidService extends CameraExtensionService {
final CaptureResult.Key [] CAPTURE_RESULT_SET = {CaptureResult.CONTROL_ZOOM_RATIO,
CaptureResult.CONTROL_AF_MODE, CaptureResult.CONTROL_AF_REGIONS,
CaptureResult.CONTROL_AF_TRIGGER, CaptureResult.CONTROL_AF_STATE,
- CaptureResult.JPEG_QUALITY, CaptureResult.JPEG_ORIENTATION};
+ CaptureResult.JPEG_QUALITY, CaptureResult.JPEG_ORIENTATION,
+ ExtensionCaptureResult.EFV_PADDING_REGION,
+ ExtensionCaptureResult.EFV_AUTO_ZOOM,
+ ExtensionCaptureResult.EFV_MAX_PADDING_ZOOM_FACTOR,
+ ExtensionCaptureResult.EFV_AUTO_ZOOM_PADDING_REGION,
+ ExtensionCaptureResult.EFV_STABILIZATION_MODE,
+ ExtensionCaptureResult.EFV_TARGET_COORDINATES,
+ ExtensionCaptureResult.EFV_PADDING_ZOOM_FACTOR,
+ ExtensionCaptureResult.EFV_TRANSLATE_VIEWPORT,
+ ExtensionCaptureResult.EFV_ROTATE_VIEWPORT
+ };
return Arrays.asList(CAPTURE_RESULT_SET);
}
+
+ @FlaggedApi(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET)
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>>
+ getAvailableCharacteristicsKeyValues() {
+ Range<Float> zoomRange = mCameraCharacteristics
+ .get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
+ int[] caps = mCameraCharacteristics
+ .get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+
+ Set<Integer> unsupportedCapabilities = new HashSet<>(Arrays.asList(
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA,
+ CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
+ ));
+
+ List<Integer> filtered = new ArrayList<>();
+ for (int c : caps) {
+ if (unsupportedCapabilities.contains(c)) {
+ continue;
+ }
+ filtered.add(c);
+ }
+ int[] extensionsCaps = new int[filtered.size()];
+ for (int i = 0; i < filtered.size(); i++) {
+ extensionsCaps[i] = filtered.get(i);
+ }
+
+ Set<Integer> supportedFormats = new HashSet<>( Arrays.asList(
+ ImageFormat.YUV_420_888,
+ ImageFormat.JPEG,
+ ImageFormat.JPEG_R,
+ ImageFormat.PRIVATE));
+
+ StreamConfiguration[] configurations = mCameraCharacteristics
+ .get(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ List<StreamConfiguration> tmpConfigs = new ArrayList<>();
+ for (StreamConfiguration sc : configurations) {
+ if (supportedFormats.contains(sc.getFormat())) {
+ tmpConfigs.add(sc);
+ }
+ }
+ StreamConfiguration[] filteredConfigurations =
+ new StreamConfiguration[tmpConfigs.size()];
+ filteredConfigurations = tmpConfigs.toArray(filteredConfigurations);
+
+ StreamConfigurationDuration[] minFrameDurations = mCameraCharacteristics
+ .get(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
+ List<StreamConfigurationDuration> tmpMinFrameDurations = new ArrayList<>();
+ for (StreamConfigurationDuration scd : minFrameDurations) {
+ if (supportedFormats.contains(scd.getFormat())) {
+ tmpMinFrameDurations.add(scd);
+ }
+ }
+ StreamConfigurationDuration[] filteredMinFrameDurations =
+ new StreamConfigurationDuration[tmpMinFrameDurations.size()];
+ filteredMinFrameDurations = tmpMinFrameDurations.toArray(filteredMinFrameDurations);
+
+ StreamConfigurationDuration[] stallDurations = mCameraCharacteristics
+ .get(CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS);
+ List<StreamConfigurationDuration> tmpStallDurations = new ArrayList<>();
+ for (StreamConfigurationDuration scd : stallDurations) {
+ if (supportedFormats.contains(scd.getFormat())) {
+ tmpStallDurations.add(scd);
+ }
+ }
+ StreamConfigurationDuration[] filteredStallDurations =
+ new StreamConfigurationDuration[tmpStallDurations.size()];
+ filteredStallDurations = tmpStallDurations.toArray(filteredStallDurations);
+
+ return Arrays.asList(
+ Pair.create(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ filteredConfigurations),
+ Pair.create(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ filteredMinFrameDurations),
+ Pair.create(CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS,
+ filteredStallDurations),
+ Pair.create(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES,
+ extensionsCaps),
+ Pair.create(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE, zoomRange),
+ Pair.create(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES,
+ new int[]{
+ CameraMetadata.CONTROL_AF_MODE_OFF,
+ CameraMetadata.CONTROL_AF_MODE_AUTO
+ }),
+ Pair.create(
+ CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ new int[]{ CameraCharacteristics
+ .CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
+ }),
+ Pair.create(CameraExtensionCharacteristics.EFV_PADDING_ZOOM_FACTOR_RANGE,
+ new Range<Float>(1.0f, 2.0f))
+ );
+ }
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public static class AdvancedExtenderImpl extends AdvancedExtender {
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ public AdvancedExtenderImpl(@NonNull CameraManager cameraManager) {
+ super(cameraManager);
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public boolean isExtensionAvailable(String cameraId,
+ CharacteristicsMap charsMap) {
+ return false;
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public void initialize(String cameraId, CharacteristicsMap map) {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+ String cameraId) {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ protected Map<Integer, List<Size>> filterOutputResolutions(List<Integer> formats) {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ protected CameraCharacteristics getCameraCharacteristics() {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+ String cameraId) {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public SessionProcessor getSessionProcessor() {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public List<CaptureRequest.Key> getAvailableCaptureRequestKeys(
+ String cameraId) {
+ throw new RuntimeException("Extension not supported");
+
+ }
+
+ @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+ @Override
+ public List<CaptureResult.Key> getAvailableCaptureResultKeys(
+ String cameraId) {
+ throw new RuntimeException("Extension not supported");
+ }
+
+ @FlaggedApi(Flags.FLAG_CAMERA_EXTENSIONS_CHARACTERISTICS_GET)
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>>
+ getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Extension not supported");
+ }
}
}
diff --git a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java
index f23f3a68..92f371fc 100644
--- a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java
+++ b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java
@@ -16,21 +16,28 @@
package android.camera.extensions.impl.service;
-import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.camera.extensions.impl.service.EyesFreeVidService.AdvancedExtenderEyesFreeImpl;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.ExtensionCaptureRequest;
+import android.hardware.camera2.ExtensionCaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.extension.CameraOutputSurface;
import android.hardware.camera2.extension.CharacteristicsMap;
@@ -39,6 +46,7 @@ import android.hardware.camera2.extension.ExtensionOutputConfiguration;
import android.hardware.camera2.extension.RequestProcessor;
import android.hardware.camera2.extension.SessionProcessor;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.SurfaceUtils;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
@@ -70,7 +78,7 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
protected final Object mParametersLock = new Object();
@GuardedBy("mParametersLock")
- protected List<Pair<CaptureRequest.Key, Object>> mParameters = new ArrayList<>();
+ protected HashMap<CaptureRequest.Key, Object> mParametersMap = new HashMap<>();
protected AtomicInteger mNextCaptureSequenceId = new AtomicInteger(1);
@@ -83,6 +91,8 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
protected ImageReader mPreviewImageReader;
protected String mCameraId;
+ protected AtomicBoolean mOnCaptureSessionEndStarted = new AtomicBoolean(false);
+
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
protected EyesFreeVidSessionProcessor(AdvancedExtenderEyesFreeImpl advancedExtender) {
mAdvancedExtender = advancedExtender;
@@ -105,7 +115,7 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
List<CameraOutputSurface> captureList = new ArrayList<>(List.of(imageCaptureSurface));
ExtensionOutputConfiguration captureConfig = new ExtensionOutputConfiguration(
- captureList, CAPTURE_OUTPUT_ID, null, 0);
+ captureList, CAPTURE_OUTPUT_ID, null, -1);
outputs.add(captureConfig);
}
@@ -114,14 +124,14 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
if (previewSurface.getSurface() != null) {
mPreviewImageReader = ImageReader.newInstance(previewSurface.getSize().getWidth(),
previewSurface.getSize().getHeight(), previewSurface.getImageFormat(),
- MAX_NUM_IMAGES);
+ MAX_NUM_IMAGES, SurfaceUtils.getSurfaceUsage(previewSurface.getSurface()));
List<CameraOutputSurface> previewList = new ArrayList<>(List.of(
new CameraOutputSurface(mPreviewImageReader.getSurface(),
previewSurface.getSize())));
ExtensionOutputConfiguration previewConfig = new ExtensionOutputConfiguration(
- previewList, PREVIEW_OUTPUT_ID, null, 0);
+ previewList, PREVIEW_OUTPUT_ID, null, -1);
outputs.add(previewConfig);
}
@@ -181,20 +191,25 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@Override
public void onCaptureSessionEnd() {
+ mOnCaptureSessionEndStarted.set(true);
+
+ if (mRequestProcessor != null) {
+ mRequestProcessor.abortCaptures();
+ }
+
mRequestProcessor = null;
}
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@Override
- public int startRepeating(@Nullable Executor executor,
+ public int startRepeating(@NonNull Executor executor,
@NonNull CaptureCallback captureCallback) {
List<Integer> outputConfigIds = new ArrayList<>(List.of(PREVIEW_OUTPUT_ID));
RequestProcessor.Request requestRes;
- synchronized (mParametersLock) {
- requestRes = new RequestProcessor.Request(outputConfigIds, mParameters,
- CameraDevice.TEMPLATE_PREVIEW);
- }
+
+ requestRes = new RequestProcessor.Request(outputConfigIds, convertParameterMapToList(),
+ CameraDevice.TEMPLATE_PREVIEW);
final int seqId = mNextCaptureSequenceId.getAndIncrement();
@@ -202,7 +217,9 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@Override
public void onCaptureStarted(RequestProcessor.Request request, long frameNumber,
long timestamp) {
- captureCallback.onCaptureStarted(seqId, timestamp);
+ if (!mOnCaptureSessionEndStarted.get()) {
+ captureCallback.onCaptureStarted(seqId, timestamp);
+ }
}
@Override
@@ -213,34 +230,48 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@Override
public void onCaptureCompleted(RequestProcessor.Request request,
TotalCaptureResult totalCaptureResult) {
- addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
- captureCallback.onCaptureProcessStarted(seqId);
+ if (!mOnCaptureSessionEndStarted.get()) {
+ addCaptureResultKeys(seqId, totalCaptureResult, captureCallback, request);
+ captureCallback.onCaptureProcessStarted(seqId);
+ }
}
@Override
public void onCaptureFailed(RequestProcessor.Request request,
CaptureFailure captureFailure) {
- captureCallback.onCaptureFailed(seqId);
+ if (!mOnCaptureSessionEndStarted.get()) {
+ captureCallback.onCaptureFailed(seqId, captureFailure.getReason());
+ }
}
@Override
public void onCaptureBufferLost(RequestProcessor.Request request,
long frameNumber, int outputStreamId) {
- captureCallback.onCaptureFailed(seqId);
+ if (!mOnCaptureSessionEndStarted.get()) {
+ captureCallback.onCaptureFailed(seqId, CaptureFailure.REASON_ERROR);
+ }
}
@Override
public void onCaptureSequenceCompleted(int sequenceId, long frameNumber) {
- captureCallback.onCaptureSequenceCompleted(seqId);
+ if (!mOnCaptureSessionEndStarted.get()) {
+ captureCallback.onCaptureSequenceCompleted(seqId);
+ }
}
@Override
public void onCaptureSequenceAborted(int sequenceId) {
- captureCallback.onCaptureSequenceAborted(seqId);
+ if (!mOnCaptureSessionEndStarted.get()) {
+ captureCallback.onCaptureSequenceAborted(seqId);
+ }
}
};
- mRequestProcessor.setRepeating(requestRes, executor, resCallback);
+ try {
+ mRequestProcessor.setRepeating(requestRes, executor, resCallback);
+ } catch(CameraAccessException e) {
+ return -1;
+ }
return seqId;
}
@@ -248,26 +279,100 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
protected void addCaptureResultKeys(
@NonNull int seqId,
@NonNull TotalCaptureResult result,
- @NonNull CaptureCallback captureCallback) {
-
- CameraMetadataNative cameraMetadataNative = new CameraMetadataNative();
- long vendorId = mAdvancedExtender.getMetadataVendorId(mCameraId);
- cameraMetadataNative.setVendorId(vendorId);
+ @NonNull CaptureCallback captureCallback,
+ @NonNull RequestProcessor.Request request) {
Long shutterTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
if (shutterTimestamp != null) {
List<CaptureResult.Key> captureResultKeys =
mAdvancedExtender.getAvailableCaptureResultKeys(mCameraId);
+ HashMap<CaptureResult.Key, Object> captureResults = new HashMap<>();
for (CaptureResult.Key key : captureResultKeys) {
if (result.get(key) != null) {
- cameraMetadataNative.set(key, result.get(key));
+ captureResults.put(key, result.get(key));
+ }
+ }
+
+ synchronized (mParametersLock) {
+ List<Pair<CaptureRequest.Key, Object>> requestParameters = request.getParameters();
+ boolean autoZoomEnabled = false;
+ boolean stabilizationModeLocked = false;
+ for (Pair<CaptureRequest.Key, Object> parameter : requestParameters) {
+ if (ExtensionCaptureRequest.EFV_AUTO_ZOOM.equals(parameter.first)) {
+ captureResults.put(ExtensionCaptureResult.EFV_AUTO_ZOOM,
+ (boolean) parameter.second);
+ autoZoomEnabled = (boolean) parameter.second;
+ if (autoZoomEnabled &&
+ ExtensionCaptureRequest.EFV_MAX_PADDING_ZOOM_FACTOR.equals(
+ parameter.first)) {
+ captureResults.put(
+ ExtensionCaptureResult.EFV_MAX_PADDING_ZOOM_FACTOR,
+ (Float) parameter.second);
+ }
+ }
+ if (ExtensionCaptureRequest.EFV_PADDING_ZOOM_FACTOR.equals(parameter.first)) {
+ captureResults.put(ExtensionCaptureResult.EFV_PADDING_ZOOM_FACTOR,
+ (Float) parameter.second);
+ }
+ if (ExtensionCaptureRequest.EFV_TRANSLATE_VIEWPORT.equals(parameter.first)) {
+ captureResults.put(ExtensionCaptureResult.EFV_TRANSLATE_VIEWPORT,
+ (Pair<Integer, Integer>) parameter.second);
+ }
+ if (ExtensionCaptureRequest.EFV_ROTATE_VIEWPORT.equals(parameter.first)) {
+ captureResults.put(ExtensionCaptureResult.EFV_ROTATE_VIEWPORT,
+ (Float) parameter.second);
+ }
+ if (ExtensionCaptureRequest.EFV_STABILIZATION_MODE.equals(parameter.first)) {
+ if (ExtensionCaptureRequest.EFV_STABILIZATION_MODE_LOCKED ==
+ (int) parameter.second) {
+ stabilizationModeLocked = true;
+ int[] samplePaddingRegion = {5, 5, 5, 5};
+ captureResults.put(ExtensionCaptureResult.EFV_PADDING_REGION,
+ samplePaddingRegion);
+ CameraCharacteristics cameraCharacteristics =
+ mAdvancedExtender.getCameraCharacteristics();
+ Rect arraySize = cameraCharacteristics.get(
+ CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ int centerX = arraySize.width() / 2;
+ int centerY = arraySize.height() / 2;
+ int squareSize = 5;
+ PointF[] sampleTargetCoordinates = new PointF[]{
+ new PointF(centerX - squareSize, centerY - squareSize),
+ new PointF(centerX + squareSize, centerY - squareSize),
+ new PointF(centerX + squareSize, centerY + squareSize),
+ new PointF(centerX - squareSize, centerY + squareSize)
+ };
+ captureResults.put(ExtensionCaptureResult.EFV_TARGET_COORDINATES,
+ sampleTargetCoordinates);
+ }
+ }
}
+
+ if (autoZoomEnabled && stabilizationModeLocked) {
+ int[] sampleAutoZoomPaddingRegion = {3, 3, 3, 3};
+ captureResults.put(ExtensionCaptureResult.EFV_AUTO_ZOOM_PADDING_REGION,
+ sampleAutoZoomPaddingRegion);
+ }
+ }
+
+ captureCallback.onCaptureCompleted(shutterTimestamp, seqId, captureResults);
+ }
+ }
+
+ protected List<Pair<CaptureRequest.Key, Object>> convertParameterMapToList() {
+ List<Pair<CaptureRequest.Key, Object>> mParametersList = new ArrayList<>();
+
+ synchronized(mParametersLock) {
+ for (Map.Entry<CaptureRequest.Key, Object> entry : mParametersMap.entrySet()) {
+ CaptureRequest.Key key = entry.getKey();
+ Object value = entry.getValue();
+ Pair<CaptureRequest.Key, Object> pair = new Pair<>(key, value);
+ mParametersList.add(pair);
}
- CaptureResult captureResult = new CaptureResult(cameraMetadataNative, seqId);
- captureCallback.onCaptureCompleted(shutterTimestamp, seqId,
- captureResult);
}
+
+ return mParametersList;
}
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@@ -278,15 +383,13 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@Override
- public int startCapture(@Nullable Executor executor,
+ public int startMultiFrameCapture(@NonNull Executor executor,
@NonNull CaptureCallback captureCallback) {
List<Integer> outputConfigIds = new ArrayList<>(List.of(CAPTURE_OUTPUT_ID));
RequestProcessor.Request requestRes;
- synchronized (mParametersLock) {
- requestRes = new RequestProcessor.Request(outputConfigIds, mParameters,
+ requestRes = new RequestProcessor.Request(outputConfigIds, convertParameterMapToList(),
CameraDevice.TEMPLATE_PREVIEW);
- }
final int seqId = mNextCaptureSequenceId.getAndIncrement();
@@ -307,19 +410,19 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@Override
public void onCaptureCompleted(RequestProcessor.Request request,
TotalCaptureResult totalCaptureResult) {
- addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
+ addCaptureResultKeys(seqId, totalCaptureResult, captureCallback, request);
}
@Override
public void onCaptureFailed(RequestProcessor.Request request,
CaptureFailure captureFailure) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, captureFailure.getReason());
}
@Override
public void onCaptureBufferLost(RequestProcessor.Request request,
long frameNumber, int outputStreamId) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, CaptureFailure.REASON_ERROR);
}
@Override
@@ -333,7 +436,11 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
}
};
- mRequestProcessor.submit(requestRes, executor, resCallback);
+ try {
+ mRequestProcessor.submit(requestRes, executor, resCallback);
+ } catch(CameraAccessException e) {
+ return -1;
+ }
captureCallback.onCaptureProcessStarted(seqId);
return seqId;
@@ -342,7 +449,7 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
@Override
public int startTrigger(@NonNull CaptureRequest captureRequest,
- @Nullable Executor executor, @NonNull CaptureCallback captureCallback) {
+ @NonNull Executor executor, @NonNull CaptureCallback captureCallback) {
List<Integer> outputConfigIds = new ArrayList<>(List.of(PREVIEW_OUTPUT_ID));
RequestProcessor.Request requestRes = new RequestProcessor.Request(outputConfigIds,
@@ -367,19 +474,19 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@Override
public void onCaptureCompleted(RequestProcessor.Request request,
TotalCaptureResult totalCaptureResult) {
- addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
+ addCaptureResultKeys(seqId, totalCaptureResult, captureCallback, request);
}
@Override
public void onCaptureFailed(RequestProcessor.Request request,
CaptureFailure captureFailure) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, captureFailure.getReason());
}
@Override
public void onCaptureBufferLost(RequestProcessor.Request request,
long frameNumber, int outputStreamId) {
- captureCallback.onCaptureFailed(seqId);
+ captureCallback.onCaptureFailed(seqId, CaptureFailure.REASON_ERROR);
}
@Override
@@ -393,7 +500,11 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
}
};
- mRequestProcessor.submit(requestRes, executor, resCallback);
+ try {
+ mRequestProcessor.submit(requestRes, executor, resCallback);
+ } catch(CameraAccessException e) {
+ return -1;
+ }
captureCallback.onCaptureProcessStarted(seqId);
return seqId;
@@ -419,9 +530,16 @@ public class EyesFreeVidSessionProcessor extends SessionProcessor {
@Override
public void setParameters(@NonNull CaptureRequest captureRequest) {
synchronized (mParametersLock) {
- for (CaptureRequest.Key<?> key : captureRequest.getKeys()) {
- Object value = captureRequest.get(key);
- mParameters.add(new Pair<>(key, value));
+
+ List<CaptureRequest.Key> supportedCaptureRequestKeys =
+ mAdvancedExtender.getAvailableCaptureRequestKeys(mCameraId);
+ List<CaptureRequest.Key<?>> requestedCaptureRequestKeys =
+ captureRequest.getKeys();
+ for (CaptureRequest.Key<?> key : requestedCaptureRequestKeys) {
+ if (supportedCaptureRequestKeys.contains(key)) {
+ Object value = captureRequest.get(key);
+ mParametersMap.put(key, value);
+ }
}
}
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
index d13efc85..abf8d453 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -216,4 +217,23 @@ public interface AdvancedExtenderImpl {
* @since 1.4
*/
boolean isPostviewAvailable();
+
+ /**
+ * Returns a list of {@link CameraCharacteristics} key/value pairs for apps to use when
+ * querying {@link CameraExtensionCharacteristics#get} and
+ * {@link CameraExtensionCharacteristics#getKeys}. The key/value pairs define the limitations
+ * on the controls returned from {@link #getAvailableCaptureRequestKeys}. If a key is not
+ * present in the returned list, then the capability is either undefined or unsupported.
+ *
+ * <p>For example, an extension may limit the zoom ratio range. In this case, an OEM returns
+ * a new zoom ratio range for the key {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
+ *
+ * <p>Similarly, an extension may support preview stabilization. In this case, the OEM returns
+ * the array containing the elements
+ * {@link CameraCharacteristics#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} and
+ * {@link CameraCharacteristics#CONTROL_VIDEO_STABILIZATION_MODE_OFF} for the key
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES}.
+ * @since 1.5
+ */
+ List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues();
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
index 8c3ac11c..45e4fccb 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -104,4 +105,9 @@ public class AutoAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isPostviewAvailable() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java
index 135306c8..8bb17f7e 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -104,4 +105,9 @@ public class BeautyAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isPostviewAvailable() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java
index fa4ad0dc..71b38d64 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -104,4 +105,9 @@ public class BokehAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isPostviewAvailable() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
index a66d3ceb..365abc3c 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
@@ -49,9 +49,9 @@ public class Camera2OutputConfigImplBuilder {
* with the given parameters.
*/
public static Camera2OutputConfigImplBuilder newImageReaderConfig(
- Size size, int imageFormat, int maxImages) {
+ Size size, int imageFormat, int maxImages, long usage) {
return new Camera2OutputConfigImplBuilder(
- new ImageReaderOutputConfigImplImpl(size, imageFormat, maxImages));
+ new ImageReaderOutputConfigImplImpl(size, imageFormat, maxImages, usage));
}
/**
@@ -181,11 +181,14 @@ public class Camera2OutputConfigImplBuilder {
private Size mSize;
private int mImageFormat;
private int mMaxImages;
+ private long mUsage;
- ImageReaderOutputConfigImplImpl(Size size, int imageFormat, int maxImages) {
+ ImageReaderOutputConfigImplImpl(Size size, int imageFormat, int maxImages,
+ long usage) {
mSize = size;
mImageFormat = imageFormat;
mMaxImages = maxImages;
+ mUsage = usage;
}
@Override
@@ -202,6 +205,11 @@ public class Camera2OutputConfigImplBuilder {
public int getMaxImages() {
return mMaxImages;
}
+
+ @Override
+ public long getUsage() {
+ return mUsage;
+ }
}
private static class MultiResolutionImageReaderOutputConfigImplImpl extends OutputConfigImplImpl
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java
index 01b65be0..f2eb3991 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/EyesFreeVideographyAdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -105,4 +106,10 @@ public class EyesFreeVideographyAdvancedExtenderImpl implements AdvancedExtender
public boolean isPostviewAvailable() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>>
+ getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
index dc5b2b60..7d87cc6e 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -105,4 +106,9 @@ public class HdrAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isPostviewAvailable() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
index ca4dcafa..7c3b48e0 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
@@ -38,4 +38,9 @@ public interface ImageReaderOutputConfigImpl extends Camera2OutputConfigImpl {
* Gets the capacity for TYPE_IMAGEREADER.
*/
int getMaxImages();
+
+ /**
+ * Gets the surface usage bits.
+ */
+ long getUsage();
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
index 5b0ed8ee..961d6695 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -104,4 +105,9 @@ public class NightAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isPostviewAvailable() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
index f6920296..7bf8df2f 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
@@ -39,4 +39,14 @@ public interface OutputSurfaceImpl {
* Gets the image format.
*/
int getImageFormat();
+
+ /**
+ * Gets the dataspace.
+ */
+ int getDataspace();
+
+ /**
+ * Gets the surface usage bits.
+ */
+ long getUsage();
}
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
index 2e5603b5..57fffd02 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
@@ -19,6 +19,7 @@ package androidx.camera.extensions.impl.advanced;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.util.Pair;
@@ -390,5 +391,20 @@ public interface SessionProcessorImpl {
* @since 1.4
*/
void onCaptureProcessProgressed(int progress);
+
+ /**
+ * This method is called instead of
+ * {@link #onCaptureProcessStarted} when the camera device failed
+ * to produce the required input for the device-specific extension. The
+ * cause could be a failed camera capture request, a failed
+ * capture result or dropped camera frame.
+ * The callback allows clients to be notified
+ * about failure reason.
+ *
+ * @param captureSequenceId id of the current capture sequence
+ * @param reason The capture failure reason @see CaptureFailure#FailureReason
+ * @since 1.5
+ */
+ void onCaptureFailed(int captureSequenceId, int reason);
}
}
diff --git a/common/tests/Android.bp b/common/tests/Android.bp
index 5b68d057..8738a5d4 100644
--- a/common/tests/Android.bp
+++ b/common/tests/Android.bp
@@ -21,9 +21,12 @@ android_test {
name: "AndroidCommonTests",
certificate: "platform",
libs: ["android.test.runner.stubs"],
- sdk_version: "8",
+ sdk_version: "19",
srcs: ["src/**/*.java"],
- static_libs: ["android-common"],
+ static_libs: [
+ "android-common",
+ "androidx.test.rules",
+ ],
optimize: {
enabled: false,
},
diff --git a/common/tests/src/com/android/common/OperationSchedulerTest.java b/common/tests/src/com/android/common/OperationSchedulerTest.java
index a25544a0..899da495 100644
--- a/common/tests/src/com/android/common/OperationSchedulerTest.java
+++ b/common/tests/src/com/android/common/OperationSchedulerTest.java
@@ -18,8 +18,9 @@ package com.android.common;
import android.content.SharedPreferences;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
public class OperationSchedulerTest extends AndroidTestCase {
/**
diff --git a/common/tests/src/com/android/common/Rfc822ValidatorTest.java b/common/tests/src/com/android/common/Rfc822ValidatorTest.java
index 61b8f252..f9bc8080 100644
--- a/common/tests/src/com/android/common/Rfc822ValidatorTest.java
+++ b/common/tests/src/com/android/common/Rfc822ValidatorTest.java
@@ -16,7 +16,7 @@
package com.android.common;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import junit.framework.TestCase;
diff --git a/common/tests/src/com/android/common/widget/CompositeCursorAdapterTest.java b/common/tests/src/com/android/common/widget/CompositeCursorAdapterTest.java
index 53d58402..17ba182a 100644
--- a/common/tests/src/com/android/common/widget/CompositeCursorAdapterTest.java
+++ b/common/tests/src/com/android/common/widget/CompositeCursorAdapterTest.java
@@ -19,10 +19,11 @@ import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.view.ViewGroup;
+import androidx.test.filters.SmallTest;
+
/**
* Tests for {@link CompositeCursorAdapter}.
*
diff --git a/framesequence/jni/Android.bp b/framesequence/jni/Android.bp
index 13ae47af..db71b51f 100644
--- a/framesequence/jni/Android.bp
+++ b/framesequence/jni/Android.bp
@@ -20,41 +20,10 @@ package {
cc_library_shared {
name: "libframesequence",
-
- // Main library
- // NOTE: the following code when dropped during the Android.mk->Android.bp
- // conversion because FRAMESEQUENCE_INCLUDE_WEBP is never set:
- // ifeq ($(FRAMESEQUENCE_INCLUDE_WEBP),true)
- // LOCAL_C_INCLUDES += external/webp/include
- // LOCAL_SRC_FILES += FrameSequence_webp.cpp
- // LOCAL_STATIC_LIBRARIES += libwebp-decode
- // endif
-
- static_libs: ["libgif"],
header_libs: ["jni_headers"],
- include_dirs: ["external/giflib"],
srcs: [
"BitmapDecoderJNI.cpp",
- "FrameSequence.cpp",
- "FrameSequenceJNI.cpp",
- "FrameSequence_gif.cpp",
- "JNIHelpers.cpp",
- "Registry.cpp",
- "Stream.cpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- "-Wno-unused-variable",
- "-Wno-overloaded-virtual",
- "-fvisibility=hidden",
],
sdk_version: "8",
- shared_libs: [
- "libjnigraphics",
- "liblog",
- ],
-
product_specific: true,
}
diff --git a/framesequence/jni/BitmapDecoderJNI.cpp b/framesequence/jni/BitmapDecoderJNI.cpp
index 5fe04b4f..6f7e246a 100644
--- a/framesequence/jni/BitmapDecoderJNI.cpp
+++ b/framesequence/jni/BitmapDecoderJNI.cpp
@@ -14,34 +14,8 @@
* limitations under the License.
*/
-#define LOG_TAG "FancyDecoding"
-
-#include <android/bitmap.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "FrameSequenceJNI.h"
-#include "JNIHelpers.h"
-#include "Stream.h"
-#include "utils/log.h"
-
-void throwException(JNIEnv* env, const char* error) {
- jclass clazz = env->FindClass("java/lang/RuntimeException");
- env->ThrowNew(clazz, error);
-}
-
-jint JNI_OnLoad(JavaVM* vm, void* reserved) {
- JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- return -1;
- }
- if (FrameSequence_OnLoad(env)) {
- ALOGE("Failed to load FrameSequence");
- return -1;
- }
- if (JavaStream_OnLoad(env)) {
- ALOGE("Failed to load JavaStream");
- return -1;
- }
+#include <jni.h>
+jint JNI_OnLoad(JavaVM*, void*) {
return JNI_VERSION_1_6;
}
diff --git a/framesequence/jni/Color.h b/framesequence/jni/Color.h
deleted file mode 100644
index e49c64a3..00000000
--- a/framesequence/jni/Color.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_COLOR_H
-#define RASTERMILL_COLOR_H
-
-#include <sys/types.h>
-
-typedef uint32_t Color8888;
-
-static const Color8888 COLOR_8888_ALPHA_MASK = 0xff000000; // TODO: handle endianness
-static const Color8888 TRANSPARENT = 0x0;
-
-// TODO: handle endianness
-#define ARGB_TO_COLOR8888(a, r, g, b) \
- ((a) << 24 | (b) << 16 | (g) << 8 | (r))
-
-#endif // RASTERMILL_COLOR_H
diff --git a/framesequence/jni/FrameSequence.cpp b/framesequence/jni/FrameSequence.cpp
deleted file mode 100644
index efcfefa0..00000000
--- a/framesequence/jni/FrameSequence.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "FrameSequence.h"
-
-#include "Registry.h"
-
-FrameSequence* FrameSequence::create(Stream* stream) {
- const RegistryEntry* entry = Registry::Find(stream);
-
- if (!entry) return NULL;
-
- FrameSequence* frameSequence = entry->createFrameSequence(stream);
- if (!frameSequence->getFrameCount() ||
- !frameSequence->getWidth() || !frameSequence->getHeight()) {
- // invalid contents, abort
- delete frameSequence;
- return NULL;
- }
-
- return frameSequence;
-}
diff --git a/framesequence/jni/FrameSequence.h b/framesequence/jni/FrameSequence.h
deleted file mode 100644
index 134c81a5..00000000
--- a/framesequence/jni/FrameSequence.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_FRAME_SEQUENCE_H
-#define RASTERMILL_FRAME_SEQUENCE_H
-
-#include "Stream.h"
-#include "Color.h"
-
-class FrameSequenceState {
-public:
- /**
- * Produces a frame of animation in the output buffer, drawing (at minimum) the delta since
- * previousFrameNr (the current contents of the buffer), or from scratch if previousFrameNr is
- * negative
- *
- * Returns frame's delay time in milliseconds.
- */
- virtual long drawFrame(int frameNr,
- Color8888* outputPtr, int outputPixelStride, int previousFrameNr) = 0;
- virtual ~FrameSequenceState() {}
-};
-
-class FrameSequence {
-public:
- /**
- * Creates a FrameSequence using data from the data stream
- *
- * Type determined by header information in the stream
- */
- static FrameSequence* create(Stream* stream);
-
- virtual ~FrameSequence() {}
- virtual int getWidth() const = 0;
- virtual int getHeight() const = 0;
- virtual bool isOpaque() const = 0;
- virtual int getFrameCount() const = 0;
- virtual int getDefaultLoopCount() const = 0;
- virtual jobject getRawByteBuffer() const = 0;
-
- virtual FrameSequenceState* createState() const = 0;
-};
-
-#endif //RASTERMILL_FRAME_SEQUENCE_H
diff --git a/framesequence/jni/FrameSequenceJNI.cpp b/framesequence/jni/FrameSequenceJNI.cpp
deleted file mode 100644
index c701f033..00000000
--- a/framesequence/jni/FrameSequenceJNI.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/bitmap.h>
-#include "JNIHelpers.h"
-#include "utils/log.h"
-#include "FrameSequence.h"
-
-#include "FrameSequenceJNI.h"
-
-#define JNI_PACKAGE "android/support/rastermill"
-
-static struct {
- jclass clazz;
- jmethodID ctor;
-} gFrameSequenceClassInfo;
-
-////////////////////////////////////////////////////////////////////////////////
-// Frame sequence
-////////////////////////////////////////////////////////////////////////////////
-
-static jobject createJavaFrameSequence(JNIEnv* env, FrameSequence* frameSequence) {
- if (!frameSequence) {
- return NULL;
- }
- return env->NewObject(gFrameSequenceClassInfo.clazz, gFrameSequenceClassInfo.ctor,
- reinterpret_cast<jlong>(frameSequence),
- frameSequence->getWidth(),
- frameSequence->getHeight(),
- frameSequence->isOpaque(),
- frameSequence->getFrameCount(),
- frameSequence->getDefaultLoopCount());
-}
-
-static jobject nativeDecodeByteArray(JNIEnv* env, jobject clazz,
- jbyteArray byteArray, jint offset, jint length) {
- jbyte* bytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(byteArray, NULL));
- if (bytes == NULL) {
- jniThrowException(env, ILLEGAL_STATE_EXEPTION,
- "couldn't read array bytes");
- return NULL;
- }
- MemoryStream stream(bytes + offset, length, NULL);
- FrameSequence* frameSequence = FrameSequence::create(&stream);
- env->ReleasePrimitiveArrayCritical(byteArray, bytes, 0);
- return createJavaFrameSequence(env, frameSequence);
-}
-
-static jobject nativeDecodeByteBuffer(JNIEnv* env, jobject clazz,
- jobject buf, jint offset, jint limit) {
- jobject globalBuf = env->NewGlobalRef(buf);
- JavaVM* vm;
- env->GetJavaVM(&vm);
- MemoryStream stream(
- (reinterpret_cast<uint8_t*>(
- env->GetDirectBufferAddress(globalBuf))) + offset,
- limit,
- globalBuf);
- FrameSequence* frameSequence = FrameSequence::create(&stream);
- jobject finalSequence = createJavaFrameSequence(env, frameSequence);
- return finalSequence;
-}
-
-static jobject nativeDecodeStream(JNIEnv* env, jobject clazz,
- jobject istream, jbyteArray byteArray) {
- JavaInputStream stream(env, istream, byteArray);
- FrameSequence* frameSequence = FrameSequence::create(&stream);
- return createJavaFrameSequence(env, frameSequence);
-}
-
-static void nativeDestroyFrameSequence(JNIEnv* env, jobject clazz,
- jlong frameSequenceLong) {
- FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong);
- jobject buf = frameSequence->getRawByteBuffer();
- if (buf != NULL) {
- env->DeleteGlobalRef(buf);
- }
- delete frameSequence;
-}
-
-static jlong nativeCreateState(JNIEnv* env, jobject clazz, jlong frameSequenceLong) {
- FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong);
- FrameSequenceState* state = frameSequence->createState();
- return reinterpret_cast<jlong>(state);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Frame sequence state
-////////////////////////////////////////////////////////////////////////////////
-
-static void nativeDestroyState(
- JNIEnv* env, jobject clazz, jlong frameSequenceStateLong) {
- FrameSequenceState* frameSequenceState =
- reinterpret_cast<FrameSequenceState*>(frameSequenceStateLong);
- delete frameSequenceState;
-}
-
-void throwIae(JNIEnv* env, const char* message, int errorCode) {
- char buf[256];
- snprintf(buf, sizeof(buf), "%s, error %d", message, errorCode);
- jniThrowException(env, ILLEGAL_STATE_EXEPTION, buf);
-}
-
-static jlong JNICALL nativeGetFrame(
- JNIEnv* env, jobject clazz, jlong frameSequenceStateLong, jint frameNr,
- jobject bitmap, jint previousFrameNr) {
- FrameSequenceState* frameSequenceState =
- reinterpret_cast<FrameSequenceState*>(frameSequenceStateLong);
- int ret;
- AndroidBitmapInfo info;
- void* pixels;
-
- if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
- throwIae(env, "Couldn't get info from Bitmap", ret);
- return 0;
- }
-
- if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
- throwIae(env, "Bitmap pixels couldn't be locked", ret);
- return 0;
- }
-
- int pixelStride = info.stride >> 2;
- jlong delayMs = frameSequenceState->drawFrame(frameNr,
- (Color8888*) pixels, pixelStride, previousFrameNr);
-
- AndroidBitmap_unlockPixels(env, bitmap);
- return delayMs;
-}
-
-static JNINativeMethod gMethods[] = {
- { "nativeDecodeByteArray",
- "([BII)L" JNI_PACKAGE "/FrameSequence;",
- (void*) nativeDecodeByteArray
- },
- { "nativeDecodeByteBuffer",
- "(Ljava/nio/ByteBuffer;II)L" JNI_PACKAGE "/FrameSequence;",
- (void*) nativeDecodeByteBuffer
- },
- { "nativeDecodeStream",
- "(Ljava/io/InputStream;[B)L" JNI_PACKAGE "/FrameSequence;",
- (void*) nativeDecodeStream
- },
- { "nativeDestroyFrameSequence",
- "(J)V",
- (void*) nativeDestroyFrameSequence
- },
- { "nativeCreateState",
- "(J)J",
- (void*) nativeCreateState
- },
- { "nativeGetFrame",
- "(JILandroid/graphics/Bitmap;I)J",
- (void*) nativeGetFrame
- },
- { "nativeDestroyState",
- "(J)V",
- (void*) nativeDestroyState
- },
-};
-
-jint FrameSequence_OnLoad(JNIEnv* env) {
- // Get jclass with env->FindClass.
- // Register methods with env->RegisterNatives.
- gFrameSequenceClassInfo.clazz = env->FindClass(JNI_PACKAGE "/FrameSequence");
- if (!gFrameSequenceClassInfo.clazz) {
- ALOGW("Failed to find " JNI_PACKAGE "/FrameSequence");
- return -1;
- }
- gFrameSequenceClassInfo.clazz = (jclass)env->NewGlobalRef(gFrameSequenceClassInfo.clazz);
-
- gFrameSequenceClassInfo.ctor = env->GetMethodID(gFrameSequenceClassInfo.clazz, "<init>", "(JIIZII)V");
- if (!gFrameSequenceClassInfo.ctor) {
- ALOGW("Failed to find constructor for FrameSequence - was it stripped?");
- return -1;
- }
-
- return env->RegisterNatives(gFrameSequenceClassInfo.clazz, gMethods, METHOD_COUNT(gMethods));
-}
diff --git a/framesequence/jni/FrameSequenceJNI.h b/framesequence/jni/FrameSequenceJNI.h
deleted file mode 100644
index a52df8a7..00000000
--- a/framesequence/jni/FrameSequenceJNI.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_FRAMESEQUENCE_JNI
-#define RASTERMILL_FRAMESEQUENCE_JNI
-
-#include <jni.h>
-
-jint FrameSequence_OnLoad(JNIEnv* env);
-
-#endif // RASTERMILL_FRAMESEQUENCE_JNI
diff --git a/framesequence/jni/FrameSequence_gif.cpp b/framesequence/jni/FrameSequence_gif.cpp
deleted file mode 100644
index ed478342..00000000
--- a/framesequence/jni/FrameSequence_gif.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-#include "JNIHelpers.h"
-#include "utils/log.h"
-#include "utils/math.h"
-
-#include "FrameSequence_gif.h"
-
-#define GIF_DEBUG 0
-
-static int streamReader(GifFileType* fileType, GifByteType* out, int size) {
- Stream* stream = (Stream*) fileType->UserData;
- return (int) stream->read(out, size);
-}
-
-static Color8888 gifColorToColor8888(const GifColorType& color) {
- return ARGB_TO_COLOR8888(0xff, color.Red, color.Green, color.Blue);
-}
-
-static long getDelayMs(GraphicsControlBlock& gcb) {
- return gcb.DelayTime * 10;
-}
-
-static bool willBeCleared(const GraphicsControlBlock& gcb) {
- return gcb.DisposalMode == DISPOSE_BACKGROUND || gcb.DisposalMode == DISPOSE_PREVIOUS;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Frame sequence
-////////////////////////////////////////////////////////////////////////////////
-
-FrameSequence_gif::FrameSequence_gif(Stream* stream) :
- mLoopCount(1), mBgColor(TRANSPARENT), mPreservedFrames(NULL), mRestoringFrames(NULL) {
- mGif = DGifOpen(stream, streamReader, NULL);
- if (!mGif) {
- ALOGW("Gif load failed");
- return;
- }
-
- if (DGifSlurp(mGif) != GIF_OK) {
- ALOGW("Gif slurp failed");
- DGifCloseFile(mGif, NULL);
- mGif = NULL;
- return;
- }
-
- long durationMs = 0;
- int lastUnclearedFrame = -1;
- mPreservedFrames = new bool[mGif->ImageCount];
- mRestoringFrames = new int[mGif->ImageCount];
-
- GraphicsControlBlock gcb;
- for (int i = 0; i < mGif->ImageCount; i++) {
- const SavedImage& image = mGif->SavedImages[i];
-
- // find the loop extension pair
- for (int j = 0; (j + 1) < image.ExtensionBlockCount; j++) {
- ExtensionBlock* eb1 = image.ExtensionBlocks + j;
- ExtensionBlock* eb2 = image.ExtensionBlocks + j + 1;
- if (eb1->Function == APPLICATION_EXT_FUNC_CODE
- // look for "NETSCAPE2.0" app extension
- && eb1->ByteCount == 11
- && !memcmp((const char*)(eb1->Bytes), "NETSCAPE2.0", 11)
- // verify extension contents and get loop count
- && eb2->Function == CONTINUE_EXT_FUNC_CODE
- && eb2->ByteCount == 3
- && eb2->Bytes[0] == 1) {
- mLoopCount = (int)(eb2->Bytes[2] << 8) + (int)(eb2->Bytes[1]);
- }
- }
-
- DGifSavedExtensionToGCB(mGif, i, &gcb);
-
- // timing
- durationMs += getDelayMs(gcb);
-
- // preserve logic
- mPreservedFrames[i] = false;
- mRestoringFrames[i] = -1;
- if (gcb.DisposalMode == DISPOSE_PREVIOUS && lastUnclearedFrame >= 0) {
- mPreservedFrames[lastUnclearedFrame] = true;
- mRestoringFrames[i] = lastUnclearedFrame;
- }
- if (!willBeCleared(gcb)) {
- lastUnclearedFrame = i;
- }
- }
-
-#if GIF_DEBUG
- ALOGD("FrameSequence_gif created with size %d %d, frames %d dur %ld",
- mGif->SWidth, mGif->SHeight, mGif->ImageCount, durationMs);
- for (int i = 0; i < mGif->ImageCount; i++) {
- DGifSavedExtensionToGCB(mGif, i, &gcb);
- ALOGD(" Frame %d - must preserve %d, restore point %d, trans color %d",
- i, mPreservedFrames[i], mRestoringFrames[i], gcb.TransparentColor);
- }
-#endif
-
- const ColorMapObject* cmap = mGif->SColorMap;
- if (cmap) {
- // calculate bg color
- GraphicsControlBlock gcb;
- DGifSavedExtensionToGCB(mGif, 0, &gcb);
- if (gcb.TransparentColor == NO_TRANSPARENT_COLOR
- && mGif->SBackGroundColor < cmap->ColorCount) {
- mBgColor = gifColorToColor8888(cmap->Colors[mGif->SBackGroundColor]);
- }
- }
-}
-
-FrameSequence_gif::~FrameSequence_gif() {
- if (mGif) {
- DGifCloseFile(mGif, NULL);
- }
- delete[] mPreservedFrames;
- delete[] mRestoringFrames;
-}
-
-FrameSequenceState* FrameSequence_gif::createState() const {
- return new FrameSequenceState_gif(*this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// draw helpers
-////////////////////////////////////////////////////////////////////////////////
-
-// return true if area of 'target' is completely covers area of 'covered'
-static bool checkIfCover(const GifImageDesc& target, const GifImageDesc& covered) {
- return target.Left <= covered.Left
- && covered.Left + covered.Width <= target.Left + target.Width
- && target.Top <= covered.Top
- && covered.Top + covered.Height <= target.Top + target.Height;
-}
-
-static void copyLine(Color8888* dst, const unsigned char* src, const ColorMapObject* cmap,
- int transparent, int width) {
- for (; width > 0; width--, src++, dst++) {
- if (*src != transparent && *src < cmap->ColorCount) {
- *dst = gifColorToColor8888(cmap->Colors[*src]);
- }
- }
-}
-
-static void setLineColor(Color8888* dst, Color8888 color, int width) {
- for (; width > 0; width--, dst++) {
- *dst = color;
- }
-}
-
-static void getCopySize(const GifImageDesc& imageDesc, int maxWidth, int maxHeight,
- GifWord& copyWidth, GifWord& copyHeight) {
- copyWidth = imageDesc.Width;
- if (imageDesc.Left + copyWidth > maxWidth) {
- copyWidth = maxWidth - imageDesc.Left;
- }
- copyHeight = imageDesc.Height;
- if (imageDesc.Top + copyHeight > maxHeight) {
- copyHeight = maxHeight - imageDesc.Top;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Frame sequence state
-////////////////////////////////////////////////////////////////////////////////
-
-FrameSequenceState_gif::FrameSequenceState_gif(const FrameSequence_gif& frameSequence) :
- mFrameSequence(frameSequence), mPreserveBuffer(NULL), mPreserveBufferFrame(-1) {
-}
-
-FrameSequenceState_gif::~FrameSequenceState_gif() {
- delete[] mPreserveBuffer;
-}
-
-void FrameSequenceState_gif::savePreserveBuffer(Color8888* outputPtr, int outputPixelStride, int frameNr) {
- if (frameNr == mPreserveBufferFrame) return;
-
- mPreserveBufferFrame = frameNr;
- const int width = mFrameSequence.getWidth();
- const int height = mFrameSequence.getHeight();
- if (!mPreserveBuffer) {
- mPreserveBuffer = new Color8888[width * height];
- }
- for (int y = 0; y < height; y++) {
- memcpy(mPreserveBuffer + width * y,
- outputPtr + outputPixelStride * y,
- width * 4);
- }
-}
-
-void FrameSequenceState_gif::restorePreserveBuffer(Color8888* outputPtr, int outputPixelStride) {
- const int width = mFrameSequence.getWidth();
- const int height = mFrameSequence.getHeight();
- if (!mPreserveBuffer) {
- ALOGD("preserve buffer not allocated! ah!");
- return;
- }
- for (int y = 0; y < height; y++) {
- memcpy(outputPtr + outputPixelStride * y,
- mPreserveBuffer + width * y,
- width * 4);
- }
-}
-
-long FrameSequenceState_gif::drawFrame(int frameNr,
- Color8888* outputPtr, int outputPixelStride, int previousFrameNr) {
-
- GifFileType* gif = mFrameSequence.getGif();
- if (!gif) {
- ALOGD("Cannot drawFrame, mGif is NULL");
- return -1;
- }
-
-#if GIF_DEBUG
- ALOGD(" drawFrame on %p nr %d on addr %p, previous frame nr %d",
- this, frameNr, outputPtr, previousFrameNr);
-#endif
-
- const int height = mFrameSequence.getHeight();
- const int width = mFrameSequence.getWidth();
-
- GraphicsControlBlock gcb;
-
- int start = max(previousFrameNr + 1, 0);
-
- for (int i = max(start - 1, 0); i < frameNr; i++) {
- int neededPreservedFrame = mFrameSequence.getRestoringFrame(i);
- if (neededPreservedFrame >= 0 && (mPreserveBufferFrame != neededPreservedFrame)) {
-#if GIF_DEBUG
- ALOGD("frame %d needs frame %d preserved, but %d is currently, so drawing from scratch",
- i, neededPreservedFrame, mPreserveBufferFrame);
-#endif
- start = 0;
- }
- }
-
- for (int i = start; i <= frameNr; i++) {
- DGifSavedExtensionToGCB(gif, i, &gcb);
- const SavedImage& frame = gif->SavedImages[i];
-
-#if GIF_DEBUG
- bool frameOpaque = gcb.TransparentColor == NO_TRANSPARENT_COLOR;
- ALOGD("producing frame %d, drawing frame %d (opaque %d, disp %d, del %d)",
- frameNr, i, frameOpaque, gcb.DisposalMode, gcb.DelayTime);
-#endif
- if (i == 0) {
- //clear bitmap
- Color8888 bgColor = mFrameSequence.getBackgroundColor();
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- outputPtr[y * outputPixelStride + x] = bgColor;
- }
- }
- } else {
- GraphicsControlBlock prevGcb;
- DGifSavedExtensionToGCB(gif, i - 1, &prevGcb);
- const SavedImage& prevFrame = gif->SavedImages[i - 1];
- bool prevFrameDisposed = willBeCleared(prevGcb);
-
- bool newFrameOpaque = gcb.TransparentColor == NO_TRANSPARENT_COLOR;
- bool prevFrameCompletelyCovered = newFrameOpaque
- && checkIfCover(frame.ImageDesc, prevFrame.ImageDesc);
-
- if (prevFrameDisposed && !prevFrameCompletelyCovered) {
- switch (prevGcb.DisposalMode) {
- case DISPOSE_BACKGROUND: {
- Color8888* dst = outputPtr + prevFrame.ImageDesc.Left +
- prevFrame.ImageDesc.Top * outputPixelStride;
-
- GifWord copyWidth, copyHeight;
- getCopySize(prevFrame.ImageDesc, width, height, copyWidth, copyHeight);
- for (; copyHeight > 0; copyHeight--) {
- setLineColor(dst, TRANSPARENT, copyWidth);
- dst += outputPixelStride;
- }
- } break;
- case DISPOSE_PREVIOUS: {
- restorePreserveBuffer(outputPtr, outputPixelStride);
- } break;
- }
- }
-
- if (mFrameSequence.getPreservedFrame(i - 1)) {
- // currently drawn frame will be restored by a following DISPOSE_PREVIOUS draw, so
- // we preserve it
- savePreserveBuffer(outputPtr, outputPixelStride, i - 1);
- }
- }
-
- bool willBeCleared = gcb.DisposalMode == DISPOSE_BACKGROUND
- || gcb.DisposalMode == DISPOSE_PREVIOUS;
- if (i == frameNr || !willBeCleared) {
- const ColorMapObject* cmap = gif->SColorMap;
- if (frame.ImageDesc.ColorMap) {
- cmap = frame.ImageDesc.ColorMap;
- }
-
- // If a cmap is missing, the frame can't be decoded, so we skip it.
- if (cmap) {
- const unsigned char* src = (unsigned char*)frame.RasterBits;
- Color8888* dst = outputPtr + frame.ImageDesc.Left +
- frame.ImageDesc.Top * outputPixelStride;
- GifWord copyWidth, copyHeight;
- getCopySize(frame.ImageDesc, width, height, copyWidth, copyHeight);
- for (; copyHeight > 0; copyHeight--) {
- copyLine(dst, src, cmap, gcb.TransparentColor, copyWidth);
- src += frame.ImageDesc.Width;
- dst += outputPixelStride;
- }
- }
- }
- }
-
- // return last frame's delay
- const int maxFrame = gif->ImageCount;
- const int lastFrame = (frameNr + maxFrame - 1) % maxFrame;
- DGifSavedExtensionToGCB(gif, lastFrame, &gcb);
- return getDelayMs(gcb);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Registry
-////////////////////////////////////////////////////////////////////////////////
-
-#include "Registry.h"
-
-static bool isGif(void* header, int header_size) {
- return !memcmp(GIF_STAMP, header, GIF_STAMP_LEN)
- || !memcmp(GIF87_STAMP, header, GIF_STAMP_LEN)
- || !memcmp(GIF89_STAMP, header, GIF_STAMP_LEN);
-}
-
-static bool acceptsBuffers() {
- return false;
-}
-
-static FrameSequence* createFramesequence(Stream* stream) {
- return new FrameSequence_gif(stream);
-}
-
-static RegistryEntry gEntry = {
- GIF_STAMP_LEN,
- isGif,
- createFramesequence,
- NULL,
- acceptsBuffers,
-};
-static Registry gRegister(gEntry);
diff --git a/framesequence/jni/FrameSequence_gif.h b/framesequence/jni/FrameSequence_gif.h
deleted file mode 100644
index 563f5b8e..00000000
--- a/framesequence/jni/FrameSequence_gif.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_FRAMESQUENCE_GIF_H
-#define RASTERMILL_FRAMESQUENCE_GIF_H
-
-#include "config.h"
-#include "gif_lib.h"
-
-#include "Stream.h"
-#include "Color.h"
-#include "FrameSequence.h"
-
-class FrameSequence_gif : public FrameSequence {
-public:
- FrameSequence_gif(Stream* stream);
- virtual ~FrameSequence_gif();
-
- virtual int getWidth() const {
- return mGif ? mGif->SWidth : 0;
- }
-
- virtual int getHeight() const {
- return mGif ? mGif->SHeight : 0;
- }
-
- virtual bool isOpaque() const {
- return (mBgColor & COLOR_8888_ALPHA_MASK) == COLOR_8888_ALPHA_MASK;
- }
-
- virtual int getFrameCount() const {
- return mGif ? mGif->ImageCount : 0;
- }
-
- virtual int getDefaultLoopCount() const {
- return mLoopCount;
- }
-
- virtual jobject getRawByteBuffer() const {
- return NULL;
- }
-
- virtual FrameSequenceState* createState() const;
-
- GifFileType* getGif() const { return mGif; }
- Color8888 getBackgroundColor() const { return mBgColor; }
- bool getPreservedFrame(int frameIndex) const { return mPreservedFrames[frameIndex]; }
- int getRestoringFrame(int frameIndex) const { return mRestoringFrames[frameIndex]; }
-
-private:
- GifFileType* mGif;
- int mLoopCount;
- Color8888 mBgColor;
-
- // array of bool per frame - if true, frame data is used by a later DISPOSE_PREVIOUS frame
- bool* mPreservedFrames;
-
- // array of ints per frame - if >= 0, points to the index of the preserve that frame needs
- int* mRestoringFrames;
-};
-
-class FrameSequenceState_gif : public FrameSequenceState {
-public:
- FrameSequenceState_gif(const FrameSequence_gif& frameSequence);
- virtual ~FrameSequenceState_gif();
-
- // returns frame's delay time in ms
- virtual long drawFrame(int frameNr,
- Color8888* outputPtr, int outputPixelStride, int previousFrameNr);
-
-private:
- void savePreserveBuffer(Color8888* outputPtr, int outputPixelStride, int frameNr);
- void restorePreserveBuffer(Color8888* outputPtr, int outputPixelStride);
-
- const FrameSequence_gif& mFrameSequence;
- Color8888* mPreserveBuffer;
- int mPreserveBufferFrame;
-};
-
-#endif //RASTERMILL_FRAMESQUENCE_GIF_H
diff --git a/framesequence/jni/FrameSequence_webp.cpp b/framesequence/jni/FrameSequence_webp.cpp
deleted file mode 100644
index f1bae82f..00000000
--- a/framesequence/jni/FrameSequence_webp.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-#include "JNIHelpers.h"
-#include "utils/log.h"
-#include "utils/math.h"
-#include "webp/format_constants.h"
-
-#include "FrameSequence_webp.h"
-
-#define WEBP_DEBUG 0
-
-////////////////////////////////////////////////////////////////////////////////
-// Frame sequence
-////////////////////////////////////////////////////////////////////////////////
-
-static uint32_t GetLE32(const uint8_t* const data) {
- return MKFOURCC(data[0], data[1], data[2], data[3]);
-}
-
-// Returns true if the frame covers full canvas.
-static bool isFullFrame(const WebPIterator& frame, int canvasWidth, int canvasHeight) {
- return (frame.width == canvasWidth && frame.height == canvasHeight);
-}
-
-// Returns true if the rectangle defined by 'frame' contains pixel (x, y).
-static bool FrameContainsPixel(const WebPIterator& frame, int x, int y) {
- const int left = frame.x_offset;
- const int right = left + frame.width;
- const int top = frame.y_offset;
- const int bottom = top + frame.height;
- return x >= left && x < right && y >= top && y < bottom;
-}
-
-// Construct mIsKeyFrame array.
-void FrameSequence_webp::constructDependencyChain() {
- const size_t frameCount = getFrameCount();
- mIsKeyFrame = new bool[frameCount];
- const int canvasWidth = getWidth();
- const int canvasHeight = getHeight();
-
- WebPIterator prev;
- WebPIterator curr;
-
- // Note: WebPDemuxGetFrame() uses base-1 counting.
- int ok = WebPDemuxGetFrame(mDemux, 1, &curr);
- ALOG_ASSERT(ok, "Could not retrieve frame# 0");
- mIsKeyFrame[0] = true; // 0th frame is always a key frame.
- for (size_t i = 1; i < frameCount; i++) {
- prev = curr;
- ok = WebPDemuxGetFrame(mDemux, i + 1, &curr); // Get ith frame.
- ALOG_ASSERT(ok, "Could not retrieve frame# %d", i);
-
- if ((!curr.has_alpha || curr.blend_method == WEBP_MUX_NO_BLEND) &&
- isFullFrame(curr, canvasWidth, canvasHeight)) {
- mIsKeyFrame[i] = true;
- } else {
- mIsKeyFrame[i] = (prev.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) &&
- (isFullFrame(prev, canvasWidth, canvasHeight) || mIsKeyFrame[i - 1]);
- }
- }
- WebPDemuxReleaseIterator(&prev);
- WebPDemuxReleaseIterator(&curr);
-
-#if WEBP_DEBUG
- ALOGD("Dependency chain:");
- for (size_t i = 0; i < frameCount; i++) {
- ALOGD("Frame# %zu: %s", i, mIsKeyFrame[i] ? "Key frame" : "NOT a key frame");
- }
-#endif
-}
-
-FrameSequence_webp::FrameSequence_webp(Stream* stream)
- : mDemux(NULL)
- , mIsKeyFrame(NULL)
- , mRawByteBuffer(NULL) {
- if (stream->getRawBuffer() != NULL) {
- mData.size = stream->getRawBufferSize();
- mData.bytes = stream->getRawBufferAddr();
- mRawByteBuffer = stream->getRawBuffer();
- } else {
- // Read RIFF header to get file size.
- uint8_t riff_header[RIFF_HEADER_SIZE];
- if (stream->read(riff_header, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE) {
- ALOGE("WebP header load failed");
- return;
- }
- uint32_t readSize = GetLE32(riff_header + TAG_SIZE);
- if (readSize > MAX_CHUNK_PAYLOAD) {
- ALOGE("WebP got header size too large");
- return;
- }
- mData.size = CHUNK_HEADER_SIZE + readSize;
- if(mData.size < RIFF_HEADER_SIZE) {
- ALOGE("WebP file malformed");
- return;
- }
- mData.bytes = new uint8_t[mData.size];
- memcpy((void*)mData.bytes, riff_header, RIFF_HEADER_SIZE);
-
- // Read rest of the bytes.
- void* remaining_bytes = (void*)(mData.bytes + RIFF_HEADER_SIZE);
- size_t remaining_size = mData.size - RIFF_HEADER_SIZE;
- if (stream->read(remaining_bytes, remaining_size) != remaining_size) {
- ALOGE("WebP full load failed");
- return;
- }
- }
-
- // Construct demux.
- mDemux = WebPDemux(&mData);
- if (!mDemux) {
- ALOGE("Parsing of WebP container file failed");
- return;
- }
- mLoopCount = WebPDemuxGetI(mDemux, WEBP_FF_LOOP_COUNT);
- mFormatFlags = WebPDemuxGetI(mDemux, WEBP_FF_FORMAT_FLAGS);
-#if WEBP_DEBUG
- ALOGD("FrameSequence_webp created with size = %d x %d, number of frames = %d, flags = 0x%X",
- getWidth(), getHeight(), getFrameCount(), mFormatFlags);
-#endif
- constructDependencyChain();
-}
-
-FrameSequence_webp::~FrameSequence_webp() {
- WebPDemuxDelete(mDemux);
- delete[] mIsKeyFrame;
- if (mRawByteBuffer == NULL) {
- delete[] mData.bytes;
- }
-}
-
-FrameSequenceState* FrameSequence_webp::createState() const {
- return new FrameSequenceState_webp(*this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// draw helpers
-////////////////////////////////////////////////////////////////////////////////
-
-static bool willBeCleared(const WebPIterator& iter) {
- return iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND;
-}
-
-// return true if area of 'target' completely covers area of 'covered'
-static bool checkIfCover(const WebPIterator& target, const WebPIterator& covered) {
- const int covered_x_max = covered.x_offset + covered.width;
- const int target_x_max = target.x_offset + target.width;
- const int covered_y_max = covered.y_offset + covered.height;
- const int target_y_max = target.y_offset + target.height;
- return target.x_offset <= covered.x_offset
- && covered_x_max <= target_x_max
- && target.y_offset <= covered.y_offset
- && covered_y_max <= target_y_max;
-}
-
-// Clear all pixels in a line to transparent.
-static void clearLine(Color8888* dst, int width) {
- memset(dst, 0, width * sizeof(*dst)); // Note: Assumes TRANSPARENT == 0x0.
-}
-
-// Copy all pixels from 'src' to 'dst'.
-static void copyFrame(const Color8888* src, int srcStride, Color8888* dst, int dstStride,
- int width, int height) {
- for (int y = 0; y < height; y++) {
- memcpy(dst, src, width * sizeof(*dst));
- src += srcStride;
- dst += dstStride;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Frame sequence state
-////////////////////////////////////////////////////////////////////////////////
-
-FrameSequenceState_webp::FrameSequenceState_webp(const FrameSequence_webp& frameSequence) :
- mFrameSequence(frameSequence) {
- WebPInitDecoderConfig(&mDecoderConfig);
- mDecoderConfig.output.is_external_memory = 1;
- mDecoderConfig.output.colorspace = MODE_rgbA; // Pre-multiplied alpha mode.
- const int canvasWidth = mFrameSequence.getWidth();
- const int canvasHeight = mFrameSequence.getHeight();
- mPreservedBuffer = new Color8888[canvasWidth * canvasHeight];
-}
-
-FrameSequenceState_webp::~FrameSequenceState_webp() {
- delete[] mPreservedBuffer;
-}
-
-void FrameSequenceState_webp::initializeFrame(const WebPIterator& currIter, Color8888* currBuffer,
- int currStride, const WebPIterator& prevIter, const Color8888* prevBuffer, int prevStride) {
- const int canvasWidth = mFrameSequence.getWidth();
- const int canvasHeight = mFrameSequence.getHeight();
- const bool currFrameIsKeyFrame = mFrameSequence.isKeyFrame(currIter.frame_num - 1);
-
- if (currFrameIsKeyFrame) { // Clear canvas.
- for (int y = 0; y < canvasHeight; y++) {
- Color8888* dst = currBuffer + y * currStride;
- clearLine(dst, canvasWidth);
- }
- } else {
- // Preserve previous frame as starting state of current frame.
- copyFrame(prevBuffer, prevStride, currBuffer, currStride, canvasWidth, canvasHeight);
-
- // Dispose previous frame rectangle to Background if needed.
- bool prevFrameCompletelyCovered =
- (!currIter.has_alpha || currIter.blend_method == WEBP_MUX_NO_BLEND) &&
- checkIfCover(currIter, prevIter);
- if ((prevIter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) &&
- !prevFrameCompletelyCovered) {
- Color8888* dst = currBuffer + prevIter.x_offset + prevIter.y_offset * currStride;
- for (int j = 0; j < prevIter.height; j++) {
- clearLine(dst, prevIter.width);
- dst += currStride;
- }
- }
- }
-}
-
-bool FrameSequenceState_webp::decodeFrame(const WebPIterator& currIter, Color8888* currBuffer,
- int currStride, const WebPIterator& prevIter, const Color8888* prevBuffer, int prevStride) {
- Color8888* dst = currBuffer + currIter.x_offset + currIter.y_offset * currStride;
- mDecoderConfig.output.u.RGBA.rgba = (uint8_t*)dst;
- mDecoderConfig.output.u.RGBA.stride = currStride * 4;
- mDecoderConfig.output.u.RGBA.size = mDecoderConfig.output.u.RGBA.stride * currIter.height;
-
- const WebPData& currFrame = currIter.fragment;
- if (WebPDecode(currFrame.bytes, currFrame.size, &mDecoderConfig) != VP8_STATUS_OK) {
- return false;
- }
-
- const int canvasWidth = mFrameSequence.getWidth();
- const int canvasHeight = mFrameSequence.getHeight();
- const bool currFrameIsKeyFrame = mFrameSequence.isKeyFrame(currIter.frame_num - 1);
- // During the decoding of current frame, we may have set some pixels to be transparent
- // (i.e. alpha < 255). However, the value of each of these pixels should have been determined
- // by blending it against the value of that pixel in the previous frame if WEBP_MUX_BLEND was
- // specified. So, we correct these pixels based on disposal method of the previous frame and
- // the previous frame buffer.
- if (currIter.blend_method == WEBP_MUX_BLEND && !currFrameIsKeyFrame) {
- if (prevIter.dispose_method == WEBP_MUX_DISPOSE_NONE) {
- for (int y = 0; y < currIter.height; y++) {
- const int canvasY = currIter.y_offset + y;
- for (int x = 0; x < currIter.width; x++) {
- const int canvasX = currIter.x_offset + x;
- Color8888& currPixel = currBuffer[canvasY * currStride + canvasX];
- // FIXME: Use alpha-blending when alpha is between 0 and 255.
- if (!(currPixel & COLOR_8888_ALPHA_MASK)) {
- const Color8888 prevPixel = prevBuffer[canvasY * prevStride + canvasX];
- currPixel = prevPixel;
- }
- }
- }
- } else { // prevIter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND
- // Need to restore transparent pixels to as they were just after frame initialization.
- // That is:
- // * Transparent if it belongs to previous frame rectangle <-- This is a no-op.
- // * Pixel in the previous canvas otherwise <-- Need to restore.
- for (int y = 0; y < currIter.height; y++) {
- const int canvasY = currIter.y_offset + y;
- for (int x = 0; x < currIter.width; x++) {
- const int canvasX = currIter.x_offset + x;
- Color8888& currPixel = currBuffer[canvasY * currStride + canvasX];
- // FIXME: Use alpha-blending when alpha is between 0 and 255.
- if (!(currPixel & COLOR_8888_ALPHA_MASK)
- && !FrameContainsPixel(prevIter, canvasX, canvasY)) {
- const Color8888 prevPixel = prevBuffer[canvasY * prevStride + canvasX];
- currPixel = prevPixel;
- }
- }
- }
- }
- }
- return true;
-}
-
-long FrameSequenceState_webp::drawFrame(int frameNr,
- Color8888* outputPtr, int outputPixelStride, int previousFrameNr) {
- WebPDemuxer* demux = mFrameSequence.getDemuxer();
- ALOG_ASSERT(demux, "Cannot drawFrame, mDemux is NULL");
-
-#if WEBP_DEBUG
- ALOGD(" drawFrame called for frame# %d, previous frame# %d", frameNr, previousFrameNr);
-#endif
-
- const int canvasWidth = mFrameSequence.getWidth();
- const int canvasHeight = mFrameSequence.getHeight();
-
- // Find the first frame to be decoded.
- int start = max(previousFrameNr + 1, 0);
- int earliestRequired = frameNr;
- while (earliestRequired > start) {
- if (mFrameSequence.isKeyFrame(earliestRequired)) {
- start = earliestRequired;
- break;
- }
- earliestRequired--;
- }
-
- WebPIterator currIter;
- WebPIterator prevIter;
- int ok = WebPDemuxGetFrame(demux, start, &currIter); // Get frame number 'start - 1'.
- ALOG_ASSERT(ok, "Could not retrieve frame# %d", start - 1);
-
- // Use preserve buffer only if needed.
- Color8888* prevBuffer = (frameNr == 0) ? outputPtr : mPreservedBuffer;
- int prevStride = (frameNr == 0) ? outputPixelStride : canvasWidth;
- Color8888* currBuffer = outputPtr;
- int currStride = outputPixelStride;
-
- for (int i = start; i <= frameNr; i++) {
- prevIter = currIter;
- ok = WebPDemuxGetFrame(demux, i + 1, &currIter); // Get ith frame.
- ALOG_ASSERT(ok, "Could not retrieve frame# %d", i);
-#if WEBP_DEBUG
- ALOGD(" producing frame %d (has_alpha = %d, dispose = %s, blend = %s, duration = %d)",
- i, currIter.has_alpha,
- (currIter.dispose_method == WEBP_MUX_DISPOSE_NONE) ? "none" : "background",
- (currIter.blend_method == WEBP_MUX_BLEND) ? "yes" : "no", currIter.duration);
-#endif
- // We swap the prev/curr buffers as we go.
- Color8888* tmpBuffer = prevBuffer;
- prevBuffer = currBuffer;
- currBuffer = tmpBuffer;
-
- int tmpStride = prevStride;
- prevStride = currStride;
- currStride = tmpStride;
-
-#if WEBP_DEBUG
- ALOGD(" prev = %p, curr = %p, out = %p, tmp = %p",
- prevBuffer, currBuffer, outputPtr, mPreservedBuffer);
-#endif
- // Process this frame.
- initializeFrame(currIter, currBuffer, currStride, prevIter, prevBuffer, prevStride);
-
- if (i == frameNr || !willBeCleared(currIter)) {
- if (!decodeFrame(currIter, currBuffer, currStride, prevIter, prevBuffer, prevStride)) {
- ALOGE("Error decoding frame# %d", i);
- return -1;
- }
- }
- }
-
- if (outputPtr != currBuffer) {
- copyFrame(currBuffer, currStride, outputPtr, outputPixelStride, canvasWidth, canvasHeight);
- }
-
- // Return last frame's delay.
- const int frameCount = mFrameSequence.getFrameCount();
- const int lastFrame = (frameNr + frameCount - 1) % frameCount;
- ok = WebPDemuxGetFrame(demux, lastFrame + 1, &currIter);
- ALOG_ASSERT(ok, "Could not retrieve frame# %d", lastFrame);
- const int lastFrameDelay = currIter.duration;
-
- WebPDemuxReleaseIterator(&currIter);
- WebPDemuxReleaseIterator(&prevIter);
-
- return lastFrameDelay;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Registry
-////////////////////////////////////////////////////////////////////////////////
-
-#include "Registry.h"
-
-static bool isWebP(void* header, int header_size) {
- const uint8_t* const header_str = (const uint8_t*)header;
- return (header_size >= RIFF_HEADER_SIZE) &&
- !memcmp("RIFF", header_str, 4) &&
- !memcmp("WEBP", header_str + 8, 4);
-}
-
-static bool acceptsWebPBuffer() {
- return true;
-}
-
-static FrameSequence* createFramesequence(Stream* stream) {
- return new FrameSequence_webp(stream);
-}
-
-static RegistryEntry gEntry = {
- RIFF_HEADER_SIZE,
- isWebP,
- createFramesequence,
- NULL,
- acceptsWebPBuffer,
-};
-static Registry gRegister(gEntry);
-
diff --git a/framesequence/jni/FrameSequence_webp.h b/framesequence/jni/FrameSequence_webp.h
deleted file mode 100644
index 148146f0..00000000
--- a/framesequence/jni/FrameSequence_webp.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_FRAMESQUENCE_WEBP_H
-#define RASTERMILL_FRAMESQUENCE_WEBP_H
-
-#include "config.h"
-#include "webp/decode.h"
-#include "webp/demux.h"
-
-#include "Stream.h"
-#include "Color.h"
-#include "FrameSequence.h"
-
-// Parser for a possibly-animated WebP bitstream.
-class FrameSequence_webp : public FrameSequence {
-public:
- FrameSequence_webp(Stream* stream);
- virtual ~FrameSequence_webp();
-
- virtual int getWidth() const {
- if (!mDemux) {
- return 0;
- }
- return WebPDemuxGetI(mDemux, WEBP_FF_CANVAS_WIDTH);
- }
-
- virtual int getHeight() const {
- if (!mDemux) {
- return 0;
- }
- return WebPDemuxGetI(mDemux, WEBP_FF_CANVAS_HEIGHT);
- }
-
- virtual bool isOpaque() const {
- return !(mFormatFlags & ALPHA_FLAG);
- }
-
- virtual int getFrameCount() const {
- if (!mDemux) {
- return 0;
- }
- return WebPDemuxGetI(mDemux, WEBP_FF_FRAME_COUNT);
- }
-
- virtual int getDefaultLoopCount() const {
- return mLoopCount;
- }
-
- virtual jobject getRawByteBuffer() const {
- return mRawByteBuffer;
- }
-
- virtual FrameSequenceState* createState() const;
-
- WebPDemuxer* getDemuxer() const { return mDemux; }
-
- bool isKeyFrame(size_t frameNr) const { return mIsKeyFrame[frameNr]; }
-
-private:
- void constructDependencyChain();
-
- WebPData mData;
- WebPDemuxer* mDemux;
- int mLoopCount;
- uint32_t mFormatFlags;
- // mIsKeyFrame[i] is true if ith canvas can be constructed without decoding any prior frames.
- bool* mIsKeyFrame;
- jobject mRawByteBuffer = nullptr;
-};
-
-// Produces frames of a possibly-animated WebP file for display.
-class FrameSequenceState_webp : public FrameSequenceState {
-public:
- FrameSequenceState_webp(const FrameSequence_webp& frameSequence);
- virtual ~FrameSequenceState_webp();
-
- // Returns frame's delay time in milliseconds.
- virtual long drawFrame(int frameNr,
- Color8888* outputPtr, int outputPixelStride, int previousFrameNr);
-
-private:
- void initializeFrame(const WebPIterator& currIter, Color8888* currBuffer, int currStride,
- const WebPIterator& prevIter, const Color8888* prevBuffer, int prevStride);
- bool decodeFrame(const WebPIterator& iter, Color8888* currBuffer, int currStride,
- const WebPIterator& prevIter, const Color8888* prevBuffer, int prevStride);
-
- const FrameSequence_webp& mFrameSequence;
- WebPDecoderConfig mDecoderConfig;
- Color8888* mPreservedBuffer;
-};
-
-#endif //RASTERMILL_FRAMESQUENCE_WEBP_H
diff --git a/framesequence/jni/JNIHelpers.cpp b/framesequence/jni/JNIHelpers.cpp
deleted file mode 100644
index dd0c8185..00000000
--- a/framesequence/jni/JNIHelpers.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "JNIHelpers.h"
-#include "utils/log.h"
-
-void jniThrowException(JNIEnv* env, const char* className, const char* msg) {
- jclass clazz = env->FindClass(className);
- if (!clazz) {
- ALOGE("Unable to find exception class %s", className);
- /* ClassNotFoundException now pending */
- return;
- }
-
- if (env->ThrowNew(clazz, msg) != JNI_OK) {
- ALOGE("Failed throwing '%s' '%s'", className, msg);
- /* an exception, most likely OOM, will now be pending */
- }
- env->DeleteLocalRef(clazz);
-}
diff --git a/framesequence/jni/JNIHelpers.h b/framesequence/jni/JNIHelpers.h
deleted file mode 100644
index 3718b388..00000000
--- a/framesequence/jni/JNIHelpers.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_JNIHELPERS_H
-#define RASTERMILL_JNIHELPERS_H
-
-#include <jni.h>
-
-#define METHOD_COUNT(methodArray) (sizeof(methodArray) / sizeof((methodArray)[0]))
-
-#define ILLEGAL_STATE_EXEPTION "java/lang/IllegalStateException"
-
-void jniThrowException(JNIEnv* env, const char* className, const char* msg);
-
-
-#endif //RASTERMILL_JNIHELPERS_H
diff --git a/framesequence/jni/Registry.cpp b/framesequence/jni/Registry.cpp
deleted file mode 100644
index e632bb27..00000000
--- a/framesequence/jni/Registry.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Registry.h"
-
-#include "Stream.h"
-
-static Registry* gHead = 0;
-static int gHeaderBytesRequired = 0;
-
-Registry::Registry(const RegistryEntry& entry) {
- mImpl = entry;
-
- mNext = gHead;
- gHead = this;
-
- if (gHeaderBytesRequired < entry.requiredHeaderBytes) {
- gHeaderBytesRequired = entry.requiredHeaderBytes;
- }
-}
-
-const RegistryEntry* Registry::Find(Stream* stream) {
- Registry* registry = gHead;
-
- if (stream->getRawBuffer() != NULL) {
- while (registry) {
- if (registry->mImpl.acceptsBuffer()) {
- return &(registry->mImpl);
- }
- registry = registry->mNext;
- }
- } else {
- int headerSize = gHeaderBytesRequired;
- char header[headerSize];
- headerSize = stream->peek(header, headerSize);
- while (registry) {
- if (headerSize >= registry->mImpl.requiredHeaderBytes
- && registry->mImpl.checkHeader(header, headerSize)) {
- return &(registry->mImpl);
- }
- registry = registry->mNext;
- }
- }
- return 0;
-}
-
diff --git a/framesequence/jni/Registry.h b/framesequence/jni/Registry.h
deleted file mode 100644
index 8db43cf8..00000000
--- a/framesequence/jni/Registry.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_REGISTRY_H
-#define RASTERMILL_REGISTRY_H
-
-#include "jni.h"
-#include <stdint.h>
-
-class FrameSequence;
-class Decoder;
-class Stream;
-
-struct RegistryEntry {
- int requiredHeaderBytes;
- bool (*checkHeader)(void* header, int header_size);
- FrameSequence* (*createFrameSequence)(Stream* stream);
- Decoder* (*createDecoder)(Stream* stream);
- bool (*acceptsBuffer)();
-};
-
-/**
- * Template class for registering subclasses that can produce instances of themselves given a
- * DataStream pointer.
- *
- * The super class / root constructable type only needs to define a single static construction
- * meathod that creates an instance by iterating through all factory methods.
- */
-class Registry {
-public:
- Registry(const RegistryEntry& entry);
-
- static const RegistryEntry* Find(Stream* stream);
-
-private:
- RegistryEntry mImpl;
- Registry* mNext;
-};
-
-#endif // RASTERMILL_REGISTRY_H
diff --git a/framesequence/jni/Stream.cpp b/framesequence/jni/Stream.cpp
deleted file mode 100644
index 10dc805b..00000000
--- a/framesequence/jni/Stream.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Stream"
-
-#include "Stream.h"
-
-#include <string.h>
-
-#include "JNIHelpers.h"
-#include "utils/log.h"
-#include "utils/math.h"
-
-static struct {
- jmethodID read;
- jmethodID reset;
-} gInputStreamClassInfo;
-
-Stream::Stream()
- : mPeekBuffer(0)
- , mPeekSize(0)
- , mPeekOffset(0) {
-}
-
-Stream::~Stream() {
- delete[] mPeekBuffer;
-}
-
-size_t Stream::peek(void* buffer, size_t size) {
- size_t peek_remaining = mPeekSize - mPeekOffset;
- if (size > peek_remaining) {
- char* old_peek = mPeekBuffer;
- mPeekBuffer = new char[size];
- if (old_peek) {
- memcpy(mPeekBuffer, old_peek + mPeekOffset, peek_remaining);
- delete[] old_peek;
- }
- size_t read = doRead(mPeekBuffer + mPeekOffset, size - peek_remaining);
- mPeekOffset = 0;
- mPeekSize = peek_remaining + read;
- }
- size = min(size, mPeekSize - mPeekOffset);
- memcpy(buffer, mPeekBuffer + mPeekOffset, size);
- return size;
-}
-
-size_t Stream::read(void* buffer, size_t size) {
- size_t bytes_read = 0;
- size_t peek_remaining = mPeekSize - mPeekOffset;
- if (peek_remaining) {
- bytes_read = min(size, peek_remaining);
- memcpy(buffer, mPeekBuffer + mPeekOffset, bytes_read);
- mPeekOffset += bytes_read;
- if (mPeekOffset == mPeekSize) {
- delete[] mPeekBuffer;
- mPeekBuffer = 0;
- mPeekOffset = 0;
- mPeekSize = 0;
- }
- size -= bytes_read;
- buffer = ((char*) buffer) + bytes_read;
- }
- if (size) {
- bytes_read += doRead(buffer, size);
- }
- return bytes_read;
-}
-
-uint8_t* Stream::getRawBufferAddr() {
- return NULL;
-}
-
-jobject Stream::getRawBuffer() {
- return NULL;
-}
-
-int Stream::getRawBufferSize() {
- return 0;
-}
-
-uint8_t* MemoryStream::getRawBufferAddr() {
- return mBuffer;
-}
-
-jobject MemoryStream::getRawBuffer() {
- return mRawBuffer;
-}
-
-int MemoryStream::getRawBufferSize() {
- if (mRawBuffer != NULL) {
- return mRemaining;
- } else {
- return 0;
- }
-}
-
-size_t MemoryStream::doRead(void* buffer, size_t size) {
- size = min(size, mRemaining);
- memcpy(buffer, mBuffer, size);
- mBuffer += size;
- mRemaining -= size;
- return size;
-}
-
-size_t FileStream::doRead(void* buffer, size_t size) {
- return fread(buffer, 1, size, mFd);
-}
-
-size_t JavaInputStream::doRead(void* dstBuffer, size_t size) {
- size_t totalBytesRead = 0;
-
- do {
- size_t requested = min(size, mByteArrayLength);
-
- jint bytesRead = mEnv->CallIntMethod(mInputStream,
- gInputStreamClassInfo.read, mByteArray, 0, requested);
- if (mEnv->ExceptionCheck() || bytesRead < 0) {
- return 0;
- }
-
- mEnv->GetByteArrayRegion(mByteArray, 0, bytesRead, (jbyte*)dstBuffer);
- dstBuffer = (char*)dstBuffer + bytesRead;
- totalBytesRead += bytesRead;
- size -= bytesRead;
- } while (size > 0);
-
- return totalBytesRead;
-}
-
-jint JavaStream_OnLoad(JNIEnv* env) {
- // Skip the verbose logging on error for these, as they won't be subject
- // to obfuscators or similar and are thus unlikely to ever fail
- jclass inputStreamClazz = env->FindClass("java/io/InputStream");
- if (!inputStreamClazz) {
- return -1;
- }
- gInputStreamClassInfo.read = env->GetMethodID(inputStreamClazz, "read", "([BII)I");
- gInputStreamClassInfo.reset = env->GetMethodID(inputStreamClazz, "reset", "()V");
- if (!gInputStreamClassInfo.read || !gInputStreamClassInfo.reset) {
- return -1;
- }
- return 0;
-}
diff --git a/framesequence/jni/Stream.h b/framesequence/jni/Stream.h
deleted file mode 100644
index f0f38954..00000000
--- a/framesequence/jni/Stream.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RASTERMILL_STREAM_H
-#define RASTERMILL_STREAM_H
-
-#include <jni.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-class Stream {
-public:
- Stream();
- virtual ~Stream();
-
- size_t peek(void* buffer, size_t size);
- size_t read(void* buffer, size_t size);
- virtual uint8_t* getRawBufferAddr();
- virtual jobject getRawBuffer();
- virtual int getRawBufferSize();
-
-protected:
- virtual size_t doRead(void* buffer, size_t size) = 0;
-
-private:
- char* mPeekBuffer;
- size_t mPeekSize;
- size_t mPeekOffset;
-};
-
-class MemoryStream : public Stream {
-public:
- MemoryStream(void* buffer, size_t size, jobject buf) :
- mBuffer((uint8_t*)buffer),
- mRemaining(size),
- mRawBuffer(buf) {}
- virtual uint8_t* getRawBufferAddr();
- virtual jobject getRawBuffer();
- virtual int getRawBufferSize();
-
-protected:
- virtual size_t doRead(void* buffer, size_t size);
-
-private:
- uint8_t* mBuffer;
- size_t mRemaining;
- jobject mRawBuffer;
-};
-
-class FileStream : public Stream {
-public:
- FileStream(FILE* fd) : mFd(fd) {}
-
-protected:
- virtual size_t doRead(void* buffer, size_t size);
-
-private:
- FILE* mFd;
-};
-
-class JavaInputStream : public Stream {
-public:
- JavaInputStream(JNIEnv* env, jobject inputStream, jbyteArray byteArray) :
- mEnv(env),
- mInputStream(inputStream),
- mByteArray(byteArray),
- mByteArrayLength(env->GetArrayLength(byteArray)) {}
-
-protected:
- virtual size_t doRead(void* buffer, size_t size);
-
-private:
- JNIEnv* mEnv;
- const jobject mInputStream;
- const jbyteArray mByteArray;
- const size_t mByteArrayLength;
-};
-
-jint JavaStream_OnLoad(JNIEnv* env);
-
-#endif //RASTERMILL_STREAM_H
diff --git a/framesequence/jni/utils/log.h b/framesequence/jni/utils/log.h
deleted file mode 100644
index d8441dc1..00000000
--- a/framesequence/jni/utils/log.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LOG_H_
-#define LOG_H_
-
-#include <android/log.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Normally we strip ALOGV (VERBOSE messages) from release builds.
- * You can modify this (for example with "#define LOG_NDEBUG 0"
- * at the top of your source file) to change that behavior.
- */
-#ifndef LOG_NDEBUG
-#ifdef NDEBUG
-#define LOG_NDEBUG 1
-#else
-#define LOG_NDEBUG 0
-#endif
-#endif
-
-/*
- * This is the local tag used for the following simplified
- * logging macros. You can change this preprocessor definition
- * before using the other macros to change the tag.
- */
-#ifndef LOG_TAG
-#define LOG_TAG "RasterMill"
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose log message using the current LOG_TAG.
- */
-#ifndef ALOGV
-#if LOG_NDEBUG
-#define ALOGV(...) ((void)0)
-#else
-#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
-
-#ifndef ALOGV_IF
-#if LOG_NDEBUG
-#define ALOGV_IF(cond, ...) ((void)0)
-#else
-#define ALOGV_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug log message using the current LOG_TAG.
- */
-#ifndef ALOGD
-#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGD_IF
-#define ALOGD_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info log message using the current LOG_TAG.
- */
-#ifndef ALOGI
-#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGI_IF
-#define ALOGI_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning log message using the current LOG_TAG.
- */
-#ifndef ALOGW
-#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGW_IF
-#define ALOGW_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error log message using the current LOG_TAG.
- */
-#ifndef ALOGE
-#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGE_IF
-#define ALOGE_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * verbose priority.
- */
-#ifndef IF_ALOGV
-#if LOG_NDEBUG
-#define IF_ALOGV() if (false)
-#else
-#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
-#endif
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * debug priority.
- */
-#ifndef IF_ALOGD
-#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * info priority.
- */
-#ifndef IF_ALOGI
-#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * warn priority.
- */
-#ifndef IF_ALOGW
-#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * error priority.
- */
-#ifndef IF_ALOGE
-#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Log a fatal error. If the given condition fails, this stops program
- * execution like a normal assertion, but also generating the given message.
- * It is NOT stripped from release builds. Note that the condition test
- * is -inverted- from the normal assert() semantics.
- */
-#ifndef LOG_ALWAYS_FATAL_IF
-#define LOG_ALWAYS_FATAL_IF(cond, ...) \
- ( (CONDITION(cond)) \
- ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
- : (void)0 )
-#endif
-
-#ifndef LOG_ALWAYS_FATAL
-#define LOG_ALWAYS_FATAL(...) \
- ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
-#endif
-
-/*
- * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
- * are stripped out of release builds.
- */
-#if LOG_NDEBUG
-
-#ifndef LOG_FATAL_IF
-#define LOG_FATAL_IF(cond, ...) ((void)0)
-#endif
-#ifndef LOG_FATAL
-#define LOG_FATAL(...) ((void)0)
-#endif
-
-#else
-
-#ifndef LOG_FATAL_IF
-#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
-#endif
-#ifndef LOG_FATAL
-#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
-#endif
-
-#endif
-
-/*
- * Assertion that generates a log message when the assertion fails.
- * Stripped out of release builds. Uses the current LOG_TAG.
- */
-#ifndef ALOG_ASSERT
-#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
-//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Basic log message macro.
- *
- * Example:
- * ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
- *
- * The second argument may be NULL or "" to indicate the "global" tag.
- */
-#ifndef ALOG
-#define ALOG(priority, tag, ...) \
- LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to specify a number for the priority.
- */
-#ifndef LOG_PRI
-#define LOG_PRI(priority, tag, ...) \
- __android_log_print(priority, tag, __VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to pass in a varargs ("args" is a va_list).
- */
-#ifndef LOG_PRI_VA
-#define LOG_PRI_VA(priority, tag, fmt, args) \
- __android_log_vprint(priority, NULL, tag, fmt, args)
-#endif
-
-/*
- * Conditional given a desired logging priority and tag.
- */
-#ifndef IF_ALOG
-#define IF_ALOG(priority, tag) \
- if (__android_log_assert(ANDROID_##priority, tag))
-#endif
-
-/* Returns 2nd arg. Used to substitute default value if caller's vararg list
- * is empty.
- */
-#define __android_second(dummy, second, ...) second
-
-/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
- * returns nothing.
- */
-#define __android_rest(first, ...) , ## __VA_ARGS__
-
-#define android_printAssert(cond, tag, fmt...) \
- __android_log_assert(cond, tag, \
- __android_second(0, ## fmt, NULL) __android_rest(fmt))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LOG_H_ */
diff --git a/framesequence/jni/utils/math.h b/framesequence/jni/utils/math.h
deleted file mode 100644
index 87f100b9..00000000
--- a/framesequence/jni/utils/math.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MATH_H_
-#define MATH_H_
-
-#define max(a,b) \
- ({ __typeof__ (a) _a = (a); \
- __typeof__ (b) _b = (b); \
- _a > _b ? _a : _b; })
-
-#define min(a,b) \
- ({ __typeof__ (a) _a = (a); \
- __typeof__ (b) _b = (b); \
- _a < _b ? _a : _b; })
-
-#endif /* MATH_H_ */
diff --git a/framesequence/samples/FrameSequenceSamples/Android.bp b/framesequence/samples/FrameSequenceSamples/Android.bp
deleted file mode 100644
index f6bd93f0..00000000
--- a/framesequence/samples/FrameSequenceSamples/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2014 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_app {
-
- name: "FrameSequenceSample",
- // java dependency
- static_libs: ["android-common-framesequence"],
- jni_libs: ["libframesequence"],
- // proguard for framesequence library code
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
- sdk_version: "19",
- srcs: ["src/**/*.java"],
- resource_dirs: ["res"],
- aaptflags: [
- "--auto-add-overlay",
- "--extra-packages",
- "com.android.framesequence.samples",
- ],
-
- product_specific: true,
-}
diff --git a/framesequence/samples/FrameSequenceSamples/AndroidManifest.xml b/framesequence/samples/FrameSequenceSamples/AndroidManifest.xml
deleted file mode 100644
index d6146318..00000000
--- a/framesequence/samples/FrameSequenceSamples/AndroidManifest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.framesequence.samples"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="15"
- android:targetSdkVersion="18" />
-
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name" >
- <activity
- android:name=".SamplesList"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity android:name=".FrameSequenceTest" />
- </application>
-
-</manifest>
diff --git a/framesequence/samples/FrameSequenceSamples/build.xml b/framesequence/samples/FrameSequenceSamples/build.xml
deleted file mode 100644
index 5e55b4e5..00000000
--- a/framesequence/samples/FrameSequenceSamples/build.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="RastermillSamples" default="help">
-
- <!-- The local.properties file is created and updated by the 'android' tool.
- It contains the path to the SDK. It should *NOT* be checked into
- Version Control Systems. -->
- <property file="local.properties" />
-
- <!-- The ant.properties file can be created by you. It is only edited by the
- 'android' tool to add properties to it.
- This is the place to change some Ant specific build properties.
- Here are some properties you may want to change/update:
-
- source.dir
- The name of the source directory. Default is 'src'.
- out.dir
- The name of the output directory. Default is 'bin'.
-
- For other overridable properties, look at the beginning of the rules
- files in the SDK, at tools/ant/build.xml
-
- Properties related to the SDK location or the project target should
- be updated using the 'android' tool with the 'update' action.
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems.
-
- -->
- <property file="ant.properties" />
-
- <!-- if sdk.dir was not set from one of the property file, then
- get it from the ANDROID_HOME env var.
- This must be done before we load project.properties since
- the proguard config can use sdk.dir -->
- <property environment="env" />
- <condition property="sdk.dir" value="${env.ANDROID_HOME}">
- <isset property="env.ANDROID_HOME" />
- </condition>
-
- <!-- The project.properties file is created and updated by the 'android'
- tool, as well as ADT.
-
- This contains project specific properties such as project target, and library
- dependencies. Lower level build properties are stored in ant.properties
- (or in .classpath for Eclipse projects).
-
- This file is an integral part of the build system for your
- application and should be checked into Version Control Systems. -->
- <loadproperties srcFile="project.properties" />
-
- <!-- quick check on sdk.dir -->
- <fail
- message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
- unless="sdk.dir"
- />
-
- <target name="-pre-build">
- <ant dir="../../" target="release" inheritAll="false" />
- <copy todir="libs">
- <fileset dir="../../exported_libs" />
- </copy>
- </target>
-
- <!--
- Import per project custom build rules if present at the root of the project.
- This is the place to put custom intermediary targets such as:
- -pre-build
- -pre-compile
- -post-compile (This is typically used for code obfuscation.
- Compiled code location: ${out.classes.absolute.dir}
- If this is not done in place, override ${out.dex.input.absolute.dir})
- -post-package
- -post-build
- -pre-clean
- -->
- <import file="custom_rules.xml" optional="true" />
-
- <!-- Import the actual build file.
-
- To customize existing targets, there are two options:
- - Customize only one target:
- - copy/paste the target into this file, *before* the
- <import> task.
- - customize it to your needs.
- - Customize the whole content of build.xml
- - copy/paste the content of the rules files (minus the top node)
- into this file, replacing the <import> task.
- - customize to your needs.
-
- ***********************
- ****** IMPORTANT ******
- ***********************
- In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
- in order to avoid having your file be overridden by tools such as "android update project"
- -->
- <!-- version-tag: 1 -->
- <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/framesequence/samples/FrameSequenceSamples/proguard.flags b/framesequence/samples/FrameSequenceSamples/proguard.flags
deleted file mode 100644
index 4acde2d6..00000000
--- a/framesequence/samples/FrameSequenceSamples/proguard.flags
+++ /dev/null
@@ -1,3 +0,0 @@
--keep class android.support.rastermill.** {
- *;
-}
diff --git a/framesequence/samples/FrameSequenceSamples/project.properties b/framesequence/samples/FrameSequenceSamples/project.properties
deleted file mode 100644
index ce39f2d0..00000000
--- a/framesequence/samples/FrameSequenceSamples/project.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-18
diff --git a/framesequence/samples/FrameSequenceSamples/res/drawable-hdpi/ic_launcher.png b/framesequence/samples/FrameSequenceSamples/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 96a442e5..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/framesequence/samples/FrameSequenceSamples/res/drawable-mdpi/ic_launcher.png b/framesequence/samples/FrameSequenceSamples/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index 359047df..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/framesequence/samples/FrameSequenceSamples/res/drawable-xhdpi/ic_launcher.png b/framesequence/samples/FrameSequenceSamples/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 71c6d760..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/framesequence/samples/FrameSequenceSamples/res/layout/basic_test_activity.xml b/framesequence/samples/FrameSequenceSamples/res/layout/basic_test_activity.xml
deleted file mode 100644
index ebe72290..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/layout/basic_test_activity.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <View
- android:id="@+id/drawableview"
- android:layout_width="match_parent"
- android:layout_height="300dp" />
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <Button
- android:id="@+id/start"
- android:text="@string/start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- <Button
- android:id="@+id/stop"
- android:text="@string/stop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- <Button
- android:id="@+id/vis"
- android:text="@string/vis"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- <Button
- android:id="@+id/invis"
- android:text="@string/invis"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
- <Button
- android:id="@+id/circle_mask"
- android:text="@string/circle_mask"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-</LinearLayout>
diff --git a/framesequence/samples/FrameSequenceSamples/res/raw/animated_gif.gif b/framesequence/samples/FrameSequenceSamples/res/raw/animated_gif.gif
deleted file mode 100644
index 51baf158..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/raw/animated_gif.gif
+++ /dev/null
Binary files differ
diff --git a/framesequence/samples/FrameSequenceSamples/res/raw/animated_webp.webp b/framesequence/samples/FrameSequenceSamples/res/raw/animated_webp.webp
deleted file mode 100644
index 25c6a4dd..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/raw/animated_webp.webp
+++ /dev/null
Binary files differ
diff --git a/framesequence/samples/FrameSequenceSamples/res/values/strings.xml b/framesequence/samples/FrameSequenceSamples/res/values/strings.xml
deleted file mode 100644
index b9ace00d..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/values/strings.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <!-- NOTE: all strings should be marked as translatable=false,
- since this sample app is for testing, and won't be shipped -->
-
- <string name="app_name" translatable="false">FrameSequence Samples</string>
- <string name="action_settings" translatable="false">Settings</string>
-
- <string name="start" translatable="false">start</string>
- <string name="stop" translatable="false">stop</string>
- <string name="vis" translatable="false">vis</string>
- <string name="invis" translatable="false">invis</string>
-
- <string name="circle_mask" translatable="false">Toggle Circle Mask</string>
-
-</resources>
diff --git a/framesequence/samples/FrameSequenceSamples/res/values/styles.xml b/framesequence/samples/FrameSequenceSamples/res/values/styles.xml
deleted file mode 100644
index 737bdc38..00000000
--- a/framesequence/samples/FrameSequenceSamples/res/values/styles.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<resources>
-
- <!-- Application theme. -->
- <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
- </style>
-
-</resources>
diff --git a/framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/FrameSequenceTest.java b/framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/FrameSequenceTest.java
deleted file mode 100644
index 7f66ce14..00000000
--- a/framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/FrameSequenceTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.framesequence.samples;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.support.rastermill.FrameSequence;
-import android.support.rastermill.FrameSequenceDrawable;
-import android.view.View;
-import android.widget.Toast;
-
-import java.io.InputStream;
-import java.util.HashSet;
-
-public class FrameSequenceTest extends Activity {
- FrameSequenceDrawable mDrawable;
- int mResourceId;
-
- // This provider is entirely unnecessary, just here to validate the acquire/release process
- private class CheckingProvider implements FrameSequenceDrawable.BitmapProvider {
- HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
- @Override
- public Bitmap acquireBitmap(int minWidth, int minHeight) {
- Bitmap bitmap =
- Bitmap.createBitmap(minWidth + 1, minHeight + 4, Bitmap.Config.ARGB_8888);
- mBitmaps.add(bitmap);
- return bitmap;
- }
-
- @Override
- public void releaseBitmap(Bitmap bitmap) {
- if (!mBitmaps.contains(bitmap)) throw new IllegalStateException();
- mBitmaps.remove(bitmap);
- bitmap.recycle();
- }
-
- public boolean isEmpty() {
- return mBitmaps.isEmpty();
- }
- }
-
- final CheckingProvider mProvider = new CheckingProvider();
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mResourceId = getIntent().getIntExtra("resourceId", R.raw.animated_gif);
-
- setContentView(R.layout.basic_test_activity);
- findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mDrawable.start();
- }
- });
- findViewById(R.id.stop).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mDrawable.stop();
- }
- });
- findViewById(R.id.vis).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mDrawable.setVisible(true, true);
- }
- });
- findViewById(R.id.invis).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mDrawable.setVisible(false, true);
- }
- });
- findViewById(R.id.circle_mask).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mDrawable.setCircleMaskEnabled(!mDrawable.getCircleMaskEnabled());
- }
- });
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- View drawableView = findViewById(R.id.drawableview);
- InputStream is = getResources().openRawResource(mResourceId);
-
- FrameSequence fs = FrameSequence.decodeStream(is);
- mDrawable = new FrameSequenceDrawable(fs, mProvider);
- mDrawable.setOnFinishedListener(new FrameSequenceDrawable.OnFinishedListener() {
- @Override
- public void onFinished(FrameSequenceDrawable drawable) {
- Toast.makeText(getApplicationContext(),
- "The animation has finished", Toast.LENGTH_SHORT).show();
- }
- });
- drawableView.setBackgroundDrawable(mDrawable);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- View drawableView = findViewById(R.id.drawableview);
-
- mDrawable.destroy();
- if (!mProvider.isEmpty()) throw new IllegalStateException("All bitmaps not recycled");
-
- mDrawable = null;
- drawableView.setBackgroundDrawable(null);
- }
-}
diff --git a/framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/SamplesList.java b/framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/SamplesList.java
deleted file mode 100644
index 36cc784c..00000000
--- a/framesequence/samples/FrameSequenceSamples/src/com/android/framesequence/samples/SamplesList.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.framesequence.samples;
-
-import android.app.ListActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.ListView;
-import android.widget.SimpleAdapter;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-public class SamplesList extends ListActivity {
-
- static final String KEY_NAME = "name";
- static final String KEY_CLASS = "clazz";
- static final String KEY_RESOURCE = "res";
-
- static Map<String,?> makeSample(String name, Class<?> activity, int resourceId) {
- Map<String,Object> ret = new HashMap<String,Object>();
- ret.put(KEY_NAME, name);
- ret.put(KEY_CLASS, activity);
- ret.put(KEY_RESOURCE, resourceId);
- return ret;
- }
-
- static final ArrayList<Map<String,?>> SAMPLES = new ArrayList<>();
- static {
- SAMPLES.add(makeSample("GIF animation", FrameSequenceTest.class, R.raw.animated_gif));
- SAMPLES.add(makeSample("WEBP animation", FrameSequenceTest.class, R.raw.animated_webp));
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setListAdapter(new SimpleAdapter(this, SAMPLES,
- android.R.layout.simple_list_item_1, new String[] { KEY_NAME },
- new int[] { android.R.id.text1 }));
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- Class<?> clazz = (Class<?>) SAMPLES.get(position).get(KEY_CLASS);
- int resourceId = ((Integer) SAMPLES.get(position).get(KEY_RESOURCE)).intValue();
-
- Intent intent = new Intent(this, clazz);
- intent.putExtra("resourceId", resourceId);
- startActivity(intent);
- }
-
-}
diff --git a/framesequence/src/android/support/rastermill/FrameSequence.java b/framesequence/src/android/support/rastermill/FrameSequence.java
index 8ff241fa..1af64d2b 100644
--- a/framesequence/src/android/support/rastermill/FrameSequence.java
+++ b/framesequence/src/android/support/rastermill/FrameSequence.java
@@ -16,136 +16,42 @@
package android.support.rastermill;
-import android.graphics.Bitmap;
import java.nio.ByteBuffer;
import java.io.InputStream;
+/**
+ * Entire class is a no-op, does nothing
+ */
+@Deprecated
public class FrameSequence {
static {
System.loadLibrary("framesequence");
}
- private final long mNativeFrameSequence;
- private final int mWidth;
- private final int mHeight;
- private final boolean mOpaque;
- private final int mFrameCount;
- private final int mDefaultLoopCount;
-
- public int getWidth() { return mWidth; }
- public int getHeight() { return mHeight; }
- public boolean isOpaque() { return mOpaque; }
- public int getFrameCount() { return mFrameCount; }
- public int getDefaultLoopCount() { return mDefaultLoopCount; }
+ public int getWidth() { return 0; }
+ public int getHeight() { return 0; }
+ public boolean isOpaque() { return true; }
+ public int getFrameCount() { return 0; }
+ public int getDefaultLoopCount() { return 0; }
- private static native FrameSequence nativeDecodeByteArray(byte[] data, int offset, int length);
- private static native FrameSequence nativeDecodeStream(InputStream is, byte[] tempStorage);
- private static native FrameSequence nativeDecodeByteBuffer(ByteBuffer buffer, int offset, int capacity);
- private static native void nativeDestroyFrameSequence(long nativeFrameSequence);
- private static native long nativeCreateState(long nativeFrameSequence);
- private static native void nativeDestroyState(long nativeState);
- private static native long nativeGetFrame(long nativeState, int frameNr,
- Bitmap output, int previousFrameNr);
-
- @SuppressWarnings("unused") // called by native
- private FrameSequence(long nativeFrameSequence, int width, int height,
- boolean opaque, int frameCount, int defaultLoopCount) {
- mNativeFrameSequence = nativeFrameSequence;
- mWidth = width;
- mHeight = height;
- mOpaque = opaque;
- mFrameCount = frameCount;
- mDefaultLoopCount = defaultLoopCount;
+ @SuppressWarnings("unused")
+ private FrameSequence() {
}
public static FrameSequence decodeByteArray(byte[] data) {
- return decodeByteArray(data, 0, data.length);
+ return null;
}
public static FrameSequence decodeByteArray(byte[] data, int offset, int length) {
- if (data == null) throw new IllegalArgumentException();
- if (offset < 0 || length < 0 || (offset + length > data.length)) {
- throw new IllegalArgumentException("invalid offset/length parameters");
- }
- return nativeDecodeByteArray(data, offset, length);
+ return null;
}
public static FrameSequence decodeByteBuffer(ByteBuffer buffer) {
- if (buffer == null) throw new IllegalArgumentException();
- if (!buffer.isDirect()) {
- if (buffer.hasArray()) {
- byte[] byteArray = buffer.array();
- return decodeByteArray(byteArray, buffer.position(), buffer.remaining());
- } else {
- throw new IllegalArgumentException("Cannot have non-direct ByteBuffer with no byte array");
- }
- }
- return nativeDecodeByteBuffer(buffer, buffer.position(), buffer.remaining());
+ return null;
}
public static FrameSequence decodeStream(InputStream stream) {
- if (stream == null) throw new IllegalArgumentException();
- byte[] tempStorage = new byte[16 * 1024]; // TODO: use buffer pool
- return nativeDecodeStream(stream, tempStorage);
- }
-
- State createState() {
- if (mNativeFrameSequence == 0) {
- throw new IllegalStateException("attempted to use incorrectly built FrameSequence");
- }
-
- long nativeState = nativeCreateState(mNativeFrameSequence);
- if (nativeState == 0) {
- return null;
- }
- return new State(nativeState);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mNativeFrameSequence != 0) nativeDestroyFrameSequence(mNativeFrameSequence);
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Playback state used when moving frames forward in a frame sequence.
- *
- * Note that this doesn't require contiguous frames to be rendered, it just stores
- * information (in the case of gif, a recall buffer) that will be used to construct
- * frames based upon data recorded before previousFrameNr.
- *
- * Note: {@link #destroy()} *must* be called before the object is GC'd to free native resources
- *
- * Note: State holds a native ref to its FrameSequence instance, so its FrameSequence should
- * remain ref'd while it is in use
- */
- static class State {
- private long mNativeState;
-
- public State(long nativeState) {
- mNativeState = nativeState;
- }
-
- public void destroy() {
- if (mNativeState != 0) {
- nativeDestroyState(mNativeState);
- mNativeState = 0;
- }
- }
-
- // TODO: consider adding alternate API for drawing into a SurfaceTexture
- public long getFrame(int frameNr, Bitmap output, int previousFrameNr) {
- if (output == null || output.getConfig() != Bitmap.Config.ARGB_8888) {
- throw new IllegalArgumentException("Bitmap passed must be non-null and ARGB_8888");
- }
- if (mNativeState == 0) {
- throw new IllegalStateException("attempted to draw destroyed FrameSequenceState");
- }
- return nativeGetFrame(mNativeState, frameNr, output, previousFrameNr);
- }
+ return null;
}
}
diff --git a/framesequence/src/android/support/rastermill/FrameSequenceDrawable.java b/framesequence/src/android/support/rastermill/FrameSequenceDrawable.java
index d86df62a..30e3a0c4 100644
--- a/framesequence/src/android/support/rastermill/FrameSequenceDrawable.java
+++ b/framesequence/src/android/support/rastermill/FrameSequenceDrawable.java
@@ -17,524 +17,116 @@
package android.support.rastermill;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorFilter;
-import android.graphics.Paint;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Shader;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.os.SystemClock;
-import android.util.Log;
+/**
+ * Entire class is a no-op, does nothing
+ */
+@Deprecated
public class FrameSequenceDrawable extends Drawable implements Animatable, Runnable {
- private static final String TAG = "FrameSequence";
- /**
- * These constants are chosen to imitate common browser behavior for WebP/GIF.
- * If other decoders are added, this behavior should be moved into the WebP/GIF decoders.
- *
- * Note that 0 delay is undefined behavior in the GIF standard.
- */
- private static final long MIN_DELAY_MS = 20;
- private static final long DEFAULT_DELAY_MS = 100;
-
- private static final Object sLock = new Object();
- private static HandlerThread sDecodingThread;
- private static Handler sDecodingThreadHandler;
- private static void initializeDecodingThread() {
- synchronized (sLock) {
- if (sDecodingThread != null) return;
-
- sDecodingThread = new HandlerThread("FrameSequence decoding thread",
- Process.THREAD_PRIORITY_BACKGROUND);
- sDecodingThread.start();
- sDecodingThreadHandler = new Handler(sDecodingThread.getLooper());
- }
- }
public static interface OnFinishedListener {
- /**
- * Called when a FrameSequenceDrawable has finished looping.
- *
- * Note that this is will not be called if the drawable is explicitly
- * stopped, or marked invisible.
- */
public abstract void onFinished(FrameSequenceDrawable drawable);
}
public static interface BitmapProvider {
- /**
- * Called by FrameSequenceDrawable to aquire an 8888 Bitmap with minimum dimensions.
- */
public abstract Bitmap acquireBitmap(int minWidth, int minHeight);
- /**
- * Called by FrameSequenceDrawable to release a Bitmap it no longer needs. The Bitmap
- * will no longer be used at all by the drawable, so it is safe to reuse elsewhere.
- *
- * This method may be called by FrameSequenceDrawable on any thread.
- */
public abstract void releaseBitmap(Bitmap bitmap);
}
- private static BitmapProvider sAllocatingBitmapProvider = new BitmapProvider() {
- @Override
- public Bitmap acquireBitmap(int minWidth, int minHeight) {
- return Bitmap.createBitmap(minWidth, minHeight, Bitmap.Config.ARGB_8888);
- }
-
- @Override
- public void releaseBitmap(Bitmap bitmap) {}
- };
-
- /**
- * Register a callback to be invoked when a FrameSequenceDrawable finishes looping.
- *
- * @see #setLoopBehavior(int)
- */
public void setOnFinishedListener(OnFinishedListener onFinishedListener) {
- mOnFinishedListener = onFinishedListener;
}
- /**
- * Loop a finite number of times, which can be set using setLoopCount. Default to loop once.
- */
public static final int LOOP_FINITE = 1;
- /**
- * Loop continuously. The OnFinishedListener will never be called.
- */
public static final int LOOP_INF = 2;
- /**
- * Use loop count stored in source data, or LOOP_ONCE if not present.
- */
public static final int LOOP_DEFAULT = 3;
- /**
- * Loop only once.
- *
- * @deprecated Use LOOP_FINITE instead.
- */
@Deprecated
public static final int LOOP_ONCE = LOOP_FINITE;
- /**
- * Define looping behavior of frame sequence.
- *
- * Must be one of LOOP_ONCE, LOOP_INF, LOOP_DEFAULT, or LOOP_FINITE.
- */
public void setLoopBehavior(int loopBehavior) {
- mLoopBehavior = loopBehavior;
+
}
- /**
- * Set the number of loops in LOOP_FINITE mode. The number must be a postive integer.
- */
public void setLoopCount(int loopCount) {
- mLoopCount = loopCount;
- }
- private final FrameSequence mFrameSequence;
- private final FrameSequence.State mFrameSequenceState;
-
- private final Paint mPaint;
- private BitmapShader mFrontBitmapShader;
- private BitmapShader mBackBitmapShader;
- private final Rect mSrcRect;
- private boolean mCircleMaskEnabled;
-
- //Protects the fields below
- private final Object mLock = new Object();
-
- private final BitmapProvider mBitmapProvider;
- private boolean mDestroyed = false;
- private Bitmap mFrontBitmap;
- private Bitmap mBackBitmap;
-
- private static final int STATE_SCHEDULED = 1;
- private static final int STATE_DECODING = 2;
- private static final int STATE_WAITING_TO_SWAP = 3;
- private static final int STATE_READY_TO_SWAP = 4;
-
- private int mState;
- private int mCurrentLoop;
- private int mLoopBehavior = LOOP_DEFAULT;
- private int mLoopCount = 1;
-
- private long mLastSwap;
- private long mNextSwap;
- private int mNextFrameToDecode;
- private OnFinishedListener mOnFinishedListener;
-
- private RectF mTempRectF = new RectF();
-
- /**
- * Runs on decoding thread, only modifies mBackBitmap's pixels
- */
- private Runnable mDecodeRunnable = new Runnable() {
- @Override
- public void run() {
- int nextFrame;
- Bitmap bitmap;
- synchronized (mLock) {
- if (mDestroyed) return;
-
- nextFrame = mNextFrameToDecode;
- if (nextFrame < 0) {
- return;
- }
- bitmap = mBackBitmap;
- mState = STATE_DECODING;
- }
- int lastFrame = nextFrame - 2;
- boolean exceptionDuringDecode = false;
- long invalidateTimeMs = 0;
- try {
- invalidateTimeMs = mFrameSequenceState.getFrame(nextFrame, bitmap, lastFrame);
- } catch(Exception e) {
- // Exception during decode: continue, but delay next frame indefinitely.
- Log.e(TAG, "exception during decode: " + e);
- exceptionDuringDecode = true;
- }
-
- if (invalidateTimeMs < MIN_DELAY_MS) {
- invalidateTimeMs = DEFAULT_DELAY_MS;
- }
-
- boolean schedule = false;
- Bitmap bitmapToRelease = null;
- synchronized (mLock) {
- if (mDestroyed) {
- bitmapToRelease = mBackBitmap;
- mBackBitmap = null;
- } else if (mNextFrameToDecode >= 0 && mState == STATE_DECODING) {
- schedule = true;
- mNextSwap = exceptionDuringDecode ? Long.MAX_VALUE : invalidateTimeMs + mLastSwap;
- mState = STATE_WAITING_TO_SWAP;
- }
- }
- if (schedule) {
- scheduleSelf(FrameSequenceDrawable.this, mNextSwap);
- }
- if (bitmapToRelease != null) {
- // destroy the bitmap here, since there's no safe way to get back to
- // drawable thread - drawable is likely detached, so schedule is noop.
- mBitmapProvider.releaseBitmap(bitmapToRelease);
- }
- }
- };
-
- private Runnable mFinishedCallbackRunnable = new Runnable() {
- @Override
- public void run() {
- synchronized (mLock) {
- mNextFrameToDecode = -1;
- mState = 0;
- }
- if (mOnFinishedListener != null) {
- mOnFinishedListener.onFinished(FrameSequenceDrawable.this);
- }
- }
- };
-
- private static Bitmap acquireAndValidateBitmap(BitmapProvider bitmapProvider,
- int minWidth, int minHeight) {
- Bitmap bitmap = bitmapProvider.acquireBitmap(minWidth, minHeight);
-
- if (bitmap.getWidth() < minWidth
- || bitmap.getHeight() < minHeight
- || bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
- throw new IllegalArgumentException("Invalid bitmap provided");
- }
-
- return bitmap;
}
public FrameSequenceDrawable(FrameSequence frameSequence) {
- this(frameSequence, sAllocatingBitmapProvider);
}
public FrameSequenceDrawable(FrameSequence frameSequence, BitmapProvider bitmapProvider) {
- if (frameSequence == null || bitmapProvider == null) throw new IllegalArgumentException();
-
- mFrameSequence = frameSequence;
- mFrameSequenceState = frameSequence.createState();
- final int width = frameSequence.getWidth();
- final int height = frameSequence.getHeight();
-
- mBitmapProvider = bitmapProvider;
- mFrontBitmap = acquireAndValidateBitmap(bitmapProvider, width, height);
- mBackBitmap = acquireAndValidateBitmap(bitmapProvider, width, height);
- mSrcRect = new Rect(0, 0, width, height);
- mPaint = new Paint();
- mPaint.setFilterBitmap(true);
-
- mFrontBitmapShader
- = new BitmapShader(mFrontBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
- mBackBitmapShader
- = new BitmapShader(mBackBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-
- mLastSwap = 0;
-
- mNextFrameToDecode = -1;
- mFrameSequenceState.getFrame(0, mFrontBitmap, -1);
- initializeDecodingThread();
}
- /**
- * Pass true to mask the shape of the animated drawing content to a circle.
- *
- * <p> The masking circle will be the largest circle contained in the Drawable's bounds.
- * Masking is done with BitmapShader, incurring minimal additional draw cost.
- */
public final void setCircleMaskEnabled(boolean circleMaskEnabled) {
- if (mCircleMaskEnabled != circleMaskEnabled) {
- mCircleMaskEnabled = circleMaskEnabled;
- // Anti alias only necessary when using circular mask
- mPaint.setAntiAlias(circleMaskEnabled);
- invalidateSelf();
- }
}
public final boolean getCircleMaskEnabled() {
- return mCircleMaskEnabled;
- }
-
- private void checkDestroyedLocked() {
- if (mDestroyed) {
- throw new IllegalStateException("Cannot perform operation on recycled drawable");
- }
+ return false;
}
public boolean isDestroyed() {
- synchronized (mLock) {
- return mDestroyed;
- }
+ return true;
}
- /**
- * Marks the drawable as permanently recycled (and thus unusable), and releases any owned
- * Bitmaps drawable to its BitmapProvider, if attached.
- *
- * If no BitmapProvider is attached to the drawable, recycle() is called on the Bitmaps.
- */
public void destroy() {
- if (mBitmapProvider == null) {
- throw new IllegalStateException("BitmapProvider must be non-null");
- }
-
- Bitmap bitmapToReleaseA;
- Bitmap bitmapToReleaseB = null;
- synchronized (mLock) {
- checkDestroyedLocked();
-
- bitmapToReleaseA = mFrontBitmap;
- mFrontBitmap = null;
-
- if (mState != STATE_DECODING) {
- bitmapToReleaseB = mBackBitmap;
- mBackBitmap = null;
- }
-
- mDestroyed = true;
- }
-
- // For simplicity and safety, we don't destroy the state object here
- mBitmapProvider.releaseBitmap(bitmapToReleaseA);
- if (bitmapToReleaseB != null) {
- mBitmapProvider.releaseBitmap(bitmapToReleaseB);
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- mFrameSequenceState.destroy();
- } finally {
- super.finalize();
- }
}
@Override
public void draw(Canvas canvas) {
- synchronized (mLock) {
- checkDestroyedLocked();
- if (mState == STATE_WAITING_TO_SWAP) {
- // may have failed to schedule mark ready runnable,
- // so go ahead and swap if swapping is due
- if (mNextSwap - SystemClock.uptimeMillis() <= 0) {
- mState = STATE_READY_TO_SWAP;
- }
- }
-
- if (isRunning() && mState == STATE_READY_TO_SWAP) {
- // Because draw has occurred, the view system is guaranteed to no longer hold a
- // reference to the old mFrontBitmap, so we now use it to produce the next frame
- Bitmap tmp = mBackBitmap;
- mBackBitmap = mFrontBitmap;
- mFrontBitmap = tmp;
-
- BitmapShader tmpShader = mBackBitmapShader;
- mBackBitmapShader = mFrontBitmapShader;
- mFrontBitmapShader = tmpShader;
-
- mLastSwap = SystemClock.uptimeMillis();
-
- boolean continueLooping = true;
- if (mNextFrameToDecode == mFrameSequence.getFrameCount() - 1) {
- mCurrentLoop++;
- if ((mLoopBehavior == LOOP_FINITE && mCurrentLoop == mLoopCount) ||
- (mLoopBehavior == LOOP_DEFAULT && mCurrentLoop == mFrameSequence.getDefaultLoopCount())) {
- continueLooping = false;
- }
- }
-
- if (continueLooping) {
- scheduleDecodeLocked();
- } else {
- scheduleSelf(mFinishedCallbackRunnable, 0);
- }
- }
- }
-
- if (mCircleMaskEnabled) {
- final Rect bounds = getBounds();
- final int bitmapWidth = getIntrinsicWidth();
- final int bitmapHeight = getIntrinsicHeight();
- final float scaleX = 1.0f * bounds.width() / bitmapWidth;
- final float scaleY = 1.0f * bounds.height() / bitmapHeight;
-
- canvas.save();
- // scale and translate to account for bounds, so we can operate in intrinsic
- // width/height (so it's valid to use an unscaled bitmap shader)
- canvas.translate(bounds.left, bounds.top);
- canvas.scale(scaleX, scaleY);
-
- final float unscaledCircleDiameter = Math.min(bounds.width(), bounds.height());
- final float scaledDiameterX = unscaledCircleDiameter / scaleX;
- final float scaledDiameterY = unscaledCircleDiameter / scaleY;
-
- // Want to draw a circle, but we have to compensate for canvas scale
- mTempRectF.set(
- (bitmapWidth - scaledDiameterX) / 2.0f,
- (bitmapHeight - scaledDiameterY) / 2.0f,
- (bitmapWidth + scaledDiameterX) / 2.0f,
- (bitmapHeight + scaledDiameterY) / 2.0f);
- mPaint.setShader(mFrontBitmapShader);
- canvas.drawOval(mTempRectF, mPaint);
- canvas.restore();
- } else {
- mPaint.setShader(null);
- canvas.drawBitmap(mFrontBitmap, mSrcRect, getBounds(), mPaint);
- }
- }
-
- private void scheduleDecodeLocked() {
- mState = STATE_SCHEDULED;
- mNextFrameToDecode = (mNextFrameToDecode + 1) % mFrameSequence.getFrameCount();
- sDecodingThreadHandler.post(mDecodeRunnable);
+ canvas.drawColor(Color.MAGENTA);
}
@Override
public void run() {
- // set ready to swap as necessary
- boolean invalidate = false;
- synchronized (mLock) {
- if (mNextFrameToDecode >= 0 && mState == STATE_WAITING_TO_SWAP) {
- mState = STATE_READY_TO_SWAP;
- invalidate = true;
- }
- }
- if (invalidate) {
- invalidateSelf();
- }
}
@Override
public void start() {
- if (!isRunning()) {
- synchronized (mLock) {
- checkDestroyedLocked();
- if (mState == STATE_SCHEDULED) return; // already scheduled
- mCurrentLoop = 0;
- scheduleDecodeLocked();
- }
- }
}
@Override
public void stop() {
- if (isRunning()) {
- unscheduleSelf(this);
- }
}
@Override
public boolean isRunning() {
- synchronized (mLock) {
- return mNextFrameToDecode > -1 && !mDestroyed;
- }
+ return false;
}
@Override
- public void unscheduleSelf(Runnable what) {
- synchronized (mLock) {
- mNextFrameToDecode = -1;
- mState = 0;
- }
- super.unscheduleSelf(what);
- }
-
- @Override
- public boolean setVisible(boolean visible, boolean restart) {
- boolean changed = super.setVisible(visible, restart);
-
- if (!visible) {
- stop();
- } else if (restart || changed) {
- stop();
- start();
- }
-
- return changed;
- }
-
- // drawing properties
-
- @Override
public void setFilterBitmap(boolean filter) {
- mPaint.setFilterBitmap(filter);
}
@Override
public void setAlpha(int alpha) {
- mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
- mPaint.setColorFilter(colorFilter);
+
}
@Override
public int getIntrinsicWidth() {
- return mFrameSequence.getWidth();
+ return 0;
}
@Override
public int getIntrinsicHeight() {
- return mFrameSequence.getHeight();
+ return 0;
}
@Override
public int getOpacity() {
- return mFrameSequence.isOpaque() ? PixelFormat.OPAQUE : PixelFormat.TRANSPARENT;
+ return PixelFormat.OPAQUE;
}
}