blob: de94467d1482a7b586a6a7203134d725a623c167 [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
sadiqsada56c98292023-11-02 16:45:31 -070023#include <fmq/AidlMessageQueue.h>
Hongguang4092f2f2021-07-08 18:49:12 -070024#include <utils/Log.h>
sadiqsada56c98292023-11-02 16:45:31 -070025#include <thread>
Hongguang4092f2f2021-07-08 18:49:12 -070026#include "Demux.h"
27
28namespace aidl {
29namespace android {
30namespace hardware {
31namespace tv {
32namespace tuner {
33
sadiqsada56c98292023-11-02 16:45:31 -070034using ::aidl::android::hardware::common::fmq::MQDescriptor;
35using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
36using ::android::AidlMessageQueue;
37using ::android::hardware::EventFlag;
38
39using FilterMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
40using AidlMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
41using AidlMQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
42
Hongguang4092f2f2021-07-08 18:49:12 -070043#define WAIT_TIMEOUT 3000000000
44
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080045Demux::Demux(int32_t demuxId, uint32_t filterTypes) {
Hongguang4092f2f2021-07-08 18:49:12 -070046 mDemuxId = demuxId;
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -080047 mFilterTypes = filterTypes;
48}
49
50void Demux::setTunerService(std::shared_ptr<Tuner> tuner) {
Hongguange423acd2021-07-27 16:56:47 -070051 mTuner = tuner;
Hongguang4092f2f2021-07-08 18:49:12 -070052}
53
54Demux::~Demux() {
Hongguang4a8ac292022-08-09 14:02:03 -070055 ALOGV("%s", __FUNCTION__);
sadiqsada028f2762023-10-31 16:09:25 -070056 if (mDemuxIptvReadThread.joinable()) {
57 mDemuxIptvReadThread.join();
58 }
Hongguang901aa7b2021-08-26 12:20:56 -070059 close();
Hongguang4092f2f2021-07-08 18:49:12 -070060}
61
sadiqsada56c98292023-11-02 16:45:31 -070062::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
63 const std::shared_ptr<IDvrCallback>& in_cb,
64 std::shared_ptr<IDvr>* _aidl_return) {
65 ALOGV("%s", __FUNCTION__);
66
67 if (in_cb == nullptr) {
68 ALOGW("[Demux] DVR callback can't be null");
69 *_aidl_return = nullptr;
70 return ::ndk::ScopedAStatus::fromServiceSpecificError(
71 static_cast<int32_t>(Result::INVALID_ARGUMENT));
72 }
73
74 set<int64_t>::iterator it;
75 switch (in_type) {
76 case DvrType::PLAYBACK:
77 mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
78 this->ref<Demux>());
79 if (!mDvrPlayback->createDvrMQ()) {
80 ALOGE("[Demux] cannot create dvr message queue");
81 mDvrPlayback = nullptr;
82 *_aidl_return = mDvrPlayback;
83 return ::ndk::ScopedAStatus::fromServiceSpecificError(
84 static_cast<int32_t>(Result::UNKNOWN_ERROR));
85 }
86
87 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
88 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
89 ALOGE("[Demux] Can't get filter info for DVR playback");
90 mDvrPlayback = nullptr;
91 *_aidl_return = mDvrPlayback;
92 return ::ndk::ScopedAStatus::fromServiceSpecificError(
93 static_cast<int32_t>(Result::UNKNOWN_ERROR));
94 }
95 }
96
97 ALOGI("Playback normal case");
98
99 *_aidl_return = mDvrPlayback;
100 return ::ndk::ScopedAStatus::ok();
101 case DvrType::RECORD:
102 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
103 this->ref<Demux>());
104 if (!mDvrRecord->createDvrMQ()) {
105 mDvrRecord = nullptr;
106 *_aidl_return = mDvrRecord;
107 return ::ndk::ScopedAStatus::fromServiceSpecificError(
108 static_cast<int32_t>(Result::UNKNOWN_ERROR));
109 }
110
111 *_aidl_return = mDvrRecord;
112 return ::ndk::ScopedAStatus::ok();
113 default:
114 *_aidl_return = nullptr;
115 return ::ndk::ScopedAStatus::fromServiceSpecificError(
116 static_cast<int32_t>(Result::INVALID_ARGUMENT));
117 }
118}
119
sadiqsada028f2762023-10-31 16:09:25 -0700120void Demux::setIptvThreadRunning(bool isIptvThreadRunning) {
121 std::unique_lock<std::mutex> lock(mIsIptvThreadRunningMutex);
122 mIsIptvReadThreadRunning = isIptvThreadRunning;
123 mIsIptvThreadRunningCv.notify_all();
124}
125
126void Demux::readIptvThreadLoop(dtv_plugin* interface, dtv_streamer* streamer, size_t buf_size,
127 int timeout_ms, int buffer_timeout) {
sadiqsada56c98292023-11-02 16:45:31 -0700128 Timer *timer, *fullBufferTimer;
sadiqsada028f2762023-10-31 16:09:25 -0700129 while (true) {
130 std::unique_lock<std::mutex> lock(mIsIptvThreadRunningMutex);
131 mIsIptvThreadRunningCv.wait(lock, [this] { return mIsIptvReadThreadRunning; });
sadiqsada56c98292023-11-02 16:45:31 -0700132 if (mIsIptvDvrFMQFull && fullBufferTimer->get_elapsed_time_ms() > buffer_timeout) {
133 ALOGE("DVR FMQ has not been flushed within timeout of %d ms", buffer_timeout);
134 delete fullBufferTimer;
135 break;
136 }
137 timer = new Timer();
sadiqsada028f2762023-10-31 16:09:25 -0700138 void* buf = malloc(sizeof(char) * IPTV_BUFFER_SIZE);
139 if (buf == nullptr) ALOGI("Buffer allocation failed");
sadiqsada56c98292023-11-02 16:45:31 -0700140 ssize_t bytes_read = interface->read_stream(streamer, buf, buf_size, timeout_ms);
141 if (bytes_read == 0) {
142 double elapsed_time = timer->get_elapsed_time_ms();
143 if (elapsed_time > timeout_ms) {
144 ALOGE("[Demux] timeout reached - elapsed_time: %f, timeout: %d", elapsed_time,
145 timeout_ms);
146 }
147 ALOGE("[Demux] Cannot read data from the socket");
148 delete timer;
149 break;
150 }
151
152 delete timer;
153 ALOGI("Number of bytes read: %zd", bytes_read);
154 int result = mDvrPlayback->writePlaybackFMQ(buf, bytes_read);
155
156 switch (result) {
157 case DVR_WRITE_FAILURE_REASON_FMQ_FULL:
158 if (!mIsIptvDvrFMQFull) {
159 mIsIptvDvrFMQFull = true;
160 fullBufferTimer = new Timer();
161 }
162 ALOGI("Waiting for client to flush DVR FMQ.");
163 break;
164 case DVR_WRITE_FAILURE_REASON_UNKNOWN:
165 ALOGE("Failed to write data into DVR FMQ for unknown reason");
166 break;
167 case DVR_WRITE_SUCCESS:
168 ALOGI("Wrote %zd bytes to DVR FMQ", bytes_read);
169 break;
170 default:
171 ALOGI("Invalid DVR Status");
172 }
sadiqsada028f2762023-10-31 16:09:25 -0700173
174 free(buf);
sadiqsada56c98292023-11-02 16:45:31 -0700175 }
sadiqsada56c98292023-11-02 16:45:31 -0700176}
177
Hongguang4092f2f2021-07-08 18:49:12 -0700178::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
179 ALOGV("%s", __FUNCTION__);
180
Hongguange423acd2021-07-27 16:56:47 -0700181 if (mTuner == nullptr) {
182 return ::ndk::ScopedAStatus::fromServiceSpecificError(
183 static_cast<int32_t>(Result::NOT_INITIALIZED));
Hongguang4092f2f2021-07-08 18:49:12 -0700184 }
Hongguange423acd2021-07-27 16:56:47 -0700185 mFrontend = mTuner->getFrontendById(in_frontendId);
Hongguang4092f2f2021-07-08 18:49:12 -0700186 if (mFrontend == nullptr) {
Hongguange423acd2021-07-27 16:56:47 -0700187 return ::ndk::ScopedAStatus::fromServiceSpecificError(
188 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700189 }
190
Hongguange423acd2021-07-27 16:56:47 -0700191 mTuner->setFrontendAsDemuxSource(in_frontendId, mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -0700192
sadiqsada56c98292023-11-02 16:45:31 -0700193 // if mFrontend is an IPTV frontend, create streamer to read TS data from socket
194 if (mFrontend->getFrontendType() == FrontendType::IPTV) {
195 // create a DVR instance on the demux
196 shared_ptr<IDvr> iptvDvr;
197
198 std::shared_ptr<IDvrCallback> dvrPlaybackCallback =
199 ::ndk::SharedRefBase::make<DvrPlaybackCallback>();
200
201 ::ndk::ScopedAStatus status =
202 openDvr(DvrType::PLAYBACK, IPTV_BUFFER_SIZE, dvrPlaybackCallback, &iptvDvr);
203 if (status.isOk()) {
204 ALOGI("DVR instance created");
205 }
206
207 // get plugin interface from frontend
208 dtv_plugin* interface = mFrontend->getIptvPluginInterface();
209 if (interface == nullptr) {
210 ALOGE("[Demux] getIptvPluginInterface(): plugin interface is null");
211 return ::ndk::ScopedAStatus::fromServiceSpecificError(
212 static_cast<int32_t>(Result::INVALID_STATE));
213 }
214 ALOGI("[Demux] getIptvPluginInterface(): plugin interface is not null");
215
216 // get streamer object from Frontend instance
217 dtv_streamer* streamer = mFrontend->getIptvPluginStreamer();
218 if (streamer == nullptr) {
219 ALOGE("[Demux] getIptvPluginStreamer(): streamer is null");
220 return ::ndk::ScopedAStatus::fromServiceSpecificError(
221 static_cast<int32_t>(Result::INVALID_STATE));
222 }
223 ALOGI("[Demux] getIptvPluginStreamer(): streamer is not null");
224
225 // get transport description from frontend
226 string transport_desc = mFrontend->getIptvTransportDescription();
227 ALOGI("[Demux] getIptvTransportDescription(): transport_desc: %s", transport_desc.c_str());
228
229 // call read_stream on the socket to populate the buffer with TS data
230 // while thread is alive, keep reading data
231 int timeout_ms = 20;
232 int buffer_timeout = 10000; // 10s
sadiqsada56c98292023-11-02 16:45:31 -0700233 mDemuxIptvReadThread = std::thread(&Demux::readIptvThreadLoop, this, interface, streamer,
sadiqsada028f2762023-10-31 16:09:25 -0700234 IPTV_BUFFER_SIZE, timeout_ms, buffer_timeout);
sadiqsada56c98292023-11-02 16:45:31 -0700235 }
Hongguang4092f2f2021-07-08 18:49:12 -0700236 return ::ndk::ScopedAStatus::ok();
237}
238
239::ndk::ScopedAStatus Demux::openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
240 const std::shared_ptr<IFilterCallback>& in_cb,
241 std::shared_ptr<IFilter>* _aidl_return) {
242 ALOGV("%s", __FUNCTION__);
243
244 int64_t filterId;
245 filterId = ++mLastUsedFilterId;
246
247 if (in_cb == nullptr) {
248 ALOGW("[Demux] callback can't be null");
249 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700250 return ::ndk::ScopedAStatus::fromServiceSpecificError(
251 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700252 }
253
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000254 std::shared_ptr<Filter> filter = ndk::SharedRefBase::make<Filter>(
255 in_type, filterId, in_bufferSize, in_cb, this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700256 if (!filter->createFilterMQ()) {
257 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700258 return ::ndk::ScopedAStatus::fromServiceSpecificError(
259 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700260 }
261
262 mFilters[filterId] = filter;
263 if (filter->isPcrFilter()) {
264 mPcrFilterIds.insert(filterId);
265 }
266 bool result = true;
267 if (!filter->isRecordFilter()) {
268 // Only save non-record filters for now. Record filters are saved when the
269 // IDvr.attacheFilter is called.
270 mPlaybackFilterIds.insert(filterId);
271 if (mDvrPlayback != nullptr) {
272 result = mDvrPlayback->addPlaybackFilter(filterId, filter);
273 }
274 }
275
276 if (!result) {
277 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700278 return ::ndk::ScopedAStatus::fromServiceSpecificError(
279 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700280 }
281
282 *_aidl_return = filter;
283 return ::ndk::ScopedAStatus::ok();
284}
285
286::ndk::ScopedAStatus Demux::openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) {
287 ALOGV("%s", __FUNCTION__);
288
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000289 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700290
291 *_aidl_return = mTimeFilter;
292 return ::ndk::ScopedAStatus::ok();
293}
294
295::ndk::ScopedAStatus Demux::getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
296 int32_t* _aidl_return) {
297 ALOGV("%s", __FUNCTION__);
298
299 int64_t id;
300 ::ndk::ScopedAStatus status;
301
302 status = in_filter->getId64Bit(&id);
303 if (!status.isOk()) {
304 ALOGE("[Demux] Can't get filter Id.");
305 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700306 return ::ndk::ScopedAStatus::fromServiceSpecificError(
307 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700308 }
309
310 if (!mFilters[id]->isMediaFilter()) {
311 ALOGE("[Demux] Given filter is not a media filter.");
312 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700313 return ::ndk::ScopedAStatus::fromServiceSpecificError(
314 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700315 }
316
317 if (!mPcrFilterIds.empty()) {
318 // Return the lowest pcr filter id in the default implementation as the av sync id
319 *_aidl_return = *mPcrFilterIds.begin();
320 return ::ndk::ScopedAStatus::ok();
321 }
322
323 ALOGE("[Demux] No PCR filter opened.");
324 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700325 return ::ndk::ScopedAStatus::fromServiceSpecificError(
326 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700327}
328
329::ndk::ScopedAStatus Demux::getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) {
330 ALOGV("%s", __FUNCTION__);
331
332 if (mPcrFilterIds.empty()) {
333 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700334 return ::ndk::ScopedAStatus::fromServiceSpecificError(
335 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700336 }
337 if (in_avSyncHwId != *mPcrFilterIds.begin()) {
338 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700339 return ::ndk::ScopedAStatus::fromServiceSpecificError(
340 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700341 }
342
343 *_aidl_return = -1;
344 return ::ndk::ScopedAStatus::ok();
345}
346
347::ndk::ScopedAStatus Demux::close() {
348 ALOGV("%s", __FUNCTION__);
349
Hongguang901aa7b2021-08-26 12:20:56 -0700350 stopFrontendInput();
351
Hongguang4092f2f2021-07-08 18:49:12 -0700352 set<int64_t>::iterator it;
353 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
354 mDvrPlayback->removePlaybackFilter(*it);
355 }
356 mPlaybackFilterIds.clear();
357 mRecordFilterIds.clear();
358 mFilters.clear();
359 mLastUsedFilterId = -1;
Hongguang4a8ac292022-08-09 14:02:03 -0700360 if (mTuner != nullptr) {
361 mTuner->removeDemux(mDemuxId);
362 mTuner = nullptr;
363 }
Hongguang4092f2f2021-07-08 18:49:12 -0700364
365 return ::ndk::ScopedAStatus::ok();
366}
367
Hongguang4092f2f2021-07-08 18:49:12 -0700368::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
369 ALOGV("%s", __FUNCTION__);
370
371 mCiCamId = in_ciCamId;
372
373 return ::ndk::ScopedAStatus::ok();
374}
375
376::ndk::ScopedAStatus Demux::disconnectCiCam() {
377 ALOGV("%s", __FUNCTION__);
378
379 return ::ndk::ScopedAStatus::ok();
380}
381
382::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
383 ALOGV("%s", __FUNCTION__);
384
385 if (mDvrPlayback != nullptr) {
386 mDvrPlayback->removePlaybackFilter(filterId);
387 }
388 mPlaybackFilterIds.erase(filterId);
389 mRecordFilterIds.erase(filterId);
390 mFilters.erase(filterId);
391
392 return ::ndk::ScopedAStatus::ok();
393}
394
395void Demux::startBroadcastTsFilter(vector<int8_t> data) {
396 set<int64_t>::iterator it;
397 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
398 if (DEBUG_DEMUX) {
399 ALOGW("[Demux] start ts filter pid: %d", pid);
400 }
401 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
402 if (pid == mFilters[*it]->getTpid()) {
403 mFilters[*it]->updateFilterOutput(data);
404 }
405 }
406}
407
408void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
409 set<int64_t>::iterator it;
410 if (DEBUG_DEMUX) {
411 ALOGW("[Demux] update record filter output");
412 }
413 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
414 mFilters[*it]->updateRecordOutput(data);
415 }
416}
417
418void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
419 sendFrontendInputToRecord(data);
420 set<int64_t>::iterator it;
421 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
422 if (pid == mFilters[*it]->getTpid()) {
423 mFilters[*it]->updatePts(pts);
424 }
425 }
426}
427
428bool Demux::startBroadcastFilterDispatcher() {
429 set<int64_t>::iterator it;
430
431 // Handle the output data per filter type
432 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
433 if (!mFilters[*it]->startFilterHandler().isOk()) {
434 return false;
435 }
436 }
437
438 return true;
439}
440
441bool Demux::startRecordFilterDispatcher() {
442 set<int64_t>::iterator it;
443
444 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
445 if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
446 return false;
447 }
448 }
449
450 return true;
451}
452
453::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
454 return mFilters[filterId]->startFilterHandler();
455}
456
457void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
458 mFilters[filterId]->updateFilterOutput(data);
459}
460
461void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
462 updateFilterOutput(filterId, data);
463 mFilters[filterId]->updatePts(pts);
464}
465
466uint16_t Demux::getFilterTpid(int64_t filterId) {
467 return mFilters[filterId]->getTpid();
468}
469
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800470int32_t Demux::getDemuxId() {
471 return mDemuxId;
472}
473
474bool Demux::isInUse() {
475 return mInUse;
476}
477
478void Demux::setInUse(bool inUse) {
479 mInUse = inUse;
480}
481
482void Demux::getDemuxInfo(DemuxInfo* demuxInfo) {
483 *demuxInfo = {.filterTypes = mFilterTypes};
484}
485
Hongguang4092f2f2021-07-08 18:49:12 -0700486void Demux::startFrontendInputLoop() {
Hongguang76ca9a82021-10-06 17:11:09 -0700487 ALOGD("[Demux] start frontend on demux");
488 // Stop current Frontend thread loop first, in case the user starts a new
489 // tuning before stopping current tuning.
490 stopFrontendInput();
Hongguang4092f2f2021-07-08 18:49:12 -0700491 mFrontendInputThreadRunning = true;
Hongguang901aa7b2021-08-26 12:20:56 -0700492 mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
Hongguang4092f2f2021-07-08 18:49:12 -0700493}
494
495void Demux::frontendInputThreadLoop() {
496 if (!mFrontendInputThreadRunning) {
497 return;
498 }
499
Hongguang4092f2f2021-07-08 18:49:12 -0700500 if (!mDvrPlayback) {
501 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
502 mFrontendInputThreadRunning = false;
503 return;
504 }
505
506 while (mFrontendInputThreadRunning) {
507 uint32_t efState = 0;
508 ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
509 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
510 true /* retry on spurious wake */);
511 if (status != ::android::OK) {
512 ALOGD("[Demux] wait for data ready on the playback FMQ");
513 continue;
514 }
515 if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
516 DataFormat::ES) {
517 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
518 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
519 break;
520 }
521 continue;
522 }
523 // Our current implementation filter the data and write it into the filter FMQ immediately
524 // after the DATA_READY from the VTS/framework
525 // This is for the non-ES data source, real playback use case handling.
526 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
527 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
528 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
529 break;
530 }
531 }
532
533 mFrontendInputThreadRunning = false;
534 ALOGW("[Demux] Frontend Input thread end.");
535}
536
537void Demux::stopFrontendInput() {
538 ALOGD("[Demux] stop frontend on demux");
539 mKeepFetchingDataFromFrontend = false;
540 mFrontendInputThreadRunning = false;
Hongguang901aa7b2021-08-26 12:20:56 -0700541 if (mFrontendInputThread.joinable()) {
542 mFrontendInputThread.join();
543 }
Hongguang4092f2f2021-07-08 18:49:12 -0700544}
545
546void Demux::setIsRecording(bool isRecording) {
547 mIsRecording = isRecording;
548}
549
550bool Demux::isRecording() {
551 return mIsRecording;
552}
553
Hongguang2ecfc392021-11-23 10:29:15 -0800554binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
555 dprintf(fd, " Demux %d:\n", mDemuxId);
556 dprintf(fd, " mIsRecording %d\n", mIsRecording);
557 {
558 dprintf(fd, " Filters:\n");
559 map<int64_t, std::shared_ptr<Filter>>::iterator it;
560 for (it = mFilters.begin(); it != mFilters.end(); it++) {
561 it->second->dump(fd, args, numArgs);
562 }
563 }
564 {
565 dprintf(fd, " TimeFilter:\n");
566 if (mTimeFilter != nullptr) {
567 mTimeFilter->dump(fd, args, numArgs);
568 }
569 }
570 {
571 dprintf(fd, " DvrPlayback:\n");
572 if (mDvrPlayback != nullptr) {
573 mDvrPlayback->dump(fd, args, numArgs);
574 }
575 }
576 {
577 dprintf(fd, " DvrRecord:\n");
578 if (mDvrRecord != nullptr) {
579 mDvrRecord->dump(fd, args, numArgs);
580 }
581 }
582 return STATUS_OK;
583}
584
Hongguang4092f2f2021-07-08 18:49:12 -0700585bool Demux::attachRecordFilter(int64_t filterId) {
586 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
587 !mFilters[filterId]->isRecordFilter()) {
588 return false;
589 }
590
591 mRecordFilterIds.insert(filterId);
592 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
593
594 return true;
595}
596
597bool Demux::detachRecordFilter(int64_t filterId) {
598 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
599 return false;
600 }
601
602 mRecordFilterIds.erase(filterId);
603 mFilters[filterId]->detachFilterFromRecord();
604
605 return true;
606}
607
608} // namespace tuner
609} // namespace tv
610} // namespace hardware
611} // namespace android
612} // namespace aidl