1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "dcamera_client_demo.h"
17
18using namespace OHOS;
19using namespace OHOS::Camera;
20using namespace OHOS::CameraStandard;
21using namespace OHOS::DistributedHardware;
22
23namespace OHOS {
24namespace DistributedHardware {
25constexpr double LOCATION_LATITUDE = 22.306;
26constexpr double LOCATION_LONGITUDE = 52.12;
27constexpr double LOCATION_ALTITUDE = 2.365;
28#ifdef DCAMERA_COMMON
29    constexpr int32_t PHOTO_WIDTH = 1280;
30    constexpr int32_t PHOTO_HEIGTH = 960;
31#else
32    constexpr int32_t PHOTO_WIDTH = 1920;
33    constexpr int32_t PHOTO_HEIGTH = 1080;
34#endif
35constexpr int32_t PREVIEW_WIDTH = 640;
36constexpr int32_t PREVIEW_HEIGTH = 480;
37constexpr int32_t VIDEO_WIDTH = 640;
38constexpr int32_t VIDEO_HEIGTH = 480;
39
40static sptr<CameraDevice> g_cameraInfo = nullptr;
41static sptr<CameraManager> g_cameraManager = nullptr;
42static sptr<CaptureInput> g_cameraInput = nullptr;
43static sptr<CaptureOutput> g_photoOutput = nullptr;
44static sptr<CaptureOutput> g_previewOutput = nullptr;
45static sptr<CaptureOutput> g_videoOutput = nullptr;
46static sptr<CaptureSession> g_captureSession = nullptr;
47static std::shared_ptr<DCameraCaptureInfo> g_photoInfo = nullptr;
48static std::shared_ptr<DCameraCaptureInfo> g_previewInfo = nullptr;
49static std::shared_ptr<DCameraCaptureInfo> g_videoInfo = nullptr;
50
51#ifdef DCAMERA_COMMON
52    constexpr int32_t PHOTO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_JPEG;
53    constexpr int32_t PREVIEW_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888;
54    constexpr int32_t VIDEO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888;
55#else
56    constexpr int32_t PHOTO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_JPEG;
57    constexpr int32_t PREVIEW_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_YCRCB_420_SP;
58    constexpr int32_t VIDEO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_YCRCB_420_SP;
59#endif
60
61int32_t InitCameraStandard(CameraPosition position)
62{
63    g_cameraManager = CameraManager::GetInstance();
64    g_cameraManager->SetCallback(std::make_shared<DemoDCameraManagerCallback>());
65
66    int rv = g_cameraManager->CreateCaptureSession(&g_captureSession);
67    if (rv != DCAMERA_OK) {
68        DHLOGE("InitCameraStandard create captureSession failed, rv: %{public}d", rv);
69        return rv;
70    }
71    std::shared_ptr<DemoDCameraSessionCallback> sessionCallback = std::make_shared<DemoDCameraSessionCallback>();
72    g_captureSession->SetCallback(sessionCallback);
73    g_captureSession->SetFocusCallback(sessionCallback);
74
75    std::vector<sptr<CameraDevice>> cameraObjList = g_cameraManager->GetSupportedCameras();
76    for (auto info : cameraObjList) {
77        DHLOGI("Camera: %{public}s, position: %{public}d, camera type: %{public}d, connection type: %{public}d",
78            GetAnonyString(info->GetID()).c_str(),
79            info->GetPosition(), info->GetCameraType(), info->GetConnectionType());
80        // CAMERA_POSITION_BACK or CAMERA_POSITION_FRONT
81        if ((info->GetPosition() == position) &&
82            (info->GetConnectionType() == ConnectionType::CAMERA_CONNECTION_REMOTE)) {
83            g_cameraInfo = info;
84            break;
85        }
86    }
87
88    if (g_cameraInfo == nullptr) {
89        DHLOGE("Distributed Camera Demo: have no remote camera");
90        return DCAMERA_BAD_VALUE;
91    }
92
93    rv = g_cameraManager->CreateCameraInput(g_cameraInfo, &((sptr<CameraInput> &)g_cameraInput));
94    if (rv != DCAMERA_OK) {
95        DHLOGE("InitCameraStandard create cameraInput failed, rv: %{public}d", rv);
96        return rv;
97    }
98    int32_t ret = ((sptr<CameraInput> &)g_cameraInput)->Open();
99    if (ret != DCAMERA_OK) {
100        DHLOGE("InitCameraStandard g_cameraInput Open failed, ret: %{public}d", ret);
101        return ret;
102    }
103    std::shared_ptr<DemoDCameraInputCallback> inputCallback = std::make_shared<DemoDCameraInputCallback>();
104    ((sptr<CameraInput> &)g_cameraInput)->SetErrorCallback(inputCallback);
105    return DCAMERA_OK;
106}
107
108void InitCaptureInfo(int32_t width, int32_t height)
109{
110    g_photoInfo = std::make_shared<DCameraCaptureInfo>();
111    g_photoInfo->width_ = PHOTO_WIDTH;
112    g_photoInfo->height_ = PHOTO_HEIGTH;
113    g_photoInfo->format_ = PHOTO_FORMAT;
114
115    g_previewInfo = std::make_shared<DCameraCaptureInfo>();
116    if (width == 0 && height == 0) {
117        g_previewInfo->width_ = PREVIEW_WIDTH;
118        g_previewInfo->height_ = PREVIEW_HEIGTH;
119    } else {
120        g_previewInfo->width_ = width;
121        g_previewInfo->height_ = height;
122    }
123    g_previewInfo->format_ = PREVIEW_FORMAT;
124
125    g_videoInfo = std::make_shared<DCameraCaptureInfo>();
126    g_videoInfo->width_ = VIDEO_WIDTH;
127    g_videoInfo->height_ = VIDEO_HEIGTH;
128    g_videoInfo->format_ = VIDEO_FORMAT;
129}
130
131CameraFormat ConvertToCameraFormat(int32_t format)
132{
133    CameraFormat ret = CameraFormat::CAMERA_FORMAT_INVALID;
134    DCameraFormat df = static_cast<DCameraFormat>(format);
135    switch (df) {
136        case DCameraFormat::OHOS_CAMERA_FORMAT_RGBA_8888:
137            ret = CameraFormat::CAMERA_FORMAT_RGBA_8888;
138            break;
139        case DCameraFormat::OHOS_CAMERA_FORMAT_YCBCR_420_888:
140            ret = CameraFormat::CAMERA_FORMAT_YCBCR_420_888;
141            break;
142        case DCameraFormat::OHOS_CAMERA_FORMAT_YCRCB_420_SP:
143            ret = CameraFormat::CAMERA_FORMAT_YUV_420_SP;
144            break;
145        case DCameraFormat::OHOS_CAMERA_FORMAT_JPEG:
146            ret = CameraFormat::CAMERA_FORMAT_JPEG;
147            break;
148        default:
149            break;
150    }
151    return ret;
152}
153
154void InitPhotoOutput(void)
155{
156    DHLOGI("Distributed Camera Demo: Create PhotoOutput, width = %{public}d, height = %{public}d, format = %{public}d",
157        g_photoInfo->width_, g_photoInfo->height_, g_photoInfo->format_);
158    sptr<IConsumerSurface> photoSurface = IConsumerSurface::Create();
159    sptr<IBufferConsumerListener> photoListener = new DemoDCameraPhotoSurfaceListener(photoSurface);
160    photoSurface->RegisterConsumerListener(photoListener);
161    CameraFormat photoFormat = ConvertToCameraFormat(g_photoInfo->format_);
162    Size photoSize = {g_photoInfo->width_, g_photoInfo->height_};
163    Profile photoProfile(photoFormat, photoSize);
164    sptr<IBufferProducer> photoProducer = photoSurface->GetProducer();
165    int rv = g_cameraManager->CreatePhotoOutput(photoProfile, photoProducer, &((sptr<PhotoOutput> &)g_photoOutput));
166    if (rv != DCAMERA_OK) {
167        DHLOGE("InitPhotoOutput create photoOutput failed, rv: %{public}d", rv);
168        return;
169    }
170    ((sptr<PhotoOutput> &)g_photoOutput)->SetCallback(std::make_shared<DemoDCameraPhotoCallback>());
171}
172
173void InitPreviewOutput(void)
174{
175    DHLOGI("Distributed Camera Demo: Create PreviewOutput, width = %{public}d, height = %{public}d, format = "
176        "%{public}d", g_previewInfo->width_, g_previewInfo->height_, g_previewInfo->format_);
177    sptr<IConsumerSurface> previewSurface = IConsumerSurface::Create();
178    sptr<IBufferConsumerListener> previewListener = new DemoDCameraPreviewSurfaceListener(previewSurface);
179    previewSurface->RegisterConsumerListener(previewListener);
180    CameraFormat previewFormat = ConvertToCameraFormat(g_previewInfo->format_);
181    Size previewSize = {g_previewInfo->width_, g_previewInfo->height_};
182    Profile previewProfile(previewFormat, previewSize);
183    sptr<IBufferProducer> previewProducer = previewSurface->GetProducer();
184    sptr<Surface> previewProducerSurface = Surface::CreateSurfaceAsProducer(previewProducer);
185    int rv = g_cameraManager->CreatePreviewOutput(
186        previewProfile, previewProducerSurface, &((sptr<PreviewOutput> &)g_previewOutput));
187    if (rv != DCAMERA_OK) {
188        DHLOGE("InitPhotoOutput create previewOutput failed, rv: %{public}d", rv);
189        return;
190    }
191    ((sptr<PreviewOutput> &)g_previewOutput)->SetCallback(std::make_shared<DemoDCameraPreviewCallback>());
192}
193
194void InitVideoOutput(void)
195{
196    DHLOGI("Distributed Camera Demo: Create VideoOutput, width = %{public}d, height = %{public}d, format = %{public}d",
197        g_videoInfo->width_, g_videoInfo->height_, g_videoInfo->format_);
198    sptr<IConsumerSurface> videoSurface = IConsumerSurface::Create();
199    sptr<IBufferConsumerListener> videoListener = new DemoDCameraVideoSurfaceListener(videoSurface);
200    videoSurface->RegisterConsumerListener(videoListener);
201    CameraFormat videoFormat = ConvertToCameraFormat(g_videoInfo->format_);
202    Size videoSize = {g_videoInfo->width_, g_videoInfo->height_};
203    std::vector<int32_t> framerates = {};
204    VideoProfile videoSettings(videoFormat, videoSize, framerates);
205    sptr<IBufferProducer> videoProducer = videoSurface->GetProducer();
206    sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(videoProducer);
207    int rv = g_cameraManager->CreateVideoOutput(videoSettings, pSurface, &((sptr<VideoOutput> &)g_videoOutput));
208    if (rv != DCAMERA_OK) {
209        DHLOGE("InitPhotoOutput create videoOutput failed, rv: %{public}d", rv);
210        return;
211    }
212    ((sptr<VideoOutput> &)g_videoOutput)->SetCallback(std::make_shared<DemoDCameraVideoCallback>());
213}
214
215void ConfigCaptureSession(void)
216{
217    g_captureSession->BeginConfig();
218    g_captureSession->AddInput(g_cameraInput);
219    g_captureSession->AddOutput(g_previewOutput);
220    g_captureSession->AddOutput(g_videoOutput);
221    g_captureSession->AddOutput(g_photoOutput);
222    g_captureSession->CommitConfig();
223
224    std::vector<VideoStabilizationMode> stabilizationModes;
225    int32_t rv = g_captureSession->GetSupportedStabilizationMode(stabilizationModes);
226    if (rv != DCAMERA_OK) {
227        DHLOGE("ConfigCaptureSession get supported stabilization mode failed, rv: %{public}d", rv);
228        return;
229    }
230    if (!stabilizationModes.empty()) {
231        for (auto mode : stabilizationModes) {
232            DHLOGI("Distributed Camera Demo: video stabilization mode %{public}d", mode);
233        }
234        g_captureSession->SetVideoStabilizationMode(stabilizationModes.back());
235    }
236    g_captureSession->Start();
237}
238
239void ConfigFocusFlashAndExposure(bool isVideo)
240{
241    g_captureSession->LockForControl();
242    FocusMode focusMode = FOCUS_MODE_CONTINUOUS_AUTO;
243    ExposureMode exposureMode = EXPOSURE_MODE_AUTO;
244    float exposureValue = 0;
245    std::vector<float> biasRange;
246    int32_t rv = g_captureSession->GetExposureBiasRange(biasRange);
247    if (rv != DCAMERA_OK) {
248        DHLOGE("ConfigFocusAndExposure get exposure bias range failed, rv: %{public}d", rv);
249        return;
250    }
251    if (!biasRange.empty()) {
252        DHLOGI("Distributed Camera Demo: get %{public}d exposure compensation range", biasRange.size());
253        exposureValue = biasRange[0];
254    }
255    FlashMode flash = FLASH_MODE_OPEN;
256    if (isVideo) {
257        flash = FLASH_MODE_ALWAYS_OPEN;
258    }
259    g_captureSession->SetFlashMode(flash);
260    g_captureSession->SetFocusMode(focusMode);
261    g_captureSession->SetExposureMode(exposureMode);
262    g_captureSession->SetExposureBias(exposureValue);
263    g_captureSession->UnlockForControl();
264}
265
266std::shared_ptr<PhotoCaptureSetting> ConfigPhotoCaptureSetting()
267{
268    std::shared_ptr<PhotoCaptureSetting> photoCaptureSettings = std::make_shared<PhotoCaptureSetting>();
269    // Rotation
270    PhotoCaptureSetting::RotationConfig rotation = PhotoCaptureSetting::RotationConfig::Rotation_0;
271    photoCaptureSettings->SetRotation(rotation);
272    // QualityLevel
273    PhotoCaptureSetting::QualityLevel quality = PhotoCaptureSetting::QualityLevel::QUALITY_LEVEL_HIGH;
274    photoCaptureSettings->SetQuality(quality);
275    // Location
276    std::unique_ptr<Location> location = std::make_unique<Location>();
277    location->latitude = LOCATION_LATITUDE;
278    location->longitude = LOCATION_LONGITUDE;
279    location->altitude = LOCATION_ALTITUDE;
280    photoCaptureSettings->SetLocation(location);
281    return photoCaptureSettings;
282}
283
284void ReleaseResource(void)
285{
286    if (g_previewOutput != nullptr) {
287        ((sptr<CameraStandard::PreviewOutput> &)g_previewOutput)->Stop();
288        g_previewOutput->Release();
289        g_previewOutput = nullptr;
290    }
291    if (g_photoOutput != nullptr) {
292        g_photoOutput->Release();
293        g_photoOutput = nullptr;
294    }
295    if (g_videoOutput != nullptr) {
296        g_videoOutput->Release();
297        g_videoOutput = nullptr;
298    }
299    if (g_cameraInput != nullptr) {
300        g_cameraInput->Close();
301        g_cameraInput->Release();
302        g_cameraInput = nullptr;
303    }
304    if (g_captureSession != nullptr) {
305        g_captureSession->Stop();
306        g_captureSession->Release();
307        g_captureSession = nullptr;
308    }
309    if (g_cameraManager != nullptr) {
310        g_cameraManager->SetCallback(nullptr);
311    }
312    g_cameraInfo = nullptr;
313    g_cameraManager = nullptr;
314}
315
316int32_t Capture()
317{
318    int32_t ret = ((sptr<PhotoOutput> &)g_photoOutput)->Capture(ConfigPhotoCaptureSetting());
319    if (ret != DCAMERA_OK) {
320        DHLOGE("main g_photoOutput Capture failed, ret: %{public}d", ret);
321        return ret;
322    }
323    return DCAMERA_OK;
324}
325
326int32_t Video()
327{
328    int32_t ret = ((sptr<VideoOutput> &)g_videoOutput)->Start();
329    if (ret != DCAMERA_OK) {
330        DHLOGE("main VideoOutput Start failed, ret: %{public}d", ret);
331        return ret;
332    }
333    return DCAMERA_OK;
334}
335
336int32_t GetPreviewProfiles(std::vector<CameraStandard::Size> &previewResolution)
337{
338    sptr<CameraOutputCapability> capability = g_cameraManager->GetSupportedOutputCapability(g_cameraInfo);
339    if (capability == nullptr) {
340        DHLOGI("get supported capability is null");
341        return DCAMERA_BAD_VALUE;
342    }
343    std::vector<CameraStandard::Profile> previewProfiles = capability->GetPreviewProfiles();
344    DHLOGI("size: %{public}d", previewProfiles.size());
345    for (auto& profile : previewProfiles) {
346        CameraStandard::Size picSize = profile.GetSize();
347        DHLOGI("width: %{public}d, height: %{public}d", picSize.width, picSize.height);
348        if (IsValid(picSize)) {
349            previewResolution.push_back(picSize);
350        }
351    }
352    return DCAMERA_OK;
353}
354
355bool IsValid(const CameraStandard::Size& size)
356{
357    return (size.width >= RESOLUTION_MIN_WIDTH) && (size.height >= RESOLUTION_MIN_HEIGHT) &&
358        (size.width <= RESOLUTION_MAX_WIDTH_CONTINUOUS) && (size.height <= RESOLUTION_MAX_HEIGHT_CONTINUOUS);
359}
360} // namespace DistributedHardware
361} // namespace OHOS
362