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/BnDvr.h>
20 #include <aidl/android/hardware/tv/tuner/RecordStatus.h>
21 
22 #include <fmq/AidlMessageQueue.h>
23 #include <math.h>
24 #include <atomic>
25 #include <set>
26 #include <thread>
27 #include "Demux.h"
28 #include "Frontend.h"
29 #include "Tuner.h"
30 
31 using namespace std;
32 
33 namespace aidl {
34 namespace android {
35 namespace hardware {
36 namespace tv {
37 namespace tuner {
38 
39 using ::aidl::android::hardware::common::fmq::MQDescriptor;
40 using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
41 using ::android::AidlMessageQueue;
42 using ::android::hardware::EventFlag;
43 
44 using DvrMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
45 
46 const int DVR_WRITE_SUCCESS = 0;
47 const int DVR_WRITE_FAILURE_REASON_FMQ_FULL = 1;
48 const int DVR_WRITE_FAILURE_REASON_UNKNOWN = 2;
49 
50 const int TS_SIZE = 188;
51 const int IPTV_BUFFER_SIZE = TS_SIZE * 7 * 8;  // defined in service_streamer_udp in cbs v3 project
52 
53 // Thresholds are defined to indicate how full the buffers are.
54 const double HIGH_THRESHOLD_PERCENT = 0.90;
55 const double LOW_THRESHOLD_PERCENT = 0.15;
56 const int IPTV_PLAYBACK_STATUS_THRESHOLD_HIGH = IPTV_BUFFER_SIZE * HIGH_THRESHOLD_PERCENT;
57 const int IPTV_PLAYBACK_STATUS_THRESHOLD_LOW = IPTV_BUFFER_SIZE * LOW_THRESHOLD_PERCENT;
58 
59 struct MediaEsMetaData {
60     bool isAudio;
61     int startIndex;
62     int len;
63     int pts;
64 };
65 
66 class Demux;
67 class Filter;
68 class Frontend;
69 class Tuner;
70 
71 class Dvr : public BnDvr {
72   public:
73     Dvr(DvrType type, uint32_t bufferSize, const std::shared_ptr<IDvrCallback>& cb,
74         std::shared_ptr<Demux> demux);
75     ~Dvr();
76 
77     ::ndk::ScopedAStatus getQueueDesc(
78             MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue) override;
79     ::ndk::ScopedAStatus configure(const DvrSettings& in_settings) override;
80     ::ndk::ScopedAStatus attachFilter(const std::shared_ptr<IFilter>& in_filter) override;
81     ::ndk::ScopedAStatus detachFilter(const std::shared_ptr<IFilter>& in_filter) override;
82     ::ndk::ScopedAStatus start() override;
83     ::ndk::ScopedAStatus stop() override;
84     ::ndk::ScopedAStatus flush() override;
85     ::ndk::ScopedAStatus close() override;
86     ::ndk::ScopedAStatus setStatusCheckIntervalHint(int64_t in_milliseconds) override;
87 
88     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
89 
90     /**
91      * To create a DvrMQ and its Event Flag.
92      *
93      * Return false is any of the above processes fails.
94      */
95     bool createDvrMQ();
96     int writePlaybackFMQ(void* buf, size_t size);
97     bool writeRecordFMQ(const std::vector<int8_t>& data);
98     bool addPlaybackFilter(int64_t filterId, std::shared_ptr<Filter> filter);
99     bool removePlaybackFilter(int64_t filterId);
100     bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording);
101     bool processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording);
102     bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording);
103     EventFlag* getDvrEventFlag();
getSettings()104     DvrSettings getSettings() { return mDvrSettings; }
105 
106   private:
107     // Demux service
108     std::shared_ptr<Demux> mDemux;
109 
110     DvrType mType;
111     uint32_t mBufferSize;
112     std::shared_ptr<IDvrCallback> mCallback;
113     std::map<int64_t, std::shared_ptr<Filter>> mFilters;
114 
115     void deleteEventFlag();
116     bool readDataFromMQ();
117     void getMetaDataValue(int& index, int8_t* dataOutputBuffer, int& value);
118     void maySendPlaybackStatusCallback();
119     void maySendIptvPlaybackStatusCallback();
120     void maySendRecordStatusCallback();
121     PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
122                                              int64_t highThreshold, int64_t lowThreshold);
123     RecordStatus checkRecordStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
124                                          int64_t highThreshold, int64_t lowThreshold);
125     /**
126      * A dispatcher to read and dispatch input data to all the started filters.
127      * Each filter handler handles the data filtering/output writing/filterEvent updating.
128      */
129     void startTpidFilter(vector<int8_t> data);
130     void playbackThreadLoop();
131 
132     unique_ptr<DvrMQ> mDvrMQ;
133     EventFlag* mDvrEventFlag;
134     /**
135      * Demux callbacks used on filter events or IO buffer status
136      */
137     bool mDvrConfigured = false;
138     DvrSettings mDvrSettings;
139 
140     // Thread handlers
141     std::thread mDvrThread;
142 
143     // FMQ status local records
144     PlaybackStatus mPlaybackStatus;
145     RecordStatus mRecordStatus;
146     /**
147      * If a specific filter's writing loop is still running
148      */
149     std::atomic<bool> mDvrThreadRunning;
150 
151     /**
152      * Lock to protect writes to the FMQs
153      */
154     std::mutex mWriteLock;
155     /**
156      * Lock to protect writes to the input status
157      */
158     std::mutex mPlaybackStatusLock;
159     std::mutex mRecordStatusLock;
160 
161     const bool DEBUG_DVR = false;
162 };
163 
164 }  // namespace tuner
165 }  // namespace tv
166 }  // namespace hardware
167 }  // namespace android
168 }  // namespace aidl
169