diff --git a/media/Camera/README_zh.md b/media/Camera/README_zh.md
index 7dcbf3c6b9a1cd97ca38af6fa4f1da74624d17fa..b14d2b322c107076149ae6f31183a983ca3fe946 100644
--- a/media/Camera/README_zh.md
+++ b/media/Camera/README_zh.md
@@ -1,6 +1,19 @@
# 相机
-- 相机模块支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照、连拍和录像等。
+### 简介
- 开发者也可以通过合适的接口或者接口组合实现闪光灯控制、曝光时间控制、手动对焦和自动对焦控制、变焦控制、人脸识别以及更多的功能。
-- 相机模块目前只能支持真机运行调试,不能支持模拟器。
\ No newline at end of file
+相机模块支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照、连拍和录像等。
+
+开发者也可以通过合适的接口或者接口组合实现闪光灯控制、曝光时间控制、手动对焦和自动对焦控制、变焦控制、人脸识别以及更多的功能。
+
+### 使用说明
+
+1.点击“Take Photo”,开启拍照功能;
+
+2.点击“Video Record”,开启录像功能。
+
+### 约束与限制
+
+本示例仅支持在大型系统上运行。
+
+相机模块目前只能支持真机运行调试,不能支持模拟器。
diff --git a/media/Camera/entry/src/main/java/ohos/samples/camera/TakePhotoAbility.java b/media/Camera/entry/src/main/java/ohos/samples/camera/TakePhotoAbility.java
index 7020281a0749c71cc15028f523992a8552b4263a..a14683f7c2a839c50cd1066bf0f1669d12d202cb 100644
--- a/media/Camera/entry/src/main/java/ohos/samples/camera/TakePhotoAbility.java
+++ b/media/Camera/entry/src/main/java/ohos/samples/camera/TakePhotoAbility.java
@@ -15,247 +15,18 @@
package ohos.samples.camera;
-import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PICTURE;
-import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;
-
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
-import ohos.agp.components.Component;
-import ohos.agp.components.ComponentContainer;
-import ohos.agp.components.DirectionalLayout;
-import ohos.agp.components.Image;
-import ohos.agp.components.surfaceprovider.SurfaceProvider;
-import ohos.agp.graphics.Surface;
-import ohos.agp.graphics.SurfaceOps;
-import ohos.agp.window.dialog.ToastDialog;
-import ohos.app.Context;
-import ohos.eventhandler.EventHandler;
-import ohos.eventhandler.EventRunner;
-import ohos.hiviewdfx.HiLog;
-import ohos.hiviewdfx.HiLogLabel;
-import ohos.media.camera.CameraKit;
-import ohos.media.camera.device.Camera;
-import ohos.media.camera.device.CameraConfig;
-import ohos.media.camera.device.CameraInfo;
-import ohos.media.camera.device.CameraStateCallback;
-import ohos.media.camera.device.FrameConfig;
-import ohos.media.image.ImageReceiver;
-import ohos.media.image.common.ImageFormat;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import ohos.samples.camera.slice.TakePhotoSlice;
/**
* TakePhotoAbility
*/
public class TakePhotoAbility extends Ability {
- private static final String TAG = TakePhotoAbility.class.getSimpleName();
-
- private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);
-
- private static final int SCREEN_WIDTH = 1080;
-
- private static final int SCREEN_HEIGHT = 1920;
-
- private static final int IMAGE_RCV_CAPACITY = 9;
-
- private SurfaceProvider surfaceProvider;
-
- private ImageReceiver imageReceiver;
-
- private boolean isFrontCamera;
-
- private Surface previewSurface;
-
- private Camera cameraDevice;
-
- private Component buttonGroupLayout;
-
- private ComponentContainer surfaceContainer;
-
- private final EventHandler eventHandler = new EventHandler(EventRunner.current()) {
- };
-
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_main_camera_slice);
-
- initComponents();
- initSurface();
- }
-
- private void initSurface() {
- getWindow().setTransparent(true);
- DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
- ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
- surfaceProvider = new SurfaceProvider(this);
- surfaceProvider.setLayoutConfig(params);
- surfaceProvider.pinToZTop(false);
- if (surfaceProvider.getSurfaceOps().isPresent()) {
- surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
- }
- surfaceContainer.addComponent(surfaceProvider);
- }
-
- private void initComponents() {
- buttonGroupLayout = findComponentById(ResourceTable.Id_directionalLayout);
- surfaceContainer = (ComponentContainer) findComponentById(ResourceTable.Id_surface_container);
- Image takePhotoImage = (Image) findComponentById(ResourceTable.Id_tack_picture_btn);
- Image exitImage = (Image) findComponentById(ResourceTable.Id_exit);
- Image switchCameraImage = (Image) findComponentById(ResourceTable.Id_switch_camera_btn);
- exitImage.setClickedListener(component -> terminateAbility());
- takePhotoImage.setClickedListener(this::takeSingleCapture);
- takePhotoImage.setLongClickedListener(this::takeMultiCapture);
- switchCameraImage.setClickedListener(this::switchCamera);
- }
-
- private void openCamera() {
- imageReceiver = ImageReceiver.create(SCREEN_WIDTH, SCREEN_HEIGHT, ImageFormat.JPEG, IMAGE_RCV_CAPACITY);
- imageReceiver.setImageArrivalListener(this::saveImage);
- CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
- String[] cameraList = cameraKit.getCameraIds();
- String cameraId = "";
- for (String logicalCameraId : cameraList) {
- int faceType = cameraKit.getCameraInfo(logicalCameraId).getFacingType();
- switch (faceType) {
- case CameraInfo.FacingType.CAMERA_FACING_FRONT:
- if (isFrontCamera) {
- cameraId = logicalCameraId;
- }
- break;
- case CameraInfo.FacingType.CAMERA_FACING_BACK:
- if (!isFrontCamera) {
- cameraId = logicalCameraId;
- }
- break;
- case CameraInfo.FacingType.CAMERA_FACING_OTHERS:
- default:
- break;
- }
- }
- if (cameraId != null && !cameraId.isEmpty()) {
- CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
- cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
- }
- }
-
- private void saveImage(ImageReceiver receiver) {
- File saveFile = new File(getFilesDir(), "IMG_" + System.currentTimeMillis() + ".jpg");
- ohos.media.image.Image image = receiver.readNextImage();
- ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);
- byte[] bytes = new byte[component.remaining()];
- component.read(bytes);
- try (FileOutputStream output = new FileOutputStream(saveFile)) {
- output.write(bytes);
- output.flush();
- String msg = "Take photo succeed";
- showTips(this, msg);
- } catch (IOException e) {
- HiLog.error(LABEL_LOG, "%{public}s", "saveImage IOException");
- }
- }
-
- private void takeSingleCapture(Component component) {
- if (cameraDevice == null || imageReceiver == null) {
- return;
- }
- FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
- framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
- FrameConfig pictureFrameConfig = framePictureConfigBuilder.build();
- cameraDevice.triggerSingleCapture(pictureFrameConfig);
- }
-
- private void takeMultiCapture(Component component) {
- FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
- framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
- List frameConfigs = new ArrayList<>();
- FrameConfig firstFrameConfig = framePictureConfigBuilder.build();
- frameConfigs.add(firstFrameConfig);
- FrameConfig secondFrameConfig = framePictureConfigBuilder.build();
- frameConfigs.add(secondFrameConfig);
- cameraDevice.triggerMultiCapture(frameConfigs);
- }
-
- private void switchCamera(Component component) {
- isFrontCamera = !isFrontCamera;
- if (cameraDevice != null) {
- cameraDevice.release();
- }
- updateComponentVisible(false);
- openCamera();
- }
-
- private class CameraStateCallbackImpl extends CameraStateCallback {
- CameraStateCallbackImpl() {
- }
-
- @Override
- public void onCreated(Camera camera) {
- if (surfaceProvider.getSurfaceOps().isPresent()) {
- previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
- }
- if (previewSurface == null) {
- HiLog.error(LABEL_LOG, "%{public}s", "Create camera filed, preview surface is null");
- return;
- }
- CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();
- cameraConfigBuilder.addSurface(previewSurface);
- cameraConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
- camera.configure(cameraConfigBuilder.build());
- cameraDevice = camera;
- updateComponentVisible(true);
- }
-
- @Override
- public void onConfigured(Camera camera) {
- FrameConfig.Builder framePreviewConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
- framePreviewConfigBuilder.addSurface(previewSurface);
- camera.triggerLoopingCapture(framePreviewConfigBuilder.build());
- }
- }
-
- private void updateComponentVisible(boolean isVisible) {
- buttonGroupLayout.setVisibility(isVisible ? Component.VISIBLE : Component.INVISIBLE);
- }
-
- private class SurfaceCallBack implements SurfaceOps.Callback {
- @Override
- public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
- if (callbackSurfaceOps != null) {
- callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
- }
- eventHandler.postTask(TakePhotoAbility.this::openCamera, 200);
- }
-
- @Override
- public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
- }
-
- @Override
- public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
- }
- }
-
- private void showTips(Context context, String msg) {
- getUITaskDispatcher().asyncDispatch(() -> new ToastDialog(context).setText(msg).show());
- }
-
- private void releaseCamera() {
- if (cameraDevice != null) {
- cameraDevice.release();
- }
-
- if (imageReceiver != null) {
- imageReceiver.release();
- }
- }
@Override
- protected void onStop() {
- releaseCamera();
+ public void onStart (Intent intent) {
+ super.onStart(intent);
+ super.setMainRoute(TakePhotoSlice.class.getName());
}
}
diff --git a/media/Camera/entry/src/main/java/ohos/samples/camera/VideoRecordAbility.java b/media/Camera/entry/src/main/java/ohos/samples/camera/VideoRecordAbility.java
index 1b4159c1d3fcafe214c5f3b2f67a480a918f6b61..f5b247586b832c525808ba3defcf2b4055d62a77 100644
--- a/media/Camera/entry/src/main/java/ohos/samples/camera/VideoRecordAbility.java
+++ b/media/Camera/entry/src/main/java/ohos/samples/camera/VideoRecordAbility.java
@@ -15,291 +15,17 @@
package ohos.samples.camera;
-import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;
-
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
-import ohos.agp.components.Component;
-import ohos.agp.components.ComponentContainer;
-import ohos.agp.components.DirectionalLayout;
-import ohos.agp.components.Image;
-import ohos.agp.components.surfaceprovider.SurfaceProvider;
-import ohos.agp.graphics.Surface;
-import ohos.agp.graphics.SurfaceOps;
-import ohos.agp.window.dialog.ToastDialog;
-import ohos.eventhandler.EventHandler;
-import ohos.eventhandler.EventRunner;
-import ohos.hiviewdfx.HiLog;
-import ohos.hiviewdfx.HiLogLabel;
-import ohos.media.camera.CameraKit;
-import ohos.media.camera.device.Camera;
-import ohos.media.camera.device.CameraConfig;
-import ohos.media.camera.device.CameraInfo;
-import ohos.media.camera.device.CameraStateCallback;
-import ohos.media.camera.device.FrameConfig;
-import ohos.media.common.AudioProperty;
-import ohos.media.common.Source;
-import ohos.media.common.StorageProperty;
-import ohos.media.common.VideoProperty;
-import ohos.media.recorder.Recorder;
-import ohos.multimodalinput.event.TouchEvent;
-
-import java.io.File;
+import ohos.samples.camera.slice.VideoRecordSlice;
/**
* VideoRecordAbility
*/
public class VideoRecordAbility extends Ability {
- private static final String TAG = VideoRecordAbility.class.getSimpleName();
-
- private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);
-
- private static final int SCREEN_WIDTH = 1080;
-
- private static final int SCREEN_HEIGHT = 1920;
-
- private SurfaceProvider surfaceProvider;
-
- private Surface recorderSurface;
-
- private Surface previewSurface;
-
- private boolean isFrontCamera;
-
- private Camera cameraDevice;
-
- private Component buttonGroupLayout;
-
- private Recorder mediaRecorder;
-
- private ComponentContainer surfaceContainer;
- private CameraConfig.Builder cameraConfigBuilder;
-
- private boolean isRecording;
-
- private final Object lock = new Object();
-
- private final EventHandler eventHandler = new EventHandler(EventRunner.current()) {
- };
-
- @Override
- public void onStart(Intent intent) {
+ public void onStart (Intent intent) {
super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_main_camera_slice);
-
- initComponents();
- initSurface();
- }
-
- private void initSurface() {
- getWindow().setTransparent(true);
- DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
- ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
- surfaceProvider = new SurfaceProvider(this);
- surfaceProvider.setLayoutConfig(params);
- surfaceProvider.pinToZTop(false);
- if (surfaceProvider.getSurfaceOps().isPresent()) {
- surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
- }
- surfaceContainer.addComponent(surfaceProvider);
- }
-
- private void initComponents() {
- buttonGroupLayout = findComponentById(ResourceTable.Id_directionalLayout);
- surfaceContainer = (ComponentContainer) findComponentById(ResourceTable.Id_surface_container);
- Image videoRecord = (Image) findComponentById(ResourceTable.Id_tack_picture_btn);
- Image exitImage = (Image) findComponentById(ResourceTable.Id_exit);
- Image switchCameraImage = (Image) findComponentById(ResourceTable.Id_switch_camera_btn);
- exitImage.setClickedListener(component -> terminateAbility());
- switchCameraImage.setClickedListener(this::switchCamera);
-
- videoRecord.setLongClickedListener(component -> {
- startRecord();
- isRecording = true;
- videoRecord.setPixelMap(ResourceTable.Media_ic_camera_video_press);
- });
-
- videoRecord.setTouchEventListener((component, touchEvent) -> {
- if (touchEvent != null && touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP && isRecording) {
- stopRecord();
- isRecording = false;
- videoRecord.setPixelMap(ResourceTable.Media_ic_camera_video_ready);
- }
- return true;
- });
- }
-
- private void initMediaRecorder() {
- mediaRecorder = new Recorder();
- VideoProperty.Builder videoPropertyBuilder = new VideoProperty.Builder();
- videoPropertyBuilder.setRecorderBitRate(10000000);
- videoPropertyBuilder.setRecorderDegrees(90);
- videoPropertyBuilder.setRecorderFps(30);
- videoPropertyBuilder.setRecorderHeight(Math.min(1440, 720));
- videoPropertyBuilder.setRecorderWidth(Math.max(1440, 720));
- videoPropertyBuilder.setRecorderVideoEncoder(Recorder.VideoEncoder.H264);
- videoPropertyBuilder.setRecorderRate(30);
-
- Source source = new Source();
- source.setRecorderAudioSource(Recorder.AudioSource.MIC);
- source.setRecorderVideoSource(Recorder.VideoSource.SURFACE);
- mediaRecorder.setSource(source);
- mediaRecorder.setOutputFormat(Recorder.OutputFormat.MPEG_4);
- File file = new File(getFilesDir(), "VID_" + System.currentTimeMillis() + ".mp4");
- StorageProperty.Builder storagePropertyBuilder = new StorageProperty.Builder();
- storagePropertyBuilder.setRecorderFile(file);
- mediaRecorder.setStorageProperty(storagePropertyBuilder.build());
-
- AudioProperty.Builder audioPropertyBuilder = new AudioProperty.Builder();
- audioPropertyBuilder.setRecorderAudioEncoder(Recorder.AudioEncoder.AAC);
- mediaRecorder.setAudioProperty(audioPropertyBuilder.build());
- mediaRecorder.setVideoProperty(videoPropertyBuilder.build());
- mediaRecorder.prepare();
- }
-
- private void openCamera() {
- CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
- String[] cameraList = cameraKit.getCameraIds();
- String cameraId = "";
- for (String logicalCameraId : cameraList) {
- int faceType = cameraKit.getCameraInfo(logicalCameraId).getFacingType();
- switch (faceType) {
- case CameraInfo.FacingType.CAMERA_FACING_FRONT:
- if (isFrontCamera) {
- cameraId = logicalCameraId;
- }
- break;
- case CameraInfo.FacingType.CAMERA_FACING_BACK:
- if (!isFrontCamera) {
- cameraId = logicalCameraId;
- }
- break;
- case CameraInfo.FacingType.CAMERA_FACING_OTHERS:
- default:
- break;
- }
- }
- if (cameraId != null && !cameraId.isEmpty()) {
- CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
- cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
- }
- }
-
- private void switchCamera(Component component) {
- isFrontCamera = !isFrontCamera;
- if (cameraDevice != null) {
- cameraDevice.release();
- }
- updateComponentVisible(false);
- openCamera();
- }
-
- private class CameraStateCallbackImpl extends CameraStateCallback {
- CameraStateCallbackImpl() {
- }
-
- @Override
- public void onCreated(Camera camera) {
- if (surfaceProvider.getSurfaceOps().isPresent()) {
- previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
- }
- if (previewSurface == null) {
- HiLog.error(LABEL_LOG, "%{public}s", "Create camera filed, preview surface is null");
- return;
- }
- cameraConfigBuilder = camera.getCameraConfigBuilder();
- cameraConfigBuilder.addSurface(previewSurface);
- camera.configure(cameraConfigBuilder.build());
- cameraDevice = camera;
- updateComponentVisible(true);
- }
-
- @Override
- public void onConfigured(Camera camera) {
- FrameConfig.Builder frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
- frameConfigBuilder.addSurface(previewSurface);
- if (isRecording && recorderSurface != null) {
- frameConfigBuilder.addSurface(recorderSurface);
- }
- camera.triggerLoopingCapture(frameConfigBuilder.build());
- if (isRecording) {
- eventHandler.postTask(() -> mediaRecorder.start());
- }
- }
- }
-
- private void startRecord() {
- if (cameraDevice == null) {
- HiLog.error(LABEL_LOG, "%{public}s", "startRecord failed, parameters is illegal");
- return;
- }
- synchronized (lock) {
- initMediaRecorder();
- recorderSurface = mediaRecorder.getVideoSurface();
- cameraConfigBuilder = cameraDevice.getCameraConfigBuilder();
- try {
- cameraConfigBuilder.addSurface(previewSurface);
- if (recorderSurface != null) {
- cameraConfigBuilder.addSurface(recorderSurface);
- }
- cameraDevice.configure(cameraConfigBuilder.build());
- } catch (IllegalStateException | IllegalArgumentException e) {
- HiLog.error(LABEL_LOG, "%{public}s", "startRecord IllegalStateException | IllegalArgumentException");
- }
- }
- new ToastDialog(this).setText("Recording").show();
- }
-
- private void stopRecord() {
- synchronized (lock) {
- try {
- eventHandler.postTask(() -> mediaRecorder.stop());
- if (cameraDevice == null || cameraDevice.getCameraConfigBuilder() == null) {
- HiLog.error(LABEL_LOG, "%{public}s", "StopRecord cameraDevice or getCameraConfigBuilder is null");
- return;
- }
- cameraConfigBuilder = cameraDevice.getCameraConfigBuilder();
- cameraConfigBuilder.addSurface(previewSurface);
- cameraConfigBuilder.removeSurface(recorderSurface);
- cameraDevice.configure(cameraConfigBuilder.build());
- } catch (IllegalStateException | IllegalArgumentException exception) {
- HiLog.error(LABEL_LOG, "%{public}s", "stopRecord occur exception");
- }
- }
- new ToastDialog(this).setText("video saved").show();
- }
-
- private void updateComponentVisible(boolean isVisible) {
- buttonGroupLayout.setVisibility(isVisible ? Component.VISIBLE : Component.INVISIBLE);
- }
-
- private class SurfaceCallBack implements SurfaceOps.Callback {
- @Override
- public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
- if (callbackSurfaceOps != null) {
- callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
- }
- eventHandler.postTask(VideoRecordAbility.this::openCamera, 200);
- }
-
- @Override
- public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
- }
-
- @Override
- public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
- }
- }
-
- private void releaseCamera() {
- if (cameraDevice != null) {
- cameraDevice.release();
- }
- }
-
- @Override
- protected void onStop() {
- releaseCamera();
+ super.setMainRoute(VideoRecordSlice.class.getName());
}
}
diff --git a/media/Camera/entry/src/main/java/ohos/samples/camera/slice/TakePhotoSlice.java b/media/Camera/entry/src/main/java/ohos/samples/camera/slice/TakePhotoSlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..144b4e4ac41e1d27c21382f80c377a45e419c6ed
--- /dev/null
+++ b/media/Camera/entry/src/main/java/ohos/samples/camera/slice/TakePhotoSlice.java
@@ -0,0 +1,241 @@
+package ohos.samples.camera.slice;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.agp.components.Component;
+import ohos.agp.components.ComponentContainer;
+import ohos.agp.components.DirectionalLayout;
+import ohos.agp.components.Image;
+import ohos.agp.components.surfaceprovider.SurfaceProvider;
+import ohos.agp.graphics.Surface;
+import ohos.agp.graphics.SurfaceOps;
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.app.Context;
+import ohos.eventhandler.EventHandler;
+import ohos.eventhandler.EventRunner;
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+import ohos.media.camera.CameraKit;
+import ohos.media.camera.device.*;
+import ohos.media.image.ImageReceiver;
+import ohos.media.image.common.ImageFormat;
+import ohos.samples.camera.ResourceTable;
+import ohos.samples.camera.TakePhotoAbility;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PICTURE;
+import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;
+
+public class TakePhotoSlice extends AbilitySlice {
+ private static final String TAG = TakePhotoAbility.class.getSimpleName();
+
+ private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);
+
+ private static final int SCREEN_WIDTH = 1080;
+
+ private static final int SCREEN_HEIGHT = 1920;
+
+ private static final int IMAGE_RCV_CAPACITY = 9;
+
+ private SurfaceProvider surfaceProvider;
+
+ private ImageReceiver imageReceiver;
+
+ private boolean isFrontCamera;
+
+ private Surface previewSurface;
+
+ private Camera cameraDevice;
+
+ private Component buttonGroupLayout;
+
+ private ComponentContainer surfaceContainer;
+
+ private final EventHandler eventHandler = new EventHandler(EventRunner.current()) {
+ };
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_main_camera_slice);
+
+ initComponents();
+ initSurface();
+ }
+
+ private void initSurface() {
+ getWindow().setTransparent(true);
+ DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
+ ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
+ surfaceProvider = new SurfaceProvider(this);
+ surfaceProvider.setLayoutConfig(params);
+ surfaceProvider.pinToZTop(false);
+ if (surfaceProvider.getSurfaceOps().isPresent()) {
+ surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
+ }
+ surfaceContainer.addComponent(surfaceProvider);
+ }
+
+ private void initComponents() {
+ buttonGroupLayout = findComponentById(ResourceTable.Id_directionalLayout);
+ surfaceContainer = (ComponentContainer) findComponentById(ResourceTable.Id_surface_container);
+ Image takePhotoImage = (Image) findComponentById(ResourceTable.Id_tack_picture_btn);
+ Image exitImage = (Image) findComponentById(ResourceTable.Id_exit);
+ Image switchCameraImage = (Image) findComponentById(ResourceTable.Id_switch_camera_btn);
+ exitImage.setClickedListener(component -> terminateAbility());
+ takePhotoImage.setClickedListener(this::takeSingleCapture);
+ takePhotoImage.setLongClickedListener(this::takeMultiCapture);
+ switchCameraImage.setClickedListener(this::switchCamera);
+ }
+
+ private void openCamera() {
+ imageReceiver = ImageReceiver.create(SCREEN_WIDTH, SCREEN_HEIGHT, ImageFormat.JPEG, IMAGE_RCV_CAPACITY);
+ imageReceiver.setImageArrivalListener(this::saveImage);
+ CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
+ String[] cameraList = cameraKit.getCameraIds();
+ String cameraId = "";
+ for (String logicalCameraId : cameraList) {
+ int faceType = cameraKit.getCameraInfo(logicalCameraId).getFacingType();
+ switch (faceType) {
+ case CameraInfo.FacingType.CAMERA_FACING_FRONT:
+ if (isFrontCamera) {
+ cameraId = logicalCameraId;
+ }
+ break;
+ case CameraInfo.FacingType.CAMERA_FACING_BACK:
+ if (!isFrontCamera) {
+ cameraId = logicalCameraId;
+ }
+ break;
+ case CameraInfo.FacingType.CAMERA_FACING_OTHERS:
+ default:
+ break;
+ }
+ }
+ if (cameraId != null && !cameraId.isEmpty()) {
+ CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
+ cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
+ }
+ }
+
+ private void saveImage(ImageReceiver receiver) {
+ File saveFile = new File(getFilesDir(), "IMG_" + System.currentTimeMillis() + ".jpg");
+ ohos.media.image.Image image = receiver.readNextImage();
+ ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);
+ byte[] bytes = new byte[component.remaining()];
+ component.read(bytes);
+ try (FileOutputStream output = new FileOutputStream(saveFile)) {
+ output.write(bytes);
+ output.flush();
+ String msg = "Take photo succeed";
+ showTips(this, msg);
+ } catch (IOException e) {
+ HiLog.error(LABEL_LOG, "%{public}s", "saveImage IOException");
+ }
+ }
+
+ private void takeSingleCapture(Component component) {
+ if (cameraDevice == null || imageReceiver == null) {
+ return;
+ }
+ FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
+ framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
+ FrameConfig pictureFrameConfig = framePictureConfigBuilder.build();
+ cameraDevice.triggerSingleCapture(pictureFrameConfig);
+ }
+
+ private void takeMultiCapture(Component component) {
+ FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
+ framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
+ List frameConfigs = new ArrayList<>();
+ FrameConfig firstFrameConfig = framePictureConfigBuilder.build();
+ frameConfigs.add(firstFrameConfig);
+ FrameConfig secondFrameConfig = framePictureConfigBuilder.build();
+ frameConfigs.add(secondFrameConfig);
+ cameraDevice.triggerMultiCapture(frameConfigs);
+ }
+
+ private void switchCamera(Component component) {
+ isFrontCamera = !isFrontCamera;
+ if (cameraDevice != null) {
+ cameraDevice.release();
+ }
+ updateComponentVisible(false);
+ openCamera();
+ }
+
+ private class CameraStateCallbackImpl extends CameraStateCallback {
+ CameraStateCallbackImpl() {
+ }
+
+ @Override
+ public void onCreated(Camera camera) {
+ if (surfaceProvider.getSurfaceOps().isPresent()) {
+ previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
+ }
+ if (previewSurface == null) {
+ HiLog.error(LABEL_LOG, "%{public}s", "Create camera filed, preview surface is null");
+ return;
+ }
+ CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();
+ cameraConfigBuilder.addSurface(previewSurface);
+ cameraConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
+ camera.configure(cameraConfigBuilder.build());
+ cameraDevice = camera;
+ updateComponentVisible(true);
+ }
+
+ @Override
+ public void onConfigured(Camera camera) {
+ FrameConfig.Builder framePreviewConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
+ framePreviewConfigBuilder.addSurface(previewSurface);
+ camera.triggerLoopingCapture(framePreviewConfigBuilder.build());
+ }
+ }
+
+ private void updateComponentVisible(boolean isVisible) {
+ buttonGroupLayout.setVisibility(isVisible ? Component.VISIBLE : Component.INVISIBLE);
+ }
+
+ private class SurfaceCallBack implements SurfaceOps.Callback {
+ @Override
+ public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
+ if (callbackSurfaceOps != null) {
+ callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
+ }
+ eventHandler.postTask(TakePhotoSlice.this::openCamera, 200);
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
+ }
+ }
+
+ private void showTips(Context context, String msg) {
+ getUITaskDispatcher().asyncDispatch(() -> new ToastDialog(context).setText(msg).show());
+ }
+
+ private void releaseCamera() {
+ if (cameraDevice != null) {
+ cameraDevice.release();
+ }
+
+ if (imageReceiver != null) {
+ imageReceiver.release();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ releaseCamera();
+ }
+}
diff --git a/media/Camera/entry/src/main/java/ohos/samples/camera/slice/VideoRecordSlice.java b/media/Camera/entry/src/main/java/ohos/samples/camera/slice/VideoRecordSlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..2048c8adf70c418ca1cefe6febdfab66d3364258
--- /dev/null
+++ b/media/Camera/entry/src/main/java/ohos/samples/camera/slice/VideoRecordSlice.java
@@ -0,0 +1,286 @@
+package ohos.samples.camera.slice;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.agp.components.Component;
+import ohos.agp.components.ComponentContainer;
+import ohos.agp.components.DirectionalLayout;
+import ohos.agp.components.Image;
+import ohos.agp.components.surfaceprovider.SurfaceProvider;
+import ohos.agp.graphics.Surface;
+import ohos.agp.graphics.SurfaceOps;
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.eventhandler.EventHandler;
+import ohos.eventhandler.EventRunner;
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+import ohos.media.camera.CameraKit;
+import ohos.media.camera.device.*;
+import ohos.media.common.AudioProperty;
+import ohos.media.common.Source;
+import ohos.media.common.StorageProperty;
+import ohos.media.common.VideoProperty;
+import ohos.media.recorder.Recorder;
+import ohos.multimodalinput.event.TouchEvent;
+import ohos.samples.camera.ResourceTable;
+import ohos.samples.camera.VideoRecordAbility;
+
+import java.io.File;
+
+import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;
+
+public class VideoRecordSlice extends AbilitySlice {
+ private static final String TAG = VideoRecordAbility.class.getSimpleName();
+
+ private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);
+
+ private static final int SCREEN_WIDTH = 1080;
+
+ private static final int SCREEN_HEIGHT = 1920;
+
+ private SurfaceProvider surfaceProvider;
+
+ private Surface recorderSurface;
+
+ private Surface previewSurface;
+
+ private boolean isFrontCamera;
+
+ private Camera cameraDevice;
+
+ private Component buttonGroupLayout;
+
+ private Recorder mediaRecorder;
+
+ private ComponentContainer surfaceContainer;
+
+ private CameraConfig.Builder cameraConfigBuilder;
+
+ private boolean isRecording;
+
+ private final Object lock = new Object();
+
+ private final EventHandler eventHandler = new EventHandler(EventRunner.current()) {
+ };
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_main_camera_slice);
+
+ initComponents();
+ initSurface();
+ }
+
+ private void initSurface() {
+ getWindow().setTransparent(true);
+ DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
+ ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
+ surfaceProvider = new SurfaceProvider(this);
+ surfaceProvider.setLayoutConfig(params);
+ surfaceProvider.pinToZTop(false);
+ if (surfaceProvider.getSurfaceOps().isPresent()) {
+ surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
+ }
+ surfaceContainer.addComponent(surfaceProvider);
+ }
+
+ private void initComponents() {
+ buttonGroupLayout = findComponentById(ResourceTable.Id_directionalLayout);
+ surfaceContainer = (ComponentContainer) findComponentById(ResourceTable.Id_surface_container);
+ Image videoRecord = (Image) findComponentById(ResourceTable.Id_tack_picture_btn);
+ Image exitImage = (Image) findComponentById(ResourceTable.Id_exit);
+ Image switchCameraImage = (Image) findComponentById(ResourceTable.Id_switch_camera_btn);
+ exitImage.setClickedListener(component -> terminateAbility());
+ switchCameraImage.setClickedListener(this::switchCamera);
+
+ videoRecord.setLongClickedListener(component -> {
+ startRecord();
+ isRecording = true;
+ videoRecord.setPixelMap(ResourceTable.Media_ic_camera_video_press);
+ });
+
+ videoRecord.setTouchEventListener((component, touchEvent) -> {
+ if (touchEvent != null && touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP && isRecording) {
+ stopRecord();
+ isRecording = false;
+ videoRecord.setPixelMap(ResourceTable.Media_ic_camera_video_ready);
+ }
+ return true;
+ });
+ }
+
+ private void initMediaRecorder() {
+ mediaRecorder = new Recorder();
+ VideoProperty.Builder videoPropertyBuilder = new VideoProperty.Builder();
+ videoPropertyBuilder.setRecorderBitRate(10000000);
+ videoPropertyBuilder.setRecorderDegrees(90);
+ videoPropertyBuilder.setRecorderFps(30);
+ videoPropertyBuilder.setRecorderHeight(Math.min(1440, 720));
+ videoPropertyBuilder.setRecorderWidth(Math.max(1440, 720));
+ videoPropertyBuilder.setRecorderVideoEncoder(Recorder.VideoEncoder.H264);
+ videoPropertyBuilder.setRecorderRate(30);
+
+ Source source = new Source();
+ source.setRecorderAudioSource(Recorder.AudioSource.MIC);
+ source.setRecorderVideoSource(Recorder.VideoSource.SURFACE);
+ mediaRecorder.setSource(source);
+ mediaRecorder.setOutputFormat(Recorder.OutputFormat.MPEG_4);
+ File file = new File(getFilesDir(), "VID_" + System.currentTimeMillis() + ".mp4");
+ StorageProperty.Builder storagePropertyBuilder = new StorageProperty.Builder();
+ storagePropertyBuilder.setRecorderFile(file);
+ mediaRecorder.setStorageProperty(storagePropertyBuilder.build());
+
+ AudioProperty.Builder audioPropertyBuilder = new AudioProperty.Builder();
+ audioPropertyBuilder.setRecorderAudioEncoder(Recorder.AudioEncoder.AAC);
+ mediaRecorder.setAudioProperty(audioPropertyBuilder.build());
+ mediaRecorder.setVideoProperty(videoPropertyBuilder.build());
+ mediaRecorder.prepare();
+ }
+
+ private void openCamera() {
+ CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
+ String[] cameraList = cameraKit.getCameraIds();
+ String cameraId = "";
+ for (String logicalCameraId : cameraList) {
+ int faceType = cameraKit.getCameraInfo(logicalCameraId).getFacingType();
+ switch (faceType) {
+ case CameraInfo.FacingType.CAMERA_FACING_FRONT:
+ if (isFrontCamera) {
+ cameraId = logicalCameraId;
+ }
+ break;
+ case CameraInfo.FacingType.CAMERA_FACING_BACK:
+ if (!isFrontCamera) {
+ cameraId = logicalCameraId;
+ }
+ break;
+ case CameraInfo.FacingType.CAMERA_FACING_OTHERS:
+ default:
+ break;
+ }
+ }
+ if (cameraId != null && !cameraId.isEmpty()) {
+ CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
+ cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
+ }
+ }
+
+ private void switchCamera(Component component) {
+ isFrontCamera = !isFrontCamera;
+ if (cameraDevice != null) {
+ cameraDevice.release();
+ }
+ updateComponentVisible(false);
+ openCamera();
+ }
+
+ private class CameraStateCallbackImpl extends CameraStateCallback {
+ CameraStateCallbackImpl() {
+ }
+
+ @Override
+ public void onCreated(Camera camera) {
+ if (surfaceProvider.getSurfaceOps().isPresent()) {
+ previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
+ }
+ if (previewSurface == null) {
+ HiLog.error(LABEL_LOG, "%{public}s", "Create camera filed, preview surface is null");
+ return;
+ }
+ cameraConfigBuilder = camera.getCameraConfigBuilder();
+ cameraConfigBuilder.addSurface(previewSurface);
+ camera.configure(cameraConfigBuilder.build());
+ cameraDevice = camera;
+ updateComponentVisible(true);
+ }
+
+ @Override
+ public void onConfigured(Camera camera) {
+ FrameConfig.Builder frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
+ frameConfigBuilder.addSurface(previewSurface);
+ if (isRecording && recorderSurface != null) {
+ frameConfigBuilder.addSurface(recorderSurface);
+ }
+ camera.triggerLoopingCapture(frameConfigBuilder.build());
+ if (isRecording) {
+ eventHandler.postTask(() -> mediaRecorder.start());
+ }
+ }
+ }
+
+ private void startRecord() {
+ if (cameraDevice == null) {
+ HiLog.error(LABEL_LOG, "%{public}s", "startRecord failed, parameters is illegal");
+ return;
+ }
+ synchronized (lock) {
+ initMediaRecorder();
+ recorderSurface = mediaRecorder.getVideoSurface();
+ cameraConfigBuilder = cameraDevice.getCameraConfigBuilder();
+ try {
+ cameraConfigBuilder.addSurface(previewSurface);
+ if (recorderSurface != null) {
+ cameraConfigBuilder.addSurface(recorderSurface);
+ }
+ cameraDevice.configure(cameraConfigBuilder.build());
+ } catch (IllegalStateException | IllegalArgumentException e) {
+ HiLog.error(LABEL_LOG, "%{public}s", "startRecord IllegalStateException | IllegalArgumentException");
+ }
+ }
+ new ToastDialog(this).setText("Recording").show();
+ }
+
+ private void stopRecord() {
+ synchronized (lock) {
+ try {
+ eventHandler.postTask(() -> mediaRecorder.stop());
+ if (cameraDevice == null || cameraDevice.getCameraConfigBuilder() == null) {
+ HiLog.error(LABEL_LOG, "%{public}s", "StopRecord cameraDevice or getCameraConfigBuilder is null");
+ return;
+ }
+ cameraConfigBuilder = cameraDevice.getCameraConfigBuilder();
+ cameraConfigBuilder.addSurface(previewSurface);
+ cameraConfigBuilder.removeSurface(recorderSurface);
+ cameraDevice.configure(cameraConfigBuilder.build());
+ } catch (IllegalStateException | IllegalArgumentException exception) {
+ HiLog.error(LABEL_LOG, "%{public}s", "stopRecord occur exception");
+ }
+ }
+ new ToastDialog(this).setText("video saved").show();
+ }
+
+ private void updateComponentVisible(boolean isVisible) {
+ buttonGroupLayout.setVisibility(isVisible ? Component.VISIBLE : Component.INVISIBLE);
+ }
+
+ private class SurfaceCallBack implements SurfaceOps.Callback {
+ @Override
+ public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
+ if (callbackSurfaceOps != null) {
+ callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
+ }
+ eventHandler.postTask(VideoRecordSlice.this::openCamera, 200);
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
+ }
+ }
+
+ private void releaseCamera() {
+ if (cameraDevice != null) {
+ cameraDevice.release();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ releaseCamera();
+ }
+
+}