HUAWEI Camera Engine provides a set of EMUI-compatible camera capability APIs for you to quickly integrate the proprietary capabilities of Huawei Camera to your app and extend their shooting functions, delivering a better shooting experience for users.

Super slow-mo is one of the multiple camera modes provided by HUAWEI Camera Engine. You will be able to:

What You Will Create

In this codelab, you will use Camera Engine to create an Android camera app that provides the Super slow-mo mode of Huawei Camera to record super slow-motion videos of objects moving at high speeds.

Super slow-mo

What You Will Learn

What You Will Need

Hardware Requirements

Software Requirements

  1. Add the following permissions to the Manifest file of your project:
    <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  2. Dynamically request permissions:
    private static final String[] PERMISSIONS_ARRAY = new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}; private static List<String> permissionsList = new ArrayList<>(PERMISSIONS_ARRAY.length); /** * Dynamically request the WRITE_EXTERNAL_STORAGE CAMERA RECORD_AUDIO permission. * * @param activity App activity. */ public static void requestPermission(final Activity activity) { for (String permission : PERMISSIONS_ARRAY) { if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(permission); } } ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]),REQUEST_CODE_ASK_PERMISSIONS); }
  1. Create an Android project and open the Android Studio project-level build.gradle file.
  2. Go to allprojects > repositories and configure the maven repository address for Camera Engine.
    allprojects { repositories { google() jcenter() maven {url 'https://developer.huawei.com/repo/'} } }
  3. Go to buildscript > repositories and add configurations.
    buildscript { repositories { maven {url 'https://developer.huawei.com/repo/'} google() jcenter() } }
  4. Open the build.gradle file in the app directory.
  5. Configure compile dependencies in dependencies.
    dependencies { implementation group: 'com.huawei.multimedia', name: 'camerakit', version: '1.1.3', ext: 'aar' }

Step 1 Create a mode: Obtain the CameraKit instance and create the Super slow-mo mode.

