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