From b6153fafa266ddc65bbd5a15bb58f203d83957ff Mon Sep 17 00:00:00 2001 From: renguang1116 Date: Mon, 12 Jun 2023 20:48:13 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E3=80=90=E9=9F=B3=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E7=BB=84=E4=BB=B6=E3=80=91common=E7=B1=BB?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0=20Signed-off-by:=20renguan?= =?UTF-8?q?g1116=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- av_transport/common/include/av_sync_utils.h | 21 +- .../common/include/av_trans_message.h | 5 + av_transport/common/include/av_trans_types.h | 14 +- av_transport/common/include/av_trans_utils.h | 3 + av_transport/common/src/av_sync_utils.cpp | 245 ++++++++++ av_transport/common/src/av_trans_buffer.cpp | 169 +++++++ av_transport/common/src/av_trans_log.cpp | 134 ++++++ av_transport/common/src/av_trans_message.cpp | 73 +++ av_transport/common/src/av_trans_meta.cpp | 109 +++++ av_transport/common/src/av_trans_utils.cpp | 302 +++++++++++++ .../common/src/softbus_channel_adapter.cpp | 425 ++++++++++++++++++ 11 files changed, 1496 insertions(+), 4 deletions(-) create mode 100644 av_transport/common/src/av_sync_utils.cpp create mode 100644 av_transport/common/src/av_trans_buffer.cpp create mode 100644 av_transport/common/src/av_trans_log.cpp create mode 100644 av_transport/common/src/av_trans_message.cpp create mode 100644 av_transport/common/src/av_trans_meta.cpp create mode 100644 av_transport/common/src/av_trans_utils.cpp create mode 100644 av_transport/common/src/softbus_channel_adapter.cpp diff --git a/av_transport/common/include/av_sync_utils.h b/av_transport/common/include/av_sync_utils.h index d053a31b..ff959ba0 100644 --- a/av_transport/common/include/av_sync_utils.h +++ b/av_transport/common/include/av_sync_utils.h @@ -43,7 +43,7 @@ struct AVSyncClockUnit { * @param name name for the shared memory. * @return shared memory struct, include fd, size and name. */ -AVTransSharedMemory CreateAVTransSharedMemory(const std::string &name); +AVTransSharedMemory CreateAVTransSharedMemory(const std::string &name, size_t size); /** * @brief close shared memory space. @@ -67,9 +67,26 @@ int32_t WriteClockUnitToMemory(const AVTransSharedMemory &memory, AVSyncClockUni */ int32_t ReadClockUnitFromMemory(const AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit); +/** + * @brief write frame number and pts into the shared memory space. + * @param memory shared memory + * @param frameNum the frame number + * @param timestamp the pts + * @return Returns DH_AVT_SUCCESS(0) if successful, otherwise returns other error code. + */ +int32_t WriteFrameInfoToMemory(const AVTransSharedMemory &memory, uint32_t frameNum, int64_t timestamp); + +/** + * @brief read frame number and pts from the shared memory space. + * @param memory shared memory + * @param frameNum the frame number + * @param timestamp the pts + * @return Returns DH_AVT_SUCCESS(0) if successful, otherwise returns other error code. + */ +int32_t ReadFrameInfoFromMemory(const AVTransSharedMemory &memory, uint32_t &frameNum, int64_t ×tamp); + bool IsInValidSharedMemory(const AVTransSharedMemory &memory); bool IsInValidClockUnit(const AVSyncClockUnit &clockUnit); -bool IsInValidUnitIndex(const AVSyncClockUnit &clockUnit); uint32_t U8ToU32(const uint8_t *ptr); uint64_t U8ToU64(const uint8_t *ptr); diff --git a/av_transport/common/include/av_trans_message.h b/av_transport/common/include/av_trans_message.h index 107a9e52..69a090f9 100644 --- a/av_transport/common/include/av_trans_message.h +++ b/av_transport/common/include/av_trans_message.h @@ -18,6 +18,7 @@ #include #include +#include "nlohmann/json.hpp" namespace OHOS { namespace DistributedHardware { @@ -30,6 +31,10 @@ public: std::string MarshalMessage(); bool UnmarshalMessage(const std::string &jsonStr); +private: + bool IsUInt32(const nlohmann::json &msgJson, const std::string &key); + bool IsString(const nlohmann::json &msgJson, const std::string &key); + public: uint32_t type_; std::string content_; diff --git a/av_transport/common/include/av_trans_types.h b/av_transport/common/include/av_trans_types.h index 06561fa8..d81e1a63 100644 --- a/av_transport/common/include/av_trans_types.h +++ b/av_transport/common/include/av_trans_types.h @@ -100,14 +100,23 @@ enum struct AVTransTag : uint32_t { PRE_TIMESTAMP, CUR_TIMESTAMP, ENGINE_READY, - AV_SYNC_GROUP_INFO, + START_AV_SYNC, + STOP_AV_SYNC, TIME_SYNC_RESULT, SHARED_MEMORY_FD, /* -------------------- d_audio tag -------------------- */ AUDIO_CHANNELS = SECTION_D_AUDIO_START + 1, AUDIO_SAMPLE_RATE, + AUDIO_CODEC_TYPE, + AUDIO_CHANNEL_MASK, AUDIO_SAMPLE_FORMAT, + AUDIO_FRAME_SIZE, + AUDIO_STREAM_USAGE, + AUDIO_RENDER_FLAGS, + AUDIO_CONTENT_TYPE, + AUDIO_CHANNEL_LAYOUT, + AUDIO_BIT_RATE, /* -------------------- d_video tag -------------------- */ VIDEO_WIDTH = SECTION_D_VIDEO_START + 1, @@ -130,7 +139,8 @@ enum struct EventType : uint32_t { EVENT_REMOTE_ERROR = 8, EVENT_DATA_RECEIVED = 9, EVENT_TIME_SYNC_RESULT = 10, - EVENT_NOTIFY_STREAM_INFO = 11, + EVENT_ADD_STREAM = 11, + EVENT_REMOVE_STREAM = 12, }; struct AVTransEvent { diff --git a/av_transport/common/include/av_trans_utils.h b/av_transport/common/include/av_trans_utils.h index 1d84412b..b49e02cf 100644 --- a/av_transport/common/include/av_trans_utils.h +++ b/av_transport/common/include/av_trans_utils.h @@ -39,6 +39,7 @@ using AVBuffer = OHOS::Media::Plugin::Buffer; constexpr int32_t MS_ONE_SECOND = 1000; SrcInputType TransName2InputType(const std::string &ownerName); +SrcInputType TransName2SoftbusInputType(const std::string &ownerName); MediaType TransName2MediaType(const std::string &ownerName); std::shared_ptr TransBuffer2HiSBuffer(const std::shared_ptr &transBuffer); @@ -58,6 +59,8 @@ bool IsString(const nlohmann::json &jsonObj, const std::string &key); int64_t GetCurrentTime(); +void GenerateAdtsHeader(unsigned char* adtsHeader, int packetLen, int profile, int sampleRate, int channels); + template inline std::shared_ptr ReinterpretCastPointer(const std::shared_ptr &ptr) noexcept { diff --git a/av_transport/common/src/av_sync_utils.cpp b/av_transport/common/src/av_sync_utils.cpp new file mode 100644 index 00000000..bc6b1c38 --- /dev/null +++ b/av_transport/common/src/av_sync_utils.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2023 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 "av_sync_utils.h" + +#include +#include +#include +#include "ashmem.h" + +#include "av_trans_errno.h" +#include "av_trans_log.h" + +namespace OHOS { +namespace DistributedHardware { +AVTransSharedMemory CreateAVTransSharedMemory(const std::string &name, size_t size) +{ + int32_t fd = AshmemCreate(name.c_str(), size); + if (fd <= 0) { + DHLOGE("create av trans shared memory failed, name=%s, fd=%" PRId32, name.c_str(), fd); + return AVTransSharedMemory{0, 0, name}; + } + + unsigned int prot = PROT_READ | PROT_WRITE; + int result = AshmemSetProt(fd, static_cast(prot)); + if (result < 0) { + DHLOGE("AshmemSetProt failed, name=%s, fd=%" PRId32, name.c_str(), fd); + (void)::close(fd); + return AVTransSharedMemory{0, 0, name}; + } + + void *addr = ::mmap(nullptr, size, static_cast(prot), MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + DHLOGE("shared memory mmap failed, name=%s, fd=%" PRId32, name.c_str(), fd); + (void)::close(fd); + return AVTransSharedMemory{0, 0, name}; + } + + uint8_t *base = reinterpret_cast(addr); + (void)memset_s(base, size, INVALID_VALUE_FALG, size); + + DHLOGI("create av trans shared memory success, name=%s, size=%" PRId32 ", fd=%" PRId32, name.c_str(), size, fd); + return AVTransSharedMemory{fd, size, name}; +} + +void CloseAVTransSharedMemory(const AVTransSharedMemory &memory) noexcept +{ + DHLOGI("close shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, memory.name.c_str(), memory.size, memory.fd); + if (IsInValidSharedMemory(memory)) { + DHLOGE("invalid input shared memory"); + return; + } + if (memory.fd > 0) { + (void)::close(memory.fd); + } +} + +int32_t WriteClockUnitToMemory(AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit) +{ + DHLOGI("write clock unit to shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, + memory.name.c_str(), memory.size, memory.fd); + TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory"); + + DHLOGI("clock unit index=%" PRId32 ", frameNum=%" PRId32 ", timestamp=%lld", clockUnit.index, + clockUnit.frameNum, (long long)clockUnit.timestamp); + TRUE_RETURN_V_MSG_E(IsInValidClockUnit(clockUnit), ERR_DH_AVT_INVALID_PARAM, "invalid input clock unit"); + + int size = AshmemGetSize(memory.fd); + TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size); + + unsigned int prot = PROT_READ | PROT_WRITE; + int result = AshmemSetProt(memory.fd, static_cast(prot)); + TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed"); + + void *addr = ::mmap(nullptr, static_cast(memory.size), static_cast(prot), MAP_SHARED, memory.fd, 0); + TRUE_RETURN_V_MSG_E(addr == MAP_FAILED, ERR_DH_AVT_SHARED_MEMORY_FAILED, "shared memory mmap failed"); + + uint8_t *base = reinterpret_cast(addr); + size_t fOffset = (sizeof(uint32_t) + sizeof(int64_t)) * clockUnit.index; + size_t tOffset = fOffset + sizeof(uint32_t); + U64ToU8(base + tOffset, clockUnit.timestamp); + U32ToU8(base + fOffset, clockUnit.frameNum); + + clockUnit.index ++; + if (clockUnit.index == MAX_CLOCK_UNIT_COUNT) { + clockUnit.index = 0; + } + return DH_AVT_SUCCESS; +} + +int32_t ReadClockUnitFromMemory(AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit) +{ + DHLOGI("read clock unit from shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, + memory.name.c_str(), memory.size, memory.fd); + TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory"); + + DHLOGI("clock unit index=%" PRId32 ", frameNum=%" PRId32, clockUnit.index, clockUnit.frameNum); + TRUE_RETURN_V_MSG_E((clockUnit.frameNum <= 0), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number"); + + int size = AshmemGetSize(memory.fd); + TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size); + + unsigned int prot = PROT_READ; + int result = AshmemSetProt(memory.fd, static_cast(prot)); + TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed"); + + void *addr = ::mmap(nullptr, static_cast(memory.size), static_cast(prot), MAP_SHARED, memory.fd, 0); + TRUE_RETURN_V_MSG_E(addr == MAP_FAILED, ERR_DH_AVT_SHARED_MEMORY_FAILED, "shared memory mmap failed"); + + uint8_t *base = reinterpret_cast(addr); + uint32_t firstUnit = U8ToU32(base); + TRUE_RETURN_V_MSG_E(firstUnit == 0, ERR_DH_AVT_MASTER_NOT_READY, "master queue not ready, clock is null."); + + uint32_t index = 0; + size_t unitSize = sizeof(uint32_t) + sizeof(int64_t); + while (index < MAX_CLOCK_UNIT_COUNT) { + uint32_t frameNum = U8ToU32(base + (index * unitSize)); + if (frameNum == clockUnit.frameNum) { + clockUnit.timestamp = U8ToU64(base + (index * unitSize) + sizeof(uint32_t)); + DHLOGI("read clock unit from shared memory success, frameNum=%" PRId32 ", timestamp=%lld", + clockUnit.frameNum, (long long)clockUnit.timestamp); + return DH_AVT_SUCCESS; + } + index++; + } + + DHLOGE("read clock unit from shared memory failed for frameNum=%" PRId32, clockUnit.frameNum); + return ERR_DH_AVT_SHARED_MEMORY_FAILED; +} + +int32_t WriteFrameInfoToMemory(const AVTransSharedMemory &memory, uint32_t frameNum, int64_t timestamp) +{ + DHLOGI("write frame number to shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, + memory.name.c_str(), memory.size, memory.fd); + TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory"); + + TRUE_RETURN_V_MSG_E((frameNum <= 0)), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number"); + + int size = AshmemGetSize(memory.fd); + TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size); + + unsigned int prot = PROT_READ | PROT_WRITE; + int result = AshmemSetProt(memory.fd, static_cast(prot)); + TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed"); + + void *addr = ::mmap(nullptr, static_cast(memory.size), static_cast(prot), MAP_SHARED, memory.fd, 0); + TRUE_RETURN_V_MSG_E(addr == MAP_FAILED, ERR_DH_AVT_SHARED_MEMORY_FAILED, "shared memory mmap failed"); + + uint8_t *base = reinterpret_cast(addr); + U32ToU8(base, frameNum); + U64ToU8(base + sizeof(uint32_t), timestamp); + + DHLOGI("write frameNum=%" PRId32 ", timestamp=%lld to shared memory success.", frameNum, (long long)timestamp); + return DH_AVT_SUCCESS; +} + +int32_t ReadFrameInfoFromMemory(const AVTransSharedMemory &memory, uint32_t &frameNum, int64_t ×tamp) +{ + DHLOGI("read frame number and pts from shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, + memory.name.c_str(), memory.size, memory.fd); + TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory"); + + int size = AshmemGetSize(memory.fd); + TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size); + + unsigned int prot = PROT_READ; + int result = AshmemSetProt(memory.fd, static_cast(prot)); + TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed"); + + void *addr = ::mmap(nullptr, static_cast(memory.size), static_cast(prot), MAP_SHARED, memory.fd, 0); + TRUE_RETURN_V_MSG_E(addr == MAP_FAILED, ERR_DH_AVT_SHARED_MEMORY_FAILED, "shared memory mmap failed"); + + uint8_t *base = reinterpret_cast(addr); + frameNum = U8ToU32(base); + timestamp = U8ToU64(base + sizeof(uint32_t)); + TRUE_RETURN_V_MSG_E(frameNum <= 0, ERR_DH_AVT_MASTER_NOT_READY, "master queue not ready, frameNum is null."); + + DHLOGI("read frameNum=%" PRId32 ", timestamp=%lld from shared memory success.", frameNum, (long long)timestamp); + return DH_AVT_SUCCESS; +} + +bool IsInValidSharedMemory(const AVTransSharedMemory &memory) +{ + return (memory.fd <= 0) || (memory.size <= 0) || memory.name.empty(); +} + +bool IsInValidClockUnit(const AVSyncClockUnit &clockUnit) +{ + return (clockUnit.index < 0) || (clockUnit.index >= MAX_CLOCK_UNIT_COUNT) || (clockUnit.frameNum <= 0) + || (clockUnit.timestamp <= 0); +} + +void U32ToU8(uint8_t *ptr, uint32_t value) +{ + ptr[0] = (uint8_t)((value) & 0xff); + ptr[1] = (uint8_t)((value >> 8) & 0xff); + ptr[2] = (uint8_t)((value >> 16) & 0xff); + ptr[3] = (uint8_t)((value >> 24) & 0xff); +} + +void U64ToU8(uint8_t *ptr, uint64_t value) +{ + ptr[0] = (uint8_t)((value) & 0xff); + ptr[1] = (uint8_t)((value >> 8) & 0xff); + ptr[2] = (uint8_t)((value >> 16) & 0xff); + ptr[3] = (uint8_t)((value >> 24) & 0xff); + ptr[4] = (uint8_t)((value >> 32) & 0xff); + ptr[5] = (uint8_t)((value >> 40) & 0xff); + ptr[6] = (uint8_t)((value >> 48) & 0xff); + ptr[7] = (uint8_t)((value >> 56) & 0xff); +} + +uint32_t U8ToU32(const uint8_t *ptr) +{ + return (((uint32_t)(ptr[0] & 0xff)) | + ((uint32_t)(ptr[1] & 0xff) << 8) | + ((uint32_t)(ptr[2] & 0xff) << 16) | + ((uint32_t)(ptr[3] & 0xff) << 24)); +} + +uint64_t U8ToU64(const uint8_t *ptr) +{ + return (((uint64_t)(ptr[0] & 0xff)) | + ((uint64_t)(ptr[1] & 0xff) << 8) | + ((uint64_t)(ptr[2] & 0xff) << 16) | + ((uint64_t)(ptr[3] & 0xff) << 24) | + ((uint64_t)(ptr[4] & 0xff) << 32) | + ((uint64_t)(ptr[5] & 0xff) << 40) | + ((uint64_t)(ptr[6] & 0xff) << 48) | + ((uint64_t)(ptr[7] & 0xff) << 56)); +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/common/src/av_trans_buffer.cpp b/av_transport/common/src/av_trans_buffer.cpp new file mode 100644 index 00000000..effa862c --- /dev/null +++ b/av_transport/common/src/av_trans_buffer.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2023 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 "av_trans_buffer.h" + +#include + +namespace OHOS { +namespace DistributedHardware { +AVTransBuffer::AVTransBuffer(MetaType type) : meta_() +{ + meta_ = std::make_shared(type); +} + +std::shared_ptr AVTransBuffer::CreateBufferData(size_t capacity) +{ + auto bufData = std::make_shared(capacity); + data_.push_back(bufData); + return bufData; +} + +std::shared_ptr AVTransBuffer::WrapBufferData(const uint8_t* data, size_t capacity, size_t size) +{ + auto bufData = std::make_shared(capacity, std::shared_ptr(const_cast(data), [](void* ptr) {})); + bufData->SetSize(size); + data_.push_back(bufData); + return bufData; +} + +std::shared_ptr AVTransBuffer::GetBufferData(uint32_t index) +{ + if (data_.size() <= index) { + return nullptr; + } + return data_[index]; +} + +std::shared_ptr AVTransBuffer::GetBufferMeta() +{ + return meta_; +} + +void AVTransBuffer::UpdateBufferMeta(std::shared_ptr bufferMeta) +{ + meta_ = bufferMeta; +} + +uint32_t AVTransBuffer::GetDataCount() +{ + return data_.size(); +} + +bool AVTransBuffer::IsEmpty() +{ + return data_.empty(); +} + +void AVTransBuffer::Reset() +{ + data_[0]->Reset(); + MetaType type = meta_->GetMetaType(); + meta_.reset(); + meta_ = std::make_shared(type); +} + +BufferData::BufferData(size_t capacity) + : capacity_(capacity), size_(0), address_(nullptr) +{ + address_ = std::shared_ptr(new uint8_t[capacity], std::default_delete()); +} + +BufferData::BufferData(size_t capacity, std::shared_ptr bufData) + : capacity_(capacity), size_(0), address_(std::move(bufData)) +{ +} + +size_t BufferData::GetSize() +{ + return size_; +} + +size_t BufferData::GetCapacity() +{ + return capacity_; +} + +uint8_t* BufferData::GetAddress() const +{ + return address_.get(); +} + +size_t BufferData::Write(const uint8_t* in, size_t writeSize, size_t position) +{ + size_t start = 0; + if (position == INVALID_POSITION) { + start = size_; + } else { + start = std::min(position, capacity_); + } + size_t length = std::min(writeSize, capacity_ - start); + if (memcpy_s(GetAddress() + start, length, in, length) != EOK) { + return 0; + } + size_ = start + length; + return length; +} + +size_t BufferData::Read(uint8_t* out, size_t readSize, size_t position) +{ + size_t start = 0; + size_t maxLength = size_; + if (position != INVALID_POSITION) { + start = std::min(position, size_); + maxLength = size_ - start; + } + size_t length = std::min(readSize, maxLength); + if (memcpy_s(out, length, GetAddress() + start, length) != EOK) { + return 0; + } + return length; +} + +void BufferData::Reset() +{ + this->size_ = 0; +} + +void BufferData::SetSize(size_t size) +{ + this->size_ = size; +} + +BufferMeta::BufferMeta(MetaType type) : type_(type) +{ +} + +bool BufferMeta::GetMetaItem(AVTransTag tag, std::string& value) +{ + if (tagMap_.count(tag) != 0) { + value = tagMap_[tag]; + return true; + } else { + return false; + } +} + +void BufferMeta::SetMetaItem(AVTransTag tag, const std::string& value) +{ + tagMap_[tag] = value; +} + +MetaType BufferMeta::GetMetaType() const +{ + return type_; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/common/src/av_trans_log.cpp b/av_transport/common/src/av_trans_log.cpp new file mode 100644 index 00000000..9b150b9a --- /dev/null +++ b/av_transport/common/src/av_trans_log.cpp @@ -0,0 +1,134 @@ +/* + * 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 "av_trans_log.h" + +#include "securec.h" + +#ifdef HI_LOG_ENABLE +#include "hilog/log.h" +#else +#include +#endif + +namespace OHOS { +namespace DistributedHardware { +const std::string DAVTRANS_LOG_TITLE_TAG = "DAVTRANS"; +constexpr int32_t LOG_MAX_LEN = 4096; + +static void DHLogOut(DHLogLevel logLevel, const char *logBuf) +{ +#ifdef HI_LOG_ENABLE + LogLevel hiLogLevel = LOG_INFO; + switch (logLevel) { + case DH_LOG_DEBUG: + hiLogLevel = LOG_DEBUG; + break; + case DH_LOG_INFO: + hiLogLevel = LOG_INFO; + break; + case DH_LOG_WARN: + hiLogLevel = LOG_WARN; + break; + case DH_LOG_ERROR: + hiLogLevel = LOG_ERROR; + break; + default: + break; + } + (void)HiLogPrint(LOG_CORE, hiLogLevel, LOG_DOMAIN, DAVTRANS_LOG_TITLE_TAG.c_str(), "%{public}s", logBuf); +#else + switch (logLevel) { + case DH_LOG_DEBUG: + printf("[D]%s\n", logBuf); + break; + case DH_LOG_INFO: + printf("[I]%s\n", logBuf); + break; + case DH_LOG_WARN: + printf("[W]%s\n", logBuf); + break; + case DH_LOG_ERROR: + printf("[E]%s\n", logBuf); + break; + default: + break; + } +#endif +} + +void DHLog(DHLogLevel logLevel, const char *fmt, ...) +{ + char logBuf[LOG_MAX_LEN] = {0}; + va_list arg; + + (void)memset_s(&arg, sizeof(va_list), 0, sizeof(va_list)); + va_start(arg, fmt); + int32_t ret = vsprintf_s(logBuf, sizeof(logBuf), fmt, arg); + va_end(arg); + if (ret < 0) { + DHLogOut(logLevel, "DH log length error."); + return; + } + DHLogOut(logLevel, logBuf); +} + +std::string GetAnonyString(const std::string &value) +{ + constexpr size_t INT32_SHORT_ID_LENGTH = 20; + constexpr size_t INT32_PLAINTEXT_LENGTH = 4; + constexpr size_t INT32_MIN_ID_LENGTH = 3; + std::string res; + std::string tmpStr("******"); + size_t strLen = value.length(); + if (strLen < INT32_MIN_ID_LENGTH) { + return tmpStr; + } + + if (strLen <= INT32_SHORT_ID_LENGTH) { + res += value[0]; + res += tmpStr; + res += value[strLen - 1]; + } else { + res.append(value, 0, INT32_PLAINTEXT_LENGTH); + res += tmpStr; + res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH); + } + + return res; +} + +std::string GetAnonyInt32(const int32_t value) +{ + constexpr int32_t INT32_STRING_LENGTH = 40; + char tempBuffer[INT32_STRING_LENGTH] = ""; + int32_t secRet = sprintf_s(tempBuffer, INT32_STRING_LENGTH, "%d", value); + if (secRet <= 0) { + std::string nullString(""); + return nullString; + } + size_t length = strlen(tempBuffer); + for (size_t i = 1; i <= length - 1; i++) { + tempBuffer[i] = '*'; + } + if (length == 0x01) { + tempBuffer[0] = '*'; + } + + std::string tempString(tempBuffer); + return tempString; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/common/src/av_trans_message.cpp b/av_transport/common/src/av_trans_message.cpp new file mode 100644 index 00000000..d151cd2d --- /dev/null +++ b/av_transport/common/src/av_trans_message.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 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 "av_trans_message.h" + +#include "av_trans_constants.h" + +namespace OHOS { +namespace DistributedHardware { +const std::string KEY_TYPE = "type"; +const std::string KEY_CONTENT = "content"; +const std::string KEY_DST_DEVID = "dstDevId"; + +AVTransMessage::AVTransMessage() +{ +} + +AVTransMessage::AVTransMessage(uint32_t type, std::string content, std::string dstDevId) + : type_(type), content_(content), dstDevId_(dstDevId) +{ +} + +AVTransMessage::~AVTransMessage() +{ +} + +std::string AVTransMessage::MarshalMessage() +{ + nlohmann::json msgJson; + msgJson[KEY_TYPE] = type_; + msgJson[KEY_CONTENT] = content_; + msgJson[KEY_DST_DEVID] = dstDevId_; + return msgJson.dump(); +} + +bool AVTransMessage::UnmarshalMessage(const std::string& jsonStr) +{ + nlohmann::json msgJson = nlohmann::json::parse(jsonStr, nullptr, false); + if (msgJson.is_discarded()) { + return false; + } + if (!IsUInt32(msgJson, KEY_TYPE) || !IsString(msgJson, KEY_CONTENT) || !IsString(msgJson, KEY_DST_DEVID)) { + return false; + } + type_ = msgJson[KEY_TYPE].get(); + content_ = msgJson[KEY_CONTENT].get(); + dstDevId_ = msgJson[KEY_DST_DEVID].get(); + return true; +} + +bool AVTransMessage::IsUInt32(const nlohmann::json &msgJson, const std::string &key) +{ + return msgJson.contains(key) && msgJson[key].is_number_unsigned() && msgJson[key] <= UINT32_MAX; +} + +bool AVTransMessage::IsString(const nlohmann::json &msgJson, const std::string &key) +{ + return msgJson.contains(key) && msgJson[key].is_string() && msgJson[key].size() <= MAX_MESSAGES_LEN; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/common/src/av_trans_meta.cpp b/av_transport/common/src/av_trans_meta.cpp new file mode 100644 index 00000000..a6931f6d --- /dev/null +++ b/av_transport/common/src/av_trans_meta.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 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 "av_trans_meta.h" + +#include "av_trans_utils.h" +#include "nlohmann/json.hpp" + +namespace OHOS { +namespace DistributedHardware { +const std::string META_DATA_TYPE = "meta_data_type"; +const std::string META_TIMESTAMP = "meta_timestamp"; +const std::string META_FRAME_NUMBER = "meta_frame_number"; + +std::shared_ptr AVTransAudioBufferMeta::Clone() +{ + auto bufferMeta = std::make_shared(); + bufferMeta->pts_ = pts_; + bufferMeta->cts_ = cts_; + bufferMeta->format_ = format_; + bufferMeta->dataType_ = dataType_; + bufferMeta->frameNum_ = frameNum_; + bufferMeta->channels_ = channels_; + bufferMeta->sampleRate_ = sampleRate_; + bufferMeta->Upate(*this); + return bufferMeta; +} + +std::string AVTransAudioBufferMeta::MarshalAudioMeta() +{ + nlohmann::json metaJson; + metaJson[META_DATA_TYPE] = dataType_; + metaJson[META_TIMESTAMP] = pts_; + metaJson[META_FRAME_NUMBER] = frameNum_; + return metaJson.dump(); +} + +bool AVTransAudioBufferMeta::UnmarshalAudioMeta(const std::string& jsonStr) +{ + nlohmann::json metaJson = nlohmann::json::parse(jsonStr, nullptr, false); + if (metaJson.is_discarded()) { + return false; + } + if (!metaJson.contains(META_DATA_TYPE) || !metaJson.contains(META_TIMESTAMP) || !metaJson.contains(META_FRAME_NUMBER)) { + return false; + } + if (!IsUInt32(metaJson, META_DATA_TYPE) || !IsInt64(metaJson, META_TIMESTAMP) || !IsUInt32(metaJson, META_FRAME_NUMBER)) { + return false; + } + dataType_ = metaJson[META_DATA_TYPE].get(); + pts_ = metaJson[META_TIMESTAMP].get(); + frameNum_ = metaJson[META_FRAME_NUMBER].get(); + return true; +} + +std::shared_ptr AVTransVideoBufferMeta::Clone() +{ + auto bufferMeta = std::make_shared(); + bufferMeta->pts_ = pts_; + bufferMeta->cts_ = cts_; + bufferMeta->width_ = width_; + bufferMeta->height_ = height_; + bufferMeta->format_ = format_; + bufferMeta->dataType_ = dataType_; + bufferMeta->frameNum_ = frameNum_; + bufferMeta->Upate(*this); + return bufferMeta; +} + +std::string AVTransVideoBufferMeta::MarshalVideoMeta() +{ + nlohmann::json metaJson; + metaJson[META_DATA_TYPE] = dataType_; + metaJson[META_TIMESTAMP] = pts_; + metaJson[META_FRAME_NUMBER] = frameNum_; + return metaJson.dump(); +} + +bool AVTransVideoBufferMeta::UnmarshalVideoMeta(const std::string& jsonStr) +{ + nlohmann::json metaJson = nlohmann::json::parse(jsonStr, nullptr, false); + if (metaJson.is_discarded()) { + return false; + } + if (!metaJson.contains(META_DATA_TYPE) || !metaJson.contains(META_TIMESTAMP) || !metaJson.contains(META_FRAME_NUMBER)) { + return false; + } + if (!IsUInt32(metaJson, META_DATA_TYPE) || !IsInt64(metaJson, META_TIMESTAMP) || !IsUInt32(metaJson, META_FRAME_NUMBER)) { + return false; + } + dataType_ = metaJson[META_DATA_TYPE].get(); + pts_ = metaJson[META_TIMESTAMP].get(); + frameNum_ = metaJson[META_FRAME_NUMBER].get(); + return true; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/common/src/av_trans_utils.cpp b/av_transport/common/src/av_trans_utils.cpp new file mode 100644 index 00000000..e0f717b2 --- /dev/null +++ b/av_transport/common/src/av_trans_utils.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2023 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 "av_trans_utils.h" + +#include +#include + +#include "av_trans_constants.h" +#include "av_trans_log.h" +#include "av_trans_meta.h" + +#include "plugin/common/share_allocator.h" + +namespace OHOS { +namespace DistributedHardware { +using HiSBufferMeta = OHOS::Media::Plugin::BufferMeta; +using TransBufferMeta = OHOS::DistributedHardware::BufferMeta; + +const std::string KEY_OWNER_NAME = "ownerName"; +const std::string KEY_PEER_DEVID = "peerDevId"; + +SrcInputType TransName2InputType(const std::string &ownerName) +{ + const static std::pair mapArray[] = { + {OWNER_NAME_D_MIC, SrcInputType::D_MIC}, + {OWNER_NAME_D_CAMERA, SrcInputType::D_CAMERA}, + {OWNER_NAME_D_SCREEN, SrcInputType::D_SCREEN}, + {OWNER_NAME_D_SPEAKER, SrcInputType::D_SPEAKER}, + }; + for (const auto& item : mapArray) { + if (item.first == ownerName) { + return item.second; + } + } + return SrcInputType::UNKNOWN; +} + +SrcInputType TransName2SoftbusInputType(const std::string &ownerName) +{ + const static std::pair mapArray[] = { + {OWNER_NAME_D_MIC, SrcInputType::D_SOFTBUS_AUDIO}, + {OWNER_NAME_D_CAMERA, SrcInputType::D_SOFTBUS_VIDEO}, + {OWNER_NAME_D_SCREEN, SrcInputType::D_SOFTBUS_VIDEO}, + {OWNER_NAME_D_SPEAKER, SrcInputType::D_SOFTBUS_AUDIO}, + }; + for (const auto& item : mapArray) { + if (item.first == ownerName) { + return item.second; + } + } + return SrcInputType::UNKNOWN; +} + +OHOS::Media::Plugin::MediaType TransName2MediaType(const std::string &ownerName) +{ + const static std::pair mapArray[] = { + {OWNER_NAME_D_MIC, OHOS::Media::Plugin::MediaType::AUDIO}, + {OWNER_NAME_D_CAMERA, OHOS::Media::Plugin::MediaType::VIDEO}, + {OWNER_NAME_D_SCREEN, OHOS::Media::Plugin::MediaType::VIDEO}, + {OWNER_NAME_D_SPEAKER, OHOS::Media::Plugin::MediaType::AUDIO}, + }; + for (const auto& item : mapArray) { + if (item.first == ownerName) { + return item.second; + } + } + return OHOS::Media::Plugin::MediaType::UNKNOWN; +} + +std::string BuildChannelDescription(const std::string &ownerName, const std::string &peerDevId) +{ + nlohmann::json descJson; + descJson[KEY_OWNER_NAME] = ownerName; + descJson[KEY_PEER_DEVID] = peerDevId; + return descJson.dump(); +} + +void ParseChannelDescription(const std::string &descJsonStr, std::string &ownerName, std::string &peerDevId) +{ + nlohmann::json descJson = nlohmann::json::parse(descJsonStr, nullptr, false); + if (descJson.is_discarded()) { + return; + } + if (!descJson.contains(KEY_OWNER_NAME) || !descJson.contains(KEY_PEER_DEVID)) { + return; + } + if (!IsString(descJson, KEY_OWNER_NAME) || !IsString(descJson, KEY_PEER_DEVID)) { + return; + } + ownerName = descJson[KEY_OWNER_NAME].get(); + peerDevId = descJson[KEY_PEER_DEVID].get(); +} + +std::shared_ptr TransBuffer2HiSBuffer(const std::shared_ptr& transBuffer) +{ + if ((transBuffer == nullptr) || transBuffer->IsEmpty()) { + return nullptr; + } + auto hisBuffer = std::make_shared(); + for (uint32_t index = 0; index < transBuffer->GetDataCount(); index++) { + auto data = transBuffer->GetBufferData(index); + hisBuffer->WrapMemory(data->GetAddress(), data->GetCapacity(), data->GetSize()); + } + Convert2HiSBufferMeta(transBuffer, hisBuffer); + return hisBuffer; +} + +std::shared_ptr HiSBuffer2TransBuffer(const std::shared_ptr& hisBuffer) +{ + if ((hisBuffer == nullptr) || hisBuffer->IsEmpty()) { + return nullptr; + } + auto transBuffer = std::make_shared(); + for (uint32_t index = 0; index < hisBuffer->GetMemoryCount(); index++) { + auto memory = hisBuffer->GetMemory(index); + transBuffer->WrapBufferData(memory->GetReadOnlyData(), memory->GetCapacity(), memory->GetSize()); + } + Convert2TransBufferMeta(hisBuffer, transBuffer); + return transBuffer; +} + +void Convert2HiSBufferMeta(std::shared_ptr transBuffer, std::shared_ptr hisBuffer) +{ + std::shared_ptr transMeta = transBuffer->GetBufferMeta(); + if ((transMeta->GetMetaType() == MetaType::AUDIO)) { + auto hisAMeta = std::make_shared(); + + std::string value; + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::BUFFER_DATA_TYPE, value), "get BUFFER_DATA_TYPE meta failed"); + uint32_t dataType = std::atoi(value.c_str()); + hisAMeta->dataType_ = (BufferDataType)dataType; + + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::AUDIO_SAMPLE_FORMAT, value), "get AUDIO_SAMPLE_FORMAT meta failed"); + uint32_t format = std::atoi(value.c_str()); + hisAMeta->format_ = (AudioSampleFormat)format; + + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::AUDIO_SAMPLE_RATE, value), "get AUDIO_SAMPLE_RATE meta failed"); + hisAMeta->sampleRate_ = std::atoi(value.c_str()); + + hisBuffer->UpdateBufferMeta(*hisAMeta); + } else { + auto hisVMeta = std::make_shared(); + + std::string value; + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::BUFFER_DATA_TYPE, value), "get BUFFER_DATA_TYPE meta failed"); + uint32_t dataType = std::atoi(value.c_str()); + hisVMeta->dataType_ = (BufferDataType)dataType; + + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::VIDEO_PIXEL_FORMAT, value), "get VIDEO_PIXEL_FORMAT meta failed"); + uint32_t format = std::atoi(value.c_str()); + hisVMeta->format_ = (VideoPixelFormat)format; + + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::VIDEO_WIDTH, value), "get VIDEO_WIDTH meta failed"); + hisVMeta->width_ = std::atoi(value.c_str()); + + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::VIDEO_HEIGHT, value), "get VIDEO_HEIGHT meta failed"); + hisVMeta->height_ = std::atoi(value.c_str()); + + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::PRE_TIMESTAMP, value), "get PRE_TIMESTAMP meta failed"); + hisVMeta->pts_ = std::stoll(value.c_str()); + + hisBuffer->pts = std::stoll(value.c_str()); + hisBuffer->UpdateBufferMeta(*hisVMeta); + } +} + +void Convert2TransBufferMeta(std::shared_ptr hisBuffer, std::shared_ptr transBuffer) +{ + std::shared_ptr hisMeta = hisBuffer->GetBufferMeta(); + if ((hisMeta->GetType() == BufferMetaType::AUDIO)) { + std::shared_ptr hisAMeta = ReinterpretCastPointer(hisMeta); + TRUE_RETURN(hisAMeta == nullptr, "hisAMeta is null"); + + auto transAMeta = std::make_shared(MetaType::AUDIO); + transAMeta->SetMetaItem(AVTransTag::BUFFER_DATA_TYPE, std::to_string((uint32_t)(hisAMeta->dataType_))); + transAMeta->SetMetaItem(AVTransTag::AUDIO_SAMPLE_FORMAT, std::to_string((uint32_t)(hisAMeta->format_))); + transAMeta->SetMetaItem(AVTransTag::AUDIO_SAMPLE_RATE, std::to_string(hisAMeta->sampleRate_)); + + transBuffer->UpdateBufferMeta(transAMeta); + } else { + std::shared_ptr hisVMeta = ReinterpretCastPointer(hisMeta); + TRUE_RETURN(hisVMeta == nullptr, "hisAMeta is null"); + + auto transVMeta = std::make_shared(MetaType::VIDEO); + transVMeta->SetMetaItem(AVTransTag::BUFFER_DATA_TYPE, std::to_string((uint32_t)(hisVMeta->dataType_))); + transVMeta->SetMetaItem(AVTransTag::VIDEO_PIXEL_FORMAT, std::to_string((uint32_t)(hisVMeta->format_))); + transVMeta->SetMetaItem(AVTransTag::VIDEO_WIDTH, std::to_string(hisVMeta->width_)); + transVMeta->SetMetaItem(AVTransTag::VIDEO_HEIGHT, std::to_string(hisVMeta->height_)); + transVMeta->SetMetaItem(AVTransTag::PRE_TIMESTAMP, std::to_string(hisVMeta->pts_)); + + transBuffer->UpdateBufferMeta(transVMeta); + } +} + +EventType CastEventType(Plugin::PluginEventType type) +{ + switch (type) { + case Plugin::PluginEventType::EVENT_CHANNEL_OPENED: + return EventType::EVENT_START_SUCCESS; + case Plugin::PluginEventType::EVENT_CHANNEL_OPEN_FAIL: + return EventType::EVENT_START_FAIL; + case Plugin::PluginEventType::EVENT_CHANNEL_CLOSED: + return EventType::EVENT_CHANNEL_CLOSED; + default: + DHLOGE("unsupport plugin event type."); + } + return EventType::EVENT_ENGINE_ERROR; +} + +void DumpBufferToFile(std::string fileName, uint8_t *buffer, int32_t bufSize) +{ + if (fileName.empty()) { + DHLOGE("input fileName is empty."); + return; + } + std::ofstream ofs(fileName, std::ios::binary | std::ios::out | std::ios::app); + if (!ofs.is_open()) { + DHLOGE("open file failed."); + return; + } + ofs.write((const char*)(buffer), bufSize); + ofs.close(); +} + +bool IsUInt32(const nlohmann::json &jsonObj, const std::string &key) +{ + bool res = jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT32_MAX; + if (!res) { + DHLOGE("the key %s in jsonObj is invalid.", key.c_str()); + } + return res; +} + +bool IsInt64(const nlohmann::json &jsonObj, const std::string &key) +{ + bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && INT64_MIN <= jsonObj[key] && + jsonObj[key] <= INT64_MAX; + if (!res) { + DHLOGE("the key %s in jsonObj is invalid.", key.c_str()); + } + return res; +} + +bool IsString(const nlohmann::json &jsonObj, const std::string &key) +{ + bool res = jsonObj.contains(key) && jsonObj[key].is_string() && jsonObj[key].size() <= MAX_MESSAGES_LEN; + if (!res) { + DHLOGE("the key %s in jsonObj is invalid.", key.c_str()); + } + return res; +} + +int64_t GetCurrentTime() +{ + struct timeval tv { + 0 + }; + gettimeofday(&tv, nullptr); + return tv.tv_sec * MS_ONE_SECOND + tv.tv_usec / MS_ONE_SECOND; +} + +void GenerateAdtsHeader(unsigned char* adtsHeader, int packetLen, int profile, int sampleRate, int channels) +{ + static std::map mapSampleRateToFreIndex { + {96000, 0}, + {88200, 1}, + {64000, 2}, + {48000, 3}, + {44100, 4}, + {32000, 5}, + {24000, 6}, + {16000, 8}, + {12000, 9}, + {11025, 10}, + {8000, 11}, + {7350, 12}, + }; + // profile only support AAC LC: 1 + int freqIdx = mapSampleRateToFreIndex[sampleRate]; // 48KHz : 3 + adtsHeader[0] = (unsigned char) 0xFF; + adtsHeader[1] = (unsigned char) 0xF9; + adtsHeader[2] = (unsigned char) (((profile - 1) << 6) + (freqIdx << 2) + (channels >> 2)); + adtsHeader[3] = (unsigned char) (((channels & 3) << 6) + (packetLen >> 11)); + adtsHeader[4] = (unsigned char) ((packetLen & 0x7FF) >> 3); + adtsHeader[5] = (unsigned char) (((packetLen & 7) << 5) + 0x1F); + adtsHeader[6] = (unsigned char) 0xFC; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/common/src/softbus_channel_adapter.cpp b/av_transport/common/src/softbus_channel_adapter.cpp new file mode 100644 index 00000000..591ca347 --- /dev/null +++ b/av_transport/common/src/softbus_channel_adapter.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2022-2023 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 "softbus_channel_adapter.h" + +#include +#include +#include + +#include "av_trans_constants.h" +#include "av_trans_errno.h" +#include "av_trans_log.h" + +namespace OHOS { +namespace DistributedHardware { +IMPLEMENT_SINGLE_INSTANCE(SoftbusChannelAdapter); + +static int32_t OnSessionOpened(int32_t sessionId, int32_t result) +{ + return SoftbusChannelAdapter::GetInstance().OnSoftbusChannelOpened(sessionId, result); +} + +static void OnSessionClosed(int32_t sessionId) +{ + SoftbusChannelAdapter::GetInstance().OnSoftbusChannelClosed(sessionId); +} + +static void OnBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen) +{ + SoftbusChannelAdapter::GetInstance().OnSoftbusBytesReceived(sessionId, data, dataLen); +} + +static void OnStreamReceived(int32_t sessionId, const StreamData *data, const StreamData *ext, + const StreamFrameInfo *frameInfo) +{ + SoftbusChannelAdapter::GetInstance().OnSoftbusStreamReceived(sessionId, data, ext, frameInfo); +} + +static void onTimeSyncResult(const TimeSyncResultInfo *info, int32_t result) +{ + SoftbusChannelAdapter::GetInstance().OnSoftbusTimeSyncResult(info, result); +} + +SoftbusChannelAdapter::SoftbusChannelAdapter() +{ + DHLOGI("SoftbusChannelAdapter ctor."); + sessListener_.OnSessionOpened = OnSessionOpened; + sessListener_.OnSessionClosed = OnSessionClosed; + sessListener_.OnBytesReceived = OnBytesReceived; + sessListener_.OnStreamReceived = OnStreamReceived; + sessListener_.OnMessageReceived = nullptr; + sessListener_.OnQosEvent = nullptr; +} + +SoftbusChannelAdapter::~SoftbusChannelAdapter() +{ + DHLOGI("~SoftbusChannelAdapter dctor."); + listenerMap_.clear(); + sessionNameSet_.clear(); + timeSyncSessNames_.clear(); + devId2SessIdMap_.clear(); +} + +int32_t SoftbusChannelAdapter::CreateChannelServer(const std::string& ownerName, const std::string &sessName) +{ + DHLOGI("Create session server for sessionName:%s.", sessName.c_str()); + TRUE_RETURN_V_MSG_E(ownerName.empty(), ERR_DH_AVT_INVALID_PARAM, "input ownerName is empty."); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessionName is empty."); + + std::lock_guard setLock(name2IdMtx_); + if (sessionNameSet_.find(sessName) == sessionNameSet_.end()) { + int32_t ret = CreateSessionServer(ownerName.c_str(), sessName.c_str(), &sessListener_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CREATE_CHANNEL_FAILED, "create session server failed"); + } else { + DHLOGE("Session already create for name:%s", sessName.c_str()); + } + sessionNameSet_.insert(sessName); + + DHLOGI("Create session server success for sessionName:%s.", sessName.c_str()); + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::RemoveChannelServer(const std::string& ownerName, const std::string &sessName) +{ + DHLOGI("Remove session server for sessionName:%s.", sessName.c_str()); + TRUE_RETURN_V_MSG_E(ownerName.empty(), ERR_DH_AVT_INVALID_PARAM, "input ownerName is empty."); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessionName is empty."); + + std::lock_guard setLock(name2IdMtx_); + if (sessionNameSet_.find(sessName) == sessionNameSet_.end()) { + DHLOGE("Can not found session name:%s", sessName.c_str()); + return ERR_DH_AVT_INVALID_PARAM_VALUE; + } + RemoveSessionServer(ownerName.c_str(), sessName.c_str()); + sessionNameSet_.erase(sessName); + + DHLOGI("Remove session server success for sessionName:%s.", sessName.c_str()); + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::OpenSoftbusChannel(const std::string& mySessName, const std::string &peerSessName, + const std::string &peerDevId) +{ + DHLOGI("Open softbus channel for mySessName:%s, peerSessName:%s, peerDevId:%s.", + mySessName.c_str(), peerSessName.c_str(), GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(mySessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input mySessName is empty."); + TRUE_RETURN_V_MSG_E(peerSessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerSessName is empty."); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + + int dataType = TYPE_BYTES; + int streamType = INVALID; + if (mySessName.find(SENDER_DATA_SESSION_NAME_SUFFIX) != std::string::npos) { + dataType = TYPE_STREAM; + streamType = COMMON_VIDEO_STREAM; + } + + SessionAttribute attr = { 0 }; + attr.dataType = dataType; + attr.linkTypeNum = LINK_TYPE_MAX; + LinkType linkTypeList[LINK_TYPE_MAX] = { + LINK_TYPE_WIFI_P2P, + LINK_TYPE_WIFI_WLAN_5G, + LINK_TYPE_WIFI_WLAN_2G, + LINK_TYPE_BR, + }; + int32_t ret = memcpy_s(attr.linkType, sizeof(attr.linkType), linkTypeList, sizeof(linkTypeList)); + if (ret != EOK) { + DHLOGE("Data copy failed."); + return ERR_DH_AVT_NO_MEMORY; + } + attr.attr.streamAttr.streamType = streamType; + int32_t sessionId = OpenSession(mySessName.c_str(), peerSessName.c_str(), peerDevId.c_str(), "0", &attr); + if (sessionId < 0) { + DHLOGE("Open softbus session failed for sessionId:%" PRId32, sessionId); + return ERR_DH_AVT_CHANNEL_ERROR; + } + { + std::lock_guard lock(idMapMutex_); + devId2SessIdMap_.insert(std::make_pair(mySessName + "_" + peerDevId, sessionId)); + } + DHLOGI("Open softbus channel finished, sessionId:%" PRId32, sessionId); + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::CloseSoftbusChannel(const std::string& sessName, const std::string &peerDevId) +{ + DHLOGI("Close softbus channel for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + + int32_t sessionId = GetSessIdBySessName(sessName, peerDevId); + CloseSession(sessionId); + { + std::lock_guard lock(idMapMutex_); + devId2SessIdMap_.erase(sessName + "_" + peerDevId); + } + + DHLOGI("Close softbus channel success, sessionId:%" PRId32, sessionId); + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::SendBytesData(const std::string& sessName, const std::string &peerDevId, const std::string &data) +{ + DHLOGI("Send bytes data for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + TRUE_RETURN_V_MSG_E(data.empty(), ERR_DH_AVT_INVALID_PARAM, "input data string is empty."); + + int32_t ret = SendBytes(GetSessIdBySessName(sessName, peerDevId), data.c_str(), strlen(data.c_str())); + if (ret != DH_AVT_SUCCESS) { + DHLOGE("Send bytes data failed ret:%" PRId32, ret); + return ERR_DH_AVT_SEND_DATA_FAILED; + } + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::SendStreamData(const std::string& sessName, const std::string &peerDevId, + const StreamData *data, const StreamData *ext) +{ + DHLOGI("Send stream data for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + TRUE_RETURN_V_MSG_E(data == nullptr, ERR_DH_AVT_INVALID_PARAM, "input data is nullptr."); + TRUE_RETURN_V_MSG_E(ext == nullptr, ERR_DH_AVT_INVALID_PARAM, "input ext data is nullptr."); + + StreamFrameInfo frameInfo = {0}; + int32_t ret = SendStream(GetSessIdBySessName(sessName, peerDevId), data, ext, &frameInfo); + if (ret != DH_AVT_SUCCESS) { + DHLOGE("Send stream data failed ret:%" PRId32, ret); + return ERR_DH_AVT_SEND_DATA_FAILED; + } + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::RegisterChannelListener(const std::string& sessName, const std::string &peerDevId, + ISoftbusChannelListener *listener) +{ + DHLOGI("Register channel listener for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + TRUE_RETURN_V_MSG_E(listener == nullptr, ERR_DH_AVT_INVALID_PARAM, "input callback is nullptr."); + + std::lock_guard lock(listenerMtx_); + listenerMap_.insert(std::make_pair(sessName + "_" + peerDevId, listener)); + + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::UnRegisterChannelListener(const std::string& sessName, const std::string &peerDevId) +{ + DHLOGI("Unregister channel listener for peerDeviceId:%s.", GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + + std::lock_guard lock(listenerMtx_); + listenerMap_.erase(sessName + "_" + peerDevId); + + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::StartDeviceTimeSync(const std::string &ownerName, const std::string& sessName, + const std::string &peerDevId) +{ + DHLOGI("Start device time sync for peerDeviceId:%s.", GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + + ITimeSyncCb timeSyncCbk = {.onTimeSyncResult = onTimeSyncResult}; + int32_t ret = StartTimeSync(ownerName.c_str(), peerDevId.c_str(), TimeSyncAccuracy::SUPER_HIGH_ACCURACY, + TimeSyncPeriod::SHORT_PERIOD, &timeSyncCbk); + if (ret != 0) { + DHLOGE("StartTimeSync failed ret:%" PRId32, ret); + return ERR_DH_AVT_TIME_SYNC_FAILED; + } + + std::lock_guard lock(timeSyncMtx_); + timeSyncSessNames_.insert(sessName + "_" + peerDevId); + + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::StopDeviceTimeSync(const std::string &ownerName, const std::string& sessName, + const std::string &peerDevId) +{ + DHLOGI("Stop device time sync for peerDeviceId:%s.", GetAnonyString(peerDevId).c_str()); + TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); + + int32_t ret = StopTimeSync(ownerName.c_str(), peerDevId.c_str()); + if (ret != 0) { + DHLOGE("StopTimeSync failed ret:%" PRId32, ret); + return ERR_DH_AVT_TIME_SYNC_FAILED; + } + + std::lock_guard lock(timeSyncMtx_); + timeSyncSessNames_.erase(sessName + "_" + peerDevId); + + return DH_AVT_SUCCESS; +} + +int32_t SoftbusChannelAdapter::GetSessIdBySessName(const std::string& sessName, const std::string &peerDevId) +{ + std::lock_guard lock(idMapMutex_); + std::string idMapKey = sessName + "_" + peerDevId; + if (devId2SessIdMap_.find(idMapKey) == devId2SessIdMap_.end()) { + DHLOGE("Can not find sessionId for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + return -1; + } + return devId2SessIdMap_[idMapKey]; +} + +std::string SoftbusChannelAdapter::GetSessionNameById(int32_t sessionId) +{ + std::lock_guard lock(idMapMutex_); + for (auto it = devId2SessIdMap_.begin(); it != devId2SessIdMap_.end(); it++) { + if (it->second == sessionId) { + return it->first; + } + } + + DHLOGE("No avaliable channel or invalid sessionId:%" PRId32, sessionId); + return EMPTY_STRING; +} + +int32_t SoftbusChannelAdapter::OnSoftbusChannelOpened(int32_t sessionId, int32_t result) +{ + DHLOGI("On softbus channel opened, sessionId:%" PRId32", result:%" PRId32, sessionId, result); + + char peerDevIdChar[MAX_DEVICE_ID_LEN] = ""; + int32_t ret = GetPeerDeviceId(sessionId, peerDevIdChar, sizeof(peerDevIdChar)); + TRUE_RETURN_V_MSG_E(ret != 0, ret, "Get peer device id from softbus failed."); + std::string peerDevId(peerDevIdChar); + + char sessNameChar[MAX_SESSION_NAME_LEN] = ""; + ret = GetMySessionName(sessionId, sessNameChar, sizeof(sessNameChar)); + TRUE_RETURN_V_MSG_E(ret != 0, ret, "Get my session name from softbus failed."); + std::string sessName(sessNameChar); + + EventType type = (result == 0) ? EventType::EVENT_CHANNEL_OPENED : EventType::EVENT_CHANNEL_OPEN_FAIL; + AVTransEvent event = {type, "", peerDevId}; + + { + std::lock_guard lock(listenerMtx_); + for (auto it = listenerMap_.begin(); it != listenerMap_.end(); it++) { + if (((it->first).find(sessName) != std::string::npos) && (it->second != nullptr)) { + std::thread(&SoftbusChannelAdapter::SendChannelEvent, this, it->second, event).detach(); + { + std::lock_guard lock(idMapMutex_); + devId2SessIdMap_.erase(it->first); + devId2SessIdMap_.insert(std::make_pair(it->first, sessionId)); + } + } + } + } + + int32_t existSessId = GetSessIdBySessName(sessName, peerDevId); + if (existSessId == -1) { + std::lock_guard lock(idMapMutex_); + devId2SessIdMap_.insert(std::make_pair(sessName + "_" + peerDevId, sessionId)); + } + + return DH_AVT_SUCCESS; +} + +void SoftbusChannelAdapter::OnSoftbusChannelClosed(int32_t sessionId) +{ + DHLOGI("On softbus channel closed, sessionId:%" PRId32, sessionId); + AVTransEvent event = {EventType::EVENT_CHANNEL_CLOSED, "", ""}; + + std::lock_guard lock(idMapMutex_); + for (auto it = devId2SessIdMap_.begin(); it != devId2SessIdMap_.end();) { + if (it->second == sessionId) { + std::lock_guard lock(listenerMtx_); + std::thread(&SoftbusChannelAdapter::SendChannelEvent, this, listenerMap_[it->first], event).detach(); + devId2SessIdMap_.erase(it++); + } + it++; + } +} + +void SoftbusChannelAdapter::OnSoftbusBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen) +{ + DHLOGI("On softbus channel bytes received, sessionId:%" PRId32, sessionId); + TRUE_RETURN(data == nullptr, "input data is nullptr."); + TRUE_RETURN(dataLen == 0, "input dataLen is 0."); + + char peerDevIdChar[MAX_DEVICE_ID_LEN] = ""; + int32_t ret = GetPeerDeviceId(sessionId, peerDevIdChar, sizeof(peerDevIdChar)); + TRUE_RETURN(ret != 0, "Get peer device id from softbus failed."); + std::string peerDevId(peerDevIdChar); + + std::string dataStr = std::string(reinterpret_cast(data), dataLen); + AVTransEvent event = {EventType::EVENT_DATA_RECEIVED, dataStr, peerDevId}; + + std::lock_guard lock(idMapMutex_); + for (auto it = devId2SessIdMap_.begin(); it != devId2SessIdMap_.end(); it++) { + if (it->second == sessionId) { + std::lock_guard lock(listenerMtx_); + std::thread(&SoftbusChannelAdapter::SendChannelEvent, this, listenerMap_[it->first], event).detach(); + } + } +} + +void SoftbusChannelAdapter::OnSoftbusStreamReceived(int32_t sessionId, const StreamData *data, + const StreamData *ext, const StreamFrameInfo *frameInfo) +{ + (void)frameInfo; + DHLOGI("On softbus channel stream received, sessionId:%" PRId32, sessionId); + TRUE_RETURN(data == nullptr, "input data is nullptr."); + TRUE_RETURN(ext == nullptr, "input ext data is nullptr."); + + std::lock_guard lock(idMapMutex_); + for (auto it = devId2SessIdMap_.begin(); it != devId2SessIdMap_.end(); it++) { + if (it->second == sessionId) { + std::lock_guard lock(listenerMtx_); + ISoftbusChannelListener *listener = listenerMap_[it->first]; + TRUE_RETURN(listener == nullptr, "Can not find channel listener."); + listener->OnStreamReceived(data, ext); + } + } +} + +void SoftbusChannelAdapter::OnSoftbusTimeSyncResult(const TimeSyncResultInfo *info, int32_t result) +{ + DHLOGI("On softbus channel time sync result:%" PRId32, result); + TRUE_RETURN(result == 0, "On softbus channel time sync failed"); + + int32_t millisecond = info->result.millisecond; + int32_t microsecond = info->result.microsecond; + TimeSyncAccuracy accuracy = info->result.accuracy; + DHLOGI("Time sync success, flag:%" PRId32", millisecond:%" PRId32", microsecond:%" PRId32", accuracy:%" PRId32, + info->flag, millisecond, microsecond, accuracy); + DHLOGI("renguang debug: targetNetworkId:%s, masterNetworkId:%s", info->target.targetNetworkId, info->target.masterNetworkId); + + std::string targetDevId(info->target.targetNetworkId); + std::string masterDevId(info->target.masterNetworkId); + std::lock_guard lock(timeSyncMtx_); + for (auto sessName : timeSyncSessNames_) { + std::lock_guard lock(listenerMtx_); + ISoftbusChannelListener *listener = listenerMap_[sessName]; + if (listener != nullptr) { + listener->OnChannelEvent({EventType::EVENT_TIME_SYNC_RESULT, std::to_string(millisecond), targetDevId}); + } + } +} + +void SoftbusChannelAdapter::SendChannelEvent(ISoftbusChannelListener *listener, const AVTransEvent &event) +{ + pthread_setname_np(pthread_self(), SEND_CHANNEL_EVENT); + + TRUE_RETURN(listener == nullptr, "input listener is nullptr."); + listener->OnChannelEvent(event); +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file -- Gitee From 44611ad861f0746d0ab46954ae98e615a18801c6 Mon Sep 17 00:00:00 2001 From: renguang1116 Date: Mon, 12 Jun 2023 21:17:47 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E3=80=90=E9=9F=B3=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E7=BB=84=E4=BB=B6=E3=80=91common=E7=B1=BB?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0=20Signed-off-by:=20renguan?= =?UTF-8?q?g1116=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- av_transport/common/src/av_trans_buffer.cpp | 5 +- av_transport/common/src/av_trans_meta.cpp | 52 +++++++++---------- av_transport/common/src/av_trans_utils.cpp | 6 ++- .../common/src/softbus_channel_adapter.cpp | 12 +++-- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/av_transport/common/src/av_trans_buffer.cpp b/av_transport/common/src/av_trans_buffer.cpp index effa862c..b279401c 100644 --- a/av_transport/common/src/av_trans_buffer.cpp +++ b/av_transport/common/src/av_trans_buffer.cpp @@ -33,10 +33,11 @@ std::shared_ptr AVTransBuffer::CreateBufferData(size_t capacity) std::shared_ptr AVTransBuffer::WrapBufferData(const uint8_t* data, size_t capacity, size_t size) { - auto bufData = std::make_shared(capacity, std::shared_ptr(const_cast(data), [](void* ptr) {})); + auto bufData = std::make_shared(capacity, + std::shared_ptr(const_cast(data), [](void* ptr) {})); bufData->SetSize(size); data_.push_back(bufData); - return bufData; + return bufData; } std::shared_ptr AVTransBuffer::GetBufferData(uint32_t index) diff --git a/av_transport/common/src/av_trans_meta.cpp b/av_transport/common/src/av_trans_meta.cpp index a6931f6d..a4e10cea 100644 --- a/av_transport/common/src/av_trans_meta.cpp +++ b/av_transport/common/src/av_trans_meta.cpp @@ -26,16 +26,16 @@ const std::string META_FRAME_NUMBER = "meta_frame_number"; std::shared_ptr AVTransAudioBufferMeta::Clone() { - auto bufferMeta = std::make_shared(); - bufferMeta->pts_ = pts_; - bufferMeta->cts_ = cts_; - bufferMeta->format_ = format_; - bufferMeta->dataType_ = dataType_; - bufferMeta->frameNum_ = frameNum_; - bufferMeta->channels_ = channels_; - bufferMeta->sampleRate_ = sampleRate_; - bufferMeta->Upate(*this); - return bufferMeta; + auto bufferMeta = std::make_shared(); + bufferMeta->pts_ = pts_; + bufferMeta->cts_ = cts_; + bufferMeta->format_ = format_; + bufferMeta->dataType_ = dataType_; + bufferMeta->frameNum_ = frameNum_; + bufferMeta->channels_ = channels_; + bufferMeta->sampleRate_ = sampleRate_; + bufferMeta->Update(*this); + return bufferMeta; } std::string AVTransAudioBufferMeta::MarshalAudioMeta() @@ -53,10 +53,8 @@ bool AVTransAudioBufferMeta::UnmarshalAudioMeta(const std::string& jsonStr) if (metaJson.is_discarded()) { return false; } - if (!metaJson.contains(META_DATA_TYPE) || !metaJson.contains(META_TIMESTAMP) || !metaJson.contains(META_FRAME_NUMBER)) { - return false; - } - if (!IsUInt32(metaJson, META_DATA_TYPE) || !IsInt64(metaJson, META_TIMESTAMP) || !IsUInt32(metaJson, META_FRAME_NUMBER)) { + if (!IsUInt32(metaJson, META_DATA_TYPE) || !IsInt64(metaJson, META_TIMESTAMP) || + !IsUInt32(metaJson, META_FRAME_NUMBER)) { return false; } dataType_ = metaJson[META_DATA_TYPE].get(); @@ -67,16 +65,16 @@ bool AVTransAudioBufferMeta::UnmarshalAudioMeta(const std::string& jsonStr) std::shared_ptr AVTransVideoBufferMeta::Clone() { - auto bufferMeta = std::make_shared(); - bufferMeta->pts_ = pts_; - bufferMeta->cts_ = cts_; - bufferMeta->width_ = width_; - bufferMeta->height_ = height_; - bufferMeta->format_ = format_; - bufferMeta->dataType_ = dataType_; - bufferMeta->frameNum_ = frameNum_; - bufferMeta->Upate(*this); - return bufferMeta; + auto bufferMeta = std::make_shared(); + bufferMeta->pts_ = pts_; + bufferMeta->cts_ = cts_; + bufferMeta->width_ = width_; + bufferMeta->height_ = height_; + bufferMeta->format_ = format_; + bufferMeta->dataType_ = dataType_; + bufferMeta->frameNum_ = frameNum_; + bufferMeta->Update(*this); + return bufferMeta; } std::string AVTransVideoBufferMeta::MarshalVideoMeta() @@ -94,10 +92,8 @@ bool AVTransVideoBufferMeta::UnmarshalVideoMeta(const std::string& jsonStr) if (metaJson.is_discarded()) { return false; } - if (!metaJson.contains(META_DATA_TYPE) || !metaJson.contains(META_TIMESTAMP) || !metaJson.contains(META_FRAME_NUMBER)) { - return false; - } - if (!IsUInt32(metaJson, META_DATA_TYPE) || !IsInt64(metaJson, META_TIMESTAMP) || !IsUInt32(metaJson, META_FRAME_NUMBER)) { + if (!IsUInt32(metaJson, META_DATA_TYPE) || !IsInt64(metaJson, META_TIMESTAMP) || + !IsUInt32(metaJson, META_FRAME_NUMBER)) { return false; } dataType_ = metaJson[META_DATA_TYPE].get(); diff --git a/av_transport/common/src/av_trans_utils.cpp b/av_transport/common/src/av_trans_utils.cpp index e0f717b2..199fcac6 100644 --- a/av_transport/common/src/av_trans_utils.cpp +++ b/av_transport/common/src/av_trans_utils.cpp @@ -143,7 +143,8 @@ void Convert2HiSBufferMeta(std::shared_ptr transBuffer, std::shar uint32_t dataType = std::atoi(value.c_str()); hisAMeta->dataType_ = (BufferDataType)dataType; - TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::AUDIO_SAMPLE_FORMAT, value), "get AUDIO_SAMPLE_FORMAT meta failed"); + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::AUDIO_SAMPLE_FORMAT, value), + "get AUDIO_SAMPLE_FORMAT meta failed"); uint32_t format = std::atoi(value.c_str()); hisAMeta->format_ = (AudioSampleFormat)format; @@ -159,7 +160,8 @@ void Convert2HiSBufferMeta(std::shared_ptr transBuffer, std::shar uint32_t dataType = std::atoi(value.c_str()); hisVMeta->dataType_ = (BufferDataType)dataType; - TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::VIDEO_PIXEL_FORMAT, value), "get VIDEO_PIXEL_FORMAT meta failed"); + TRUE_RETURN(!transMeta->GetMetaItem(AVTransTag::VIDEO_PIXEL_FORMAT, value), + "get VIDEO_PIXEL_FORMAT meta failed"); uint32_t format = std::atoi(value.c_str()); hisVMeta->format_ = (VideoPixelFormat)format; diff --git a/av_transport/common/src/softbus_channel_adapter.cpp b/av_transport/common/src/softbus_channel_adapter.cpp index 591ca347..f2bbc440 100644 --- a/av_transport/common/src/softbus_channel_adapter.cpp +++ b/av_transport/common/src/softbus_channel_adapter.cpp @@ -171,7 +171,8 @@ int32_t SoftbusChannelAdapter::CloseSoftbusChannel(const std::string& sessName, return DH_AVT_SUCCESS; } -int32_t SoftbusChannelAdapter::SendBytesData(const std::string& sessName, const std::string &peerDevId, const std::string &data) +int32_t SoftbusChannelAdapter::SendBytesData(const std::string& sessName, const std::string &peerDevId, + const std::string &data) { DHLOGI("Send bytes data for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); @@ -207,7 +208,8 @@ int32_t SoftbusChannelAdapter::SendStreamData(const std::string& sessName, const int32_t SoftbusChannelAdapter::RegisterChannelListener(const std::string& sessName, const std::string &peerDevId, ISoftbusChannelListener *listener) { - DHLOGI("Register channel listener for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + DHLOGI("Register channel listener for sessName:%s, peerDevId:%s.", + sessName.c_str(), GetAnonyString(peerDevId).c_str()); TRUE_RETURN_V_MSG_E(sessName.empty(), ERR_DH_AVT_INVALID_PARAM, "input sessName is empty."); TRUE_RETURN_V_MSG_E(peerDevId.empty(), ERR_DH_AVT_INVALID_PARAM, "input peerDevId is empty."); TRUE_RETURN_V_MSG_E(listener == nullptr, ERR_DH_AVT_INVALID_PARAM, "input callback is nullptr."); @@ -273,7 +275,8 @@ int32_t SoftbusChannelAdapter::GetSessIdBySessName(const std::string& sessName, std::lock_guard lock(idMapMutex_); std::string idMapKey = sessName + "_" + peerDevId; if (devId2SessIdMap_.find(idMapKey) == devId2SessIdMap_.end()) { - DHLOGE("Can not find sessionId for sessName:%s, peerDevId:%s.", sessName.c_str(), GetAnonyString(peerDevId).c_str()); + DHLOGE("Can not find sessionId for sessName:%s, peerDevId:%s.", + sessName.c_str(), GetAnonyString(peerDevId).c_str()); return -1; } return devId2SessIdMap_[idMapKey]; @@ -400,7 +403,8 @@ void SoftbusChannelAdapter::OnSoftbusTimeSyncResult(const TimeSyncResultInfo *in TimeSyncAccuracy accuracy = info->result.accuracy; DHLOGI("Time sync success, flag:%" PRId32", millisecond:%" PRId32", microsecond:%" PRId32", accuracy:%" PRId32, info->flag, millisecond, microsecond, accuracy); - DHLOGI("renguang debug: targetNetworkId:%s, masterNetworkId:%s", info->target.targetNetworkId, info->target.masterNetworkId); + DHLOGI("renguang debug: targetNetworkId:%s, masterNetworkId:%s", info->target.targetNetworkId, + info->target.masterNetworkId); std::string targetDevId(info->target.targetNetworkId); std::string masterDevId(info->target.masterNetworkId); -- Gitee From 04b979531f061334ea2e822d72cc8b34a187d1b7 Mon Sep 17 00:00:00 2001 From: renguang1116 Date: Mon, 12 Jun 2023 22:18:37 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E3=80=90=E9=9F=B3=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E7=BB=84=E4=BB=B6=E3=80=91common=E7=B1=BB?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0=20Signed-off-by:=20renguan?= =?UTF-8?q?g1116=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../av_trans_engine/av_sender/BUILD.gn | 108 +++++ .../av_sender/include/av_sender_engine.h | 116 +++++ .../include/av_sender_engine_provider.h | 48 ++ .../av_sender/src/av_sender_engine.cpp | 430 ++++++++++++++++++ .../src/av_sender_engine_provider.cpp | 92 ++++ av_transport/common/src/av_sync_utils.cpp | 2 +- 6 files changed, 795 insertions(+), 1 deletion(-) create mode 100644 av_transport/av_trans_engine/av_sender/BUILD.gn create mode 100644 av_transport/av_trans_engine/av_sender/include/av_sender_engine.h create mode 100644 av_transport/av_trans_engine/av_sender/include/av_sender_engine_provider.h create mode 100644 av_transport/av_trans_engine/av_sender/src/av_sender_engine.cpp create mode 100644 av_transport/av_trans_engine/av_sender/src/av_sender_engine_provider.cpp diff --git a/av_transport/av_trans_engine/av_sender/BUILD.gn b/av_transport/av_trans_engine/av_sender/BUILD.gn new file mode 100644 index 00000000..339cc8c2 --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/BUILD.gn @@ -0,0 +1,108 @@ +# Copyright (c) 2023 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. + +import("//build/ohos.gni") +import( + "//foundation/distributedhardware/distributed_hardware_fwk/av_transport/distributed_av_transport.gni") + +ohos_shared_library("distributed_av_sender") { + include_dirs = [ + "//base/hiviewdfx/hisysevent/interfaces/native/innerkits/hisysevent/include", + "//base/hiviewdfx/hitrace/interfaces/native/innerkits/include/hitrace_meter", + "//drivers/peripheral/display/interfaces/include", + "//foundation/graphic/graphic_2d/interfaces/inner_api", + "//foundation/graphic/graphic_2d/interfaces/inner_api/common", + "//foundation/graphic/graphic_2d/utils/buffer_handle/export", + "//foundation/multimedia/player_framework/interfaces/inner_api/native", + "//third_party/json/include", + + "${common_path}/include", + "${engine_path}", + "${engine_path}/av_sender/include", + "${engine_path}/av_receiver/include", + "${interface_path}", + "${dh_fwk_utils_path}/include", + "${control_center_path}/inner_kits/include", + "${control_center_path}/inner_kits/include/ipc", + + "${histreamer_path}/include", + "${histreamer_path}/include/foundation", + "${histreamer_path}/include/pipeline", + "${histreamer_path}/include/pipeline/core", + "${histreamer_path}/include/pipeline/factory", + "${histreamer_path}/include/pipeline/filters", + "${histreamer_path}/include/pipeline/filters/codec/audio_encoder", + "${histreamer_path}/include/pipeline/filters/codec/video_encoder", + "${histreamer_path}/include/pipeline/filters/source/av_transport_input", + "${histreamer_path}/include/pipeline/filters/sink/av_transport_output", + "${histreamer_path}/include/plugin", + "${histreamer_path}/include/plugin/common", + "${histreamer_path}/include/scene/standard", + ] + + sources = [ + "${engine_path}/av_sender/src/av_sender_engine_provider.cpp", + "${engine_path}/av_sender/src/av_sender_engine.cpp", + "${common_path}/src/av_trans_buffer.cpp", + "${common_path}/src/av_trans_log.cpp", + "${common_path}/src/av_trans_message.cpp", + "${common_path}/src/av_trans_meta.cpp", + "${common_path}/src/av_trans_utils.cpp", + "${common_path}/src/softbus_channel_adapter.cpp", + ] + + deps = [ + "${histreamer_path}/pipeline:histreamer_pipeline", + "${histreamer_path}/pipeline:histreamer_pipeline_base", + "${control_center_path}/inner_kits:avtranscenter_sdk", + ] + + defines = [ + "HI_LOG_ENABLE", + "DH_LOG_TAG=\"distributed_av_transport_sender\"", + "LOG_DOMAIN=0xD004100", + ] + + defines += [ + "MEDIA_OHOS", + "RECORDER_SUPPORT", + "VIDEO_SUPPORT", + ] + + external_deps = [ + "c_utils:utils", + "dsoftbus:softbus_client", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + remove_configs = [ + "//build/config/compiler:no_rtti", + "//build/config/compiler:no_exceptions" + ] + cflags = [ + "-O2", + "-fPIC", + "-Wall", + "-frtti", + "-fexceptions", + ] + cflags_cc = cflags + + part_name = "distributed_hardware_fwk" + subsystem_name = "distributedhardware" +} \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/include/av_sender_engine.h b/av_transport/av_trans_engine/av_sender/include/av_sender_engine.h new file mode 100644 index 00000000..f9ac4623 --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/include/av_sender_engine.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_AV_SENDER_ENGINE_H +#define OHOS_AV_SENDER_ENGINE_H + +#include "av_trans_buffer.h" +#include "av_trans_errno.h" +#include "av_trans_constants.h" +#include "av_trans_log.h" +#include "av_trans_message.h" +#include "av_trans_types.h" +#include "av_trans_utils.h" +#include "i_av_sender_engine.h" +#include "softbus_channel_adapter.h" +#include "av_trans_control_center_kit.h" +#include "av_trans_control_center_callback.h" + +// follwing head files depends on histreamer +#include "error_code.h" +#include "event.h" +#include "pipeline/core/filter.h" +#include "pipeline_core.h" +#include "audio_encoder_filter.h" +#include "video_encoder_filter.h" +#include "av_transport_input_filter.h" +#include "av_transport_output_filter.h" + +namespace OHOS { +namespace DistributedHardware { +using namespace OHOS::Media; +using namespace OHOS::Media::Plugin; +using namespace OHOS::Media::Pipeline; +using AVBuffer = OHOS::Media::Plugin::Buffer; + +class AVSenderEngine : public IAVSenderEngine, + public ISoftbusChannelListener, + public OHOS::Media::Pipeline::EventReceiver, + public std::enable_shared_from_this { +public: + AVSenderEngine(const std::string& ownerName); + ~AVSenderEngine() override; + AVSenderEngine(const AVSenderEngine& other) = delete; + AVSenderEngine& operator=(const AVSenderEngine& other) = delete; + + // interfaces from IAVSenderEngine + int32_t Initialize() override; + int32_t Start() override; + int32_t Stop() override; + int32_t Release() override; + int32_t SetParameter(AVTransTag tag, const std::string& value) override; + int32_t PushData(const std::shared_ptr& buffer) override; + int32_t SendMessage(const std::shared_ptr &message) override; + int32_t CreateControlChannel(const std::vector &dstDevIds, + const ChannelAttribute &attribution) override; + int32_t RegisterSenderCallback(const std::shared_ptr &callback) override; + + // interfaces from ISoftbusChannelListener + void OnChannelEvent(const AVTransEvent &event) override; + void OnStreamReceived(const StreamData *data, const StreamData *ext) override; + + // interfaces from OHOS::Media::Pipeline::EventReceiver + void OnEvent(const OHOS::Media::Event& event) override; + +private: + int32_t InitPipeline(); + int32_t InitControlCenter(); + int32_t PreparePipeline(const std::string& configParam); + void NotifyStreamChange(EventType type); + + StateId GetCurrentState() + { + std::lock_guard lock(stateMutex_); + return currentState_; + } + + void SetCurrentState(StateId stateId) + { + std::lock_guard lock(stateMutex_); + currentState_ = stateId; + } + +private: + int32_t engineId_ = 0; + std::string ownerName_; + std::string sessionName_; + std::string peerDevId_; + + std::mutex stateMutex_; + std::atomic initialized_ {false}; + std::atomic currentState_ = StateId::IDLE; + + sptr ctlCenCallback_ = nullptr; + std::shared_ptr senderCallback_ = nullptr; + std::shared_ptr pipeline_ = nullptr; + + std::shared_ptr avInput_ = nullptr; + std::shared_ptr avOutput_ = nullptr; + std::shared_ptr audioEncoder_ = nullptr; + std::shared_ptr videoEncoder_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/include/av_sender_engine_provider.h b/av_transport/av_trans_engine/av_sender/include/av_sender_engine_provider.h new file mode 100644 index 00000000..5b32f8b5 --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/include/av_sender_engine_provider.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_AV_SENDER_ENGINE_PROVIDER_H +#define OHOS_AV_SENDER_ENGINE_PROVIDER_H + +#include + +#include "i_av_engine_provider.h" +#include "softbus_channel_adapter.h" + +namespace OHOS { +namespace DistributedHardware { +class AVSenderEngineProvider : public IAVEngineProvider, public ISoftbusChannelListener { +public: + AVSenderEngineProvider(const std::string ownerName); + ~AVSenderEngineProvider() override; + + std::shared_ptr CreateAVSenderEngine() override; + std::vector> GetAVSenderEngineList() override; + int32_t RegisterProviderCallback(const std::shared_ptr &callback) override; + + // interfaces from ISoftbusChannelListener + void OnChannelEvent(const AVTransEvent &event) override; + void OnStreamReceived(const StreamData *data, const StreamData *ext) override; + +private: + std::string ownerName_; + std::string sessionName_; + std::mutex listMutex_; + std::shared_ptr providerCallback_; + std::vector> senderEngineList_; +}; +} +} +#endif \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/src/av_sender_engine.cpp b/av_transport/av_trans_engine/av_sender/src/av_sender_engine.cpp new file mode 100644 index 00000000..3c97db6d --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/src/av_sender_engine.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2023 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 "av_sender_engine.h" + +#include "pipeline/factory/filter_factory.h" +#include "plugin_video_tags.h" + +namespace OHOS { +namespace DistributedHardware { +AVSenderEngine::AVSenderEngine(const std::string& ownerName) : ownerName_(ownerName) +{ + DHLOGI("AVSenderEngine ctor."); + sessionName_ = ownerName_ + "_" + SENDER_CONTROL_SESSION_NAME_SUFFIX; +} + +AVSenderEngine::~AVSenderEngine() +{ + DHLOGI("AVSenderEngine dctor."); + Release(); + + pipeline_ = nullptr; + avInput_ = nullptr; + avOutput_ = nullptr; + audioEncoder_ = nullptr; + videoEncoder_ = nullptr; + senderCallback_ = nullptr; + ctlCenCallback_ = nullptr; +} + +int32_t AVSenderEngine::Initialize() +{ + TRUE_RETURN_V_MSG_E(initialized_.load(), DH_AVT_SUCCESS, "sender engine has been initialized"); + + int32_t ret = InitPipeline(); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_INIT_FAILED, "init pipeline failed"); + + ret = InitControlCenter(); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_INIT_FAILED, "init av control center failed"); + + initialized_ = true; + SetCurrentState(StateId::INITIALIZED); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::InitPipeline() +{ + DHLOGI("InitPipeline enter."); + FilterFactory::Instance().Init(); + avInput_ = FilterFactory::Instance().CreateFilterWithType(AVINPUT_NAME, "avinput"); + TRUE_RETURN_V_MSG_E(avInput_ == nullptr, ERR_DH_AVT_NULL_POINTER, "create av input filter failed"); + + avOutput_ = FilterFactory::Instance().CreateFilterWithType(AVOUTPUT_NAME, "avoutput"); + TRUE_RETURN_V_MSG_E(avOutput_ == nullptr, ERR_DH_AVT_NULL_POINTER, "create av output filter failed"); + + videoEncoder_ = FilterFactory::Instance().CreateFilterWithType(VENCODER_NAME, "videoencoder"); + TRUE_RETURN_V_MSG_E(videoEncoder_ == nullptr, ERR_DH_AVT_NULL_POINTER, "create av video encoder filter failed"); + + audioEncoder_ = FilterFactory::Instance().CreateFilterWithType(AENCODER_NAME, "audioencoder"); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, ERR_DH_AVT_NULL_POINTER, "create av audio encoder filter failed"); + + ErrorCode ret; + pipeline_ = std::make_shared(); + pipeline_->Init(this, nullptr); + if ((ownerName_ == OWNER_NAME_D_SCREEN) || (ownerName_ == OWNER_NAME_D_CAMERA)) { + ret = pipeline_->AddFilters({avInput_.get(), videoEncoder_.get(), avOutput_.get()}); + if (ret == ErrorCode::SUCCESS) { + ret = pipeline_->LinkFilters({avInput_.get(), videoEncoder_.get(), avOutput_.get()}); + } + } else if ((ownerName_ == OWNER_NAME_D_MIC) || (ownerName_ == OWNER_NAME_D_SPEAKER)) { + ret = pipeline_->AddFilters({avInput_.get(), audioEncoder_.get(), avOutput_.get()}); + if (ret == ErrorCode::SUCCESS) { + ret = pipeline_->LinkFilters({avInput_.get(), audioEncoder_.get(), avOutput_.get()}); + } + } else { + DHLOGI("unsupport ownerName:%s", ownerName_.c_str()); + return ERR_DH_AVT_INVALID_PARAM_VALUE; + } + if (ret != ErrorCode::SUCCESS) { + pipeline_->RemoveFilterChain(avInput_.get()); + } + return (ret == ErrorCode::SUCCESS) ? DH_AVT_SUCCESS : ERR_DH_AVT_INVALID_OPERATION; +} + +int32_t AVSenderEngine::InitControlCenter() +{ + int32_t ret = AVTransControlCenterKit::GetInstance().Initialize(TransRole::AV_SENDER, engineId_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CTRL_CENTER_INIT_FAIL, "init av trans control center failed"); + + ctlCenCallback_ = new (std::nothrow) AVTransControlCenterCallback(); + TRUE_RETURN_V_MSG_E(ctlCenCallback_ == nullptr, ERR_DH_AVT_REGISTER_CALLBACK_FAIL, "new control center callback failed"); + + ret = AVTransControlCenterKit::GetInstance().RegisterCtlCenterCallback(engineId_, ctlCenCallback_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_REGISTER_CALLBACK_FAIL, "register control center callback failed"); + + std::shared_ptr engine = std::shared_ptr(shared_from_this()); + ctlCenCallback_->SetSenderEngine(engine); + + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::CreateControlChannel(const std::vector &dstDevIds, const ChannelAttribute &attribution) +{ + (void)attribution; + DHLOGI("CreateControlChannel enter."); + TRUE_RETURN_V_MSG_E(dstDevIds.empty(), ERR_DH_AVT_NULL_POINTER, "dst deviceId vector is empty"); + + peerDevId_ = dstDevIds[0]; + int32_t ret = SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, peerDevId_, this); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CREATE_CHANNEL_FAILED, + "register control channel callback failed"); + + std::string peerSessName = ownerName_ + "_" + RECEIVER_CONTROL_SESSION_NAME_SUFFIX; + ret = SoftbusChannelAdapter::GetInstance().OpenSoftbusChannel(sessionName_, peerSessName, peerDevId_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CREATE_CHANNEL_FAILED, + "create control channel failed"); + + SetCurrentState(StateId::CH_CREATING); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::Start() +{ + DHLOGI("Start sender engine enter."); + + bool isErrState = (GetCurrentState() != StateId::CH_CREATED); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_START_FAILED, "current state=%" PRId32 " is invalid.", GetCurrentState()); + + ErrorCode errCode = pipeline_->Start(); + TRUE_RETURN_V_MSG_E(errCode != ErrorCode::SUCCESS, ERR_DH_AVT_START_FAILED, "start pipeline failed"); + + int32_t ret = AVTransControlCenterKit::GetInstance().CreateControlChannel(engineId_, peerDevId_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CREATE_CHANNEL_FAILED, "create av control center channel failed"); + + SetCurrentState(StateId::STARTED); + DHLOGI("Start sender engine success."); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::Stop() +{ + DHLOGI("Stop sender engine enter."); + ErrorCode ret = pipeline_->Pause(); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_STOP_FAILED, "stop pipeline failed"); + SetCurrentState(StateId::STOPPED); + NotifyStreamChange(EventType::EVENT_REMOVE_STREAM); + DHLOGI("Stop sender engine success."); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::Release() +{ + DHLOGI("Release sender engine enter."); + AVTransControlCenterKit::GetInstance().Release(engineId_); + pipeline_->Stop(); + + SoftbusChannelAdapter::GetInstance().CloseSoftbusChannel(sessionName_, peerDevId_); + SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(sessionName_, peerDevId_); + initialized_ = false; + SetCurrentState(StateId::IDLE); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::SetParameter(AVTransTag tag, const std::string& value) +{ + DHLOGI("SetParameter enter. tag:%" PRId32, tag); + switch (tag) { + case AVTransTag::VIDEO_WIDTH: { + avInput_->SetParameter(static_cast(Plugin::Tag::VIDEO_WIDTH), std::atoi(value.c_str())); + DHLOGI("SetParameter VIDEO_WIDTH success, video width = %s", value.c_str()); + break; + } + case AVTransTag::VIDEO_HEIGHT: { + avInput_->SetParameter(static_cast(Plugin::Tag::VIDEO_HEIGHT), std::atoi(value.c_str())); + DHLOGI("SetParameter VIDEO_HEIGHT success, video height = %s", value.c_str()); + break; + } + case AVTransTag::VIDEO_PIXEL_FORMAT: { + avInput_->SetParameter(static_cast(Plugin::Tag::VIDEO_PIXEL_FORMAT), Plugin::VideoPixelFormat::RGBA); + DHLOGI("SetParameter VIDEO_PIXEL_FORMAT success, pixel format = %s", value.c_str()); + break; + } + case AVTransTag::VIDEO_FRAME_RATE: { + avInput_->SetParameter(static_cast(Plugin::Tag::VIDEO_FRAME_RATE), std::atoi(value.c_str())); + avOutput_->SetParameter(static_cast(Plugin::Tag::VIDEO_FRAME_RATE), std::atoi(value.c_str())); + DHLOGI("SetParameter VIDEO_FRAME_RATE success, frame rate = %s", value.c_str()); + break; + } + case AVTransTag::AUDIO_BIT_RATE: + case AVTransTag::VIDEO_BIT_RATE: { + avInput_->SetParameter(static_cast(Plugin::Tag::MEDIA_BITRATE), std::atoi(value.c_str())); + DHLOGI("SetParameter MEDIA_BITRATE success, bit rate = %s", value.c_str()); + break; + } + case AVTransTag::VIDEO_CODEC_TYPE: { + Plugin::Meta encoderMeta; + encoderMeta.Set(MEDIA_MIME_VIDEO_H264); + encoderMeta.Set(Plugin::VideoH264Profile::BASELINE); + encoderMeta.Set(32); + videoEncoder_->SetVideoEncoder(0, std::make_shared(encoderMeta)); + DHLOGI("SetParameter VIDEO_CODEC_TYPE = H264 success"); + break; + } + case AVTransTag::AUDIO_CODEC_TYPE: { + Plugin::Meta encoderMeta; + encoderMeta.Set(MEDIA_MIME_AUDIO_AAC); + encoderMeta.Set(Plugin::AudioAacProfile::LC); + videoEncoder_->SetAudioEncoder(0, std::make_shared(encoderMeta)); + DHLOGI("SetParameter AUDIO_CODEC_TYPE = ACC success"); + break; + } + case AVTransTag::AUDIO_CHANNEL_MASK: { + avInput_->SetParameter(static_cast(Plugin::Tag::AUDIO_CHANNELS), std::atoi(value.c_str())); + avOutput_->SetParameter(static_cast(Plugin::Tag::AUDIO_CHANNELS), std::atoi(value.c_str())); + DHLOGI("SetParameter AUDIO_CHANNEL_MASK success, audio channels = %s", value.c_str()); + break; + } + case AVTransTag::AUDIO_SAMPLE_RATE: { + avInput_->SetParameter(static_cast(Plugin::Tag::AUDIO_SAMPLE_RATE), std::atoi(value.c_str())); + avOutput_->SetParameter(static_cast(Plugin::Tag::AUDIO_SAMPLE_RATE), std::atoi(value.c_str())); + DHLOGI("SetParameter AUDIO_SAMPLE_RATE success, audio sample rate = %s", value.c_str()); + break; + } + case AVTransTag::AUDIO_CHANNEL_LAYOUT: { + avInput_->SetParameter(static_cast(Plugin::Tag::AUDIO_CHANNEL_LAYOUT), std::atoi(value.c_str())); + avOutput_->SetParameter(static_cast(Plugin::Tag::AUDIO_CHANNEL_LAYOUT), std::atoi(value.c_str())); + DHLOGI("SetParameter AUDIO_CHANNEL_LAYOUT success, audio channel layout = %s", value.c_str()); + break; + } + case AVTransTag::AUDIO_SAMPLE_FORMAT: { + avInput_->SetParameter(static_cast(Plugin::Tag::AUDIO_SAMPLE_FORMAT), std::atoi(value.c_str())); + DHLOGI("SetParameter AUDIO_SAMPLE_FORMAT success, audio sample format = %s", value.c_str()); + break; + } + case AVTransTag::AUDIO_FRAME_SIZE: { + avInput_->SetParameter(static_cast(Plugin::Tag::AUDIO_SAMPLE_PER_FRAME), std::atoi(value.c_str())); + DHLOGI("SetParameter AUDIO_SAMPLE_PER_FRAME success, audio sample per frame = %s", value.c_str()); + break; + } + case AVTransTag::SHARED_MEMORY_FD: { + avInput_->SetParameter(static_cast(Plugin::Tag::SHARED_MEMORY_FD), std::atoi(value.c_str())); + DHLOGI("SetParameter SHARED_MEMORY_FD success, shared memory info = %s", value.c_str()); + break; + } + case AVTransTag::ENGINE_READY: { + int32_t ret = PreparePipeline(value); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_SETUP_FAILED, "SetParameter ENGINE_READY failed"); + break; + } + default: + DHLOGE("Invalid tag."); + } + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::PushData(const std::shared_ptr& buffer) +{ + DHLOGI("PushData enter."); + + StateId currentState = GetCurrentState(); + bool isErrState = (currentState != StateId::STARTED) && (currentState != StateId::PLAYING); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_PUSH_DATA_FAILED, + "current state=%" PRId32 " is invalid.", currentState); + + if (currentState == StateId::STARTED) { + NotifyStreamChange(EventType::EVENT_ADD_STREAM); + } + TRUE_RETURN_V_MSG_E(avInput_ == nullptr, ERR_DH_AVT_PUSH_DATA_FAILED, "av input filter is null"); + + std::shared_ptr hisBuffer = TransBuffer2HiSBuffer(buffer); + TRUE_RETURN_V(hisBuffer == nullptr, ERR_DH_AVT_PUSH_DATA_FAILED); + + ErrorCode ret = avInput_->PushData(avInput_->GetName(), hisBuffer, -1); + TRUE_RETURN_V(ret != ErrorCode::SUCCESS, ERR_DH_AVT_PUSH_DATA_FAILED); + + SetCurrentState(StateId::PLAYING); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::PreparePipeline(const std::string& configParam) +{ + DHLOGI("PreparePipeline enter."); + + bool isErrState = (GetCurrentState() != StateId::CH_CREATED); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_PREPARE_FAILED, + "current state=%" PRId32 " is invalid.", GetCurrentState()); + + TRUE_RETURN_V_MSG_E((avInput_ == nullptr) || (avOutput_ == nullptr), ERR_DH_AVT_PREPARE_FAILED, + "av input or output filter is null"); + + // First: config av input filter + ErrorCode ret = avInput_->SetParameter(static_cast(Plugin::Tag::SRC_INPUT_TYPE), TransName2InputType(ownerName_)); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_SET_PARAM_FAILED, "set src_input_type failed"); + + ret = avInput_->SetParameter(static_cast(Plugin::Tag::MEDIA_TYPE), TransName2MediaType(ownerName_)); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_SET_PARAM_FAILED, "set media_type failed"); + + ret = avInput_->SetParameter(static_cast(Plugin::Tag::VIDEO_BIT_STREAM_FORMAT), VideoBitStreamFormat::ANNEXB); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_SET_PARAM_FAILED, "set video_bit_stream_format failed"); + + ret = avInput_->SetParameter(static_cast(Plugin::Tag::INPUT_MEMORY_TYPE), OHOS::Media::Plugin::MemoryType::VIRTUAL_ADDR); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_SET_PARAM_FAILED, "set input_memory_type failed"); + + // Second: config av output filter + ret = avOutput_->SetParameter(static_cast(Plugin::Tag::SRC_INPUT_TYPE), TransName2SoftbusInputType(ownerName_)); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_SET_PARAM_FAILED, "set src_input_type failed"); + + ret = avOutput_->SetParameter(static_cast(Plugin::Tag::MEDIA_DESCRIPTION), BuildChannelDescription(ownerName_, peerDevId_)); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_SET_PARAM_FAILED, "set media_description failed"); + + ret = pipeline_->Prepare(); + TRUE_RETURN_V_MSG_E(ret != ErrorCode::SUCCESS, ERR_DH_AVT_PREPARE_FAILED, "pipeline prepare failed"); + return DH_AVT_SUCCESS; +} + +int32_t AVSenderEngine::SendMessage(const std::shared_ptr &message) +{ + DHLOGI("SendMessage enter."); + TRUE_RETURN_V_MSG_E(message == nullptr, ERR_DH_AVT_INVALID_PARAM, "input message is nullptr."); + std::string msgData = message->MarshalMessage(); + return SoftbusChannelAdapter::GetInstance().SendBytesData(sessionName_, message->dstDevId_, msgData); +} + +int32_t AVSenderEngine::RegisterSenderCallback(const std::shared_ptr &callback) +{ + DHLOGI("RegisterSenderCallback enter."); + if (callback == nullptr) { + DHLOGE("RegisterSenderCallback failed, sender engine callback is nullptr."); + return ERR_DH_AVT_INVALID_PARAM; + } + senderCallback_ = callback; + return DH_AVT_SUCCESS; +} + +void AVSenderEngine::NotifyStreamChange(EventType type) +{ + DHLOGI("NotifyStreamChange enter, change type=%" PRId32, type); + + std::string sceneType = ""; + if (ownerName_ == OWNER_NAME_D_MIC) { + sceneType = SCENE_TYPE_D_MIC; + } else if (ownerName_ == OWNER_NAME_D_SPEAKER) { + sceneType = SCENE_TYPE_D_SPEAKER; + } else if (ownerName_ == OWNER_NAME_D_SCREEN) { + sceneType = SCENE_TYPE_D_SCREEN; + } else if (ownerName_ == OWNER_NAME_D_CAMERA) { + TRUE_RETURN(avInput_ == nullptr, "av input filter is null"); + Plugin::Any value; + avInput_->GetParameter(static_cast(Plugin::Tag::VIDEO_PIXEL_FORMAT), value); + std::string videoFormat = Plugin::AnyCast(value); + sceneType = (videoFormat == VIDEO_FORMAT_JEPG) ? SCENE_TYPE_D_CAMERA_PIC : SCENE_TYPE_D_CAMERA_STR; + } else { + DHLOGE("Unknown owner name=%s", ownerName_.c_str()); + return; + } + + AVTransEvent event = { type, sceneType, peerDevId_ }; + AVTransControlCenterKit::GetInstance().Notify(engineId_, event); +} + +void AVSenderEngine::OnChannelEvent(const AVTransEvent &event) +{ + DHLOGI("OnChannelEvent enter. event type:%" PRId32, event.type); + TRUE_RETURN(senderCallback_ == nullptr, "sender callback is nullptr"); + + switch (event.type) { + case EventType::EVENT_CHANNEL_OPENED: { + senderCallback_->OnSenderEvent(event); + SetCurrentState(StateId::CH_CREATED); + break; + } + case EventType::EVENT_CHANNEL_OPEN_FAIL: { + senderCallback_->OnSenderEvent(event); + SetCurrentState(StateId::INITIALIZED); + break; + } + case EventType::EVENT_CHANNEL_CLOSED: { + StateId currentState = GetCurrentState(); + if ((currentState != StateId::IDLE) && (currentState != StateId::INITIALIZED)) { + senderCallback_->OnSenderEvent(event); + } + SetCurrentState(StateId::INITIALIZED); + break; + } + case EventType::EVENT_DATA_RECEIVED: { + auto avMessage = std::make_shared(); + TRUE_RETURN(!avMessage->UnmarshalMessage(event.content), "unmarshal message failed"); + senderCallback_->OnMessageReceived(avMessage); + break; + } + default: + DHLOGE("Invalid event type."); + } +} + +void AVSenderEngine::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} + +void AVSenderEngine::OnEvent(const Event& event) +{ + DHLOGI("OnEvent enter. event type:%s", GetEventName(event.type)); + TRUE_RETURN(senderCallback_ == nullptr, "sender callback is nullptr"); + + switch (event.type) { + case OHOS::Media::EventType::EVENT_PLUGIN_EVENT: { + Plugin::PluginEvent pluginEvent = Plugin::AnyCast(event.param); + senderCallback_->OnSenderEvent(AVTransEvent{CastEventType(pluginEvent.type), "", peerDevId_}); + break; + } + default: + DHLOGE("Invalid event type."); + } +} +} +} \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/src/av_sender_engine_provider.cpp b/av_transport/av_trans_engine/av_sender/src/av_sender_engine_provider.cpp new file mode 100644 index 00000000..54cd1e2e --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/src/av_sender_engine_provider.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 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 "av_sender_engine_provider.h" + +#include "av_sender_engine.h" + +namespace OHOS { +namespace DistributedHardware { +AVSenderEngineProvider::AVSenderEngineProvider(const std::string ownerName) : ownerName_(ownerName) +{ + DHLOGI("AVSenderEngineProvider ctor."); + sessionName_ = ownerName + "_" + SENDER_CONTROL_SESSION_NAME_SUFFIX; + SoftbusChannelAdapter::GetInstance().CreateChannelServer(ownerName, sessionName_); + SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, AV_TRANS_SPECIAL_DEVICE_ID, this); +} + +AVSenderEngineProvider::~AVSenderEngineProvider() +{ + DHLOGI("AVSenderEngineProvider dctor."); + std::lock_guard lock(listMutex_); + for (auto &sender : senderEngineList_) { + sender->Release(); + } + SoftbusChannelAdapter::GetInstance().RemoveChannelServer(ownerName_, sessionName_); + ownerName_ = ""; + sessionName_ = ""; + senderEngineList_.clear(); + providerCallback_ = nullptr; +} + +std::shared_ptr AVSenderEngineProvider::CreateAVSenderEngine() +{ + DHLOGI("CreateAVSenderEngine enter."); + auto sender = std::shared_ptr(new (std::nothrow) AVSenderEngine(ownerName_)); + if (sender && sender->Initialize() == DH_AVT_SUCCESS) { + { + std::lock_guard lock(listMutex_); + senderEngineList_.push_back(sender); + } + return sender; + } + DHLOGE("create sender failed or sender init failed."); + return nullptr; +} + +std::vector> AVSenderEngineProvider::GetAVSenderEngineList() +{ + std::lock_guard lock(listMutex_); + return senderEngineList_; +} + +int32_t AVSenderEngineProvider::RegisterProviderCallback(const std::shared_ptr &callback) +{ + providerCallback_ = callback; + return DH_AVT_SUCCESS; +} + +void AVSenderEngineProvider::OnChannelEvent(const AVTransEvent &event) +{ + if ((providerCallback_ != nullptr) && + ((event.type == EventType::EVENT_CHANNEL_OPENED) || (event.type == EventType::EVENT_CHANNEL_CLOSED))) { + DHLOGI("on receiver channel event. event type:%" PRId32, event.type); + providerCallback_->OnProviderEvent(event); + } +} + +void AVSenderEngineProvider::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} +} +} + +extern "C" __attribute__((visibility("default"))) + OHOS::DistributedHardware::IAVEngineProvider* GetAVSenderEngineProvider(const std::string ownerName) +{ + return new (std::nothrow) OHOS::DistributedHardware::AVSenderEngineProvider(ownerName); +} \ No newline at end of file diff --git a/av_transport/common/src/av_sync_utils.cpp b/av_transport/common/src/av_sync_utils.cpp index bc6b1c38..a5c75a16 100644 --- a/av_transport/common/src/av_sync_utils.cpp +++ b/av_transport/common/src/av_sync_utils.cpp @@ -146,7 +146,7 @@ int32_t WriteFrameInfoToMemory(const AVTransSharedMemory &memory, uint32_t frame memory.name.c_str(), memory.size, memory.fd); TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory"); - TRUE_RETURN_V_MSG_E((frameNum <= 0)), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number"); + TRUE_RETURN_V_MSG_E((frameNum <= 0), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number"); int size = AshmemGetSize(memory.fd); TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size); -- Gitee