From 47712635f9b889a822cbfb02e9e71d368f369f03 Mon Sep 17 00:00:00 2001 From: byndyx Date: Thu, 6 Feb 2025 11:41:21 +0800 Subject: [PATCH] new pipeline Signed-off-by: byndyx --- .../av_trans_engine/av_receiver/BUILD.gn | 11 + .../include/av_audio_receiver_engine.h | 137 ++++ .../av_audio_receiver_engine_provider.h} | 65 +- .../src/av_audio_receiver_engine.cpp | 712 ++++++++++++++++ .../src/av_audio_receiver_engine_provider.cpp | 130 +++ .../av_trans_engine/av_sender/BUILD.gn | 11 + .../include/av_audio_sender_engine.h | 142 ++++ .../include/av_audio_sender_engine_provider.h | 50 ++ .../av_sender/src/av_audio_sender_engine.cpp | 757 ++++++++++++++++++ .../src/av_audio_sender_engine_provider.cpp | 127 +++ .../av_trans_audio_decoder_filter.cpp | 617 ++++++++++++++ .../av_trans_audio_decoder_filter.h | 147 ++++ .../av_trans_audio_encoder_filter.cpp | 605 ++++++++++++++ .../av_trans_audio_encoder_filter.h | 143 ++++ .../av_trans_audio_input_filter.cpp | 358 +++++++++ .../av_trans_audio_input_filter.h} | 40 +- .../av_trans_bus_input_filter.cpp | 494 ++++++++++++ .../av_trans_bus_input_filter.h | 100 +++ .../av_trans_output/daudio_output_filter.cpp | 315 ++++++++ .../av_trans_output/daudio_output_filter.h} | 34 +- .../dsoftbus_output_filter.cpp | 406 ++++++++++ .../av_trans_output/dsoftbus_output_filter.h} | 41 +- .../common/include/av_trans_constants.h | 2 + av_transport/common/include/pipeline_event.h | 6 + av_transport/framework/BUILD.gn | 11 + av_transport/framework/test/demo/BUILD.gn | 84 -- .../framework/test/demo/head_filter.cpp | 243 ------ .../framework/test/demo/mid_filter.cpp | 247 ------ .../framework/test/demo/pipe_demo.cpp | 209 ----- .../framework/test/demo/tail_filter.cpp | 236 ------ bundle.json | 1 - 31 files changed, 5384 insertions(+), 1097 deletions(-) create mode 100644 av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine.h rename av_transport/{framework/test/demo/pipe_demo.h => av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h} (34%) create mode 100644 av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine.cpp create mode 100644 av_transport/av_trans_engine/av_receiver/src/av_audio_receiver_engine_provider.cpp create mode 100644 av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine.h create mode 100644 av_transport/av_trans_engine/av_sender/include/av_audio_sender_engine_provider.h create mode 100644 av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine.cpp create mode 100644 av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine_provider.cpp create mode 100644 av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.cpp create mode 100644 av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.h create mode 100644 av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.cpp create mode 100644 av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.h create mode 100644 av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.cpp rename av_transport/{framework/test/demo/head_filter.h => av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.h} (72%) create mode 100644 av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.cpp create mode 100644 av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.h create mode 100644 av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.cpp rename av_transport/{framework/test/demo/mid_filter.h => av_trans_engine/filters/av_trans_output/daudio_output_filter.h} (75%) create mode 100644 av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.cpp rename av_transport/{framework/test/demo/tail_filter.h => av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.h} (67%) delete mode 100644 av_transport/framework/test/demo/BUILD.gn delete mode 100644 av_transport/framework/test/demo/head_filter.cpp delete mode 100644 av_transport/framework/test/demo/mid_filter.cpp delete mode 100644 av_transport/framework/test/demo/pipe_demo.cpp delete mode 100644 av_transport/framework/test/demo/tail_filter.cpp diff --git a/av_transport/av_trans_engine/av_receiver/BUILD.gn b/av_transport/av_trans_engine/av_receiver/BUILD.gn index 2e2c26c3..09e2050b 100644 --- a/av_transport/av_trans_engine/av_receiver/BUILD.gn +++ b/av_transport/av_trans_engine/av_receiver/BUILD.gn @@ -36,6 +36,12 @@ ohos_shared_library("distributed_av_receiver") { include_dirs = [ "${common_path}/include", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_coder", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_input", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_output", + "${distributed_av_transport_path}/framework", + "${distributed_av_transport_path}/framework/filter/include", + "${distributed_av_transport_path}/framework/pipeline/include", "${engine_path}", "${engine_path}/av_sender/include", "${engine_path}/av_receiver/include", @@ -58,12 +64,15 @@ ohos_shared_library("distributed_av_receiver") { "${common_path}/src/av_trans_meta.cpp", "${common_path}/src/av_trans_utils.cpp", "${common_path}/src/softbus_channel_adapter.cpp", + "${engine_path}/av_receiver/src/av_audio_receiver_engine.cpp", + "${engine_path}/av_receiver/src/av_audio_receiver_engine_provider.cpp", "${engine_path}/av_receiver/src/av_receiver_engine.cpp", "${engine_path}/av_receiver/src/av_receiver_engine_provider.cpp", ] deps = [ "${dh_fwk_sdk_path}:libdhfwk_sdk", + "${distributed_av_transport_path}/framework:distributed_av_pipeline_fwk", "${filters_path}:avtrans_input_filter", "${filters_path}:avtrans_output_filter", ] @@ -94,6 +103,8 @@ ohos_shared_library("distributed_av_receiver") { } external_deps += [ + "av_codec:av_codec_client", + "av_codec:native_media_acodec", "bounds_checking_function:libsec_shared", "cJSON:cjson", "c_utils:utils", 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 00000000..6f8dad5f --- /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/framework/test/demo/pipe_demo.h b/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h similarity index 34% rename from av_transport/framework/test/demo/pipe_demo.h rename to av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h index b424d674..8a1cbcb3 100644 --- a/av_transport/framework/test/demo/pipe_demo.h +++ b/av_transport/av_trans_engine/av_receiver/include/av_audio_receiver_engine_provider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -13,57 +13,38 @@ * limitations under the License. */ -#ifndef OHOS_AV_PIPELINE_DEMO_H -#define OHOS_AV_PIPELINE_DEMO_H +#ifndef OHOS_AV_AUDIO_RECEIVER_ENGINE_PROVIDER_H +#define OHOS_AV_AUDIO_RECEIVER_ENGINE_PROVIDER_H -#include -#include -#include +#include -#include "osal/task/mutex.h" - -#include "filter.h" -#include "head_filter.h" -#include "mid_filter.h" -#include "pipeline_status.h" -#include "pipeline/include/pipeline.h" -#include "tail_filter.h" +#include "i_av_engine_provider.h" +#include "softbus_channel_adapter.h" namespace OHOS { namespace DistributedHardware { -namespace Pipeline { -class PipeDemo { +class AVAudioReceiverEngineProvider : public IAVEngineProvider, public ISoftbusChannelListener { public: - PipeDemo(); - ~PipeDemo(); - - int32_t InitPipe(); - - int32_t Prepare(); - - int32_t Start(); - - int32_t Pause(); - - int32_t Stop(); + AVAudioReceiverEngineProvider(const std::string &ownerName); + ~AVAudioReceiverEngineProvider() override; - int32_t Release(); + std::shared_ptr CreateAVReceiverEngine(const std::string &peerDevId) override; + std::vector> GetAVReceiverEngineList() override; + int32_t RegisterProviderCallback(const std::shared_ptr &callback) override; - Status OnCallback(std::shared_ptr filter, const FilterCallBackCommand cmd, - StreamType outType); - Status LinkAudioDecoderFilter(const std::shared_ptr& preFilter, StreamType type); - Status LinkAudioSinkFilter(const std::shared_ptr& preFilter, StreamType type); + // 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 demoId_ {-1}; - std::shared_ptr playerEventReceiver_ {nullptr}; - std::shared_ptr playerFilterCallback_ {nullptr}; - std::shared_ptr pipeline_ {nullptr}; - std::shared_ptr headFilter_ {nullptr}; - std::shared_ptr midFilter_ {nullptr}; - std::shared_ptr tailFilter_ {nullptr}; + std::string ownerName_; + std::string sessionName_; + std::mutex listMutex_; + std::mutex callbackMutex_; + std::shared_ptr providerCallback_; + std::vector> receiverEngineList_; }; -} // namespace Pipeline } // namespace DistributedHardware } // namespace OHOS -#endif // OHOS_AV_PIPELINE_DEMO_H +#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 00000000..a9af8c9c --- /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 00000000..6c632faf --- /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/BUILD.gn b/av_transport/av_trans_engine/av_sender/BUILD.gn index 37a4483c..6f074dc6 100644 --- a/av_transport/av_trans_engine/av_sender/BUILD.gn +++ b/av_transport/av_trans_engine/av_sender/BUILD.gn @@ -35,6 +35,12 @@ ohos_shared_library("distributed_av_sender") { public_configs = [ ":sender_external_config" ] include_dirs = [ + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_coder", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_input", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_output", + "${distributed_av_transport_path}/framework", + "${distributed_av_transport_path}/framework/filter/include", + "${distributed_av_transport_path}/framework/pipeline/include", "${dh_fwk_utils_path}/include", "${control_center_path}/inner_kits/include", "${control_center_path}/inner_kits/include/ipc", @@ -52,12 +58,15 @@ ohos_shared_library("distributed_av_sender") { "${common_path}/src/av_trans_meta.cpp", "${common_path}/src/av_trans_utils.cpp", "${common_path}/src/softbus_channel_adapter.cpp", + "${engine_path}/av_sender/src/av_audio_sender_engine.cpp", + "${engine_path}/av_sender/src/av_audio_sender_engine_provider.cpp", "${engine_path}/av_sender/src/av_sender_engine.cpp", "${engine_path}/av_sender/src/av_sender_engine_provider.cpp", ] deps = [ "${dh_fwk_sdk_path}:libdhfwk_sdk", + "${distributed_av_transport_path}/framework:distributed_av_pipeline_fwk", "${filters_path}:avtrans_input_filter", "${filters_path}:avtrans_output_filter", ] @@ -88,6 +97,8 @@ ohos_shared_library("distributed_av_sender") { } external_deps += [ + "av_codec:av_codec_client", + "av_codec:native_media_acodec", "bounds_checking_function:libsec_shared", "cJSON:cjson", "c_utils:utils", 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 00000000..4d6321bf --- /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 00000000..8d95527a --- /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 00000000..d05ad827 --- /dev/null +++ b/av_transport/av_trans_engine/av_sender/src/av_audio_sender_engine.cpp @@ -0,0 +1,757 @@ +/* + * 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); + return Status::OK; +} + +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 00000000..5e2751bb --- /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 diff --git a/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.cpp b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.cpp new file mode 100644 index 00000000..d8e9c5de --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.cpp @@ -0,0 +1,617 @@ +/* + * 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_trans_audio_decoder_filter.h" + +#include "av_trans_log.h" +#include "filter_factory.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "AudioDecoderFilter" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +static AutoRegisterFilter g_registerAudioDecoderFilter("builtin.recorder.audiodecoderfilter", + FilterType::FILTERTYPE_ADEC, + [](const std::string& name, const FilterType type) { + return std::make_shared(name, FilterType::FILTERTYPE_ADEC); + }); + +class AudioDecoderFilterCallback : public FilterLinkCallback { +public: + explicit AudioDecoderFilterCallback(std::shared_ptr filter) + : inputFilter_(std::move(filter)) {} + ~AudioDecoderFilterCallback() = default; + + void OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) override + { + if (auto filter = inputFilter_.lock()) { + filter->OnLinkedResult(queue, meta); + } else { + AVTRANS_LOGE("Invalid inputfilter"); + } + } + void OnUnlinkedResult(std::shared_ptr& meta) override + { + if (auto filter = inputFilter_.lock()) { + filter->OnUnLinkedResult(meta); + } else { + AVTRANS_LOGE("Invalid inputfilter"); + } + } + void OnUpdatedResult(std::shared_ptr& meta) override + { + if (auto filter = inputFilter_.lock()) { + filter->OnUpdatedResult(meta); + } else { + AVTRANS_LOGE("Invalid inputfilter"); + } + } + +private: + std::weak_ptr inputFilter_{}; +}; + +class AVBufferAvaliableListener : public Media::IConsumerListener { +public: + explicit AVBufferAvaliableListener(std::weak_ptr decoder) + { + decoder_ = decoder; + } + void OnBufferAvailable() override + { + auto decoder = decoder_.lock(); + TRUE_RETURN(decoder == nullptr, "decoder is nullptr"); + decoder->ProcessInputBuffer(); + } +private: + std::weak_ptr decoder_; +}; + +static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) +{ + (void)codec; + AudioDecoderFilter *decoder = static_cast(userData); + TRUE_RETURN(decoder == nullptr, "decoder is nullptr"); + decoder->OnDecError(errorCode); +} + +static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) +{ + (void)codec; + AudioDecoderFilter *decoder = static_cast(userData); + TRUE_RETURN(decoder == nullptr, "decoder is nullptr"); + decoder->OnDecOutputFormatChanged(format); +} + +static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) +{ + (void)codec; + AudioDecoderFilter *decoder = static_cast(userData); + TRUE_RETURN(decoder == nullptr, "decoder is nullptr"); + decoder->OnDecInputBufferAvailable(index, buffer); +} + +static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) +{ + (void)codec; + AudioDecoderFilter *decoder = static_cast(userData); + TRUE_RETURN(decoder == nullptr, "decoder is nullptr"); + decoder->OnDecOutputBufferAvailable(index, buffer); +} + +AudioDecoderFilter::AudioDecoderFilter(std::string name, FilterType type) : Filter(name, type) +{ +} + +AudioDecoderFilter::~AudioDecoderFilter() +{ + AVTRANS_LOGI("enter"); + if (audioDecoder_ != nullptr) { + AVTRANS_LOGI("release audio decoder"); + ReleaseAudioCodec(); + } +} + +void AudioDecoderFilter::Init(const std::shared_ptr& receiver, + const std::shared_ptr& callback) +{ + receiver_ = receiver; + callback_ = callback; +} + +Status AudioDecoderFilter::DoInitAfterLink() +{ + return Status::OK; +} + +Status AudioDecoderFilter::PrepareInputBufferQueue() +{ + AVTRANS_LOGI("enter"); + if (inputBufferQueue_ == nullptr) { + inputBufferQueue_ = Media::AVBufferQueue::Create(DEFAULT_BUFFER_NUM, Media::MemoryType::VIRTUAL_MEMORY, + INPUT_BUFFERQUEUE_NAME); + } + TRUE_RETURN_V_MSG_E(inputBufferQueue_ == nullptr, Status::ERROR_NULL_POINTER, "create bufferqueue failed"); + inputProducer_ = inputBufferQueue_->GetProducer(); + TRUE_RETURN_V_MSG_E(inputProducer_ == nullptr, Status::ERROR_NULL_POINTER, "GetProducer failed"); + inputConsumer_ = inputBufferQueue_->GetConsumer(); + TRUE_RETURN_V_MSG_E(inputConsumer_ == nullptr, Status::ERROR_NULL_POINTER, "GetConsumer failed"); + + sptr listener(new AVBufferAvaliableListener(shared_from_this())); + inputConsumer_->SetBufferAvailableListener(listener); + return Status::OK; +} + +Status AudioDecoderFilter::DoPrepare() +{ + AVTRANS_LOGI("enter"); + auto ret = CreateAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "Create AudioCodec failed"); + ret = ConfigureAudioCodec(initDecParams_); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "Configure AudioCodec failed"); + + ret = PrepareInputBufferQueue(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "PrepareInputBufferQueue failed"); + + TRUE_RETURN_V_MSG_E(callback_ == nullptr, Status::ERROR_NULL_POINTER, "callback is nullptr"); + callback_->OnCallback(shared_from_this(), FilterCallBackCommand::NEXT_FILTER_NEEDED, + StreamType::STREAMTYPE_RAW_AUDIO); + return Status::OK; +} + +Status AudioDecoderFilter::DoStart() +{ + AVTRANS_LOGI("enter"); + auto ret = StartAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "StartAudioCodec failed"); + return Status::OK; +} + +Status AudioDecoderFilter::DoPause() +{ + return Status::OK; +} + +Status AudioDecoderFilter::DoPauseDragging() +{ + return Status::OK; +} + +Status AudioDecoderFilter::DoResume() +{ + return Status::OK; +} + +Status AudioDecoderFilter::DoResumeDragging() +{ + return Status::OK; +} + +Status AudioDecoderFilter::DoStop() +{ + AVTRANS_LOGI("enter"); + auto ret = StopAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "StopAudioCodec failed"); + return Status::OK; +} + +Status AudioDecoderFilter::DoFlush() +{ + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + auto res = OH_AudioCodec_Flush(audioDecoder_); + TRUE_RETURN_V_MSG_E(res != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "audioDecoder flush failed: %{public}d", res); + return Status::OK; +} + +Status AudioDecoderFilter::DoRelease() +{ + AVTRANS_LOGI("enter"); + auto ret = ReleaseAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "StartAudioCodec failed"); + return Status::OK; +} + +Status AudioDecoderFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) +{ + AVTRANS_LOGD("enter"); + std::shared_ptr buffer = nullptr; + TRUE_RETURN_V_MSG_E(inputConsumer_ == nullptr, Status::ERROR_NULL_POINTER, "inputConsumer is null"); + Media::Status ret = inputConsumer_->AcquireBuffer(buffer); + TRUE_RETURN_V_MSG_E(ret != Media::Status::OK, Status::ERROR_INVALID_OPERATION, "AcquireBuffer failed"); + { + std::lock_guard datalock(mtxData_); + while (inputDataBufferQueue_.size() > AUDIO_DECODER_QUEUE_MAX) { + AVTRANS_LOGE("inputDataBufferQueue_ overflow"); + auto frontBuffer = inputDataBufferQueue_.front(); + inputDataBufferQueue_.pop(); + if (frontBuffer != nullptr) { + inputConsumer_->ReleaseBuffer(frontBuffer); + } + } + inputDataBufferQueue_.push(buffer); + } + decodeCond_.notify_all(); + return Status::OK; +} + +Status AudioDecoderFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, + bool byIdx, uint32_t idx, int64_t renderTime) +{ + return Status::OK; +} + +void AudioDecoderFilter::SetParameter(const std::shared_ptr& meta) +{ + meta_ = meta; +} + +void AudioDecoderFilter::GetParameter(std::shared_ptr& meta) +{ + meta = meta_; +} + +Status AudioDecoderFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(nextFilter == nullptr, Status::ERROR_NULL_POINTER, "input nextFilter is nullptr"); + nextFilter_ = nextFilter; + { + std::lock_guard lock(nextFiltersMutex_); + nextFiltersMap_[outType].push_back(nextFilter); + } + auto filterLinkCallback = std::make_shared(shared_from_this()); + auto ret = nextFilter->OnLinked(outType, meta_, filterLinkCallback); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "Onlinked failed: %{public}d", ret); + return Status::OK; +} + +Status AudioDecoderFilter::UpdateNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + return Status::OK; +} + +Status AudioDecoderFilter::UnLinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + std::lock_guard lock(nextFiltersMutex_); + nextFiltersMap_.clear(); + return Status::OK; +} + +Status AudioDecoderFilter::OnLinked(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(callback == nullptr, Status::ERROR_NULL_POINTER, "input callback is nullptr"); + onLinkedResultCallback_ = callback; + TRUE_RETURN_V_MSG_E(meta == nullptr, Status::ERROR_NULL_POINTER, "input meta is nullptr"); + meta->GetData(Media::Tag::AUDIO_CHANNEL_COUNT, initDecParams_.channel); + meta->GetData(Media::Tag::AUDIO_SAMPLE_RATE, initDecParams_.sampleRate); + meta->GetData(Media::Tag::AUDIO_SAMPLE_FORMAT, initDecParams_.sampleDepth); + meta_ = meta; + return Status::OK; +} + +Status AudioDecoderFilter::OnUpdated(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) +{ + return Status::OK; +} + +Status AudioDecoderFilter::OnUnLinked(StreamType inType, const std::shared_ptr& callback) +{ + onLinkedResultCallback_ = nullptr; + return Status::OK; +} + +void AudioDecoderFilter::OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN(queue == nullptr, "input queue is nullptr"); + outputProducer_ = queue; + TRUE_RETURN(onLinkedResultCallback_ == nullptr, "onLinkedResultCallback_ is nullptr"); + onLinkedResultCallback_->OnLinkedResult(inputProducer_, meta); +} + +void AudioDecoderFilter::OnUnLinkedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +void AudioDecoderFilter::OnUpdatedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +Status AudioDecoderFilter::CreateAudioCodec() +{ + AVTRANS_LOGI("enter"); + audioDecoder_ = OH_AudioCodec_CreateByName((MediaAVCodec::AVCodecCodecName::AUDIO_DECODER_AAC_NAME).data()); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "Create AudioCodec failed"); + OH_AVCodecCallback cb = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable}; + int32_t ret = OH_AudioCodec_RegisterCallback(audioDecoder_, cb, this); + TRUE_RETURN_V_MSG_E(ret != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, "Codec setCallback failed"); + return Status::OK; +} + +Status AudioDecoderFilter::ConfigureAudioCodec(const ADecInitParams& initDecParams) +{ + AVTRANS_LOGI("enter"); + auto ret = SetDecoderFormat(initDecParams); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "input meta is invalid"); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + auto res = OH_AudioCodec_Prepare(audioDecoder_); + TRUE_RETURN_V_MSG_E(res != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "audioDecoder prepare failed: %{public}d", res); + return Status::OK; +} + +Status AudioDecoderFilter::ReleaseAudioCodec() +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + bool isSuccess = true; + if (!isStoped_.load()) { + auto ret = StopAudioCodec(); + if (ret != Status::OK) { + AVTRANS_LOGE("Stop before Release AudioCodec failed"); + isSuccess = false; + } + } + auto res = OH_AudioCodec_Destroy(audioDecoder_); + if (res != AV_ERR_OK) { + AVTRANS_LOGE("Release AudioCodec failed"); + isSuccess = false; + } + audioDecoder_ = nullptr; + return isSuccess ? Status::OK : Status::ERROR_INVALID_OPERATION; +} + +Status AudioDecoderFilter::SetDecoderFormat(const ADecInitParams& initDecParams) +{ + AVTRANS_LOGI("enter"); + auto ret = CheckDecoderFormat(initDecParams); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "input meta is invalid"); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + AVTRANS_LOGI("initDecParams channel: %{public}d, sampleRate: %{public}d, sampleDepth: %{public}d", + initDecParams.channel, initDecParams.sampleRate, initDecParams.sampleDepth); + + OH_AVFormat *format = OH_AVFormat_Create(); + TRUE_RETURN_V_MSG_E(format == nullptr, Status::ERROR_NULL_POINTER, "Create AV format failed."); + OH_AVFormat_SetIntValue(format, MediaAVCodec::MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), + initDecParams.channel); + OH_AVFormat_SetIntValue(format, MediaAVCodec::MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), + initDecParams.sampleRate); + OH_AVFormat_SetIntValue(format, MediaAVCodec::MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), + initDecParams.sampleDepth); + int32_t res = OH_AudioCodec_Configure(audioDecoder_, format); + if (res != AV_ERR_OK) { + AVTRANS_LOGE("configure decoder failed: %{public}d", ret); + OH_AVFormat_Destroy(format); + return Status::ERROR_INVALID_OPERATION; + } + OH_AVFormat_Destroy(format); + return Status::OK; +} + +Status AudioDecoderFilter::CheckDecoderFormat(const ADecInitParams& initDecParams) +{ + if (initDecParams.channel >= CHANNEL_MASK_MIN && initDecParams.channel <= CHANNEL_MASK_MAX && + initDecParams.sampleRate >= SAMPLE_RATE_MIN && initDecParams.sampleRate <= SAMPLE_RATE_MAX && + initDecParams.sampleDepth >= MediaAVCodec::AudioSampleFormat::SAMPLE_U8 && + initDecParams.sampleDepth <= MediaAVCodec::AudioSampleFormat::SAMPLE_F32LE) { + return Status::OK; + } + AVTRANS_LOGE("initDecParams from meta err, channel: %{public}d, sampleRate: %{public}d, sampleDepth: %{public}d", + initDecParams.channel, initDecParams.sampleRate, initDecParams.sampleDepth); + return Status::ERROR_INVALID_PARAMETER; +} + +Status AudioDecoderFilter::StartAudioCodec() +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + auto res = OH_AudioCodec_Start(audioDecoder_); + TRUE_RETURN_V_MSG_E(res != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "audioDecoder start failed: %{public}d", res); + StartInputThread(); + return Status::OK; +} + +Status AudioDecoderFilter::StopAudioCodec() +{ + AVTRANS_LOGI("enter"); + StopInputThread(); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + bool isSuccess = true; + auto ret = OH_AudioCodec_Flush(audioDecoder_); + if (ret != AV_ERR_OK) { + AVTRANS_LOGE("OH_AudioCodec_Flush failed"); + isSuccess = false; + } + TRUE_RETURN_V_MSG_E(OH_AudioCodec_Stop(audioDecoder_) != AV_ERR_OK || !isSuccess, + Status::ERROR_INVALID_OPERATION, "StopAudioCodec failed"); + isStoped_.store(true); + return Status::OK; +} + +void AudioDecoderFilter::StartInputThread() +{ + AVTRANS_LOGI("enter"); + isDecoderRunning_.store(true); + decoderThread_ = std::thread(&AudioDecoderFilter::InputDecodeAudioData, this); + if (pthread_setname_np(decoderThread_.native_handle(), DECODE_THREAD) != AV_ERR_OK) { + AVTRANS_LOGD("Decode thread setname failed"); + } +} + +void AudioDecoderFilter::StopInputThread() +{ + AVTRANS_LOGI("enter"); + isDecoderRunning_.store(false); + if (decoderThread_.joinable()) { + decoderThread_.join(); + } + std::lock_guard dataLock(mtxData_); + std::queue().swap(codecIndexQueue_); + std::queue().swap(codecBufQueue_); + while (!inputDataBufferQueue_.empty()) { + auto audioData = inputDataBufferQueue_.front(); + inputDataBufferQueue_.pop(); + inputConsumer_->ReleaseBuffer(audioData); + } +} + +void AudioDecoderFilter::InputDecodeAudioData() +{ + AVTRANS_LOGD("enter"); + while (isDecoderRunning_.load()) { + std::shared_ptr audioData; + uint32_t index = 0; + OH_AVBuffer *codecMem; + { + std::unique_lock datalock(mtxData_); + decodeCond_.wait_for(datalock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS), + [this]() { + return (!inputDataBufferQueue_.empty() && !codecBufQueue_.empty()); + }); + if (inputDataBufferQueue_.empty() || codecBufQueue_.empty()) { + continue; + } + index = codecIndexQueue_.front(); + codecIndexQueue_.pop(); + codecMem = codecBufQueue_.front(); + codecBufQueue_.pop(); + audioData = inputDataBufferQueue_.front(); + inputDataBufferQueue_.pop(); + } + auto ret = ProcessData(audioData, index, codecMem); + if (ret == Status::ERROR_INVALID_OPERATION) { + AVTRANS_LOGE("Decoder is not runnnig"); + return; + } else if (ret != Status::OK) { + AVTRANS_LOGE("Process data fail. Error type: %d.", ret); + continue; + } + TRUE_RETURN(inputConsumer_ == nullptr, "inputConsumer is null"); + inputConsumer_->ReleaseBuffer(audioData); + } +} + +Status AudioDecoderFilter::ProcessData(std::shared_ptr audioData, const uint32_t index, + OH_AVBuffer *codecMem) +{ + AVTRANS_LOGD("enter"); + TRUE_RETURN_V_MSG_E(audioDecoder_ == nullptr || !isDecoderRunning_.load(), Status::ERROR_INVALID_OPERATION, + "Decoder is not runnnig, isDecoderRunning_: %{public}d", isDecoderRunning_.load()); + TRUE_RETURN_V_MSG_E(codecMem == nullptr || codecMem->buffer_ == nullptr || codecMem->buffer_->memory_ == nullptr || + codecMem->buffer_->meta_ == nullptr, Status::ERROR_NULL_POINTER, "codecMem is invaild"); + TRUE_RETURN_V_MSG_E(audioData == nullptr || audioData->memory_ == nullptr || audioData->meta_ == nullptr, + Status::ERROR_NULL_POINTER, "audioData is invaild"); + + auto memSize = audioData->memory_->GetSize(); + codecMem->buffer_->memory_->SetSize(memSize); + errno_t err = memcpy_s(OH_AVBuffer_GetAddr(codecMem), memSize, audioData->memory_->GetAddr(), memSize); + TRUE_RETURN_V_MSG_E(err != EOK, Status::ERROR_INVALID_OPERATION, + "memcpy_s err: %{public}d, memSize: %{public}d", err, memSize); + int64_t pts = 0; + audioData->meta_->GetData(Media::Tag::USER_FRAME_PTS, pts); + { + std::lock_guard lock(ptsMutex_); + ptsMap_.insert(std::make_pair(index, pts)); + } + codecMem->buffer_->pts_ = pts; + codecMem->buffer_->meta_->SetData(Media::Tag::USER_FRAME_PTS, pts); + codecMem->buffer_->flag_ = MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE; + auto ret = OH_AudioCodec_PushInputBuffer(audioDecoder_, index); + TRUE_RETURN_V_MSG_E(ret != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "OH_AudioCodec_PushInputBuffer err: %{public}d", ret); + return Status::OK; +} + +void AudioDecoderFilter::OnDecError(int32_t errorCode) +{ + AVTRANS_LOGE("Decoder err: %{public}d", errorCode); + isDecoderRunning_.store(false); +} + +void AudioDecoderFilter::OnDecOutputFormatChanged(const OH_AVFormat *format) +{ + TRUE_RETURN(format == nullptr, "input format is nullptr"); + outputFormat_.format_ = format->format_; +} + +void AudioDecoderFilter::OnDecInputBufferAvailable(uint32_t index, OH_AVBuffer *buffer) +{ + AVTRANS_LOGD("enter"); + TRUE_RETURN(buffer == nullptr, "input buffer is nullptr"); + { + std::lock_guard datalock(mtxData_); + while (codecBufQueue_.size() > AUDIO_DECODER_QUEUE_MAX || codecIndexQueue_.size() > AUDIO_DECODER_QUEUE_MAX) { + AVTRANS_LOGE("codecBufQueue_ or codecIndexQueue_ overflow"); + codecIndexQueue_.pop(); + codecBufQueue_.pop(); + } + codecIndexQueue_.push(index); + codecBufQueue_.push(buffer); + } + decodeCond_.notify_all(); +} + +void AudioDecoderFilter::OnDecOutputBufferAvailable(uint32_t index, OH_AVBuffer *buffer) +{ + AVTRANS_LOGD("enter"); + TRUE_RETURN(audioDecoder_ == nullptr || !isDecoderRunning_.load(), + "Decoder is not runnnig, isDecoderRunning_: %{public}d", isDecoderRunning_.load()); + TRUE_RETURN(buffer == nullptr || buffer->buffer_ == nullptr || buffer->buffer_->memory_ == nullptr || + buffer->buffer_->memory_->GetSize() <= 0 || buffer->buffer_->meta_ == nullptr, "audioData is invaild"); + TRUE_RETURN(outputProducer_ == nullptr, "input queue is nullptr"); + + Media::AVBufferConfig config; + config.size = buffer->buffer_->memory_->GetSize(); + config.memoryType = Media::MemoryType::VIRTUAL_MEMORY; + config.memoryFlag = Media::MemoryFlag::MEMORY_READ_WRITE; + std::shared_ptr outBuffer = nullptr; + outputProducer_->RequestBuffer(outBuffer, config, MAX_TIME_OUT_MS); + TRUE_RETURN(outBuffer == nullptr || outBuffer->memory_ == nullptr, "RequestBuffer failed"); + auto meta = outBuffer->meta_; + if (meta == nullptr) { + AVTRANS_LOGE("outBuffer->meta_ is null"); + outputProducer_->PushBuffer(outBuffer, true); + return; + } + int64_t pts = 0; + { + std::lock_guard lock(ptsMutex_); + auto iter = ptsMap_.find(index); + if (iter != ptsMap_.end()) { + pts = iter->second; + ptsMap_.erase(iter); + } + } + outBuffer->pts_ = pts; + meta->SetData(Media::Tag::USER_FRAME_PTS, pts); + outBuffer->memory_->Write(buffer->buffer_->memory_->GetAddr(), buffer->buffer_->memory_->GetSize(), 0); + outputProducer_->PushBuffer(outBuffer, true); + auto ret = OH_AudioCodec_FreeOutputBuffer(audioDecoder_, index); + TRUE_RETURN(ret != AV_ERR_OK, "OH_AudioCodec_FreeOutputBuffer err: %{public}d", ret); +} +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS diff --git a/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.h b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.h new file mode 100644 index 00000000..a937b651 --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.h @@ -0,0 +1,147 @@ +/* + * 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 MEDIA_PIPELINE_DECODER_FILTER_H +#define MEDIA_PIPELINE_DECODER_FILTER_H + +#include +#include +#include +#include +#include + +#include "pipeline_status.h" +#include "filter.h" + +#include "avcodec_audio_decoder.h" +#include "avcodec_codec_name.h" +#include "avcodec_common.h" +#include "avcodec_errors.h" +#include "buffer/avbuffer_queue.h" +#include "buffer/avbuffer_queue_consumer.h" +#include "buffer/avbuffer_queue_producer.h" +#include "media_description.h" +#include "common/native_mfmagic.h" +#include "securec.h" +#include "native_avcodec_audiocodec.h" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +typedef struct { + int32_t codecType; + int32_t channel; + int32_t sampleRate; + MediaAVCodec::AudioSampleFormat sampleDepth; +} ADecInitParams; + +class AudioDecoderFilter : public Filter, public std::enable_shared_from_this { +public: + AudioDecoderFilter(std::string name, FilterType type); + ~AudioDecoderFilter() override; + void Init(const std::shared_ptr &receiver, const std::shared_ptr &callback) override; + Status DoInitAfterLink() override; + Status DoPrepare() override; + Status DoStart() override; + Status DoPause() override; + Status DoPauseDragging() override; + Status DoResume() override; + Status DoResumeDragging() override; + Status DoStop() override; + Status DoFlush() override; + Status DoRelease() override; + + Status DoProcessInputBuffer(int recvArg, bool dropFrame) override; + Status DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTime) override; + void SetParameter(const std::shared_ptr& meta) override; + void GetParameter(std::shared_ptr& meta) override; + + Status LinkNext(const std::shared_ptr& nextFilter, StreamType outType) override; + Status UpdateNext(const std::shared_ptr& nextFilter, StreamType outType) override; + Status UnLinkNext(const std::shared_ptr& nextFilter, StreamType outType) override; + + Status OnLinked(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) override; + Status OnUpdated(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) override; + Status OnUnLinked(StreamType inType, const std::shared_ptr& callback) override; + + void OnLinkedResult(const sptr& queue, std::shared_ptr& meta); + void OnUnLinkedResult(std::shared_ptr& meta); + void OnUpdatedResult(std::shared_ptr& meta); + + Status CreateAudioCodec(); + Status ConfigureAudioCodec(const ADecInitParams &initDecParams); + Status ReleaseAudioCodec(); + + void OnDecError(int32_t errorCode); + void OnDecOutputFormatChanged(const OH_AVFormat *format); + void OnDecInputBufferAvailable(uint32_t index, OH_AVBuffer *buffer); + void OnDecOutputBufferAvailable(uint32_t index, OH_AVBuffer *buffer); + +private: + Status PrepareInputBufferQueue(); + Status SetDecoderFormat(const ADecInitParams &initDecParams); + Status CheckDecoderFormat(const ADecInitParams &initDecParams); + Status StartAudioCodec(); + Status StopAudioCodec(); + void StartInputThread(); + void StopInputThread(); + void InputDecodeAudioData(); + Status ProcessData(std::shared_ptr audioData, const uint32_t index, OH_AVBuffer *codecMem); + +private: + constexpr static int32_t AUDIO_DECODER_QUEUE_MAX = 100; + constexpr static int32_t DECODE_WAIT_MILLISECONDS = 50; + constexpr static int64_t MAX_TIME_OUT_MS = 1; + constexpr static int32_t CHANNEL_MASK_MIN = 1; + constexpr static int32_t CHANNEL_MASK_MAX = 2; + constexpr static int32_t SAMPLE_RATE_MIN = 8000; + constexpr static int32_t SAMPLE_RATE_MAX = 96000; + + std::shared_ptr nextFilter_ {nullptr}; + std::shared_ptr eventReceiver_ {nullptr}; + std::shared_ptr filterCallback_ {nullptr}; + std::shared_ptr filterLinkCallback_ {nullptr}; + std::shared_ptr onLinkedResultCallback_ {nullptr}; + std::mutex nextFiltersMutex_; + sptr inputProducer_ {nullptr}; + sptr outputProducer_ {nullptr}; + sptr inputConsumer_ {nullptr}; + std::shared_ptr inputBufferQueue_ {nullptr}; + static constexpr int32_t DEFAULT_BUFFER_NUM = 8; + const std::string INPUT_BUFFERQUEUE_NAME = "AvTransDecoderBufferQueue"; + static constexpr const char *DECODE_THREAD = "decodeFilterThread"; + + std::mutex mtxData_; + std::mutex mtxCnt_; + std::thread decoderThread_; + std::condition_variable decodeCond_; + std::atomic isDecoderRunning_ = false; + std::atomic isStoped_ = false; + + OH_AVFormat outputFormat_ = {}; + ADecInitParams initDecParams_; + OH_AVCodec *audioDecoder_ = nullptr; + std::queue codecBufQueue_; + std::queue codecIndexQueue_; + std::queue> inputDataBufferQueue_; + std::map ptsMap_; + std::mutex ptsMutex_; +}; +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS +#endif \ No newline at end of file diff --git a/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.cpp b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.cpp new file mode 100644 index 00000000..c7f2afc3 --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.cpp @@ -0,0 +1,605 @@ +/* + * 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_trans_audio_encoder_filter.h" + +#include "av_trans_log.h" +#include "filter_factory.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "AudioEncoderFilter" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +static AutoRegisterFilterg_registerAudioEncoderFilter("builtin.recorder.audioencoderfilter", + FilterType::FILTERTYPE_AENC, + [](const std::string& name, const FilterType type) { + return std::make_shared(name, FilterType::FILTERTYPE_AENC); + }); + +class AudioEncoderFilterCallback : public FilterLinkCallback { +public: + explicit AudioEncoderFilterCallback(std::shared_ptr filter) + : inputFilter_(std::move(filter)) {} + ~AudioEncoderFilterCallback() = default; + + void OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) override + { + if (auto filter = inputFilter_.lock()) { + filter->OnLinkedResult(queue, meta); + } else { + AVTRANS_LOGE("Invalid inputfilter"); + } + } + void OnUnlinkedResult(std::shared_ptr& meta) override + { + if (auto filter = inputFilter_.lock()) { + filter->OnUnLinkedResult(meta); + } else { + AVTRANS_LOGE("Invalid inputfilter"); + } + } + void OnUpdatedResult(std::shared_ptr& meta) override + { + if (auto filter = inputFilter_.lock()) { + filter->OnUpdatedResult(meta); + } else { + AVTRANS_LOGE("Invalid inputfilter"); + } + } +private: + std::weak_ptr inputFilter_ {}; +}; + +class AVBufferAvaliableListener : public Media::IConsumerListener { +public: + explicit AVBufferAvaliableListener(std::weak_ptr encoder) + { + encoder_ = encoder; + } + void OnBufferAvailable() override + { + auto encoder = encoder_.lock(); + TRUE_RETURN(encoder == nullptr, "encoder is nullptr"); + encoder->ProcessInputBuffer(); + } +private: + std::weak_ptr encoder_; +}; + +static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) +{ + (void)codec; + AudioEncoderFilter *encoder = static_cast(userData); + TRUE_RETURN(encoder == nullptr, "encoder is nullptr"); + encoder->OnEncError(errorCode); +} + +static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) +{ + (void)codec; + AudioEncoderFilter *encoder = static_cast(userData); + TRUE_RETURN(encoder == nullptr, "encoder is nullptr"); + encoder->OnEncOutputFormatChanged(format); +} + +static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) +{ + (void)codec; + AudioEncoderFilter *encoder = static_cast(userData); + TRUE_RETURN(encoder == nullptr, "encoder is nullptr"); + encoder->OnEncInputBufferAvailable(index, buffer); +} + +static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) +{ + (void)codec; + AudioEncoderFilter *encoder = static_cast(userData); + TRUE_RETURN(encoder == nullptr, "encoder is nullptr"); + encoder->OnEncOutputBufferAvailable(index, buffer); +} + +AudioEncoderFilter::AudioEncoderFilter(std::string name, FilterType type) : Filter(name, type) +{ +} + +AudioEncoderFilter::~AudioEncoderFilter() +{ + AVTRANS_LOGI("enter"); + if (audioEncoder_ != nullptr) { + AVTRANS_LOGI("release audio encoder"); + ReleaseAudioCodec(); + } +} + +void AudioEncoderFilter::Init(const std::shared_ptr& receiver, + const std::shared_ptr& callback) +{ + receiver_ = receiver; + callback_ = callback; +} + +Status AudioEncoderFilter::DoInitAfterLink() +{ + return Status::OK; +} + +Status AudioEncoderFilter::PrepareInputBufferQueue() +{ + AVTRANS_LOGI("enter"); + if (inputBufferQueue_ == nullptr) { + inputBufferQueue_ = Media::AVBufferQueue::Create(DEFAULT_BUFFER_NUM, Media::MemoryType::VIRTUAL_MEMORY, + INPUT_BUFFERQUEUE_NAME); + } + TRUE_RETURN_V_MSG_E(inputBufferQueue_ == nullptr, Status::ERROR_NULL_POINTER, "create bufferqueue failed"); + inputProducer_ = inputBufferQueue_->GetProducer(); + TRUE_RETURN_V_MSG_E(inputProducer_ == nullptr, Status::ERROR_NULL_POINTER, "GetProducer failed"); + inputConsumer_ = inputBufferQueue_->GetConsumer(); + TRUE_RETURN_V_MSG_E(inputConsumer_ == nullptr, Status::ERROR_NULL_POINTER, "GetConsumer failed"); + + sptr listener(new AVBufferAvaliableListener(shared_from_this())); + inputConsumer_->SetBufferAvailableListener(listener); + return Status::OK; +} + +Status AudioEncoderFilter::DoPrepare() +{ + AVTRANS_LOGI("enter"); + auto ret = PrepareInputBufferQueue(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "PrepareInputBufferQueue failed"); + + ret = CreateAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "Create AudioCodec failed"); + ret = ConfigureAudioCodec(initEncParams_); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "Configure AudioCodec failed"); + + TRUE_RETURN_V_MSG_E(callback_ == nullptr, Status::ERROR_NULL_POINTER, "callback is nullptr"); + callback_->OnCallback(shared_from_this(), FilterCallBackCommand::NEXT_FILTER_NEEDED, + StreamType::STREAMTYPE_RAW_AUDIO); + return Status::OK; +} + +Status AudioEncoderFilter::DoStart() +{ + AVTRANS_LOGI("enter"); + auto ret = StartAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "StartAudioCodec failed"); + return Status::OK; +} + +Status AudioEncoderFilter::DoPause() +{ + return Status::OK; +} + +Status AudioEncoderFilter::DoPauseDragging() +{ + return Status::OK; +} + +Status AudioEncoderFilter::DoResume() +{ + return Status::OK; +} + +Status AudioEncoderFilter::DoResumeDragging() +{ + return Status::OK; +} + +Status AudioEncoderFilter::DoStop() +{ + AVTRANS_LOGI("enter"); + auto ret = StopAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "StopAudioCodec failed"); + return Status::OK; +} + +Status AudioEncoderFilter::DoFlush() +{ + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + auto res = OH_AudioCodec_Flush(audioEncoder_); + TRUE_RETURN_V_MSG_E(res != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "audioEncoder flush failed: %{public}d", res); + return Status::OK; +} + +Status AudioEncoderFilter::DoRelease() +{ + AVTRANS_LOGI("enter"); + auto ret = ReleaseAudioCodec(); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "StartAudioCodec failed"); + return Status::OK; +} + +Status AudioEncoderFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) +{ + AVTRANS_LOGD("enter"); + std::shared_ptr buffer = nullptr; + TRUE_RETURN_V_MSG_E(inputConsumer_ == nullptr, Status::ERROR_NULL_POINTER, "inputConsumer is null"); + Media::Status ret = inputConsumer_->AcquireBuffer(buffer); + TRUE_RETURN_V_MSG_E(ret != Media::Status::OK, Status::ERROR_INVALID_OPERATION, "AcquireBuffer failed"); + { + std::lock_guard datalock(mtxData_); + while (inputDataBufferQueue_.size() > AUDIO_ENCODER_QUEUE_MAX) { + AVTRANS_LOGE("inputDataBufferQueue_ overflow"); + auto frontBuffer = inputDataBufferQueue_.front(); + inputDataBufferQueue_.pop(); + if (frontBuffer != nullptr) { + inputConsumer_->ReleaseBuffer(frontBuffer); + } + } + inputDataBufferQueue_.push(buffer); + } + encodeCond_.notify_all(); + return Status::OK; +} + +Status AudioEncoderFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, + bool byIdx, uint32_t idx, int64_t renderTime) +{ + return Status::OK; +} + +void AudioEncoderFilter::SetParameter(const std::shared_ptr& meta) +{ + meta_ = meta; +} + +void AudioEncoderFilter::GetParameter(std::shared_ptr& meta) +{ + meta = meta_; +} + +Status AudioEncoderFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(nextFilter == nullptr, Status::ERROR_NULL_POINTER, "input nextFilter is nullptr"); + nextFilter_ = nextFilter; + { + std::lock_guard lock(nextFiltersMutex_); + nextFiltersMap_[outType].push_back(nextFilter); + } + auto filterLinkCallback = std::make_shared(shared_from_this()); + auto ret = nextFilter->OnLinked(outType, meta_, filterLinkCallback); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "Onlinked failed: %{public}d", ret); + return Status::OK; +} + +Status AudioEncoderFilter::UpdateNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + return Status::OK; +} + +Status AudioEncoderFilter::UnLinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + std::lock_guard lock(nextFiltersMutex_); + nextFiltersMap_.clear(); + return Status::OK; +} + +Status AudioEncoderFilter::OnLinked(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(callback == nullptr, Status::ERROR_NULL_POINTER, "input callback is nullptr"); + onLinkedResultCallback_ = callback; + TRUE_RETURN_V_MSG_E(meta == nullptr, Status::ERROR_NULL_POINTER, "input meta is nullptr"); + meta->GetData(Media::Tag::AUDIO_CHANNEL_COUNT, initEncParams_.channel); + meta->GetData(Media::Tag::AUDIO_SAMPLE_RATE, initEncParams_.sampleRate); + meta->GetData(Media::Tag::AUDIO_SAMPLE_FORMAT, initEncParams_.sampleDepth); + meta_ = meta; + return Status::OK; +} + +Status AudioEncoderFilter::OnUpdated(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) +{ + return Status::OK; +} + +Status AudioEncoderFilter::OnUnLinked(StreamType inType, const std::shared_ptr& callback) +{ + onLinkedResultCallback_ = nullptr; + return Status::OK; +} + +void AudioEncoderFilter::OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN(queue == nullptr, "input queue is nullptr"); + outputProducer_ = queue; + TRUE_RETURN(onLinkedResultCallback_ == nullptr, "onLinkedResultCallback_ is nullptr"); + onLinkedResultCallback_->OnLinkedResult(inputProducer_, meta); +} + +void AudioEncoderFilter::OnUnLinkedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +void AudioEncoderFilter::OnUpdatedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +Status AudioEncoderFilter::CreateAudioCodec() +{ + AVTRANS_LOGI("enter"); + audioEncoder_ = OH_AudioCodec_CreateByName((MediaAVCodec::AVCodecCodecName::AUDIO_ENCODER_AAC_NAME).data()); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "Create AudioCodec failed"); + OH_AVCodecCallback cb = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable}; + int32_t ret = OH_AudioCodec_RegisterCallback(audioEncoder_, cb, this); + TRUE_RETURN_V_MSG_E(ret != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, "Codec setCallback failed"); + return Status::OK; +} + +Status AudioEncoderFilter::ConfigureAudioCodec(const AEncInitParams &initEncParams) +{ + AVTRANS_LOGI("enter"); + auto ret = SetEncoderFormat(initEncParams); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "input meta is invalid"); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + auto res = OH_AudioCodec_Prepare(audioEncoder_); + TRUE_RETURN_V_MSG_E(res != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "audioEncoder prepare failed: %{public}d", res); + return Status::OK; +} + +Status AudioEncoderFilter::ReleaseAudioCodec() +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + bool isSuccess = true; + if (!isStoped_.load()) { + auto ret = StopAudioCodec(); + if (ret != Status::OK) { + AVTRANS_LOGE("Stop before Release AudioCodec failed"); + isSuccess = false; + } + } + auto res = OH_AudioCodec_Destroy(audioEncoder_); + if (res != AV_ERR_OK) { + AVTRANS_LOGE("Release AudioCodec failed"); + isSuccess = false; + } + audioEncoder_ = nullptr; + return isSuccess ? Status::OK : Status::ERROR_INVALID_OPERATION; +} + +Status AudioEncoderFilter::SetEncoderFormat(const AEncInitParams &initEncParams) +{ + AVTRANS_LOGI("enter"); + auto ret = CheckEncoderFormat(initEncParams); + TRUE_RETURN_V_MSG_E(ret != Status::OK, ret, "input meta is invalid"); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + AVTRANS_LOGI("initEncParams channel: %{public}d, sampleRate: %{public}d, sampleDepth: %{public}d", + initEncParams.channel, initEncParams.sampleRate, initEncParams.sampleDepth); + OH_AVFormat *format = OH_AVFormat_Create(); + OH_AVFormat_SetIntValue(format, MediaAVCodec::MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), + initEncParams.channel); + OH_AVFormat_SetIntValue(format, MediaAVCodec::MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), + initEncParams.sampleRate); + OH_AVFormat_SetIntValue(format, MediaAVCodec::MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), + initEncParams.sampleDepth); + + int32_t res = OH_AudioCodec_Configure(audioEncoder_, format); + if (res != AV_ERR_OK) { + AVTRANS_LOGE("configure encoder failed: %{public}d", ret); + OH_AVFormat_Destroy(format); + return Status::ERROR_INVALID_OPERATION; + } + OH_AVFormat_Destroy(format); + return Status::OK; +} + +Status AudioEncoderFilter::CheckEncoderFormat(const AEncInitParams &initEncParams) +{ + AVTRANS_LOGI("enter"); + if (initEncParams.channel >= CHANNEL_MASK_MIN && initEncParams.channel <= CHANNEL_MASK_MAX && + initEncParams.sampleRate >= SAMPLE_RATE_MIN && initEncParams.sampleRate <= SAMPLE_RATE_MAX && + initEncParams.sampleDepth >= MediaAVCodec::AudioSampleFormat::SAMPLE_U8 && + initEncParams.sampleDepth <= MediaAVCodec::AudioSampleFormat::SAMPLE_F32LE) { + return Status::OK; + } + AVTRANS_LOGE("initEncParams from meta err, channel: %{public}d, sampleRate: %{public}d, sampleDepth: %{public}d", + initEncParams.channel, initEncParams.sampleRate, initEncParams.sampleDepth); + return Status::ERROR_INVALID_PARAMETER; +} + +Status AudioEncoderFilter::StartAudioCodec() +{ + AVTRANS_LOGI("enter"); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + auto res = OH_AudioCodec_Start(audioEncoder_); + TRUE_RETURN_V_MSG_E(res != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "audioEncoder start failed: %{public}d", res); + StartInputThread(); + return Status::OK; +} + +Status AudioEncoderFilter::StopAudioCodec() +{ + AVTRANS_LOGI("enter"); + StopInputThread(); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr, Status::ERROR_NULL_POINTER, "audioCodec is null"); + bool isSuccess = true; + auto ret = OH_AudioCodec_Flush(audioEncoder_); + if (ret != AV_ERR_OK) { + AVTRANS_LOGE("OH_AudioCodec_Flush failed"); + isSuccess = false; + } + TRUE_RETURN_V_MSG_E(OH_AudioCodec_Stop(audioEncoder_)!= AV_ERR_OK || !isSuccess, + Status::ERROR_INVALID_OPERATION, "StopAudioCodec failed"); + isStoped_.store(true); + return Status::OK; +} + +void AudioEncoderFilter::StartInputThread() +{ + AVTRANS_LOGI("enter"); + isEncoderRunning_.store(true); + encoderThread_ = std::thread(&AudioEncoderFilter::InputEncodeAudioData, this); + if (pthread_setname_np(encoderThread_.native_handle(), ENCODE_THREAD) != AV_ERR_OK) { + AVTRANS_LOGD("Encode thread setname failed"); + } +} + +void AudioEncoderFilter::StopInputThread() +{ + AVTRANS_LOGI("enter"); + isEncoderRunning_.store(false); + if (encoderThread_.joinable()) { + encoderThread_.join(); + } + std::lock_guard dataLock(mtxData_); + std::queue().swap(codecIndexQueue_); + std::queue().swap(codecBufQueue_); + while (!inputDataBufferQueue_.empty()) { + auto audioData = inputDataBufferQueue_.front(); + inputDataBufferQueue_.pop(); + inputConsumer_->ReleaseBuffer(audioData); + } +} + +void AudioEncoderFilter::InputEncodeAudioData() +{ + AVTRANS_LOGD("enter"); + while (isEncoderRunning_.load()) { + std::shared_ptr audioData; + uint32_t index = 0; + OH_AVBuffer *codecMem; + { + std::unique_lock datalock(mtxData_); + encodeCond_.wait_for(datalock, std::chrono::milliseconds(ENCODE_WAIT_MILLISECONDS), + [this]() { + return (!inputDataBufferQueue_.empty() && !codecBufQueue_.empty()); + }); + if (inputDataBufferQueue_.empty() || codecBufQueue_.empty()) { + continue; + } + index = codecIndexQueue_.front(); + codecIndexQueue_.pop(); + codecMem = codecBufQueue_.front(); + codecBufQueue_.pop(); + audioData = inputDataBufferQueue_.front(); + inputDataBufferQueue_.pop(); + } + auto ret = ProcessData(audioData, index, codecMem); + if (ret == Status::ERROR_INVALID_OPERATION) { + AVTRANS_LOGE("Encoder is not runnnig"); + return; + } else if (ret != Status::OK) { + AVTRANS_LOGE("Process data fail. Error type: %d.", ret); + continue; + } + TRUE_RETURN(inputConsumer_ == nullptr, "inputConsumer is null"); + inputConsumer_->ReleaseBuffer(audioData); + } +} + +Status AudioEncoderFilter::ProcessData(std::shared_ptr audioData, const uint32_t index, + OH_AVBuffer *codecMem) +{ + AVTRANS_LOGD("enter"); + TRUE_RETURN_V_MSG_E(audioEncoder_ == nullptr || !isEncoderRunning_.load(), Status::ERROR_INVALID_OPERATION, + "Encoder is not runnnig, isEncoderRunning_: %{public}d", isEncoderRunning_.load()); + TRUE_RETURN_V_MSG_E(codecMem == nullptr || codecMem->buffer_ == nullptr || codecMem->buffer_->memory_ == nullptr || + codecMem->buffer_->meta_ == nullptr, Status::ERROR_NULL_POINTER, "codecMem is invaild"); + TRUE_RETURN_V_MSG_E(audioData == nullptr || audioData->memory_ == nullptr || audioData->meta_ == nullptr, + Status::ERROR_NULL_POINTER, "audioData is invaild"); + + auto memSize = audioData->memory_->GetSize(); + codecMem->buffer_->memory_->SetSize(memSize); + errno_t err = memcpy_s(OH_AVBuffer_GetAddr(codecMem), memSize, audioData->memory_->GetAddr(), memSize); + TRUE_RETURN_V_MSG_E(err != EOK, Status::ERROR_INVALID_OPERATION, + "memcpy_s err: %{public}d, memSize: %{public}d", err, memSize); + int64_t pts = 0; + audioData->meta_->GetData(Media::Tag::USER_FRAME_PTS, pts); + codecMem->buffer_->meta_->SetData(Media::Tag::USER_FRAME_PTS, pts); + codecMem->buffer_->flag_ = MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE; + auto ret = OH_AudioCodec_PushInputBuffer(audioEncoder_, index); + TRUE_RETURN_V_MSG_E(ret != AV_ERR_OK, Status::ERROR_INVALID_OPERATION, + "OH_AudioCodec_PushInputBuffer err: %{public}d", ret); + return Status::OK; +} + +void AudioEncoderFilter::OnEncError(int32_t errorCode) +{ + AVTRANS_LOGE("Encoder err: %{public}d", errorCode); + isEncoderRunning_.store(false); +} + +void AudioEncoderFilter::OnEncOutputFormatChanged(const OH_AVFormat *format) +{ + TRUE_RETURN(format == nullptr, "input format is nullptr"); + outputFormat_.format_ = format->format_; +} + +void AudioEncoderFilter::OnEncInputBufferAvailable(uint32_t index, OH_AVBuffer *buffer) +{ + AVTRANS_LOGD("enter"); + TRUE_RETURN(buffer == nullptr, "input buffer is nullptr"); + { + std::lock_guard datalock(mtxData_); + while (codecBufQueue_.size() > AUDIO_ENCODER_QUEUE_MAX || codecIndexQueue_.size() > AUDIO_ENCODER_QUEUE_MAX) { + AVTRANS_LOGE("codecBufQueue_ or codecIndexQueue_ overflow"); + codecIndexQueue_.pop(); + codecBufQueue_.pop(); + } + codecIndexQueue_.push(index); + codecBufQueue_.push(buffer); + } + encodeCond_.notify_all(); +} + +void AudioEncoderFilter::OnEncOutputBufferAvailable(uint32_t index, OH_AVBuffer *buffer) +{ + AVTRANS_LOGD("enter"); + TRUE_RETURN(audioEncoder_ == nullptr || !isEncoderRunning_.load(), + "Encoder is not runnnig, isEncoderRunning_: %{public}d", isEncoderRunning_.load()); + TRUE_RETURN(buffer == nullptr || buffer->buffer_ == nullptr || buffer->buffer_->memory_ == nullptr || + buffer->buffer_->memory_->GetSize() <= 0 || buffer->buffer_->meta_ == nullptr, "audioData is invaild"); + TRUE_RETURN(outputProducer_ == nullptr, "input queue is nullptr"); + + Media::AVBufferConfig config; + config.size = buffer->buffer_->memory_->GetSize(); + config.memoryType = Media::MemoryType::VIRTUAL_MEMORY; + config.memoryFlag = Media::MemoryFlag::MEMORY_READ_WRITE; + std::shared_ptr outBuffer = nullptr; + outputProducer_->RequestBuffer(outBuffer, config, MAX_TIME_OUT_MS); + TRUE_RETURN(outBuffer == nullptr || outBuffer->memory_ == nullptr, "RequestBuffer failed"); + auto meta = outBuffer->meta_; + if (meta == nullptr) { + AVTRANS_LOGE("outBuffer->meta_ is null"); + outputProducer_->PushBuffer(outBuffer, true); + return; + } + int64_t pts = 0; + buffer->buffer_->meta_->GetData(Media::Tag::USER_FRAME_PTS, pts); + outBuffer->pts_ = pts; + meta->SetData(Media::Tag::USER_FRAME_PTS, pts); + meta->SetData(Media::Tag::AUDIO_OBJECT_NUMBER, index); + outBuffer->memory_->Write(buffer->buffer_->memory_->GetAddr(), buffer->buffer_->memory_->GetSize(), 0); + outputProducer_->PushBuffer(outBuffer, true); + auto ret = OH_AudioCodec_FreeOutputBuffer(audioEncoder_, index); + TRUE_RETURN(ret != AV_ERR_OK, "OH_AudioCodec_FreeOutputBuffer err: %{public}d", ret); +} +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS diff --git a/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.h b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.h new file mode 100644 index 00000000..5a2312f5 --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.h @@ -0,0 +1,143 @@ +/* + * 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 MEDIA_PIPELINE_ENCODER_FILTER_H +#define MEDIA_PIPELINE_ENCODER_FILTER_H + +#include +#include +#include +#include +#include + +#include "pipeline_status.h" +#include "filter.h" + +#include "avcodec_audio_encoder.h" +#include "avcodec_codec_name.h" +#include "avcodec_common.h" +#include "avcodec_errors.h" +#include "buffer/avbuffer_queue.h" +#include "buffer/avbuffer_queue_consumer.h" +#include "buffer/avbuffer_queue_producer.h" +#include "media_description.h" +#include "common/native_mfmagic.h" +#include "securec.h" +#include "native_avcodec_audiocodec.h" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +typedef struct { + int32_t codecType; + int32_t channel; + int32_t sampleRate; + MediaAVCodec::AudioSampleFormat sampleDepth; +} AEncInitParams; + +class AudioEncoderFilter : public Filter, public std::enable_shared_from_this { +public: + AudioEncoderFilter(std::string name, FilterType type); + ~AudioEncoderFilter() override; + void Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) override; + Status DoInitAfterLink() override; + Status DoPrepare() override; + Status DoStart() override; + Status DoPause() override; + Status DoPauseDragging() override; + Status DoResume() override; + Status DoResumeDragging() override; + Status DoStop() override; + Status DoFlush() override; + Status DoRelease() override; + + Status DoProcessInputBuffer(int recvArg, bool dropFrame) override; + Status DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTime) override; + void SetParameter(const std::shared_ptr& meta) override; + void GetParameter(std::shared_ptr& meta) override; + + Status LinkNext(const std::shared_ptr& nextFilter, StreamType outType) override; + Status UpdateNext(const std::shared_ptr& nextFilter, StreamType outType) override; + Status UnLinkNext(const std::shared_ptr& nextFilter, StreamType outType) override; + + Status OnLinked(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) override; + Status OnUpdated(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) override; + Status OnUnLinked(StreamType inType, const std::shared_ptr& callback) override; + + void OnLinkedResult(const sptr& queue, std::shared_ptr& meta); + void OnUnLinkedResult(std::shared_ptr& meta); + void OnUpdatedResult(std::shared_ptr& meta); + + Status CreateAudioCodec(); + Status ConfigureAudioCodec(const AEncInitParams &initEncParams); + Status ReleaseAudioCodec(); + + void OnEncError(int32_t errorCode); + void OnEncOutputFormatChanged(const OH_AVFormat *format); + void OnEncInputBufferAvailable(uint32_t index, OH_AVBuffer *buffer); + void OnEncOutputBufferAvailable(uint32_t index, OH_AVBuffer *buffer); + +private: + Status PrepareInputBufferQueue(); + Status SetEncoderFormat(const AEncInitParams &initEncParams); + Status CheckEncoderFormat(const AEncInitParams &initEncParams); + Status StartAudioCodec(); + Status StopAudioCodec(); + void StartInputThread(); + void StopInputThread(); + void InputEncodeAudioData(); + Status ProcessData(std::shared_ptr audioData, const uint32_t index, OH_AVBuffer *codecMem); +private: + constexpr static int32_t AUDIO_ENCODER_QUEUE_MAX = 100; + constexpr static int32_t ENCODE_WAIT_MILLISECONDS = 50; + constexpr static int64_t MAX_TIME_OUT_MS = 1; + constexpr static int32_t CHANNEL_MASK_MIN = 1; + constexpr static int32_t CHANNEL_MASK_MAX = 2; + constexpr static int32_t SAMPLE_RATE_MIN = 8000; + constexpr static int32_t SAMPLE_RATE_MAX = 96000; + + std::shared_ptr nextFilter_ {nullptr}; + std::shared_ptr eventReceiver_ {nullptr}; + std::shared_ptr filterCallback_ {nullptr}; + std::shared_ptr filterLinkCallback_ {nullptr}; + std::shared_ptr onLinkedResultCallback_ {nullptr}; + std::mutex nextFiltersMutex_; + sptr inputProducer_ {nullptr}; + sptr outputProducer_ {nullptr}; + sptr inputConsumer_ {nullptr}; + std::shared_ptr inputBufferQueue_ {nullptr}; + static constexpr int32_t DEFAULT_BUFFER_NUM = 8; + const std::string INPUT_BUFFERQUEUE_NAME = "AvTransEncoderBufferQueue"; + static constexpr const char* ENCODE_THREAD = "encodeFilterThread"; + + std::mutex mtxData_; + std::thread encoderThread_; + std::condition_variable encodeCond_; + std::atomic isEncoderRunning_ = false; + std::atomic isStoped_ = false; + + OH_AVFormat outputFormat_ = {}; + AEncInitParams initEncParams_; + OH_AVCodec *audioEncoder_ = nullptr; + std::queue codecBufQueue_; + std::queue codecIndexQueue_; + std::queue> inputDataBufferQueue_; +}; +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS +#endif diff --git a/av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.cpp b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.cpp new file mode 100644 index 00000000..c3bbdc85 --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.cpp @@ -0,0 +1,358 @@ +/* + * 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_trans_audio_input_filter.h" + +#include +#include + +#include "av_trans_log.h" +#include "filter_factory.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "AudioInputFilter" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +namespace { +constexpr int32_t DEFAULT_BUFFER_NUM = 8; +constexpr int32_t MAX_TIME_OUT_MS = 1; +constexpr int64_t MS_ONE_S = 1000; +constexpr int64_t NS_ONE_S = 1000000; +const std::string INPUT_BUFFER_QUEUE_NAME = "AVTransAudioInputBufferQueue"; + +int64_t GetCurrentTime() +{ + struct timespec time = { 0, 0 }; + clock_gettime(CLOCK_MONOTONIC, &time); + return time.tv_sec * MS_ONE_S + time.tv_nsec / NS_ONE_S; +} +} + +static AutoRegisterFilter g_registerAudioEncoderFilter("builtin.avtrans.audio.input", + FilterType::FILTERTYPE_SOURCE, + [](const std::string& name, const FilterType type) { + return std::make_shared(name, FilterType::FILTERTYPE_SOURCE); + }); + +class HeadFilterLinkCallback : public FilterLinkCallback { +public: + explicit HeadFilterLinkCallback(std::shared_ptr filter) + : filter_(std::move(filter)) {} + ~HeadFilterLinkCallback() = default; + + void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override + { + if (auto filter = filter_.lock()) { + filter->OnLinkedResult(queue, meta); + } else { + AVTRANS_LOGI("invalid headFilter"); + } + } + + void OnUnlinkedResult(std::shared_ptr &meta) override + { + if (auto filter = filter_.lock()) { + filter->OnUnlinkedResult(meta); + } else { + AVTRANS_LOGI("invalid headFilter"); + } + } + + void OnUpdatedResult(std::shared_ptr &meta) override + { + if (auto filter = filter_.lock()) { + filter->OnUpdatedResult(meta); + } else { + AVTRANS_LOGI("invalid headFilter"); + } + } + +private: + std::weak_ptr filter_ {}; +}; + +class InputBufAvailableListener : public Media::IConsumerListener { +public: + explicit InputBufAvailableListener(const std::weak_ptr inputFilter) + { + inputFilter_ = inputFilter; + } + + void OnBufferAvailable() override + { + auto inputFilter = inputFilter_.lock(); + if (inputFilter != nullptr) { + inputFilter->ProcessInputBuffer(); + } + } + +private: + std::weak_ptr inputFilter_; +}; + +AVTransAudioInputFilter::AVTransAudioInputFilter(std::string name, FilterType type, bool isAsyncMode) + : Filter(name, type) +{ +} + +AVTransAudioInputFilter::~AVTransAudioInputFilter() +{ + nextFiltersMap_.clear(); +} + +void AVTransAudioInputFilter::Init(const std::shared_ptr& receiver, + const std::shared_ptr& callback) +{ + AVTRANS_LOGI("AVTransAudioInputFilter::Init"); + receiver_ = receiver; + callback_ = callback; + AVTRANS_LOGI("AVTransAudioInputFilter::Init Done"); +} + +Status AVTransAudioInputFilter::DoInitAfterLink() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoInitAfterLink"); + return Status::OK; +} + +void AVTransAudioInputFilter::PrepareInputBuffer() +{ + AVTRANS_LOGI("Preparing input buffer."); + int32_t inputBufNum = DEFAULT_BUFFER_NUM; + Media::MemoryType memoryType = Media::MemoryType::VIRTUAL_MEMORY; + if (inputBufQue_ == nullptr) { + inputBufQue_ = Media::AVBufferQueue::Create(inputBufNum, memoryType, INPUT_BUFFER_QUEUE_NAME); + } + if (inputBufQue_ == nullptr) { + AVTRANS_LOGE("Create buffer queue failed."); + return; + } + inputBufQueProducer_ = inputBufQue_->GetProducer(); + TRUE_RETURN((inputBufQueProducer_ == nullptr), "Get producer failed"); + + inputBufQueConsumer_ = inputBufQue_->GetConsumer(); + TRUE_RETURN((inputBufQueConsumer_ == nullptr), "Get consumer failed"); + + sptr listener(new InputBufAvailableListener(shared_from_this())); + inputBufQueConsumer_->SetBufferAvailableListener(listener); +} + +Status AVTransAudioInputFilter::DoPrepare() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoPrepare"); + PrepareInputBuffer(); + frameNumber_.store(0); + if (callback_ == nullptr) { + AVTRANS_LOGE("filter callback is null"); + return Status::ERROR_NULL_POINTER; + } + TRUE_RETURN_V_MSG_E(meta_ == nullptr, Status::ERROR_NULL_POINTER, "meta_ is nullptr"); + int32_t mimeType = 0; + auto filterType = StreamType::STREAMTYPE_ENCODED_AUDIO; + meta_->GetData(Media::Tag::MIME_TYPE, mimeType); + if (static_cast(mimeType) == AudioCodecType::AUDIO_CODEC_AAC) { + filterType = StreamType::STREAMTYPE_RAW_AUDIO; + } + AVTRANS_LOGD("mimeType: %{public}d.", mimeType); + callback_->OnCallback(shared_from_this(), FilterCallBackCommand::NEXT_FILTER_NEEDED, filterType); + AVTRANS_LOGI("AVTransAudioInputFilter::DoPrepare done"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoStart() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoStart"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoPause() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoPause"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoPauseDragging() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoPauseDragging"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoResume() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoResume"); + frameNumber_.store(0); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoResumeDragging() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoResumeDragging"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoStop() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoStop"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoFlush() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoFlush"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoRelease() +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoRelease"); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) +{ + AVTRANS_LOGD("DoProcessInputBuffer"); + (void)recvArg; + (void)dropFrame; + std::shared_ptr filledBuffer = nullptr; + if (curState_ != FilterState::RUNNING) { + AVTRANS_LOGE("Current status ia not running."); + return Status::ERROR_WRONG_STATE; + } + Media::Status ret = inputBufQueConsumer_->AcquireBuffer(filledBuffer); + if (ret != Media::Status::OK) { + AVTRANS_LOGE("Acquire buffer err."); + return Status::ERROR_INVALID_OPERATION; + } + ProcessAndSendBuffer(filledBuffer); + inputBufQueConsumer_->ReleaseBuffer(filledBuffer); + return Status::OK; +} + +Status AVTransAudioInputFilter::ProcessAndSendBuffer(const std::shared_ptr buffer) +{ + if (buffer == nullptr || buffer->memory_ == nullptr) { + AVTRANS_LOGE("AVBuffer is null"); + return Status::ERROR_NULL_POINTER; + } + + TRUE_RETURN_V_MSG_E((outputBufQueProducer_ == nullptr), Status::ERROR_NULL_POINTER, "Producer is null"); + Media::AVBufferConfig config(buffer->GetConfig()); + AVTRANS_LOGD("outPut config, size: %{public}u, capacity: %{public}u, memtype: %{public}hhu", + config.size, config.capacity, config.memoryType); + std::shared_ptr outBuffer = nullptr; + outputBufQueProducer_->RequestBuffer(outBuffer, config, MAX_TIME_OUT_MS); + TRUE_RETURN_V_MSG_E((outBuffer == nullptr || outBuffer->memory_ == nullptr), Status::ERROR_NULL_POINTER, + "OutBuffer or memory is null"); + auto meta = outBuffer->meta_; + if (meta == nullptr) { + AVTRANS_LOGE("Meta of AVBuffer is null"); + outputBufQueProducer_->PushBuffer(outBuffer, true); + return Status::ERROR_NULL_POINTER; + } + ++frameNumber_; + outBuffer->pts_ = GetCurrentTime(); + meta->SetData(Media::Tag::USER_FRAME_PTS, outBuffer->pts_); + outBuffer->memory_->Write(buffer->memory_->GetAddr(), buffer->memory_->GetSize(), 0); + outputBufQueProducer_->PushBuffer(outBuffer, true); + return Status::OK; +} + +Status AVTransAudioInputFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, + uint32_t idx, int64_t renderTimee) +{ + AVTRANS_LOGI("AVTransAudioInputFilter::DoProcessOutputBuffer"); + return Status::OK; +} + +void AVTransAudioInputFilter::SetParameter(const std::shared_ptr& meta) +{ + meta_ = meta; +} + +void AVTransAudioInputFilter::GetParameter(std::shared_ptr& meta) +{ + meta = meta_; +} + +Status AVTransAudioInputFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + AVTRANS_LOGI("cur: AVTransAudioInputFilter, link next filter.."); + nextFilter_ = nextFilter; + nextFiltersMap_[outType].push_back(nextFilter_); + auto filterLinkCallback = std::make_shared(shared_from_this()); + auto ret = nextFilter->OnLinked(outType, meta_, filterLinkCallback); + if (ret != Status::OK) { + AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); + return ret; + } + return Status::OK; +} + +Status AVTransAudioInputFilter::UpdateNext(const std::shared_ptr&, StreamType) +{ + return Status::OK; +} + +Status AVTransAudioInputFilter::UnLinkNext(const std::shared_ptr&, StreamType) +{ + AVTRANS_LOGI("cur: AVTransAudioInputFilter, unlink next filter.."); + return Status::OK; +} + +Status AVTransAudioInputFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, + const std::shared_ptr &callback) +{ + AVTRANS_LOGI("cur: AVTransAudioInputFilter, OnLinked"); + return Status::OK; +}; + +Status AVTransAudioInputFilter::OnUpdated(StreamType, const std::shared_ptr&, + const std::shared_ptr&) +{ + return Status::OK; +} + +Status AVTransAudioInputFilter::OnUnLinked(StreamType, const std::shared_ptr&) +{ + AVTRANS_LOGI("cur: AVTransAudioInputFilter, OnUnLinked."); + return Status::OK; +} + +void AVTransAudioInputFilter::OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) +{ + AVTRANS_LOGI("cur: AVTransAudioInputFilter, OnLinkedResult"); + outputBufQueProducer_ = queue; +} + +void AVTransAudioInputFilter::OnUnlinkedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +void AVTransAudioInputFilter::OnUpdatedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +sptr AVTransAudioInputFilter::GetInputBufQueProducer() +{ + return inputBufQueProducer_; +} +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS diff --git a/av_transport/framework/test/demo/head_filter.h b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.h similarity index 72% rename from av_transport/framework/test/demo/head_filter.h rename to av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.h index cf68cdb6..47bfdc07 100644 --- a/av_transport/framework/test/demo/head_filter.h +++ b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -13,12 +13,16 @@ * limitations under the License. */ -#ifndef OHOS_AV_PIPELINE_HEAD_FILTER_DEMO_H -#define OHOS_AV_PIPELINE_HEAD_FILTER_DEMO_H +#ifndef OHOS_AV_TRANS_AUDIO_INPUT_FILTER_H +#define OHOS_AV_TRANS_AUDIO_INPUT_FILTER_H -#include -#include #include +#include +#include + +#include "buffer/avbuffer_queue.h" +#include "buffer/avbuffer_queue_consumer.h" +#include "buffer/avbuffer_queue_producer.h" #include "pipeline_status.h" #include "filter.h" @@ -26,11 +30,11 @@ namespace OHOS { namespace DistributedHardware { namespace Pipeline { -// 分两步:第一先保证fiter连接正常,第二,filter保证数据流转正常 -class HeadFilter : public Filter, public std::enable_shared_from_this { +class AVTransAudioInputFilter : public Filter, public std::enable_shared_from_this { public: - HeadFilter(std::string name, FilterType type, bool asyncMode = false); - virtual ~HeadFilter(); + AVTransAudioInputFilter(std::string name, FilterType type, bool asyncMode = false); + virtual ~AVTransAudioInputFilter(); + void Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) override; Status DoInitAfterLink() override; Status DoPrepare() override; @@ -58,20 +62,28 @@ public: const std::shared_ptr& callback) override; Status OnUnLinked(StreamType inType, const std::shared_ptr& callback) override; - // PipeLinked 后处理 void OnLinkedResult(const sptr& queue, std::shared_ptr& meta); void OnUnlinkedResult(std::shared_ptr& meta); void OnUpdatedResult(std::shared_ptr& meta); + sptr GetInputBufQueProducer(); + +private: + void PrepareInputBuffer(); + Status ProcessAndSendBuffer(const std::shared_ptr buffer); private: std::shared_ptr configureParam_ {nullptr}; std::shared_ptr nextFilter_ {nullptr}; - - std::shared_ptr eventReceiver_ {nullptr}; - std::shared_ptr filterCallback_ {nullptr}; std::shared_ptr onLinkedResultCallback_ {nullptr}; + + std::shared_ptr inputBufQue_ {nullptr}; + sptr inputBufQueProducer_ {nullptr}; + sptr inputBufQueConsumer_ {nullptr}; + sptr outputBufQueProducer_ {nullptr}; + + std::atomic frameNumber_ {0}; }; } // namespace Pipeline } // namespace DistributedHardware } // namespace OHOS -#endif // OHOS_AV_PIPELINE_HEAD_FILTER_DEMO_H +#endif diff --git a/av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.cpp b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.cpp new file mode 100644 index 00000000..4856f0fc --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.cpp @@ -0,0 +1,494 @@ +/* + * 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_trans_bus_input_filter.h" + +#include +#include + +#include "av_trans_constants.h" +#include "av_trans_errno.h" +#include "av_trans_log.h" +#include "av_trans_types.h" +#include "filter_factory.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "AVTransBusInputFilter" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +namespace { +constexpr int32_t DEFAULT_BUFFER_NUM = 8; +constexpr int32_t MAX_TIME_OUT_MS = 1; +const std::string INPUT_BUFFER_QUEUE_NAME = "AVTransBusInputBufferQueue"; +const std::string META_TIMESTAMP = "meta_timestamp"; + +bool IsUInt32(const cJSON *jsonObj, const std::string &key) +{ + cJSON *keyObj = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str()); + return (keyObj != nullptr) && cJSON_IsNumber(keyObj) && + static_cast(keyObj->valueint) <= UINT32_MAX; +} +} + +static AutoRegisterFilter g_registerAudioFilter("builtin.avtrans.softbus.input", + FilterType::AUDIO_DATA_SOURCE, + [](const std::string& name, const FilterType type) { + return std::make_shared(name, FilterType::AUDIO_DATA_SOURCE); + }); + +class BusInputFilterLinkCB : public FilterLinkCallback { +public: + explicit BusInputFilterLinkCB(std::shared_ptr filter) + : filter_(std::move(filter)) {} + ~BusInputFilterLinkCB() = default; + + void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override + { + if (auto filter = filter_.lock()) { + filter->OnLinkedResult(queue, meta); + } else { + AVTRANS_LOGI("invalid headFilter"); + } + } + + void OnUnlinkedResult(std::shared_ptr &meta) override + { + if (auto filter = filter_.lock()) { + filter->OnUnlinkedResult(meta); + } else { + AVTRANS_LOGI("invalid headFilter"); + } + } + + void OnUpdatedResult(std::shared_ptr &meta) override + { + if (auto filter = filter_.lock()) { + filter->OnUpdatedResult(meta); + } else { + AVTRANS_LOGI("invalid headFilter"); + } + } + +private: + std::weak_ptr filter_ {}; +}; + +class InputBufAvailableListener : public Media::IConsumerListener { +public: + explicit InputBufAvailableListener(const std::weak_ptr inputFilter) + { + inputFilter_ = inputFilter; + } + + void OnBufferAvailable() override + { + auto inputFilter = inputFilter_.lock(); + if (inputFilter != nullptr) { + inputFilter->ProcessInputBuffer(); + } + } + +private: + std::weak_ptr inputFilter_; +}; + +AVTransBusInputFilter::AVTransBusInputFilter(std::string name, FilterType type, bool isAsyncMode) + : Filter(name, type) +{ +} + +AVTransBusInputFilter::~AVTransBusInputFilter() +{ + nextFiltersMap_.clear(); +} + +void AVTransBusInputFilter::Init(const std::shared_ptr& receiver, + const std::shared_ptr& callback) +{ + AVTRANS_LOGI("AVTransBusInputFilter::Init"); + receiver_ = receiver; + callback_ = callback; + AVTRANS_LOGI("AVTransBusInputFilter::Init Done"); +} + +Status AVTransBusInputFilter::DoInitAfterLink() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoInitAfterLink"); + return Status::OK; +} + +void AVTransBusInputFilter::PrepareInputBuffer() +{ + AVTRANS_LOGI("Preparing input buffer."); + int32_t inputBufNum = DEFAULT_BUFFER_NUM; + Media::MemoryType memoryType = Media::MemoryType::VIRTUAL_MEMORY; + if (inputBufQue_ == nullptr) { + inputBufQue_ = Media::AVBufferQueue::Create(inputBufNum, memoryType, INPUT_BUFFER_QUEUE_NAME); + } + if (inputBufQue_ == nullptr) { + AVTRANS_LOGE("Create buffer queue failed."); + return; + } + inputBufQueProducer_ = inputBufQue_->GetProducer(); + TRUE_RETURN((inputBufQueProducer_ == nullptr), "Get producer failed"); + + inputBufQueConsumer_ = inputBufQue_->GetConsumer(); + TRUE_RETURN((inputBufQueConsumer_ == nullptr), "Get consumer failed"); + + sptr listener(new InputBufAvailableListener(shared_from_this())); + inputBufQueConsumer_->SetBufferAvailableListener(listener); +} + +Status AVTransBusInputFilter::DoPrepare() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoPrepare"); + std::string str; + if (meta_ != nullptr) { + meta_->GetData(Media::Tag::MEDIA_DESCRIPTION, str); + } + cJSON *jParam = cJSON_Parse(str.c_str()); + TRUE_RETURN_V_MSG_E(jParam == nullptr, Status::ERROR_NULL_POINTER, "Failed to parse json."); + cJSON *ownerName = cJSON_GetObjectItem(jParam, KEY_ONWER_NAME.c_str()); + if (ownerName == nullptr || !cJSON_IsString(ownerName)) { + AVTRANS_LOGE("The key ownerName is null."); + cJSON_Delete(jParam); + return Status::ERROR_NULL_POINTER; + } + ownerName_ = std::string(ownerName->valuestring); + cJSON *peerDevId = cJSON_GetObjectItem(jParam, KEY_PEERDEVID_NAME.c_str()); + if (peerDevId == nullptr || !cJSON_IsString(peerDevId)) { + AVTRANS_LOGE("The key peerDevId is null."); + cJSON_Delete(jParam); + return Status::ERROR_NULL_POINTER; + } + peerDevId_ = std::string(peerDevId->valuestring); + AVTRANS_LOGD("ownerName = %{public}s, peerDevId = %{public}s.", ownerName_.c_str(), peerDevId_.c_str()); + sessionName_ = ownerName_ + "_" + RECEIVER_DATA_SESSION_NAME_SUFFIX; + SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, peerDevId_, this); + int32_t ret = SoftbusChannelAdapter::GetInstance().CreateChannelServer(TransName2PkgName(ownerName_), sessionName_); + TRUE_RETURN_V_MSG_E(ret != DH_AVT_SUCCESS, Status::ERROR_INVALID_OPERATION, + "Create Session Server failed ret: %{public}d.", ret); + TRUE_RETURN_V_MSG_E(callback_ == nullptr || meta_ == nullptr, Status::ERROR_NULL_POINTER, "callback is null"); + int32_t mimeType = 0; + auto filterType = StreamType::STREAMTYPE_DECODED_AUDIO; + meta_->GetData(Media::Tag::MIME_TYPE, mimeType); + if (static_cast(mimeType) == AudioCodecType::AUDIO_CODEC_AAC) { + filterType = StreamType::STREAMTYPE_RAW_AUDIO; + } + callback_->OnCallback(shared_from_this(), FilterCallBackCommand::NEXT_FILTER_NEEDED, filterType); + return Status::OK; +} + +Status AVTransBusInputFilter::DoStart() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoStart"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoPause() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoPause"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoPauseDragging() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoPauseDragging"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoResume() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoResume"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoResumeDragging() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoResumeDragging"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoStop() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoStop"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoFlush() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoFlush"); + return Status::OK; +} + +Status AVTransBusInputFilter::DoRelease() +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoRelease"); + SoftbusChannelAdapter::GetInstance().RemoveChannelServer(TransName2PkgName(ownerName_), sessionName_); + SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(sessionName_, peerDevId_); + return Status::OK; +} + +Status AVTransBusInputFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoProcessInputBuffer"); + (void)recvArg; + (void)dropFrame; + std::shared_ptr filledBuffer = nullptr; + if (curState_ != FilterState::RUNNING) { + AVTRANS_LOGE("Current status ia not running."); + return Status::ERROR_WRONG_STATE; + } + Media::Status ret = inputBufQueConsumer_->AcquireBuffer(filledBuffer); + if (ret != Media::Status::OK) { + AVTRANS_LOGE("Acquire buffer err."); + return Status::ERROR_INVALID_OPERATION; + } + ProcessAndSendBuffer(filledBuffer); + inputBufQueConsumer_->ReleaseBuffer(filledBuffer); + return Status::OK; +} + +Status AVTransBusInputFilter::ProcessAndSendBuffer(const std::shared_ptr buffer) +{ + if (buffer == nullptr || buffer->memory_ == nullptr) { + AVTRANS_LOGE("AVBuffer is null"); + return Status::ERROR_NULL_POINTER; + } + + TRUE_RETURN_V_MSG_E((outputBufQueProducer_ == nullptr), Status::ERROR_NULL_POINTER, "Producer is null"); + Media::AVBufferConfig config(buffer->GetConfig()); + AVTRANS_LOGD("outPut config, size: %{public}u, capacity: %{public}u, memtype: %{public}hhu", + config.size, config.capacity, config.memoryType); + std::shared_ptr outBuffer = nullptr; + outputBufQueProducer_->RequestBuffer(outBuffer, config, MAX_TIME_OUT_MS); + TRUE_RETURN_V_MSG_E((outBuffer == nullptr || outBuffer->memory_ == nullptr), Status::ERROR_NULL_POINTER, + "OutBuffer or memory is null"); + auto meta = outBuffer->meta_; + if (meta == nullptr) { + AVTRANS_LOGE("Meta of AVBuffer is null"); + outputBufQueProducer_->PushBuffer(outBuffer, true); + return Status::ERROR_NULL_POINTER; + } + meta->SetData(Media::Tag::USER_FRAME_PTS, outBuffer->pts_); + outBuffer->memory_->Write(buffer->memory_->GetAddr(), buffer->memory_->GetSize(), 0); + outputBufQueProducer_->PushBuffer(outBuffer, true); + return Status::OK; +} + +Status AVTransBusInputFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, + uint32_t idx, int64_t renderTimee) +{ + AVTRANS_LOGI("AVTransBusInputFilter::DoProcessOutputBuffer"); + return Status::OK; +} + +void AVTransBusInputFilter::SetParameter(const std::shared_ptr& meta) +{ + meta_ = meta; +} + +void AVTransBusInputFilter::GetParameter(std::shared_ptr& meta) +{ + meta = meta_; +} + +Status AVTransBusInputFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + AVTRANS_LOGI("cur: AVTransBusInputFilter, link next filter.."); + nextFilter_ = nextFilter; + nextFiltersMap_[outType].push_back(nextFilter_); + auto filterLinkCallback = std::make_shared(shared_from_this()); + auto ret = nextFilter->OnLinked(outType, meta_, filterLinkCallback); + if (ret != Status::OK) { + AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); + return ret; + } + return Status::OK; +} + +Status AVTransBusInputFilter::UpdateNext(const std::shared_ptr&, StreamType) +{ + return Status::OK; +} + +Status AVTransBusInputFilter::UnLinkNext(const std::shared_ptr&, StreamType) +{ + AVTRANS_LOGI("cur: AVTransBusInputFilter, unlink next filter.."); + return Status::OK; +} + +Status AVTransBusInputFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, + const std::shared_ptr &callback) +{ + AVTRANS_LOGI("cur: AVTransBusInputFilter, OnLinked"); + return Status::OK; +}; + +Status AVTransBusInputFilter::OnUpdated(StreamType, const std::shared_ptr&, + const std::shared_ptr&) +{ + return Status::OK; +} + +Status AVTransBusInputFilter::OnUnLinked(StreamType, const std::shared_ptr&) +{ + AVTRANS_LOGI("cur: AVTransBusInputFilter, OnUnLinked."); + return Status::OK; +} + +void AVTransBusInputFilter::OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) +{ + AVTRANS_LOGI("cur: AVTransBusInputFilter, OnLinkedResult"); + outputBufQueProducer_ = queue; +} + +void AVTransBusInputFilter::OnUnlinkedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +void AVTransBusInputFilter::OnUpdatedResult(std::shared_ptr& meta) +{ + (void)meta; +} + +void AVTransBusInputFilter::OnChannelEvent(const AVTransEvent &event) +{ + AVTRANS_LOGI("OnChannelEvent enter, event type: %{public}d", event.type); + switch (event.type) { + case OHOS::DistributedHardware::EventType::EVENT_CHANNEL_OPENED: { + AVTRANS_LOGD("channel opened."); + TRUE_RETURN(receiver_ == nullptr, "receiver_ is nullptr"); + Event channelEvent; + channelEvent.type = EventType::EVENT_AUDIO_PROGRESS; + channelEvent.param = event; + receiver_->OnEvent(channelEvent); + break; + } + case OHOS::DistributedHardware::EventType::EVENT_CHANNEL_OPEN_FAIL: { + AVTRANS_LOGE("channel open failed."); + break; + } + case OHOS::DistributedHardware::EventType::EVENT_CHANNEL_CLOSED: { + AVTRANS_LOGI("channel closed."); + break; + } + default: + AVTRANS_LOGE("Unsupported event type."); + } +} + +void AVTransBusInputFilter::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + if (ext == nullptr) { + AVTRANS_LOGE("ext is nullptr."); + return; + } + std::string message(reinterpret_cast(ext->buf), ext->bufLen); + AVTRANS_LOGD("Receive message : %{public}s", message.c_str()); + + cJSON *resMsg = cJSON_Parse(message.c_str()); + if (resMsg == nullptr) { + AVTRANS_LOGE("The resMsg parse failed."); + return; + } + if (!IsUInt32(resMsg, AVT_DATA_META_TYPE)) { + AVTRANS_LOGE("Invalid data type."); + cJSON_Delete(resMsg); + return; + } + StreamDataEnqueue(data, resMsg); + cJSON_Delete(resMsg); +} + +bool AVTransBusInputFilter::UnmarshalAudioMeta(const std::string& jsonStr, int64_t& pts) +{ + cJSON *metaJson = cJSON_Parse(jsonStr.c_str()); + if (metaJson == nullptr) { + return false; + } + cJSON *ptsObj = cJSON_GetObjectItemCaseSensitive(metaJson, META_TIMESTAMP.c_str()); + if (ptsObj == nullptr || !cJSON_IsNumber(ptsObj)) { + cJSON_Delete(metaJson); + return false; + } + pts = static_cast(ptsObj->valueint); + cJSON_Delete(metaJson); + return true; +} + +void AVTransBusInputFilter::StreamDataEnqueue(const StreamData *data, const cJSON *extMsg) +{ + TRUE_RETURN((outputBufQueProducer_ == nullptr || data == nullptr || extMsg == nullptr), "Producer is null"); + Media::AVBufferConfig config; + config.size = data->bufLen; + config.memoryType = Media::MemoryType::VIRTUAL_MEMORY; + config.memoryFlag = Media::MemoryFlag::MEMORY_READ_WRITE; + AVTRANS_LOGD("outPut config, size: %{public}u, capacity: %{public}u, memtype: %{public}hhu", + config.size, config.capacity, config.memoryType); + std::shared_ptr outBuffer = nullptr; + outputBufQueProducer_->RequestBuffer(outBuffer, config, MAX_TIME_OUT_MS); + TRUE_RETURN((outBuffer == nullptr || outBuffer->memory_ == nullptr), + "OutBuffer or memory is null"); + auto meta = outBuffer->meta_; + if (meta == nullptr) { + AVTRANS_LOGE("Meta of AVBuffer is null"); + outputBufQueProducer_->PushBuffer(outBuffer, false); + return; + } + cJSON *paramItem = cJSON_GetObjectItem(extMsg, AVT_DATA_PARAM.c_str()); + if (paramItem == nullptr || !cJSON_IsString(paramItem)) { + AVTRANS_LOGE("paramItem is invalid."); + return; + } + int64_t ptsValue = 0; + UnmarshalAudioMeta(std::string(paramItem->valuestring), ptsValue); + outBuffer->pts_ = ptsValue; + meta->SetData(Media::Tag::USER_FRAME_PTS, ptsValue); + outBuffer->memory_->Write(reinterpret_cast(data->buf), data->bufLen, 0); + outputBufQueProducer_->PushBuffer(outBuffer, true); +} + +sptr AVTransBusInputFilter::GetInputBufQueProducer() +{ + return inputBufQueProducer_; +} + +std::string AVTransBusInputFilter::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 Pipeline +} // namespace DistributedHardware +} // namespace OHOS diff --git a/av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.h b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.h new file mode 100644 index 00000000..bfeb26a4 --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.h @@ -0,0 +1,100 @@ +/* + * 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_TRANS_AUDIO_INPUT_FILTER_H +#define OHOS_AV_TRANS_AUDIO_INPUT_FILTER_H + +#include +#include +#include + +#include "buffer/avbuffer_queue.h" +#include "buffer/avbuffer_queue_consumer.h" +#include "buffer/avbuffer_queue_producer.h" +#include "cJSON.h" + +#include "pipeline_status.h" +#include "filter.h" +#include "softbus_channel_adapter.h" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +class AVTransBusInputFilter : public Filter, + public ISoftbusChannelListener, + public std::enable_shared_from_this { +public: + AVTransBusInputFilter(std::string name, FilterType type, bool asyncMode = false); + virtual ~AVTransBusInputFilter(); + + void Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) override; + Status DoInitAfterLink() override; + Status DoPrepare() override; + Status DoStart() override; + Status DoPause() override; + Status DoPauseDragging() override; + Status DoResume() override; + Status DoResumeDragging() override; + Status DoStop() override; + Status DoFlush() override; + Status DoRelease() override; + + Status DoProcessInputBuffer(int recvArg, bool dropFrame) override; + Status DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTime) override; + void SetParameter(const std::shared_ptr& meta) override; + void GetParameter(std::shared_ptr& meta) override; + + Status LinkNext(const std::shared_ptr& nextFilter, StreamType outType) override; + Status UpdateNext(const std::shared_ptr& nextFilter, StreamType outType) override; + Status UnLinkNext(const std::shared_ptr& nextFilter, StreamType outType) override; + + Status OnLinked(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) override; + Status OnUpdated(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) override; + Status OnUnLinked(StreamType inType, const std::shared_ptr& callback) override; + + void OnLinkedResult(const sptr& queue, std::shared_ptr& meta); + void OnUnlinkedResult(std::shared_ptr& meta); + void OnUpdatedResult(std::shared_ptr& meta); + sptr GetInputBufQueProducer(); + + void OnChannelEvent(const AVTransEvent &event) override; + void OnStreamReceived(const StreamData *data, const StreamData *ext) override; + +private: + void PrepareInputBuffer(); + Status ProcessAndSendBuffer(const std::shared_ptr buffer); + void StreamDataEnqueue(const StreamData *data, const cJSON *extMsg); + std::string TransName2PkgName(const std::string &ownerName); + bool UnmarshalAudioMeta(const std::string& jsonStr, int64_t& pts); + +private: + std::shared_ptr configureParam_ {nullptr}; + std::shared_ptr nextFilter_ {nullptr}; + std::shared_ptr onLinkedResultCallback_ {nullptr}; + + std::shared_ptr inputBufQue_ {nullptr}; + sptr inputBufQueProducer_ {nullptr}; + sptr inputBufQueConsumer_ {nullptr}; + sptr outputBufQueProducer_ {nullptr}; + std::string ownerName_; + std::string sessionName_; + std::string peerDevId_; +}; +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS +#endif diff --git a/av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.cpp b/av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.cpp new file mode 100644 index 00000000..a09c1c2f --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.cpp @@ -0,0 +1,315 @@ +/* + * 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 "daudio_output_filter.h" + +#include + +#include "av_trans_log.h" +#include "filter_factory.h" + +#include "cJSON.h" +#include "av_trans_errno.h" +#include "av_trans_log.h" +#include "av_trans_constants.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DAudioOutputFilter" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +constexpr int32_t DEFAULT_BUFFER_NUM = 8; +const std::string OUTPUT_BUFFER_QUEUE_NAME = "AVTransAudioOutputBufferQueue"; + +static AutoRegisterFilter g_registerAudioEncoderFilter("builtin.daudio.output", + FilterType::FILTERTYPE_SSINK, + [](const std::string& name, const FilterType type) { + return std::make_shared(name, FilterType::FILTERTYPE_SSINK); + }); + +class DAudioOutputFilterLinkCallback : public FilterLinkCallback { +public: + explicit DAudioOutputFilterLinkCallback(std::shared_ptr filter) + : outFilter_(std::move(filter)) {} + ~DAudioOutputFilterLinkCallback() = default; + + void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override + { + if (auto filter = outFilter_.lock()) { + filter->OnLinkedResult(queue, meta); + } else { + AVTRANS_LOGI("invalid dAudioOutputFilter"); + } + } + + void OnUnlinkedResult(std::shared_ptr &meta) override + { + if (auto filter = outFilter_.lock()) { + filter->OnUnlinkedResult(meta); + } else { + AVTRANS_LOGI("invalid dAudioOutputFilter"); + } + } + + void OnUpdatedResult(std::shared_ptr &meta) override + { + if (auto filter = outFilter_.lock()) { + filter->OnUpdatedResult(meta); + } else { + AVTRANS_LOGI("invalid dAudioOutputFilter"); + } + } + +private: + std::weak_ptr outFilter_ {}; +}; + +class AVBufferAvailableListener : public Media::IConsumerListener { +public: + explicit AVBufferAvailableListener(std::weak_ptr outputFilter) + { + outputFilter_ = outputFilter; + } + + void OnBufferAvailable() override + { + auto outputFilter = outputFilter_.lock(); + if (outputFilter != nullptr) { + outputFilter->ProcessInputBuffer(); + } + } + +private: + std::weak_ptr outputFilter_; +}; + +DAudioOutputFilter::DAudioOutputFilter(std::string name, FilterType type) + : Filter(name, type) +{ +} + +DAudioOutputFilter::~DAudioOutputFilter() +{ + nextFiltersMap_.clear(); +} + +void DAudioOutputFilter::Init(const std::shared_ptr& receiver, + const std::shared_ptr& callback) +{ + eventReceiver_ = receiver; + filterCallback_ = callback; +} + +Status DAudioOutputFilter::DoInitAfterLink() +{ + return Status::OK; +} + +void DAudioOutputFilter::PrepareInputBuffer() +{ + AVTRANS_LOGI("Preparing input buffer."); + int32_t outputBufNum = DEFAULT_BUFFER_NUM; + Media::MemoryType memoryType = Media::MemoryType::VIRTUAL_MEMORY; + if (outputBufQue_ == nullptr) { + outputBufQue_ = Media::AVBufferQueue::Create(outputBufNum, memoryType, OUTPUT_BUFFER_QUEUE_NAME); + } + if (outputBufQue_ == nullptr) { + AVTRANS_LOGE("Create buffer queue failed."); + return; + } + inputBufQueProducer_ = outputBufQue_->GetProducer(); + TRUE_RETURN((inputBufQueProducer_ == nullptr), "Get producer failed"); + + inputBufQueConsumer_ = outputBufQue_->GetConsumer(); + TRUE_RETURN((inputBufQueConsumer_ == nullptr), "Get consumer failed"); + + sptr listener(new AVBufferAvailableListener(shared_from_this())); + inputBufQueConsumer_->SetBufferAvailableListener(listener); +} + +Status DAudioOutputFilter::DoPrepare() +{ + PrepareInputBuffer(); + int32_t inputBufNum = DEFAULT_BUFFER_NUM; + sptr producer = nullptr; + Media::MemoryType memoryType = Media::MemoryType::UNKNOWN_MEMORY; + if (outputBufQue_ == nullptr) { + outputBufQue_ = Media::AVBufferQueue::Create(inputBufNum, memoryType, OUTPUT_BUFFER_QUEUE_NAME); + } + if (outputBufQue_ == nullptr) { + AVTRANS_LOGE("Create buffer queue failed."); + return Status::ERROR_NULL_POINTER; + } + producer = outputBufQue_->GetProducer(); + TRUE_RETURN_V_MSG_E((producer == nullptr), Status::ERROR_NULL_POINTER, "Get producer failed"); + sptr consumer = outputBufQue_->GetConsumer(); + sptr listener(new AVBufferAvailableListener(shared_from_this())); + consumer->SetBufferAvailableListener(listener); + + std::shared_ptr meta = std::make_shared(); + if (onLinkedResultCallback_ != nullptr) { + onLinkedResultCallback_->OnLinkedResult(producer, meta); + } + return Status::OK; +} + +Status DAudioOutputFilter::DoStart() +{ + AVTRANS_LOGI("Do Start"); + return Status::OK; +} + +Status DAudioOutputFilter::DoPause() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoPauseDragging() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoResume() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoResumeDragging() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoStop() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoFlush() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoRelease() +{ + return Status::OK; +} + +Status DAudioOutputFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) +{ + (void)recvArg; + (void)dropFrame; + std::shared_ptr filledBuffer = nullptr; + Media::Status ret = inputBufQueConsumer_->AcquireBuffer(filledBuffer); + if (ret != Media::Status::OK) { + AVTRANS_LOGE("Acquire buffer err: %{public}d.", ret); + return Status::ERROR_INVALID_OPERATION; + } + ProcessAndSendBuffer(filledBuffer); + inputBufQueConsumer_->ReleaseBuffer(filledBuffer); + return Status::OK; +} + +Status DAudioOutputFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, + uint32_t idx, int64_t renderTimee) +{ + return Status::OK; +} + +Status DAudioOutputFilter::ProcessAndSendBuffer(const std::shared_ptr buffer) +{ + if (buffer == nullptr) { + AVTRANS_LOGE("ProcessAndSendBuffer buffer is nullptr"); + return Status::ERROR_INVALID_OPERATION; + } + TRUE_RETURN_V_MSG_E(eventReceiver_ == nullptr, Status::ERROR_NULL_POINTER, "receiver_ is nullptr"); + Event event; + event.type = EventType::EVENT_BUFFER_PROGRESS; + event.param = buffer; + eventReceiver_->OnEvent(event); + return Status::OK; +} + +void DAudioOutputFilter::SetParameter(const std::shared_ptr& meta) +{ + meta_ = meta; +} + +void DAudioOutputFilter::GetParameter(std::shared_ptr& meta) +{ + meta = meta_; +} + +Status DAudioOutputFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + nextFilter_ = nextFilter; + nextFiltersMap_[outType].push_back(nextFilter_); + auto filterLinkCallback = std::make_shared(shared_from_this()); + auto ret = nextFilter->OnLinked(outType, meta_, filterLinkCallback); + if (ret != Status::OK) { + AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); + return ret; + } + return Status::OK; +} + +Status DAudioOutputFilter::UpdateNext(const std::shared_ptr&, StreamType) +{ + return Status::OK; +} + +Status DAudioOutputFilter::UnLinkNext(const std::shared_ptr&, StreamType) +{ + AVTRANS_LOGI("cur: DAudioOutputFilter, unlink next filter.."); + return Status::OK; +} + +Status DAudioOutputFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, + const std::shared_ptr &callback) +{ + AVTRANS_LOGI("cur: DAudioOutputFilter, OnLinked"); + onLinkedResultCallback_ = callback; + SetParameter(meta); + return Status::OK; +}; + +Status DAudioOutputFilter::OnUpdated(StreamType, const std::shared_ptr&, + const std::shared_ptr&) +{ + return Status::OK; +} + +Status DAudioOutputFilter::OnUnLinked(StreamType, const std::shared_ptr&) +{ + AVTRANS_LOGI("cur: DAudioOutputFilter, OnUnLinked."); + return Status::OK; +} + +void DAudioOutputFilter::OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) +{ + outputBufQueProducer_ = queue; +} + +void DAudioOutputFilter::OnUnlinkedResult(std::shared_ptr& meta) +{ +} + +void DAudioOutputFilter::OnUpdatedResult(std::shared_ptr& meta) +{ +} +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS diff --git a/av_transport/framework/test/demo/mid_filter.h b/av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.h similarity index 75% rename from av_transport/framework/test/demo/mid_filter.h rename to av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.h index 51fa583b..eaa67ec4 100644 --- a/av_transport/framework/test/demo/mid_filter.h +++ b/av_transport/av_trans_engine/filters/av_trans_output/daudio_output_filter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -13,24 +13,29 @@ * limitations under the License. */ -#ifndef OHOS_AV_PIPELINE_MID_FILTER_DEMO_H -#define OHOS_AV_PIPELINE_MID_FILTER_DEMO_H +#ifndef OHOS_DAUDIO_OUTPUT_FILTER_H +#define OHOS_DAUDIO_OUTPUT_FILTER_H #include #include #include +#include "buffer/avbuffer_queue.h" +#include "buffer/avbuffer_queue_consumer.h" +#include "buffer/avbuffer_queue_producer.h" +#include "softbus_channel_adapter.h" + #include "pipeline_status.h" #include "filter.h" namespace OHOS { namespace DistributedHardware { namespace Pipeline { -// 分两步:第一先保证fiter连接正常,第二,filter保证数据流转正常 -class MidFilter : public Filter, public std::enable_shared_from_this { +class DAudioOutputFilter : public Filter, public std::enable_shared_from_this { public: - MidFilter(std::string name, FilterType type, bool asyncMode = false); - virtual ~MidFilter(); + DAudioOutputFilter(std::string name, FilterType type); + virtual ~DAudioOutputFilter(); + void Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) override; Status DoInitAfterLink() override; Status DoPrepare() override; @@ -58,20 +63,27 @@ public: const std::shared_ptr& callback) override; Status OnUnLinked(StreamType inType, const std::shared_ptr& callback) override; - // PipeLinked 后处理 void OnLinkedResult(const sptr& queue, std::shared_ptr& meta); void OnUnlinkedResult(std::shared_ptr& meta); void OnUpdatedResult(std::shared_ptr& meta); private: - std::shared_ptr configureParam_ {nullptr}; - std::shared_ptr nextFilter_ {nullptr}; + void PrepareInputBuffer(); + Status ProcessAndSendBuffer(const std::shared_ptr buffer); +private: + std::shared_ptr meta_ {nullptr}; + std::shared_ptr nextFilter_ {nullptr}; std::shared_ptr eventReceiver_ {nullptr}; std::shared_ptr filterCallback_ {nullptr}; std::shared_ptr onLinkedResultCallback_ {nullptr}; + + std::shared_ptr outputBufQue_ {nullptr}; + sptr inputBufQueProducer_ {nullptr}; + sptr inputBufQueConsumer_ {nullptr}; + sptr outputBufQueProducer_ {nullptr}; }; } // namespace Pipeline } // namespace DistributedHardware } // namespace OHOS -#endif // OHOS_AV_PIPELINE_MID_FILTER_DEMO_H +#endif diff --git a/av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.cpp b/av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.cpp new file mode 100644 index 00000000..5487d33a --- /dev/null +++ b/av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.cpp @@ -0,0 +1,406 @@ +/* + * 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 "dsoftbus_output_filter.h" + +#include + +#include "av_trans_log.h" +#include "filter_factory.h" +#include "cJSON.h" +#include "av_trans_errno.h" +#include "av_trans_log.h" +#include "av_trans_constants.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DSoftbusOutputFilter" + +namespace OHOS { +namespace DistributedHardware { +namespace Pipeline { +constexpr int32_t DEFAULT_BUFFER_NUM = 8; +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"; +const std::string META_EXT_TIMESTAMP = "meta_ext_timestamp"; +const std::string META_EXT_FRAME_NUMBER = "meta_ext_frame_number"; +const std::string INPUT_BUFFER_QUEUE_NAME = "buffer_queue_input"; +const std::string SENDER_DATA_SESSION_NAME_SUFFIX = "sender.avtrans.data"; +const std::string RECEIVER_DATA_SESSION_NAME_SUFFIX = "receiver.avtrans.data"; +const std::string OUTPUT_BUFFER_QUEUE_NAME = "AVTransAudioOutputBufferQueue"; + +static AutoRegisterFilter g_registerAudioEncoderFilter("builtin.avtransport.avoutput", + FilterType::FILTERTYPE_ASINK, + [](const std::string& name, const FilterType type) { + return std::make_shared(name, FilterType::FILTERTYPE_ASINK); + }); + +class DAudioSoftbusFilterLinkCallback : public FilterLinkCallback { +public: + explicit DAudioSoftbusFilterLinkCallback(std::shared_ptr filter) + : outFilter_(std::move(filter)) {} + ~DAudioSoftbusFilterLinkCallback() = default; + + void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override + { + if (auto filter = outFilter_.lock()) { + filter->OnLinkedResult(queue, meta); + } else { + AVTRANS_LOGI("invalid DSoftbusOutputFilter"); + } + } + + void OnUnlinkedResult(std::shared_ptr &meta) override + { + if (auto filter = outFilter_.lock()) { + filter->OnUnlinkedResult(meta); + } else { + AVTRANS_LOGI("invalid DSoftbusOutputFilter"); + } + } + + void OnUpdatedResult(std::shared_ptr &meta) override + { + if (auto filter = outFilter_.lock()) { + filter->OnUpdatedResult(meta); + } else { + AVTRANS_LOGI("invalid daudioSoftbusOutputFilter"); + } + } + +private: + std::weak_ptr outFilter_ {}; +}; + +class AVBufferAvailableListener : public Media::IConsumerListener { +public: + explicit AVBufferAvailableListener(std::weak_ptr dsoftbusFilter) + { + dsoftbusFilter_ = dsoftbusFilter; + } + + void OnBufferAvailable() override + { + auto dsoftbusFilter = dsoftbusFilter_.lock(); + if (dsoftbusFilter != nullptr) { + dsoftbusFilter->ProcessInputBuffer(); + } + } + +private: + std::weak_ptr dsoftbusFilter_; +}; + +DSoftbusOutputFilter::DSoftbusOutputFilter(std::string name, FilterType type) + : Filter(name, type) +{ +} + +DSoftbusOutputFilter::~DSoftbusOutputFilter() +{ + nextFiltersMap_.clear(); +} + +void DSoftbusOutputFilter::Init(const std::shared_ptr& receiver, + const std::shared_ptr& callback) +{ + eventReceiver_ = receiver; + filterCallback_ = callback; +} + +Status DSoftbusOutputFilter::DoInitAfterLink() +{ + return Status::OK; +} + +void DSoftbusOutputFilter::PrepareInputBuffer() +{ + AVTRANS_LOGI("Preparing input buffer."); + int32_t outputBufNum = DEFAULT_BUFFER_NUM; + Media::MemoryType memoryType = Media::MemoryType::VIRTUAL_MEMORY; + if (outputBufQue_ == nullptr) { + outputBufQue_ = Media::AVBufferQueue::Create(outputBufNum, memoryType, OUTPUT_BUFFER_QUEUE_NAME); + } + if (outputBufQue_ == nullptr) { + AVTRANS_LOGE("Create buffer queue failed."); + return; + } + inputBufQueProducer_ = outputBufQue_->GetProducer(); + TRUE_RETURN((inputBufQueProducer_ == nullptr), "Get producer failed"); + + inputBufQueConsumer_ = outputBufQue_->GetConsumer(); + TRUE_RETURN((inputBufQueConsumer_ == nullptr), "Get consumer failed"); + + sptr listener(new AVBufferAvailableListener(shared_from_this())); + inputBufQueConsumer_->SetBufferAvailableListener(listener); +} + +Status DSoftbusOutputFilter::DoPrepare() +{ + std::string str; + if (meta_ != nullptr) { + meta_->GetData(Media::Tag::MEDIA_DESCRIPTION, str); + } + cJSON *jParam = cJSON_Parse(str.c_str()); + if (jParam == nullptr) { + AVTRANS_LOGE("Failed to parse json."); + return Status::ERROR_NULL_POINTER; + } + cJSON *ownerName = cJSON_GetObjectItem(jParam, KEY_ONWER_NAME.c_str()); + if (ownerName == nullptr || !cJSON_IsString(ownerName)) { + AVTRANS_LOGE("The key ownerName is null."); + cJSON_Delete(jParam); + return Status::ERROR_NULL_POINTER; + } + AVTRANS_LOGI("RegData type is : %{public}s.", ownerName->valuestring); + ownerName_ = std::string(ownerName->valuestring); + + cJSON *peerDevId = cJSON_GetObjectItem(jParam, KEY_PEERDEVID_NAME.c_str()); + if (peerDevId == nullptr || !cJSON_IsString(peerDevId)) { + AVTRANS_LOGE("The key peerDevId is null."); + cJSON_Delete(jParam); + return Status::ERROR_NULL_POINTER; + } + AVTRANS_LOGI("RegData type is : %{public}s.", peerDevId->valuestring); + peerDevId_ = std::string(peerDevId->valuestring); + sessionName_ = ownerName_ + "_" + SENDER_DATA_SESSION_NAME_SUFFIX; + PrepareInputBuffer(); + AVTRANS_LOGI("OnLinkedResult."); + + std::shared_ptr meta = std::make_shared(); + if (onLinkedResultCallback_ != nullptr) { + onLinkedResultCallback_->OnLinkedResult(inputBufQueProducer_, meta); + } + return Status::OK; +} + +Status DSoftbusOutputFilter::DoStart() +{ + std::string peerSessName = ownerName_ + "_" + RECEIVER_DATA_SESSION_NAME_SUFFIX; + SoftbusChannelAdapter::GetInstance().RegisterChannelListener(sessionName_, peerDevId_, this); + int32_t ret = SoftbusChannelAdapter::GetInstance().OpenSoftbusChannel(sessionName_, peerSessName, peerDevId_); + if ((ret != DH_AVT_SUCCESS) && (ret != ERR_DH_AVT_SESSION_HAS_OPENED)) { + AVTRANS_LOGE("Open softbus channel failed ret: %{public}d.", ret); + return Status::ERROR_INVALID_OPERATION; + } + return Status::OK; +} + +Status DSoftbusOutputFilter::DoPause() +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::DoPauseDragging() +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::DoResume() +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::DoResumeDragging() +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::DoStop() +{ + int32_t ret = SoftbusChannelAdapter::GetInstance().CloseSoftbusChannel(sessionName_, peerDevId_); + if (ret != DH_AVT_SUCCESS) { + AVTRANS_LOGE("Close softbus channel failed ret: %{public}d.", ret); + return Status::ERROR_NULL_POINTER; + } + return Status::OK; +} + +Status DSoftbusOutputFilter::DoFlush() +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::DoRelease() +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) +{ + (void)recvArg; + (void)dropFrame; + std::shared_ptr filledBuffer = nullptr; + Media::Status ret = inputBufQueConsumer_->AcquireBuffer(filledBuffer); + if (ret != Media::Status::OK) { + AVTRANS_LOGE("Acquire buffer err: %{public}d.", ret); + return Status::ERROR_INVALID_OPERATION; + } + ProcessAndSendBuffer(filledBuffer); + inputBufQueConsumer_->ReleaseBuffer(filledBuffer); + return Status::OK; +} + +Status DSoftbusOutputFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, + uint32_t idx, int64_t renderTimee) +{ + return Status::OK; +} + +std::string DSoftbusOutputFilter::MarshalAudioMeta(BufferDataType dataType, int64_t pts, uint32_t frameNumber) +{ + cJSON *metaJson = cJSON_CreateObject(); + if (metaJson == nullptr) { + return ""; + } + cJSON_AddNumberToObject(metaJson, META_DATA_TYPE.c_str(), static_cast(dataType)); + cJSON_AddNumberToObject(metaJson, META_TIMESTAMP.c_str(), pts); + cJSON_AddNumberToObject(metaJson, META_FRAME_NUMBER.c_str(), frameNumber); + char *data = cJSON_PrintUnformatted(metaJson); + if (data == nullptr) { + cJSON_Delete(metaJson); + return ""; + } + std::string jsonstr(data); + cJSON_free(data); + cJSON_Delete(metaJson); + return jsonstr; +} + +Status DSoftbusOutputFilter::ProcessAndSendBuffer(const std::shared_ptr buffer) +{ + if (buffer == nullptr || buffer->memory_ == nullptr || buffer->meta_ == nullptr || meta_ == nullptr) { + AVTRANS_LOGE("AVBuffer is nullptr"); + return Status::ERROR_NULL_POINTER; + } + auto bufferData = buffer->memory_; + int64_t pts = 0; + uint32_t frameNumber = 0; + buffer->meta_->GetData(Media::Tag::USER_FRAME_PTS, pts); + buffer->meta_->GetData(Media::Tag::AUDIO_OBJECT_NUMBER, frameNumber); + BufferDataType dataType; + meta_->GetData(Media::Tag::MEDIA_STREAM_TYPE, dataType); + auto dataParam = MarshalAudioMeta(dataType, pts, frameNumber); + cJSON *jsonObj = cJSON_CreateObject(); + if (jsonObj == nullptr) { + return Status::ERROR_NULL_POINTER; + } + cJSON_AddNumberToObject(jsonObj, AVT_DATA_META_TYPE.c_str(), static_cast(dataType)); + cJSON_AddStringToObject(jsonObj, AVT_DATA_PARAM.c_str(), dataParam.c_str()); + auto str = cJSON_PrintUnformatted(jsonObj); + if (str == nullptr) { + cJSON_Delete(jsonObj); + return Status::ERROR_NULL_POINTER; + } + std::string jsonStr = std::string(str); + StreamData data = {reinterpret_cast(const_cast(bufferData->GetAddr())), + bufferData->GetSize()}; + StreamData ext = {const_cast(jsonStr.c_str()), jsonStr.length()}; + int32_t ret = SoftbusChannelAdapter::GetInstance().SendStreamData(sessionName_, peerDevId_, &data, &ext); + if (ret != DH_AVT_SUCCESS) { + AVTRANS_LOGE("Send data to softbus failed."); + } + cJSON_free(str); + cJSON_Delete(jsonObj); + return Status::OK; +} + +void DSoftbusOutputFilter::SetParameter(const std::shared_ptr& meta) +{ + meta_ = meta; +} + +void DSoftbusOutputFilter::GetParameter(std::shared_ptr& meta) +{ + meta = meta_; +} + +Status DSoftbusOutputFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) +{ + nextFilter_ = nextFilter; + nextFiltersMap_[outType].push_back(nextFilter_); + auto filterLinkCallback = std::make_shared(shared_from_this()); + auto ret = nextFilter->OnLinked(outType, meta_, filterLinkCallback); + if (ret != Status::OK) { + AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); + return ret; + } + return Status::OK; +} + +Status DSoftbusOutputFilter::UpdateNext(const std::shared_ptr&, StreamType outType) +{ + return Status::OK; +} + +Status DSoftbusOutputFilter::UnLinkNext(const std::shared_ptr&, StreamType outType) +{ + AVTRANS_LOGI("cur: DSoftbusOutputFilter, unlink next filter.."); + return Status::OK; +} + +Status DSoftbusOutputFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, + const std::shared_ptr &callback) +{ + AVTRANS_LOGI("DSoftbusOutputFilter, OnLinked"); + onLinkedResultCallback_ = callback; + SetParameter(meta); + return Status::OK; +}; + +Status DSoftbusOutputFilter::OnUpdated(StreamType inType, const std::shared_ptr& meta, + const std::shared_ptr& callback) +{ + AVTRANS_LOGI("DSoftbusOutputFilter, OnUpdated"); + return Status::OK; +} + +Status DSoftbusOutputFilter::OnUnLinked(StreamType, const std::shared_ptr& callback) +{ + return Status::OK; +} + +void DSoftbusOutputFilter::OnLinkedResult(const sptr& queue, + std::shared_ptr& meta) +{ + outputBufQueProducer_ = queue; +} + +void DSoftbusOutputFilter::OnUpdatedResult(std::shared_ptr& meta) +{ +} + +void DSoftbusOutputFilter::OnUnlinkedResult(std::shared_ptr& meta) +{ +} + +void DSoftbusOutputFilter::OnChannelEvent(const AVTransEvent &event) +{ + AVTRANS_LOGI("OnChannelEvent enter, event type: %{public}d", event.type); + TRUE_RETURN(eventReceiver_ == nullptr, "receiver_ is nullptr"); + Event channelEvent; + channelEvent.type = EventType::EVENT_AUDIO_PROGRESS; + channelEvent.param = event; + eventReceiver_->OnEvent(channelEvent); +} + +void DSoftbusOutputFilter::OnStreamReceived(const StreamData *data, const StreamData *ext) +{ + (void)data; + (void)ext; +} +} // namespace Pipeline +} // namespace DistributedHardware +} // namespace OHOS diff --git a/av_transport/framework/test/demo/tail_filter.h b/av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.h similarity index 67% rename from av_transport/framework/test/demo/tail_filter.h rename to av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.h index 4978f289..7313d1fb 100644 --- a/av_transport/framework/test/demo/tail_filter.h +++ b/av_transport/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 @@ -13,24 +13,31 @@ * limitations under the License. */ -#ifndef OHOS_AV_PIPELINE_TAIL_FILTER_DEMO_H -#define OHOS_AV_PIPELINE_TAIL_FILTER_DEMO_H +#ifndef OHOS_DSOFTFBUS_OUTPUT_AUDIO_FILTER_H +#define OHOS_DSOFTFBUS_OUTPUT_AUDIO_FILTER_H #include #include #include +#include "buffer/avbuffer_queue.h" +#include "buffer/avbuffer_queue_consumer.h" +#include "buffer/avbuffer_queue_producer.h" +#include "softbus_channel_adapter.h" + #include "pipeline_status.h" #include "filter.h" namespace OHOS { namespace DistributedHardware { namespace Pipeline { -// 分两步:第一先保证fiter连接正常,第二,filter保证数据流转正常 -class TailFilter : public Filter, public std::enable_shared_from_this { +class DSoftbusOutputFilter : public Filter, + public ISoftbusChannelListener, + public std::enable_shared_from_this { public: - TailFilter(std::string name, FilterType type, bool asyncMode = false); - virtual ~TailFilter(); + DSoftbusOutputFilter(std::string name, FilterType type); + virtual ~DSoftbusOutputFilter(); + void Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) override; Status DoInitAfterLink() override; Status DoPrepare() override; @@ -45,6 +52,7 @@ public: Status DoProcessInputBuffer(int recvArg, bool dropFrame) override; Status DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTime) override; + void SetParameter(const std::shared_ptr& meta) override; void GetParameter(std::shared_ptr& meta) override; @@ -58,20 +66,33 @@ public: const std::shared_ptr& callback) override; Status OnUnLinked(StreamType inType, const std::shared_ptr& callback) override; - // PipeLinked 后处理 void OnLinkedResult(const sptr& queue, std::shared_ptr& meta); void OnUnlinkedResult(std::shared_ptr& meta); void OnUpdatedResult(std::shared_ptr& meta); + void OnChannelEvent(const AVTransEvent &event) override; + void OnStreamReceived(const StreamData *data, const StreamData *ext) override; private: - std::shared_ptr configureParam_ {nullptr}; + void PrepareInputBuffer(); + Status ProcessAndSendBuffer(const std::shared_ptr buffer); + std::string MarshalAudioMeta(BufferDataType dataType, int64_t pts, uint32_t frameNumber); + std::shared_ptr meta_ {nullptr}; std::shared_ptr nextFilter_ {nullptr}; std::shared_ptr eventReceiver_ {nullptr}; std::shared_ptr filterCallback_ {nullptr}; std::shared_ptr onLinkedResultCallback_ {nullptr}; + + std::shared_ptr outputBufQue_ {nullptr}; + sptr inputBufQueProducer_ {nullptr}; + sptr inputBufQueConsumer_ {nullptr}; + sptr outputBufQueProducer_ {nullptr}; + std::mutex paramsMapMutex_; + std::string ownerName_; + std::string sessionName_; + std::string peerDevId_; }; } // namespace Pipeline } // namespace DistributedHardware } // namespace OHOS -#endif // OHOS_AV_PIPELINE_TAIL_FILTER_DEMO_H +#endif diff --git a/av_transport/common/include/av_trans_constants.h b/av_transport/common/include/av_trans_constants.h index 8673cdb1..6ff9da41 100644 --- a/av_transport/common/include/av_trans_constants.h +++ b/av_transport/common/include/av_trans_constants.h @@ -74,6 +74,8 @@ const std::string KEY_GROUP_INFO_ARRAY = "groupInfoArray"; const std::string KEY_SHARED_MEM_FD = "sharedMemoryFd"; const std::string KEY_SHARED_MEM_SIZE = "sharedMemorySize"; const std::string KEY_SHARED_MEM_NAME = "sharedMemoryName"; +const std::string KEY_ONWER_NAME = "ownerName"; +const std::string KEY_PEERDEVID_NAME = "peerDevId"; const std::string SCREEN_FILE_NAME_BEFOREENCODING = "/data/data/dscreen/BeforeEncoding.h265"; const std::string SCREEN_FILE_NAME_AFTERCODING = "/data/data/dscreen/AfterCoding.h265"; diff --git a/av_transport/common/include/pipeline_event.h b/av_transport/common/include/pipeline_event.h index 611373da..7411326a 100644 --- a/av_transport/common/include/pipeline_event.h +++ b/av_transport/common/include/pipeline_event.h @@ -63,6 +63,12 @@ struct Event { Media::Any param; }; +typedef enum { + AUDIO_CODEC_AAC = 0, + AUDIO_CODEC_FLAC = 1, + AUDIO_CODEC_AAC_EN = 2 +} AudioCodecType; + const char* GetEventName(EventType type); } // namespace Pipeline } // namespace DistributedHardware diff --git a/av_transport/framework/BUILD.gn b/av_transport/framework/BUILD.gn index c4672acf..4bc3abb9 100644 --- a/av_transport/framework/BUILD.gn +++ b/av_transport/framework/BUILD.gn @@ -40,6 +40,10 @@ ohos_shared_library("distributed_av_pipeline_fwk") { "${dh_fwk_utils_path}/include", "${distributed_av_transport_path}/framework", "${distributed_av_transport_path}/framework/filter/include", + "${distributed_av_transport_path}/framework/pipeline/include", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_coder", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_input", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_output", ] sources = [ @@ -47,6 +51,13 @@ ohos_shared_library("distributed_av_pipeline_fwk") { "${distributed_av_transport_path}/framework/filter/src/filter.cpp", "${distributed_av_transport_path}/framework/filter/src/filter_factory.cpp", "${distributed_av_transport_path}/framework/pipeline/src/pipeline.cpp", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_coder/av_trans_audio_decoder_filter.cpp", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_coder/av_trans_audio_encoder_filter.cpp", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_input/av_trans_audio_input_filter.cpp", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_input/av_trans_bus_input_filter.cpp", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_output/daudio_output_filter.cpp", + "${distributed_av_transport_path}/av_trans_engine/filters/av_trans_output/dsoftbus_output_filter.cpp", + "${common_path}/src/softbus_channel_adapter.cpp", ] deps = [ "${dh_fwk_sdk_path}:libdhfwk_sdk" ] diff --git a/av_transport/framework/test/demo/BUILD.gn b/av_transport/framework/test/demo/BUILD.gn deleted file mode 100644 index add42a8f..00000000 --- a/av_transport/framework/test/demo/BUILD.gn +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2024 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("../../../distributed_av_transport.gni") - -config("av_pipeline_demo_external_config") { - include_dirs = [ - "${common_path}/include", - "${dh_fwk_sdk_path}/include", - "${interface_path}", - ] -} - -ohos_executable("av_trans_pipelie_demo") { - sanitize = { - cfi = true - cfi_cross_dso = true - cfi_no_nvcall = true - cfi_vcall_icall_only = true - debug = false - boundary_sanitize = true - integer_overflow = true - ubsan = true - } - branch_protector_ret = "pac_ret" - public_configs = [ ":av_pipeline_demo_external_config" ] - - include_dirs = [ - "./include", - "${distributed_av_transport_path}/framework", - "${distributed_av_transport_path}/framework/filter/include", - ] - - sources = [ - "${distributed_av_transport_path}/framework/test/demo/head_filter.cpp", - "${distributed_av_transport_path}/framework/test/demo/mid_filter.cpp", - "${distributed_av_transport_path}/framework/test/demo/pipe_demo.cpp", - "${distributed_av_transport_path}/framework/test/demo/tail_filter.cpp", - ] - - deps = [ - "${dh_fwk_sdk_path}:libdhfwk_sdk", - "${distributed_av_transport_path}/framework:distributed_av_pipeline_fwk", - ] - - defines = [ - "HI_LOG_ENABLE", - "DH_LOG_TAG=\"av_trans_pipe_demo\"", - "LOG_DOMAIN=0xD004101", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - ] - - if (histreamer_compile_part) { - external_deps += [ "media_foundation:media_foundation" ] - } - - cflags = [ - "-fexceptions", - "-fno-rtti", - "-fPIC", - "-O2", - "-Wall", - ] - cflags_cc = cflags - - install_enable = false - part_name = "distributed_hardware_fwk" - subsystem_name = "distributedhardware" -} diff --git a/av_transport/framework/test/demo/head_filter.cpp b/av_transport/framework/test/demo/head_filter.cpp deleted file mode 100644 index 3cb0a226..00000000 --- a/av_transport/framework/test/demo/head_filter.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2024 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 "head_filter.h" - -#include - -#include "av_trans_log.h" -#include "filter_factory.h" - -#undef DH_LOG_TAG -#define DH_LOG_TAG "HeadFilter" - -namespace OHOS { -namespace DistributedHardware { -namespace Pipeline { -static AutoRegisterFilter g_registerAudioEncoderFilter("builtin.recorder.test1", - FilterType::FILTERTYPE_MUXER, - [](const std::string& name, const FilterType type) { - return std::make_shared(name, FilterType::FILTERTYPE_MUXER); - }); - -class HeadFilterLinkCallback : public FilterLinkCallback { -public: - explicit HeadFilterLinkCallback(std::shared_ptr filter) - : headFilter_(std::move(filter)) {} - ~HeadFilterLinkCallback() = default; - - void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnLinkedResult(queue, meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - - void OnUnlinkedResult(std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnUnlinkedResult(meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - - void OnUpdatedResult(std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnUpdatedResult(meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - -private: - std::weak_ptr headFilter_ {}; -}; - -HeadFilter::HeadFilter(std::string name, FilterType type, bool isAsyncMode) - : Filter(name, type) -{ -} - -HeadFilter::~HeadFilter() -{ - nextFiltersMap_.clear(); -} - -void HeadFilter::Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) -{ - AVTRANS_LOGI("HeadFilter::Init"); - receiver_ = receiver; - callback_ = callback; - AVTRANS_LOGI("HeadFilter::Init Done"); -} - -Status HeadFilter::DoInitAfterLink() -{ - AVTRANS_LOGI("HeadFilter::DoInitAfterLink"); - return Status::OK; -} - -Status HeadFilter::DoPrepare() -{ - // 1. 本Filter的准备 - AVTRANS_LOGI("HeadFilter::DoPrepare"); - - // 2. 回调申请下一级filter - if (callback_ == nullptr) { - AVTRANS_LOGE("filter callback is null"); - return Status::ERROR_NULL_POINTER; - } - callback_->OnCallback(shared_from_this(), FilterCallBackCommand::NEXT_FILTER_NEEDED, - StreamType::STREAMTYPE_ENCODED_AUDIO); - AVTRANS_LOGI("HeadFilter::DoPrepare done"); - return Status::OK; -} - -Status HeadFilter::DoStart() -{ - AVTRANS_LOGI("HeadFilter::DoStart"); - return Status::OK; -} - -Status HeadFilter::DoPause() -{ - AVTRANS_LOGI("HeadFilter::DoPause"); - return Status::OK; -} - -Status HeadFilter::DoPauseDragging() -{ - AVTRANS_LOGI("HeadFilter::DoPauseDragging"); - return Status::OK; -} - -Status HeadFilter::DoResume() -{ - AVTRANS_LOGI("HeadFilter::DoResume"); - return Status::OK; -} - -Status HeadFilter::DoResumeDragging() -{ - AVTRANS_LOGI("HeadFilter::DoResumeDragging"); - return Status::OK; -} - -Status HeadFilter::DoStop() -{ - AVTRANS_LOGI("HeadFilter::DoStop"); - return Status::OK; -} - -Status HeadFilter::DoFlush() -{ - AVTRANS_LOGI("HeadFilter::DoFlush"); - return Status::OK; -} - -Status HeadFilter::DoRelease() -{ - AVTRANS_LOGI("HeadFilter::DoRelease"); - return Status::OK; -} - -Status HeadFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) -{ - AVTRANS_LOGI("HeadFilter::DoProcessInputBuffer"); - return Status::OK; -} - -Status HeadFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTimee) -{ - AVTRANS_LOGI("HeadFilter::DoProcessOutputBuffer"); - return Status::OK; -} - -void HeadFilter::SetParameter(const std::shared_ptr& meta) -{ - meta_ = meta; -} - -void HeadFilter::GetParameter(std::shared_ptr& meta) -{ - meta = meta_; -} - -Status HeadFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) -{ - AVTRANS_LOGI("cur: HeadFilter, link next filter.."); - // 1. 插入下级filter维护map - nextFilter_ = nextFilter; - nextFiltersMap_[outType].push_back(nextFilter_); - // 2. 下级节点的Link初始化 - auto filterLinkCallback = std::make_shared(shared_from_this()); - auto ret = nextFilter->OnLinked(outType, configureParam_, filterLinkCallback); - if (ret != Status::OK) { - AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); - return ret; - } - return Status::OK; -} - -Status HeadFilter::UpdateNext(const std::shared_ptr&, StreamType) -{ - return Status::OK; -} - -Status HeadFilter::UnLinkNext(const std::shared_ptr&, StreamType) -{ - AVTRANS_LOGI("cur: HeadFilter, unlink next filter.."); - return Status::OK; -} - -Status HeadFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, - const std::shared_ptr &callback) -{ - AVTRANS_LOGI("cur: HeadFilter, OnLinked"); - return Status::OK; -}; - -Status HeadFilter::OnUpdated(StreamType, const std::shared_ptr&, - const std::shared_ptr&) -{ - return Status::OK; -} - -Status HeadFilter::OnUnLinked(StreamType, const std::shared_ptr&) -{ - AVTRANS_LOGI("cur: HeadFilter, OnUnLinked."); - return Status::OK; -} - -void HeadFilter::OnLinkedResult(const sptr& queue, std::shared_ptr& meta) -{ - // link bufferQueue - AVTRANS_LOGI("cur: HeadFilter, OnLinkedResult"); -} - -void HeadFilter::OnUnlinkedResult(std::shared_ptr& meta) -{ -} - -void HeadFilter::OnUpdatedResult(std::shared_ptr& meta) -{ -} -} // namespace Pipeline -} // namespace DistributedHardware -} // namespace OHOS diff --git a/av_transport/framework/test/demo/mid_filter.cpp b/av_transport/framework/test/demo/mid_filter.cpp deleted file mode 100644 index edec23d7..00000000 --- a/av_transport/framework/test/demo/mid_filter.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2024 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 "mid_filter.h" - -#include - -#include "av_trans_log.h" -#include "filter_factory.h" - -#undef DH_LOG_TAG -#define DH_LOG_TAG "MidFilter" - -namespace OHOS { -namespace DistributedHardware { -namespace Pipeline { -static AutoRegisterFilter g_registerAudioEncoderFilter("builtin.recorder.midfilter", - FilterType::FILTERTYPE_VIDEODEC, - [](const std::string& name, const FilterType type) { - return std::make_shared(name, FilterType::FILTERTYPE_VIDEODEC); - }); - -class MidFilterLinkCallback : public FilterLinkCallback { -public: - explicit MidFilterLinkCallback(std::shared_ptr filter) - : headFilter_(std::move(filter)) {} - ~MidFilterLinkCallback() = default; - - void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnLinkedResult(queue, meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - - void OnUnlinkedResult(std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnUnlinkedResult(meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - - void OnUpdatedResult(std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnUpdatedResult(meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - -private: - std::weak_ptr headFilter_ {}; -}; - -MidFilter::MidFilter(std::string name, FilterType type, bool isAsyncMode) - : Filter(name, type) -{ -} - -MidFilter::~MidFilter() -{ - nextFiltersMap_.clear(); -} - -void MidFilter::Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) -{ - receiver_ = receiver; - callback_ = callback; -} - -Status MidFilter::DoInitAfterLink() -{ - AVTRANS_LOGI("MidFilter::DoInitAfterLink"); - return Status::OK; -} - -Status MidFilter::DoPrepare() -{ - // 1. 本Filter的准备 - AVTRANS_LOGI("MidFilter::DoPrepare"); - - // 2. 回调申请下一级filter - if (callback_ == nullptr) { - AVTRANS_LOGE("filter callback is null"); - return Status::ERROR_NULL_POINTER; - } - callback_->OnCallback(shared_from_this(), FilterCallBackCommand::NEXT_FILTER_NEEDED, - StreamType::STREAMTYPE_RAW_AUDIO); - AVTRANS_LOGI("MidFilter::DoPrepare done"); - return Status::OK; -} - -Status MidFilter::DoStart() -{ - AVTRANS_LOGI("MidFilter::DoStart"); - return Status::OK; -} - -Status MidFilter::DoPause() -{ - AVTRANS_LOGI("MidFilter::DoPause"); - return Status::OK; -} - -Status MidFilter::DoPauseDragging() -{ - AVTRANS_LOGI("MidFilter::DoPauseDragging"); - return Status::OK; -} - -Status MidFilter::DoResume() -{ - AVTRANS_LOGI("MidFilter::DoResume"); - return Status::OK; -} - -Status MidFilter::DoResumeDragging() -{ - AVTRANS_LOGI("MidFilter::DoResumeDragging"); - return Status::OK; -} - -Status MidFilter::DoStop() -{ - AVTRANS_LOGI("MidFilter::DoStop"); - return Status::OK; -} - -Status MidFilter::DoFlush() -{ - AVTRANS_LOGI("MidFilter::DoFlush"); - return Status::OK; -} - -Status MidFilter::DoRelease() -{ - AVTRANS_LOGI("MidFilter::DoRelease"); - return Status::OK; -} - -Status MidFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) -{ - AVTRANS_LOGI("MidFilter::DoProcessInputBuffer"); - return Status::OK; -} - -Status MidFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTimee) -{ - AVTRANS_LOGI("MidFilter::DoProcessOutputBuffer"); - return Status::OK; -} - -void MidFilter::SetParameter(const std::shared_ptr& meta) -{ - meta_ = meta; -} - -void MidFilter::GetParameter(std::shared_ptr& meta) -{ - meta = meta_; -} - -Status MidFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) -{ - AVTRANS_LOGI("cur: MidFilter, link next filter.."); - // 1. 插入下级filter维护map - nextFilter_ = nextFilter; - nextFiltersMap_[outType].push_back(nextFilter_); - // 2. 下级节点的Link初始化 - auto filterLinkCallback = std::make_shared(shared_from_this()); - auto ret = nextFilter->OnLinked(outType, configureParam_, filterLinkCallback); - if (ret != Status::OK) { - AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); - return ret; - } - return Status::OK; -} - -Status MidFilter::UpdateNext(const std::shared_ptr&, StreamType) -{ - return Status::OK; -} - -Status MidFilter::UnLinkNext(const std::shared_ptr&, StreamType) -{ - AVTRANS_LOGI("cur: MidFilter, unlink next filter.."); - return Status::OK; -} - -Status MidFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, - const std::shared_ptr &callback) -{ - AVTRANS_LOGI("cur: MidFilter, OnLinked"); - onLinkedResultCallback_ = callback; - return Status::OK; -}; - -Status MidFilter::OnUpdated(StreamType, const std::shared_ptr&, - const std::shared_ptr&) -{ - return Status::OK; -} - -Status MidFilter::OnUnLinked(StreamType, const std::shared_ptr&) -{ - AVTRANS_LOGI("cur: MidFilter, OnUnLinked."); - return Status::OK; -} - -void MidFilter::OnLinkedResult(const sptr& queue, std::shared_ptr& meta) -{ - // link bufferQueue - AVTRANS_LOGI("cur: MidFilter, OnLinkedResult."); - sptr producer = nullptr; - std::shared_ptr midMeta = std::make_shared(); - if (onLinkedResultCallback_ != nullptr) { - onLinkedResultCallback_->OnLinkedResult(producer, midMeta); - } -} - -void MidFilter::OnUnlinkedResult(std::shared_ptr& meta) -{ -} - -void MidFilter::OnUpdatedResult(std::shared_ptr& meta) -{ -} -} // namespace Pipeline -} // namespace DistributedHardware -} // namespace OHOS diff --git a/av_transport/framework/test/demo/pipe_demo.cpp b/av_transport/framework/test/demo/pipe_demo.cpp deleted file mode 100644 index 513ad285..00000000 --- a/av_transport/framework/test/demo/pipe_demo.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2024 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 "pipe_demo.h" - -#include -#include - -#include "av_trans_log.h" -#include "filter_factory.h" - -#undef DH_LOG_TAG -#define DH_LOG_TAG "PipeDemo" - -namespace OHOS { -namespace DistributedHardware { -namespace Pipeline { -class PlayerEventReceiver : public EventReceiver { -public: - explicit PlayerEventReceiver(PipeDemo* pipeDemo, std::string playerId) - { - AVTRANS_LOGI("PlayerEventReceiver ctor called."); - pipeDemo_ = pipeDemo; - } - - void OnEvent(const Event &event) - { - AVTRANS_LOGD("PlayerEventReceiver OnEvent."); - } - -private: - PipeDemo* pipeDemo_; -}; - -class PlayerFilterCallback : public FilterCallback { -public: - explicit PlayerFilterCallback(PipeDemo* pipeDemo) - { - AVTRANS_LOGI("PlayerFilterCallback ctor called."); - pipeDemo_ = pipeDemo; - } - - Status OnCallback(const std::shared_ptr& filter, FilterCallBackCommand cmd, StreamType outType) override - { - AVTRANS_LOGI("PlayerFilterCallback OnCallback."); - if (pipeDemo_ == nullptr) { - return Status::ERROR_NULL_POINTER; - } - return pipeDemo_->OnCallback(filter, cmd, outType); - } - -private: - PipeDemo* pipeDemo_; -}; - - -PipeDemo::PipeDemo() {} - -PipeDemo::~PipeDemo() {} - -int32_t PipeDemo::InitPipe() -{ - // 初始化pipeline - demoId_ = std::string("PipeDemo") + std::to_string(Pipeline::GetNextPipelineId()); - pipeline_ = std::make_shared(); - playerEventReceiver_ = std::make_shared(this, demoId_); - playerFilterCallback_ = std::make_shared(this); - - AVTRANS_LOGI("pipeline Init in"); - pipeline_->Init(playerEventReceiver_, playerFilterCallback_, demoId_); - AVTRANS_LOGI("pipeline Init out"); - // 添加头Filter - headFilter_ = FilterFactory::Instance().CreateFilter("builtin.recorder.test1", - FilterType::FILTERTYPE_MUXER); - if (headFilter_ == nullptr) { - return -1; - } - - headFilter_->Init(playerEventReceiver_, playerFilterCallback_); - pipeline_->AddHeadFilters({headFilter_}); - return 0; -} - -int32_t PipeDemo::Prepare() -{ - if (pipeline_ != nullptr) { - pipeline_->Prepare(); - } - return 0; -} - -int32_t PipeDemo::Start() -{ - if (pipeline_ != nullptr) { - pipeline_->Start(); - } - return 0; -} - -int32_t PipeDemo::Pause() -{ - if (pipeline_ != nullptr) { - pipeline_->Pause(); - } - return 0; -} - -int32_t PipeDemo::Stop() -{ - if (pipeline_ != nullptr) { - pipeline_->Stop(); - } - return 0; -} - -int32_t PipeDemo::Release() -{ - if (pipeline_ != nullptr) { - pipeline_->Release(); - } - return 0; -} - -Status PipeDemo::OnCallback(std::shared_ptr filter, const FilterCallBackCommand cmd, - StreamType outType) -{ - AVTRANS_LOGI("PipeDemo::OnCallback filter, outType: %{public}d", outType); - if (cmd == FilterCallBackCommand::NEXT_FILTER_NEEDED) { - switch (outType) { - case StreamType::STREAMTYPE_RAW_AUDIO: - return LinkAudioSinkFilter(filter, outType); - case StreamType::STREAMTYPE_ENCODED_AUDIO: - return LinkAudioDecoderFilter(filter, outType); - default: - break; - } - } - return Status::OK; -} - -Status PipeDemo::LinkAudioDecoderFilter(const std::shared_ptr& preFilter, StreamType type) -{ - AVTRANS_LOGI("PipeDemo::LinkAudioDecoderFilter"); - TRUE_RETURN_V(midFilter_ != nullptr, Status::OK); - midFilter_ = FilterFactory::Instance().CreateFilter("builtin.recorder.midfilter", - FilterType::FILTERTYPE_VIDEODEC); - TRUE_RETURN_V(midFilter_ == nullptr, Status::ERROR_NULL_POINTER); - midFilter_->Init(playerEventReceiver_, playerFilterCallback_); - - return pipeline_->LinkFilters(preFilter, {midFilter_}, type); -} - -Status PipeDemo::LinkAudioSinkFilter(const std::shared_ptr& preFilter, StreamType type) -{ - AVTRANS_LOGI("PipeDemo::LinkAudioSinkFilter"); - TRUE_RETURN_V(tailFilter_ != nullptr, Status::OK); - tailFilter_ = FilterFactory::Instance().CreateFilter("builtin.recorder.tailfilter", - FilterType::FILTERTYPE_DEMUXER); - TRUE_RETURN_V(tailFilter_ == nullptr, Status::ERROR_NULL_POINTER); - tailFilter_->Init(playerEventReceiver_, playerFilterCallback_); - - return pipeline_->LinkFilters(preFilter, {tailFilter_}, type); -} -} // namespace Pipeline -} // namespace DistributedHardware -} // namespace OHOS - - -int main(int argc, char *argv[]) -{ - auto pipeDemo = std::make_shared(); - std::cout << "Initing..." << std::endl; - pipeDemo->InitPipe(); - std::cout << "Init piep success" << std::endl; - - std::cout << "Preparing..." << std::endl; - pipeDemo->Prepare(); - std::cout << "Prepare success" << std::endl; - - std::cout << "Starting..." << std::endl; - pipeDemo->Start(); - std::cout << "Start success" << std::endl; - - std::cout << "Pausing..." << std::endl; - pipeDemo->Pause(); - std::cout << "Pause success" << std::endl; - - std::cout << "Stoping..." << std::endl; - pipeDemo->Stop(); - std::cout << "Stop success" << std::endl; - - std::cout << "Releasing..." << std::endl; - pipeDemo->Release(); - std::cout << "Release success" << std::endl; - - return 0; -} diff --git a/av_transport/framework/test/demo/tail_filter.cpp b/av_transport/framework/test/demo/tail_filter.cpp deleted file mode 100644 index dc1c425d..00000000 --- a/av_transport/framework/test/demo/tail_filter.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2024 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 "tail_filter.h" - -#include - -#include "av_trans_log.h" -#include "filter_factory.h" - -#undef DH_LOG_TAG -#define DH_LOG_TAG "TailFilter" - -namespace OHOS { -namespace DistributedHardware { -namespace Pipeline { -static AutoRegisterFilter g_registerAudioEncoderFilter("builtin.recorder.tailfilter", - FilterType::FILTERTYPE_DEMUXER, - [](const std::string& name, const FilterType type) { - return std::make_shared(name, FilterType::FILTERTYPE_DEMUXER); - }); - -class TailFilterLinkCallback : public FilterLinkCallback { -public: - explicit TailFilterLinkCallback(std::shared_ptr filter) - : headFilter_(std::move(filter)) {} - ~TailFilterLinkCallback() = default; - - void OnLinkedResult(const sptr &queue, std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnLinkedResult(queue, meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - - void OnUnlinkedResult(std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnUnlinkedResult(meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - - void OnUpdatedResult(std::shared_ptr &meta) override - { - if (auto filter = headFilter_.lock()) { - filter->OnUpdatedResult(meta); - } else { - AVTRANS_LOGI("invalid headFilter"); - } - } - -private: - std::weak_ptr headFilter_ {}; -}; - -TailFilter::TailFilter(std::string name, FilterType type, bool isAsyncMode) - : Filter(name, type) -{ -} - -TailFilter::~TailFilter() -{ - nextFiltersMap_.clear(); -} - -void TailFilter::Init(const std::shared_ptr& receiver, const std::shared_ptr& callback) -{ - receiver_ = receiver; - callback_ = callback; -} - -Status TailFilter::DoInitAfterLink() -{ - AVTRANS_LOGI("TailFilter::DoInitAfterLink"); - return Status::OK; -} - -Status TailFilter::DoPrepare() -{ - AVTRANS_LOGI("cur: TailFilter, notify linkedResult."); - sptr producer = nullptr; - std::shared_ptr meta = std::make_shared(); - if (onLinkedResultCallback_ != nullptr) { - onLinkedResultCallback_->OnLinkedResult(producer, meta); - } - return Status::OK; -} - -Status TailFilter::DoStart() -{ - AVTRANS_LOGI("TailFilter::DoStart"); - return Status::OK; -} - -Status TailFilter::DoPause() -{ - AVTRANS_LOGI("TailFilter::DoPause"); - return Status::OK; -} - -Status TailFilter::DoPauseDragging() -{ - AVTRANS_LOGI("TailFilter::DoPauseDragging"); - return Status::OK; -} - -Status TailFilter::DoResume() -{ - AVTRANS_LOGI("TailFilter::DoResume"); - return Status::OK; -} - -Status TailFilter::DoResumeDragging() -{ - AVTRANS_LOGI("TailFilter::DoResumeDragging"); - return Status::OK; -} - -Status TailFilter::DoStop() -{ - AVTRANS_LOGI("TailFilter::DoStop"); - return Status::OK; -} - -Status TailFilter::DoFlush() -{ - AVTRANS_LOGI("TailFilter::DoFlush"); - return Status::OK; -} - -Status TailFilter::DoRelease() -{ - AVTRANS_LOGI("TailFilter::DoRelease"); - return Status::OK; -} - -Status TailFilter::DoProcessInputBuffer(int recvArg, bool dropFrame) -{ - AVTRANS_LOGI("TailFilter::DoProcessInputBuffer"); - return Status::OK; -} - -Status TailFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx, int64_t renderTimee) -{ - AVTRANS_LOGI("TailFilter::DoProcessOutputBuffer"); - return Status::OK; -} - -void TailFilter::SetParameter(const std::shared_ptr& meta) -{ - meta_ = meta; -} - -void TailFilter::GetParameter(std::shared_ptr& meta) -{ - meta = meta_; -} - -Status TailFilter::LinkNext(const std::shared_ptr& nextFilter, StreamType outType) -{ - AVTRANS_LOGI("cur: TailFilter, link next filter.."); - // 1. 插入下级filter维护map - nextFilter_ = nextFilter; - nextFiltersMap_[outType].push_back(nextFilter_); - // 2. 下级节点的Link初始化 - auto filterLinkCallback = std::make_shared(shared_from_this()); - auto ret = nextFilter->OnLinked(outType, configureParam_, filterLinkCallback); - if (ret != Status::OK) { - AVTRANS_LOGE("Onlinked failed, status: %{public}d.", ret); - return ret; - } - return Status::OK; -} - -Status TailFilter::UpdateNext(const std::shared_ptr&, StreamType) -{ - return Status::OK; -} - -Status TailFilter::UnLinkNext(const std::shared_ptr&, StreamType) -{ - AVTRANS_LOGI("cur: TailFilter, unlink next filter.."); - return Status::OK; -} - -Status TailFilter::OnLinked(StreamType inType, const std::shared_ptr &meta, - const std::shared_ptr &callback) -{ - AVTRANS_LOGI("cur: TailFilter, OnLinked"); - onLinkedResultCallback_ = callback; - return Status::OK; -}; - -Status TailFilter::OnUpdated(StreamType, const std::shared_ptr&, - const std::shared_ptr&) -{ - return Status::OK; -} - -Status TailFilter::OnUnLinked(StreamType, const std::shared_ptr&) -{ - AVTRANS_LOGI("cur: TailFilter, OnUnLinked."); - return Status::OK; -} - -void TailFilter::OnLinkedResult(const sptr& queue, std::shared_ptr& meta) -{ - // link bufferQueue -} - -void TailFilter::OnUnlinkedResult(std::shared_ptr& meta) -{ -} - -void TailFilter::OnUpdatedResult(std::shared_ptr& meta) -{ -} -} // namespace Pipeline -} // namespace DistributedHardware -} // namespace OHOS diff --git a/bundle.json b/bundle.json index 313deb80..350547e7 100644 --- a/bundle.json +++ b/bundle.json @@ -68,7 +68,6 @@ "//foundation/distributedhardware/distributed_hardware_fwk/av_transport/av_trans_engine/av_sender:distributed_av_sender", "//foundation/distributedhardware/distributed_hardware_fwk/av_transport/av_trans_handler/histreamer_ability_querier:histreamer_ability_querier", "//foundation/distributedhardware/distributed_hardware_fwk/av_transport/framework:distributed_av_pipeline_fwk", - "//foundation/distributedhardware/distributed_hardware_fwk/av_transport/framework/test/demo:av_trans_pipelie_demo", "//foundation/distributedhardware/distributed_hardware_fwk/interfaces/inner_kits:libdhfwk_sdk", "//foundation/distributedhardware/distributed_hardware_fwk/interfaces/kits/napi:hardwaremanager", "//foundation/distributedhardware/distributed_hardware_fwk/sa_profile:dhardware.cfg", -- Gitee