diff --git a/camera_hdf/hdi_impl/src/dstream_operator/dstream_operator.cpp b/camera_hdf/hdi_impl/src/dstream_operator/dstream_operator.cpp index 362fa246f766e7593a8b23e2c2bc7b330cd34de6..21af8d7640b6d29ab9d715628463aaed5850e0f9 100644 --- a/camera_hdf/hdi_impl/src/dstream_operator/dstream_operator.cpp +++ b/camera_hdf/hdi_impl/src/dstream_operator/dstream_operator.cpp @@ -50,7 +50,7 @@ CamRetCode DStreamOperator::IsStreamsSupported(OperationMode mode, return CamRetCode::INVALID_ARGUMENT; } } - return CamRetCode::METHOD_NOT_SUPPORTED; + return CamRetCode::NO_ERROR; } CamRetCode DStreamOperator::CreateStreams(const std::vector>& streamInfos) diff --git a/camera_hdf/interfaces/hdi_ipc/client/provider/dcamera_provider_proxy.cpp b/camera_hdf/interfaces/hdi_ipc/client/provider/dcamera_provider_proxy.cpp index 6b67de6aaf3cefe902519543908f1b8bb66decab..ec5e2120f60d34c76beb3e6d3d14be64c513a3b3 100644 --- a/camera_hdf/interfaces/hdi_ipc/client/provider/dcamera_provider_proxy.cpp +++ b/camera_hdf/interfaces/hdi_ipc/client/provider/dcamera_provider_proxy.cpp @@ -276,6 +276,7 @@ DCamRetCode DCameraProviderProxy::Notify(const std::shared_ptr &dhBase, return static_cast(reply.ReadInt32()); } +#ifdef BALTIMORE_CAMERA void* DCameraProviderProxy::DCameraMemoryMap(const BufferHandle *buffer) { if (buffer == nullptr) { @@ -293,6 +294,22 @@ void* DCameraProviderProxy::DCameraMemoryMap(const BufferHandle *buffer) } return virAddr; } +#else +void* DCameraProviderProxy::DCameraMemoryMap(const BufferHandle *buffer) +{ + if (buffer == nullptr) { + DHLOGE("mmap the buffer handle is NULL"); + return nullptr; + } + + void* virAddr = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, buffer->fd, 0); + if (virAddr == MAP_FAILED) { + DHLOGE("mmap failed errno %s, fd : %d", strerror(errno), buffer->fd); + return nullptr; + } + return virAddr; +} +#endif void DCameraProviderProxy::DCameraMemoryUnmap(BufferHandle *buffer) { diff --git a/services/cameraservice/cameraoperator/client/BUILD.gn b/services/cameraservice/cameraoperator/client/BUILD.gn index c92d304e9351c440f74a0c02dc3cb17f40e7b3b5..3bd8ed81973cc29e696c1ebe4d8bb0d2dc6805fb 100644 --- a/services/cameraservice/cameraoperator/client/BUILD.gn +++ b/services/cameraservice/cameraoperator/client/BUILD.gn @@ -13,7 +13,8 @@ import("//build/ohos.gni") import("//build/ohos_var.gni") -import("//foundation/distributedhardware/distributedcamera/distributedcamera.gni") +import( + "//foundation/distributedhardware/distributedcamera/distributedcamera.gni") ohos_shared_library("distributed_camera_client") { include_dirs = [ @@ -47,23 +48,34 @@ ohos_shared_library("distributed_camera_client") { ] sources = [ + "src/callback/dcamera_input_callback.cpp", + "src/callback/dcamera_manager_callback.cpp", + "src/callback/dcamera_photo_callback.cpp", + "src/callback/dcamera_preview_callback.cpp", + "src/callback/dcamera_session_callback.cpp", + "src/callback/dcamera_video_callback.cpp", + ] + + if (device_name == "baltimore") { + sources += [ "src/dcamera_client.cpp", - "src/callback/dcamera_input_callback.cpp", - "src/callback/dcamera_manager_callback.cpp", - "src/callback/dcamera_photo_callback.cpp", - "src/callback/dcamera_preview_callback.cpp", - "src/callback/dcamera_session_callback.cpp", - "src/callback/dcamera_video_callback.cpp", "src/listener/dcamera_photo_surface_listener.cpp", "src/listener/dcamera_video_surface_listener.cpp", - ] + ] + } else { + sources += [ + "src/dcamera_client_common.cpp", + "src/listener/dcamera_photo_surface_listener_common.cpp", + "src/listener/dcamera_video_surface_listener_common.cpp", + ] + } deps = [ - "${fwk_utils_path}:distributedhardwareutils", - "${common_path}:distributed_camera_utils", - "${graphicstandard_path}:libsurface", "${camerastandard_path}/frameworks/native/camera:camera_framework", "${camerastandard_path}/frameworks/native/metadata:metadata", + "${common_path}:distributed_camera_utils", + "${fwk_utils_path}:distributedhardwareutils", + "${graphicstandard_path}:libsurface", "//third_party/jsoncpp:jsoncpp", "//utils/native/base:utils", ] @@ -82,4 +94,4 @@ ohos_shared_library("distributed_camera_client") { subsystem_name = "distributedhardware" part_name = "distributed_camera" -} \ No newline at end of file +} diff --git a/services/cameraservice/cameraoperator/client/src/dcamera_client_common.cpp b/services/cameraservice/cameraoperator/client/src/dcamera_client_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b87edf7dfe2a549d00b71dd830c0dbbc2ee712fe --- /dev/null +++ b/services/cameraservice/cameraoperator/client/src/dcamera_client_common.cpp @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dcamera_client.h" + +#include "anonymous_string.h" +#include "dcamera_input_callback.h" +#include "dcamera_manager_callback.h" +#include "dcamera_photo_callback.h" +#include "dcamera_preview_callback.h" +#include "dcamera_session_callback.h" +#include "dcamera_utils_tools.h" +#include "dcamera_video_callback.h" +#include "distributed_camera_constants.h" +#include "distributed_camera_errno.h" +#include "distributed_hardware_log.h" +#include "metadata_utils.h" + +namespace OHOS { +namespace DistributedHardware { +DCameraClient::DCameraClient(const std::string& dhId) +{ + DHLOGI("DCameraClientCommon Constructor dhId: %s", GetAnonyString(dhId).c_str()); + cameraId_ = dhId.substr(CAMERA_ID_PREFIX.size()); + isInit_ = false; +} + +DCameraClient::~DCameraClient() +{ + if (isInit_) { + UnInit(); + } +} + +int32_t DCameraClient::Init() +{ + DHLOGI("DCameraClientCommon::Init cameraId: %s", GetAnonyString(cameraId_).c_str()); + cameraManager_ = CameraStandard::CameraManager::GetInstance(); + if (cameraManager_ == nullptr) { + DHLOGE("DCameraClientCommon::Init cameraManager getInstance failed"); + return DCAMERA_BAD_VALUE; + } + cameraManager_->SetCallback(std::make_shared()); + + std::vector> cameraList = cameraManager_->GetCameras(); + DHLOGI("DCameraClientCommon::Init camera size: %d", cameraList.size()); + for (auto& info : cameraList) { + if (info->GetID() == cameraId_) { + DHLOGI("DCameraClientCommon::Init cameraInfo get id: %s", GetAnonyString(info->GetID()).c_str()); + cameraInfo_ = info; + break; + } + } + if (cameraInfo_ == nullptr) { + DHLOGE("DCameraClientCommon::Init cameraInfo is null"); + return DCAMERA_BAD_VALUE; + } + + isInit_ = true; + DHLOGI("DCameraClientCommon::Init %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::UnInit() +{ + DHLOGI("DCameraClientCommon::UnInit cameraId: %s", GetAnonyString(cameraId_).c_str()); + if (cameraManager_ != nullptr) { + DHLOGI("DCameraClientCommon::UnInit unregister cameraManager callback"); + cameraManager_->SetCallback(nullptr); + } + + isInit_ = false; + cameraInfo_ = nullptr; + cameraManager_ = nullptr; + DHLOGI("DCameraClientCommon::UnInit %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::UpdateSettings(std::vector>& settings) +{ + DHLOGI("DCameraClientCommon::UpdateCameraSettings cameraId: %s", GetAnonyString(cameraId_).c_str()); + for (auto& setting : settings) { + switch (setting->type_) { + case UPDATE_METADATA: { + DHLOGI("DCameraClientCommon::UpdateCameraSettings %s update metadata settings", + GetAnonyString(cameraId_).c_str()); + std::string metadataStr = Base64Decode(setting->value_); + int32_t ret = ((sptr &)cameraInput_)->SetCameraSettings(metadataStr); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::UpdateSettings %s update metadata settings failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + break; + } + default: { + DHLOGE("DCameraClientCommon::UpdateSettings unknown setting type"); + break; + } + } + } + DHLOGI("DCameraClientCommon::UpdateCameraSettings %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::StartCapture(std::vector>& captureInfos) +{ + DHLOGI("DCameraClientCommon::StartCapture cameraId: %s", GetAnonyString(cameraId_).c_str()); + if ((photoOutput_ == nullptr) && (previewOutput_ == nullptr)) { + DHLOGI("DCameraClientCommon::StartCapture %s config capture session", GetAnonyString(cameraId_).c_str()); + int32_t ret = ConfigCaptureSession(captureInfos); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::StartCapture config capture session failed, cameraId: %s, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + } + + for (auto& info : captureInfos) { + if ((info->streamType_ == CONTINUOUS_FRAME) || (!info->isCapture_)) { + continue; + } + int32_t ret = StartCaptureInner(info); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::StartCapture failed, cameraId: %s, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + } + DHLOGI("DCameraClientCommon::StartCapture %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::StopCapture() +{ + DHLOGI("DCameraClientCommon::StopCapture cameraId: %s", GetAnonyString(cameraId_).c_str()); + if (captureSession_ != nullptr) { + DHLOGI("DCameraClientCommon::StopCapture %s stop captureSession", GetAnonyString(cameraId_).c_str()); + int32_t ret = captureSession_->Stop(); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::StopCapture captureSession stop failed, cameraId: %s, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + } + DHLOGI("DCameraClientCommon::StopCapture %s release captureSession", GetAnonyString(cameraId_).c_str()); + captureSession_->Release(); + } + + if (cameraInput_ != nullptr) { + DHLOGI("DCameraClientCommon::StopCapture %s release cameraInput", GetAnonyString(cameraId_).c_str()); + cameraInput_->Release(); + } + + photoOutput_ = nullptr; + previewOutput_ = nullptr; + cameraInput_ = nullptr; + captureSession_ = nullptr; + DHLOGI("DCameraClientCommon::StopCapture %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::SetStateCallback(std::shared_ptr& callback) +{ + DHLOGI("DCameraClientCommon::SetStateCallback cameraId: %s", GetAnonyString(cameraId_).c_str()); + if (callback == nullptr) { + DHLOGE("DCameraClientCommon::SetStateCallback %s unregistering state callback", + GetAnonyString(cameraId_).c_str()); + } + stateCallback_ = callback; + return DCAMERA_OK; +} + +int32_t DCameraClient::SetResultCallback(std::shared_ptr& callback) +{ + DHLOGI("DCameraClientCommon::SetResultCallback cameraId: %s", GetAnonyString(cameraId_).c_str()); + if (callback == nullptr) { + DHLOGE("DCameraClientCommon::SetResultCallback %s unregistering result callback", + GetAnonyString(cameraId_).c_str()); + } + resultCallback_ = callback; + return DCAMERA_OK; +} + +int32_t DCameraClient::ConfigCaptureSession(std::vector>& captureInfos) +{ + DHLOGI("DCameraClientCommon::ConfigCaptureSession cameraId: %s", GetAnonyString(cameraId_).c_str()); + cameraInput_ = cameraManager_->CreateCameraInput(cameraInfo_); + if (cameraInput_ == nullptr) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s create cameraInput failed", + GetAnonyString(cameraId_).c_str()); + return DCAMERA_BAD_VALUE; + } + std::shared_ptr inputCallback = std::make_shared(stateCallback_); + ((sptr &)cameraInput_)->SetErrorCallback(inputCallback); + + captureSession_ = cameraManager_->CreateCaptureSession(); + if (captureSession_ == nullptr) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s create captureSession failed", + GetAnonyString(cameraId_).c_str()); + return DCAMERA_BAD_VALUE; + } + captureSession_->SetCallback(std::make_shared(stateCallback_)); + + int32_t ret = CreateCaptureOutput(captureInfos); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession create capture output failed, cameraId: %s, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + + return ConfigCaptureSessionInner(); +} + +int32_t DCameraClient::ConfigCaptureSessionInner() +{ + int32_t ret = captureSession_->BeginConfig(); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s config captureSession failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + + ret = captureSession_->AddInput(cameraInput_); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s add cameraInput to captureSession failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + + if (photoOutput_ != nullptr) { + ret = captureSession_->AddOutput(photoOutput_); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s add photoOutput to captureSession failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + } + + if (previewOutput_ != nullptr) { + ret = captureSession_->AddOutput(previewOutput_); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s add previewOutput to captureSession failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + } + + ret = captureSession_->CommitConfig(); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s commit captureSession failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + + ret = captureSession_->Start(); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::ConfigCaptureSession %s start captureSession failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + } + + DHLOGI("DCameraClientCommon::ConfigCaptureSession %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::CreateCaptureOutput(std::vector>& captureInfos) +{ + if (captureInfos.empty()) { + DHLOGE("DCameraClientCommon::CreateCaptureOutput no capture info, cameraId: %s", + GetAnonyString(cameraId_).c_str()); + return DCAMERA_BAD_VALUE; + } + + for (auto& info : captureInfos) { + if (info->streamType_ == SNAPSHOT_FRAME) { + int32_t ret = CreatePhotoOutput(info); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::CreateCaptureOutput %s create photo output failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + } else if (info->streamType_ == CONTINUOUS_FRAME) { + int32_t ret = CreateVideoOutput(info); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::CreateCaptureOutput %s create video output failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + } else { + DHLOGE("DCameraClientCommon::CreateCaptureOutput unknown stream type"); + return DCAMERA_BAD_VALUE; + } + } + return DCAMERA_OK; +} + +int32_t DCameraClient::CreatePhotoOutput(std::shared_ptr& info) +{ + DHLOGI("DCameraClientCommon::CreatePhotoOutput camId: %s, w: %d, h: %d, f: %d, stream: %d, isCapture: %d", + GetAnonyString(cameraId_).c_str(), info->width_, info->height_, + camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888, info->streamType_, info->isCapture_); + photoSurface_ = Surface::CreateSurfaceAsConsumer(); + photoSurface_->SetDefaultWidthAndHeight(info->width_, info->height_); + photoSurface_->SetUserData(CAMERA_SURFACE_FORMAT, std::to_string(camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888)); + photoListener_ = std::make_shared(photoSurface_, resultCallback_); + photoSurface_->RegisterConsumerListener((sptr &)photoListener_); + photoOutput_ = cameraManager_->CreatePhotoOutput(photoSurface_); + if (photoOutput_ == nullptr) { + DHLOGE("DCameraClientCommon::CreatePhotoOutput %s create photo output failed", + GetAnonyString(cameraId_).c_str()); + return DCAMERA_BAD_VALUE; + } + std::shared_ptr photoCallback = std::make_shared(stateCallback_); + ((sptr &)photoOutput_)->SetCallback(photoCallback); + DHLOGI("DCameraClientCommon::CreatePhotoOutput %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::CreateVideoOutput(std::shared_ptr& info) +{ + DHLOGI("DCameraClientCommon::CreatePreviewOutput camId: %s, w: %d, h: %d, f: %d, stream: %d, isCapture: %d", + GetAnonyString(cameraId_).c_str(), info->width_, info->height_, + camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888, info->streamType_, info->isCapture_); + videoSurface_ = Surface::CreateSurfaceAsConsumer(); + videoSurface_->SetDefaultWidthAndHeight(info->width_, info->height_); + videoSurface_->SetUserData(CAMERA_SURFACE_FORMAT, std::to_string(camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888)); + videoListener_ = std::make_shared(videoSurface_, resultCallback_); + videoSurface_->RegisterConsumerListener((sptr &)videoListener_); + previewOutput_ = cameraManager_->CreateCustomPreviewOutput(videoSurface_, info->width_, info->height_); + if (previewOutput_ == nullptr) { + DHLOGE("DCameraClientCommon::CreatePreviewOutput %s create preview output failed", + GetAnonyString(cameraId_).c_str()); + return DCAMERA_BAD_VALUE; + } + std::shared_ptr previewCallback = std::make_shared(stateCallback_); + ((sptr &)previewOutput_)->SetCallback(previewCallback); + DHLOGI("DCameraClientCommon::CreatePreviewOutput %s success", GetAnonyString(cameraId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraClient::StartCaptureInner(std::shared_ptr& info) +{ + switch (info->streamType_) { + case CONTINUOUS_FRAME: { + return StartVideoOutput(); + } + case SNAPSHOT_FRAME: { + return StartPhotoOutput(info); + } + default: { + DHLOGE("DCameraClientCommon::StartCaptureInner unknown stream type"); + return DCAMERA_BAD_VALUE; + } + } +} + +int32_t DCameraClient::StartPhotoOutput(std::shared_ptr& info) +{ + DHLOGI("DCameraClientCommon::StartPhotoOutput cameraId: %s", GetAnonyString(cameraId_).c_str()); + if (photoOutput_ == nullptr) { + DHLOGE("DCameraClientCommon::StartPhotoOutput photoOutput is null"); + return DCAMERA_BAD_VALUE; + } + int32_t ret = ((sptr &)photoOutput_)->Capture(); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::StartPhotoOutput %s photoOutput capture failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + return DCAMERA_OK; +} + +int32_t DCameraClient::StartVideoOutput() +{ + DHLOGI("DCameraClientCommon::StartVideoOutput cameraId: %s", GetAnonyString(cameraId_).c_str()); + if (videoOutput_ == nullptr) { + DHLOGE("DCameraClientCommon::StartVideoOutput videoOutput is null"); + return DCAMERA_BAD_VALUE; + } + int32_t ret = ((sptr &)videoOutput_)->Start(); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraClientCommon::StartVideoOutput %s videoOutput start failed, ret: %d", + GetAnonyString(cameraId_).c_str(), ret); + return ret; + } + return DCAMERA_OK; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/cameraservice/cameraoperator/client/src/listener/dcamera_photo_surface_listener_common.cpp b/services/cameraservice/cameraoperator/client/src/listener/dcamera_photo_surface_listener_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c60a198d82906ddbbefb1801f32e12580ccaac7 --- /dev/null +++ b/services/cameraservice/cameraoperator/client/src/listener/dcamera_photo_surface_listener_common.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dcamera_photo_surface_listener.h" + +#include + +#include "data_buffer.h" +#include "distributed_camera_errno.h" +#include "distributed_hardware_log.h" + +namespace OHOS { +namespace DistributedHardware { +DCameraPhotoSurfaceListener::DCameraPhotoSurfaceListener(const sptr& surface, + const std::shared_ptr& callback) : surface_(surface), callback_(callback) +{ +} + +void DCameraPhotoSurfaceListener::OnBufferAvailable() +{ + DHLOGI("DCameraPhotoSurfaceListenerCommon::OnBufferAvailable"); + OHOS::sptr buffer = nullptr; + int32_t flushFence = 0; + int64_t timestamp = 0; + OHOS::Rect damage; + + do { + surface_->AcquireBuffer(buffer, flushFence, timestamp, damage); + if (buffer == nullptr) { + DHLOGE("DCameraPhotoSurfaceListenerCommon AcquireBuffer failed"); + break; + } + + int32_t size; + buffer->ExtraGet("dataSize", size); + if (size <= 0) { + size = static_cast(buffer->GetSize()); + } + + char *address = static_cast(buffer->GetVirAddr()); + if ((address == nullptr) || (size <= 0)) { + DHLOGE("DCameraPhotoSurfaceListenerCommon invalid params, size: %d", size); + break; + } + + DHLOGI("DCameraPhotoSurfaceListenerCommon size: %d", size); + std::shared_ptr dataBuffer = std::make_shared(size); + int32_t ret = memcpy_s(dataBuffer->Data(), dataBuffer->Capacity(), address, size); + if (ret != EOK) { + DHLOGE("DCameraPhotoSurfaceListenerCommon Memory Copy failed, ret: %d", ret); + break; + } + + if (callback_ == nullptr) { + DHLOGE("DCameraPhotoSurfaceListenerCommon ResultCallback is null"); + break; + } + callback_->OnPhotoResult(dataBuffer); + } while (0); + surface_->ReleaseBuffer(buffer, -1); +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/cameraservice/cameraoperator/client/src/listener/dcamera_video_surface_listener_common.cpp b/services/cameraservice/cameraoperator/client/src/listener/dcamera_video_surface_listener_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19dc37b86ec5f5bc87ab2c1b18be5c9f0250a813 --- /dev/null +++ b/services/cameraservice/cameraoperator/client/src/listener/dcamera_video_surface_listener_common.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dcamera_video_surface_listener.h" + +#include + +#include "data_buffer.h" +#include "distributed_camera_errno.h" +#include "distributed_hardware_log.h" + +namespace OHOS { +namespace DistributedHardware { +DCameraVideoSurfaceListener::DCameraVideoSurfaceListener(const sptr& surface, + const std::shared_ptr& callback) : surface_(surface), callback_(callback) +{ +} + +void DCameraVideoSurfaceListener::OnBufferAvailable() +{ + DHLOGI("DCameraVideoSurfaceListenerCommon::OnBufferAvailable"); + OHOS::sptr buffer = nullptr; + int32_t flushFence = 0; + int64_t timestamp = 0; + OHOS::Rect damage; + + do { + surface_->AcquireBuffer(buffer, flushFence, timestamp, damage); + if (buffer == nullptr) { + DHLOGE("DCameraVideoSurfaceListenerCommon AcquireBuffer failed"); + break; + } + + int32_t width = buffer->GetWidth(); + int32_t height = buffer->GetHeight(); + int32_t size = width * height * 4; + char *address = static_cast(buffer->GetVirAddr()); + if ((address == nullptr) || (size <= 0)) { + DHLOGE("DCameraVideoSurfaceListenerCommon invalid params, size: %d", size); + break; + } + + DHLOGI("DCameraVideoSurfaceListenerCommon size: %d", size); + std::shared_ptr dataBuffer = std::make_shared(size); + int32_t ret = memcpy_s(dataBuffer->Data(), dataBuffer->Capacity(), address, size); + if (ret != EOK) { + DHLOGE("DCameraVideoSurfaceListenerCommon Memory Copy failed, ret: %d", ret); + break; + } + + if (callback_ == nullptr) { + DHLOGE("DCameraVideoSurfaceListenerCommon ResultCallback is null"); + break; + } + callback_->OnVideoResult(dataBuffer); + } while (0); + surface_->ReleaseBuffer(buffer, -1); +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/cameraservice/cameraoperator/handler/BUILD.gn b/services/cameraservice/cameraoperator/handler/BUILD.gn index 39c468a28fcab989bb3d2c26bedbed28f1a36899..f3f6d8137cee3a85a7f1fbf959259d251fc305e1 100644 --- a/services/cameraservice/cameraoperator/handler/BUILD.gn +++ b/services/cameraservice/cameraoperator/handler/BUILD.gn @@ -13,7 +13,8 @@ import("//build/ohos.gni") import("//build/ohos_var.gni") -import("//foundation/distributedhardware/distributedcamera/distributedcamera.gni") +import( + "//foundation/distributedhardware/distributedcamera/distributedcamera.gni") ohos_shared_library("distributed_camera_handler") { include_dirs = [ @@ -45,19 +46,22 @@ ohos_shared_library("distributed_camera_handler") { "${services_path}/cameraservice/cameraoperator/client/include/callback", ] - sources = [ - "src/dcamera_handler.cpp", - "${services_path}/cameraservice/cameraoperator/client/src/callback/dcamera_manager_callback.cpp", - ] + sources = [ "${services_path}/cameraservice/cameraoperator/client/src/callback/dcamera_manager_callback.cpp" ] + + if (device_name == "baltimore") { + sources += [ "src/dcamera_handler.cpp" ] + } else { + sources += [ "src/dcamera_handler_common.cpp" ] + } deps = [ - "${fwk_utils_path}:distributedhardwareutils", - "${common_path}:distributed_camera_utils", - "${graphicstandard_path}:libsurface", "${camerastandard_path}/frameworks/native/camera:camera_framework", "${camerastandard_path}/frameworks/native/metadata:metadata", - "//utils/native/base:utils", + "${common_path}:distributed_camera_utils", + "${fwk_utils_path}:distributedhardwareutils", + "${graphicstandard_path}:libsurface", "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", ] defines = [ @@ -74,4 +78,4 @@ ohos_shared_library("distributed_camera_handler") { subsystem_name = "distributedhardware" part_name = "distributed_camera" -} \ No newline at end of file +} diff --git a/services/cameraservice/cameraoperator/handler/src/dcamera_handler_common.cpp b/services/cameraservice/cameraoperator/handler/src/dcamera_handler_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..837e62aa2814530b0d5bbddd801e72d3d4e5ab73 --- /dev/null +++ b/services/cameraservice/cameraoperator/handler/src/dcamera_handler_common.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dcamera_handler.h" + +#include "anonymous_string.h" +#include "avcodec_info.h" +#include "avcodec_list.h" +#include "dcamera_manager_callback.h" +#include "dcamera_utils_tools.h" +#include "distributed_camera_constants.h" +#include "distributed_camera_errno.h" +#include "distributed_hardware_log.h" +#include "metadata_utils.h" + +namespace OHOS { +namespace DistributedHardware { +IMPLEMENT_SINGLE_INSTANCE(DCameraHandler); + +DCameraHandler::~DCameraHandler() +{ + DHLOGI("~DCameraHandlerCommon"); +} + +int32_t DCameraHandler::Initialize() +{ + DHLOGI("DCameraHandlerCommon::Initialize"); + cameraManager_ = CameraStandard::CameraManager::GetInstance(); + if (cameraManager_ == nullptr) { + DHLOGE("DCameraHandlerCommon::Initialize cameraManager getInstance failed"); + return DCAMERA_INIT_ERR; + } + std::shared_ptr cameraMgrCallback = std::make_shared(); + cameraManager_->SetCallback(cameraMgrCallback); + DHLOGI("DCameraHandlerCommon::Initialize success"); + return DCAMERA_OK; +} + +std::vector DCameraHandler::Query() +{ + std::vector itemList; + std::vector> cameraList = cameraManager_->GetCameras(); + DHLOGI("DCameraHandlerCommon::Query get %d cameras", cameraList.size()); + if (cameraList.empty()) { + DHLOGE("DCameraHandlerCommon::Query no camera device"); + return itemList; + } + for (auto& info : cameraList) { + if (info->GetConnectionType() != OHOS_CAMERA_CONNECTION_TYPE_BUILTIN) { + DHLOGI("DCameraHandlerCommon::Query connection type: %d", info->GetConnectionType()); + continue; + } + if ((info->GetPosition() == OHOS_CAMERA_POSITION_OTHER) || + (info->GetPosition() == OHOS_CAMERA_POSITION_FRONT) || + (info->GetPosition() == OHOS_CAMERA_POSITION_BACK && + info->GetCameraType() == OHOS_CAMERA_TYPE_LOGICAL)) { + DHItem item = CreateDHItem(info); + itemList.push_back(item); + } + } + DHLOGI("DCameraHandlerCommon::Query success, get %d items", itemList.size()); + return itemList; +} + +std::map DCameraHandler::QueryExtraInfo() +{ + DHLOGI("DCameraHandler::QueryExtraInfo"); + std::map extraInfo; + return extraInfo; +} + +bool DCameraHandler::IsSupportPlugin() +{ + DHLOGI("DCameraHandler::IsSupportPlugin"); + return false; +} + +void DCameraHandler::RegisterPluginListener(std::shared_ptr listener) +{ + DHLOGI("DCameraHandler::RegisterPluginListener"); + if (listener == nullptr) { + DHLOGE("DCameraHandler unregistering plugin listener"); + } + pluginListener_ = listener; +} + +std::vector DCameraHandler::GetCameras() +{ + std::vector cameras; + std::vector> cameraList = cameraManager_->GetCameras(); + DHLOGI("DCameraHandlerCommon::GetCameras get %d cameras", cameraList.size()); + if (cameraList.empty()) { + DHLOGE("DCameraHandlerCommon::GetCameras no camera device"); + return cameras; + } + for (auto& info : cameraList) { + if (info->GetConnectionType() != OHOS_CAMERA_CONNECTION_TYPE_BUILTIN) { + DHLOGI("DCameraHandlerCommon::GetCameras connection type: %d", info->GetConnectionType()); + continue; + } + if ((info->GetPosition() == OHOS_CAMERA_POSITION_OTHER) || + (info->GetPosition() == OHOS_CAMERA_POSITION_FRONT) || + (info->GetPosition() == OHOS_CAMERA_POSITION_BACK && + info->GetCameraType() == OHOS_CAMERA_TYPE_LOGICAL)) { + std::string dhId = CAMERA_ID_PREFIX + info->GetID(); + cameras.push_back(dhId); + } + } + DHLOGI("DCameraHandlerCommon::GetCameras success, get %d items", cameras.size()); + return cameras; +} + +DHItem DCameraHandler::CreateDHItem(sptr& info) +{ + DHItem item; + std::string id = info->GetID(); + item.dhId = CAMERA_ID_PREFIX + id; + DHLOGI("DCameraHandlerCommon::CreateDHItem camera id: %s", GetAnonyString(id).c_str()); + + Json::Value root; + root[CAMERA_PROTOCOL_VERSION_KEY] = Json::Value(CAMERA_PROTOCOL_VERSION_VALUE); + root[CAMERA_POSITION_KEY] = Json::Value(GetCameraPosition(info->GetPosition())); + root[CAMERA_CODEC_TYPE_KEY].append("OMX_hisi_video_encoder_avc"); + + sptr cameraInput = cameraManager_->CreateCameraInput(info); + if (cameraInput == nullptr) { + DHLOGE("DCameraHandlerCommon::CreateDHItem create cameraInput failed"); + return item; + } + + Json::Value outputFormat; + Json::Value resolution; + std::set formatSet; + + std::vector videoFormats; + videoFormats.push_back(camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888); + ConfigInfo videoConfig = {CONTINUOUS_FRAME, CAMERA_FORMAT_VIDEO, cameraInput}; + ConfigFormatAndResolution(videoConfig, outputFormat, resolution, videoFormats, formatSet); + + std::vector previewFormats; + previewFormats.push_back(camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888); + ConfigInfo previewInfo = {CONTINUOUS_FRAME, CAMERA_FORMAT_PREVIEW, cameraInput}; + ConfigFormatAndResolution(previewInfo, outputFormat, resolution, previewFormats, formatSet); + + std::vector photoFormats; + photoFormats.push_back(camera_format_t::OHOS_CAMERA_FORMAT_RGBA_8888); + ConfigInfo photoConfig = {SNAPSHOT_FRAME, CAMERA_FORMAT_PHOTO, cameraInput}; + ConfigFormatAndResolution(photoConfig, outputFormat, resolution, photoFormats, formatSet); + + root[CAMERA_FORMAT_KEY] = outputFormat; + root[CAMERA_RESOLUTION_KEY] = resolution; + + std::string abilityString = cameraInput->GetCameraSettings(); + std::string encodeString = Base64Encode(reinterpret_cast(abilityString.c_str()), + abilityString.length()); + root[CAMERA_METADATA_KEY] = Json::Value(encodeString); + + item.attrs = root.toStyledString(); + cameraInput->Release(); + return item; +} + +std::string DCameraHandler::GetCameraPosition(camera_position_enum_t position) +{ + DHLOGI("DCameraHandler::GetCameraPosition position: %d", position); + std::string ret = ""; + switch (position) { + case OHOS_CAMERA_POSITION_BACK: { + ret = CAMERA_POSITION_BACK; + break; + } + case OHOS_CAMERA_POSITION_FRONT: { + ret = CAMERA_POSITION_FRONT; + break; + } + case OHOS_CAMERA_POSITION_OTHER: { + ret = CAMERA_POSITION_UNSPECIFIED; + break; + } + default: { + DHLOGE("DCameraHandler::GetCameraPosition unknown camera position"); + break; + } + } + DHLOGI("DCameraHandler::GetCameraPosition success ret: %s", ret.c_str()); + return ret; +} + +void DCameraHandler::ConfigFormatAndResolution(ConfigInfo& info, Json::Value& outputFormat, Json::Value& resolution, + std::vector& formatList, std::set& formatSet) +{ + DHLOGI("DCameraHandlerCommon::ConfigFormatAndResolution camera format size: %d", formatList.size()); + for (auto& format : formatList) { + DHLOGI("DCameraHandlerCommon::ConfigFormatAndResolution %s format: %d", info.formatKey.c_str(), format); + outputFormat[info.formatKey].append(format); + if (formatSet.insert(format).second) { + std::string keyName = std::to_string(format); + resolution[keyName].append("640*480"); + } + } +} + +bool DCameraHandler::IsValid(DCStreamType type, CameraStandard::CameraPicSize& size) +{ + bool ret = false; + switch (type) { + case CONTINUOUS_FRAME: { + ret = (size.width >= RESOLUTION_MIN_WIDTH) && + (size.height >= RESOLUTION_MIN_HEIGHT) && + (size.width <= RESOLUTION_MAX_WIDTH_CONTINUOUS) && + (size.height <= RESOLUTION_MAX_HEIGHT_CONTINUOUS); + break; + } + case SNAPSHOT_FRAME: { + ret = (size.width >= RESOLUTION_MIN_WIDTH) && + (size.height >= RESOLUTION_MIN_HEIGHT) && + (size.width <= RESOLUTION_MAX_WIDTH_SNAPSHOT) && + (size.height <= RESOLUTION_MAX_HEIGHT_SNAPSHOT); + break; + } + default: { + DHLOGE("DCameraHandler::isValid unknown stream type"); + break; + } + } + return ret; +} + +IHardwareHandler* GetHardwareHandler() +{ + DHLOGI("DCameraHandler::GetHardwareHandler"); + return &DCameraHandler::GetInstance(); +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/cameraservice/sinkservice/BUILD.gn b/services/cameraservice/sinkservice/BUILD.gn index 8f442aed5edd400ad90232d98e62eac8b5888340..5cd3337aa0aa8cea12cb42cfeb965e2988df0149 100644 --- a/services/cameraservice/sinkservice/BUILD.gn +++ b/services/cameraservice/sinkservice/BUILD.gn @@ -13,7 +13,8 @@ import("//build/ohos.gni") import("//build/ohos_var.gni") -import("//foundation/distributedhardware/distributedcamera/distributedcamera.gni") +import( + "//foundation/distributedhardware/distributedcamera/distributedcamera.gni") ohos_shared_library("distributed_camera_sink") { include_dirs = [ @@ -63,49 +64,50 @@ ohos_shared_library("distributed_camera_sink") { ] sources = [ - "src/distributedcamera/distributed_camera_sink_service.cpp", - "src/distributedcamera/distributed_camera_sink_stub.cpp", - "${innerkits_path}/native_cpp/camera_source/src/distributed_camera_source_proxy.cpp", - - "src/distributedcameramgr/callback/dcamera_sink_controller_state_callback.cpp", - "src/distributedcameramgr/callback/dcamera_sink_output_result_callback.cpp", - - "src/distributedcameramgr/eventbus/dcamera_frame_trigger_event.cpp", - "src/distributedcameramgr/eventbus/dcamera_photo_output_event.cpp", - "src/distributedcameramgr/eventbus/dcamera_post_authorization_event.cpp", - "src/distributedcameramgr/eventbus/dcamera_video_output_event.cpp", - - "src/distributedcameramgr/listener/dcamera_sink_controller_channel_listener.cpp", - "src/distributedcameramgr/listener/dcamera_sink_data_process_listener.cpp", - "src/distributedcameramgr/listener/dcamera_sink_output_channel_listener.cpp", - - "src/distributedcameramgr/dcamera_sink_access_control.cpp", - "src/distributedcameramgr/dcamera_sink_controller.cpp", - "src/distributedcameramgr/dcamera_sink_data_process.cpp", - "src/distributedcameramgr/dcamera_sink_dev.cpp", - "src/distributedcameramgr/dcamera_sink_output.cpp", - "src/distributedcameramgr/dcamera_sink_service_ipc.cpp", - - "${services_path}/cameraservice/base/src/dcamera_capture_info_cmd.cpp", - "${services_path}/cameraservice/base/src/dcamera_channel_info_cmd.cpp", - "${services_path}/cameraservice/base/src/dcamera_event_cmd.cpp", - "${services_path}/cameraservice/base/src/dcamera_info_cmd.cpp", - "${services_path}/cameraservice/base/src/dcamera_metadata_setting_cmd.cpp", - "${services_path}/cameraservice/base/src/dcamera_open_info_cmd.cpp", + "${innerkits_path}/native_cpp/camera_source/src/distributed_camera_source_proxy.cpp", + "${services_path}/cameraservice/base/src/dcamera_capture_info_cmd.cpp", + "${services_path}/cameraservice/base/src/dcamera_channel_info_cmd.cpp", + "${services_path}/cameraservice/base/src/dcamera_event_cmd.cpp", + "${services_path}/cameraservice/base/src/dcamera_info_cmd.cpp", + "${services_path}/cameraservice/base/src/dcamera_metadata_setting_cmd.cpp", + "${services_path}/cameraservice/base/src/dcamera_open_info_cmd.cpp", + "src/distributedcamera/distributed_camera_sink_service.cpp", + "src/distributedcamera/distributed_camera_sink_stub.cpp", + "src/distributedcameramgr/callback/dcamera_sink_controller_state_callback.cpp", + "src/distributedcameramgr/callback/dcamera_sink_output_result_callback.cpp", + "src/distributedcameramgr/dcamera_sink_access_control.cpp", + "src/distributedcameramgr/dcamera_sink_controller.cpp", + "src/distributedcameramgr/dcamera_sink_dev.cpp", + "src/distributedcameramgr/dcamera_sink_output.cpp", + "src/distributedcameramgr/dcamera_sink_service_ipc.cpp", + "src/distributedcameramgr/eventbus/dcamera_frame_trigger_event.cpp", + "src/distributedcameramgr/eventbus/dcamera_photo_output_event.cpp", + "src/distributedcameramgr/eventbus/dcamera_post_authorization_event.cpp", + "src/distributedcameramgr/eventbus/dcamera_video_output_event.cpp", + "src/distributedcameramgr/listener/dcamera_sink_controller_channel_listener.cpp", + "src/distributedcameramgr/listener/dcamera_sink_data_process_listener.cpp", + "src/distributedcameramgr/listener/dcamera_sink_output_channel_listener.cpp", ] + if (device_name == "baltimore") { + sources += [ "src/distributedcameramgr/dcamera_sink_data_process.cpp" ] + } else { + sources += + [ "src/distributedcameramgr/dcamera_sink_data_process_common.cpp" ] + } + deps = [ - "${fwk_utils_path}:distributedhardwareutils", - "${common_path}:distributed_camera_utils", - "${graphicstandard_path}:libsurface", "${camerastandard_path}/frameworks/native/camera:camera_framework", "${camerastandard_path}/frameworks/native/metadata:metadata", + "${common_path}:distributed_camera_utils", + "${fwk_utils_path}:distributedhardwareutils", + "${graphicstandard_path}:libsurface", "${services_path}/cameraservice/cameraoperator/client:distributed_camera_client", "${services_path}/cameraservice/cameraoperator/handler:distributed_camera_handler", "${services_path}/channel:distributed_camera_channel", "${services_path}/data_process:distributed_camera_data_process", - "//utils/native/base:utils", "//third_party/jsoncpp:jsoncpp", + "//utils/native/base:utils", ] defines = [ @@ -125,4 +127,4 @@ ohos_shared_library("distributed_camera_sink") { subsystem_name = "distributedhardware" part_name = "distributed_camera" -} \ No newline at end of file +} diff --git a/services/cameraservice/sinkservice/src/distributedcameramgr/dcamera_sink_data_process_common.cpp b/services/cameraservice/sinkservice/src/distributedcameramgr/dcamera_sink_data_process_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c44c69296591a9639cc86960173e7f62f6fc0ff0 --- /dev/null +++ b/services/cameraservice/sinkservice/src/distributedcameramgr/dcamera_sink_data_process_common.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dcamera_sink_data_process.h" + +#include "anonymous_string.h" +#include "dcamera_channel_sink_impl.h" +#include "dcamera_pipeline_sink.h" +#include "dcamera_sink_data_process_listener.h" +#include "distributed_camera_constants.h" +#include "distributed_camera_errno.h" +#include "distributed_hardware_log.h" + +namespace OHOS { +namespace DistributedHardware { +DCameraSinkDataProcess::DCameraSinkDataProcess(const std::string& dhId, std::shared_ptr& channel) + : dhId_(dhId), channel_(channel) +{ + DHLOGI("DCameraSinkDataProcess Constructor dhId: %s", GetAnonyString(dhId_).c_str()); + eventBus_ = std::make_shared(); + DCameraPhotoOutputEvent photoEvent(*this); + DCameraVideoOutputEvent videoEvent(*this); + eventBus_->AddHandler(photoEvent.GetType(), *this); + eventBus_->AddHandler(videoEvent.GetType(), *this); +} + +int32_t DCameraSinkDataProcess::StartCapture(std::shared_ptr& captureInfo) +{ + DHLOGI("DCameraSinkDataProcess::StartCapture dhId: %s, width: %d, height: %d, format: %d, stream: %d, encode: %d", + GetAnonyString(dhId_).c_str(), captureInfo->width_, captureInfo->height_, captureInfo->format_, + captureInfo->streamType_, captureInfo->encodeType_); + captureInfo_ = captureInfo; + if (pipeline_ != nullptr) { + DHLOGI("DCameraSinkDataProcess::StartCapture %s pipeline already exits", GetAnonyString(dhId_).c_str()); + return DCAMERA_OK; + } + + if (captureInfo->streamType_ == CONTINUOUS_FRAME) { + DHLOGI("DCameraSinkDataProcess::StartCapture %s create data process pipeline", GetAnonyString(dhId_).c_str()); + pipeline_ = std::make_shared(); + auto dataProcess = std::shared_ptr(shared_from_this()); + std::shared_ptr listener = std::make_shared(dataProcess); + VideoConfigParams srcParams(VideoCodecType::NO_CODEC, + GetPipelineFormat(captureInfo->format_), + DCAMERA_PRODUCER_FPS_DEFAULT, + captureInfo->width_, + captureInfo->height_); + VideoConfigParams destParams(GetPipelineCodecType(captureInfo->encodeType_), + GetPipelineFormat(captureInfo->format_), + DCAMERA_PRODUCER_FPS_DEFAULT, + captureInfo->width_, + captureInfo->height_); + int32_t ret = pipeline_->CreateDataProcessPipeline(PipelineType::VIDEO, srcParams, destParams, listener); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraSinkDataProcess::StartCapture create data process pipeline failed, dhId: %s, ret: %d", + GetAnonyString(dhId_).c_str(), ret); + return ret; + } + } + DHLOGI("DCameraSinkDataProcess::StartCapture %s success", GetAnonyString(dhId_).c_str()); + return DCAMERA_OK; +} + +int32_t DCameraSinkDataProcess::StopCapture() +{ + DHLOGI("DCameraSinkDataProcess::StopCapture dhId: %s", GetAnonyString(dhId_).c_str()); + if (pipeline_ != nullptr) { + pipeline_->DestroyDataProcessPipeline(); + pipeline_ = nullptr; + } + return DCAMERA_OK; +} + +int32_t DCameraSinkDataProcess::FeedStream(std::shared_ptr& dataBuffer) +{ + DCStreamType type = captureInfo_->streamType_; + DHLOGI("DCameraSinkDataProcess::FeedStream dhId: %s, stream type: %d", GetAnonyString(dhId_).c_str(), type); + switch (type) { + case CONTINUOUS_FRAME: { + int32_t ret = FeedStreamInner(dataBuffer); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraSinkDataProcess::FeedStream continuous frame failed, dhId: %s, ret: %d", + GetAnonyString(dhId_).c_str(), ret); + return ret; + } + break; + } + case SNAPSHOT_FRAME: { + DCameraPhotoOutputEvent photoEvent(*this, dataBuffer); + eventBus_->PostEvent(photoEvent, POSTMODE::POST_ASYNC); + break; + } + default: { + DHLOGE("DCameraSinkDataProcess::FeedStream %s unknown stream type: %d", + GetAnonyString(dhId_).c_str(), type); + break; + } + } + DHLOGI("DCameraSinkDataProcess::FeedStream %s success", GetAnonyString(dhId_).c_str()); + return DCAMERA_OK; +} + +void DCameraSinkDataProcess::OnEvent(DCameraPhotoOutputEvent& event) +{ + std::shared_ptr buffer = event.GetParam(); + int32_t ret = channel_->SendData(buffer); + DHLOGI("DCameraSinkDataProcess::OnEvent %s send photo output data ret: %d", GetAnonyString(dhId_).c_str(), ret); +} + +void DCameraSinkDataProcess::OnEvent(DCameraVideoOutputEvent& event) +{ + std::shared_ptr buffer = event.GetParam(); + int32_t ret = channel_->SendData(buffer); + DHLOGI("DCameraSinkDataProcess::OnEvent %s send video output data ret: %d", GetAnonyString(dhId_).c_str(), ret); +} + +void DCameraSinkDataProcess::OnProcessedVideoBuffer(const std::shared_ptr& videoResult) +{ + DCameraVideoOutputEvent videoEvent(*this, videoResult); + eventBus_->PostEvent(videoEvent, POSTMODE::POST_ASYNC); +} + +void DCameraSinkDataProcess::OnError(DataProcessErrorType errorType) +{ + DHLOGE("DCameraSinkDataProcess::OnError %s data process pipeline error, errorType: %d", + GetAnonyString(dhId_).c_str(), errorType); +} + +int32_t DCameraSinkDataProcess::FeedStreamInner(std::shared_ptr& dataBuffer) +{ + DHLOGI("DCameraSinkDataProcess::FeedStreamInner dhId: %s", GetAnonyString(dhId_).c_str()); + std::vector> buffers; + buffers.push_back(dataBuffer); + int32_t ret = pipeline_->ProcessData(buffers); + if (ret != DCAMERA_OK) { + DHLOGE("DCameraSinkDataProcess::FeedStreamInner process data failed, dhId: %s, ret: %d", + GetAnonyString(dhId_).c_str(), ret); + return ret; + } + DHLOGI("DCameraSinkDataProcess::FeedStreamInner %s success", GetAnonyString(dhId_).c_str()); + return DCAMERA_OK; +} + +VideoCodecType DCameraSinkDataProcess::GetPipelineCodecType(DCEncodeType encodeType) +{ + VideoCodecType codecType; + switch (encodeType) { + case ENCODE_TYPE_H264: + codecType = VideoCodecType::CODEC_H264; + break; + case ENCODE_TYPE_H265: + codecType = VideoCodecType::CODEC_H265; + break; + default: + codecType = VideoCodecType::NO_CODEC; + break; + } + return codecType; +} + +Videoformat DCameraSinkDataProcess::GetPipelineFormat(int32_t format) +{ + return Videoformat::NV21; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/data_process/BUILD.gn b/services/data_process/BUILD.gn index a4aa82d71b277e46473a86451808fa79c9134321..bd5419a5d79495cf3ca9bada17e6c90d4f6f5fe1 100644 --- a/services/data_process/BUILD.gn +++ b/services/data_process/BUILD.gn @@ -13,7 +13,8 @@ import("//build/ohos.gni") import("//build/ohos_var.gni") -import("//foundation/distributedhardware/distributedcamera/distributedcamera.gni") +import( + "//foundation/distributedhardware/distributedcamera/distributedcamera.gni") ohos_shared_library("distributed_camera_data_process") { include_dirs = [ @@ -44,21 +45,31 @@ ohos_shared_library("distributed_camera_data_process") { ] sources = [ + "src/pipeline/abstract_data_process.cpp", "src/pipeline/dcamera_pipeline_sink.cpp", "src/pipeline/dcamera_pipeline_source.cpp", - "src/pipeline/abstract_data_process.cpp", - "src/utils/image_common_type.cpp", - "src/pipeline_node/multimedia_codec/decode_data_process.cpp", + "src/pipeline_node/colorspace_conversion/convert_nv12_to_nv21.cpp", + "src/pipeline_node/fpscontroller/fps_controller_process.cpp", "src/pipeline_node/multimedia_codec/decode_video_callback.cpp", - "src/pipeline_node/multimedia_codec/encode_data_process.cpp", "src/pipeline_node/multimedia_codec/encode_video_callback.cpp", - "src/pipeline_node/fpscontroller/fps_controller_process.cpp", - "src/pipeline_node/colorspace_conversion/convert_nv12_to_nv21.cpp", + "src/utils/image_common_type.cpp", ] + if (device_name == "baltimore") { + sources += [ + "src/pipeline_node/multimedia_codec/decode_data_process.cpp", + "src/pipeline_node/multimedia_codec/encode_data_process.cpp", + ] + } else { + sources += [ + "src/pipeline_node/multimedia_codec/decode_data_process_common.cpp", + "src/pipeline_node/multimedia_codec/encode_data_process_common.cpp", + ] + } + deps = [ - "${fwk_utils_path}:distributedhardwareutils", "${common_path}:distributed_camera_utils", + "${fwk_utils_path}:distributedhardwareutils", "//foundation/graphic/standard/frameworks/surface:surface", "//utils/native/base:utils", ] @@ -78,4 +89,4 @@ ohos_shared_library("distributed_camera_data_process") { subsystem_name = "distributedhardware" part_name = "distributed_camera" -} \ No newline at end of file +} diff --git a/services/data_process/include/pipeline_node/multimedia_codec/decode_data_process.h b/services/data_process/include/pipeline_node/multimedia_codec/decode_data_process.h index 8843eaad67a2d6e287d5c1d3abf1295e8f09f86f..0695f92b39ab99c4a88f9b8522bb0d76d5212f31 100644 --- a/services/data_process/include/pipeline_node/multimedia_codec/decode_data_process.h +++ b/services/data_process/include/pipeline_node/multimedia_codec/decode_data_process.h @@ -78,7 +78,6 @@ private: int32_t InitDecoder(); int32_t InitDecoderMetadataFormat(); int32_t SetDecoderOutputSurface(); - void ReleaseDecoder(); int32_t FeedDecoderInputBuffer(); int64_t GetDecoderTimeStamp(); int32_t GetAlignedHeight(); @@ -113,6 +112,7 @@ private: std::shared_ptr decodeVideoCallback_ = nullptr; sptr decodeConsumerSurface_ = nullptr; sptr decodeProducerSurface_ = nullptr; + sptr decodeSurfaceListener_ = nullptr; bool isDecoderProcess_ = false; int32_t waitDecoderOutputCount_ = 0; @@ -131,7 +131,7 @@ class DecodeSurfaceListener : public IBufferConsumerListener { public: DecodeSurfaceListener(sptr surface, std::weak_ptr decodeVideoNode) : surface_(surface), decodeVideoNode_(decodeVideoNode) {} - ~DecodeSurfaceListener() = default; + ~DecodeSurfaceListener(); void OnBufferAvailable() override; void SetSurface(const sptr& surface); diff --git a/services/data_process/src/pipeline_node/multimedia_codec/decode_data_process.cpp b/services/data_process/src/pipeline_node/multimedia_codec/decode_data_process.cpp index 488dec5bf9580e5f4bfea1b593b854b0356cc4d8..52cb298fceaa1699458b2d243f0b5db9bab7034a 100644 --- a/services/data_process/src/pipeline_node/multimedia_codec/decode_data_process.cpp +++ b/services/data_process/src/pipeline_node/multimedia_codec/decode_data_process.cpp @@ -105,7 +105,7 @@ int32_t DecodeDataProcess::InitDecoder() return err; } - videoDecoder_ = Media::VideoDecoderFactory::CreateByName("OMX_hisi_video_decoder_avc"); + videoDecoder_ = Media::VideoDecoderFactory::CreateByMime(processType_); if (videoDecoder_ == nullptr) { DHLOGE("Create video decoder failed."); return DCAMERA_INIT_ERR; @@ -179,8 +179,7 @@ int32_t DecodeDataProcess::SetDecoderOutputSurface() } decodeConsumerSurface_->SetDefaultWidthAndHeight((int32_t)sourceConfig_.GetWidth(), (int32_t)sourceConfig_.GetHeight()); - sptr decodeSurfaceListener_ = new DecodeSurfaceListener(decodeConsumerSurface_, - shared_from_this()); + decodeSurfaceListener_ = new DecodeSurfaceListener(decodeConsumerSurface_, shared_from_this()); if (decodeConsumerSurface_->RegisterConsumerListener(decodeSurfaceListener_) != SURFACE_ERROR_OK) { DHLOGE("Register consumer listener fail."); @@ -230,12 +229,19 @@ void DecodeDataProcess::ReleaseProcessNode() videoDecoder_->Flush(); videoDecoder_->Stop(); videoDecoder_->Release(); - decodeConsumerSurface_ = nullptr; - decodeProducerSurface_ = nullptr; videoDecoder_ = nullptr; decodeVideoCallback_ = nullptr; } } + if (decodeConsumerSurface_ != nullptr) { + int32_t ret = decodeConsumerSurface_->UnregisterConsumerListener(); + if (ret != SURFACE_ERROR_OK) { + DHLOGE("Unregister consumer listener failed. Error type: %d.", ret); + } + decodeConsumerSurface_ = nullptr; + decodeProducerSurface_ = nullptr; + decodeSurfaceListener_ = nullptr; + } processType_ = ""; std::queue> emptyBuffersQueue; @@ -696,5 +702,11 @@ void DecodeSurfaceListener::SetDecodeVideoNode(const std::weak_ptr(sourceConfig_.GetHeight()); + if (alignedHeight % alignedBits != 0) { + alignedHeight = ((alignedHeight / alignedBits) + 1) * alignedBits; + } + return alignedHeight; +} + +bool DecodeDataProcess::IsInDecoderRange(const VideoConfigParams& curConfig) +{ + return (curConfig.GetWidth() >= MIN_VIDEO_WIDTH || curConfig.GetWidth() <= MAX_VIDEO_WIDTH || + curConfig.GetHeight() >= MIN_VIDEO_HEIGHT || curConfig.GetHeight() <= MAX_VIDEO_HEIGHT || + curConfig.GetFrameRate() <= MAX_FRAME_RATE); +} + +bool DecodeDataProcess::IsConvertible(const VideoConfigParams& sourceConfig, const VideoConfigParams& targetConfig) +{ + return (sourceConfig.GetVideoCodecType() == targetConfig.GetVideoCodecType() || + targetConfig.GetVideoCodecType() == VideoCodecType::NO_CODEC); +} + +void DecodeDataProcess::InitCodecEvent() +{ + DHLOGD("Common Init DecodeNode eventBus, and add handler for it."); + eventBusDecode_ = std::make_shared(); + DCameraCodecEvent codecEvent(*this, std::make_shared()); + eventBusRegHandleDecode_ = eventBusDecode_->AddHandler(codecEvent.GetType(), *this); + + DHLOGD("Common Add handler for DCamera pipeline eventBus."); + eventBusRegHandlePipeline2Decode_ = eventBusPipeline_->AddHandler(codecEvent.GetType(), *this); +} + +int32_t DecodeDataProcess::InitDecoder() +{ + DHLOGD("Common Init video decoder."); + int32_t err = InitDecoderMetadataFormat(); + if (err != DCAMERA_OK) { + DHLOGE("Init video decoder metadata format fail."); + return err; + } + + videoDecoder_ = Media::VideoDecoderFactory::CreateByMime(processType_); + if (videoDecoder_ == nullptr) { + DHLOGE("Create video decoder failed."); + return DCAMERA_INIT_ERR; + } + decodeVideoCallback_ = std::make_shared(shared_from_this()); + int32_t retVal = videoDecoder_->SetCallback(decodeVideoCallback_); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Set video decoder callback failed."); + return DCAMERA_INIT_ERR; + } + retVal = videoDecoder_->Configure(metadataFormat_); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Set video decoder metadata format failed."); + return DCAMERA_INIT_ERR; + } + retVal = SetDecoderOutputSurface(); + if (retVal != DCAMERA_OK) { + DHLOGE("Set decoder output surface fail."); + return retVal; + } + + retVal = videoDecoder_->Prepare(); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Video decoder prepare failed."); + return DCAMERA_INIT_ERR; + } + retVal = videoDecoder_->Start(); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Video decoder start failed."); + return DCAMERA_INIT_ERR; + } + return DCAMERA_OK; +} + +int32_t DecodeDataProcess::InitDecoderMetadataFormat() +{ + DHLOGD("Common Init video decoder metadata format."); + processType_ = "video/mp4v-es"; + metadataFormat_.PutStringValue("codec_mime", processType_); + + int32_t width = (int32_t)sourceConfig_.GetWidth(); + int32_t height = (int32_t)sourceConfig_.GetHeight(); + metadataFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::RGBA); + metadataFormat_.PutIntValue("max_input_size", width * height * 4 * 2); + metadataFormat_.PutIntValue("width", width); + metadataFormat_.PutIntValue("height", height); + metadataFormat_.PutIntValue("frame_rate", MAX_FRAME_RATE); + return DCAMERA_OK; +} + +int32_t DecodeDataProcess::SetDecoderOutputSurface() +{ + DHLOGD("Set the video decoder output surface."); + if (videoDecoder_ == nullptr) { + DHLOGE("The video decoder is null."); + return DCAMERA_BAD_VALUE; + } + + decodeConsumerSurface_ = Surface::CreateSurfaceAsConsumer(); + if (decodeConsumerSurface_ == nullptr) { + DHLOGE("Creat the decode consumer surface fail."); + return DCAMERA_INIT_ERR; + } + decodeConsumerSurface_->SetDefaultWidthAndHeight((int32_t)sourceConfig_.GetWidth(), + (int32_t)sourceConfig_.GetHeight()); + decodeSurfaceListener_ = new DecodeSurfaceListener(decodeConsumerSurface_, shared_from_this()); + if (decodeConsumerSurface_->RegisterConsumerListener(decodeSurfaceListener_) != + SURFACE_ERROR_OK) { + DHLOGE("Register consumer listener fail."); + return DCAMERA_INIT_ERR; + } + + sptr surfaceProducer = decodeConsumerSurface_->GetProducer(); + if (surfaceProducer == nullptr) { + DHLOGE("Get the surface producer of the decode consumer surface fail."); + return DCAMERA_INIT_ERR; + } + decodeProducerSurface_ = Surface::CreateSurfaceAsProducer(surfaceProducer); + if (decodeProducerSurface_ == nullptr) { + DHLOGE("Creat the decode producer surface of the decode consumer surface fail."); + return DCAMERA_INIT_ERR; + } + + DHLOGD("Set the producer surface to video decoder output surface."); + int32_t err = videoDecoder_->SetOutputSurface(decodeProducerSurface_); + if (err != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Set decoder output surface fail."); + return DCAMERA_INIT_ERR; + } + return DCAMERA_OK; +} + +void DecodeDataProcess::ReleaseProcessNode() +{ + DHLOGD("Start release [%d] node : DecodeNode.", nodeRank_); + isDecoderProcess_ = false; + if (nextDataProcess_ != nullptr) { + nextDataProcess_->ReleaseProcessNode(); + } + if (eventBusDecode_ != nullptr && eventBusPipeline_ != nullptr) { + DHLOGD("Start release DecodeNode eventBusDecode_ and eventBusPipeline_."); + DCameraCodecEvent codecEvent(*this, std::make_shared()); + eventBusDecode_->RemoveHandler(codecEvent.GetType(), eventBusRegHandleDecode_); + eventBusDecode_ = nullptr; + eventBusPipeline_->RemoveHandler(codecEvent.GetType(), eventBusRegHandlePipeline2Decode_); + eventBusPipeline_ = nullptr; + } + + { + std::lock_guard lck(mtxDecoderState_); + if (videoDecoder_ != nullptr) { + DHLOGD("Start release videoDecoder."); + videoDecoder_->Flush(); + videoDecoder_->Stop(); + videoDecoder_->Release(); + videoDecoder_ = nullptr; + decodeVideoCallback_ = nullptr; + } + } + if (decodeConsumerSurface_ != nullptr) { + int32_t ret = decodeConsumerSurface_->UnregisterConsumerListener(); + if (ret != SURFACE_ERROR_OK) { + DHLOGE("Unregister consumer listener failed. Error type: %d.", ret); + } + decodeConsumerSurface_ = nullptr; + decodeProducerSurface_ = nullptr; + decodeSurfaceListener_ = nullptr; + } + + processType_ = ""; + std::queue> emptyBuffersQueue; + inputBuffersQueue_.swap(emptyBuffersQueue); + std::queue emptyIndexsQueue; + availableInputIndexsQueue_.swap(emptyIndexsQueue); + waitDecoderOutputCount_ = 0; + lastFeedDecoderInputBufferTimeUs_ = 0; + outputTimeStampUs_ = 0; + alignedHeight_ = 0; + DHLOGD("Release [%d] node : DecodeNode end.", nodeRank_); +} + +int32_t DecodeDataProcess::ProcessData(std::vector>& inputBuffers) +{ + DHLOGD("Process data in DecodeDataProcess."); + if (inputBuffers.empty()) { + DHLOGE("The input data buffers is empty."); + return DCAMERA_BAD_VALUE; + } + if (sourceConfig_.GetVideoCodecType() == targetConfig_.GetVideoCodecType()) { + DHLOGD("The target VideoCodecType : %d is the same as the source VideoCodecType : %d.", + sourceConfig_.GetVideoCodecType(), targetConfig_.GetVideoCodecType()); + return DecodeDone(inputBuffers); + } + + if (videoDecoder_ == nullptr) { + DHLOGE("The video decoder does not exist before decoding data."); + return DCAMERA_INIT_ERR; + } + if (inputBuffersQueue_.size() > VIDEO_DECODER_QUEUE_MAX) { + DHLOGE("video decoder input buffers queue over flow."); + return DCAMERA_INDEX_OVERFLOW; + } + int32_t bufferSize = 1920 * 1808 * 4 * 2; + if (inputBuffers[0]->Size() > bufferSize) { + DHLOGE("DecodeNode input buffer size %d error.", inputBuffers[0]->Size()); + return DCAMERA_MEMORY_OPT_ERROR; + } + if (!isDecoderProcess_) { + DHLOGE("Decoder node occurred error or start release."); + return DCAMERA_DISABLE_PROCESS; + } + inputBuffersQueue_.push(inputBuffers[0]); + DHLOGD("Push inputBuffer sucess. BufSize %d, QueueSize %d.", inputBuffers[0]->Size(), inputBuffersQueue_.size()); + int32_t err = FeedDecoderInputBuffer(); + if (err != DCAMERA_OK) { + int32_t sleepTimeUs = 5000; + std::this_thread::sleep_for(std::chrono::microseconds(sleepTimeUs)); + DHLOGD("Feed decoder input buffer fail. Try FeedDecoderInputBuffer again."); + std::shared_ptr reFeedInputPacket = std::make_shared(); + reFeedInputPacket->SetVideoCodecType(sourceConfig_.GetVideoCodecType()); + DCameraCodecEvent dCamCodecEv(*this, reFeedInputPacket, VideoCodecAction::ACTION_ONCE_AGAIN); + if (eventBusPipeline_ == nullptr) { + DHLOGE("eventBusPipeline_ is nullptr."); + return DCAMERA_BAD_VALUE; + } + eventBusPipeline_->PostEvent(dCamCodecEv, POSTMODE::POST_ASYNC); + } + return DCAMERA_OK; +} + +int32_t DecodeDataProcess::FeedDecoderInputBuffer() +{ + DHLOGD("Feed decoder input buffer."); + while ((!inputBuffersQueue_.empty()) && (isDecoderProcess_)) { + std::shared_ptr buffer = inputBuffersQueue_.front(); + if (buffer == nullptr || availableInputIndexsQueue_.empty()) { + DHLOGE("inputBuffersQueue size %d, availableInputIndexsQueue size %d.", + inputBuffersQueue_.size(), availableInputIndexsQueue_.size()); + return DCAMERA_BAD_VALUE; + } + + { + std::lock_guard lck(mtxDecoderState_); + if (videoDecoder_ == nullptr) { + DHLOGE("The video decoder does not exist before GetInputBuffer."); + return DCAMERA_OK; + } + uint32_t index = availableInputIndexsQueue_.front(); + std::shared_ptr sharedMemoryInput = videoDecoder_->GetInputBuffer(index); + if (sharedMemoryInput == nullptr) { + DHLOGE("Failed to obtain the input shared memory corresponding to the [%d] index.", index); + return DCAMERA_BAD_VALUE; + } + size_t inputMemoDataSize = static_cast(sharedMemoryInput->GetSize()); + errno_t err = memcpy_s(sharedMemoryInput->GetBase(), inputMemoDataSize, buffer->Data(), buffer->Size()); + if (err != EOK) { + DHLOGE("memcpy_s buffer failed."); + return DCAMERA_MEMORY_OPT_ERROR; + } + int64_t timeUs = GetDecoderTimeStamp(); + DHLOGD("Decoder input buffer size %d, timeStamp %lld.", buffer->Size(), (long long)timeUs); + Media::AVCodecBufferInfo bufferInfo {timeUs, static_cast(buffer->Size()), 0}; + int32_t ret = videoDecoder_->QueueInputBuffer(index, bufferInfo, + Media::AVCODEC_BUFFER_FLAG_NONE); + if (ret != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("queue Input buffer failed."); + return DCAMERA_BAD_OPERATE; + } + } + + inputBuffersQueue_.pop(); + DHLOGD("Push inputBuffer sucess. inputBuffersQueue size is %d.", inputBuffersQueue_.size()); + + { + std::lock_guard lck(mtxHoldCount_); + availableInputIndexsQueue_.pop(); + waitDecoderOutputCount_++; + DHLOGD("Wait decoder output frames number is %d.", waitDecoderOutputCount_); + } + } + return DCAMERA_OK; +} + +int64_t DecodeDataProcess::GetDecoderTimeStamp() +{ + int64_t TimeDifferenceStampUs = 0; + int64_t nowTimeUs = GetNowTimeStampUs(); + if (lastFeedDecoderInputBufferTimeUs_ == 0) { + lastFeedDecoderInputBufferTimeUs_ = nowTimeUs; + return TimeDifferenceStampUs; + } + TimeDifferenceStampUs = nowTimeUs - lastFeedDecoderInputBufferTimeUs_; + lastFeedDecoderInputBufferTimeUs_ = nowTimeUs; + return TimeDifferenceStampUs; +} + +void DecodeDataProcess::GetDecoderOutputBuffer(const sptr& surface) +{ + DHLOGD("Get decoder output buffer."); + if (surface == nullptr) { + DHLOGE("Get decode consumer surface failed."); + return; + } + Rect damage = {0, 0, 0, 0}; + int32_t acquireFence = 0; + int64_t timeStampUs = 0; + sptr surfaceBuffer = nullptr; + GSError ret = surface->AcquireBuffer(surfaceBuffer, acquireFence, timeStampUs, damage); + if (ret != GSERROR_OK || surfaceBuffer == nullptr) { + DHLOGE("Acquire surface buffer failed!"); + return; + } + int32_t alignedWidth = surfaceBuffer->GetStride(); + int32_t alignedHeight = alignedHeight_; + DHLOGD("OutputBuffer alignedWidth %d, alignedHeight %d, TimeUs %lld.", alignedWidth, alignedHeight, timeStampUs); + CopyDecodedImage(surfaceBuffer, timeStampUs, alignedWidth, alignedHeight); + surface->ReleaseBuffer(surfaceBuffer, -1); + outputTimeStampUs_ = timeStampUs; + { + std::lock_guard lck(mtxHoldCount_); + if (waitDecoderOutputCount_ <= 0) { + DHLOGE("The waitDecoderOutputCount_ = %d.", waitDecoderOutputCount_); + } + if (outputTimeStampUs_ == 0) { + waitDecoderOutputCount_ -= FIRST_FRAME_INPUT_NUM; + } else { + waitDecoderOutputCount_--; + } + DHLOGD("Wait decoder output frames number is %d.", waitDecoderOutputCount_); + } +} + +void DecodeDataProcess::CopyDecodedImage(const sptr& surBuf, int64_t timeStampUs, int32_t alignedWidth, + int32_t alignedHeight) +{ + if (surBuf == nullptr) { + DHLOGE("surface buffer is null!"); + return; + } + size_t validDecodedImageSize = static_cast(sourceConfig_.GetWidth() * sourceConfig_.GetHeight() * 4); + size_t surfaceBufSize = static_cast(surBuf->GetSize()); + if (validDecodedImageSize > surfaceBufSize) { + DHLOGE("Buffer size error, validDecodedImageSize %d, surBufSize %d.", + validDecodedImageSize, surBuf->GetSize()); + return; + } + std::shared_ptr bufferOutput = std::make_shared(validDecodedImageSize); + uint8_t *addr = static_cast(surBuf->GetVirAddr()); + errno_t err = memcpy_s(bufferOutput->Data(), bufferOutput->Size(), addr, validDecodedImageSize); + if (err != EOK) { + DHLOGE("memcpy_s surface buffer failed."); + return; + } + bufferOutput->SetInt64("timeUs", timeStampUs); + bufferOutput->SetInt32("Videoformat", static_cast(sourceConfig_.GetVideoformat())); + bufferOutput->SetInt32("alignedWidth", static_cast(sourceConfig_.GetWidth())); + bufferOutput->SetInt32("alignedHeight", static_cast(sourceConfig_.GetHeight())); + bufferOutput->SetInt32("width", static_cast(sourceConfig_.GetWidth())); + bufferOutput->SetInt32("height", static_cast(sourceConfig_.GetHeight())); + PostOutputDataBuffers(bufferOutput); +} + +int32_t DecodeDataProcess::CopyYUVPlaneByRow(const ImageUnitInfo& srcImgInfo, const ImageUnitInfo& dstImgInfo) +{ + int32_t ret = CheckCopyImageInfo(srcImgInfo, dstImgInfo); + if (ret != DCAMERA_OK) { + DHLOGE("Check CopyImageUnitInfo failed."); + return ret; + } + errno_t err = EOK; + int32_t srcDataOffset = 0; + int32_t dstDataOffset = 0; + for (int32_t yh = 0; yh < dstImgInfo.height; yh++) { + err = memcpy_s(dstImgInfo.imgData + dstDataOffset, dstImgInfo.chromaOffset - dstDataOffset, + srcImgInfo.imgData + srcDataOffset, dstImgInfo.width); + if (err != EOK) { + DHLOGE("memcpy_s YPlane in line[%d] failed.", yh); + return DCAMERA_MEMORY_OPT_ERROR; + } + dstDataOffset += dstImgInfo.alignedWidth; + srcDataOffset += srcImgInfo.alignedWidth; + } + DHLOGD("Copy Yplane end, dstDataOffset %d, srcDataOffset %d, validYPlaneSize %d.", + dstDataOffset, srcDataOffset, dstImgInfo.chromaOffset); + + int32_t y2UvRatio = 2; + dstDataOffset = dstImgInfo.chromaOffset; + srcDataOffset = srcImgInfo.chromaOffset; + for (int32_t uvh = 0; uvh < dstImgInfo.height / y2UvRatio; uvh++) { + err = memcpy_s(dstImgInfo.imgData + dstDataOffset, dstImgInfo.imgSize - dstDataOffset, + srcImgInfo.imgData + srcDataOffset, dstImgInfo.width); + if (err != EOK) { + DHLOGE("memcpy_s UVPlane in line[%d] failed.", uvh); + return DCAMERA_MEMORY_OPT_ERROR; + } + dstDataOffset += dstImgInfo.alignedWidth; + srcDataOffset += srcImgInfo.alignedWidth; + } + DHLOGD("Copy UVplane end, dstDataOffset %d, srcDataOffset %d.", dstDataOffset, srcDataOffset); + return DCAMERA_OK; +} + +int32_t DecodeDataProcess::CheckCopyImageInfo(const ImageUnitInfo& srcImgInfo, const ImageUnitInfo& dstImgInfo) +{ + if (srcImgInfo.imgData == nullptr || dstImgInfo.imgData == nullptr) { + DHLOGE("The imgData of srcImgInfo or the imgData of dstImgInfo are null!"); + return DCAMERA_BAD_VALUE; + } + if (srcImgInfo.colorFormat != dstImgInfo.colorFormat) { + DHLOGE("CopyInfo error : srcImgInfo colorFormat %d, dstImgInfo colorFormat %d.", + srcImgInfo.colorFormat, dstImgInfo.colorFormat); + return DCAMERA_BAD_VALUE; + } + + if (!IsCorrectImageUnitInfo(srcImgInfo)) { + DHLOGE("srcImginfo fail: width %d, height %d, alignedWidth %d, alignedHeight %d, chromaOffset %lld, " + + "imgSize %lld.", srcImgInfo.width, srcImgInfo.height, srcImgInfo.alignedWidth, srcImgInfo.alignedHeight, + srcImgInfo.chromaOffset, srcImgInfo.imgSize); + return DCAMERA_BAD_VALUE; + } + if (!IsCorrectImageUnitInfo(dstImgInfo)) { + DHLOGE("dstImginfo fail: width %d, height %d, alignedWidth %d, alignedHeight %d, chromaOffset %lld, " + + "imgSize %lld.", dstImgInfo.width, dstImgInfo.height, dstImgInfo.alignedWidth, dstImgInfo.alignedHeight, + dstImgInfo.chromaOffset, dstImgInfo.imgSize); + return DCAMERA_BAD_VALUE; + } + + if (dstImgInfo.width > srcImgInfo.alignedWidth || dstImgInfo.height > srcImgInfo.alignedHeight) { + DHLOGE("Comparison ImgInfo fail: dstwidth %d, dstheight %d, srcAlignedWidth %d, srcAlignedHeight %d.", + dstImgInfo.width, dstImgInfo.height, srcImgInfo.alignedWidth, srcImgInfo.alignedHeight); + return DCAMERA_BAD_VALUE; + } + return DCAMERA_OK; +} + +bool DecodeDataProcess::IsCorrectImageUnitInfo(const ImageUnitInfo& imgInfo) +{ + int32_t y2UvRatio = 2; + int32_t bytesPerPixel = 3; + size_t expectedImgSize = static_cast(imgInfo.alignedWidth * imgInfo.alignedHeight * + bytesPerPixel / y2UvRatio); + size_t expectedChromaOffset = static_cast(imgInfo.alignedWidth * imgInfo.alignedHeight); + return (imgInfo.width <= imgInfo.alignedWidth && imgInfo.height <= imgInfo.alignedHeight && + imgInfo.imgSize >= expectedImgSize && imgInfo.chromaOffset == expectedChromaOffset); +} + +void DecodeDataProcess::PostOutputDataBuffers(std::shared_ptr& outputBuffer) +{ + if (eventBusDecode_ == nullptr || outputBuffer == nullptr) { + DHLOGE("eventBusDecode_ or outputBuffer is null."); + return; + } + std::vector> multiDataBuffers; + multiDataBuffers.push_back(outputBuffer); + std::shared_ptr transNextNodePacket = std::make_shared(VideoCodecType::NO_CODEC, + multiDataBuffers); + DCameraCodecEvent dCamCodecEv(*this, transNextNodePacket, VideoCodecAction::NO_ACTION); + eventBusDecode_->PostEvent(dCamCodecEv, POSTMODE::POST_ASYNC); + DHLOGD("Send video decoder output asynchronous DCameraCodecEvents success."); +} + +int32_t DecodeDataProcess::DecodeDone(std::vector> outputBuffers) +{ + DHLOGD("Decoder Done."); + if (outputBuffers.empty()) { + DHLOGE("The received data buffers is empty."); + return DCAMERA_BAD_VALUE; + } + + if (nextDataProcess_ != nullptr) { + DHLOGD("Send to the next node of the decoder for processing."); + int32_t err = nextDataProcess_->ProcessData(outputBuffers); + if (err != DCAMERA_OK) { + DHLOGE("Someone node after the decoder processes fail."); + } + return err; + } + DHLOGD("The current node is the last node, and Output the processed video buffer"); + std::shared_ptr targetPipelineSource = callbackPipelineSource_.lock(); + if (targetPipelineSource == nullptr) { + DHLOGE("callbackPipelineSource_ is nullptr."); + return DCAMERA_BAD_VALUE; + } + targetPipelineSource->OnProcessedVideoBuffer(outputBuffers[0]); + return DCAMERA_OK; +} + +void DecodeDataProcess::OnEvent(DCameraCodecEvent& ev) +{ + DHLOGD("Receiving asynchronous DCameraCodecEvents."); + std::shared_ptr receivedCodecPacket = ev.GetCodecPacket(); + VideoCodecAction action = ev.GetAction(); + switch (action) { + case VideoCodecAction::NO_ACTION: { + if (receivedCodecPacket == nullptr) { + DHLOGE("the received codecPacket of action [%d] is null.", action); + OnError(); + return; + } + DecodeDone(receivedCodecPacket->GetDataBuffers()); + break; + } + case VideoCodecAction::ACTION_ONCE_AGAIN: + DHLOGD("Try FeedDecoderInputBuffer again."); + FeedDecoderInputBuffer(); + return; + default: + DHLOGD("The action : %d is not supported.", action); + return; + } +} + +void DecodeDataProcess::OnError() +{ + DHLOGD("DecodeDataProcess : OnError."); + isDecoderProcess_ = false; + videoDecoder_->Stop(); + std::shared_ptr targetPipelineSource = callbackPipelineSource_.lock(); + if (targetPipelineSource == nullptr) { + DHLOGE("callbackPipelineSource_ is nullptr."); + return; + } + targetPipelineSource->OnError(DataProcessErrorType::ERROR_PIPELINE_DECODER); +} + +void DecodeDataProcess::OnInputBufferAvailable(uint32_t index) +{ + DHLOGD("DecodeDataProcess::OnInputBufferAvailable"); + std::lock_guard lck(mtxHoldCount_); + if (availableInputIndexsQueue_.size() > VIDEO_DECODER_QUEUE_MAX) { + DHLOGE("Video decoder available indexs queue overflow."); + return; + } + DHLOGD("Video decoder available indexs queue push index [%d].", index); + availableInputIndexsQueue_.push(index); +} + +void DecodeDataProcess::OnOutputFormatChanged(const Media::Format &format) +{ + if (decodeOutputFormat_.GetFormatMap().empty()) { + DHLOGE("The first changed video decoder output format is null."); + return; + } + decodeOutputFormat_ = format; +} + +void DecodeDataProcess::OnOutputBufferAvailable(uint32_t index, const Media::AVCodecBufferInfo& info, + const Media::AVCodecBufferFlag& flag) +{ + if (!isDecoderProcess_) { + DHLOGE("Decoder node occurred error or start release."); + return; + } + DHLOGD("Video decode buffer info: presentation TimeUs %lld, size %d, offset %d, flag %d", + info.presentationTimeUs, info.size, info.offset, flag); + outputInfo_ = info; + { + std::lock_guard lck(mtxDecoderState_); + if (videoDecoder_ == nullptr) { + DHLOGE("The video decoder does not exist before decoding data."); + return; + } + int32_t errRelease = videoDecoder_->ReleaseOutputBuffer(index, true); + if (errRelease != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("The video decoder output decoded data to surface fail, index : [%d].", index); + } + } +} + +VideoConfigParams DecodeDataProcess::GetSourceConfig() const +{ + return sourceConfig_; +} + +VideoConfigParams DecodeDataProcess::GetTargetConfig() const +{ + return targetConfig_; +} + +void DecodeSurfaceListener::OnBufferAvailable() +{ + DHLOGD("DecodeSurfaceListener : OnBufferAvailable."); + std::shared_ptr targetDecoderNode = decodeVideoNode_.lock(); + if (targetDecoderNode == nullptr) { + DHLOGE("decodeVideoNode_ is nullptr."); + return; + } + targetDecoderNode->GetDecoderOutputBuffer(surface_); +} + +void DecodeSurfaceListener::SetSurface(const sptr& surface) +{ + surface_ = surface; +} + +void DecodeSurfaceListener::SetDecodeVideoNode(const std::weak_ptr& decodeVideoNode) +{ + decodeVideoNode_ = decodeVideoNode; +} + +DecodeSurfaceListener::~DecodeSurfaceListener() +{ + DHLOGD("DecodeSurfaceListener : ~DecodeSurfaceListener."); + surface_ = nullptr; +} +} +} \ No newline at end of file diff --git a/services/data_process/src/pipeline_node/multimedia_codec/encode_data_process_common.cpp b/services/data_process/src/pipeline_node/multimedia_codec/encode_data_process_common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05c91aeb06ac61343fd7be3c69f89444f9fc2337 --- /dev/null +++ b/services/data_process/src/pipeline_node/multimedia_codec/encode_data_process_common.cpp @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "encode_data_process.h" + +#include + +#include "display_type.h" +#include "distributed_hardware_log.h" +#include "graphic_common_c.h" + +#include "dcamera_utils_tools.h" +#include "encode_video_callback.h" + +#ifndef DH_LOG_TAG +#define DH_LOG_TAG "DCDP_NODE_ENCODEC" +#endif + +namespace OHOS { +namespace DistributedHardware { +const std::map EncodeDataProcess::ENCODER_BITRATE_TABLE = { + std::map::value_type(WIDTH_320_HEIGHT_240, BITRATE_500000), + std::map::value_type(WIDTH_480_HEIGHT_360, BITRATE_1110000), + std::map::value_type(WIDTH_640_HEIGHT_360, BITRATE_1500000), + std::map::value_type(WIDTH_640_HEIGHT_480, BITRATE_1800000), + std::map::value_type(WIDTH_720_HEIGHT_540, BITRATE_2100000), + std::map::value_type(WIDTH_960_HEIGHT_540, BITRATE_2300000), + std::map::value_type(WIDTH_960_HEIGHT_720, BITRATE_2800000), + std::map::value_type(WIDTH_1280_HEIGHT_720, BITRATE_3400000), + std::map::value_type(WIDTH_1440_HEIGHT_1080, BITRATE_5000000), + std::map::value_type(WIDTH_1920_HEIGHT_1080, BITRATE_6000000), +}; + +EncodeDataProcess::~EncodeDataProcess() +{ + if (isEncoderProcess_) { + DHLOGD("~EncodeDataProcess : ReleaseProcessNode."); + ReleaseProcessNode(); + } +} + +int32_t EncodeDataProcess::InitNode() +{ + DHLOGD("Common Init DCamera EncodeNode start."); + if (!(IsInEncoderRange(sourceConfig_) && IsInEncoderRange(targetConfig_))) { + DHLOGE("Common Source config or target config are invalid."); + return DCAMERA_BAD_VALUE; + } + if (!IsConvertible(sourceConfig_, targetConfig_)) { + DHLOGE("Common The EncodeNode cannot convert source VideoCodecType %d to target VideoCodecType %d.", + sourceConfig_.GetVideoCodecType(), targetConfig_.GetVideoCodecType()); + return DCAMERA_BAD_TYPE; + } + if (sourceConfig_.GetVideoCodecType() == targetConfig_.GetVideoCodecType()) { + DHLOGD("Common Disable EncodeNode. The target VideoCodecType %d is the same as the source VideoCodecType %d.", + sourceConfig_.GetVideoCodecType(), targetConfig_.GetVideoCodecType()); + return DCAMERA_OK; + } + + int32_t err = InitEncoder(); + if (err != DCAMERA_OK) { + DHLOGE("Common Init video encoder fail."); + ReleaseProcessNode(); + return err; + } + isEncoderProcess_ = true; + return DCAMERA_OK; +} + +bool EncodeDataProcess::IsInEncoderRange(const VideoConfigParams& curConfig) +{ + return (curConfig.GetWidth() >= MIN_VIDEO_WIDTH || curConfig.GetWidth() <= MAX_VIDEO_WIDTH || + curConfig.GetHeight() >= MIN_VIDEO_HEIGHT || curConfig.GetHeight() <= MAX_VIDEO_HEIGHT || + curConfig.GetFrameRate() <= MAX_FRAME_RATE); +} + +bool EncodeDataProcess::IsConvertible(const VideoConfigParams& sourceConfig, const VideoConfigParams& targetConfig) +{ + return (sourceConfig.GetVideoCodecType() == targetConfig.GetVideoCodecType() || + sourceConfig.GetVideoCodecType() == VideoCodecType::NO_CODEC); +} + +int32_t EncodeDataProcess::InitEncoder() +{ + DHLOGD("Common Init video encoder."); + int32_t err = InitEncoderMetadataFormat(); + if (err != DCAMERA_OK) { + DHLOGE("Common Init video encoder metadata format fail."); + return err; + } + err = InitEncoderBitrateFormat(); + if (err != DCAMERA_OK) { + DHLOGE("Common Init video encoder bitrate format fail."); + return err; + } + + videoEncoder_ = Media::VideoEncoderFactory::CreateByMime(processType_); + if (videoEncoder_ == nullptr) { + DHLOGE("Create video encoder failed."); + return DCAMERA_INIT_ERR; + } + encodeVideoCallback_ = std::make_shared(shared_from_this()); + int32_t retVal = videoEncoder_->SetCallback(encodeVideoCallback_); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Set video encoder callback failed."); + return DCAMERA_INIT_ERR; + } + retVal = videoEncoder_->Configure(metadataFormat_); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Set video encoder metadata format failed."); + return DCAMERA_INIT_ERR; + } + encodeProducerSurface_ = videoEncoder_->CreateInputSurface(); + if (encodeProducerSurface_ == nullptr) { + DHLOGE("Get video encoder producer surface failed."); + return DCAMERA_INIT_ERR; + } + retVal = videoEncoder_->Prepare(); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Video encoder prepare failed."); + return DCAMERA_INIT_ERR; + } + retVal = videoEncoder_->Start(); + if (retVal != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("Video encoder start failed."); + return DCAMERA_INIT_ERR; + } + DHLOGI("Common Init video encoder success"); + return DCAMERA_OK; +} + +int32_t EncodeDataProcess::InitEncoderMetadataFormat() +{ + DHLOGD("Common Init video encoder metadata format."); + processType_ = "video/mp4v-es"; + metadataFormat_.PutStringValue("codec_mime", processType_); + metadataFormat_.PutIntValue("codec_profile", Media::MPEG4Profile::MPEG4_PROFILE_ADVANCED_CODING); + + int32_t width = (int32_t)sourceConfig_.GetWidth(); + int32_t height = (int32_t)sourceConfig_.GetHeight(); + metadataFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::RGBA); + metadataFormat_.PutLongValue("max_input_size", width * height * 4); + metadataFormat_.PutIntValue("width", width); + metadataFormat_.PutIntValue("height", height); + metadataFormat_.PutIntValue("frame_rate", MAX_FRAME_RATE); + return DCAMERA_OK; +} + +int32_t EncodeDataProcess::InitEncoderBitrateFormat() +{ + DHLOGD("Init video encoder bitrate format."); + if (!(IsInEncoderRange(sourceConfig_) && IsInEncoderRange(targetConfig_))) { + DHLOGE("Source config or target config are invalid."); + return DCAMERA_BAD_VALUE; + } + metadataFormat_.PutIntValue("i_frame_interval", IDR_FRAME_INTERVAL_MS); + metadataFormat_.PutIntValue("video_encode_bitrate_mode", Media::VideoEncodeBitrateMode::VBR); + + if (ENCODER_BITRATE_TABLE.empty()) { + DHLOGD("ENCODER_BITRATE_TABLE is null, use the default bitrate of the encoder."); + return DCAMERA_OK; + } + int64_t pixelformat = static_cast(sourceConfig_.GetWidth() * sourceConfig_.GetHeight()); + int32_t matchedBitrate = BITRATE_6000000; + int64_t minPixelformatDiff = WIDTH_1920_HEIGHT_1080 - pixelformat; + for (auto it = ENCODER_BITRATE_TABLE.begin(); it != ENCODER_BITRATE_TABLE.end(); it++) { + int64_t pixelformatDiff = abs(pixelformat - it->first); + if (pixelformatDiff == 0) { + matchedBitrate = it->second; + break; + } + if (minPixelformatDiff >= pixelformatDiff) { + minPixelformatDiff = pixelformatDiff; + matchedBitrate = it->second; + } + } + DHLOGD("Source config: width : %d, height : %d, matched bitrate %d.", sourceConfig_.GetWidth(), + sourceConfig_.GetHeight(), matchedBitrate); + metadataFormat_.PutIntValue("bitrate", matchedBitrate); + return DCAMERA_OK; +} + +void EncodeDataProcess::ReleaseProcessNode() +{ + DHLOGD("Start release [%d] node : EncodeNode.", nodeRank_); + isEncoderProcess_ = false; + if (nextDataProcess_ != nullptr) { + nextDataProcess_->ReleaseProcessNode(); + } + + { + std::lock_guard lck(mtxEncoderState_); + if (videoEncoder_ != nullptr) { + DHLOGD("Start release videoEncoder."); + videoEncoder_->Flush(); + videoEncoder_->Stop(); + videoEncoder_->Release(); + encodeProducerSurface_ = nullptr; + videoEncoder_ = nullptr; + encodeVideoCallback_ = nullptr; + } + } + + waitEncoderOutputCount_ = 0; + lastFeedEncoderInputBufferTimeUs_ = 0; + inputTimeStampUs_ = 0; + processType_ = ""; + DHLOGD("Release [%d] node : EncodeNode end.", nodeRank_); +} + +int32_t EncodeDataProcess::ProcessData(std::vector>& inputBuffers) +{ + DHLOGD("Process data in EncodeDataProcess."); + if (inputBuffers.empty()) { + DHLOGE("The input data buffers is empty."); + return DCAMERA_BAD_VALUE; + } + if (sourceConfig_.GetVideoCodecType() == targetConfig_.GetVideoCodecType()) { + DHLOGD("The target VideoCodecType : %d is the same as the source VideoCodecType : %d.", + sourceConfig_.GetVideoCodecType(), targetConfig_.GetVideoCodecType()); + return EncodeDone(inputBuffers); + } + + if (videoEncoder_ == nullptr) { + DHLOGE("The video encoder does not exist before encoding data."); + return DCAMERA_INIT_ERR; + } + size_t bufferSize = 1920 * 1808 * 4; + if (inputBuffers[0]->Size() > bufferSize) { + DHLOGE("EncodeNode input buffer size %d error.", inputBuffers[0]->Size()); + return DCAMERA_MEMORY_OPT_ERROR; + } + if (!isEncoderProcess_) { + DHLOGE("EncodeNode occurred error or start release."); + return DCAMERA_DISABLE_PROCESS; + } + int32_t err = FeedEncoderInputBuffer(inputBuffers[0]); + if (err != DCAMERA_OK) { + DHLOGE("Feed encoder input Buffer fail."); + return err; + } + { + std::lock_guard lck(mtxHoldCount_); + if (inputTimeStampUs_ == 0) { + waitEncoderOutputCount_ += FIRST_FRAME_OUTPUT_NUM; + } else { + waitEncoderOutputCount_++; + } + DHLOGD("Wait encoder output frames number is %d.", waitEncoderOutputCount_); + } + return DCAMERA_OK; +} + +int32_t EncodeDataProcess::FeedEncoderInputBuffer(std::shared_ptr& inputBuffer) +{ + std::lock_guard lck(mtxEncoderState_); + DHLOGD("Feed encoder input buffer, buffer size %d.", inputBuffer->Size()); + if (encodeProducerSurface_ == nullptr) { + DHLOGE("Get encoder input producer surface failed."); + return DCAMERA_INIT_ERR; + } + sptr surfacebuffer = GetEncoderInputSurfaceBuffer(); + if (surfacebuffer == nullptr) { + DHLOGE("Get encoder input producer surface buffer failed."); + return DCAMERA_BAD_OPERATE; + } + uint8_t *addr = static_cast(surfacebuffer->GetVirAddr()); + if (addr == nullptr) { + DHLOGE("SurfaceBuffer address is nullptr"); + encodeProducerSurface_->CancelBuffer(surfacebuffer); + return DCAMERA_BAD_OPERATE; + } + size_t size = static_cast(surfacebuffer->GetSize()); + errno_t err = memcpy_s(addr, size, inputBuffer->Data(), inputBuffer->Size()); + DHLOGI("FeedEncoderInputBuffer size: %d, bufferSize: %d, err: %d", size, inputBuffer->Size(), err); + if (err != EOK) { + DHLOGE("memcpy_s encoder input producer surface buffer failed."); + return DCAMERA_MEMORY_OPT_ERROR; + } + inputTimeStampUs_ = GetEncoderTimeStamp(); + DHLOGD("Encoder input buffer size %d, timeStamp %lld.", inputBuffer->Size(), (long long)inputTimeStampUs_); + surfacebuffer->ExtraSet("timeStamp", inputTimeStampUs_); + BufferFlushConfig flushConfig = { {0, 0, sourceConfig_.GetWidth(), sourceConfig_.GetHeight()}, 0}; + SurfaceError ret = encodeProducerSurface_->FlushBuffer(surfacebuffer, -1, flushConfig); + if (ret != SURFACE_ERROR_OK) { + DHLOGE("Flush encoder input producer surface buffer failed."); + return DCAMERA_BAD_OPERATE; + } + return DCAMERA_OK; +} + +sptr EncodeDataProcess::GetEncoderInputSurfaceBuffer() +{ + BufferRequestConfig requestConfig; + requestConfig.width = static_cast(sourceConfig_.GetWidth()); + requestConfig.height = static_cast(sourceConfig_.GetHeight()); + requestConfig.usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA; + requestConfig.timeout = 0; + requestConfig.strideAlignment = ENCODER_STRIDE_ALIGNMENT; + requestConfig.format = PixelFormat::PIXEL_FMT_RGBA_8888; + sptr surfacebuffer = nullptr; + int32_t flushFence = -1; + GSError err = encodeProducerSurface_->RequestBuffer(surfacebuffer, flushFence, requestConfig); + if (err != GSERROR_OK || surfacebuffer == nullptr) { + DHLOGE("Request encoder input producer surface buffer failed, error code: %d.", err); + } + return surfacebuffer; +} + +int64_t EncodeDataProcess::GetEncoderTimeStamp() +{ + const int64_t nsPerUs = 1000L; + int64_t nowTimeUs = GetNowTimeStampUs() * nsPerUs; + return nowTimeUs; +} + +int32_t EncodeDataProcess::GetEncoderOutputBuffer(uint32_t index, Media::AVCodecBufferInfo info) +{ + DHLOGD("Get encoder output buffer."); + if (videoEncoder_ == nullptr) { + DHLOGE("The video encoder does not exist before output encoded data."); + return DCAMERA_BAD_VALUE; + } + std::shared_ptr sharedMemoryOutput = videoEncoder_->GetOutputBuffer(index); + if (sharedMemoryOutput == nullptr) { + DHLOGE("Failed to get the output shared memory, index : %d", index); + return DCAMERA_BAD_OPERATE; + } + + if (info.size <= 0) { + DHLOGE("AVCodecBufferInfo error, buffer size : %d", info.size); + return DCAMERA_BAD_VALUE; + } + + size_t outputMemoDataSize = static_cast(info.size); + DHLOGD("Encoder output buffer size : %d", outputMemoDataSize); + std::shared_ptr bufferOutput = std::make_shared(outputMemoDataSize); + errno_t err = memcpy_s(bufferOutput->Data(), bufferOutput->Size(), + sharedMemoryOutput->GetBase(), outputMemoDataSize); + if (err != EOK) { + DHLOGE("memcpy_s buffer failed."); + return DCAMERA_MEMORY_OPT_ERROR; + } + bufferOutput->SetInt64("timeUs", info.presentationTimeUs); + + std::vector> nextInputBuffers; + nextInputBuffers.push_back(bufferOutput); + return EncodeDone(nextInputBuffers); +} + +int32_t EncodeDataProcess::EncodeDone(std::vector> outputBuffers) +{ + DHLOGD("Encoder done."); + if (outputBuffers.empty()) { + DHLOGE("The received data buffers is empty."); + return DCAMERA_BAD_VALUE; + } + + if (nextDataProcess_ != nullptr) { + DHLOGD("Send to the next node of the encoder for processing."); + int32_t err = nextDataProcess_->ProcessData(outputBuffers); + if (err != DCAMERA_OK) { + DHLOGE("Someone node after the encoder processes fail."); + } + return err; + } + DHLOGD("The current node is the last node, and Output the processed video buffer"); + std::shared_ptr targetPipelineSink = callbackPipelineSink_.lock(); + if (targetPipelineSink == nullptr) { + DHLOGE("callbackPipelineSink_ is nullptr."); + return DCAMERA_BAD_VALUE; + } + targetPipelineSink->OnProcessedVideoBuffer(outputBuffers[0]); + return DCAMERA_OK; +} + +void EncodeDataProcess::OnError() +{ + DHLOGD("EncodeDataProcess : OnError."); + isEncoderProcess_ = false; + videoEncoder_->Flush(); + videoEncoder_->Stop(); + std::shared_ptr targetPipelineSink = callbackPipelineSink_.lock(); + if (targetPipelineSink == nullptr) { + DHLOGE("callbackPipelineSink_ is nullptr."); + return; + } + targetPipelineSink->OnError(DataProcessErrorType::ERROR_PIPELINE_ENCODER); +} + +void EncodeDataProcess::OnInputBufferAvailable(uint32_t index) +{ + DHLOGD("The available input buffer index : %d. No operation when using surface input.", index); +} + +void EncodeDataProcess::OnOutputFormatChanged(const Media::Format &format) +{ + if (encodeOutputFormat_.GetFormatMap().empty()) { + DHLOGE("The first changed video encoder output format is null."); + return; + } + encodeOutputFormat_ = format; +} + +void EncodeDataProcess::OnOutputBufferAvailable(uint32_t index, Media::AVCodecBufferInfo info, + Media::AVCodecBufferFlag flag) +{ + if (!isEncoderProcess_) { + DHLOGE("EncodeNode occurred error or start release."); + return; + } + DHLOGD("Video encode buffer info: presentation TimeUs %lld, size %d, offset %d, flag %d", + info.presentationTimeUs, info.size, info.offset, flag); + int32_t err = GetEncoderOutputBuffer(index, info); + if (err != DCAMERA_OK) { + DHLOGE("Get encode output Buffer fail."); + return; + } + { + std::lock_guard lck(mtxHoldCount_); + if (waitEncoderOutputCount_ <= 0) { + DHLOGE("The waitEncoderOutputCount_ = %d.", waitEncoderOutputCount_); + } + waitEncoderOutputCount_--; + DHLOGD("Wait encoder output frames number is %d.", waitEncoderOutputCount_); + } + if (videoEncoder_ == nullptr) { + DHLOGE("The video encoder does not exist before release output buffer index."); + return; + } + int32_t errRelease = videoEncoder_->ReleaseOutputBuffer(index); + if (errRelease != Media::MediaServiceErrCode::MSERR_OK) { + DHLOGE("The video encoder release output buffer fail, index : [%d].", index); + } +} +VideoConfigParams EncodeDataProcess::GetSourceConfig() const +{ + return sourceConfig_; +} + +VideoConfigParams EncodeDataProcess::GetTargetConfig() const +{ + return targetConfig_; +} +} +} \ No newline at end of file