blob: 11e7131220afccb54d249c4f584445715efb2bc3 [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
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080034Demux::Demux(int32_t demuxId, uint32_t filterTypes) {
Hongguang4092f2f2021-07-08 18:49:12 -070035 mDemuxId = demuxId;
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080036 mFilterTypes = filterTypes;
37}
38
39void Demux::setTunerService(std::shared_ptr<Tuner> tuner) {
Hongguange423acd2021-07-27 16:56:47 -070040 mTuner = tuner;
Hongguang4092f2f2021-07-08 18:49:12 -070041}
42
43Demux::~Demux() {
Hongguang4a8ac292022-08-09 14:02:03 -070044 ALOGV("%s", __FUNCTION__);
Hongguang901aa7b2021-08-26 12:20:56 -070045 close();
Hongguang4092f2f2021-07-08 18:49:12 -070046}
47
48::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
49 ALOGV("%s", __FUNCTION__);
50
Hongguange423acd2021-07-27 16:56:47 -070051 if (mTuner == nullptr) {
52 return ::ndk::ScopedAStatus::fromServiceSpecificError(
53 static_cast<int32_t>(Result::NOT_INITIALIZED));
Hongguang4092f2f2021-07-08 18:49:12 -070054 }
55
Hongguange423acd2021-07-27 16:56:47 -070056 mFrontend = mTuner->getFrontendById(in_frontendId);
Hongguang4092f2f2021-07-08 18:49:12 -070057 if (mFrontend == nullptr) {
Hongguange423acd2021-07-27 16:56:47 -070058 return ::ndk::ScopedAStatus::fromServiceSpecificError(
59 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -070060 }
61
Hongguange423acd2021-07-27 16:56:47 -070062 mTuner->setFrontendAsDemuxSource(in_frontendId, mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -070063
64 return ::ndk::ScopedAStatus::ok();
65}
66
67::ndk::ScopedAStatus Demux::openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
68 const std::shared_ptr<IFilterCallback>& in_cb,
69 std::shared_ptr<IFilter>* _aidl_return) {
70 ALOGV("%s", __FUNCTION__);
71
72 int64_t filterId;
73 filterId = ++mLastUsedFilterId;
74
75 if (in_cb == nullptr) {
76 ALOGW("[Demux] callback can't be null");
77 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -070078 return ::ndk::ScopedAStatus::fromServiceSpecificError(
79 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -070080 }
81
Hongguang Chenff2c6b02021-08-07 00:12:26 +000082 std::shared_ptr<Filter> filter = ndk::SharedRefBase::make<Filter>(
83 in_type, filterId, in_bufferSize, in_cb, this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -070084 if (!filter->createFilterMQ()) {
85 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -070086 return ::ndk::ScopedAStatus::fromServiceSpecificError(
87 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -070088 }
89
90 mFilters[filterId] = filter;
91 if (filter->isPcrFilter()) {
92 mPcrFilterIds.insert(filterId);
93 }
94 bool result = true;
95 if (!filter->isRecordFilter()) {
96 // Only save non-record filters for now. Record filters are saved when the
97 // IDvr.attacheFilter is called.
98 mPlaybackFilterIds.insert(filterId);
99 if (mDvrPlayback != nullptr) {
100 result = mDvrPlayback->addPlaybackFilter(filterId, filter);
101 }
102 }
103
104 if (!result) {
105 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700106 return ::ndk::ScopedAStatus::fromServiceSpecificError(
107 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700108 }
109
110 *_aidl_return = filter;
111 return ::ndk::ScopedAStatus::ok();
112}
113
114::ndk::ScopedAStatus Demux::openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) {
115 ALOGV("%s", __FUNCTION__);
116
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000117 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700118
119 *_aidl_return = mTimeFilter;
120 return ::ndk::ScopedAStatus::ok();
121}
122
123::ndk::ScopedAStatus Demux::getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
124 int32_t* _aidl_return) {
125 ALOGV("%s", __FUNCTION__);
126
127 int64_t id;
128 ::ndk::ScopedAStatus status;
129
130 status = in_filter->getId64Bit(&id);
131 if (!status.isOk()) {
132 ALOGE("[Demux] Can't get filter Id.");
133 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700134 return ::ndk::ScopedAStatus::fromServiceSpecificError(
135 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700136 }
137
138 if (!mFilters[id]->isMediaFilter()) {
139 ALOGE("[Demux] Given filter is not a media filter.");
140 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700141 return ::ndk::ScopedAStatus::fromServiceSpecificError(
142 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700143 }
144
145 if (!mPcrFilterIds.empty()) {
146 // Return the lowest pcr filter id in the default implementation as the av sync id
147 *_aidl_return = *mPcrFilterIds.begin();
148 return ::ndk::ScopedAStatus::ok();
149 }
150
151 ALOGE("[Demux] No PCR filter opened.");
152 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700153 return ::ndk::ScopedAStatus::fromServiceSpecificError(
154 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700155}
156
157::ndk::ScopedAStatus Demux::getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) {
158 ALOGV("%s", __FUNCTION__);
159
160 if (mPcrFilterIds.empty()) {
161 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700162 return ::ndk::ScopedAStatus::fromServiceSpecificError(
163 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700164 }
165 if (in_avSyncHwId != *mPcrFilterIds.begin()) {
166 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700167 return ::ndk::ScopedAStatus::fromServiceSpecificError(
168 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700169 }
170
171 *_aidl_return = -1;
172 return ::ndk::ScopedAStatus::ok();
173}
174
175::ndk::ScopedAStatus Demux::close() {
176 ALOGV("%s", __FUNCTION__);
177
Hongguang901aa7b2021-08-26 12:20:56 -0700178 stopFrontendInput();
179
Hongguang4092f2f2021-07-08 18:49:12 -0700180 set<int64_t>::iterator it;
181 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
182 mDvrPlayback->removePlaybackFilter(*it);
183 }
184 mPlaybackFilterIds.clear();
185 mRecordFilterIds.clear();
186 mFilters.clear();
187 mLastUsedFilterId = -1;
Hongguang4a8ac292022-08-09 14:02:03 -0700188 if (mTuner != nullptr) {
189 mTuner->removeDemux(mDemuxId);
190 mTuner = nullptr;
191 }
Hongguang4092f2f2021-07-08 18:49:12 -0700192
193 return ::ndk::ScopedAStatus::ok();
194}
195
196::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
197 const std::shared_ptr<IDvrCallback>& in_cb,
198 std::shared_ptr<IDvr>* _aidl_return) {
199 ALOGV("%s", __FUNCTION__);
200
201 if (in_cb == nullptr) {
202 ALOGW("[Demux] DVR callback can't be null");
203 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700204 return ::ndk::ScopedAStatus::fromServiceSpecificError(
205 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700206 }
207
208 set<int64_t>::iterator it;
209 switch (in_type) {
210 case DvrType::PLAYBACK:
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000211 mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
212 this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700213 if (!mDvrPlayback->createDvrMQ()) {
214 mDvrPlayback = nullptr;
215 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700216 return ::ndk::ScopedAStatus::fromServiceSpecificError(
217 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700218 }
219
220 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
221 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
222 ALOGE("[Demux] Can't get filter info for DVR playback");
223 mDvrPlayback = nullptr;
224 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700225 return ::ndk::ScopedAStatus::fromServiceSpecificError(
226 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700227 }
228 }
229
230 *_aidl_return = mDvrPlayback;
231 return ::ndk::ScopedAStatus::ok();
232 case DvrType::RECORD:
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000233 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
234 this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700235 if (!mDvrRecord->createDvrMQ()) {
236 mDvrRecord = nullptr;
237 *_aidl_return = mDvrRecord;
Hongguange423acd2021-07-27 16:56:47 -0700238 return ::ndk::ScopedAStatus::fromServiceSpecificError(
239 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700240 }
241
242 *_aidl_return = mDvrRecord;
243 return ::ndk::ScopedAStatus::ok();
244 default:
245 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700246 return ::ndk::ScopedAStatus::fromServiceSpecificError(
247 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700248 }
249}
250
251::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
252 ALOGV("%s", __FUNCTION__);
253
254 mCiCamId = in_ciCamId;
255
256 return ::ndk::ScopedAStatus::ok();
257}
258
259::ndk::ScopedAStatus Demux::disconnectCiCam() {
260 ALOGV("%s", __FUNCTION__);
261
262 return ::ndk::ScopedAStatus::ok();
263}
264
265::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
266 ALOGV("%s", __FUNCTION__);
267
268 if (mDvrPlayback != nullptr) {
269 mDvrPlayback->removePlaybackFilter(filterId);
270 }
271 mPlaybackFilterIds.erase(filterId);
272 mRecordFilterIds.erase(filterId);
273 mFilters.erase(filterId);
274
275 return ::ndk::ScopedAStatus::ok();
276}
277
278void Demux::startBroadcastTsFilter(vector<int8_t> data) {
279 set<int64_t>::iterator it;
280 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
281 if (DEBUG_DEMUX) {
282 ALOGW("[Demux] start ts filter pid: %d", pid);
283 }
284 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
285 if (pid == mFilters[*it]->getTpid()) {
286 mFilters[*it]->updateFilterOutput(data);
287 }
288 }
289}
290
291void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
292 set<int64_t>::iterator it;
293 if (DEBUG_DEMUX) {
294 ALOGW("[Demux] update record filter output");
295 }
296 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
297 mFilters[*it]->updateRecordOutput(data);
298 }
299}
300
301void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
302 sendFrontendInputToRecord(data);
303 set<int64_t>::iterator it;
304 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
305 if (pid == mFilters[*it]->getTpid()) {
306 mFilters[*it]->updatePts(pts);
307 }
308 }
309}
310
311bool Demux::startBroadcastFilterDispatcher() {
312 set<int64_t>::iterator it;
313
314 // Handle the output data per filter type
315 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
316 if (!mFilters[*it]->startFilterHandler().isOk()) {
317 return false;
318 }
319 }
320
321 return true;
322}
323
324bool Demux::startRecordFilterDispatcher() {
325 set<int64_t>::iterator it;
326
327 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
328 if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
329 return false;
330 }
331 }
332
333 return true;
334}
335
336::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
337 return mFilters[filterId]->startFilterHandler();
338}
339
340void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
341 mFilters[filterId]->updateFilterOutput(data);
342}
343
344void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
345 updateFilterOutput(filterId, data);
346 mFilters[filterId]->updatePts(pts);
347}
348
349uint16_t Demux::getFilterTpid(int64_t filterId) {
350 return mFilters[filterId]->getTpid();
351}
352
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800353int32_t Demux::getDemuxId() {
354 return mDemuxId;
355}
356
357bool Demux::isInUse() {
358 return mInUse;
359}
360
361void Demux::setInUse(bool inUse) {
362 mInUse = inUse;
363}
364
365void Demux::getDemuxInfo(DemuxInfo* demuxInfo) {
366 *demuxInfo = {.filterTypes = mFilterTypes};
367}
368
Hongguang4092f2f2021-07-08 18:49:12 -0700369void Demux::startFrontendInputLoop() {
Hongguang76ca9a82021-10-06 17:11:09 -0700370 ALOGD("[Demux] start frontend on demux");
371 // Stop current Frontend thread loop first, in case the user starts a new
372 // tuning before stopping current tuning.
373 stopFrontendInput();
Hongguang4092f2f2021-07-08 18:49:12 -0700374 mFrontendInputThreadRunning = true;
Hongguang901aa7b2021-08-26 12:20:56 -0700375 mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
Hongguang4092f2f2021-07-08 18:49:12 -0700376}
377
378void Demux::frontendInputThreadLoop() {
379 if (!mFrontendInputThreadRunning) {
380 return;
381 }
382
Hongguang4092f2f2021-07-08 18:49:12 -0700383 if (!mDvrPlayback) {
384 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
385 mFrontendInputThreadRunning = false;
386 return;
387 }
388
389 while (mFrontendInputThreadRunning) {
390 uint32_t efState = 0;
391 ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
392 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
393 true /* retry on spurious wake */);
394 if (status != ::android::OK) {
395 ALOGD("[Demux] wait for data ready on the playback FMQ");
396 continue;
397 }
398 if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
399 DataFormat::ES) {
400 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
401 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
402 break;
403 }
404 continue;
405 }
406 // Our current implementation filter the data and write it into the filter FMQ immediately
407 // after the DATA_READY from the VTS/framework
408 // This is for the non-ES data source, real playback use case handling.
409 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
410 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
411 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
412 break;
413 }
414 }
415
416 mFrontendInputThreadRunning = false;
417 ALOGW("[Demux] Frontend Input thread end.");
418}
419
420void Demux::stopFrontendInput() {
421 ALOGD("[Demux] stop frontend on demux");
422 mKeepFetchingDataFromFrontend = false;
423 mFrontendInputThreadRunning = false;
Hongguang901aa7b2021-08-26 12:20:56 -0700424 if (mFrontendInputThread.joinable()) {
425 mFrontendInputThread.join();
426 }
Hongguang4092f2f2021-07-08 18:49:12 -0700427}
428
429void Demux::setIsRecording(bool isRecording) {
430 mIsRecording = isRecording;
431}
432
433bool Demux::isRecording() {
434 return mIsRecording;
435}
436
Hongguang2ecfc392021-11-23 10:29:15 -0800437binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
438 dprintf(fd, " Demux %d:\n", mDemuxId);
439 dprintf(fd, " mIsRecording %d\n", mIsRecording);
440 {
441 dprintf(fd, " Filters:\n");
442 map<int64_t, std::shared_ptr<Filter>>::iterator it;
443 for (it = mFilters.begin(); it != mFilters.end(); it++) {
444 it->second->dump(fd, args, numArgs);
445 }
446 }
447 {
448 dprintf(fd, " TimeFilter:\n");
449 if (mTimeFilter != nullptr) {
450 mTimeFilter->dump(fd, args, numArgs);
451 }
452 }
453 {
454 dprintf(fd, " DvrPlayback:\n");
455 if (mDvrPlayback != nullptr) {
456 mDvrPlayback->dump(fd, args, numArgs);
457 }
458 }
459 {
460 dprintf(fd, " DvrRecord:\n");
461 if (mDvrRecord != nullptr) {
462 mDvrRecord->dump(fd, args, numArgs);
463 }
464 }
465 return STATUS_OK;
466}
467
Hongguang4092f2f2021-07-08 18:49:12 -0700468bool Demux::attachRecordFilter(int64_t filterId) {
469 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
470 !mFilters[filterId]->isRecordFilter()) {
471 return false;
472 }
473
474 mRecordFilterIds.insert(filterId);
475 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
476
477 return true;
478}
479
480bool Demux::detachRecordFilter(int64_t filterId) {
481 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
482 return false;
483 }
484
485 mRecordFilterIds.erase(filterId);
486 mFilters[filterId]->detachFilterFromRecord();
487
488 return true;
489}
490
491} // namespace tuner
492} // namespace tv
493} // namespace hardware
494} // namespace android
495} // namespace aidl