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