1/* 2 * Copyright (c) 2021 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 <common.h> 17#include "camera.h" 18 19namespace OHOS::Camera { 20uint64_t Test::GetCurrentLocalTimeStamp() 21{ 22 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp = 23 std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()); 24 auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()); 25 return static_cast<uint64_t>(tmp.count()); 26} 27 28void Test::CreateStreamOperatorCallback() 29{ 30#ifdef CAMERA_BUILT_ON_OHOS_LITE 31 streamOperatorCallback = std::make_shared<OHOS::Camera::HdiOperatorCallback>(this); 32#else 33 streamOperatorCallback = new HdiOperatorCallback(this); 34#endif 35} 36 37void Test::CreateDeviceCallback() 38{ 39#ifdef CAMERA_BUILT_ON_OHOS_LITE 40 deviceCallback = std::make_shared<CameraDeviceCallback>(); 41#else 42 deviceCallback = new CameraDeviceCallback(); 43#endif 44} 45 46void Test::CreateOfflineStreamOperatorCallback() 47{ 48#ifdef CAMERA_BUILT_ON_OHOS_LITE 49 offlineStreamOperatorCallback = std::make_shared<OHOS::Camera::StreamOperatorCallback>(); 50#else 51 offlineStreamOperatorCallback = streamOperatorCallback; 52#endif 53} 54 55void Test::StreamInfoFormat() 56{ 57#ifdef CAMERA_BUILT_ON_OHOS_LITE 58 streamInfo->format_ = IMAGE_PIXEL_FORMAT_NV21; 59#else 60 streamInfo->format_ = PIXEL_FMT_YCRCB_420_SP; 61#endif 62} 63 64int32_t Test::SaveYUV(const char* type, const void* buffer, int32_t size) 65{ 66 if (strncmp(type, "preview", strlen(type)) == 0) { 67 previewBufCnt += 1; 68 if (previewBufCnt % 8 != 0) { // 8:Save one frame every eight frames 69 std::cout << "receive preview buffer not save" << std::endl; 70 return 0; 71 } 72 } 73 char path[PATH_MAX] = {0}; 74#ifdef CAMERA_BUILT_ON_OHOS_LITE 75 if (strncmp(type, "preview", strlen(type)) == 0) { 76 system("mkdir -p /userdata/camera"); 77 char prefix[] = "/userdata/camera/"; 78 79 if (sprintf_s(path, sizeof(path) / sizeof(path[0]), "%s%s_%lld.yuv", 80 prefix, type, GetCurrentLocalTimeStamp()) < 0) { 81 CAMERA_LOGE("%s: sprintf path failed", __func__); 82 return 0; 83 } 84 } else { 85 system("mkdir -p /userdata/camera"); 86 char prefix[] = "/userdata/camera/"; 87 88 if (sprintf_s(path, sizeof(path) / sizeof(path[0]), "%s%s_%lld.jpg", 89 prefix, type, GetCurrentLocalTimeStamp()) < 0) { 90 CAMERA_LOGE("%s: sprintf path failed", __func__); 91 return 0; 92 } 93 } 94#else 95 if (strncmp(type, "preview", strlen(type)) == 0) { 96 system("mkdir -p /data/camera/preview"); 97 char prefix[] = "/data/camera/preview/"; 98 99 if (sprintf_s(path, sizeof(path) / sizeof(path[0]), "%s%s_%lld.yuv", 100 prefix, type, GetCurrentLocalTimeStamp()) < 0) { 101 CAMERA_LOGE("%s: sprintf path failed", __func__); 102 return 0; 103 } 104 } else { 105 system("mkdir -p /data/camera/capture"); 106 char prefix[] = "/data/camera/capture/"; 107 108 if (sprintf_s(path, sizeof(path) / sizeof(path[0]), "%s%s_%lld.jpg", 109 prefix, type, GetCurrentLocalTimeStamp()) < 0) { 110 CAMERA_LOGE("%s: sprintf path failed", __func__); 111 return 0; 112 } 113 } 114#endif 115 std::cout << "save yuv to file:" << path << std::endl; 116 int imgFd = open(path, O_RDWR | O_CREAT | O_APPEND, 00766); // 00766:file jurisdiction 117 if (imgFd == -1) { 118 std::cout << "open file failed, errno = " << strerror(errno) << std::endl; 119 return -1; 120 } 121 122 int32_t ret = write(imgFd, buffer, size); 123 if (ret == -1) { 124 std::cout << "write file failed, error = " << strerror(errno) << std::endl; 125 close(imgFd); 126 return -1; 127 } 128 close(imgFd); 129 return 0; 130} 131 132int32_t Test::SaveVideoFile(const char* type, const void* buffer, int32_t size, int32_t operationMode) 133{ 134 std::cout << "SaveVideoFile: operationMode = " << operationMode << " videoFd = "<< videoFd << std::endl; 135 if (operationMode == 0) { 136 char path[PATH_MAX] = {0}; 137#ifdef CAMERA_BUILT_ON_OHOS_LITE 138 system("mkdir -p /userdata/camera"); 139 char prefix[] = "/userdata/camera/"; 140 141 if (sprintf_s(path, sizeof(path) / sizeof(path[0]), "%s%s_%lld.h265", 142 prefix, type, GetCurrentLocalTimeStamp()) < 0) { 143 CAMERA_LOGE("%s: sprintf path failed", __func__); 144 return 0; 145 } 146#else 147 system("mkdir -p /data/camera/video"); 148 char prefix[] = "/data/camera/video/"; 149 150 if (sprintf_s(path, sizeof(path) / sizeof(path[0]), "%s%s_%lld.h265", 151 prefix, type, GetCurrentLocalTimeStamp()) < 0) { 152 CAMERA_LOGE("%s: sprintf path failed", __func__); 153 return 0; 154 } 155#endif 156 CAMERA_LOGI("%{public}s, save yuv to file %{public}s", __FUNCTION__, path); 157 videoFd = open(path, O_RDWR | O_CREAT, 00766); // 00766:file jurisdiction 158 if (videoFd == -1) { 159 std::cout << "open file failed, errno = " << strerror(errno) << std::endl; 160 return -1; 161 } 162 } else if (operationMode == 1 && videoFd != -1) { 163 int32_t ret = write(videoFd, buffer, size); 164 if (ret == -1) { 165 std::cout << "write file failed, error = " << strerror(errno) << std::endl; 166 close(videoFd); 167 videoFd = -1; 168 return -1; 169 } 170 } else { 171 if (videoFd != -1) { 172 close(videoFd); 173 videoFd = -1; 174 } 175 } 176 return 0; 177} 178 179void Test::Init() 180{ 181#ifdef CAMERA_BUILT_ON_OHOS_LITE 182 if (service == nullptr) { 183 service = CameraHost::CreateCameraHost(); 184 if (service == nullptr) { 185 std::cout << "==========[test log]ICameraHost get failed."<< std::endl; 186 } else { 187 std::cout << "==========[test log]ICameraHost get success."<< std::endl; 188 } 189 } 190 hostCallback = std::make_shared<HdiHostCallback>(this); 191#else 192 if (service == nullptr) { 193 service = ICameraHost::Get("camera_service"); 194 if (service == nullptr) { 195 std::cout << "==========[test log]ICameraHost get failed."<< std::endl; 196 } else { 197 std::cout << "==========[test log]ICameraHost get success."<< std::endl; 198 } 199 ASSERT_TRUE(service != nullptr); 200 } 201 hostCallback = new HdiHostCallback(this); 202#endif 203 service->SetCallback(hostCallback); 204} 205 206void Test::GetCameraAbility() 207{ 208 if (cameraDevice == nullptr) { 209 rc = service->GetCameraIds(cameraIds); 210 if (rc != Camera::NO_ERROR) { 211 std::cout << "==========[test log]GetCameraIds failed." << std::endl; 212 return; 213 } else { 214 std::cout << "==========[test log]GetCameraIds success." << std::endl; 215 } 216 GetCameraMetadata(); 217 } 218} 219 220void Test::GetCameraMetadata() 221{ 222 rc = service->GetCameraAbility(cameraIds.front(), ability); 223 if (rc != Camera::NO_ERROR) { 224 std::cout << "==========[test log]GetCameraAbility failed, rc = " << rc << std::endl; 225 } 226 common_metadata_header_t* data = ability->get(); 227 camera_metadata_item_t entry; 228 int ret = FindCameraMetadataItem(data, OHOS_CONTROL_AE_AVAILABLE_MODES, &entry); 229 if (ret == 0) { 230 std::cout << "==========[test log] get OHOS_CONTROL_AE_AVAILABLE_MODES success" << std::endl; 231 } 232} 233 234void Test::Open() 235{ 236 if (cameraDevice == nullptr) { 237 service->GetCameraIds(cameraIds); 238#ifdef CAMERA_BUILT_ON_OHOS_LITE 239 deviceCallback = std::make_shared<HdiDeviceCallback>(this); 240#else 241 deviceCallback = new HdiDeviceCallback(this); 242#endif 243 rc = service->OpenCamera(cameraIds.front(), deviceCallback, cameraDevice); 244 if (rc != Camera::NO_ERROR || cameraDevice == nullptr) { 245 std::cout << "==========[test log]OpenCamera failed, rc = " << rc << std::endl; 246 return; 247 } 248 std::cout << "==========[test log]OpenCamera success." << std::endl; 249 GetCameraMetadata(); 250 } 251} 252 253void Test::Close() 254{ 255 if (cameraDevice != nullptr) { 256 cameraDevice->Close(); 257 std::cout << "cameraDevice->Close" << std::endl; 258 cameraDevice = nullptr; 259 } 260} 261 262void Test::StartStream(std::vector<Camera::StreamIntent> intents) 263{ 264 EXPECT_EQ(true, cameraDevice != nullptr); 265 CreateStreamOperatorCallback(); 266 rc = cameraDevice->GetStreamOperator(streamOperatorCallback, streamOperator); 267 EXPECT_EQ(true, rc == Camera::NO_ERROR); 268 if (rc == Camera::NO_ERROR) { 269 std::cout << "==========[test log]GetStreamOperator success." << std::endl; 270 } else { 271 std::cout << "==========[test log]GetStreamOperator fail, rc = " << rc << std::endl; 272 } 273 streamInfo = std::make_shared<Camera::StreamInfo>(); 274 streamInfo_video = std::make_shared<Camera::StreamInfo>(); 275 streamInfo_capture = std::make_shared<Camera::StreamInfo>(); 276 for (const auto& intent : intents) { 277 if (intent == 0) { 278 streamInfo->streamId_ = streamId_preview; 279 streamInfo->width_ = 640; // 640:width of stream 280 streamInfo->height_ = 480; // 480: height of stream 281 streamInfo->dataspace_ = 8; // 8:dataspace of stream 282 streamInfo->intent_ = intent; 283 streamInfo->tunneledMode_ = 5; // 5:tunneledMode of stream 284 StreamInfoFormat(); 285 std::shared_ptr<StreamConsumer> consumer_pre = std::make_shared<StreamConsumer>(); 286 std::cout << "==========[test log]received a preview buffer ... 0" << std::endl; 287#ifdef CAMERA_BUILT_ON_OHOS_LITE 288 streamInfo->bufferQueue_ = consumer_pre->CreateProducer([this](OHOS::SurfaceBuffer* buffer) { 289 SaveYUV("preview", buffer->GetVirAddr(), buffer->GetSize()); 290 }); 291#else 292 streamInfo->bufferQueue_ = consumer_pre->CreateProducer([this](void* addr, uint32_t size) { 293 SaveYUV("preview", addr, size); 294 }); 295#endif 296 streamInfo->bufferQueue_->SetQueueSize(8); // 8:bufferqueue size 297 consumerMap_[intent] = consumer_pre; 298 streamInfos.push_back(streamInfo); 299 } else if (intent == 1) { 300 streamInfo_video->streamId_ = streamId_video; 301 streamInfo_video->width_ = 1280; // 1280:width of stream 302 streamInfo_video->height_ = 960; // 960: height of stream 303 streamInfo_video->dataspace_ = 8; // 8:dataspace of stream 304 streamInfo_video->intent_ = intent; 305 streamInfo_video->encodeType_ = ENCODE_TYPE_H265; 306 streamInfo_video->tunneledMode_ = 5; // 5:tunneledMode of stream 307#ifdef CAMERA_BUILT_ON_OHOS_LITE 308 streamInfo_video->format_ = IMAGE_PIXEL_FORMAT_NV21; 309#else 310 streamInfo_video->format_ = PIXEL_FMT_YCRCB_420_SP; 311#endif 312 std::shared_ptr<StreamConsumer> consumer_video = std::make_shared<StreamConsumer>(); 313 std::cout << "==========[test log]received a video buffer ... 1" << std::endl; 314 SaveVideoFile("video", nullptr, 0, 0); 315#ifdef CAMERA_BUILT_ON_OHOS_LITE 316 streamInfo_video->bufferQueue_ = consumer_video->CreateProducer([this](OHOS::SurfaceBuffer* buffer) { 317 int32_t size = 0; 318 buffer->GetInt32(OHOS::Camera::VIDEO_KEY_INFO_DATA_SIZE, size); 319 SaveVideoFile("video", buffer->GetVirAddr(), size, 1); 320 }); 321#else 322 streamInfo_video->bufferQueue_ = consumer_video->CreateProducer([this](void* addr, uint32_t size) { 323 SaveVideoFile("video", addr, size, 1); 324 }); 325#endif 326 streamInfo_video->bufferQueue_->SetQueueSize(8); // 8:bufferqueue size 327 consumerMap_[intent] = consumer_video; 328 streamInfos.push_back(streamInfo_video); 329 } else { 330 streamInfo_capture->streamId_ = streamId_capture; 331 streamInfo_capture->width_ = 1280; // 1280:width of stream 332 streamInfo_capture->height_ = 960; // 960: height of stream 333 streamInfo_capture->dataspace_ = 8; // 8:dataspace of stream 334 streamInfo_capture->intent_ = intent; 335 streamInfo_capture->encodeType_ = ENCODE_TYPE_JPEG; 336 streamInfo_capture->tunneledMode_ = 5; // 5:tunneledMode of stream 337#ifdef CAMERA_BUILT_ON_OHOS_LITE 338 streamInfo_capture->format_ = IMAGE_PIXEL_FORMAT_NV21; 339#else 340 streamInfo_capture->format_ = PIXEL_FMT_YCRCB_420_SP; 341#endif 342 std::shared_ptr<StreamConsumer> consumer_capture = std::make_shared<StreamConsumer>(); 343 std::cout << "==========[test log]received a capture buffer ... 2" << std::endl; 344#ifdef CAMERA_BUILT_ON_OHOS_LITE 345 streamInfo_capture->bufferQueue_ = consumer_capture->CreateProducer([this](OHOS::SurfaceBuffer* buffer) { 346 SaveYUV("capture", buffer->GetVirAddr(), buffer->GetSize()); 347 }); 348#else 349 streamInfo_capture->bufferQueue_ = consumer_capture->CreateProducer([this](void* addr, uint32_t size) { 350 SaveYUV("capture", addr, size); 351 }); 352#endif 353 streamInfo_capture->bufferQueue_->SetQueueSize(8); // 8:bufferqueue size 354 consumerMap_[intent] = consumer_capture; 355 streamInfos.push_back(streamInfo_capture); 356 } 357 } 358 rc = streamOperator->CreateStreams(streamInfos); 359 EXPECT_EQ(false, rc != Camera::NO_ERROR); 360 if (rc == Camera::NO_ERROR) { 361 std::cout << "==========[test log]CreateStreams success." << std::endl; 362 } else { 363 std::cout << "==========[test log]CreateStreams fail, rc = " << rc << std::endl; 364 } 365 366 rc = streamOperator->CommitStreams(Camera::NORMAL, ability); 367 EXPECT_EQ(false, rc != Camera::NO_ERROR); 368 if (rc == Camera::NO_ERROR) { 369 std::cout << "==========[test log]CommitStreams success." << std::endl; 370 } else { 371 std::cout << "==========[test log]CommitStreams fail, rc = " << rc << std::endl; 372 } 373 sleep(2); // 2:The program waits two seconds 374 std::vector<std::shared_ptr<Camera::StreamInfo>>().swap(streamInfos); 375} 376 377void Test::StartCapture(int streamId, int captureId, bool shutterCallback, bool isStreaming) 378{ 379 captureInfo = std::make_shared<Camera::CaptureInfo>(); 380 captureInfo->streamIds_.push_back(streamId); 381 captureInfo->captureSetting_ = ability; 382 captureInfo->enableShutterCallback_ = shutterCallback; 383 rc = streamOperator->Capture(captureId, captureInfo, isStreaming); 384 EXPECT_EQ(true, rc == Camera::NO_ERROR); 385 if (rc == Camera::NO_ERROR) { 386 std::cout << "==========[test log]check Capture: Capture success, " << captureId << std::endl; 387 } else { 388 std::cout << "==========[test log]check Capture: Capture fail, rc = " << rc << std::endl; 389 } 390 sleep(1); // 1:Wait 1 seconds for the program to run 391} 392 393void Test::StopStream(std::vector<int>& captureIds, std::vector<int>& streamIds) 394{ 395 if (captureIds.size() > 0) { 396 std::cout << "captureIds.size() = " << captureIds.size() << std::endl; 397 for (auto &captureId : captureIds) { 398 std::cout << "captureId = " << captureId << std::endl; 399 rc = streamOperator->CancelCapture(captureId); 400 EXPECT_EQ(true, rc == Camera::NO_ERROR); 401 if (rc == Camera::NO_ERROR) { 402 std::cout << "==========[test log]check Capture: CancelCapture success," << captureId << std::endl; 403 } else { 404 std::cout << "==========[test log]check Capture: CancelCapture fail, rc = " << rc << std::endl; 405 std::cout << "captureId = " << captureId << std::endl; 406 } 407 if (captureId == captureId_preview) { 408 captureId_preview++; 409 } else if (captureId == captureId_capture) { 410 captureId_capture++; 411 } else if (captureId == captureId_video) { 412 captureId_video++; 413 } 414 } 415 } 416 SaveVideoFile("video", nullptr, 0, 2); // 2:Operation Mode 417 if (streamIds.size() > 0) { 418 rc = streamOperator->ReleaseStreams(streamIds); 419 EXPECT_EQ(true, rc == Camera::NO_ERROR); 420 if (rc == Camera::NO_ERROR) { 421 std::cout << "==========[test log]check Capture: ReleaseStreams success." << std::endl; 422 } else { 423 std::cout << "==========[test log]check Capture: ReleaseStreams fail, rc = " << rc << std::endl; 424 } 425 } 426 streamIds.clear(); 427} 428 429void Test::StopConsumer(std::vector<Camera::StreamIntent> intents) 430{ 431 for (const auto& intent : intents) { 432 consumerMap_[intent]->StopConsumer(); 433 } 434} 435 436void Test::StopOfflineStream(int captureId) 437{ 438 captureId--; 439 rc = offlineStreamOperator->CancelCapture(captureId); 440 EXPECT_EQ(rc, Camera::NO_ERROR); 441 if (rc == Camera::NO_ERROR) { 442 std::cout << "==========[test log]check offline: CancelCapture success," << captureId << std::endl; 443 } else { 444 std::cout << "==========[test log]check offline: CancelCapture fail, rc = " << rc; 445 std::cout << "captureId = " << captureId << std::endl; 446 } 447 rc = offlineStreamOperator->Release(); 448 EXPECT_EQ(rc, Camera::NO_ERROR); 449 if (rc == Camera::NO_ERROR) { 450 std::cout << "==========[test log]Check offline stream: offline Release success." << std::endl; 451 } else { 452 std::cout << "==========[test log]Check offline stream: offline Release fail, rc = " << rc << std::endl; 453 } 454} 455 456#ifdef CAMERA_BUILT_ON_OHOS_LITE 457std::shared_ptr<OHOS::Surface> Test::StreamConsumer::CreateProducer(std::function<void(OHOS::SurfaceBuffer*)> callback) 458{ 459 Surface* surface = OHOS::Surface::CreateSurface(); 460 consumer_ = std::shared_ptr<OHOS::Surface>(surface); 461 if (consumer_ == nullptr) { 462 return nullptr; 463 } 464 callback_ = callback; 465 466 consumerThread_ = new std::thread([this] { 467 while (running_ == true) { 468 OHOS::SurfaceBuffer* buffer = consumer_->AcquireBuffer(); 469 if (buffer != nullptr) { 470 if (callback_ != nullptr) { 471 callback_(buffer); 472 } 473 consumer_->ReleaseBuffer(buffer); 474 } 475 } 476 }); 477 return consumer_; 478} 479#else 480OHOS::sptr<OHOS::IBufferProducer> Test::StreamConsumer::CreateProducer(std::function<void(void*, uint32_t)> callback) 481{ 482 consumer_ = OHOS::Surface::CreateSurfaceAsConsumer(); 483 if (consumer_ == nullptr) { 484 return nullptr; 485 } 486 sptr<IBufferConsumerListener> listener = new TestBufferConsumerListener(); 487 CHECK_IF_PTR_NULL_RETURN_VALUE(listener, nullptr); 488 consumer_->RegisterConsumerListener(listener); 489 auto producer = consumer_->GetProducer(); 490 std::cout << "create a buffer queue producer:" << producer.GetRefPtr() << std::endl; 491 if (producer == nullptr) { 492 return nullptr; 493 } 494 callback_ = callback; 495 running_ = true; 496 consumerThread_ = new std::thread([this] { 497 int32_t flushFence = 0; 498 int64_t timestamp = 0; 499 OHOS::Rect damage; 500 OHOS::BufferRequestConfig config; 501 while (running_ == true) { 502 OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr; 503 consumer_->AcquireBuffer(buffer, flushFence, timestamp, damage); 504 if (buffer != nullptr) { 505 void* addr = buffer->GetVirAddr(); 506 uint32_t size = buffer->GetSize(); 507 uint64_t pa = buffer->GetPhyAddr(); 508 CAMERA_LOGI("consumer receive buffer add = %{public}llu", pa); 509 if (callback_ != nullptr) { 510 callback_(addr, size); 511 } 512 consumer_->ReleaseBuffer(buffer, -1); 513 CAMERA_LOGI("consumer release buffer add = %{public}llu", pa); 514 shotCount_--; 515 if (shotCount_ == 0) { 516 std::unique_lock<std::mutex> l(l_); 517 cv_.notify_one(); 518 } 519 } 520 if (running_ == false) { 521 break; 522 } 523 } 524 return; 525 }); 526 return producer; 527} 528#endif 529 530void Test::StreamConsumer::StopConsumer() 531{ 532 running_ = false; 533} 534} 535