/* * Copyright 2021 The Android Open Source Project * * 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. */ #pragma once #include #include #include #include #include #include #include #include "Dvr.h" #include "Filter.h" #include "Frontend.h" #include "TimeFilter.h" #include "Timer.h" #include "Tuner.h" #include "dtv_plugin.h" using namespace std; namespace aidl { namespace android { namespace hardware { namespace tv { namespace tuner { using ::aidl::android::hardware::common::fmq::MQDescriptor; using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; using ::android::AidlMessageQueue; using ::android::hardware::EventFlag; using FilterMQ = AidlMessageQueue; using AidlMQ = AidlMessageQueue; using AidlMQDesc = MQDescriptor; class Dvr; class Filter; class Frontend; class TimeFilter; class Tuner; const int IPTV_PLAYBACK_TIMEOUT = 20; // ms const int IPTV_PLAYBACK_BUFFER_TIMEOUT = 20000; // ms class DvrPlaybackCallback : public BnDvrCallback { public: virtual ::ndk::ScopedAStatus onPlaybackStatus(PlaybackStatus status) override { ALOGD("demux.h: playback status %d", status); return ndk::ScopedAStatus::ok(); } virtual ::ndk::ScopedAStatus onRecordStatus(RecordStatus status) override { ALOGD("Record Status %hhd", status); return ndk::ScopedAStatus::ok(); } }; class Demux : public BnDemux { public: Demux(int32_t demuxId, uint32_t filterTypes); ~Demux(); ::ndk::ScopedAStatus setFrontendDataSource(int32_t in_frontendId) override; ::ndk::ScopedAStatus openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize, const std::shared_ptr& in_cb, std::shared_ptr* _aidl_return) override; ::ndk::ScopedAStatus openTimeFilter(std::shared_ptr* _aidl_return) override; ::ndk::ScopedAStatus getAvSyncHwId(const std::shared_ptr& in_filter, int32_t* _aidl_return) override; ::ndk::ScopedAStatus getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) override; ::ndk::ScopedAStatus close() override; ::ndk::ScopedAStatus openDvr(DvrType in_type, int32_t in_bufferSize, const std::shared_ptr& in_cb, std::shared_ptr* _aidl_return) override; ::ndk::ScopedAStatus connectCiCam(int32_t in_ciCamId) override; ::ndk::ScopedAStatus disconnectCiCam() override; binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; // Functions interacts with Tuner Service void stopFrontendInput(); ::ndk::ScopedAStatus removeFilter(int64_t filterId); bool attachRecordFilter(int64_t filterId); bool detachRecordFilter(int64_t filterId); ::ndk::ScopedAStatus startFilterHandler(int64_t filterId); void updateFilterOutput(int64_t filterId, vector data); void updateMediaFilterOutput(int64_t filterId, vector data, uint64_t pts); uint16_t getFilterTpid(int64_t filterId); void setIsRecording(bool isRecording); bool isRecording(); void startFrontendInputLoop(); void frontendIptvInputThreadLoop(dtv_plugin* interface, dtv_streamer* streamer, void* buf); /** * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. * Note that recording filters are not included. */ bool startBroadcastFilterDispatcher(); void startBroadcastTsFilter(vector data); void sendFrontendInputToRecord(vector data); void sendFrontendInputToRecord(vector data, uint16_t pid, uint64_t pts); bool startRecordFilterDispatcher(); void getDemuxInfo(DemuxInfo* demuxInfo); int32_t getDemuxId(); bool isInUse(); void setInUse(bool inUse); void setTunerService(std::shared_ptr tuner); /** * Setter for IPTV Reading thread */ void setIptvThreadRunning(bool isIptvThreadRunning); /** * Stops IPTV playback reading thread. */ void stopIptvFrontendInput(); private: // Tuner service std::shared_ptr mTuner; // Frontend source std::shared_ptr mFrontend; // A struct that passes the arguments to a newly created filter thread struct ThreadArgs { Demux* user; int64_t filterId; }; static void* __threadLoopFrontend(void* user); void frontendInputThreadLoop(); /** * To create a FilterMQ with the next available Filter ID. * Creating Event Flag at the same time. * Add the successfully created/saved FilterMQ into the local list. * * Return false is any of the above processes fails. */ void deleteEventFlag(); bool readDataFromMQ(); int32_t mDemuxId = -1; int32_t mCiCamId; set mPcrFilterIds; /** * Record the last used filter id. Initial value is -1. * Filter Id starts with 0. */ int64_t mLastUsedFilterId = -1; /** * Record all the used playback filter Ids. * Any removed filter id should be removed from this set. */ set mPlaybackFilterIds; /** * Record all the attached record filter Ids. * Any removed filter id should be removed from this set. */ set mRecordFilterIds; /** * A list of created Filter sp. * The array number is the filter ID. */ std::map> mFilters; /** * Local reference to the opened Timer Filter instance. */ std::shared_ptr mTimeFilter; /** * Local reference to the opened DVR object. */ std::shared_ptr mDvrPlayback; std::shared_ptr mDvrRecord; // Thread handlers std::thread mFrontendInputThread; std::thread mDemuxIptvReadThread; // track whether the DVR FMQ for IPTV Playback is full bool mIsIptvDvrFMQFull = false; /** * If a specific filter's writing loop is still running */ std::atomic mFrontendInputThreadRunning; std::atomic mKeepFetchingDataFromFrontend; /** * Controls IPTV reading thread status */ bool mIsIptvReadThreadRunning = false; std::atomic mIsIptvReadThreadTerminated = false; std::mutex mIsIptvThreadRunningMutex; std::condition_variable mIsIptvThreadRunningCv; /** * If the dvr recording is running. */ bool mIsRecording = false; /** * Lock to protect writes to the FMQs */ std::mutex mWriteLock; // temp handle single PES filter // TODO handle mulptiple Pes filters int mPesSizeLeft = 0; vector mPesOutput; const bool DEBUG_DEMUX = false; int32_t mFilterTypes; bool mInUse = false; }; } // namespace tuner } // namespace tv } // namespace hardware } // namespace android } // namespace aidl