/** Super Slow-mo mode*/ private static final @Mode.Type int CURRENT_MODE_TYPE = Mode.Type.SUPER_SLOW_MOTION; private CameraKit mCameraKit; private void createMode() { mCameraKit = CameraKit.getInstance(getApplicationContext()); if (mCameraKit == null) { Log.e(TAG, "This device does not support CameraKit!"); } // Query the camera ID list. String[] cameraLists = mCameraKit.getCameraIdList(); if ((cameraLists != null) && (cameraLists.length > 0)) { mCameraId = cameraLists[0]; Log.i(TAG, "Try to use camera with id " + cameraLists[0]); // Query the modes supported by the current device. int[] modes = mCameraKit.getSupportedModes(cameraLists[0]); if (!Arrays.stream(modes).anyMatch((i) -> i == CURRENT_MODE_TYPE)) { Log.w(TAG, "Current mode is not supported in this device!"); return; } mCameraKit.createMode(mCameraId, CURRENT_MODE_TYPE, mModeStateCallback, mModeCbHandler); } }

Step 2 Configure the mode: Configure the status callback of the mode, data callback, handler for processing the callback, and parameters such as the preview and recording resolution.

After the onCreated function of mModeStateCallback is called back, the Super slow-mo mode instance can be obtained from the input parameter.

/** Obtain the mode object from the onCreated callback, and initialize ModeConfig.Builder by using the behavior status callback, data callback, and the corresponding thread as input parameters. Configure the preview surface and recording size, and call the configure method to set the configuration items to mMode to activate the mode.*/ private void configureMode() { try { mPrepareModeConfigLock.acquire(); mModeCharacteristics = mCameraKit.getModeCharacteristics(mCameraId, CURRENT_MODE_TYPE); List<Size> previewSizes = mModeCharacteristics.getSupportedPreviewSizes(SurfaceTexture.class); Map<Integer, List<Size>> recordSizes = mModeCharacteristics.getSupportedVideoSizes(MediaRecorder.class); // Obtain the recording frame rate and resolution. The two configuration items must be set in pairs based on the map returned by the modeCharacteristics.getSupportedVideoSizes(). if (recordSizes.containsKey(Metadata.FpsRange.HW_FPS_960)) { mRecordFps = Metadata.FpsRange.HW_FPS_960; mRecordSize = recordSizes.get(Metadata.FpsRange.HW_FPS_960).get(0); } else { Log.e(TAG, "prepareConfig: Internal error"); return; } Log.d(TAG, "prepareConfig: recordFps = " + mRecordFps + ", recordSize = " + mRecordSize); // The video resolution must be the same as the preview resolution. if (!previewSizes.contains(mRecordSize)) { Log.e(TAG, "preparePreviewSurface: the previewSize and recordSize should be the same, Internal error!"); return; } SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); if (surfaceTexture != null) { surfaceTexture.setDefaultBufferSize(mRecordSize.getWidth(), mRecordSize.getHeight()); mPreviewSurface = new Surface(surfaceTexture); } mModeConfigBuilder = mCurrentMode.getModeConfigBuilder(); mModeConfigBuilder.setStateCallback(mActionStateCallback, mStatusCbHandler); mModeConfigBuilder.setVideoFps(mRecordFps); mModeConfigBuilder.addVideoSize(mRecordSize); mModeConfigBuilder.addPreviewSurface(mPreviewSurface); mCurrentMode.configure(); } catch (InterruptedException e) { Log.e(TAG, "prepareModeConfig fail " + e.getMessage()); } finally { mPrepareModeConfigLock.release(); } }

Call ModeConfig.Builder to configure the state callback of the mode and execute the handler where the callback is located. From the status callback, you can obtain various status information during the Super slow-mo recording process, such as a returned unknown error, or that the bottom layer is ready, or that the recording starts, ends, or is saved. You can also configure the preview surface and shooting resolution by calling ModeConfig.Builder.

Step 3 Perform operations in the mode.

  1. Enable the preview.

    /* After the onConfigured callback is received, the mode is successfully configured and enabled. In this case, call startPreview to enable the preview function. */ private void startPreview() { mCurrentMode.startPreview(); }
  2. Set the parameters.

    /* You can call ModeCharacteristics#getSupportedParameters to query the parameters supported in the current mode (for example, Super slow-mo mode supports zooming, flashlight, and automatic focus), call ModeCharacteristics#getParameterRange to query the value range of the parameters, and call Mode#setParameter to set the shooting effects. */ /* Set the flash.*/ int[] flashDatas = mMode.getModeCharacteristics().getSupportedFlashMode(); mCurrentMode.setFlashMode(1); /* You can design an entry, such as a button, which calls startRecording to start recording. */ private void startRecord() { mRecordOrStop.setEnabled(false); mCurrentMode.startRecording(getExternalFilesDir(null)); }

Step 4 Implement the callback.

/* Use the action status callback as an example to obtain the callback of the execution status result, for example, preparing for, starting, ending, and saving Super slow-mo recording. */ private ActionStateCallback mActionStateCallback = new ActionStateCallback() { @Override public void onRecording(Mode mode, int state, RecordingResult result) { switch (state) { // An IO error occurs. case RecordingResult.State.ERROR_FILE_IO: // An unknown error occurs. case RecordingResult.State.ERROR_UNKNOWN: throw new IllegalStateException("error!"); //The bottom-layer initialization is not ready. case RecordingResult.State.ERROR_RECORDING_NOT_READY: runOnUiThread( () -> Toast.makeText(SuperSlowDemoActivity.this, R.string.status_not_ready, Toast.LENGTH_SHORT).show()); break; // The bottom layer is ready. case RecordingResult.State.RECORDING_READY: runOnUiThread(() -> mRecordOrStop.setEnabled(true)); break; // Recording is started. This parameter is returned only in automatic mode. case RecordingResult.State.RECORDING_STARTED: runOnUiThread(() -> { mRecordOrStop.setEnabled(false); Toast.makeText(SuperSlowDemoActivity.this, R.string.status_started, Toast.LENGTH_SHORT).show(); }); break; // Recording is stopped. case RecordingResult.State.RECORDING_STOPPED: runOnUiThread(() -> { Toast.makeText(SuperSlowDemoActivity.this, R.string.status_stopped, Toast.LENGTH_SHORT).show(); }); break; // Recording is complete. case RecordingResult.State.RECORDING_COMPLETED: runOnUiThread( () -> Toast.makeText(SuperSlowDemoActivity.this, R.string.status_completed, Toast.LENGTH_SHORT).show()); break; // The recorded file is saved. case RecordingResult.State.RECORDING_FILE_SAVED: runOnUiThread(() -> { Toast.makeText(SuperSlowDemoActivity.this, mSaveFilePath + " saved", Toast.LENGTH_SHORT).show(); mRecordOrStop.setText(R.string.button_record); mRecordOrStop.setEnabled(true); }); break; default: break; } } };

Step 5 Release the mode.

/* The mode needs to be released when the app is closed or switched to the background. */ @Override protected void onPause() { if (mBackgroundHandler != null) { mBackgroundHandler.post(new Runnable() { @Override public void run() { if (mCurrentMode!= null) { mCurrentMode.release(); mCurrentMode = null; } } }); } super.onPause(); }

You have successfully completed this codelab and learned how to:

For more information about Camera Engine, visit our official website:


Code copied