Recording is cyclic frame capture and one of the most important features of a camera app. For recording smoothness, refer to step 7 in the development procedure of Photo Capture (C/C++) to set the resolution, flash, focal length, photo quality, rotation angle, and other parameters.
For detailed API descriptions, refer to OH_Camera.
Import the NDK, which provides camera-related properties and methods.
#include <cstdint>
#include <native_buffer/buffer_common.h>
#include <unistd.h>
#include <string>
#include <thread>
#include <cstdio>
#include <fcntl.h>
#include <map>
#include <vector>
#include <native_buffer/native_buffer.h>
#include "iostream"
#include "mutex"
#include "hilog/log.h"
#include "ohcamera/camera.h"
#include "ohcamera/camera_input.h"
#include "ohcamera/capture_session.h"
#include "ohcamera/photo_output.h"
#include "ohcamera/preview_output.h"
#include "ohcamera/video_output.h"
#include "napi/native_api.h"
#include "ohcamera/camera_manager.h"
#include <window_manager/oh_display_info.h>
#include <window_manager/oh_display_manager.h>
namespace OHOS_CAMERA_SAMPLE {
class NDKCamera {
public:
struct CameraBuildingConfig {
char *str;
uint32_t focusMode;
uint32_t cameraDeviceIndex;
bool isVideo;
bool isHdr;
char *videoId;
};
~NDKCamera();
explicit NDKCamera(CameraBuildingConfig config);
// ...
};
} // namespace OHOS_CAMERA_SAMPLE Link the dynamic library in the CMake script.
target_link_libraries(entry PUBLIC
libace_napi.z.so
libohcamera.so
libhilog_ndk.z.so
) Obtain the surface ID.
The system-provided OH_AVRecorder_Create() API creates an AVRecorder instance for recording, and the OH_AVRecorder_GetInputSurface() method of this instance obtains the surface ID.
Create a video output stream.
Based on the surface ID passed in, call OH_CameraManager_GetSupportedCameraOutputCapability to obtain Camera_OutputCapability. From there, you can access videoProfiles to obtain the video output streams supported by the device. Then, define video recording parameters and use OH_CameraManager_CreateVideoOutput to create a video output stream.
The aspect ratio of the preview stream must be consistent with that of the recording output stream. For example, if the aspect ratio in the sample code is 640:480 = 4:3, the resolution in the preview stream must also have an aspect ratio of 4:3. Available resolutions include 640:480, 960:720, 1440:1080, and so on.
Before setting the resolution aspect ratio of the preview output stream, query the configurable width and height ranges supported for video frames through OH_AVRecorder_Profile.
Camera_ErrorCode NDKCamera::CreateVideoOutput(char *videoId)
{
if (videoProfile_ == nullptr) {
OH_LOG_ERROR(LOG_APP, "Get videoProfiles failed.");
return CAMERA_INVALID_ARGUMENT;
}
ret_ = OH_CameraManager_CreateVideoOutput(cameraManager_, videoProfile_, videoId, &videoOutput_);
OH_LOG_INFO(LOG_APP, " create video width: %{public}d, height: %{public}d, format: %{public}d",
videoProfile_->size.width, videoProfile_->size.height, videoProfile_->format);
if (videoId == nullptr || videoOutput_ == nullptr || ret_ != CAMERA_OK) {
OH_LOG_ERROR(LOG_APP, "CreateVideoOutput failed.");
return CAMERA_INVALID_ARGUMENT;
}
VideoOutputRegisterCallback();
return ret_;
} Start video recording.
Call OH_VideoOutput_Start() to start the video output stream.
Camera_ErrorCode NDKCamera::VideoOutputStart(void)
{
OH_LOG_INFO(LOG_APP, "VideoOutputStart begin.");
Camera_ErrorCode ret = OH_VideoOutput_Start(videoOutput_);
if (ret == CAMERA_OK) {
OH_LOG_INFO(LOG_APP, "OH_VideoOutput_Start success.");
} else {
OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Start failed. %d ", ret);
}
return ret;
} Stop video recording.
Call OH_VideoOutput_Stop() to stop the video output stream.
Camera_ErrorCode NDKCamera::VideoOutputStop(void)
{
OH_LOG_INFO(LOG_APP, "enter VideoOutputStop.");
ret_ = OH_VideoOutput_Stop(videoOutput_);
if (ret_ != CAMERA_OK) {
OH_LOG_ERROR(LOG_APP, "VideoOutputStop failed.");
return CAMERA_INVALID_ARGUMENT;
}
return ret_;
} During camera application development, you can listen for the status of the video output stream, including recording start, recording end, and video output errors.
Register the 'frameStart' event to listen for recording start events. This event can be registered when a VideoOutput instance is created and is triggered when the bottom layer starts exposure for recording for the first time. Video recording starts as long as the event is triggered.
void VideoOutputOnFrameStart(Camera_VideoOutput *videoOutput)
{
OH_LOG_INFO(LOG_APP, "VideoOutputOnFrameStart");
} Register the 'frameEnd' event to listen for recording end events. This event can be registered when a VideoOutput instance is created and is triggered when the last frame of recording ends. Video recording ends as long as a result is returned.
void VideoOutputOnFrameEnd(Camera_VideoOutput *videoOutput, int32_t frameCount)
{
OH_LOG_INFO(LOG_APP, "VideoOutput frameCount = %{public}d", frameCount);
} Register the 'error' event to listen for video output errors. The callback function returns an error code when a video output API is incorrectly used. For details about the error code types, see Camera_ErrorCode.
void VideoOutputOnError(Camera_VideoOutput *videoOutput, Camera_ErrorCode errorCode)
{
OH_LOG_ERROR(LOG_APP, "VideoOutput errorCode = %{public}d", errorCode);
} VideoOutput_Callbacks *NDKCamera::GetVideoOutputListener(void)
{
static VideoOutput_Callbacks videoOutputListener = {
.onFrameStart = VideoOutputOnFrameStart,
.onFrameEnd = VideoOutputOnFrameEnd,
.onError = VideoOutputOnError
};
return &videoOutputListener;
}
Camera_ErrorCode NDKCamera::VideoOutputRegisterCallback(void)
{
ret_ = OH_VideoOutput_RegisterCallback(videoOutput_, GetVideoOutputListener());
if (ret_ != CAMERA_OK) {
OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_RegisterCallback failed.");
}
return ret_;
}