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