blob: 9055a43bd801a25dbaa6019584afbb5cfb6633c0 [file] [log] [blame]
Amyfd4243a2019-08-16 16:01:27 -07001/*
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
22namespace android {
23namespace hardware {
24namespace tv {
25namespace tuner {
26namespace V1_0 {
27namespace implementation {
28
Amya609d5a2019-08-23 14:38:31 -070029#define WAIT_TIMEOUT 3000000000
30
Amy5094ae12019-10-04 18:43:21 -070031Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
Amyfd4243a2019-08-16 16:01:27 -070032 mDemuxId = demuxId;
Amy5094ae12019-10-04 18:43:21 -070033 mTunerService = tuner;
Amyfd4243a2019-08-16 16:01:27 -070034}
35
36Demux::~Demux() {}
37
38Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
39 ALOGV("%s", __FUNCTION__);
40
Amy5094ae12019-10-04 18:43:21 -070041 if (mTunerService == nullptr) {
42 return Result::NOT_INITIALIZED;
43 }
Amyfd4243a2019-08-16 16:01:27 -070044
Amy5094ae12019-10-04 18:43:21 -070045 mFrontend = mTunerService->getFrontendById(frontendId);
46
47 if (mFrontend == nullptr) {
48 return Result::INVALID_STATE;
49 }
50
Amy5094ae12019-10-04 18:43:21 -070051 mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
Amy5ed13572019-12-11 15:33:51 -080052
Amy Zhang0fe25be2020-04-08 17:30:52 -070053 return Result::SUCCESS;
Amyfd4243a2019-08-16 16:01:27 -070054}
55
Amyb4b68012019-10-15 17:38:19 -070056Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
57 const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070058 ALOGV("%s", __FUNCTION__);
59
Amya4885292019-09-06 10:30:53 -070060 uint32_t filterId;
Amy Zhangb717eb52020-05-15 18:35:42 -070061 filterId = ++mLastUsedFilterId;
Amya4885292019-09-06 10:30:53 -070062
Amyb4b68012019-10-15 17:38:19 -070063 if (cb == nullptr) {
Amy Zhang6e8163a2020-04-24 15:41:21 -070064 ALOGW("[Demux] callback can't be null");
Amyb4b68012019-10-15 17:38:19 -070065 _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
Amya609d5a2019-08-23 14:38:31 -070066 return Void();
67 }
Amya4885292019-09-06 10:30:53 -070068
Amyb4b68012019-10-15 17:38:19 -070069 sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
Amya609d5a2019-08-23 14:38:31 -070070
Amyb4b68012019-10-15 17:38:19 -070071 if (!filter->createFilterMQ()) {
72 _hidl_cb(Result::UNKNOWN_ERROR, filter);
Amya609d5a2019-08-23 14:38:31 -070073 return Void();
74 }
Amyb4b68012019-10-15 17:38:19 -070075
Amy Zhang6e8163a2020-04-24 15:41:21 -070076 mFilters[filterId] = filter;
Amy Zhangb717eb52020-05-15 18:35:42 -070077 if (filter->isPcrFilter()) {
78 mPcrFilterIds.insert(filterId);
79 }
Amy Zhang6e8163a2020-04-24 15:41:21 -070080 bool result = true;
Amy Zhang6bda6392020-05-26 19:00:46 -070081 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 }
Amy Zhang6e8163a2020-04-24 15:41:21 -070088 }
89
90 _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
Amya609d5a2019-08-23 14:38:31 -070091 return Void();
92}
93
Amyb4b68012019-10-15 17:38:19 -070094Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070095 ALOGV("%s", __FUNCTION__);
96
Amy Zhang7e4859c2020-06-08 15:10:48 -070097 mTimeFilter = new TimeFilter(this);
Amya609d5a2019-08-23 14:38:31 -070098
Amy Zhang7e4859c2020-06-08 15:10:48 -070099 _hidl_cb(Result::SUCCESS, mTimeFilter);
Amya609d5a2019-08-23 14:38:31 -0700100 return Void();
101}
102
Amy Zhangb717eb52020-05-15 18:35:42 -0700103Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700104 ALOGV("%s", __FUNCTION__);
105
Amy Zhangb717eb52020-05-15 18:35:42 -0700106 uint32_t avSyncHwId = -1;
107 int id;
108 Result status;
Amya609d5a2019-08-23 14:38:31 -0700109
Amy Zhangb717eb52020-05-15 18:35:42 -0700110 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()) {
Amy Zhangb717eb52020-05-15 18:35:42 -0700128 // 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
Amy Zhange5a9da22020-06-01 19:12:29 -0700133 ALOGE("[Demux] No PCR filter opened.");
Amy Zhangb717eb52020-05-15 18:35:42 -0700134 _hidl_cb(Result::INVALID_STATE, avSyncHwId);
Amya609d5a2019-08-23 14:38:31 -0700135 return Void();
136}
137
Amy Zhangb717eb52020-05-15 18:35:42 -0700138Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700139 ALOGV("%s", __FUNCTION__);
140
Amy Zhangb717eb52020-05-15 18:35:42 -0700141 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 }
Amya609d5a2019-08-23 14:38:31 -0700150
151 _hidl_cb(Result::SUCCESS, avSyncTime);
152 return Void();
153}
154
Amyfd4243a2019-08-16 16:01:27 -0700155Return<Result> Demux::close() {
156 ALOGV("%s", __FUNCTION__);
157
Amy Zhang6bda6392020-05-26 19:00:46 -0700158 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();
Amya4885292019-09-06 10:30:53 -0700165 mLastUsedFilterId = -1;
Amy Zhang45c12632020-07-16 14:06:25 -0700166 mTunerService->removeDemux(mDemuxId);
Amya4885292019-09-06 10:30:53 -0700167
Amyfd4243a2019-08-16 16:01:27 -0700168 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700169}
170
Amyb4b68012019-10-15 17:38:19 -0700171Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
172 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700173 ALOGV("%s", __FUNCTION__);
174
Amyb4b68012019-10-15 17:38:19 -0700175 if (cb == nullptr) {
Amy Zhang6e8163a2020-04-24 15:41:21 -0700176 ALOGW("[Demux] DVR callback can't be null");
Amyb4b68012019-10-15 17:38:19 -0700177 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700178 return Void();
179 }
180
Amy Zhang6bda6392020-05-26 19:00:46 -0700181 set<uint32_t>::iterator it;
182 switch (type) {
183 case DvrType::PLAYBACK:
184 mDvrPlayback = new Dvr(type, bufferSize, cb, this);
185 if (!mDvrPlayback->createDvrMQ()) {
186 _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
187 return Void();
188 }
Amya4885292019-09-06 10:30:53 -0700189
Amy Zhang6bda6392020-05-26 19:00:46 -0700190 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
191 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
192 ALOGE("[Demux] Can't get filter info for DVR playback");
193 _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
194 return Void();
195 }
196 }
197
198 _hidl_cb(Result::SUCCESS, mDvrPlayback);
199 return Void();
200 case DvrType::RECORD:
201 mDvrRecord = new Dvr(type, bufferSize, cb, this);
202 if (!mDvrRecord->createDvrMQ()) {
203 _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
204 return Void();
205 }
206
207 _hidl_cb(Result::SUCCESS, mDvrRecord);
208 return Void();
209 default:
210 _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
211 return Void();
Amya4885292019-09-06 10:30:53 -0700212 }
Amya4885292019-09-06 10:30:53 -0700213}
214
Henry Fang89f12f52019-11-05 13:48:59 -0800215Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
216 ALOGV("%s", __FUNCTION__);
217
218 mCiCamId = ciCamId;
219
220 return Result::SUCCESS;
221}
222
223Return<Result> Demux::disconnectCiCam() {
224 ALOGV("%s", __FUNCTION__);
225
226 return Result::SUCCESS;
227}
228
Amyb4b68012019-10-15 17:38:19 -0700229Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700230 ALOGV("%s", __FUNCTION__);
231
Amy Zhang6bda6392020-05-26 19:00:46 -0700232 if (mDvrPlayback != nullptr) {
233 mDvrPlayback->removePlaybackFilter(filterId);
234 }
235 mPlaybackFilterIds.erase(filterId);
Amy5ed13572019-12-11 15:33:51 -0800236 mRecordFilterIds.erase(filterId);
Amyb4b68012019-10-15 17:38:19 -0700237 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700238
Amya4885292019-09-06 10:30:53 -0700239 return Result::SUCCESS;
240}
241
Amy5ed13572019-12-11 15:33:51 -0800242void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
Amy5094ae12019-10-04 18:43:21 -0700243 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700244 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
245 if (DEBUG_DEMUX) {
246 ALOGW("[Demux] start ts filter pid: %d", pid);
247 }
Amy Zhang6bda6392020-05-26 19:00:46 -0700248 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700249 if (pid == mFilters[*it]->getTpid()) {
250 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700251 }
252 }
Amy5094ae12019-10-04 18:43:21 -0700253}
254
Amy5ed13572019-12-11 15:33:51 -0800255void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
256 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700257 if (DEBUG_DEMUX) {
258 ALOGW("[Demux] update record filter output");
259 }
Amy5ed13572019-12-11 15:33:51 -0800260 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
Amy5ed13572019-12-11 15:33:51 -0800261 mFilters[*it]->updateRecordOutput(data);
262 }
263}
264
265bool Demux::startBroadcastFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700266 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700267
268 // Handle the output data per filter type
Amy Zhang6bda6392020-05-26 19:00:46 -0700269 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700270 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
271 return false;
Amya4885292019-09-06 10:30:53 -0700272 }
Amya609d5a2019-08-23 14:38:31 -0700273 }
274
Amyb4b68012019-10-15 17:38:19 -0700275 return true;
Amya609d5a2019-08-23 14:38:31 -0700276}
277
Amy5ed13572019-12-11 15:33:51 -0800278bool Demux::startRecordFilterDispatcher() {
279 set<uint32_t>::iterator it;
280
281 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
282 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
283 return false;
284 }
285 }
286
287 return true;
288}
289
Amyb4b68012019-10-15 17:38:19 -0700290Result Demux::startFilterHandler(uint32_t filterId) {
291 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700292}
293
Amyb4b68012019-10-15 17:38:19 -0700294void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
295 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700296}
Amya609d5a2019-08-23 14:38:31 -0700297
Amy Zhang85a9ab32020-06-19 16:44:52 -0700298void Demux::updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts) {
299 updateFilterOutput(filterId, data);
300 mFilters[filterId]->updatePts(pts);
301}
302
Amyb4b68012019-10-15 17:38:19 -0700303uint16_t Demux::getFilterTpid(uint32_t filterId) {
304 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700305}
306
Amy Zhang0fe25be2020-04-08 17:30:52 -0700307void Demux::startFrontendInputLoop() {
Amy5ed13572019-12-11 15:33:51 -0800308 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
309 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
Amy5094ae12019-10-04 18:43:21 -0700310}
311
Amy5ed13572019-12-11 15:33:51 -0800312void* Demux::__threadLoopFrontend(void* user) {
Amy5094ae12019-10-04 18:43:21 -0700313 Demux* const self = static_cast<Demux*>(user);
Amy5ed13572019-12-11 15:33:51 -0800314 self->frontendInputThreadLoop();
Amy5094ae12019-10-04 18:43:21 -0700315 return 0;
316}
317
Amy5ed13572019-12-11 15:33:51 -0800318void Demux::frontendInputThreadLoop() {
319 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
320 mFrontendInputThreadRunning = true;
Amy5094ae12019-10-04 18:43:21 -0700321
Amy Zhang45c12632020-07-16 14:06:25 -0700322 if (!mDvrPlayback) {
323 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
324 mFrontendInputThreadRunning = false;
325 return;
326 }
327
Amy5ed13572019-12-11 15:33:51 -0800328 while (mFrontendInputThreadRunning) {
Amy Zhang6bda6392020-05-26 19:00:46 -0700329 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 }
Amy Zhang85a9ab32020-06-19 16:44:52 -0700337 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 }
Amy Zhang6bda6392020-05-26 19:00:46 -0700343 // 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;
Amy5094ae12019-10-04 18:43:21 -0700349 }
350 }
351
Amy Zhang6bda6392020-05-26 19:00:46 -0700352 mFrontendInputThreadRunning = false;
Amy5ed13572019-12-11 15:33:51 -0800353 ALOGW("[Demux] Frontend Input thread end.");
Amy5094ae12019-10-04 18:43:21 -0700354}
355
Amy5ed13572019-12-11 15:33:51 -0800356void Demux::stopFrontendInput() {
Amyb4b68012019-10-15 17:38:19 -0700357 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700358 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800359 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(int filterId) {
Amy Zhang6bda6392020-05-26 19:00:46 -0700368 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
369 !mFilters[filterId]->isRecordFilter()) {
Amy5ed13572019-12-11 15:33:51 -0800370 return false;
371 }
372
373 mRecordFilterIds.insert(filterId);
Amy Zhang6bda6392020-05-26 19:00:46 -0700374 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
Amy5ed13572019-12-11 15:33:51 -0800375
376 return true;
377}
378
379bool Demux::detachRecordFilter(int filterId) {
Amy Zhang6bda6392020-05-26 19:00:46 -0700380 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
Amy5ed13572019-12-11 15:33:51 -0800381 return false;
382 }
383
384 mRecordFilterIds.erase(filterId);
385 mFilters[filterId]->detachFilterFromRecord();
386
387 return true;
Amy5094ae12019-10-04 18:43:21 -0700388}
389
Amyfd4243a2019-08-16 16:01:27 -0700390} // namespace implementation
391} // namespace V1_0
392} // namespace tuner
393} // namespace tv
394} // namespace hardware
395} // namespace android