1 /*
2 * Copyright 2020 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.1-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 mFrontendInputThreadRunning = false;
38 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
39 }
40
setFrontendDataSource(uint32_t frontendId)41 Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
42 ALOGV("%s", __FUNCTION__);
43
44 if (mTunerService == nullptr) {
45 return Result::NOT_INITIALIZED;
46 }
47
48 mFrontend = mTunerService->getFrontendById(frontendId);
49
50 if (mFrontend == nullptr) {
51 return Result::INVALID_STATE;
52 }
53
54 mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
55
56 return Result::SUCCESS;
57 }
58
openFilter(const DemuxFilterType & type,uint32_t bufferSize,const sp<IFilterCallback> & cb,openFilter_cb _hidl_cb)59 Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
60 const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
61 ALOGV("%s", __FUNCTION__);
62
63 uint64_t filterId;
64 filterId = ++mLastUsedFilterId;
65
66 if (cb == nullptr) {
67 ALOGW("[Demux] callback can't be null");
68 _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
69 return Void();
70 }
71
72 sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
73
74 if (!filter->createFilterMQ()) {
75 _hidl_cb(Result::UNKNOWN_ERROR, filter);
76 return Void();
77 }
78
79 mFilters[filterId] = filter;
80 if (filter->isPcrFilter()) {
81 mPcrFilterIds.insert(filterId);
82 }
83 bool result = true;
84 if (!filter->isRecordFilter()) {
85 // Only save non-record filters for now. Record filters are saved when the
86 // IDvr.attacheFilter is called.
87 mPlaybackFilterIds.insert(filterId);
88 if (mDvrPlayback != nullptr) {
89 result = mDvrPlayback->addPlaybackFilter(filterId, filter);
90 }
91 }
92
93 _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
94 return Void();
95 }
96
openTimeFilter(openTimeFilter_cb _hidl_cb)97 Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
98 ALOGV("%s", __FUNCTION__);
99
100 mTimeFilter = new TimeFilter(this);
101
102 _hidl_cb(Result::SUCCESS, mTimeFilter);
103 return Void();
104 }
105
getAvSyncHwId(const sp<IFilter> & filter,getAvSyncHwId_cb _hidl_cb)106 Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
107 ALOGV("%s", __FUNCTION__);
108
109 uint32_t avSyncHwId = -1;
110 uint64_t id;
111 Result status;
112
113 sp<V1_1::IFilter> filter_v1_1 = V1_1::IFilter::castFrom(filter);
114 if (filter_v1_1 != NULL) {
115 filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) {
116 id = filterId;
117 status = result;
118 });
119 } else {
120 filter->getId([&](Result result, uint32_t filterId) {
121 id = filterId;
122 status = result;
123 });
124 }
125
126 if (status != Result::SUCCESS) {
127 ALOGE("[Demux] Can't get filter Id.");
128 _hidl_cb(Result::INVALID_STATE, avSyncHwId);
129 return Void();
130 }
131
132 if (!mFilters[id]->isMediaFilter()) {
133 ALOGE("[Demux] Given filter is not a media filter.");
134 _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
135 return Void();
136 }
137
138 if (!mPcrFilterIds.empty()) {
139 // Return the lowest pcr filter id in the default implementation as the av sync id
140 _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
141 return Void();
142 }
143
144 ALOGE("[Demux] No PCR filter opened.");
145 _hidl_cb(Result::INVALID_STATE, avSyncHwId);
146 return Void();
147 }
148
getAvSyncTime(AvSyncHwId avSyncHwId,getAvSyncTime_cb _hidl_cb)149 Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
150 ALOGV("%s", __FUNCTION__);
151
152 uint64_t avSyncTime = -1;
153 if (mPcrFilterIds.empty()) {
154 _hidl_cb(Result::INVALID_STATE, avSyncTime);
155 return Void();
156 }
157 if (avSyncHwId != *mPcrFilterIds.begin()) {
158 _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime);
159 return Void();
160 }
161
162 _hidl_cb(Result::SUCCESS, avSyncTime);
163 return Void();
164 }
165
close()166 Return<Result> Demux::close() {
167 ALOGV("%s", __FUNCTION__);
168
169 set<uint64_t>::iterator it;
170 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
171 mDvrPlayback->removePlaybackFilter(*it);
172 }
173 mPlaybackFilterIds.clear();
174 mRecordFilterIds.clear();
175 mFilters.clear();
176 mLastUsedFilterId = -1;
177 mTunerService->removeDemux(mDemuxId);
178 mFrontendInputThreadRunning = false;
179 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
180
181 return Result::SUCCESS;
182 }
183
openDvr(DvrType type,uint32_t bufferSize,const sp<IDvrCallback> & cb,openDvr_cb _hidl_cb)184 Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
185 openDvr_cb _hidl_cb) {
186 ALOGV("%s", __FUNCTION__);
187
188 if (cb == nullptr) {
189 ALOGW("[Demux] DVR callback can't be null");
190 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
191 return Void();
192 }
193
194 set<uint64_t>::iterator it;
195 switch (type) {
196 case DvrType::PLAYBACK:
197 mDvrPlayback = new Dvr(type, bufferSize, cb, this);
198 if (!mDvrPlayback->createDvrMQ()) {
199 _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
200 return Void();
201 }
202
203 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
204 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
205 ALOGE("[Demux] Can't get filter info for DVR playback");
206 _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
207 return Void();
208 }
209 }
210
211 _hidl_cb(Result::SUCCESS, mDvrPlayback);
212 return Void();
213 case DvrType::RECORD:
214 mDvrRecord = new Dvr(type, bufferSize, cb, this);
215 if (!mDvrRecord->createDvrMQ()) {
216 _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
217 return Void();
218 }
219
220 _hidl_cb(Result::SUCCESS, mDvrRecord);
221 return Void();
222 default:
223 _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
224 return Void();
225 }
226 }
227
connectCiCam(uint32_t ciCamId)228 Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
229 ALOGV("%s", __FUNCTION__);
230
231 mCiCamId = ciCamId;
232
233 return Result::SUCCESS;
234 }
235
disconnectCiCam()236 Return<Result> Demux::disconnectCiCam() {
237 ALOGV("%s", __FUNCTION__);
238
239 return Result::SUCCESS;
240 }
241
removeFilter(uint64_t filterId)242 Result Demux::removeFilter(uint64_t filterId) {
243 ALOGV("%s", __FUNCTION__);
244
245 if (mDvrPlayback != nullptr) {
246 mDvrPlayback->removePlaybackFilter(filterId);
247 }
248 mPlaybackFilterIds.erase(filterId);
249 mRecordFilterIds.erase(filterId);
250 mFilters.erase(filterId);
251
252 return Result::SUCCESS;
253 }
254
startBroadcastTsFilter(vector<uint8_t> data)255 void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
256 set<uint64_t>::iterator it;
257 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
258 if (DEBUG_DEMUX) {
259 ALOGW("[Demux] start ts filter pid: %d", pid);
260 }
261 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
262 if (pid == mFilters[*it]->getTpid()) {
263 mFilters[*it]->updateFilterOutput(data);
264 }
265 }
266 }
267
sendFrontendInputToRecord(vector<uint8_t> data)268 void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
269 set<uint64_t>::iterator it;
270 if (DEBUG_DEMUX) {
271 ALOGW("[Demux] update record filter output");
272 }
273 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
274 mFilters[*it]->updateRecordOutput(data);
275 }
276 }
277
sendFrontendInputToRecord(vector<uint8_t> data,uint16_t pid,uint64_t pts)278 void Demux::sendFrontendInputToRecord(vector<uint8_t> data, uint16_t pid, uint64_t pts) {
279 sendFrontendInputToRecord(data);
280 set<uint64_t>::iterator it;
281 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
282 if (pid == mFilters[*it]->getTpid()) {
283 mFilters[*it]->updatePts(pts);
284 }
285 }
286 }
287
startBroadcastFilterDispatcher()288 bool Demux::startBroadcastFilterDispatcher() {
289 set<uint64_t>::iterator it;
290
291 // Handle the output data per filter type
292 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
293 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
294 return false;
295 }
296 }
297
298 return true;
299 }
300
startRecordFilterDispatcher()301 bool Demux::startRecordFilterDispatcher() {
302 set<uint64_t>::iterator it;
303
304 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
305 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
306 return false;
307 }
308 }
309
310 return true;
311 }
312
startFilterHandler(uint64_t filterId)313 Result Demux::startFilterHandler(uint64_t filterId) {
314 return mFilters[filterId]->startFilterHandler();
315 }
316
updateFilterOutput(uint64_t filterId,vector<uint8_t> data)317 void Demux::updateFilterOutput(uint64_t filterId, vector<uint8_t> data) {
318 mFilters[filterId]->updateFilterOutput(data);
319 }
320
updateMediaFilterOutput(uint64_t filterId,vector<uint8_t> data,uint64_t pts)321 void Demux::updateMediaFilterOutput(uint64_t filterId, vector<uint8_t> data, uint64_t pts) {
322 updateFilterOutput(filterId, data);
323 mFilters[filterId]->updatePts(pts);
324 }
325
getFilterTpid(uint64_t filterId)326 uint16_t Demux::getFilterTpid(uint64_t filterId) {
327 return mFilters[filterId]->getTpid();
328 }
329
startFrontendInputLoop()330 void Demux::startFrontendInputLoop() {
331 mFrontendInputThreadRunning = true;
332 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
333 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
334 }
335
__threadLoopFrontend(void * user)336 void* Demux::__threadLoopFrontend(void* user) {
337 Demux* const self = static_cast<Demux*>(user);
338 self->frontendInputThreadLoop();
339 return 0;
340 }
341
frontendInputThreadLoop()342 void Demux::frontendInputThreadLoop() {
343 if (!mFrontendInputThreadRunning) {
344 return;
345 }
346
347 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
348 if (!mDvrPlayback) {
349 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
350 mFrontendInputThreadRunning = false;
351 return;
352 }
353
354 while (mFrontendInputThreadRunning) {
355 uint32_t efState = 0;
356 status_t status = mDvrPlayback->getDvrEventFlag()->wait(
357 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
358 true /* retry on spurious wake */);
359 if (status != OK) {
360 ALOGD("[Demux] wait for data ready on the playback FMQ");
361 continue;
362 }
363 if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) {
364 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
365 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
366 break;
367 }
368 continue;
369 }
370 // Our current implementation filter the data and write it into the filter FMQ immediately
371 // after the DATA_READY from the VTS/framework
372 // This is for the non-ES data source, real playback use case handling.
373 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
374 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
375 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
376 break;
377 }
378 }
379
380 mFrontendInputThreadRunning = false;
381 ALOGW("[Demux] Frontend Input thread end.");
382 }
383
stopFrontendInput()384 void Demux::stopFrontendInput() {
385 ALOGD("[Demux] stop frontend on demux");
386 mKeepFetchingDataFromFrontend = false;
387 mFrontendInputThreadRunning = false;
388 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
389 }
390
setIsRecording(bool isRecording)391 void Demux::setIsRecording(bool isRecording) {
392 mIsRecording = isRecording;
393 }
394
isRecording()395 bool Demux::isRecording() {
396 return mIsRecording;
397 }
398
attachRecordFilter(uint64_t filterId)399 bool Demux::attachRecordFilter(uint64_t filterId) {
400 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
401 !mFilters[filterId]->isRecordFilter()) {
402 return false;
403 }
404
405 mRecordFilterIds.insert(filterId);
406 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
407
408 return true;
409 }
410
detachRecordFilter(uint64_t filterId)411 bool Demux::detachRecordFilter(uint64_t filterId) {
412 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
413 return false;
414 }
415
416 mRecordFilterIds.erase(filterId);
417 mFilters[filterId]->detachFilterFromRecord();
418
419 return true;
420 }
421
422 } // namespace implementation
423 } // namespace V1_0
424 } // namespace tuner
425 } // namespace tv
426 } // namespace hardware
427 } // namespace android
428