blob: 60fd89981b95393462f4e9020e70ce15d110cdce [file] [log] [blame]
Hongguang4092f2f2021-07-08 18:49:12 -07001/*
2 * Copyright 2021 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_NDEBUG 0
18#define LOG_TAG "android.hardware.tv.tuner-service.example-Demux"
19
20#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
Hongguange423acd2021-07-27 16:56:47 -070021#include <aidl/android/hardware/tv/tuner/Result.h>
Hongguang4092f2f2021-07-08 18:49:12 -070022
23#include <utils/Log.h>
24#include "Demux.h"
25
26namespace aidl {
27namespace android {
28namespace hardware {
29namespace tv {
30namespace tuner {
31
32#define WAIT_TIMEOUT 3000000000
33
Hongguang Chenff2c6b02021-08-07 00:12:26 +000034Demux::Demux(int32_t demuxId, std::shared_ptr<Tuner> tuner) {
Hongguang4092f2f2021-07-08 18:49:12 -070035 mDemuxId = demuxId;
Hongguange423acd2021-07-27 16:56:47 -070036 mTuner = tuner;
Hongguang4092f2f2021-07-08 18:49:12 -070037}
38
39Demux::~Demux() {
Hongguang4a8ac292022-08-09 14:02:03 -070040 ALOGV("%s", __FUNCTION__);
Hongguang901aa7b2021-08-26 12:20:56 -070041 close();
Hongguang4092f2f2021-07-08 18:49:12 -070042}
43
44::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
45 ALOGV("%s", __FUNCTION__);
46
Hongguange423acd2021-07-27 16:56:47 -070047 if (mTuner == nullptr) {
48 return ::ndk::ScopedAStatus::fromServiceSpecificError(
49 static_cast<int32_t>(Result::NOT_INITIALIZED));
Hongguang4092f2f2021-07-08 18:49:12 -070050 }
51
Hongguange423acd2021-07-27 16:56:47 -070052 mFrontend = mTuner->getFrontendById(in_frontendId);
Hongguang4092f2f2021-07-08 18:49:12 -070053 if (mFrontend == nullptr) {
Hongguange423acd2021-07-27 16:56:47 -070054 return ::ndk::ScopedAStatus::fromServiceSpecificError(
55 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -070056 }
57
Hongguange423acd2021-07-27 16:56:47 -070058 mTuner->setFrontendAsDemuxSource(in_frontendId, mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -070059
60 return ::ndk::ScopedAStatus::ok();
61}
62
63::ndk::ScopedAStatus Demux::openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
64 const std::shared_ptr<IFilterCallback>& in_cb,
65 std::shared_ptr<IFilter>* _aidl_return) {
66 ALOGV("%s", __FUNCTION__);
67
68 int64_t filterId;
69 filterId = ++mLastUsedFilterId;
70
71 if (in_cb == nullptr) {
72 ALOGW("[Demux] callback can't be null");
73 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -070074 return ::ndk::ScopedAStatus::fromServiceSpecificError(
75 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -070076 }
77
Hongguang Chenff2c6b02021-08-07 00:12:26 +000078 std::shared_ptr<Filter> filter = ndk::SharedRefBase::make<Filter>(
79 in_type, filterId, in_bufferSize, in_cb, this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -070080 if (!filter->createFilterMQ()) {
81 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -070082 return ::ndk::ScopedAStatus::fromServiceSpecificError(
83 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -070084 }
85
86 mFilters[filterId] = filter;
87 if (filter->isPcrFilter()) {
88 mPcrFilterIds.insert(filterId);
89 }
90 bool result = true;
91 if (!filter->isRecordFilter()) {
92 // Only save non-record filters for now. Record filters are saved when the
93 // IDvr.attacheFilter is called.
94 mPlaybackFilterIds.insert(filterId);
95 if (mDvrPlayback != nullptr) {
96 result = mDvrPlayback->addPlaybackFilter(filterId, filter);
97 }
98 }
99
100 if (!result) {
101 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700102 return ::ndk::ScopedAStatus::fromServiceSpecificError(
103 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700104 }
105
106 *_aidl_return = filter;
107 return ::ndk::ScopedAStatus::ok();
108}
109
110::ndk::ScopedAStatus Demux::openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) {
111 ALOGV("%s", __FUNCTION__);
112
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000113 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700114
115 *_aidl_return = mTimeFilter;
116 return ::ndk::ScopedAStatus::ok();
117}
118
119::ndk::ScopedAStatus Demux::getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
120 int32_t* _aidl_return) {
121 ALOGV("%s", __FUNCTION__);
122
123 int64_t id;
124 ::ndk::ScopedAStatus status;
125
126 status = in_filter->getId64Bit(&id);
127 if (!status.isOk()) {
128 ALOGE("[Demux] Can't get filter Id.");
129 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700130 return ::ndk::ScopedAStatus::fromServiceSpecificError(
131 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700132 }
133
134 if (!mFilters[id]->isMediaFilter()) {
135 ALOGE("[Demux] Given filter is not a media filter.");
136 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700137 return ::ndk::ScopedAStatus::fromServiceSpecificError(
138 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700139 }
140
141 if (!mPcrFilterIds.empty()) {
142 // Return the lowest pcr filter id in the default implementation as the av sync id
143 *_aidl_return = *mPcrFilterIds.begin();
144 return ::ndk::ScopedAStatus::ok();
145 }
146
147 ALOGE("[Demux] No PCR filter opened.");
148 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700149 return ::ndk::ScopedAStatus::fromServiceSpecificError(
150 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700151}
152
153::ndk::ScopedAStatus Demux::getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) {
154 ALOGV("%s", __FUNCTION__);
155
156 if (mPcrFilterIds.empty()) {
157 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700158 return ::ndk::ScopedAStatus::fromServiceSpecificError(
159 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700160 }
161 if (in_avSyncHwId != *mPcrFilterIds.begin()) {
162 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700163 return ::ndk::ScopedAStatus::fromServiceSpecificError(
164 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700165 }
166
167 *_aidl_return = -1;
168 return ::ndk::ScopedAStatus::ok();
169}
170
171::ndk::ScopedAStatus Demux::close() {
172 ALOGV("%s", __FUNCTION__);
173
Hongguang901aa7b2021-08-26 12:20:56 -0700174 stopFrontendInput();
175
Hongguang4092f2f2021-07-08 18:49:12 -0700176 set<int64_t>::iterator it;
177 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
178 mDvrPlayback->removePlaybackFilter(*it);
179 }
180 mPlaybackFilterIds.clear();
181 mRecordFilterIds.clear();
182 mFilters.clear();
183 mLastUsedFilterId = -1;
Hongguang4a8ac292022-08-09 14:02:03 -0700184 if (mTuner != nullptr) {
185 mTuner->removeDemux(mDemuxId);
186 mTuner = nullptr;
187 }
Hongguang4092f2f2021-07-08 18:49:12 -0700188
189 return ::ndk::ScopedAStatus::ok();
190}
191
192::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
193 const std::shared_ptr<IDvrCallback>& in_cb,
194 std::shared_ptr<IDvr>* _aidl_return) {
195 ALOGV("%s", __FUNCTION__);
196
197 if (in_cb == nullptr) {
198 ALOGW("[Demux] DVR callback can't be null");
199 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700200 return ::ndk::ScopedAStatus::fromServiceSpecificError(
201 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700202 }
203
204 set<int64_t>::iterator it;
205 switch (in_type) {
206 case DvrType::PLAYBACK:
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000207 mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
208 this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700209 if (!mDvrPlayback->createDvrMQ()) {
210 mDvrPlayback = nullptr;
211 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700212 return ::ndk::ScopedAStatus::fromServiceSpecificError(
213 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700214 }
215
216 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
217 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
218 ALOGE("[Demux] Can't get filter info for DVR playback");
219 mDvrPlayback = nullptr;
220 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700221 return ::ndk::ScopedAStatus::fromServiceSpecificError(
222 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700223 }
224 }
225
226 *_aidl_return = mDvrPlayback;
227 return ::ndk::ScopedAStatus::ok();
228 case DvrType::RECORD:
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000229 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
230 this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700231 if (!mDvrRecord->createDvrMQ()) {
232 mDvrRecord = nullptr;
233 *_aidl_return = mDvrRecord;
Hongguange423acd2021-07-27 16:56:47 -0700234 return ::ndk::ScopedAStatus::fromServiceSpecificError(
235 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700236 }
237
238 *_aidl_return = mDvrRecord;
239 return ::ndk::ScopedAStatus::ok();
240 default:
241 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700242 return ::ndk::ScopedAStatus::fromServiceSpecificError(
243 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700244 }
245}
246
247::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
248 ALOGV("%s", __FUNCTION__);
249
250 mCiCamId = in_ciCamId;
251
252 return ::ndk::ScopedAStatus::ok();
253}
254
255::ndk::ScopedAStatus Demux::disconnectCiCam() {
256 ALOGV("%s", __FUNCTION__);
257
258 return ::ndk::ScopedAStatus::ok();
259}
260
261::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
262 ALOGV("%s", __FUNCTION__);
263
264 if (mDvrPlayback != nullptr) {
265 mDvrPlayback->removePlaybackFilter(filterId);
266 }
267 mPlaybackFilterIds.erase(filterId);
268 mRecordFilterIds.erase(filterId);
269 mFilters.erase(filterId);
270
271 return ::ndk::ScopedAStatus::ok();
272}
273
274void Demux::startBroadcastTsFilter(vector<int8_t> data) {
275 set<int64_t>::iterator it;
276 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
277 if (DEBUG_DEMUX) {
278 ALOGW("[Demux] start ts filter pid: %d", pid);
279 }
280 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
281 if (pid == mFilters[*it]->getTpid()) {
282 mFilters[*it]->updateFilterOutput(data);
283 }
284 }
285}
286
287void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
288 set<int64_t>::iterator it;
289 if (DEBUG_DEMUX) {
290 ALOGW("[Demux] update record filter output");
291 }
292 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
293 mFilters[*it]->updateRecordOutput(data);
294 }
295}
296
297void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
298 sendFrontendInputToRecord(data);
299 set<int64_t>::iterator it;
300 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
301 if (pid == mFilters[*it]->getTpid()) {
302 mFilters[*it]->updatePts(pts);
303 }
304 }
305}
306
307bool Demux::startBroadcastFilterDispatcher() {
308 set<int64_t>::iterator it;
309
310 // Handle the output data per filter type
311 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
312 if (!mFilters[*it]->startFilterHandler().isOk()) {
313 return false;
314 }
315 }
316
317 return true;
318}
319
320bool Demux::startRecordFilterDispatcher() {
321 set<int64_t>::iterator it;
322
323 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
324 if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
325 return false;
326 }
327 }
328
329 return true;
330}
331
332::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
333 return mFilters[filterId]->startFilterHandler();
334}
335
336void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
337 mFilters[filterId]->updateFilterOutput(data);
338}
339
340void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
341 updateFilterOutput(filterId, data);
342 mFilters[filterId]->updatePts(pts);
343}
344
345uint16_t Demux::getFilterTpid(int64_t filterId) {
346 return mFilters[filterId]->getTpid();
347}
348
349void Demux::startFrontendInputLoop() {
Hongguang76ca9a82021-10-06 17:11:09 -0700350 ALOGD("[Demux] start frontend on demux");
351 // Stop current Frontend thread loop first, in case the user starts a new
352 // tuning before stopping current tuning.
353 stopFrontendInput();
Hongguang4092f2f2021-07-08 18:49:12 -0700354 mFrontendInputThreadRunning = true;
Hongguang901aa7b2021-08-26 12:20:56 -0700355 mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
Hongguang4092f2f2021-07-08 18:49:12 -0700356}
357
358void Demux::frontendInputThreadLoop() {
359 if (!mFrontendInputThreadRunning) {
360 return;
361 }
362
Hongguang4092f2f2021-07-08 18:49:12 -0700363 if (!mDvrPlayback) {
364 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
365 mFrontendInputThreadRunning = false;
366 return;
367 }
368
369 while (mFrontendInputThreadRunning) {
370 uint32_t efState = 0;
371 ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
372 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
373 true /* retry on spurious wake */);
374 if (status != ::android::OK) {
375 ALOGD("[Demux] wait for data ready on the playback FMQ");
376 continue;
377 }
378 if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
379 DataFormat::ES) {
380 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
381 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
382 break;
383 }
384 continue;
385 }
386 // Our current implementation filter the data and write it into the filter FMQ immediately
387 // after the DATA_READY from the VTS/framework
388 // This is for the non-ES data source, real playback use case handling.
389 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
390 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
391 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
392 break;
393 }
394 }
395
396 mFrontendInputThreadRunning = false;
397 ALOGW("[Demux] Frontend Input thread end.");
398}
399
400void Demux::stopFrontendInput() {
401 ALOGD("[Demux] stop frontend on demux");
402 mKeepFetchingDataFromFrontend = false;
403 mFrontendInputThreadRunning = false;
Hongguang901aa7b2021-08-26 12:20:56 -0700404 if (mFrontendInputThread.joinable()) {
405 mFrontendInputThread.join();
406 }
Hongguang4092f2f2021-07-08 18:49:12 -0700407}
408
409void Demux::setIsRecording(bool isRecording) {
410 mIsRecording = isRecording;
411}
412
413bool Demux::isRecording() {
414 return mIsRecording;
415}
416
Hongguang2ecfc392021-11-23 10:29:15 -0800417binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
418 dprintf(fd, " Demux %d:\n", mDemuxId);
419 dprintf(fd, " mIsRecording %d\n", mIsRecording);
420 {
421 dprintf(fd, " Filters:\n");
422 map<int64_t, std::shared_ptr<Filter>>::iterator it;
423 for (it = mFilters.begin(); it != mFilters.end(); it++) {
424 it->second->dump(fd, args, numArgs);
425 }
426 }
427 {
428 dprintf(fd, " TimeFilter:\n");
429 if (mTimeFilter != nullptr) {
430 mTimeFilter->dump(fd, args, numArgs);
431 }
432 }
433 {
434 dprintf(fd, " DvrPlayback:\n");
435 if (mDvrPlayback != nullptr) {
436 mDvrPlayback->dump(fd, args, numArgs);
437 }
438 }
439 {
440 dprintf(fd, " DvrRecord:\n");
441 if (mDvrRecord != nullptr) {
442 mDvrRecord->dump(fd, args, numArgs);
443 }
444 }
445 return STATUS_OK;
446}
447
Hongguang4092f2f2021-07-08 18:49:12 -0700448bool Demux::attachRecordFilter(int64_t filterId) {
449 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
450 !mFilters[filterId]->isRecordFilter()) {
451 return false;
452 }
453
454 mRecordFilterIds.insert(filterId);
455 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
456
457 return true;
458}
459
460bool Demux::detachRecordFilter(int64_t filterId) {
461 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
462 return false;
463 }
464
465 mRecordFilterIds.erase(filterId);
466 mFilters[filterId]->detachFilterFromRecord();
467
468 return true;
469}
470
471} // namespace tuner
472} // namespace tv
473} // namespace hardware
474} // namespace android
475} // namespace aidl