1 /*
2  * Copyright (c) 2022-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 
18 #include "access_token.h"
19 #include "accesstoken_kit.h"
20 #include "hap_token_info.h"
21 #include "ipc_skeleton.h"
22 #include "nativetoken_kit.h"
23 #include "token_setproc.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::Camera;
27 using namespace OHOS::CameraStandard;
28 using namespace OHOS::DistributedHardware;
29 
30 constexpr double LATITUDE = 22.306;
31 constexpr double LONGITUDE = 52.12;
32 constexpr double ALTITUDE = 2.365;
33 constexpr int32_t PHOTO_WIDTH = 1280;
34 constexpr int32_t PHOTO_HEIGTH = 960;
35 constexpr int32_t PREVIEW_WIDTH = 640;
36 constexpr int32_t PREVIEW_HEIGTH = 480;
37 constexpr int32_t VIDEO_WIDTH = 640;
38 constexpr int32_t VIDEO_HEIGTH = 480;
39 constexpr int32_t SLEEP_FIVE_SECOND = 5;
40 constexpr int32_t SLEEP_TWENTY_SECOND = 20;
41 
42 static sptr<CameraDevice> g_cameraInfo = nullptr;
43 static sptr<CameraManager> g_cameraManager = nullptr;
44 static sptr<CaptureInput> g_cameraInput = nullptr;
45 static sptr<CaptureOutput> g_photoOutput = nullptr;
46 static sptr<CaptureOutput> g_previewOutput = nullptr;
47 static sptr<CaptureOutput> g_videoOutput = nullptr;
48 static sptr<CaptureSession> g_captureSession = nullptr;
49 static std::shared_ptr<DCameraCaptureInfo> g_photoInfo = nullptr;
50 static std::shared_ptr<DCameraCaptureInfo> g_previewInfo = nullptr;
51 static std::shared_ptr<DCameraCaptureInfo> g_videoInfo = nullptr;
52 
53 #ifdef DCAMERA_YUV
54     constexpr int32_t PHOTO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_JPEG;
55     constexpr int32_t PREVIEW_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_YCRCB_420_SP;
56     constexpr int32_t VIDEO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_YCRCB_420_SP;
57 #else
58     constexpr int32_t PHOTO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_JPEG;
59     constexpr int32_t PREVIEW_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888;
60     constexpr int32_t VIDEO_FORMAT = camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888;
61 #endif
62 
InitCameraStandard()63 static int32_t InitCameraStandard()
64 {
65     g_cameraManager = CameraManager::GetInstance();
66     g_cameraManager->SetCallback(std::make_shared<DemoDCameraManagerCallback>());
67 
68     int rv = g_cameraManager->CreateCaptureSession(&g_captureSession);
69     if (rv != DCAMERA_OK) {
70         DHLOGE("InitCameraStandard create captureSession failed, rv: %{public}d", rv);
71         return rv;
72     }
73     std::shared_ptr<DemoDCameraSessionCallback> sessionCallback = std::make_shared<DemoDCameraSessionCallback>();
74     g_captureSession->SetCallback(sessionCallback);
75     g_captureSession->SetFocusCallback(sessionCallback);
76 
77     std::vector<sptr<CameraDevice>> cameraObjList = g_cameraManager->GetSupportedCameras();
78     for (auto info : cameraObjList) {
79         DHLOGI("Camera: %{public}s, position: %{public}d, camera type: %{public}d, connection type: %{public}d",
80             GetAnonyString(info->GetID()).c_str(),
81             info->GetPosition(), info->GetCameraType(), info->GetConnectionType());
82         // OHOS_CAMERA_POSITION_FRONT or OHOS_CAMERA_POSITION_BACK
83         if ((info->GetPosition() == CameraPosition::CAMERA_POSITION_FRONT) &&
84             (info->GetConnectionType() == ConnectionType::CAMERA_CONNECTION_REMOTE)) {
85             g_cameraInfo = info;
86             break;
87         }
88     }
89 
90     if (g_cameraInfo == nullptr) {
91         DHLOGE("Distributed Camera Demo: have no remote camera");
92         return DCAMERA_BAD_VALUE;
93     }
94 
95     rv = g_cameraManager->CreateCameraInput(g_cameraInfo, &((sptr<CameraInput> &)g_cameraInput));
96     if (rv != DCAMERA_OK) {
97         DHLOGE("InitCameraStandard create cameraInput failed, rv: %{public}d", rv);
98         return rv;
99     }
100     int32_t ret = ((sptr<CameraInput> &)g_cameraInput)->Open();
101     if (ret != DCAMERA_OK) {
102         DHLOGE("InitCameraStandard g_cameraInput Open failed, ret: %{public}d", ret);
103         return ret;
104     }
105     std::shared_ptr<DemoDCameraInputCallback> inputCallback = std::make_shared<DemoDCameraInputCallback>();
106     ((sptr<CameraInput> &)g_cameraInput)->SetErrorCallback(inputCallback);
107     return DCAMERA_OK;
108 }
109 
InitCaptureInfo()110 static void InitCaptureInfo()
111 {
112     g_photoInfo = std::make_shared<DCameraCaptureInfo>();
113     g_photoInfo->width_ = PHOTO_WIDTH;
114     g_photoInfo->height_ = PHOTO_HEIGTH;
115     g_photoInfo->format_ = PHOTO_FORMAT;
116 
117     g_previewInfo = std::make_shared<DCameraCaptureInfo>();
118     g_previewInfo->width_ = PREVIEW_WIDTH;
119     g_previewInfo->height_ = PREVIEW_HEIGTH;
120     g_previewInfo->format_ = PREVIEW_FORMAT;
121 
122     g_videoInfo = std::make_shared<DCameraCaptureInfo>();
123     g_videoInfo->width_ = VIDEO_WIDTH;
124     g_videoInfo->height_ = VIDEO_HEIGTH;
125     g_videoInfo->format_ = VIDEO_FORMAT;
126 }
127 
ConvertToCameraFormat(int32_t format)128 static CameraFormat ConvertToCameraFormat(int32_t format)
129 {
130     CameraFormat ret = CameraFormat::CAMERA_FORMAT_INVALID;
131     DCameraFormat df = static_cast<DCameraFormat>(format);
132     switch (df) {
133         case DCameraFormat::OHOS_CAMERA_FORMAT_RGBA_8888:
134             ret = CameraFormat::CAMERA_FORMAT_RGBA_8888;
135             break;
136         case DCameraFormat::OHOS_CAMERA_FORMAT_YCBCR_420_888:
137             ret = CameraFormat::CAMERA_FORMAT_YCBCR_420_888;
138             break;
139         case DCameraFormat::OHOS_CAMERA_FORMAT_YCRCB_420_SP:
140             ret = CameraFormat::CAMERA_FORMAT_YUV_420_SP;
141             break;
142         case DCameraFormat::OHOS_CAMERA_FORMAT_JPEG:
143             ret = CameraFormat::CAMERA_FORMAT_JPEG;
144             break;
145         default:
146             break;
147     }
148     return ret;
149 }
150 
InitPhotoOutput()151 static void InitPhotoOutput()
152 {
153     DHLOGI("Distributed Camera Demo: Create PhotoOutput, width = %{public}d, height = %{public}d, format = %{public}d",
154         g_photoInfo->width_, g_photoInfo->height_, g_photoInfo->format_);
155     sptr<IConsumerSurface> photoSurface = IConsumerSurface::Create();
156     sptr<IBufferConsumerListener> photoListener(new DemoDCameraPhotoSurfaceListener(photoSurface));
157     photoSurface->RegisterConsumerListener(photoListener);
158     CameraFormat photoFormat = ConvertToCameraFormat(g_photoInfo->format_);
159     Size photoSize = {g_photoInfo->width_, g_photoInfo->height_};
160     Profile photoProfile(photoFormat, photoSize);
161     sptr<IBufferProducer> photoProducer = photoSurface->GetProducer();
162     int rv = g_cameraManager->CreatePhotoOutput(photoProfile, photoProducer, &((sptr<PhotoOutput> &)g_photoOutput));
163     if (rv != DCAMERA_OK) {
164         DHLOGE("InitPhotoOutput create photoOutput failed, rv: %{public}d", rv);
165         return;
166     }
167     ((sptr<PhotoOutput> &)g_photoOutput)->SetCallback(std::make_shared<DemoDCameraPhotoCallback>());
168 }
169 
InitPreviewOutput()170 static void InitPreviewOutput()
171 {
172     DHLOGI("Distributed Camera Demo: Create PreviewOutput, width = %{public}d, height = %{public}d, format = "
173         "%{public}d", g_previewInfo->width_, g_previewInfo->height_, g_previewInfo->format_);
174     sptr<IConsumerSurface> previewSurface = IConsumerSurface::Create();
175     sptr<IBufferConsumerListener> previewListener(new DemoDCameraPreviewSurfaceListener(previewSurface));
176     previewSurface->RegisterConsumerListener(previewListener);
177     CameraFormat previewFormat = ConvertToCameraFormat(g_previewInfo->format_);
178     Size previewSize = {g_previewInfo->width_, g_previewInfo->height_};
179     Profile previewProfile(previewFormat, previewSize);
180     sptr<IBufferProducer> previewProducer = previewSurface->GetProducer();
181     sptr<Surface> previewProducerSurface = Surface::CreateSurfaceAsProducer(previewProducer);
182     int rv = g_cameraManager->CreatePreviewOutput(
183         previewProfile, previewProducerSurface, &((sptr<PreviewOutput> &)g_previewOutput));
184     if (rv != DCAMERA_OK) {
185         DHLOGE("InitPhotoOutput create previewOutput failed, rv: %{public}d", rv);
186         return;
187     }
188     ((sptr<PreviewOutput> &)g_previewOutput)->SetCallback(std::make_shared<DemoDCameraPreviewCallback>());
189 }
190 
InitVideoOutput()191 static void InitVideoOutput()
192 {
193     DHLOGI("Distributed Camera Demo: Create VideoOutput, width = %{public}d, height = %{public}d, format = %{public}d",
194         g_videoInfo->width_, g_videoInfo->height_, g_videoInfo->format_);
195     sptr<IConsumerSurface> videoSurface = IConsumerSurface::Create();
196     sptr<IBufferConsumerListener> videoListener(new DemoDCameraVideoSurfaceListener(videoSurface));
197     videoSurface->RegisterConsumerListener(videoListener);
198     CameraFormat videoFormat = ConvertToCameraFormat(g_videoInfo->format_);
199     Size videoSize = {g_videoInfo->width_, g_videoInfo->height_};
200     std::vector<int32_t> framerates = {};
201     VideoProfile videoSettings(videoFormat, videoSize, framerates);
202     sptr<IBufferProducer> videoProducer = videoSurface->GetProducer();
203     sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(videoProducer);
204     int rv = g_cameraManager->CreateVideoOutput(videoSettings, pSurface, &((sptr<VideoOutput> &)g_videoOutput));
205     if (rv != DCAMERA_OK) {
206         DHLOGE("InitPhotoOutput create videoOutput failed, rv: %{public}d", rv);
207         return;
208     }
209     ((sptr<VideoOutput> &)g_videoOutput)->SetCallback(std::make_shared<DemoDCameraVideoCallback>());
210 }
211 
ConfigCaptureSession()212 static void ConfigCaptureSession()
213 {
214     g_captureSession->BeginConfig();
215     g_captureSession->AddInput(g_cameraInput);
216     g_captureSession->AddOutput(g_previewOutput);
217     g_captureSession->AddOutput(g_videoOutput);
218     g_captureSession->AddOutput(g_photoOutput);
219     g_captureSession->CommitConfig();
220 
221     std::vector<VideoStabilizationMode> stabilizationModes;
222     int32_t rv = g_captureSession->GetSupportedStabilizationMode(stabilizationModes);
223     if (rv != DCAMERA_OK) {
224         DHLOGE("ConfigCaptureSession get supported stabilization mode failed, rv: %{public}d", rv);
225         return;
226     }
227     if (!stabilizationModes.empty()) {
228         for (auto mode : stabilizationModes) {
229             DHLOGI("Distributed Camera Demo: video stabilization mode %{public}d", mode);
230         }
231         g_captureSession->SetVideoStabilizationMode(stabilizationModes.back());
232     }
233 }
234 
ConfigFocusAndExposure()235 static void ConfigFocusAndExposure()
236 {
237     g_captureSession->LockForControl();
238     FocusMode focusMode = FOCUS_MODE_CONTINUOUS_AUTO;
239     ExposureMode exposureMode = EXPOSURE_MODE_AUTO;
240     float exposureValue = 0;
241     std::vector<float> biasRange;
242     int32_t rv = g_captureSession->GetExposureBiasRange(biasRange);
243     if (rv != DCAMERA_OK) {
244         DHLOGE("ConfigFocusAndExposure get exposure bias range failed, rv: %{public}d", rv);
245         return;
246     }
247     if (!biasRange.empty()) {
248         DHLOGI("Distributed Camera Demo: get %{public}zu exposure compensation range", biasRange.size());
249         exposureValue = biasRange[0];
250     }
251     g_captureSession->SetFocusMode(focusMode);
252     g_captureSession->SetExposureMode(exposureMode);
253     g_captureSession->SetExposureBias(exposureValue);
254     g_captureSession->UnlockForControl();
255 }
256 
ConfigPhotoCaptureSetting()257 static std::shared_ptr<PhotoCaptureSetting> ConfigPhotoCaptureSetting()
258 {
259     std::shared_ptr<PhotoCaptureSetting> photoCaptureSettings = std::make_shared<PhotoCaptureSetting>();
260     // Rotation
261     PhotoCaptureSetting::RotationConfig rotation = PhotoCaptureSetting::RotationConfig::Rotation_0;
262     photoCaptureSettings->SetRotation(rotation);
263     // QualityLevel
264     PhotoCaptureSetting::QualityLevel quality = PhotoCaptureSetting::QualityLevel::QUALITY_LEVEL_HIGH;
265     photoCaptureSettings->SetQuality(quality);
266     // Location
267     auto location = std::make_shared<Location>();
268     location->latitude = LATITUDE;
269     location->longitude = LONGITUDE;
270     location->altitude = ALTITUDE;
271     photoCaptureSettings->SetLocation(location);
272     return photoCaptureSettings;
273 }
274 
SetPermissions()275 static void SetPermissions()
276 {
277     uint64_t tokenId;
278     const char *perms[2];
279     perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
280     perms[1] = "ohos.permission.CAMERA";
281     NativeTokenInfoParams infoInstance = {
282         .dcapsNum = 0,
283         .permsNum = 2,
284         .aclsNum = 0,
285         .dcaps = NULL,
286         .perms = perms,
287         .acls = NULL,
288         .processName = "dcamera_client_demo",
289         .aplStr = "system_basic",
290     };
291     tokenId = GetAccessTokenId(&infoInstance);
292     SetSelfTokenID(tokenId);
293     OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
294 }
295 
main()296 int main()
297 {
298     DHLOGI("========== Distributed Camera Demo Start ==========");
299     SetPermissions();
300     int32_t ret = InitCameraStandard();
301     if (ret != DCAMERA_OK) {
302         std::cout << "have no remote camera" << std::endl;
303         return 0;
304     }
305 
306     InitCaptureInfo();
307     InitPhotoOutput();
308     InitPreviewOutput();
309     InitVideoOutput();
310     ConfigCaptureSession();
311 
312     g_captureSession->Start();
313     sleep(SLEEP_FIVE_SECOND);
314 
315     if (((sptr<VideoOutput> &)g_videoOutput)->Start() != DCAMERA_OK) {
316         DHLOGE("main g_videoOutput Start failed");
317     }
318     sleep(SLEEP_FIVE_SECOND);
319 
320     ConfigFocusAndExposure();
321     sleep(SLEEP_FIVE_SECOND);
322 
323     ((sptr<PhotoOutput> &)g_photoOutput)->Capture(ConfigPhotoCaptureSetting());
324     sleep(SLEEP_TWENTY_SECOND);
325 
326     if (((sptr<VideoOutput> &)g_videoOutput)->Stop() != DCAMERA_OK) {
327         DHLOGE("main g_videoOutput Stop failed");
328     }
329     sleep(SLEEP_FIVE_SECOND);
330 
331     g_captureSession->Stop();
332     if (g_cameraInput->Close() != DCAMERA_OK) {
333         DHLOGE("main g_cameraInput Close failed");
334     }
335     g_captureSession->Release();
336     if (g_cameraInput->Release() != DCAMERA_OK) {
337         DHLOGE("main g_cameraInput Close failed");
338     }
339     DHLOGI("========== Distributed Camera Demo End ==========");
340     return 0;
341 }