diff --git a/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine.h b/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..6f8dad5f3cc97da747a1729be3831781973fd3ad --- /dev/null +++ b/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2025 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_AUDIO_RECEIVER_ENGINE_H +#define OHOS_AV_AUDIO_RECEIVER_ENGINE_H + +#include "av_trans_audio_decoder_filter.h" +#include "av_trans_buffer.h" +#include "av_trans_bus_input_filter.h" +#include "av_trans_constants.h" +#include "av_trans_control_center_callback.h" +#include "av_trans_errno.h" +#include "av_trans_log.h" +#include "av_trans_message.h" +#include "av_trans_types.h" +#include "daudio_output_filter.h" +#include "distributed_hardware_fwk_kit.h" +#include "i_av_receiver_engine.h" +#include "pipeline.h" +#include "pipeline_event.h" +#include "softbus_channel_adapter.h" + +namespace OHOS { +namespace DistributedHardware { +class AVAudioReceiverEngine : public IAVReceiverEngine, + public ISoftbusChannelListener, + public std::enable_shared_from_this { +public: + AVAudioReceiverEngine(const std::string &ownerName, const std::string &peerDevId); + ~AVAudioReceiverEngine() override; + AVAudioReceiverEngine(const AVAudioReceiverEngine &other) = delete; + AVAudioReceiverEngine& operator=(const AVAudioReceiverEngine &other) = delete; + + // interfaces from IAVReceiverEngine + 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 SendMessage(const std::shared_ptr &message) override; + int32_t CreateControlChannel(const std::vector &dstDevIds, + const ChannelAttribute &attribution) override; + int32_t RegisterReceiverCallback(const std::shared_ptr &callback) override; + bool StartDumpMediaData() override; + bool StopDumpMediaData() override; + bool ReStartDumpMediaData() override; + + // interfaces from ISoftbusChannelListener + void OnChannelEvent(const AVTransEvent &event) override; + void OnStreamReceived(const StreamData *data, const StreamData *ext) override; + + void OnEvent(const Pipeline::Event &event); + Status OnCallback(const std::shared_ptr& filter, const Pipeline::FilterCallBackCommand cmd, + Pipeline::StreamType outType); + Status LinkAudioDecoderFilter(const std::shared_ptr& preFilter, Pipeline::StreamType type); + Status LinkAudioSinkFilter(const std::shared_ptr& preFilter, Pipeline::StreamType type); + + Status Prepare(); + +private: + int32_t InitPipeline(); + int32_t InitControlCenter(); + int32_t PreparePipeline(const std::string &configParam); + int32_t HandleOutputBuffer(std::shared_ptr &hisBuffer); + + void RegRespFunMap(); + void SetVideoWidth(const std::string &value); + void SetVideoHeight(const std::string &value); + void SetVideoFrameRate(const std::string &value); + void SetAudioBitRate(const std::string &value); + void SetVideoBitRate(const std::string &value); + void SetVideoCodecType(const std::string &value); + void SetAudioCodecType(const std::string &value); + void SetAudioChannelMask(const std::string &value); + void SetAudioSampleRate(const std::string &value); + void SetAudioChannelLayout(const std::string &value); + void SetAudioSampleFormat(const std::string &value); + void SetAudioFrameSize(const std::string &value); + void SetSyncResult(const std::string &value); + void SetStartAvSync(const std::string &value); + void SetStopAvSync(const std::string &value); + void SetSharedMemoryFd(const std::string &value); + void SetEngineReady(const std::string &value); + void SetParameterInner(AVTransTag tag, const std::string &value); + + StateId GetCurrentState() + { + std::lock_guard lock(stateMutex_); + return currentState_; + } + + void SetCurrentState(StateId stateId) + { + std::lock_guard lock(stateMutex_); + currentState_ = stateId; + } + +private: + static constexpr uint8_t TIME_OUT_MS = 50; + int32_t engineId_ = 0; + std::string ownerName_; + std::string sessionName_; + std::string peerDevId_; + std::mutex stateMutex_; + std::atomic isInitialized_ = false; + std::atomic currentState_ = StateId::IDLE; + + sptr ctlCtrCallback_ = nullptr; + std::shared_ptr dhFwkKit_ = nullptr; + std::shared_ptr receiverCallback_ = nullptr; + std::shared_ptr pipeline_ = nullptr; + std::shared_ptr playEventReceiver_ = nullptr; + std::shared_ptr playFilterCallback_ = nullptr; + std::string receiverId_ = ""; + std::shared_ptr avInput_ = nullptr; + std::shared_ptr audioDecoder_ = nullptr; + std::shared_ptr avOutput_ = nullptr; + std::shared_ptr meta_ = nullptr; + + using SetParaFunc = void (AVAudioReceiverEngine::*)(const std::string &value); + std::map funcMap_; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_AV_AUDIO_RECEIVER_ENGINE_H \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h b/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..8a1cbcb3ff073d22b4329d9200d50de30886a154 --- /dev/null +++ b/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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_AUDIO_RECEIVER_ENGINE_PROVIDER_H +#define OHOS_AV_AUDIO_RECEIVER_ENGINE_PROVIDER_H + +#include + +#include "i_av_engine_provider.h" +#include "softbus_channel_adapter.h" + +namespace OHOS { +namespace DistributedHardware { +class AVAudioReceiverEngineProvider : public IAVEngineProvider, public ISoftbusChannelListener { +public: + AVAudioReceiverEngineProvider(const std::string &ownerName); + ~AVAudioReceiverEngineProvider() override; + + std::shared_ptr CreateAVReceiverEngine(const std::string &peerDevId) override; + std::vector> GetAVReceiverEngineList() 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; + std::string TransName2PkgName(const std::string &ownerName); + +private: + std::string ownerName_; + std::string sessionName_; + std::mutex listMutex_; + std::mutex callbackMutex_; + std::shared_ptr providerCallback_; + std::vector> receiverEngineList_; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_AV_AUDIO_RECEIVER_ENGINE_PROVIDER_H \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine.cpp b/av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9af8c9c5ac0c5d7a1c155bd386e2234c638e2e4 --- /dev/null +++ b/av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine.cpp @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2025 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_audio_receiver_engine.h" + +namespace OHOS { +namespace DistributedHardware { +#undef DH_LOG_TAG +#define DH_LOG_TAG "AVAudioReceiverEngine" +class PlayerEventCbRec : public Pipeline::EventReceiver { +public: + explicit PlayerEventCbRec(std::shared_ptr receiver, std::string playerId) + { + AVTRANS_LOGI("PlayerEventCbRec ctor called."); + receiver_ = receiver; + } + + void OnEvent(const Pipeline::Event &event) override + { + AVTRANS_LOGD("PlayerEventCbRec OnEvent."); + if (auto receiver = receiver_.lock()) { + receiver->OnEvent(event); + } else { + AVTRANS_LOGI("invalid receiver_"); + } + } + +private: + std::weak_ptr receiver_; +}; + +class PlayerFilterCbRec : public Pipeline::FilterCallback { +public: + explicit PlayerFilterCbRec(std::shared_ptr receiver) + { + AVTRANS_LOGI("PlayerFilterCbRec ctor called."); + receiver_ = receiver; + } + + Status OnCallback(const std::shared_ptr& filter, Pipeline::FilterCallBackCommand cmd, + Pipeline::StreamType outType) override + { + AVTRANS_LOGD("PlayerFilterCbRec OnCallback."); + if (auto receiver = receiver_.lock()) { + return receiver->OnCallback(filter, cmd, outType); + } else { + AVTRANS_LOGI("invalid receiver_"); + return Status::ERROR_NULL_POINTER; + } + } + +private: + std::weak_ptr receiver_; +}; + +AVAudioReceiverEngine::AVAudioReceiverEngine(const std::string &ownerName, const std::string &peerDevId) + : ownerName_(ownerName), peerDevId_(peerDevId) +{ + AVTRANS_LOGI("AVAudioReceiverEngine ctor."); + sessionName_ = ownerName_ + "_" + RECEIVER_CONTROL_SESSION_NAME_SUFFIX; +} + +AVAudioReceiverEngine::~AVAudioReceiverEngine() +{ + AVTRANS_LOGI("AVAudioReceiverEngine dctor."); + Release(); + + dhFwkKit_ = nullptr; + pipeline_ = nullptr; + avInput_ = nullptr; + avOutput_ = nullptr; + audioDecoder_ = nullptr; + ctlCtrCallback_ = nullptr; +} + +int32_t AVAudioReceiverEngine::Initialize() +{ + TRUE_RETURN_V_MSG_E(isInitialized_.load(), DH_AVT_SUCCESS, "receiver 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"); + + ret = SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, peerDevId_, this); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_INIT_FAILED, "register receiver channel callback failed"); + RegRespFunMap(); + isInitialized_ = true; + SetCurrentState(StateId::INITIALIZED); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioReceiverEngine::InitPipeline() +{ + AVTRANS_LOGI("InitPipeline enter."); + receiverId_ = std::string("AVreceiverEngine") + std::to_string(Pipeline::Pipeline::GetNextPipelineId()); + playEventReceiver_ = std::make_shared(shared_from_this(), receiverId_); + playFilterCallback_ = std::make_shared(shared_from_this()); + pipeline_ = std::make_shared(); + pipeline_->Init(playEventReceiver_, playFilterCallback_, receiverId_); + + avInput_ = std::make_shared("builtin.avtrans.softbus.input", + Pipeline::FilterType::AUDIO_DATA_SOURCE); + TRUE_RETURN_V_MSG_E(avInput_ == nullptr, ERR_DH_AVT_NULL_POINTER, "create av input filter failed"); + avInput_->Init(playEventReceiver_, playFilterCallback_); + meta_ = std::make_shared(); + + Status ret = pipeline_->AddHeadFilters({avInput_}); + if (ret == Status::OK) { + AVTRANS_LOGI("Add head filters success."); + return DH_AVT_SUCCESS; + } else { + AVTRANS_LOGI("add head filter failed."); + return ERR_DH_AVT_INVALID_PARAM_VALUE; + } +} + +int32_t AVAudioReceiverEngine::InitControlCenter() +{ + dhFwkKit_ = std::make_shared(); + int32_t ret = dhFwkKit_->InitializeAVCenter(TransRole::AV_RECEIVER, engineId_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CTRL_CENTER_INIT_FAIL, "init av trans control center failed"); + + ctlCtrCallback_ = sptr(new (std::nothrow) AVTransControlCenterCallback()); + TRUE_RETURN_V_MSG_E(ctlCtrCallback_ == nullptr, ERR_DH_AVT_REGISTER_CALLBACK_FAIL, + "new control center callback failed"); + + std::shared_ptr engine = std::shared_ptr(shared_from_this()); + ctlCtrCallback_->SetReceiverEngine(engine); + + ret = dhFwkKit_->RegisterCtlCenterCallback(engineId_, ctlCtrCallback_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_REGISTER_CALLBACK_FAIL, + "register control center callback failed"); + + return DH_AVT_SUCCESS; +} + +int32_t AVAudioReceiverEngine::CreateControlChannel(const std::vector &dstDevIds, + const ChannelAttribute &attribution) +{ + (void)attribution; + AVTRANS_LOGI("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 receiver control channel callback failed"); + + std::string peerSessName = ownerName_ + "_" + SENDER_CONTROL_SESSION_NAME_SUFFIX; + ret = SoftbusChannelAdapter::GetInstance().OpenSoftbusChannel(sessionName_, peerSessName, peerDevId_); + TRUE_RETURN_V(ret == ERR_DH_AVT_SESSION_HAS_OPENED, ERR_DH_AVT_CHANNEL_ALREADY_CREATED); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CREATE_CHANNEL_FAILED, + "create receiver control channel failed"); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioReceiverEngine::PreparePipeline(const std::string &configParam) +{ + AVTRANS_LOGI("PreparePipeline enter."); + + StateId currentState = GetCurrentState(); + bool isErrState = ((currentState != StateId::INITIALIZED) && (currentState != StateId::CH_CREATED)); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_PREPARE_FAILED, + "current state=%{public}" PRId32 " is invalid.", currentState); + + cJSON *jsonObj = cJSON_CreateObject(); + if (jsonObj == nullptr) { + return ERR_DH_AVT_NULL_POINTER; + } + cJSON_AddStringToObject(jsonObj, KEY_ONWER_NAME.c_str(), ownerName_.c_str()); + cJSON_AddStringToObject(jsonObj, KEY_PEERDEVID_NAME.c_str(), peerDevId_.c_str()); + auto str = cJSON_PrintUnformatted(jsonObj); + if (str == nullptr) { + cJSON_Delete(jsonObj); + return ERR_DH_AVT_NULL_POINTER; + } + std::string jsonStr = std::string(str); + cJSON_free(str); + cJSON_Delete(jsonObj); + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return ERR_DH_AVT_NULL_POINTER; + } + meta_->SetData(Media::Tag::MEDIA_DESCRIPTION, jsonStr); + BufferDataType dataType = BufferDataType::AUDIO; + meta_->SetData(Media::Tag::MEDIA_STREAM_TYPE, dataType); + auto ret = Prepare(); + TRUE_RETURN_V(ret != Status::OK, ERR_DH_AVT_PREPARE_FAILED); + + SetCurrentState(StateId::CH_CREATED); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioReceiverEngine::Start() +{ + AVTRANS_LOGI("Start enter."); + + bool isErrState = (GetCurrentState() != StateId::CH_CREATED); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_START_FAILED, "current state=%{public}" PRId32 " is invalid.", + GetCurrentState()); + + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline is nullptr."); + return ERR_DH_AVT_START_FAILED; + } + auto ret = pipeline_->Start(); + TRUE_RETURN_V(ret != Status::OK, ERR_DH_AVT_START_FAILED); + SetCurrentState(StateId::STARTED); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioReceiverEngine::Stop() +{ + AVTRANS_LOGI("Stop enter."); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline is nullptr."); + return ERR_DH_AVT_START_FAILED; + } + auto ret = pipeline_->Stop(); + TRUE_RETURN_V(ret != Status::OK, ERR_DH_AVT_STOP_FAILED); + SetCurrentState(StateId::STOPPED); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioReceiverEngine::Release() +{ + AVTRANS_LOGI("Release enter."); + TRUE_RETURN_V(GetCurrentState() == StateId::IDLE, DH_AVT_SUCCESS); + if (pipeline_ != nullptr) { + pipeline_->Stop(); + } + if (dhFwkKit_ != nullptr) { + dhFwkKit_->ReleaseAVCenter(engineId_); + } + SoftbusChannelAdapter::GetInstance().CloseSoftbusChannel(sessionName_, peerDevId_); + SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(sessionName_, peerDevId_); + isInitialized_ = false; + pipeline_ = nullptr; + dhFwkKit_ = nullptr; + avInput_ = nullptr; + audioDecoder_ = nullptr; + avOutput_ = nullptr; + ctlCtrCallback_ = nullptr; + SetCurrentState(StateId::IDLE); + return DH_AVT_SUCCESS; +} + +void AVAudioReceiverEngine::SetParameterInner(AVTransTag tag, const std::string &value) +{ + switch (tag) { + case AVTransTag::VIDEO_CODEC_TYPE: + SetVideoCodecType(value); + break; + case AVTransTag::AUDIO_CODEC_TYPE: + SetAudioCodecType(value); + break; + case AVTransTag::AUDIO_CHANNEL_MASK: + SetAudioChannelMask(value); + break; + case AVTransTag::AUDIO_SAMPLE_RATE: + SetAudioSampleRate(value); + break; + case AVTransTag::AUDIO_CHANNEL_LAYOUT: + SetAudioChannelLayout(value); + break; + case AVTransTag::AUDIO_SAMPLE_FORMAT: + SetAudioSampleFormat(value); + break; + case AVTransTag::AUDIO_FRAME_SIZE: + SetAudioFrameSize(value); + break; + case AVTransTag::TIME_SYNC_RESULT: + SetSyncResult(value); + break; + case AVTransTag::START_AV_SYNC: + SetStartAvSync(value); + break; + case AVTransTag::STOP_AV_SYNC: + SetStopAvSync(value); + break; + case AVTransTag::SHARED_MEMORY_FD: + SetSharedMemoryFd(value); + break; + case AVTransTag::ENGINE_READY: + SetEngineReady(value); + break; + default: + break; + } +} + +int32_t AVAudioReceiverEngine::SetParameter(AVTransTag tag, const std::string &value) +{ + AVTRANS_LOGI("AVTransTag=%{public}u.", tag); + switch (tag) { + case AVTransTag::VIDEO_WIDTH: + SetVideoWidth(value); + break; + case AVTransTag::VIDEO_HEIGHT: + SetVideoHeight(value); + break; + case AVTransTag::VIDEO_FRAME_RATE: + SetVideoFrameRate(value); + break; + case AVTransTag::AUDIO_BIT_RATE: + SetAudioBitRate(value); + break; + case AVTransTag::VIDEO_BIT_RATE: + SetVideoBitRate(value); + break; + case AVTransTag::VIDEO_CODEC_TYPE: + case AVTransTag::AUDIO_CODEC_TYPE: + case AVTransTag::AUDIO_CHANNEL_MASK: + case AVTransTag::AUDIO_SAMPLE_RATE: + case AVTransTag::AUDIO_CHANNEL_LAYOUT: + case AVTransTag::AUDIO_SAMPLE_FORMAT: + case AVTransTag::AUDIO_FRAME_SIZE: + case AVTransTag::TIME_SYNC_RESULT: + case AVTransTag::START_AV_SYNC: + case AVTransTag::STOP_AV_SYNC: + case AVTransTag::SHARED_MEMORY_FD: + case AVTransTag::ENGINE_READY: + SetParameterInner(tag, value); + break; + default: + AVTRANS_LOGE("AVTransTag %{public}u is undefined.", tag); + return ERR_DH_AVT_INVALID_PARAM; + } + return DH_AVT_SUCCESS; +} + +void AVAudioReceiverEngine::RegRespFunMap() +{ + funcMap_[AVTransTag::VIDEO_WIDTH] = &AVAudioReceiverEngine::SetVideoWidth; + funcMap_[AVTransTag::VIDEO_HEIGHT] = &AVAudioReceiverEngine::SetVideoHeight; + funcMap_[AVTransTag::VIDEO_FRAME_RATE] = &AVAudioReceiverEngine::SetVideoFrameRate; + funcMap_[AVTransTag::AUDIO_BIT_RATE] = &AVAudioReceiverEngine::SetAudioBitRate; + funcMap_[AVTransTag::VIDEO_BIT_RATE] = &AVAudioReceiverEngine::SetVideoBitRate; + funcMap_[AVTransTag::VIDEO_CODEC_TYPE] = &AVAudioReceiverEngine::SetVideoCodecType; + funcMap_[AVTransTag::AUDIO_CODEC_TYPE] = &AVAudioReceiverEngine::SetAudioCodecType; + funcMap_[AVTransTag::AUDIO_CHANNEL_MASK] = &AVAudioReceiverEngine::SetAudioChannelMask; + funcMap_[AVTransTag::AUDIO_SAMPLE_RATE] = &AVAudioReceiverEngine::SetAudioSampleRate; + funcMap_[AVTransTag::AUDIO_CHANNEL_LAYOUT] = &AVAudioReceiverEngine::SetAudioChannelLayout; + funcMap_[AVTransTag::AUDIO_SAMPLE_FORMAT] = &AVAudioReceiverEngine::SetAudioSampleFormat; + funcMap_[AVTransTag::AUDIO_FRAME_SIZE] = &AVAudioReceiverEngine::SetAudioFrameSize; + funcMap_[AVTransTag::TIME_SYNC_RESULT] = &AVAudioReceiverEngine::SetSyncResult; + funcMap_[AVTransTag::START_AV_SYNC] = &AVAudioReceiverEngine::SetStartAvSync; + funcMap_[AVTransTag::STOP_AV_SYNC] = &AVAudioReceiverEngine::SetStopAvSync; + funcMap_[AVTransTag::SHARED_MEMORY_FD] = &AVAudioReceiverEngine::SetSharedMemoryFd; + funcMap_[AVTransTag::ENGINE_READY] = &AVAudioReceiverEngine::SetEngineReady; +} + +void AVAudioReceiverEngine::SetVideoWidth(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_WIDTH, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_WIDTH success, video width = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetVideoHeight(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_HEIGHT, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_HEIGHT success, video height = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetVideoFrameRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_FRAME_RATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_FRAME_RATE success, frame rate = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetAudioBitRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MEDIA_BITRATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter MEDIA_BITRATE success, bit rate = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetVideoBitRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MEDIA_BITRATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter MEDIA_BITRATE success, bit rate = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetVideoCodecType(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MIME_TYPE, value); +} + +void AVAudioReceiverEngine::SetAudioCodecType(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MIME_TYPE, std::stoi(value)); +} + +void AVAudioReceiverEngine::SetAudioChannelMask(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_CHANNEL_COUNT, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_CHANNELS success, audio channels = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetAudioSampleRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_SAMPLE_RATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_SAMPLE_RATE success, audio sample rate = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetAudioChannelLayout(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("avInput_ or avOutput_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_CHANNEL_LAYOUT, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_CHANNEL_LAYOUT success, audio channel layout = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetAudioSampleFormat(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + auto sampleFormat = static_cast(std::stoi(value)); + meta_->SetData(Media::Tag::AUDIO_SAMPLE_FORMAT, sampleFormat); + AVTRANS_LOGI("SetParameter AUDIO_SAMPLE_FORMAT success, audio sample format = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetAudioFrameSize(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_SAMPLE_PER_FRAME, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_SAMPLE_PER_FRAME success, audio sample per frame = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetSyncResult(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::USER_TIME_SYNC_RESULT, value); + AVTRANS_LOGI("SetParameter USER_TIME_SYNC_RESULT success, time sync result = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetStartAvSync(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::USER_AV_SYNC_GROUP_INFO, value); + AVTRANS_LOGI("SetParameter START_AV_SYNC success."); +} + +void AVAudioReceiverEngine::SetStopAvSync(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::USER_AV_SYNC_GROUP_INFO, value); + AVTRANS_LOGI("SetParameter STOP_AV_SYNC success."); +} + +void AVAudioReceiverEngine::SetSharedMemoryFd(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::USER_SHARED_MEMORY_FD, value); + AVTRANS_LOGI("SetParameter USER_SHARED_MEMORY_FD success, shared memory info = %{public}s", value.c_str()); +} + +void AVAudioReceiverEngine::SetEngineReady(const std::string &value) +{ + int32_t ret = PreparePipeline(value); + TRUE_LOG_MSG(ret != DH_AVT_SUCCESS, "SetParameter ENGINE_READY failed"); +} + +int32_t AVAudioReceiverEngine::SendMessage(const std::shared_ptr &message) +{ + 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 AVAudioReceiverEngine::RegisterReceiverCallback(const std::shared_ptr &callback) +{ + AVTRANS_LOGI("RegisterReceiverCallback enter."); + if (callback == nullptr) { + AVTRANS_LOGE("RegisterReceiverCallback failed, receiver engine callback is nullptr."); + return ERR_DH_AVT_INVALID_PARAM; + } + receiverCallback_ = callback; + return DH_AVT_SUCCESS; +} + +bool AVAudioReceiverEngine::StartDumpMediaData() +{ + return true; +} + +bool AVAudioReceiverEngine::StopDumpMediaData() +{ + return true; +} + +bool AVAudioReceiverEngine::ReStartDumpMediaData() +{ + return true; +} + +int32_t AVAudioReceiverEngine::HandleOutputBuffer(std::shared_ptr &hisBuffer) +{ + StateId currentState = GetCurrentState(); + bool isErrState = (currentState != StateId::STARTED) && (currentState != StateId::PLAYING); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_OUTPUT_DATA_FAILED, + "current state=%{public}" PRId32 " is invalid.", currentState); + std::shared_ptr transBuffer = std::make_shared(MetaType::AUDIO); + TRUE_RETURN_V_MSG_E(hisBuffer == nullptr || hisBuffer->memory_ == nullptr, ERR_DH_AVT_NULL_POINTER, + "hisBuffer is invalid"); + transBuffer->WrapBufferData(hisBuffer->memory_->GetAddr(), hisBuffer->memory_->GetCapacity(), + hisBuffer->memory_->GetSize()); + + SetCurrentState(StateId::PLAYING); + TRUE_RETURN_V(receiverCallback_ == nullptr, ERR_DH_AVT_OUTPUT_DATA_FAILED); + return receiverCallback_->OnDataAvailable(transBuffer); +} + +void AVAudioReceiverEngine::OnChannelEvent(const AVTransEvent &event) +{ + AVTRANS_LOGI("OnChannelEvent enter. event type:%{public}" PRId32, event.type); + TRUE_RETURN(receiverCallback_ == nullptr, "receiver callback is nullptr."); + + switch (event.type) { + case OHOS::DistributedHardware::EventType::EVENT_CHANNEL_OPENED: { + if (GetCurrentState() != StateId::STARTED) { + SetCurrentState(StateId::CH_CREATED); + } + AVTransEvent eventSend; + eventSend.type = EventType::EVENT_START_SUCCESS; + receiverCallback_->OnReceiverEvent(eventSend); + break; + } + case OHOS::DistributedHardware::EventType::EVENT_CHANNEL_OPEN_FAIL: { + SetCurrentState(StateId::INITIALIZED); + receiverCallback_->OnReceiverEvent(event); + break; + } + case OHOS::DistributedHardware::EventType::EVENT_CHANNEL_CLOSED: { + StateId currentState = GetCurrentState(); + if ((currentState != StateId::IDLE) && (currentState != StateId::INITIALIZED)) { + SetCurrentState(StateId::INITIALIZED); + receiverCallback_->OnReceiverEvent(event); + } + break; + } + case OHOS::DistributedHardware::EventType::EVENT_DATA_RECEIVED: { + auto avMessage = std::make_shared(); + TRUE_RETURN(!avMessage->UnmarshalMessage(event.content, event.peerDevId), "unmarshal message failed"); + receiverCallback_->OnMessageReceived(avMessage); + break; + } + default: + AVTRANS_LOGE("Invalid event type."); + } +} + +void AVAudioReceiverEngine::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} + +void AVAudioReceiverEngine::OnEvent(const Pipeline::Event &event) +{ + switch (event.type) { + case Pipeline::EventType::EVENT_BUFFER_PROGRESS: { + auto hisBuffer = Media::AnyCast>(event.param); + HandleOutputBuffer(hisBuffer); + break; + } + case Pipeline::EventType::EVENT_AUDIO_PROGRESS: { + auto channelEvent = Media::AnyCast(event.param); + OnChannelEvent(channelEvent); + break; + } + default: + AVTRANS_LOGE("Invalid event type."); + } +} + +Status AVAudioReceiverEngine::OnCallback(const std::shared_ptr& filter, + const Pipeline::FilterCallBackCommand cmd, Pipeline::StreamType outType) +{ + AVTRANS_LOGI("PipeDemo::OnCallback filter, outType: %{public}d", outType); + if (cmd == Pipeline::FilterCallBackCommand::NEXT_FILTER_NEEDED) { + switch (outType) { + case Pipeline::StreamType::STREAMTYPE_RAW_AUDIO: + return LinkAudioSinkFilter(filter, outType); + case Pipeline::StreamType::STREAMTYPE_DECODED_AUDIO: + return LinkAudioDecoderFilter(filter, outType); + default: + break; + } + } + return Status::OK; +} + +Status AVAudioReceiverEngine::LinkAudioDecoderFilter(const std::shared_ptr& preFilter, + Pipeline::StreamType type) +{ + AVTRANS_LOGI("PipeDemo::LinkAudioDecoderFilter"); + TRUE_RETURN_V(audioDecoder_ != nullptr, Status::OK); + audioDecoder_ = std::make_shared("builtin.recorder.audiodecoderfilter", + Pipeline::FilterType::FILTERTYPE_ADEC); + TRUE_RETURN_V(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER); + audioDecoder_->Init(playEventReceiver_, playFilterCallback_); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("Pipeline_ is nullptr"); + return Status::ERROR_NULL_POINTER; + } + pipeline_->LinkFilters(preFilter, {audioDecoder_}, type); + return Status::OK; +} + +Status AVAudioReceiverEngine::LinkAudioSinkFilter(const std::shared_ptr& preFilter, + Pipeline::StreamType type) +{ + AVTRANS_LOGI("PipeDemo::LinkAudioDecoderFilter"); + TRUE_RETURN_V(avOutput_ != nullptr, Status::OK); + avOutput_ = std::make_shared("builtin.daudio.output", + Pipeline::FilterType::FILTERTYPE_SSINK); + TRUE_RETURN_V(avOutput_ == nullptr, Status::ERROR_NULL_POINTER); + avOutput_->Init(playEventReceiver_, playFilterCallback_); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("Pipeline_ is nullptr"); + return Status::ERROR_NULL_POINTER; + } + pipeline_->LinkFilters(preFilter, {avOutput_}, type); + return Status::OK; +} + +Status AVAudioReceiverEngine::Prepare() +{ + if (avInput_ == nullptr) { + AVTRANS_LOGE("avInput_ is nullptr"); + return Status::ERROR_INVALID_OPERATION; + } + avInput_->SetParameter(meta_); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("Pipeline_ is nullptr"); + return Status::ERROR_INVALID_OPERATION; + } + Status ret = pipeline_->Prepare(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, Status::ERROR_INVALID_OPERATION, "pipeline prepare failed"); + return Status::OK; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine_provider.cpp b/av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine_provider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c632faf301d9d4fba73a600c2d8f651f5a30c64 --- /dev/null +++ b/av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine_provider.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2025 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_audio_receiver_engine_provider.h" + +#include "av_audio_receiver_engine.h" + +namespace OHOS { +namespace DistributedHardware { +#undef DH_LOG_TAG +#define DH_LOG_TAG "AVAudioReceiverEngineProvider" + +AVAudioReceiverEngineProvider::AVAudioReceiverEngineProvider(const std::string &ownerName) : ownerName_(ownerName) +{ + AVTRANS_LOGI("AVAudioReceiverEngineProvider ctor."); + sessionName_ = ownerName + "_" + RECEIVER_CONTROL_SESSION_NAME_SUFFIX; + if (ownerName != OWNER_NAME_D_MIC && ownerName != OWNER_NAME_D_VIRMODEM_MIC) { + SoftbusChannelAdapter::GetInstance().CreateChannelServer(TransName2PkgName(ownerName), sessionName_); + SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, AV_TRANS_SPECIAL_DEVICE_ID, this); + } +} + +AVAudioReceiverEngineProvider::~AVAudioReceiverEngineProvider() +{ + AVTRANS_LOGI("AVAudioReceiverEngineProvider dctor."); + { + std::lock_guard lock(listMutex_); + for (auto &receiver : receiverEngineList_) { + if (receiver == nullptr) { + continue; + } + receiver->Release(); + } + } + if (ownerName_ != OWNER_NAME_D_MIC && ownerName_ != OWNER_NAME_D_VIRMODEM_MIC) { + SoftbusChannelAdapter::GetInstance().RemoveChannelServer(TransName2PkgName(ownerName_), sessionName_); + SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(sessionName_, AV_TRANS_SPECIAL_DEVICE_ID); + } + ownerName_ = ""; + sessionName_ = ""; + receiverEngineList_.clear(); + providerCallback_ = nullptr; +} + +std::shared_ptr AVAudioReceiverEngineProvider::CreateAVReceiverEngine(const std::string &peerDevId) +{ + AVTRANS_LOGI("CreateAVReceiverEngine enter."); + auto receiver = std::make_shared(ownerName_, peerDevId); + if (receiver && receiver->Initialize() == DH_AVT_SUCCESS) { + { + std::lock_guard lock(listMutex_); + receiverEngineList_.push_back(receiver); + } + return receiver; + } + AVTRANS_LOGE("create receiver failed or receiver init failed."); + return nullptr; +} + +std::vector> AVAudioReceiverEngineProvider::GetAVReceiverEngineList() +{ + std::lock_guard lock(listMutex_); + return receiverEngineList_; +} + +int32_t AVAudioReceiverEngineProvider::RegisterProviderCallback( + const std::shared_ptr &callback) +{ + std::lock_guard lock(callbackMutex_); + providerCallback_ = callback; + return DH_AVT_SUCCESS; +} + +void AVAudioReceiverEngineProvider::OnChannelEvent(const AVTransEvent &event) +{ + if (providerCallback_ == nullptr) { + AVTRANS_LOGE("providerCallback_ is nullptr."); + return; + } + if ((event.type == EventType::EVENT_CHANNEL_OPENED) || (event.type == EventType::EVENT_CHANNEL_CLOSED)) { + AVTRANS_LOGI("on receiver channel event. event type:%{public}" PRId32, event.type); + providerCallback_->OnProviderEvent(event); + } +} + +void AVAudioReceiverEngineProvider::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} + +std::string AVAudioReceiverEngineProvider::TransName2PkgName(const std::string &ownerName) +{ + const static std::pair mapArray[] = { + {OWNER_NAME_D_MIC, PKG_NAME_D_AUDIO}, + {OWNER_NAME_D_VIRMODEM_MIC, PKG_NAME_D_CALL}, + {OWNER_NAME_D_CAMERA, PKG_NAME_D_CAMERA}, + {OWNER_NAME_D_SCREEN, PKG_NAME_D_SCREEN}, + {OWNER_NAME_D_SPEAKER, PKG_NAME_D_AUDIO}, + {OWNER_NAME_D_VIRMODEM_SPEAKER, PKG_NAME_D_CALL}, + {AV_SYNC_SENDER_CONTROL_SESSION_NAME, PKG_NAME_DH_FWK}, + {AV_SYNC_RECEIVER_CONTROL_SESSION_NAME, PKG_NAME_DH_FWK}, + }; + auto foundItem = std::find_if(std::begin(mapArray), std::end(mapArray), + [&](const auto& item) { return item.first == ownerName; }); + if (foundItem != std::end(mapArray)) { + return foundItem->second; + } + return EMPTY_STRING; +} +} // namespace DistributedHardware +} // namespace OHOS + +extern "C" __attribute__((visibility("default"))) + OHOS::DistributedHardware::IAVEngineProvider* GetAVAudioReceiverEngineProvider(const std::string ownerName) +{ + return new (std::nothrow) OHOS::DistributedHardware::AVAudioReceiverEngineProvider(ownerName); +} \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine.h b/av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..4d6321bf50a00c9c01e4582df43039f15302153b --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025 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_AUDIO_SENDER_ENGINE_H +#define OHOS_AV_AUDIO_SENDER_ENGINE_H + +#include "av_trans_buffer.h" +#include "av_trans_constants.h" +#include "av_trans_control_center_callback.h" +#include "av_trans_errno.h" +#include "av_trans_log.h" +#include "av_trans_message.h" + +#include "distributed_hardware_fwk_kit.h" + +#include "pipeline.h" +#include "pipeline_event.h" +#include "i_av_sender_engine.h" +#include "softbus_channel_adapter.h" +#include "av_trans_audio_input_filter.h" +#include "av_trans_audio_encoder_filter.h" +#include "dsoftbus_output_filter.h" + + +namespace OHOS { +namespace DistributedHardware { +class AVAudioSenderEngine : public IAVSenderEngine, + public ISoftbusChannelListener, + public std::enable_shared_from_this { +public: + AVAudioSenderEngine(const std::string &ownerName, const std::string &peerDevId); + ~AVAudioSenderEngine() override; + AVAudioSenderEngine(const AVAudioSenderEngine &other) = delete; + AVAudioSenderEngine& operator=(const AVAudioSenderEngine &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; + bool StartDumpMediaData() override; + bool StopDumpMediaData() override; + bool ReStartDumpMediaData() 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 + Status OnCallback(std::shared_ptr filter, const Pipeline::FilterCallBackCommand cmd, + Pipeline::StreamType outType); + Status LinkAudioEncoderFilter(const std::shared_ptr& preFilter, Pipeline::StreamType type); + Status LinkAudioSinkFilter(const std::shared_ptr& preFilter, Pipeline::StreamType type); + void OnEvent(const Pipeline::Event &event); + + Status Prepare(); + +private: + int32_t InitPipeline(); + int32_t InitControlCenter(); + int32_t PreparePipeline(const std::string &configParam); + void NotifyStreamChange(EventType type); + + void RegRespFunMap(); + void SetVideoWidth(const std::string &value); + void SetVideoHeight(const std::string &value); + void SetVideoPixelFormat(const std::string &value); + void SetVideoFrameRate(const std::string &value); + void SetAudioBitRate(const std::string &value); + void SetVideoBitRate(const std::string &value); + void SetVideoCodecType(const std::string &value); + void SetAudioCodecType(const std::string &value); + void SetAudioChannelMask(const std::string &value); + void SetAudioSampleRate(const std::string &value); + void SetAudioChannelLayout(const std::string &value); + void SetAudioSampleFormat(const std::string &value); + void SetAudioFrameSize(const std::string &value); + void SetSharedMemoryFd(const std::string &value); + void SetEngineReady(const std::string &value); + void SetEnginePause(const std::string &value); + void SetEngineResume(const std::string &value); + void SetParameterInner(AVTransTag tag, const std::string &value); + + 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_; + static constexpr uint8_t TIME_OUT_MS = 50; + + std::mutex stateMutex_; + std::atomic isInitialized_ = false; + std::atomic currentState_ = StateId::IDLE; + + sptr ctlCenCallback_ = nullptr; + std::shared_ptr dhFwkKit_ = nullptr; + std::shared_ptr senderCallback_ = nullptr; + std::shared_ptr pipeline_ = nullptr; + std::shared_ptr playEventReceiver_ = nullptr; + std::shared_ptr playFilterCallback_ = nullptr; + std::string senderId_ = ""; + std::shared_ptr avInput_ = nullptr; + std::shared_ptr encoderFilter_ = nullptr; + std::shared_ptr avOutput_ = nullptr; + std::shared_ptr meta_ = nullptr; + + using SetParaFunc = void (AVAudioSenderEngine::*)(const std::string &value); + std::map funcMap_; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_AV_AUDIO_SENDER_ENGINE_H \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine_provider.h b/av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..8d95527a1c1818fe12d88c3577d03fd2928624f0 --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine_provider.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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_AUDIO_SENDER_ENGINE_PROVIDER_H +#define OHOS_AV_AUDIO_SENDER_ENGINE_PROVIDER_H + +#include + +#include "i_av_engine_provider.h" +#include "softbus_channel_adapter.h" + +namespace OHOS { +namespace DistributedHardware { +class AVAudioSenderEngineProvider : public IAVEngineProvider, public ISoftbusChannelListener { +public: + AVAudioSenderEngineProvider(const std::string ownerName); + ~AVAudioSenderEngineProvider() override; + + std::shared_ptr CreateAVSenderEngine(const std::string &peerDevId) 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; + std::string TransName2PkgName(const std::string &ownerName); + +private: + std::string ownerName_; + std::string sessionName_; + std::mutex listMutex_; + std::mutex callbackMutex_; + std::shared_ptr providerCallback_; + std::vector> senderEngineList_; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_AV_AUDIO_SENDER_ENGINE_PROVIDER_H \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine.cpp b/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb73edf7de2a0aeeb1915cc129f6b082f98dddbd --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine.cpp @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2025 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_audio_sender_engine.h" + +namespace OHOS { +namespace DistributedHardware { + +#undef DH_LOG_TAG +#define DH_LOG_TAG "AVAudioSenderEngine" +class PlayerEventCbSen : public Pipeline::EventReceiver { +public: + explicit PlayerEventCbSen(std::shared_ptr sender, std::string playerId) + { + AVTRANS_LOGI("PlayerEventCbSen ctor called."); + sender_ = sender; + } + + void OnEvent(const Pipeline::Event &event) override + { + AVTRANS_LOGD("PlayerEventCbSen OnEvent."); + if (auto sender = sender_.lock()) { + sender->OnEvent(event); + } else { + AVTRANS_LOGI("invalid sender_"); + } + } + +private: + std::weak_ptr sender_; +}; + +class PlayerFilterCbSen : public Pipeline::FilterCallback { +public: + explicit PlayerFilterCbSen(std::shared_ptr sender) :sender_(sender) + { + AVTRANS_LOGI("PlayerFilterCbSen ctor called."); + sender_ = sender; + } + + Status OnCallback(const std::shared_ptr& filter, Pipeline::FilterCallBackCommand cmd, + Pipeline::StreamType outType) override + { + AVTRANS_LOGD("PlayerFilterCbSen OnCallback."); + if (auto lockedSender_ = sender_.lock()) { + return lockedSender_->OnCallback(filter, cmd, outType); + } else { + AVTRANS_LOGI("invalid receiver_"); + return Status::ERROR_NULL_POINTER; + } + } + +private: + std::weak_ptr sender_; +}; + +AVAudioSenderEngine::AVAudioSenderEngine(const std::string &ownerName, const std::string &peerDevId) + : ownerName_(ownerName), peerDevId_(peerDevId) +{ + AVTRANS_LOGI("AVAudioSenderEngine ctor()."); + sessionName_ = ownerName_ + "_" + SENDER_CONTROL_SESSION_NAME_SUFFIX; +} + +AVAudioSenderEngine::~AVAudioSenderEngine() +{ + AVTRANS_LOGI("AVAudioSenderEngine dctor()."); + Release(); + + dhFwkKit_ = nullptr; + pipeline_ = nullptr; + avInput_ = nullptr; + encoderFilter_ = nullptr; + avOutput_ = nullptr; + senderCallback_ = nullptr; + ctlCenCallback_ = nullptr; +} + +int32_t AVAudioSenderEngine::Initialize() +{ + TRUE_RETURN_V_MSG_E(isInitialized_.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"); + + int32_t retCenter = InitControlCenter(); + TRUE_RETURN_V_MSG_E(retCenter != DH_AVT_SUCCESS, ERR_DH_AVT_INIT_FAILED, "init av control center failed"); + + RegRespFunMap(); + isInitialized_ = true; + SetCurrentState(StateId::INITIALIZED); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioSenderEngine::InitPipeline() +{ + AVTRANS_LOGI("InitPipeline enter."); + senderId_ = std::string("AVAudioSenderEngine") + std::to_string(Pipeline::Pipeline::GetNextPipelineId()); + playEventReceiver_ = std::make_shared(shared_from_this(), senderId_); + playFilterCallback_ = std::make_shared(shared_from_this()); + pipeline_ = std::make_shared(); + pipeline_->Init(playEventReceiver_, playFilterCallback_, senderId_); + + avInput_ = std::make_shared("builtin.avtrans.audio.input", + Pipeline::FilterType::FILTERTYPE_SOURCE); + TRUE_RETURN_V_MSG_E(avInput_ == nullptr, ERR_DH_AVT_NULL_POINTER, "create av input filter failed"); + avInput_->Init(playEventReceiver_, playFilterCallback_); + meta_ = std::make_shared(); + + Status ret = pipeline_->AddHeadFilters({avInput_}); + if (ret == Status::OK) { + AVTRANS_LOGI("Add head filters success."); + return DH_AVT_SUCCESS; + } else { + AVTRANS_LOGI("add head filter failed."); + return ERR_DH_AVT_INVALID_PARAM_VALUE; + } +} + +int32_t AVAudioSenderEngine::InitControlCenter() +{ + dhFwkKit_ = std::make_shared(); + int32_t ret = dhFwkKit_->InitializeAVCenter(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_ = sptr(new (std::nothrow) AVTransControlCenterCallback()); + TRUE_RETURN_V_MSG_E(ctlCenCallback_ == nullptr, ERR_DH_AVT_REGISTER_CALLBACK_FAIL, + "new control center callback failed"); + + std::shared_ptr engine = std::shared_ptr(shared_from_this()); + ctlCenCallback_->SetSenderEngine(engine); + + ret = dhFwkKit_->RegisterCtlCenterCallback(engineId_, ctlCenCallback_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_REGISTER_CALLBACK_FAIL, + "register control center callback failed"); + + return DH_AVT_SUCCESS; +} + +int32_t AVAudioSenderEngine::CreateControlChannel(const std::vector &dstDevIds, + const ChannelAttribute &attribution) +{ + (void)attribution; + AVTRANS_LOGI("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(ret == ERR_DH_AVT_SESSION_HAS_OPENED, ERR_DH_AVT_CHANNEL_ALREADY_CREATED); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, ERR_DH_AVT_CREATE_CHANNEL_FAILED, + "create control channel failed"); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioSenderEngine::PreparePipeline(const std::string &configParam) +{ + AVTRANS_LOGI("PreparePipeline enter."); + + StateId currentState = GetCurrentState(); + bool isErrState = ((currentState != StateId::INITIALIZED) && (currentState != StateId::CH_CREATED)); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_PREPARE_FAILED, + "current state=%{public}" PRId32 " is invalid.", currentState); + + cJSON *jsonObj = cJSON_CreateObject(); + if (jsonObj == nullptr) { + return ERR_DH_AVT_NULL_POINTER; + } + cJSON_AddStringToObject(jsonObj, KEY_ONWER_NAME.c_str(), ownerName_.c_str()); + cJSON_AddStringToObject(jsonObj, KEY_PEERDEVID_NAME.c_str(), peerDevId_.c_str()); + auto str = cJSON_PrintUnformatted(jsonObj); + if (str == nullptr) { + cJSON_Delete(jsonObj); + return ERR_DH_AVT_NULL_POINTER; + } + std::string jsonStr = std::string(str); + cJSON_free(str); + cJSON_Delete(jsonObj); + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return ERR_DH_AVT_NULL_POINTER; + } + meta_->SetData(Media::Tag::MEDIA_DESCRIPTION, jsonStr); + BufferDataType dataType = BufferDataType::AUDIO; + meta_->SetData(Media::Tag::MEDIA_STREAM_TYPE, dataType); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline is nullptr."); + return ERR_DH_AVT_SET_PARAM_FAILED; + } + auto ret = Prepare(); + TRUE_RETURN_V(ret != Status::OK, ERR_DH_AVT_PREPARE_FAILED); + + SetCurrentState(StateId::CH_CREATED); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioSenderEngine::Start() +{ + AVTRANS_LOGI("Start enter."); + + bool isErrState = (GetCurrentState() != StateId::CH_CREATED); + TRUE_RETURN_V_MSG_E(isErrState, ERR_DH_AVT_START_FAILED, "current state=%{public}" PRId32 " is invalid.", + GetCurrentState()); + + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline_ is nullptr."); + return ERR_DH_AVT_START_FAILED; + } + Status errCode = pipeline_->Start(); + TRUE_RETURN_V_MSG_E(errCode != Status::OK, ERR_DH_AVT_START_FAILED, "start pipeline failed"); + + if (dhFwkKit_ != nullptr) { + int32_t ret = dhFwkKit_->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); + AVTRANS_LOGI("Start sender engine success."); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioSenderEngine::Stop() +{ + AVTRANS_LOGI("Stop sender engine enter."); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline_ is nullptr."); + return ERR_DH_AVT_STOP_FAILED; + } + Status ret = pipeline_->Stop(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ERR_DH_AVT_STOP_FAILED, "stop pipeline failed"); + SetCurrentState(StateId::STOPPED); + NotifyStreamChange(EventType::EVENT_REMOVE_STREAM); + AVTRANS_LOGI("Stop sender engine success."); + return DH_AVT_SUCCESS; +} + +int32_t AVAudioSenderEngine::Release() +{ + AVTRANS_LOGI("Release sender engine enter."); + if (pipeline_ != nullptr) { + pipeline_->Stop(); + } + if (dhFwkKit_ != nullptr) { + dhFwkKit_->ReleaseAVCenter(engineId_); + } + SoftbusChannelAdapter::GetInstance().CloseSoftbusChannel(sessionName_, peerDevId_); + SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(sessionName_, peerDevId_); + isInitialized_ = false; + pipeline_ = nullptr; + dhFwkKit_ = nullptr; + avInput_ = nullptr; + encoderFilter_ = nullptr; + avOutput_ = nullptr; + senderCallback_ = nullptr; + ctlCenCallback_ = nullptr; + SetCurrentState(StateId::IDLE); + return DH_AVT_SUCCESS; +} + +void AVAudioSenderEngine::SetParameterInner(AVTransTag tag, const std::string &value) +{ + switch (tag) { + case AVTransTag::VIDEO_CODEC_TYPE: + SetVideoCodecType(value); + break; + case AVTransTag::AUDIO_CODEC_TYPE: + SetAudioCodecType(value); + break; + case AVTransTag::AUDIO_CHANNEL_MASK: + SetAudioChannelMask(value); + break; + case AVTransTag::AUDIO_SAMPLE_RATE: + SetAudioSampleRate(value); + break; + case AVTransTag::AUDIO_CHANNEL_LAYOUT: + SetAudioChannelLayout(value); + break; + case AVTransTag::AUDIO_SAMPLE_FORMAT: + SetAudioSampleFormat(value); + break; + case AVTransTag::AUDIO_FRAME_SIZE: + SetAudioFrameSize(value); + break; + case AVTransTag::SHARED_MEMORY_FD: + SetSharedMemoryFd(value); + break; + case AVTransTag::ENGINE_READY: + SetEngineReady(value); + break; + case AVTransTag::ENGINE_PAUSE: + SetEnginePause(value); + break; + case AVTransTag::ENGINE_RESUME: + SetEngineResume(value); + break; + default: + break; + } +} + +int32_t AVAudioSenderEngine::SetParameter(AVTransTag tag, const std::string &value) +{ + AVTRANS_LOGI("AVTransTag=%{public}u.", tag); + switch (tag) { + case AVTransTag::VIDEO_WIDTH: + SetVideoWidth(value); + break; + case AVTransTag::VIDEO_HEIGHT: + SetVideoHeight(value); + break; + case AVTransTag::VIDEO_PIXEL_FORMAT: + SetVideoPixelFormat(value); + break; + case AVTransTag::VIDEO_FRAME_RATE: + SetVideoFrameRate(value); + break; + case AVTransTag::AUDIO_BIT_RATE: + SetAudioBitRate(value); + break; + case AVTransTag::VIDEO_BIT_RATE: + SetVideoBitRate(value); + break; + case AVTransTag::VIDEO_CODEC_TYPE: + case AVTransTag::AUDIO_CODEC_TYPE: + case AVTransTag::AUDIO_CHANNEL_MASK: + case AVTransTag::AUDIO_SAMPLE_RATE: + case AVTransTag::AUDIO_CHANNEL_LAYOUT: + case AVTransTag::AUDIO_SAMPLE_FORMAT: + case AVTransTag::AUDIO_FRAME_SIZE: + case AVTransTag::SHARED_MEMORY_FD: + case AVTransTag::ENGINE_READY: + case AVTransTag::ENGINE_PAUSE: + case AVTransTag::ENGINE_RESUME: + SetParameterInner(tag, value); + break; + default: + AVTRANS_LOGE("AVTransTag %{public}u is undefined.", tag); + return ERR_DH_AVT_INVALID_PARAM; + } + return DH_AVT_SUCCESS; +} + +void AVAudioSenderEngine::RegRespFunMap() +{ + funcMap_[AVTransTag::VIDEO_WIDTH] = &AVAudioSenderEngine::SetVideoWidth; + funcMap_[AVTransTag::VIDEO_HEIGHT] = &AVAudioSenderEngine::SetVideoHeight; + funcMap_[AVTransTag::VIDEO_PIXEL_FORMAT] = &AVAudioSenderEngine::SetVideoPixelFormat; + funcMap_[AVTransTag::VIDEO_FRAME_RATE] = &AVAudioSenderEngine::SetVideoFrameRate; + funcMap_[AVTransTag::AUDIO_BIT_RATE] = &AVAudioSenderEngine::SetAudioBitRate; + funcMap_[AVTransTag::VIDEO_BIT_RATE] = &AVAudioSenderEngine::SetVideoBitRate; + funcMap_[AVTransTag::VIDEO_CODEC_TYPE] = &AVAudioSenderEngine::SetVideoCodecType; + funcMap_[AVTransTag::AUDIO_CODEC_TYPE] = &AVAudioSenderEngine::SetAudioCodecType; + funcMap_[AVTransTag::AUDIO_CHANNEL_MASK] = &AVAudioSenderEngine::SetAudioChannelMask; + funcMap_[AVTransTag::AUDIO_SAMPLE_RATE] = &AVAudioSenderEngine::SetAudioSampleRate; + funcMap_[AVTransTag::AUDIO_CHANNEL_LAYOUT] = &AVAudioSenderEngine::SetAudioChannelLayout; + funcMap_[AVTransTag::AUDIO_SAMPLE_FORMAT] = &AVAudioSenderEngine::SetAudioSampleFormat; + funcMap_[AVTransTag::AUDIO_FRAME_SIZE] = &AVAudioSenderEngine::SetAudioFrameSize; + funcMap_[AVTransTag::SHARED_MEMORY_FD] = &AVAudioSenderEngine::SetSharedMemoryFd; + funcMap_[AVTransTag::ENGINE_READY] = &AVAudioSenderEngine::SetEngineReady; + funcMap_[AVTransTag::ENGINE_PAUSE] = &AVAudioSenderEngine::SetEnginePause; + funcMap_[AVTransTag::ENGINE_RESUME] = &AVAudioSenderEngine::SetEngineResume; +} + +void AVAudioSenderEngine::SetVideoWidth(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_WIDTH, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_WIDTH success, video width = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetVideoHeight(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_HEIGHT, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_HEIGHT success, video height = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetVideoPixelFormat(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("avInput_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_PIXEL_FORMAT, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_PIXEL_FORMAT success, pixel format = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetVideoFrameRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::VIDEO_FRAME_RATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter VIDEO_FRAME_RATE success, frame rate = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetAudioBitRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MEDIA_BITRATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter MEDIA_BITRATE success, bit rate = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetVideoBitRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MEDIA_BITRATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter MEDIA_BITRATE success, bit rate = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetVideoCodecType(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MIME_TYPE, value); +} + +void AVAudioSenderEngine::SetAudioCodecType(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::MIME_TYPE, std::stoi(value)); +} + +void AVAudioSenderEngine::SetAudioChannelMask(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_CHANNEL_COUNT, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_CHANNELS success, audio channels = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetAudioSampleRate(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_SAMPLE_RATE, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_SAMPLE_RATE success, audio sample rate = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetAudioChannelLayout(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("avInput_ or avOutput_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_CHANNEL_LAYOUT, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_CHANNEL_LAYOUT success, audio channel layout = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetAudioSampleFormat(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + auto sampleFormat = static_cast(std::stoi(value)); + meta_->SetData(Media::Tag::AUDIO_SAMPLE_FORMAT, sampleFormat); + AVTRANS_LOGI("SetParameter AUDIO_SAMPLE_FORMAT success, audio sample format = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetAudioFrameSize(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::AUDIO_SAMPLE_PER_FRAME, std::stoi(value)); + AVTRANS_LOGI("SetParameter AUDIO_SAMPLE_PER_FRAME success, audio sample per frame = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetSharedMemoryFd(const std::string &value) +{ + if (meta_ == nullptr) { + AVTRANS_LOGE("meta_ is nullptr."); + return; + } + meta_->SetData(Media::Tag::USER_SHARED_MEMORY_FD, value); + AVTRANS_LOGI("SetParameter USER_SHARED_MEMORY_FD success, shared memory info = %{public}s", value.c_str()); +} + +void AVAudioSenderEngine::SetEngineReady(const std::string &value) +{ + int32_t ret = PreparePipeline(value); + TRUE_LOG_MSG(ret != DH_AVT_SUCCESS, "SetParameter ENGINE_READY failed"); +} + +void AVAudioSenderEngine::SetEnginePause(const std::string &value) +{ + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline is null, need init first."); + return; + } + + Status ret = pipeline_->Pause(); + TRUE_LOG_MSG(ret != Status::OK, "pipeline pause failed"); +} + +void AVAudioSenderEngine::SetEngineResume(const std::string &value) +{ + if (pipeline_ == nullptr) { + AVTRANS_LOGE("pipeline is null, need init first."); + return; + } + + Status ret = pipeline_->Resume(); + TRUE_LOG_MSG(ret != Status::OK, "pipeline resume failed"); +} + +int32_t AVAudioSenderEngine::PushData(const std::shared_ptr &buffer) +{ + 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=%{public}" 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"); + sptr producer = avInput_->GetInputBufQueProducer(); + auto data = buffer->GetBufferData(); + if (data == nullptr) { + return ERR_DH_AVT_PUSH_DATA_FAILED; + } + Media::AVBufferConfig config; + auto bufferSize = static_cast(data->GetSize()); + config.size = bufferSize; + config.memoryType = Media::MemoryType::VIRTUAL_MEMORY; + config.memoryFlag = Media::MemoryFlag::MEMORY_READ_WRITE; + std::shared_ptr outBuffer = nullptr; + producer->RequestBuffer(outBuffer, config, TIME_OUT_MS); + TRUE_RETURN_V_MSG_E(outBuffer == nullptr, ERR_DH_AVT_PUSH_DATA_FAILED, "RequestBuffer fail"); + auto meta = outBuffer->meta_; + if (meta == nullptr) { + AVTRANS_LOGE("outBuffer->meta_ is null"); + producer->PushBuffer(outBuffer, true); + return ERR_DH_AVT_PREPARE_FAILED; + } + outBuffer->memory_->Write(data->GetAddress(), bufferSize, 0); + producer->PushBuffer(outBuffer, true); + SetCurrentState(StateId::PLAYING); + return DH_AVT_SUCCESS; +} + +Status AVAudioSenderEngine::Prepare() +{ + if (avInput_ == nullptr) { + AVTRANS_LOGE("avInput_ is nullptr"); + return Status::ERROR_INVALID_OPERATION; + } + avInput_->SetParameter(meta_); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("Pipeline_ is nullptr"); + return Status::ERROR_INVALID_OPERATION; + } + Status ret = pipeline_->Prepare(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, Status::ERROR_INVALID_OPERATION, "pipeline prepare failed"); + return Status::OK; +} + +int32_t AVAudioSenderEngine::SendMessage(const std::shared_ptr &message) +{ + 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 AVAudioSenderEngine::RegisterSenderCallback(const std::shared_ptr &callback) +{ + AVTRANS_LOGI("RegisterSenderCallback enter."); + TRUE_RETURN_V_MSG_E(callback == nullptr, ERR_DH_AVT_INVALID_PARAM, "input sender engine callback is nullptr."); + + senderCallback_ = callback; + return DH_AVT_SUCCESS; +} + +bool AVAudioSenderEngine::StartDumpMediaData() +{ + return true; +} + +bool AVAudioSenderEngine::StopDumpMediaData() +{ + return true; +} + +bool AVAudioSenderEngine::ReStartDumpMediaData() +{ + return true; +} + +void AVAudioSenderEngine::NotifyStreamChange(EventType type) +{ + AVTRANS_LOGI("NotifyStreamChange enter, change type=%{public}" 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"); + } else { + AVTRANS_LOGE("Unknown owner name=%{public}s", ownerName_.c_str()); + return; + } + + TRUE_RETURN(dhFwkKit_ == nullptr, "dh fwk kit is nullptr."); + dhFwkKit_->NotifyAVCenter(engineId_, { type, sceneType, peerDevId_ }); +} + +void AVAudioSenderEngine::OnEvent(const Pipeline::Event &event) +{ + switch (event.type) { + case Pipeline::EventType::EVENT_AUDIO_PROGRESS: { + auto channelEvent = Media::AnyCast(event.param); + OnChannelEvent(channelEvent); + break; + } + default: + AVTRANS_LOGE("Invalid event type."); + } +} + +void AVAudioSenderEngine::OnChannelEvent(const AVTransEvent &event) +{ + AVTRANS_LOGI("OnChannelEvent enter. event type:%{public}" PRId32, event.type); + TRUE_RETURN(senderCallback_ == nullptr, "sender callback is nullptr"); + + switch (event.type) { + case EventType::EVENT_CHANNEL_OPENED: { + if (GetCurrentState() != StateId::STARTED) { + SetCurrentState(StateId::CH_CREATED); + } + AVTransEvent eventSend; + eventSend.type = EventType::EVENT_START_SUCCESS; + senderCallback_->OnSenderEvent(eventSend); + break; + } + case EventType::EVENT_CHANNEL_OPEN_FAIL: { + SetCurrentState(StateId::INITIALIZED); + senderCallback_->OnSenderEvent(event); + break; + } + case EventType::EVENT_CHANNEL_CLOSED: { + StateId currentState = GetCurrentState(); + if ((currentState != StateId::IDLE) && (currentState != StateId::INITIALIZED)) { + SetCurrentState(StateId::INITIALIZED); + senderCallback_->OnSenderEvent(event); + } + break; + } + case EventType::EVENT_DATA_RECEIVED: { + auto avMessage = std::make_shared(); + TRUE_RETURN(!avMessage->UnmarshalMessage(event.content, event.peerDevId), "unmarshal message failed"); + senderCallback_->OnMessageReceived(avMessage); + break; + } + default: + AVTRANS_LOGE("Invalid event type."); + } +} + +void AVAudioSenderEngine::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} + +Status AVAudioSenderEngine::OnCallback(std::shared_ptr filter, + const Pipeline::FilterCallBackCommand cmd, Pipeline::StreamType outType) +{ + AVTRANS_LOGI("AVAudioSenderEngine::OnCallback filter, outType: %{public}d", outType); + if (cmd == Pipeline::FilterCallBackCommand::NEXT_FILTER_NEEDED) { + switch (outType) { + case Pipeline::StreamType::STREAMTYPE_RAW_AUDIO: + return LinkAudioSinkFilter(filter, outType); + case Pipeline::StreamType::STREAMTYPE_ENCODED_AUDIO: + return LinkAudioEncoderFilter(filter, outType); + default: + break; + } + } + return Status::OK; +} + +Status AVAudioSenderEngine::LinkAudioEncoderFilter(const std::shared_ptr& preFilter, + Pipeline::StreamType type) +{ + AVTRANS_LOGI("AVAudioSenderEngine::LinkAudioDecoderFilter"); + TRUE_RETURN_V(encoderFilter_ != nullptr, Status::OK); + encoderFilter_ = std::make_shared("builtin.recorder.EncoderFilter", + Pipeline::FilterType::FILTERTYPE_AENC); + TRUE_RETURN_V(encoderFilter_ == nullptr, Status::ERROR_NULL_POINTER); + encoderFilter_->Init(playEventReceiver_, playFilterCallback_); + + return pipeline_->LinkFilters(preFilter, {encoderFilter_}, type); +} + +Status AVAudioSenderEngine::LinkAudioSinkFilter(const std::shared_ptr& preFilter, + Pipeline::StreamType type) +{ + AVTRANS_LOGI("AVAudioSenderEngine::LinkAudioDecoderFilter"); + TRUE_RETURN_V(avOutput_ != nullptr, Status::OK); + avOutput_ = std::make_shared("builtin.avtransport.avoutput", + Pipeline::FilterType::FILTERTYPE_ASINK); + TRUE_RETURN_V(avOutput_ == nullptr, Status::ERROR_NULL_POINTER); + avOutput_->Init(playEventReceiver_, playFilterCallback_); + if (pipeline_ == nullptr) { + AVTRANS_LOGE("Pipeline_ is nullptr"); + return Status::ERROR_INVALID_OPERATION; + } + return pipeline_->LinkFilters(preFilter, {avOutput_}, type); +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine_provider.cpp b/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine_provider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e2751bbb4e1d0f9847d66809e78e36a4e21ae1a --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine_provider.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025 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_audio_sender_engine_provider.h" + +#include "av_audio_sender_engine.h" + +namespace OHOS { +namespace DistributedHardware { +#undef DH_LOG_TAG +#define DH_LOG_TAG "AVAudioSenderEngineProvider" + +AVAudioSenderEngineProvider::AVAudioSenderEngineProvider(const std::string ownerName) : ownerName_(ownerName) +{ + AVTRANS_LOGI("AVAudioSenderEngineProvider ctor."); + sessionName_ = ownerName + "_" + SENDER_CONTROL_SESSION_NAME_SUFFIX; + if (ownerName == OWNER_NAME_D_MIC || ownerName == OWNER_NAME_D_VIRMODEM_MIC) { + SoftbusChannelAdapter::GetInstance().CreateChannelServer(TransName2PkgName(ownerName), sessionName_); + SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, AV_TRANS_SPECIAL_DEVICE_ID, this); + } +} + +AVAudioSenderEngineProvider::~AVAudioSenderEngineProvider() +{ + AVTRANS_LOGI("AVAudioSenderEngineProvider dctor."); + std::lock_guard lock(listMutex_); + for (auto &sender : senderEngineList_) { + if (sender == nullptr) { + continue; + } + sender->Release(); + } + if (ownerName_ == OWNER_NAME_D_MIC || ownerName_ == OWNER_NAME_D_VIRMODEM_MIC) { + SoftbusChannelAdapter::GetInstance().RemoveChannelServer(TransName2PkgName(ownerName_), sessionName_); + SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(sessionName_, AV_TRANS_SPECIAL_DEVICE_ID); + } + ownerName_ = ""; + sessionName_ = ""; + senderEngineList_.clear(); + providerCallback_ = nullptr; +} + +std::shared_ptr AVAudioSenderEngineProvider::CreateAVSenderEngine(const std::string &peerDevId) +{ + AVTRANS_LOGI("CreateAVSenderEngine enter."); + auto sender = std::make_shared(ownerName_, peerDevId); + if (sender && sender->Initialize() == DH_AVT_SUCCESS) { + { + std::lock_guard lock(listMutex_); + senderEngineList_.push_back(sender); + } + return sender; + } + AVTRANS_LOGE("create sender failed or sender init failed."); + return nullptr; +} + +std::vector> AVAudioSenderEngineProvider::GetAVSenderEngineList() +{ + std::lock_guard lock(listMutex_); + return senderEngineList_; +} + +int32_t AVAudioSenderEngineProvider::RegisterProviderCallback( + const std::shared_ptr &callback) +{ + std::lock_guard lock(callbackMutex_); + providerCallback_ = callback; + return DH_AVT_SUCCESS; +} + +void AVAudioSenderEngineProvider::OnChannelEvent(const AVTransEvent &event) +{ + if (providerCallback_ == nullptr) { + AVTRANS_LOGE("providerCallback_ is nullptr"); + return; + } + if ((event.type == EventType::EVENT_CHANNEL_OPENED) || (event.type == EventType::EVENT_CHANNEL_CLOSED)) { + AVTRANS_LOGI("on receiver channel event. event type:%{public}" PRId32, event.type); + providerCallback_->OnProviderEvent(event); + } +} + +void AVAudioSenderEngineProvider::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} +std::string AVAudioSenderEngineProvider::TransName2PkgName(const std::string &ownerName) +{ + const static std::pair mapArray[] = { + {OWNER_NAME_D_MIC, PKG_NAME_D_AUDIO}, + {OWNER_NAME_D_VIRMODEM_MIC, PKG_NAME_D_CALL}, + {OWNER_NAME_D_CAMERA, PKG_NAME_D_CAMERA}, + {OWNER_NAME_D_SCREEN, PKG_NAME_D_SCREEN}, + {OWNER_NAME_D_SPEAKER, PKG_NAME_D_AUDIO}, + {OWNER_NAME_D_VIRMODEM_SPEAKER, PKG_NAME_D_CALL}, + {AV_SYNC_SENDER_CONTROL_SESSION_NAME, PKG_NAME_DH_FWK}, + {AV_SYNC_RECEIVER_CONTROL_SESSION_NAME, PKG_NAME_DH_FWK}, + }; + auto foundItem = std::find_if(std::begin(mapArray), std::end(mapArray), + [&](const auto& item) { return item.first == ownerName; }); + if (foundItem != std::end(mapArray)) { + return foundItem->second; + } + return EMPTY_STRING; +} +} // namespace DistributedHardware +} // namespace OHOS + +extern "C" __attribute__((visibility("default"))) + OHOS::DistributedHardware::IAVEngineProvider* GetAVAudioSenderEngineProvider(const std::string ownerName) +{ + return new (std::nothrow) OHOS::DistributedHardware::AVAudioSenderEngineProvider(ownerName); +} \ No newline at end of file