/* * Copyright (c) 2020 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ #define LOG_TAG "AmlMpPlayerDemo_AmlDemuxBase" #include #include "AmlDemuxBase.h" #include "AmlHwDemux.h" #include "AmlSwDemux.h" #ifdef HAVE_TUNER_HAL #ifndef BUILD_AMP_SERVER #include "AmlTunerHalDemux.h" #endif #endif #include #include #include #include static const char* mName = LOG_TAG; namespace aml_mp { //////////////////////////////////////////////////////////////////////////////// struct AmlDemuxBase::Filter : public AmlMpHandle { Filter(Aml_MP_Demux_FilterCb cb, void* userData, int id); ~Filter(); void notifyListener(int pid, const sptr& data, int version); void setOwner(const sptr& channel); bool hasOwner() const; int id() const { return mId; } wptr getOwner() const { return mChannel; } private: Aml_MP_Demux_FilterCb mCb; void* pUserData; const int mId; int mVersion; wptr mChannel; private: Filter(const Filter&); Filter& operator= (const Filter&); }; struct AmlDemuxBase::Channel : public AmlMpHandle { Channel(int pid); ~Channel(); bool attachFilter(const sptr& filter); bool detachFilter(const sptr& filter); bool hasFilter() const; void onData(int pid, const sptr& data, int version); int pid() const { return mPid; } bool enabled() const; void setEnable(bool enable); private: const int mPid = AML_MP_INVALID_PID; std::atomic_bool mEnabled {true}; mutable std::mutex mLock; std::set> mFilters; private: Channel(const Channel&); Channel& operator= (const Channel&); }; ////////////////////////////////////////////////////////////////////////////// AmlDemuxBase::Filter::Filter(Aml_MP_Demux_FilterCb cb, void* userData, int id) : mCb(cb) , pUserData(userData) , mId(id) , mVersion(-1) { MLOG("ctor filter:%d", mId); } AmlDemuxBase::Filter::~Filter() { MLOG("dtor filter:%d", mId); } void AmlDemuxBase::Filter::notifyListener(int pid, const sptr& data, int version) { if (mCb == nullptr) { MLOGW("user cb is NULL!"); return; } if (mVersion >= 0 && version >= 0 && mVersion == version) { return; } mVersion = version; if (mVersion >= 0) { MLOGI("notify filter:%d, version:%d", mId, mVersion); } mCb(pid, data->size(), data->base(), pUserData); } void AmlDemuxBase::Filter::setOwner(const sptr& channel) { mChannel = channel; } bool AmlDemuxBase::Filter::hasOwner() const { return mChannel != nullptr; } //////////////////////////////////////////////////////////////////////////////// AmlDemuxBase::Channel::Channel(int pid) : mPid(pid) { MLOG("ctor channel, pid:%d", mPid); } AmlDemuxBase::Channel::~Channel() { MLOG("dtor channel, pid:%d", mPid); } bool AmlDemuxBase::Channel::attachFilter(const sptr& filter) { { std::lock_guard _l(mLock); mFilters.insert(filter); MLOGV("attach filter:%d to channel:%d, total filters num:%zu", filter->id(), mPid, mFilters.size()); } filter->setOwner(this); return true; } bool AmlDemuxBase::Channel::detachFilter(const sptr& filter) { std::lock_guard _l(mLock); if (mFilters.find(filter) != mFilters.end()) { filter->setOwner(nullptr); mFilters.erase(filter); MLOGV("detach filter:%d from channel:%d, total filters num:%zu", filter->id(), mPid, mFilters.size()); } return true; } bool AmlDemuxBase::Channel::hasFilter() const { std::lock_guard _l(mLock); return !mFilters.empty(); } void AmlDemuxBase::Channel::onData(int pid, const sptr& data, int version) { std::set> filters; { std::lock_guard _l(mLock); if (!enabled() || mFilters.empty()) { return; } filters = mFilters; } for (auto& f : filters) { f->notifyListener(pid, data, version); } } bool AmlDemuxBase::Channel::enabled() const { return mEnabled.load(std::memory_order_relaxed); } void AmlDemuxBase::Channel::setEnable(bool enable) { mEnabled.store(enable, std::memory_order_relaxed); } //////////////////////////////////////////////////////////////////////////////// sptr AmlDemuxBase::create(Aml_MP_DemuxType demuxType) { sptr demux; switch (demuxType) { #ifndef __ANDROID_RECOVERY__ case AML_MP_DEMUX_TYPE_HARDWARE: demux = new AmlHwDemux(); break; #endif case AML_MP_DEMUX_TYPE_SOFTWARE: demux = new AmlSwDemux(); break; #ifdef HAVE_TUNER_HAL #ifndef BUILD_AMP_SERVER case AML_MP_DEMUX_TYPE_TUNERHAL: demux = new AmlTunerHalDemux(); break; #endif #endif default: #ifndef __ANDROID_RECOVERY__ demux = new AmlHwDemux(); #else demux = new AmlSwDemux(); #endif break; } return demux; } AmlDemuxBase::AmlDemuxBase() { } AmlDemuxBase::~AmlDemuxBase() { } AmlDemuxBase::CHANNEL AmlDemuxBase::createChannel(int pid, const Aml_MP_DemuxFilterParams* params) { sptr channel; { std::lock_guard _l(mLock); if (isStopped()) { MLOGE("can't create channel for pid:%d, mStopped:%d", pid, isStopped()); return NULL; } auto it = mChannels.find(pid); if (it != mChannels.end()) { MLOGV("return exist channel:%p", channel.get()); channel = it->second; goto exit; } if (addDemuxFilter(pid, params) < 0) { MLOGE("openHardwareChannel failed!"); return nullptr; } channel = new Channel(pid); auto ret = mChannels.emplace(pid, channel); if (ret.second) { //MLOGI("create channel success!"); } } channel->incStrong(this); exit: return aml_handle_cast(channel); } int AmlDemuxBase::destroyChannel(CHANNEL _channel) { sptr channel = aml_handle_cast(_channel); if (channel == nullptr) { return -1; } int pid = channel->pid(); MLOG("channel:%d", pid); if (channel->hasFilter()) { MLOGI("channel:%d has filter, don't do destroy!", channel->pid()); return -1; } removeDemuxFilter(pid); std::lock_guard _l(mLock); auto it = mChannels.find(pid); if (it != mChannels.end()) { mChannels.erase(it); } channel->decStrong(this); return 0; } int AmlDemuxBase::openChannel(CHANNEL _channel) { sptr channel = aml_handle_cast(_channel); if (channel == nullptr) { return -1; } MLOGV("enable channel:%d", channel->pid()); return 0; } int AmlDemuxBase::closeChannel(CHANNEL _channel) { sptr channel = aml_handle_cast(_channel); if (channel == nullptr) { return -1; } MLOGV("disable channel:%d", channel->pid()); return 0; } AmlDemuxBase::FILTER AmlDemuxBase::createFilter(Aml_MP_Demux_FilterCb cb, void* userData) { sptr filter(new Filter(cb, userData, mFilterId++)); filter->incStrong(this); return aml_handle_cast(filter); } int AmlDemuxBase::destroyFilter(FILTER _filter) { sptr filter = aml_handle_cast(_filter); if (filter == nullptr) { return -1; } if (filter->hasOwner()) { MLOGW("filter has not been detached before!!!"); sptr channel = filter->getOwner().promote(); if (channel != nullptr) { channel->detachFilter(filter); } } filter->decStrong(this); return 0; } int AmlDemuxBase::attachFilter(FILTER _filter, CHANNEL _channel) { sptr filter = aml_handle_cast(_filter); sptr channel = aml_handle_cast(_channel); if (filter == nullptr || channel == nullptr) { return -1; } channel->attachFilter(filter); return 0; } int AmlDemuxBase::detachFilter(FILTER _filter, CHANNEL _channel) { sptr filter = aml_handle_cast(_filter); sptr channel = aml_handle_cast(_channel); if (filter == nullptr || channel == nullptr) { return -1; } if (!channel->hasFilter()) { MLOGW("channel has no filter!!!"); return -1; } channel->detachFilter(filter); return 0; } void AmlDemuxBase::notifyData(int pid, const sptr& data, int version) { sptr channel; { std::unique_lock _l(mLock); auto it = mChannels.find(pid); if (it != mChannels.end()) { channel = it->second; } } if (channel) { channel->onData(pid, data, version); } } //////////////////////////////////////////////////////////////////////////////// AmlDemuxBase::ITsParser::ITsParser(const std::function& cb) : mFilterCallback(cb) { MLOG(); } }