blob: bdc3849e34d8418d8bf6f45c71d357ae7fce0c2d [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
Hongguang50899fb2021-08-05 22:51:58 -070034Demux::Demux(int32_t demuxId, 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() {
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 =
Hongguang50899fb2021-08-05 22:51:58 -070079 ndk::SharedRefBase::make<Filter>(in_type, filterId, in_bufferSize, in_cb, this);
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
Hongguang50899fb2021-08-05 22:51:58 -0700113 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this);
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
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:
Hongguang50899fb2021-08-05 22:51:58 -0700204 mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb, this);
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:
Hongguang50899fb2021-08-05 22:51:58 -0700225 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb, this);
Hongguang4092f2f2021-07-08 18:49:12 -0700226 if (!mDvrRecord->createDvrMQ()) {
227 mDvrRecord = nullptr;
228 *_aidl_return = mDvrRecord;
Hongguange423acd2021-07-27 16:56:47 -0700229 return ::ndk::ScopedAStatus::fromServiceSpecificError(
230 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700231 }
232
233 *_aidl_return = mDvrRecord;
234 return ::ndk::ScopedAStatus::ok();
235 default:
236 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700237 return ::ndk::ScopedAStatus::fromServiceSpecificError(
238 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700239 }
240}
241
242::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
243 ALOGV("%s", __FUNCTION__);
244
245 mCiCamId = in_ciCamId;
246
247 return ::ndk::ScopedAStatus::ok();
248}
249
250::ndk::ScopedAStatus Demux::disconnectCiCam() {
251 ALOGV("%s", __FUNCTION__);
252
253 return ::ndk::ScopedAStatus::ok();
254}
255
256::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
257 ALOGV("%s", __FUNCTION__);
258
259 if (mDvrPlayback != nullptr) {
260 mDvrPlayback->removePlaybackFilter(filterId);
261 }
262 mPlaybackFilterIds.erase(filterId);
263 mRecordFilterIds.erase(filterId);
264 mFilters.erase(filterId);
265
266 return ::ndk::ScopedAStatus::ok();
267}
268
269void Demux::startBroadcastTsFilter(vector<int8_t> data) {
270 set<int64_t>::iterator it;
271 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
272 if (DEBUG_DEMUX) {
273 ALOGW("[Demux] start ts filter pid: %d", pid);
274 }
275 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
276 if (pid == mFilters[*it]->getTpid()) {
277 mFilters[*it]->updateFilterOutput(data);
278 }
279 }
280}
281
282void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
283 set<int64_t>::iterator it;
284 if (DEBUG_DEMUX) {
285 ALOGW("[Demux] update record filter output");
286 }
287 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
288 mFilters[*it]->updateRecordOutput(data);
289 }
290}
291
292void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
293 sendFrontendInputToRecord(data);
294 set<int64_t>::iterator it;
295 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
296 if (pid == mFilters[*it]->getTpid()) {
297 mFilters[*it]->updatePts(pts);
298 }
299 }
300}
301
302bool Demux::startBroadcastFilterDispatcher() {
303 set<int64_t>::iterator it;
304
305 // Handle the output data per filter type
306 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
307 if (!mFilters[*it]->startFilterHandler().isOk()) {
308 return false;
309 }
310 }
311
312 return true;
313}
314
315bool Demux::startRecordFilterDispatcher() {
316 set<int64_t>::iterator it;
317
318 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
319 if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
320 return false;
321 }
322 }
323
324 return true;
325}
326
327::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
328 return mFilters[filterId]->startFilterHandler();
329}
330
331void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
332 mFilters[filterId]->updateFilterOutput(data);
333}
334
335void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
336 updateFilterOutput(filterId, data);
337 mFilters[filterId]->updatePts(pts);
338}
339
340uint16_t Demux::getFilterTpid(int64_t filterId) {
341 return mFilters[filterId]->getTpid();
342}
343
344void Demux::startFrontendInputLoop() {
345 mFrontendInputThreadRunning = true;
346 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
347 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
348}
349
350void* Demux::__threadLoopFrontend(void* user) {
351 Demux* const self = static_cast<Demux*>(user);
352 self->frontendInputThreadLoop();
353 return 0;
354}
355
356void Demux::frontendInputThreadLoop() {
357 if (!mFrontendInputThreadRunning) {
358 return;
359 }
360
361 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
362 if (!mDvrPlayback) {
363 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
364 mFrontendInputThreadRunning = false;
365 return;
366 }
367
368 while (mFrontendInputThreadRunning) {
369 uint32_t efState = 0;
370 ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
371 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
372 true /* retry on spurious wake */);
373 if (status != ::android::OK) {
374 ALOGD("[Demux] wait for data ready on the playback FMQ");
375 continue;
376 }
377 if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
378 DataFormat::ES) {
379 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
380 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
381 break;
382 }
383 continue;
384 }
385 // Our current implementation filter the data and write it into the filter FMQ immediately
386 // after the DATA_READY from the VTS/framework
387 // This is for the non-ES data source, real playback use case handling.
388 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
389 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
390 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
391 break;
392 }
393 }
394
395 mFrontendInputThreadRunning = false;
396 ALOGW("[Demux] Frontend Input thread end.");
397}
398
399void Demux::stopFrontendInput() {
400 ALOGD("[Demux] stop frontend on demux");
401 mKeepFetchingDataFromFrontend = false;
402 mFrontendInputThreadRunning = false;
403 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
404}
405
406void Demux::setIsRecording(bool isRecording) {
407 mIsRecording = isRecording;
408}
409
410bool Demux::isRecording() {
411 return mIsRecording;
412}
413
414bool Demux::attachRecordFilter(int64_t filterId) {
415 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
416 !mFilters[filterId]->isRecordFilter()) {
417 return false;
418 }
419
420 mRecordFilterIds.insert(filterId);
421 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
422
423 return true;
424}
425
426bool Demux::detachRecordFilter(int64_t filterId) {
427 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
428 return false;
429 }
430
431 mRecordFilterIds.erase(filterId);
432 mFilters[filterId]->detachFilterFromRecord();
433
434 return true;
435}
436
437} // namespace tuner
438} // namespace tv
439} // namespace hardware
440} // namespace android
441} // namespace aidl