blob: d5a653b3e6b137e8296f2d736a248784eae42f5d [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
34Demux::Demux(int32_t demuxId, std::shared_ptr<Tuner> tuner) {
35 mDemuxId = demuxId;
Hongguange423acd2021-07-27 16:56:47 -070036 mTuner = tuner;
Hongguang4092f2f2021-07-08 18:49:12 -070037}
38
39Demux::~Demux() {
40 mFrontendInputThreadRunning = false;
41 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
42}
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
78 std::shared_ptr<Filter> filter =
79 ndk::SharedRefBase::make<Filter>(in_type, filterId, in_bufferSize, in_cb, ref<Demux>());
80 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
113 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(ref<Demux>());
114
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
174 set<int64_t>::iterator it;
175 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
176 mDvrPlayback->removePlaybackFilter(*it);
177 }
178 mPlaybackFilterIds.clear();
179 mRecordFilterIds.clear();
180 mFilters.clear();
181 mLastUsedFilterId = -1;
Hongguange423acd2021-07-27 16:56:47 -0700182 mTuner->removeDemux(mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -0700183 mFrontendInputThreadRunning = false;
184 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
185
186 return ::ndk::ScopedAStatus::ok();
187}
188
189::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
190 const std::shared_ptr<IDvrCallback>& in_cb,
191 std::shared_ptr<IDvr>* _aidl_return) {
192 ALOGV("%s", __FUNCTION__);
193
194 if (in_cb == nullptr) {
195 ALOGW("[Demux] DVR callback can't be null");
196 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700197 return ::ndk::ScopedAStatus::fromServiceSpecificError(
198 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700199 }
200
201 set<int64_t>::iterator it;
202 switch (in_type) {
203 case DvrType::PLAYBACK:
204 mDvrPlayback =
205 ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb, ref<Demux>());
206 if (!mDvrPlayback->createDvrMQ()) {
207 mDvrPlayback = nullptr;
208 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700209 return ::ndk::ScopedAStatus::fromServiceSpecificError(
210 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700211 }
212
213 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
214 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
215 ALOGE("[Demux] Can't get filter info for DVR playback");
216 mDvrPlayback = nullptr;
217 *_aidl_return = mDvrPlayback;
Hongguange423acd2021-07-27 16:56:47 -0700218 return ::ndk::ScopedAStatus::fromServiceSpecificError(
219 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700220 }
221 }
222
223 *_aidl_return = mDvrPlayback;
224 return ::ndk::ScopedAStatus::ok();
225 case DvrType::RECORD:
226 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb, ref<Demux>());
227 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() {
346 mFrontendInputThreadRunning = true;
347 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
348 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
349}
350
351void* Demux::__threadLoopFrontend(void* user) {
352 Demux* const self = static_cast<Demux*>(user);
353 self->frontendInputThreadLoop();
354 return 0;
355}
356
357void Demux::frontendInputThreadLoop() {
358 if (!mFrontendInputThreadRunning) {
359 return;
360 }
361
362 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
363 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;
404 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
405}
406
407void Demux::setIsRecording(bool isRecording) {
408 mIsRecording = isRecording;
409}
410
411bool Demux::isRecording() {
412 return mIsRecording;
413}
414
415bool Demux::attachRecordFilter(int64_t filterId) {
416 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
417 !mFilters[filterId]->isRecordFilter()) {
418 return false;
419 }
420
421 mRecordFilterIds.insert(filterId);
422 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
423
424 return true;
425}
426
427bool Demux::detachRecordFilter(int64_t filterId) {
428 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
429 return false;
430 }
431
432 mRecordFilterIds.erase(filterId);
433 mFilters[filterId]->detachFilterFromRecord();
434
435 return true;
436}
437
438} // namespace tuner
439} // namespace tv
440} // namespace hardware
441} // namespace android
442} // namespace aidl