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 20namespace OHOS::Camera { 21Test::ResultCallback Test::resultCallback_ = 0; 22 23uint64_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 31int32_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 70void 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 91void 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 128void 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 146void Test::Close() 147{ 148 if (cameraDevice != nullptr) { 149 cameraDevice->Close(); 150 cameraDevice = nullptr; 151 } 152} 153 154void 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 258void 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 275void 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 300void 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 325OHOS::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 386OHOS::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 397int32_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 405int32_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 414int32_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 423int32_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 433int32_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 439int32_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 449int32_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 455int32_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 461int32_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}