blob: a94b4ad38aa89d94e0d8a73f613e640fb7010943 [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() {
Hongguang901aa7b2021-08-26 12:20:56 -070040 close();
Hongguang4092f2f2021-07-08 18:49:12 -070041}
42
43::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
44 ALOGV("%s", __FUNCTION__);
45
Hongguange423acd2021-07-27 16:56:47 -070046 if (mTuner == nullptr) {
47 return ::ndk::ScopedAStatus::fromServiceSpecificError(
48 static_cast<int32_t>(Result::NOT_INITIALIZED));
Hongguang4092f2f2021-07-08 18:49:12 -070049 }
50
Hongguange423acd2021-07-27 16:56:47 -070051 mFrontend = mTuner->getFrontendById(in_frontendId);
Hongguang4092f2f2021-07-08 18:49:12 -070052 if (mFrontend == nullptr) {
Hongguange423acd2021-07-27 16:56:47 -070053 return ::ndk::ScopedAStatus::fromServiceSpecificError(
54 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -070055 }
56
Hongguange423acd2021-07-27 16:56:47 -070057 mTuner->setFrontendAsDemuxSource(in_frontendId, mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -070058
59 return ::ndk::ScopedAStatus::ok();
60}
61
62::ndk::ScopedAStatus Demux::openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
63 const std::shared_ptr<IFilterCallback>& in_cb,
64 std::shared_ptr<IFilter>* _aidl_return) {
65 ALOGV("%s", __FUNCTION__);
66
67 int64_t filterId;
68 filterId = ++mLastUsedFilterId;
69
70 if (in_cb == nullptr) {
71 ALOGW("[Demux] callback can't be null");
72 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -070073 return ::ndk::ScopedAStatus::fromServiceSpecificError(
74 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -070075 }
76
Hongguang Chenff2c6b02021-08-07 00:12:26 +000077 std::shared_ptr<Filter> filter = ndk::SharedRefBase::make<Filter>(
78 in_type, filterId, in_bufferSize, in_cb, this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -070079 if (!filter->createFilterMQ()) {
80 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -070081 return ::ndk::ScopedAStatus::fromServiceSpecificError(
82 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -070083 }
84
85 mFilters[filterId] = filter;
86 if (filter->isPcrFilter()) {
87 mPcrFilterIds.insert(filterId);
88 }
89 bool result = true;
90 if (!filter->isRecordFilter()) {
91 // Only save non-record filters for now. Record filters are saved when the
92 // IDvr.attacheFilter is called.
93 mPlaybackFilterIds.insert(filterId);
94 if (mDvrPlayback != nullptr) {
95 result = mDvrPlayback->addPlaybackFilter(filterId, filter);
96 }
97 }
98
99 if (!result) {
100 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700101 return ::ndk::ScopedAStatus::fromServiceSpecificError(
102 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700103 }
104
105 *_aidl_return = filter;
106 return ::ndk::ScopedAStatus::ok();
107}
108
109::ndk::ScopedAStatus Demux::openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) {
110 ALOGV("%s", __FUNCTION__);
111
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000112 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700113
114 *_aidl_return = mTimeFilter;
115 return ::ndk::ScopedAStatus::ok();
116}
117
118::ndk::ScopedAStatus Demux::getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
119 int32_t* _aidl_return) {
120 ALOGV("%s", __FUNCTION__);
121
122 int64_t id;
123 ::ndk::ScopedAStatus status;
124
125 status = in_filter->getId64Bit(&id);
126 if (!status.isOk()) {
127 ALOGE("[Demux] Can't get filter Id.");
128 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700129 return ::ndk::ScopedAStatus::fromServiceSpecificError(
130 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700131 }
132
133 if (!mFilters[id]->isMediaFilter()) {
134 ALOGE("[Demux] Given filter is not a media filter.");
135 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700136 return ::ndk::ScopedAStatus::fromServiceSpecificError(
137 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700138 }
139
140 if (!mPcrFilterIds.empty()) {
141 // Return the lowest pcr filter id in the default implementation as the av sync id
142 *_aidl_return = *mPcrFilterIds.begin();
143 return ::ndk::ScopedAStatus::ok();
144 }
145
146 ALOGE("[Demux] No PCR filter opened.");
147 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700148 return ::ndk::ScopedAStatus::fromServiceSpecificError(
149 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700150}
151
152::ndk::ScopedAStatus Demux::getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) {
153 ALOGV("%s", __FUNCTION__);
154
155 if (mPcrFilterIds.empty()) {
156 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700157 return ::ndk::ScopedAStatus::fromServiceSpecificError(
158 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700159 }
160 if (in_avSyncHwId != *mPcrFilterIds.begin()) {
161 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700162 return ::ndk::ScopedAStatus::fromServiceSpecificError(
163 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700164 }
165
166 *_aidl_return = -1;
167 return ::ndk::ScopedAStatus::ok();
168}
169
170::ndk::ScopedAStatus Demux::close() {
171 ALOGV("%s", __FUNCTION__);
172
Hongguang901aa7b2021-08-26 12:20:56 -0700173 stopFrontendInput();
174
Hongguang4092f2f2021-07-08 18:49:12 -0700175 set<int64_t>::iterator it;
176 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
177 mDvrPlayback->removePlaybackFilter(*it);
178 }
179 mPlaybackFilterIds.clear();
180 mRecordFilterIds.clear();
181 mFilters.clear();
182 mLastUsedFilterId = -1;
Hongguange423acd2021-07-27 16:56:47 -0700183 mTuner->removeDemux(mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -0700184
185 return ::ndk::ScopedAStatus::ok();
186}
187
188::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
189 const std::shared_ptr<IDvrCallback>& in_cb,
190 std::shared_ptr<IDvr>* _aidl_return) {
191 ALOGV("%s", __FUNCTION__);
192
193 if (in_cb == nullptr) {
194 ALOGW("[Demux] DVR callback can't be null");
195 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700196 return ::ndk::ScopedAStatus::fromServiceSpecificError(
197 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700198 }
199
200 set<int64_t>::iterator it;
201 switch (in_type) {
202 case DvrType::PLAYBACK:
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000203 mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
204 this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700205 if (!mDvrPlayback->createDvrMQ()) {
206 mDvrPlayback = nullptr;
207 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700208 return ::ndk::ScopedAStatus::fromServiceSpecificError(
209 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700210 }
211
212 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
213 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
214 ALOGE("[Demux] Can't get filter info for DVR playback");
215 mDvrPlayback = nullptr;
216 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700217 return ::ndk::ScopedAStatus::fromServiceSpecificError(
218 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700219 }
220 }
221
222 *_aidl_return = mDvrPlayback;
223 return ::ndk::ScopedAStatus::ok();
224 case DvrType::RECORD:
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000225 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
226 this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700227 if (!mDvrRecord->createDvrMQ()) {
228 mDvrRecord = nullptr;
229 *_aidl_return = mDvrRecord;
Hongguange423acd2021-07-27 16:56:47 -0700230 return ::ndk::ScopedAStatus::fromServiceSpecificError(
231 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700232 }
233
234 *_aidl_return = mDvrRecord;
235 return ::ndk::ScopedAStatus::ok();
236 default:
237 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700238 return ::ndk::ScopedAStatus::fromServiceSpecificError(
239 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700240 }
241}
242
243::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
244 ALOGV("%s", __FUNCTION__);
245
246 mCiCamId = in_ciCamId;
247
248 return ::ndk::ScopedAStatus::ok();
249}
250
251::ndk::ScopedAStatus Demux::disconnectCiCam() {
252 ALOGV("%s", __FUNCTION__);
253
254 return ::ndk::ScopedAStatus::ok();
255}
256
257::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
258 ALOGV("%s", __FUNCTION__);
259
260 if (mDvrPlayback != nullptr) {
261 mDvrPlayback->removePlaybackFilter(filterId);
262 }
263 mPlaybackFilterIds.erase(filterId);
264 mRecordFilterIds.erase(filterId);
265 mFilters.erase(filterId);
266
267 return ::ndk::ScopedAStatus::ok();
268}
269
270void Demux::startBroadcastTsFilter(vector<int8_t> data) {
271 set<int64_t>::iterator it;
272 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
273 if (DEBUG_DEMUX) {
274 ALOGW("[Demux] start ts filter pid: %d", pid);
275 }
276 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
277 if (pid == mFilters[*it]->getTpid()) {
278 mFilters[*it]->updateFilterOutput(data);
279 }
280 }
281}
282
283void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
284 set<int64_t>::iterator it;
285 if (DEBUG_DEMUX) {
286 ALOGW("[Demux] update record filter output");
287 }
288 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
289 mFilters[*it]->updateRecordOutput(data);
290 }
291}
292
293void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
294 sendFrontendInputToRecord(data);
295 set<int64_t>::iterator it;
296 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
297 if (pid == mFilters[*it]->getTpid()) {
298 mFilters[*it]->updatePts(pts);
299 }
300 }
301}
302
303bool Demux::startBroadcastFilterDispatcher() {
304 set<int64_t>::iterator it;
305
306 // Handle the output data per filter type
307 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
308 if (!mFilters[*it]->startFilterHandler().isOk()) {
309 return false;
310 }
311 }
312
313 return true;
314}
315
316bool Demux::startRecordFilterDispatcher() {
317 set<int64_t>::iterator it;
318
319 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
320 if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
321 return false;
322 }
323 }
324
325 return true;
326}
327
328::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
329 return mFilters[filterId]->startFilterHandler();
330}
331
332void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
333 mFilters[filterId]->updateFilterOutput(data);
334}
335
336void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
337 updateFilterOutput(filterId, data);
338 mFilters[filterId]->updatePts(pts);
339}
340
341uint16_t Demux::getFilterTpid(int64_t filterId) {
342 return mFilters[filterId]->getTpid();
343}
344
345void Demux::startFrontendInputLoop() {
Hongguang76ca9a82021-10-06 17:11:09 -0700346 ALOGD("[Demux] start frontend on demux");
347 // Stop current Frontend thread loop first, in case the user starts a new
348 // tuning before stopping current tuning.
349 stopFrontendInput();
Hongguang4092f2f2021-07-08 18:49:12 -0700350 mFrontendInputThreadRunning = true;
Hongguang901aa7b2021-08-26 12:20:56 -0700351 mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
Hongguang4092f2f2021-07-08 18:49:12 -0700352}
353
354void Demux::frontendInputThreadLoop() {
355 if (!mFrontendInputThreadRunning) {
356 return;
357 }
358
Hongguang4092f2f2021-07-08 18:49:12 -0700359 if (!mDvrPlayback) {
360 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
361 mFrontendInputThreadRunning = false;
362 return;
363 }
364
365 while (mFrontendInputThreadRunning) {
366 uint32_t efState = 0;
367 ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
368 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
369 true /* retry on spurious wake */);
370 if (status != ::android::OK) {
371 ALOGD("[Demux] wait for data ready on the playback FMQ");
372 continue;
373 }
374 if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
375 DataFormat::ES) {
376 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
377 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
378 break;
379 }
380 continue;
381 }
382 // Our current implementation filter the data and write it into the filter FMQ immediately
383 // after the DATA_READY from the VTS/framework
384 // This is for the non-ES data source, real playback use case handling.
385 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
386 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
387 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
388 break;
389 }
390 }
391
392 mFrontendInputThreadRunning = false;
393 ALOGW("[Demux] Frontend Input thread end.");
394}
395
396void Demux::stopFrontendInput() {
397 ALOGD("[Demux] stop frontend on demux");
398 mKeepFetchingDataFromFrontend = false;
399 mFrontendInputThreadRunning = false;
Hongguang901aa7b2021-08-26 12:20:56 -0700400 if (mFrontendInputThread.joinable()) {
401 mFrontendInputThread.join();
402 }
Hongguang4092f2f2021-07-08 18:49:12 -0700403}
404
405void Demux::setIsRecording(bool isRecording) {
406 mIsRecording = isRecording;
407}
408
409bool Demux::isRecording() {
410 return mIsRecording;
411}
412
Hongguang2ecfc392021-11-23 10:29:15 -0800413binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
414 dprintf(fd, " Demux %d:\n", mDemuxId);
415 dprintf(fd, " mIsRecording %d\n", mIsRecording);
416 {
417 dprintf(fd, " Filters:\n");
418 map<int64_t, std::shared_ptr<Filter>>::iterator it;
419 for (it = mFilters.begin(); it != mFilters.end(); it++) {
420 it->second->dump(fd, args, numArgs);
421 }
422 }
423 {
424 dprintf(fd, " TimeFilter:\n");
425 if (mTimeFilter != nullptr) {
426 mTimeFilter->dump(fd, args, numArgs);
427 }
428 }
429 {
430 dprintf(fd, " DvrPlayback:\n");
431 if (mDvrPlayback != nullptr) {
432 mDvrPlayback->dump(fd, args, numArgs);
433 }
434 }
435 {
436 dprintf(fd, " DvrRecord:\n");
437 if (mDvrRecord != nullptr) {
438 mDvrRecord->dump(fd, args, numArgs);
439 }
440 }
441 return STATUS_OK;
442}
443
Hongguang4092f2f2021-07-08 18:49:12 -0700444bool Demux::attachRecordFilter(int64_t filterId) {
445 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
446 !mFilters[filterId]->isRecordFilter()) {
447 return false;
448 }
449
450 mRecordFilterIds.insert(filterId);
451 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
452
453 return true;
454}
455
456bool Demux::detachRecordFilter(int64_t filterId) {
457 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
458 return false;
459 }
460
461 mRecordFilterIds.erase(filterId);
462 mFilters[filterId]->detachFilterFromRecord();
463
464 return true;
465}
466
467} // namespace tuner
468} // namespace tv
469} // namespace hardware
470} // namespace android
471} // namespace aidl