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 }