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