• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <aidl/android/hardware/tv/tuner/BnDemux.h>
20 #include <aidl/android/hardware/tv/tuner/BnDvrCallback.h>
21 
22 #include <fmq/AidlMessageQueue.h>
23 #include <math.h>
24 #include <atomic>
25 #include <set>
26 #include <thread>
27 
28 #include "Dvr.h"
29 #include "Filter.h"
30 #include "Frontend.h"
31 #include "TimeFilter.h"
32 #include "Timer.h"
33 #include "Tuner.h"
34 #include "dtv_plugin.h"
35 
36 using namespace std;
37 
38 namespace aidl {
39 namespace android {
40 namespace hardware {
41 namespace tv {
42 namespace tuner {
43 
44 using ::aidl::android::hardware::common::fmq::MQDescriptor;
45 using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
46 using ::android::AidlMessageQueue;
47 using ::android::hardware::EventFlag;
48 
49 using FilterMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
50 using AidlMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
51 using AidlMQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
52 
53 class Dvr;
54 class Filter;
55 class Frontend;
56 class TimeFilter;
57 class Tuner;
58 
59 const int IPTV_PLAYBACK_TIMEOUT = 20;            // ms
60 const int IPTV_PLAYBACK_BUFFER_TIMEOUT = 20000;  // ms
61 
62 class DvrPlaybackCallback : public BnDvrCallback {
63   public:
onPlaybackStatus(PlaybackStatus status)64     virtual ::ndk::ScopedAStatus onPlaybackStatus(PlaybackStatus status) override {
65         ALOGD("demux.h: playback status %d", status);
66         return ndk::ScopedAStatus::ok();
67     }
68 
onRecordStatus(RecordStatus status)69     virtual ::ndk::ScopedAStatus onRecordStatus(RecordStatus status) override {
70         ALOGD("Record Status %hhd", status);
71         return ndk::ScopedAStatus::ok();
72     }
73 };
74 
75 class Demux : public BnDemux {
76   public:
77     Demux(int32_t demuxId, uint32_t filterTypes);
78     ~Demux();
79 
80     ::ndk::ScopedAStatus setFrontendDataSource(int32_t in_frontendId) override;
81     ::ndk::ScopedAStatus openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
82                                     const std::shared_ptr<IFilterCallback>& in_cb,
83                                     std::shared_ptr<IFilter>* _aidl_return) override;
84     ::ndk::ScopedAStatus openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) override;
85     ::ndk::ScopedAStatus getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
86                                        int32_t* _aidl_return) override;
87     ::ndk::ScopedAStatus getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) override;
88     ::ndk::ScopedAStatus close() override;
89     ::ndk::ScopedAStatus openDvr(DvrType in_type, int32_t in_bufferSize,
90                                  const std::shared_ptr<IDvrCallback>& in_cb,
91                                  std::shared_ptr<IDvr>* _aidl_return) override;
92     ::ndk::ScopedAStatus connectCiCam(int32_t in_ciCamId) override;
93     ::ndk::ScopedAStatus disconnectCiCam() override;
94 
95     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
96 
97     // Functions interacts with Tuner Service
98     void stopFrontendInput();
99     ::ndk::ScopedAStatus removeFilter(int64_t filterId);
100     bool attachRecordFilter(int64_t filterId);
101     bool detachRecordFilter(int64_t filterId);
102     ::ndk::ScopedAStatus startFilterHandler(int64_t filterId);
103     void updateFilterOutput(int64_t filterId, vector<int8_t> data);
104     void updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts);
105     uint16_t getFilterTpid(int64_t filterId);
106     void setIsRecording(bool isRecording);
107     bool isRecording();
108     void startFrontendInputLoop();
109     void frontendIptvInputThreadLoop(dtv_plugin* interface, dtv_streamer* streamer, void* buf);
110 
111     /**
112      * A dispatcher to read and dispatch input data to all the started filters.
113      * Each filter handler handles the data filtering/output writing/filterEvent updating.
114      * Note that recording filters are not included.
115      */
116     bool startBroadcastFilterDispatcher();
117     void startBroadcastTsFilter(vector<int8_t> data);
118 
119     void sendFrontendInputToRecord(vector<int8_t> data);
120     void sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts);
121     bool startRecordFilterDispatcher();
122 
123     void getDemuxInfo(DemuxInfo* demuxInfo);
124     int32_t getDemuxId();
125     bool isInUse();
126     void setInUse(bool inUse);
127     void setTunerService(std::shared_ptr<Tuner> tuner);
128 
129     /**
130      * Setter for IPTV Reading thread
131      */
132     void setIptvThreadRunning(bool isIptvThreadRunning);
133     /**
134      * Stops IPTV playback reading thread.
135      */
136     void stopIptvFrontendInput();
137 
138   private:
139     // Tuner service
140     std::shared_ptr<Tuner> mTuner;
141 
142     // Frontend source
143     std::shared_ptr<Frontend> mFrontend;
144 
145     // A struct that passes the arguments to a newly created filter thread
146     struct ThreadArgs {
147         Demux* user;
148         int64_t filterId;
149     };
150 
151     static void* __threadLoopFrontend(void* user);
152     void frontendInputThreadLoop();
153 
154     /**
155      * To create a FilterMQ with the next available Filter ID.
156      * Creating Event Flag at the same time.
157      * Add the successfully created/saved FilterMQ into the local list.
158      *
159      * Return false is any of the above processes fails.
160      */
161     void deleteEventFlag();
162     bool readDataFromMQ();
163 
164     int32_t mDemuxId = -1;
165     int32_t mCiCamId;
166     set<int64_t> mPcrFilterIds;
167     /**
168      * Record the last used filter id. Initial value is -1.
169      * Filter Id starts with 0.
170      */
171     int64_t mLastUsedFilterId = -1;
172     /**
173      * Record all the used playback filter Ids.
174      * Any removed filter id should be removed from this set.
175      */
176     set<int64_t> mPlaybackFilterIds;
177     /**
178      * Record all the attached record filter Ids.
179      * Any removed filter id should be removed from this set.
180      */
181     set<int64_t> mRecordFilterIds;
182     /**
183      * A list of created Filter sp.
184      * The array number is the filter ID.
185      */
186     std::map<int64_t, std::shared_ptr<Filter>> mFilters;
187 
188     /**
189      * Local reference to the opened Timer Filter instance.
190      */
191     std::shared_ptr<TimeFilter> mTimeFilter;
192 
193     /**
194      * Local reference to the opened DVR object.
195      */
196     std::shared_ptr<Dvr> mDvrPlayback;
197     std::shared_ptr<Dvr> mDvrRecord;
198 
199     // Thread handlers
200     std::thread mFrontendInputThread;
201     std::thread mDemuxIptvReadThread;
202 
203     // track whether the DVR FMQ for IPTV Playback is full
204     bool mIsIptvDvrFMQFull = false;
205 
206     /**
207      * If a specific filter's writing loop is still running
208      */
209     std::atomic<bool> mFrontendInputThreadRunning;
210     std::atomic<bool> mKeepFetchingDataFromFrontend;
211 
212     /**
213      * Controls IPTV reading thread status
214      */
215     bool mIsIptvReadThreadRunning = false;
216     std::atomic<bool> mIsIptvReadThreadTerminated = false;
217     std::mutex mIsIptvThreadRunningMutex;
218     std::condition_variable mIsIptvThreadRunningCv;
219 
220     /**
221      * If the dvr recording is running.
222      */
223     bool mIsRecording = false;
224     /**
225      * Lock to protect writes to the FMQs
226      */
227     std::mutex mWriteLock;
228 
229     // temp handle single PES filter
230     // TODO handle mulptiple Pes filters
231     int mPesSizeLeft = 0;
232     vector<uint8_t> mPesOutput;
233 
234     const bool DEBUG_DEMUX = false;
235 
236     int32_t mFilterTypes;
237     bool mInUse = false;
238 };
239 
240 }  // namespace tuner
241 }  // namespace tv
242 }  // namespace hardware
243 }  // namespace android
244 }  // namespace aidl
245