blob: b122a050174755f32cfe4893956daf743aebbad5 [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;
166
Amyfd4243a2019-08-16 16:01:27 -0700167 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700168}
169
Amyb4b68012019-10-15 17:38:19 -0700170Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
171 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700172 ALOGV("%s", __FUNCTION__);
173
Amyb4b68012019-10-15 17:38:19 -0700174 if (cb == nullptr) {
Amy Zhang6e8163a2020-04-24 15:41:21 -0700175 ALOGW("[Demux] DVR callback can't be null");
Amyb4b68012019-10-15 17:38:19 -0700176 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700177 return Void();
178 }
179
Amy Zhang6bda6392020-05-26 19:00:46 -0700180 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 }
Amya4885292019-09-06 10:30:53 -0700188
Amy Zhang6bda6392020-05-26 19:00:46 -0700189 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();
Amya4885292019-09-06 10:30:53 -0700211 }
Amya4885292019-09-06 10:30:53 -0700212}
213
Henry Fang89f12f52019-11-05 13:48:59 -0800214Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
215 ALOGV("%s", __FUNCTION__);
216
217 mCiCamId = ciCamId;
218
219 return Result::SUCCESS;
220}
221
222Return<Result> Demux::disconnectCiCam() {
223 ALOGV("%s", __FUNCTION__);
224
225 return Result::SUCCESS;
226}
227
Amyb4b68012019-10-15 17:38:19 -0700228Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700229 ALOGV("%s", __FUNCTION__);
230
Amy Zhang6bda6392020-05-26 19:00:46 -0700231 if (mDvrPlayback != nullptr) {
232 mDvrPlayback->removePlaybackFilter(filterId);
233 }
234 mPlaybackFilterIds.erase(filterId);
Amy5ed13572019-12-11 15:33:51 -0800235 mRecordFilterIds.erase(filterId);
Amyb4b68012019-10-15 17:38:19 -0700236 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700237
Amya4885292019-09-06 10:30:53 -0700238 return Result::SUCCESS;
239}
240
Amy5ed13572019-12-11 15:33:51 -0800241void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
Amy5094ae12019-10-04 18:43:21 -0700242 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700243 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
244 if (DEBUG_DEMUX) {
245 ALOGW("[Demux] start ts filter pid: %d", pid);
246 }
Amy Zhang6bda6392020-05-26 19:00:46 -0700247 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700248 if (pid == mFilters[*it]->getTpid()) {
249 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700250 }
251 }
Amy5094ae12019-10-04 18:43:21 -0700252}
253
Amy5ed13572019-12-11 15:33:51 -0800254void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
255 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700256 if (DEBUG_DEMUX) {
257 ALOGW("[Demux] update record filter output");
258 }
Amy5ed13572019-12-11 15:33:51 -0800259 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
Amy5ed13572019-12-11 15:33:51 -0800260 mFilters[*it]->updateRecordOutput(data);
261 }
262}
263
264bool Demux::startBroadcastFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700265 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700266
267 // Handle the output data per filter type
Amy Zhang6bda6392020-05-26 19:00:46 -0700268 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700269 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
270 return false;
Amya4885292019-09-06 10:30:53 -0700271 }
Amya609d5a2019-08-23 14:38:31 -0700272 }
273
Amyb4b68012019-10-15 17:38:19 -0700274 return true;
Amya609d5a2019-08-23 14:38:31 -0700275}
276
Amy5ed13572019-12-11 15:33:51 -0800277bool 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
Amyb4b68012019-10-15 17:38:19 -0700289Result Demux::startFilterHandler(uint32_t filterId) {
290 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700291}
292
Amyb4b68012019-10-15 17:38:19 -0700293void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
294 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700295}
Amya609d5a2019-08-23 14:38:31 -0700296
Amy Zhang85a9ab32020-06-19 16:44:52 -0700297void Demux::updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts) {
298 updateFilterOutput(filterId, data);
299 mFilters[filterId]->updatePts(pts);
300}
301
Amyb4b68012019-10-15 17:38:19 -0700302uint16_t Demux::getFilterTpid(uint32_t filterId) {
303 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700304}
305
Amy Zhang0fe25be2020-04-08 17:30:52 -0700306void Demux::startFrontendInputLoop() {
Amy5ed13572019-12-11 15:33:51 -0800307 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
308 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
Amy5094ae12019-10-04 18:43:21 -0700309}
310
Amy5ed13572019-12-11 15:33:51 -0800311void* Demux::__threadLoopFrontend(void* user) {
Amy5094ae12019-10-04 18:43:21 -0700312 Demux* const self = static_cast<Demux*>(user);
Amy5ed13572019-12-11 15:33:51 -0800313 self->frontendInputThreadLoop();
Amy5094ae12019-10-04 18:43:21 -0700314 return 0;
315}
316
Amy5ed13572019-12-11 15:33:51 -0800317void Demux::frontendInputThreadLoop() {
318 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
319 mFrontendInputThreadRunning = true;
Amy5094ae12019-10-04 18:43:21 -0700320
Amy5ed13572019-12-11 15:33:51 -0800321 while (mFrontendInputThreadRunning) {
Amy Zhang6bda6392020-05-26 19:00:46 -0700322 uint32_t efState = 0;
323 status_t status = mDvrPlayback->getDvrEventFlag()->wait(
324 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
325 true /* retry on spurious wake */);
326 if (status != OK) {
327 ALOGD("[Demux] wait for data ready on the playback FMQ");
328 continue;
329 }
Amy Zhang85a9ab32020-06-19 16:44:52 -0700330 if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) {
331 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
332 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
333 break;
334 }
335 }
Amy Zhang6bda6392020-05-26 19:00:46 -0700336 // Our current implementation filter the data and write it into the filter FMQ immediately
337 // after the DATA_READY from the VTS/framework
338 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
339 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
340 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
341 break;
Amy5094ae12019-10-04 18:43:21 -0700342 }
343 }
344
Amy Zhang6bda6392020-05-26 19:00:46 -0700345 mFrontendInputThreadRunning = false;
Amy5ed13572019-12-11 15:33:51 -0800346 ALOGW("[Demux] Frontend Input thread end.");
Amy5094ae12019-10-04 18:43:21 -0700347}
348
Amy5ed13572019-12-11 15:33:51 -0800349void Demux::stopFrontendInput() {
Amyb4b68012019-10-15 17:38:19 -0700350 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700351 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800352 mFrontendInputThreadRunning = false;
353 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
354}
355
356void Demux::setIsRecording(bool isRecording) {
357 mIsRecording = isRecording;
358}
359
360bool Demux::attachRecordFilter(int filterId) {
Amy Zhang6bda6392020-05-26 19:00:46 -0700361 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
362 !mFilters[filterId]->isRecordFilter()) {
Amy5ed13572019-12-11 15:33:51 -0800363 return false;
364 }
365
366 mRecordFilterIds.insert(filterId);
Amy Zhang6bda6392020-05-26 19:00:46 -0700367 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
Amy5ed13572019-12-11 15:33:51 -0800368
369 return true;
370}
371
372bool Demux::detachRecordFilter(int filterId) {
Amy Zhang6bda6392020-05-26 19:00:46 -0700373 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
Amy5ed13572019-12-11 15:33:51 -0800374 return false;
375 }
376
377 mRecordFilterIds.erase(filterId);
378 mFilters[filterId]->detachFilterFromRecord();
379
380 return true;
Amy5094ae12019-10-04 18:43:21 -0700381}
382
Amyfd4243a2019-08-16 16:01:27 -0700383} // namespace implementation
384} // namespace V1_0
385} // namespace tuner
386} // namespace tv
387} // namespace hardware
388} // namespace android