1 /*
2  * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file expected 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 "common.h"
17 #include "camera.h"
18 #include "video_key_info.h"
19 
20 namespace OHOS::Camera {
21 Test::ResultCallback Test::resultCallback_ = 0;
22 
GetCurrentLocalTimeStamp()23 uint64_t Test::GetCurrentLocalTimeStamp()
24 {
25     std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp =
26         std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
27     auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
28     return static_cast<uint64_t>(tmp.count());
29 }
30 
DumpImageFile(int streamId, std::string suffix, const void* buffer, int32_t size)31 int32_t Test::DumpImageFile(int streamId, std::string suffix, const void* buffer, int32_t size)
32 {
33     if (imageDataSaveSwitch == SWITCH_OFF) {
34         return 0;
35     }
36     if (streamId < 0) {
37         CAMERA_LOGE("ivalid stream id: %{public}d", streamId);
38         return -1;
39     }
40     char mkdirCmd[PATH_MAX] = {0};
41     char path[PATH_MAX] = {0};
42     int ret = sprintf_s(mkdirCmd, sizeof(mkdirCmd) / sizeof(mkdirCmd[0]),
43         "mkdir -p /data/stream-%d", streamId);
44     if (ret < 0) {
45         return -1;
46     }
47     system(mkdirCmd);
48     ret = sprintf_s(path, sizeof(path) / sizeof(path[0]), "data/stream-%d/%lld.%s",
49         streamId, GetCurrentLocalTimeStamp(), suffix.c_str());
50     if (ret < 0) {
51         return -1;
52     }
53 
54     int imgFd = open(path, O_RDWR | O_CREAT, 00766);
55     if (imgFd == -1) {
56         CAMERA_LOGE("open file failed, errno: %{public}s", strerror(errno));
57         return -1;
58     }
59 
60     ret = write(imgFd, buffer, size);
61     if (ret == -1) {
62         CAMERA_LOGE("write file failed, error: %{public}s", strerror(errno));
63         close(imgFd);
64         return -1;
65     }
66     close(imgFd);
67     return 0;
68 }
69 
Init()70 void Test::Init()
71 {
72     if (service == nullptr) {
73         service = ICameraHost::Get("camera_service", false);
74         if (service == nullptr) {
75             CAMERA_LOGI("ICameraHost get failed");
76         } else {
77             CAMERA_LOGE("ICameraHost get success");
78         }
79         ASSERT_TRUE(service != nullptr);
80     }
81     hostCallback = new TestCameraHostCallback();
82     service->SetCallback(hostCallback);
83     service->GetCameraIds(cameraIds);
84     if (cameraIds.size() == 0) {
85         CAMERA_LOGE("camera device list empty");
86         GTEST_SKIP() << "No Camera Available" << std::endl;
87         return;
88     }
89 }
90 
GetCameraMetadata()91 void Test::GetCameraMetadata()
92 {
93     rc = service->GetCameraAbility(cameraIds.front(), abilityVec);
94     if (rc != HDI::Camera::V1_0::NO_ERROR) {
95         CAMERA_LOGE("GetCameraAbility failed, rc = %{public}d", rc);
96     }
97     MetadataUtils::ConvertVecToMetadata(abilityVec, ability);
98 
99     common_metadata_header_t* data = ability->get();
100     camera_metadata_item_t entry;
101     int ret = FindCameraMetadataItem(data, OHOS_CONTROL_AE_AVAILABLE_MODES, &entry);
102     if (ret == 0) {
103         CAMERA_LOGI("get OHOS_CONTROL_AE_AVAILABLE_MODES success");
104     }
105     camera_metadata_item_t connectEntry;
106     ret = FindCameraMetadataItem(data, OHOS_ABILITY_CAMERA_CONNECTION_TYPE, &connectEntry);
107     if (ret == HDI::Camera::V1_0::NO_ERROR && connectEntry.data.u8 != nullptr && connectEntry.count > 0) {
108         uint8_t cameraConnectionType = *(connectEntry.data.u8);
109         if (static_cast<int>(cameraConnectionType) == OHOS_CAMERA_CONNECTION_TYPE_USB_PLUGIN) {
110             CAMERA_LOGI("get OHOS_ABILITY_CAMERA_CONNECTION_TYPE success, this camera is usb camera.");
111             previewWidth = usbCamera_previewWidth;
112             previewHeight = usbCamera_previewHeight;
113             videoWidth = usbCamera_videoWidth;
114             videoHeight = usbCamera_videoHeight;
115             captureWidth = usbCamera_captureWidth;
116             captureHeight = usbCamera_captureHeight;
117             analyzeWidth = usbCamera_analyzeWidth;
118             analyzeHeight = usbCamera_analyzeHeight;
119             previewFormat = usbCamera_previewFormat;
120             videoFormat = usbCamera_videoFormat;
121             snapshotFormat = usbCamera_snapshotFormat;
122             analyzeFormat = usbCamera_analyzeFormat;
123             videoEncodeType = usbCamera_videoEncodeType;
124         }
125     }
126 }
127 
Open()128 void Test::Open()
129 {
130     if (cameraDevice == nullptr) {
131         if (cameraIds.size() == 0) {
132             CAMERA_LOGE("camera device list empty");
133             return;
134         }
135         GetCameraMetadata();
136         deviceCallback = new OHOS::Camera::Test::DemoCameraDeviceCallback();
137         rc = service->OpenCamera(cameraIds.front(), deviceCallback, cameraDevice);
138         if (rc != HDI::Camera::V1_0::NO_ERROR || cameraDevice == nullptr) {
139             CAMERA_LOGE("openCamera failed, rc = %{public}d", rc);
140             return;
141         }
142         CAMERA_LOGI("OpenCamera success");
143     }
144 }
145 
Close()146 void Test::Close()
147 {
148     if (cameraDevice != nullptr) {
149         cameraDevice->Close();
150         cameraDevice = nullptr;
151     }
152 }
153 
StartStream(std::vector<StreamIntent> intents)154 void Test::StartStream(std::vector<StreamIntent> intents)
155 {
156     streamOperatorCallback = new TestStreamOperatorCallback();
157     rc = cameraDevice->GetStreamOperator(streamOperatorCallback, streamOperator);
158     if (rc == HDI::Camera::V1_0::NO_ERROR) {
159         CAMERA_LOGI("GetStreamOperator success");
160     } else {
161         CAMERA_LOGE("GetStreamOperator fail, rc = %{public}d", rc);
162     }
163     streamInfoPre = std::make_shared<StreamInfo>();
164     streamInfoVideo = std::make_shared<StreamInfo>();
165     streamInfoCapture = std::make_shared<StreamInfo>();
166     streamInfoAnalyze = std::make_shared<StreamInfo>();
167     for (auto& intent : intents) {
168         if (intent == StreamIntent::PREVIEW) {
169             streamInfoPre->streamId_ = streamIdPreview;
170             streamInfoPre->width_ = previewWidth;
171             streamInfoPre->height_ = previewHeight;
172             streamInfoPre->format_ = previewFormat;
173             streamInfoPre->dataspace_ = UT_DATA_SIZE;
174             streamInfoPre->intent_ = intent;
175             streamInfoPre->tunneledMode_ = UT_TUNNEL_MODE;
176             std::shared_ptr<StreamConsumer> consumer_pre = std::make_shared<StreamConsumer>();
177             streamInfoPre->bufferQueue_ = consumer_pre->CreateProducerSeq([this](void* addr, uint32_t size) {
178                 DumpImageFile(streamIdPreview, "yuv", addr, size);
179             });
180             streamInfoPre->bufferQueue_->producer_->SetQueueSize(UT_DATA_SIZE);
181             consumerMap_[intent] = consumer_pre;
182             streamInfos.push_back(*streamInfoPre);
183         } else if (intent == StreamIntent::VIDEO) {
184             streamInfoVideo->streamId_ = streamIdVideo;
185             streamInfoVideo->width_ = videoWidth;
186             streamInfoVideo->height_ = videoHeight;
187             streamInfoVideo->format_ = videoFormat;
188             streamInfoVideo->dataspace_ = UT_DATA_SIZE;
189             streamInfoVideo->intent_ = intent;
190             streamInfoVideo->encodeType_ = ENCODE_TYPE_H265;
191             streamInfoVideo->tunneledMode_ = UT_TUNNEL_MODE;
192             std::shared_ptr<StreamConsumer> consumer_video = std::make_shared<StreamConsumer>();
193             streamInfoVideo->bufferQueue_ = consumer_video->CreateProducerSeq([this](void* addr, uint32_t size) {
194                 DumpImageFile(streamIdPreview, "yuv", addr, size);
195             });
196             streamInfoVideo->bufferQueue_->producer_->SetQueueSize(UT_DATA_SIZE);
197             consumerMap_[intent] = consumer_video;
198             streamInfos.push_back(*streamInfoVideo);
199         } else if (intent == StreamIntent::ANALYZE) {
200             streamInfoAnalyze->streamId_ = streamIdAnalyze;
201             streamInfoAnalyze->width_ = analyzeWidth;
202             streamInfoAnalyze->height_ = analyzeHeight;
203             streamInfoAnalyze->format_ = analyzeFormat;
204             streamInfoAnalyze->dataspace_ = UT_DATA_SIZE;
205             streamInfoAnalyze->intent_ = intent;
206             streamInfoAnalyze->tunneledMode_ = UT_TUNNEL_MODE;
207 
208             std::shared_ptr<StreamConsumer> consumer_analyze = std::make_shared<StreamConsumer>();
209             streamInfoAnalyze->bufferQueue_ = consumer_analyze->CreateProducerSeq([this](void* addr, uint32_t size) {
210                 common_metadata_header_t *data = static_cast<common_metadata_header_t *>(addr);
211                 camera_metadata_item_t entry = {};
212 
213                 int ret = FindCameraMetadataItem(data, OHOS_STATISTICS_FACE_IDS, &entry);
214                 if (ret == 0) {
215                     for (size_t i = 0; i < entry.count; i++) {
216                         int id = entry.data.i32[i];
217                         CAMERA_LOGI("Face ids : %{public}d", id);
218                     }
219                 }
220 
221                 ret = FindCameraMetadataItem(data, OHOS_STATISTICS_FACE_RECTANGLES, &entry);
222                 if (ret == 0) {
223                     for (size_t i = 0; i < entry.count; i++) {
224                         int id = entry.data.i32[i];
225                         CAMERA_LOGI("Face rectangles : %{public}d", id);
226                     }
227                 }
228             });
229             streamInfoAnalyze->bufferQueue_->producer_->SetQueueSize(UT_DATA_SIZE);
230             consumerMap_[intent] = consumer_analyze;
231             streamInfos.push_back(*streamInfoAnalyze);
232         } else {
233             streamInfoCapture->streamId_ = streamIdAnalyze;
234             streamInfoCapture->width_ = analyzeWidth;
235             streamInfoCapture->height_ = analyzeHeight;
236             streamInfoCapture->format_ = analyzeFormat;
237             streamInfoCapture->dataspace_ = UT_DATA_SIZE;
238             streamInfoCapture->intent_ = intent;
239             streamInfoCapture->tunneledMode_ = UT_TUNNEL_MODE;
240             std::shared_ptr<StreamConsumer> consumer_capture = std::make_shared<StreamConsumer>();
241             streamInfoCapture->bufferQueue_ = consumer_capture->CreateProducerSeq([this](void* addr, uint32_t size) {
242                 DumpImageFile(streamIdPreview, "yuv", addr, size);
243             });
244             streamInfoCapture->bufferQueue_->producer_->SetQueueSize(UT_DATA_SIZE);
245             consumerMap_[intent] = consumer_capture;
246             streamInfos.push_back(*streamInfoCapture);
247         }
248     }
249 
250     rc = streamOperator->CreateStreams(streamInfos);
251     EXPECT_EQ(false, rc != HDI::Camera::V1_0::NO_ERROR);
252     rc = streamOperator->CommitStreams(OperationMode::NORMAL, abilityVec);
253     EXPECT_EQ(false, rc != HDI::Camera::V1_0::NO_ERROR);
254     sleep(1);
255     std::vector<StreamInfo>().swap(streamInfos);
256 }
257 
StartCapture(int streamId, int captureId, bool shutterCallback, bool isStreaming)258 void Test::StartCapture(int streamId, int captureId, bool shutterCallback, bool isStreaming)
259 {
260     captureInfo = std::make_shared<CaptureInfo>();
261     captureInfo->streamIds_ = {streamId};
262     captureInfo->captureSetting_ = abilityVec;
263     captureInfo->enableShutterCallback_ = shutterCallback;
264     rc = (CamRetCode)streamOperator->Capture(captureId, *captureInfo, isStreaming);
265     EXPECT_EQ(true, rc == HDI::Camera::V1_0::NO_ERROR);
266     if (rc == HDI::Camera::V1_0::NO_ERROR) {
267         CAMERA_LOGI("check Capture: Capture success, %{public}d", captureId);
268     } else {
269         std::cout << "rc = " << rc << std::endl;
270         CAMERA_LOGE("check Capture: Capture fail, rc = %{public}d", rc);
271     }
272     sleep(UT_SLEEP_TIME);
273 }
274 
StopStream(std::vector<int>& captureIds, std::vector<int>& streamIds)275 void Test::StopStream(std::vector<int>& captureIds, std::vector<int>& streamIds)
276 {
277     if (sizeof(captureIds) > 0) {
278         for (auto &captureId : captureIds) {
279             rc = streamOperator->CancelCapture(captureId);
280             EXPECT_EQ(true, rc == HDI::Camera::V1_0::NO_ERROR);
281             if (rc == HDI::Camera::V1_0::NO_ERROR) {
282                 CAMERA_LOGI("check Capture: CancelCapture success, %{public}d", captureId);
283             } else {
284                 CAMERA_LOGE("check Capture: CancelCapture fail, rc = %{public}d, captureId = %{public}d",
285                     rc, captureId);
286             }
287         }
288     }
289     if (sizeof(streamIds) > 0) {
290         rc = streamOperator->ReleaseStreams(streamIds);
291         EXPECT_EQ(true, rc == HDI::Camera::V1_0::NO_ERROR);
292         if (rc == HDI::Camera::V1_0::NO_ERROR) {
293             CAMERA_LOGI("check Capture: ReleaseStream success");
294         } else {
295             CAMERA_LOGE("check Capture: ReleaseStreams fail, rc = %{public}d", rc);
296         }
297     }
298 }
299 
CalculateFps(int64_t timestamp, int32_t streamId)300 void Test::StreamConsumer::CalculateFps(int64_t timestamp, int32_t streamId)
301 {
302     if (isFirstCalculateFps_) {
303         if ((timestamp - intervalTimestamp_) >= interval_) {
304             int64_t timeInterval = timestamp - intervalTimestamp_;
305             if (timeInterval != 0) {
306                 float fps = (int64_t)(100000000000 * timestampCount_ / timeInterval) / 100.0;
307                 CAMERA_LOGI("Calculate FPS success, streamId: %{public}d, Fps:%{public}f", streamId, fps);
308                 interval_ = ONESECOND_OF_MICROSECOND_UNIT;
309             } else {
310                 CAMERA_LOGE("Calculate FPS error timeInerval is 0");
311             }
312         }
313     } else {
314         intervalTimestamp_ = timestamp;
315         isFirstCalculateFps_ = true;
316     }
317     if ((timestamp - intervalTimestamp_) >= ONESECOND_OF_MICROSECOND_UNIT * UT_SECOND_TIMES) {
318         intervalTimestamp_ = timestamp;
319         timestampCount_ = 0;
320         interval_ = ONESECOND_OF_MICROSECOND_UNIT;
321     }
322     timestampCount_++;
323 }
324 
CreateProducer(std::function<void(void*, uint32_t)> callback)325 OHOS::sptr<OHOS::IBufferProducer> Test::StreamConsumer::CreateProducer(std::function<void(void*, uint32_t)> callback)
326 {
327     consumer_ = OHOS::IConsumerSurface::Create();
328     if (consumer_ == nullptr) {
329         return nullptr;
330     }
331     sptr<IBufferConsumerListener> listener = new TestBufferConsumerListener();
332     consumer_->RegisterConsumerListener(listener);
333     auto producer = consumer_->GetProducer();
334     if (producer == nullptr) {
335         return nullptr;
336     }
337 
338     callback_ = callback;
339     consumerThread_ = new std::thread([this, listener] {
340         int32_t flushFence = 0;
341         int64_t timestamp = 0;
342         OHOS::Rect damage;
343         TestBufferConsumerListener* checker = static_cast<TestBufferConsumerListener*>(listener.GetRefPtr());
344         while (running_ == true) {
345             OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;
346             if (checker->checkBufferAvailable()) {
347                 consumer_->AcquireBuffer(buffer, flushFence, timestamp, damage);
348                 if (buffer != nullptr) {
349                     void* addr = buffer->GetVirAddr();
350                     uint32_t size = buffer->GetSize();
351 
352                     int32_t gotSize = 0;
353                     int32_t isKey = 0;
354                     int32_t streamId = 0;
355                     int32_t captureId = 0;
356                     buffer->GetExtraData()->ExtraGet(OHOS::Camera::dataSize, gotSize);
357                     buffer->GetExtraData()->ExtraGet(OHOS::Camera::isKeyFrame, isKey);
358                     buffer->GetExtraData()->ExtraGet(OHOS::Camera::timeStamp, timestamp);
359                     buffer->GetExtraData()->ExtraGet(OHOS::Camera::streamId, streamId);
360                     buffer->GetExtraData()->ExtraGet(OHOS::Camera::captureId, captureId);
361                     if (gotSize) {
362                         CalculateFps(timestamp, streamId);
363                         callback_(addr, gotSize);
364                     } else {
365                         callback_(addr, size);
366                     }
367 
368                     consumer_->ReleaseBuffer(buffer, -1);
369                     shotCount_--;
370                     if (shotCount_ == 0) {
371                         std::unique_lock<std::mutex> l(l_);
372                         cv_.notify_one();
373                     }
374                 }
375             }
376             if (running_ == false) {
377                 break;
378             }
379             usleep(1);
380         }
381     });
382 
383     return producer;
384 }
385 
CreateProducerSeq( std::function<void(void*, uint32_t)> callback)386 OHOS::sptr<BufferProducerSequenceable> Test::StreamConsumer::CreateProducerSeq(
387     std::function<void(void*, uint32_t)> callback)
388 {
389     OHOS::sptr<OHOS::IBufferProducer> producer = CreateProducer(callback);
390     if (producer == nullptr) {
391         return nullptr;
392     }
393 
394     return new BufferProducerSequenceable(producer);
395 }
396 
OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamId)397 int32_t Test::TestStreamOperatorCallback::OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamId)
398 {
399     for (auto it : streamId) {
400         CAMERA_LOGE("captureId: %{public}d, streamId: %{public}d", captureId, it);
401     }
402     return HDI::Camera::V1_0::NO_ERROR;
403 }
404 
OnCaptureEnded(int32_t captureId, const std::vector<CaptureEndedInfo> &infos)405 int32_t Test::TestStreamOperatorCallback::OnCaptureEnded(int32_t captureId, const std::vector<CaptureEndedInfo> &infos)
406 {
407     for (auto it : infos) {
408         CAMERA_LOGE("captureId: %{public}d, streamId: %{public}d, count: %{public}d", captureId, it.streamId_,
409             it.frameCount_);
410     }
411     return HDI::Camera::V1_0::NO_ERROR;
412 }
413 
OnCaptureError(int32_t captureId, const std::vector<CaptureErrorInfo> &infos)414 int32_t Test::TestStreamOperatorCallback::OnCaptureError(int32_t captureId, const std::vector<CaptureErrorInfo> &infos)
415 {
416     for (auto it : infos) {
417         CAMERA_LOGE("captureId: %{public}d, streamId: %{public}d, error: %{public}d", captureId, it.streamId_,
418             it.error_);
419     }
420     return HDI::Camera::V1_0::NO_ERROR;
421 }
422 
OnFrameShutter(int32_t captureId, const std::vector<int32_t> &streamIds, uint64_t timestamp)423 int32_t Test::TestStreamOperatorCallback::OnFrameShutter(int32_t captureId,
424     const std::vector<int32_t> &streamIds, uint64_t timestamp)
425 {
426     (void)timestamp;
427     for (auto it : streamIds) {
428         CAMERA_LOGE("captureId: %{public}d, streamId: %{public}d", captureId, it);
429     }
430     return HDI::Camera::V1_0::NO_ERROR;
431 }
432 
OnError(ErrorType type, int32_t errorMsg)433 int32_t Test::DemoCameraDeviceCallback::OnError(ErrorType type, int32_t errorMsg)
434 {
435     CAMERA_LOGE("type: %{public}d, errorMsg: %{public}d", type, errorMsg);
436     return HDI::Camera::V1_0::NO_ERROR;
437 }
438 
OnResult(uint64_t timestamp, const std::vector<uint8_t> &result)439 int32_t Test::DemoCameraDeviceCallback::OnResult(uint64_t timestamp, const std::vector<uint8_t> &result)
440 {
441     if (Test::resultCallback_) {
442         std::shared_ptr<CameraMetadata> resultMeta;
443         MetadataUtils::ConvertVecToMetadata(result, resultMeta);
444         Test::resultCallback_(timestamp, resultMeta);
445     }
446     return HDI::Camera::V1_0::NO_ERROR;
447 }
448 
OnCameraStatus(const std::string& cameraId, CameraStatus status)449 int32_t Test::TestCameraHostCallback::OnCameraStatus(const std::string& cameraId, CameraStatus status)
450 {
451     CAMERA_LOGE("cameraId: %{public}s, status: %{public}d", cameraId.c_str(), status);
452     return HDI::Camera::V1_0::NO_ERROR;
453 }
454 
OnFlashlightStatus(const std::string& cameraId, FlashlightStatus status)455 int32_t Test::TestCameraHostCallback::OnFlashlightStatus(const std::string& cameraId, FlashlightStatus status)
456 {
457     CAMERA_LOGE("cameraId: %{public}s, status: %{public}d", cameraId.c_str(), status);
458     return HDI::Camera::V1_0::NO_ERROR;
459 }
460 
OnCameraEvent(const std::string& cameraId, CameraEvent event)461 int32_t Test::TestCameraHostCallback::OnCameraEvent(const std::string& cameraId, CameraEvent event)
462 {
463     CAMERA_LOGE("cameraId: %{public}s, status: %{public}d", cameraId.c_str(), event);
464     return HDI::Camera::V1_0::NO_ERROR;
465 }
466 
467 }