1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "android.hardware.tv.tuner@1.0-Demux"
18
19 #include "Demux.h"
20 #include <utils/Log.h>
21
22 namespace android {
23 namespace hardware {
24 namespace tv {
25 namespace tuner {
26 namespace V1_0 {
27 namespace implementation {
28
29 #define WAIT_TIMEOUT 3000000000
30
Demux(uint32_t demuxId,sp<Tuner> tuner)31 Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
32 mDemuxId = demuxId;
33 mTunerService = tuner;
34 }
35
~Demux()36 Demux::~Demux() {}
37
setFrontendDataSource(uint32_t frontendId)38 Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
39 ALOGV("%s", __FUNCTION__);
40
41 if (mTunerService == nullptr) {
42 return Result::NOT_INITIALIZED;
43 }
44
45 mFrontend = mTunerService->getFrontendById(frontendId);
46
47 if (mFrontend == nullptr) {
48 return Result::INVALID_STATE;
49 }
50
51 mFrontendSourceFile = mFrontend->getSourceFile();
52
53 mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
54
55 return startFrontendInputLoop();
56 }
57
openFilter(const DemuxFilterType & type,uint32_t bufferSize,const sp<IFilterCallback> & cb,openFilter_cb _hidl_cb)58 Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
59 const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
60 ALOGV("%s", __FUNCTION__);
61
62 uint32_t filterId;
63
64 if (!mUnusedFilterIds.empty()) {
65 filterId = *mUnusedFilterIds.begin();
66
67 mUnusedFilterIds.erase(filterId);
68 } else {
69 filterId = ++mLastUsedFilterId;
70 }
71
72 mUsedFilterIds.insert(filterId);
73
74 if (cb == nullptr) {
75 ALOGW("callback can't be null");
76 _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
77 return Void();
78 }
79
80 sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
81
82 if (!filter->createFilterMQ()) {
83 _hidl_cb(Result::UNKNOWN_ERROR, filter);
84 return Void();
85 }
86
87 mFilters[filterId] = filter;
88
89 _hidl_cb(Result::SUCCESS, filter);
90 return Void();
91 }
92
openTimeFilter(openTimeFilter_cb _hidl_cb)93 Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
94 ALOGV("%s", __FUNCTION__);
95
96 sp<TimeFilter> timeFilter = new TimeFilter(this);
97
98 _hidl_cb(Result::SUCCESS, timeFilter);
99 return Void();
100 }
101
getAvSyncHwId(const sp<IFilter> &,getAvSyncHwId_cb _hidl_cb)102 Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
103 ALOGV("%s", __FUNCTION__);
104
105 AvSyncHwId avSyncHwId = 0;
106
107 _hidl_cb(Result::SUCCESS, avSyncHwId);
108 return Void();
109 }
110
getAvSyncTime(AvSyncHwId,getAvSyncTime_cb _hidl_cb)111 Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
112 ALOGV("%s", __FUNCTION__);
113
114 uint64_t avSyncTime = 0;
115
116 _hidl_cb(Result::SUCCESS, avSyncTime);
117 return Void();
118 }
119
close()120 Return<Result> Demux::close() {
121 ALOGV("%s", __FUNCTION__);
122
123 mUnusedFilterIds.clear();
124 mUsedFilterIds.clear();
125 mLastUsedFilterId = -1;
126
127 return Result::SUCCESS;
128 }
129
openDvr(DvrType type,uint32_t bufferSize,const sp<IDvrCallback> & cb,openDvr_cb _hidl_cb)130 Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
131 openDvr_cb _hidl_cb) {
132 ALOGV("%s", __FUNCTION__);
133
134 if (cb == nullptr) {
135 ALOGW("DVR callback can't be null");
136 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
137 return Void();
138 }
139
140 mDvr = new Dvr(type, bufferSize, cb, this);
141
142 if (!mDvr->createDvrMQ()) {
143 _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
144 return Void();
145 }
146
147 _hidl_cb(Result::SUCCESS, mDvr);
148 return Void();
149 }
150
connectCiCam(uint32_t ciCamId)151 Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
152 ALOGV("%s", __FUNCTION__);
153
154 mCiCamId = ciCamId;
155
156 return Result::SUCCESS;
157 }
158
disconnectCiCam()159 Return<Result> Demux::disconnectCiCam() {
160 ALOGV("%s", __FUNCTION__);
161
162 return Result::SUCCESS;
163 }
164
removeFilter(uint32_t filterId)165 Result Demux::removeFilter(uint32_t filterId) {
166 ALOGV("%s", __FUNCTION__);
167
168 // resetFilterRecords(filterId);
169 mUsedFilterIds.erase(filterId);
170 mRecordFilterIds.erase(filterId);
171 mUnusedFilterIds.insert(filterId);
172 mFilters.erase(filterId);
173
174 return Result::SUCCESS;
175 }
176
startBroadcastTsFilter(vector<uint8_t> data)177 void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
178 set<uint32_t>::iterator it;
179 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
180 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
181 if (DEBUG_FILTER) {
182 ALOGW("start ts filter pid: %d", pid);
183 }
184 if (pid == mFilters[*it]->getTpid()) {
185 mFilters[*it]->updateFilterOutput(data);
186 }
187 }
188 }
189
sendFrontendInputToRecord(vector<uint8_t> data)190 void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
191 set<uint32_t>::iterator it;
192 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
193 if (DEBUG_FILTER) {
194 ALOGW("update record filter output");
195 }
196 mFilters[*it]->updateRecordOutput(data);
197 }
198 }
199
startBroadcastFilterDispatcher()200 bool Demux::startBroadcastFilterDispatcher() {
201 set<uint32_t>::iterator it;
202
203 // Handle the output data per filter type
204 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
205 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
206 return false;
207 }
208 }
209
210 return true;
211 }
212
startRecordFilterDispatcher()213 bool Demux::startRecordFilterDispatcher() {
214 set<uint32_t>::iterator it;
215
216 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
217 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
218 return false;
219 }
220 }
221
222 return true;
223 }
224
startFilterHandler(uint32_t filterId)225 Result Demux::startFilterHandler(uint32_t filterId) {
226 return mFilters[filterId]->startFilterHandler();
227 }
228
updateFilterOutput(uint16_t filterId,vector<uint8_t> data)229 void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
230 mFilters[filterId]->updateFilterOutput(data);
231 }
232
getFilterTpid(uint32_t filterId)233 uint16_t Demux::getFilterTpid(uint32_t filterId) {
234 return mFilters[filterId]->getTpid();
235 }
236
startFrontendInputLoop()237 Result Demux::startFrontendInputLoop() {
238 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
239 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
240
241 return Result::SUCCESS;
242 }
243
__threadLoopFrontend(void * user)244 void* Demux::__threadLoopFrontend(void* user) {
245 Demux* const self = static_cast<Demux*>(user);
246 self->frontendInputThreadLoop();
247 return 0;
248 }
249
frontendInputThreadLoop()250 void Demux::frontendInputThreadLoop() {
251 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
252 mFrontendInputThreadRunning = true;
253 mKeepFetchingDataFromFrontend = true;
254
255 // open the stream and get its length
256 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
257 // TODO take the packet size from the frontend setting
258 int packetSize = 188;
259 int writePacketAmount = 6;
260 char* buffer = new char[packetSize];
261 ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
262 if (!inputData.is_open()) {
263 mFrontendInputThreadRunning = false;
264 ALOGW("[Demux] Error %s", strerror(errno));
265 }
266
267 while (mFrontendInputThreadRunning) {
268 // move the stream pointer for packet size * 6 every read until the end
269 while (mKeepFetchingDataFromFrontend) {
270 for (int i = 0; i < writePacketAmount; i++) {
271 inputData.read(buffer, packetSize);
272 if (!inputData) {
273 mKeepFetchingDataFromFrontend = false;
274 mFrontendInputThreadRunning = false;
275 break;
276 }
277 // filter and dispatch filter output
278 vector<uint8_t> byteBuffer;
279 byteBuffer.resize(packetSize);
280 for (int index = 0; index < byteBuffer.size(); index++) {
281 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
282 }
283 if (mIsRecording) {
284 // Feed the data into the Dvr recording input
285 sendFrontendInputToRecord(byteBuffer);
286 } else {
287 // Feed the data into the broadcast demux filter
288 startBroadcastTsFilter(byteBuffer);
289 }
290 }
291 if (mIsRecording) {
292 // Dispatch the data into the broadcasting filters.
293 startRecordFilterDispatcher();
294 } else {
295 // Dispatch the data into the broadcasting filters.
296 startBroadcastFilterDispatcher();
297 }
298 usleep(100);
299 }
300 }
301
302 ALOGW("[Demux] Frontend Input thread end.");
303 delete[] buffer;
304 inputData.close();
305 }
306
stopFrontendInput()307 void Demux::stopFrontendInput() {
308 ALOGD("[Demux] stop frontend on demux");
309 mKeepFetchingDataFromFrontend = false;
310 mFrontendInputThreadRunning = false;
311 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
312 }
313
setIsRecording(bool isRecording)314 void Demux::setIsRecording(bool isRecording) {
315 mIsRecording = isRecording;
316 }
317
attachRecordFilter(int filterId)318 bool Demux::attachRecordFilter(int filterId) {
319 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
320 return false;
321 }
322
323 mRecordFilterIds.insert(filterId);
324 mFilters[filterId]->attachFilterToRecord(mDvr);
325
326 return true;
327 }
328
detachRecordFilter(int filterId)329 bool Demux::detachRecordFilter(int filterId) {
330 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
331 return false;
332 }
333
334 mRecordFilterIds.erase(filterId);
335 mFilters[filterId]->detachFilterFromRecord();
336
337 return true;
338 }
339
340 } // namespace implementation
341 } // namespace V1_0
342 } // namespace tuner
343 } // namespace tv
344 } // namespace hardware
345 } // namespace android
346