blob: 34e3442df0d168c46ffacc32d047c8ae692e0c2a [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__);
Hongguang901aa7b2021-08-26 12:20:56 -070056 close();
Hongguang4092f2f2021-07-08 18:49:12 -070057}
58
sadiqsada56c98292023-11-02 16:45:31 -070059::ndk::ScopedAStatus Demux::openDvr(DvrType in_type, int32_t in_bufferSize,
60 const std::shared_ptr<IDvrCallback>& in_cb,
61 std::shared_ptr<IDvr>* _aidl_return) {
62 ALOGV("%s", __FUNCTION__);
63
64 if (in_cb == nullptr) {
65 ALOGW("[Demux] DVR callback can't be null");
66 *_aidl_return = nullptr;
67 return ::ndk::ScopedAStatus::fromServiceSpecificError(
68 static_cast<int32_t>(Result::INVALID_ARGUMENT));
69 }
70
71 set<int64_t>::iterator it;
72 switch (in_type) {
73 case DvrType::PLAYBACK:
74 mDvrPlayback = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
75 this->ref<Demux>());
76 if (!mDvrPlayback->createDvrMQ()) {
77 ALOGE("[Demux] cannot create dvr message queue");
78 mDvrPlayback = nullptr;
79 *_aidl_return = mDvrPlayback;
80 return ::ndk::ScopedAStatus::fromServiceSpecificError(
81 static_cast<int32_t>(Result::UNKNOWN_ERROR));
82 }
83
84 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
85 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
86 ALOGE("[Demux] Can't get filter info for DVR playback");
87 mDvrPlayback = nullptr;
88 *_aidl_return = mDvrPlayback;
89 return ::ndk::ScopedAStatus::fromServiceSpecificError(
90 static_cast<int32_t>(Result::UNKNOWN_ERROR));
91 }
92 }
93
94 ALOGI("Playback normal case");
95
96 *_aidl_return = mDvrPlayback;
97 return ::ndk::ScopedAStatus::ok();
98 case DvrType::RECORD:
99 mDvrRecord = ndk::SharedRefBase::make<Dvr>(in_type, in_bufferSize, in_cb,
100 this->ref<Demux>());
101 if (!mDvrRecord->createDvrMQ()) {
102 mDvrRecord = nullptr;
103 *_aidl_return = mDvrRecord;
104 return ::ndk::ScopedAStatus::fromServiceSpecificError(
105 static_cast<int32_t>(Result::UNKNOWN_ERROR));
106 }
107
108 *_aidl_return = mDvrRecord;
109 return ::ndk::ScopedAStatus::ok();
110 default:
111 *_aidl_return = nullptr;
112 return ::ndk::ScopedAStatus::fromServiceSpecificError(
113 static_cast<int32_t>(Result::INVALID_ARGUMENT));
114 }
115}
116
117void Demux::readIptvThreadLoop(dtv_plugin* interface, dtv_streamer* streamer, void* buf,
118 size_t buf_size, int timeout_ms, int buffer_timeout) {
119 Timer *timer, *fullBufferTimer;
120 while (mDemuxIptvReadThreadRunning) {
121 if (mIsIptvDvrFMQFull && fullBufferTimer->get_elapsed_time_ms() > buffer_timeout) {
122 ALOGE("DVR FMQ has not been flushed within timeout of %d ms", buffer_timeout);
123 delete fullBufferTimer;
124 break;
125 }
126 timer = new Timer();
127 ssize_t bytes_read = interface->read_stream(streamer, buf, buf_size, timeout_ms);
128 if (bytes_read == 0) {
129 double elapsed_time = timer->get_elapsed_time_ms();
130 if (elapsed_time > timeout_ms) {
131 ALOGE("[Demux] timeout reached - elapsed_time: %f, timeout: %d", elapsed_time,
132 timeout_ms);
133 }
134 ALOGE("[Demux] Cannot read data from the socket");
135 delete timer;
136 break;
137 }
138
139 delete timer;
140 ALOGI("Number of bytes read: %zd", bytes_read);
141 int result = mDvrPlayback->writePlaybackFMQ(buf, bytes_read);
142
143 switch (result) {
144 case DVR_WRITE_FAILURE_REASON_FMQ_FULL:
145 if (!mIsIptvDvrFMQFull) {
146 mIsIptvDvrFMQFull = true;
147 fullBufferTimer = new Timer();
148 }
149 ALOGI("Waiting for client to flush DVR FMQ.");
150 break;
151 case DVR_WRITE_FAILURE_REASON_UNKNOWN:
152 ALOGE("Failed to write data into DVR FMQ for unknown reason");
153 break;
154 case DVR_WRITE_SUCCESS:
155 ALOGI("Wrote %zd bytes to DVR FMQ", bytes_read);
156 break;
157 default:
158 ALOGI("Invalid DVR Status");
159 }
160 }
161 mDemuxIptvReadThreadRunning = false;
162}
163
Hongguang4092f2f2021-07-08 18:49:12 -0700164::ndk::ScopedAStatus Demux::setFrontendDataSource(int32_t in_frontendId) {
165 ALOGV("%s", __FUNCTION__);
166
Hongguange423acd2021-07-27 16:56:47 -0700167 if (mTuner == nullptr) {
168 return ::ndk::ScopedAStatus::fromServiceSpecificError(
169 static_cast<int32_t>(Result::NOT_INITIALIZED));
Hongguang4092f2f2021-07-08 18:49:12 -0700170 }
Hongguange423acd2021-07-27 16:56:47 -0700171 mFrontend = mTuner->getFrontendById(in_frontendId);
Hongguang4092f2f2021-07-08 18:49:12 -0700172 if (mFrontend == nullptr) {
Hongguange423acd2021-07-27 16:56:47 -0700173 return ::ndk::ScopedAStatus::fromServiceSpecificError(
174 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700175 }
176
Hongguange423acd2021-07-27 16:56:47 -0700177 mTuner->setFrontendAsDemuxSource(in_frontendId, mDemuxId);
Hongguang4092f2f2021-07-08 18:49:12 -0700178
sadiqsada56c98292023-11-02 16:45:31 -0700179 // if mFrontend is an IPTV frontend, create streamer to read TS data from socket
180 if (mFrontend->getFrontendType() == FrontendType::IPTV) {
181 // create a DVR instance on the demux
182 shared_ptr<IDvr> iptvDvr;
183
184 std::shared_ptr<IDvrCallback> dvrPlaybackCallback =
185 ::ndk::SharedRefBase::make<DvrPlaybackCallback>();
186
187 ::ndk::ScopedAStatus status =
188 openDvr(DvrType::PLAYBACK, IPTV_BUFFER_SIZE, dvrPlaybackCallback, &iptvDvr);
189 if (status.isOk()) {
190 ALOGI("DVR instance created");
191 }
192
193 // get plugin interface from frontend
194 dtv_plugin* interface = mFrontend->getIptvPluginInterface();
195 if (interface == nullptr) {
196 ALOGE("[Demux] getIptvPluginInterface(): plugin interface is null");
197 return ::ndk::ScopedAStatus::fromServiceSpecificError(
198 static_cast<int32_t>(Result::INVALID_STATE));
199 }
200 ALOGI("[Demux] getIptvPluginInterface(): plugin interface is not null");
201
202 // get streamer object from Frontend instance
203 dtv_streamer* streamer = mFrontend->getIptvPluginStreamer();
204 if (streamer == nullptr) {
205 ALOGE("[Demux] getIptvPluginStreamer(): streamer is null");
206 return ::ndk::ScopedAStatus::fromServiceSpecificError(
207 static_cast<int32_t>(Result::INVALID_STATE));
208 }
209 ALOGI("[Demux] getIptvPluginStreamer(): streamer is not null");
210
211 // get transport description from frontend
212 string transport_desc = mFrontend->getIptvTransportDescription();
213 ALOGI("[Demux] getIptvTransportDescription(): transport_desc: %s", transport_desc.c_str());
214
215 // call read_stream on the socket to populate the buffer with TS data
216 // while thread is alive, keep reading data
217 int timeout_ms = 20;
218 int buffer_timeout = 10000; // 10s
219 void* buf = malloc(sizeof(char) * IPTV_BUFFER_SIZE);
220 if (buf == nullptr) ALOGI("malloc buf failed");
221 ALOGI("[ INFO ] Allocated buffer of size %d", IPTV_BUFFER_SIZE);
222 ALOGI("Getting FMQ from DVR instance to write socket data");
223 mDemuxIptvReadThreadRunning = true;
224 mDemuxIptvReadThread = std::thread(&Demux::readIptvThreadLoop, this, interface, streamer,
225 buf, IPTV_BUFFER_SIZE, timeout_ms, buffer_timeout);
226 if (mDemuxIptvReadThread.joinable()) {
227 mDemuxIptvReadThread.join();
228 }
229 free(buf);
230 }
Hongguang4092f2f2021-07-08 18:49:12 -0700231 return ::ndk::ScopedAStatus::ok();
232}
233
234::ndk::ScopedAStatus Demux::openFilter(const DemuxFilterType& in_type, int32_t in_bufferSize,
235 const std::shared_ptr<IFilterCallback>& in_cb,
236 std::shared_ptr<IFilter>* _aidl_return) {
237 ALOGV("%s", __FUNCTION__);
238
239 int64_t filterId;
240 filterId = ++mLastUsedFilterId;
241
242 if (in_cb == nullptr) {
243 ALOGW("[Demux] callback can't be null");
244 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700245 return ::ndk::ScopedAStatus::fromServiceSpecificError(
246 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700247 }
248
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000249 std::shared_ptr<Filter> filter = ndk::SharedRefBase::make<Filter>(
250 in_type, filterId, in_bufferSize, in_cb, this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700251 if (!filter->createFilterMQ()) {
252 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700253 return ::ndk::ScopedAStatus::fromServiceSpecificError(
254 static_cast<int32_t>(Result::UNKNOWN_ERROR));
Hongguang4092f2f2021-07-08 18:49:12 -0700255 }
256
257 mFilters[filterId] = filter;
258 if (filter->isPcrFilter()) {
259 mPcrFilterIds.insert(filterId);
260 }
261 bool result = true;
262 if (!filter->isRecordFilter()) {
263 // Only save non-record filters for now. Record filters are saved when the
264 // IDvr.attacheFilter is called.
265 mPlaybackFilterIds.insert(filterId);
266 if (mDvrPlayback != nullptr) {
267 result = mDvrPlayback->addPlaybackFilter(filterId, filter);
268 }
269 }
270
271 if (!result) {
272 *_aidl_return = nullptr;
Hongguange423acd2021-07-27 16:56:47 -0700273 return ::ndk::ScopedAStatus::fromServiceSpecificError(
274 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700275 }
276
277 *_aidl_return = filter;
278 return ::ndk::ScopedAStatus::ok();
279}
280
281::ndk::ScopedAStatus Demux::openTimeFilter(std::shared_ptr<ITimeFilter>* _aidl_return) {
282 ALOGV("%s", __FUNCTION__);
283
Hongguang Chenff2c6b02021-08-07 00:12:26 +0000284 mTimeFilter = ndk::SharedRefBase::make<TimeFilter>(this->ref<Demux>());
Hongguang4092f2f2021-07-08 18:49:12 -0700285
286 *_aidl_return = mTimeFilter;
287 return ::ndk::ScopedAStatus::ok();
288}
289
290::ndk::ScopedAStatus Demux::getAvSyncHwId(const std::shared_ptr<IFilter>& in_filter,
291 int32_t* _aidl_return) {
292 ALOGV("%s", __FUNCTION__);
293
294 int64_t id;
295 ::ndk::ScopedAStatus status;
296
297 status = in_filter->getId64Bit(&id);
298 if (!status.isOk()) {
299 ALOGE("[Demux] Can't get filter Id.");
300 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700301 return ::ndk::ScopedAStatus::fromServiceSpecificError(
302 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700303 }
304
305 if (!mFilters[id]->isMediaFilter()) {
306 ALOGE("[Demux] Given filter is not a media filter.");
307 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700308 return ::ndk::ScopedAStatus::fromServiceSpecificError(
309 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700310 }
311
312 if (!mPcrFilterIds.empty()) {
313 // Return the lowest pcr filter id in the default implementation as the av sync id
314 *_aidl_return = *mPcrFilterIds.begin();
315 return ::ndk::ScopedAStatus::ok();
316 }
317
318 ALOGE("[Demux] No PCR filter opened.");
319 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700320 return ::ndk::ScopedAStatus::fromServiceSpecificError(
321 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700322}
323
324::ndk::ScopedAStatus Demux::getAvSyncTime(int32_t in_avSyncHwId, int64_t* _aidl_return) {
325 ALOGV("%s", __FUNCTION__);
326
327 if (mPcrFilterIds.empty()) {
328 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700329 return ::ndk::ScopedAStatus::fromServiceSpecificError(
330 static_cast<int32_t>(Result::INVALID_STATE));
Hongguang4092f2f2021-07-08 18:49:12 -0700331 }
332 if (in_avSyncHwId != *mPcrFilterIds.begin()) {
333 *_aidl_return = -1;
Hongguange423acd2021-07-27 16:56:47 -0700334 return ::ndk::ScopedAStatus::fromServiceSpecificError(
335 static_cast<int32_t>(Result::INVALID_ARGUMENT));
Hongguang4092f2f2021-07-08 18:49:12 -0700336 }
337
338 *_aidl_return = -1;
339 return ::ndk::ScopedAStatus::ok();
340}
341
342::ndk::ScopedAStatus Demux::close() {
343 ALOGV("%s", __FUNCTION__);
344
Hongguang901aa7b2021-08-26 12:20:56 -0700345 stopFrontendInput();
346
Hongguang4092f2f2021-07-08 18:49:12 -0700347 set<int64_t>::iterator it;
348 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
349 mDvrPlayback->removePlaybackFilter(*it);
350 }
351 mPlaybackFilterIds.clear();
352 mRecordFilterIds.clear();
353 mFilters.clear();
354 mLastUsedFilterId = -1;
Hongguang4a8ac292022-08-09 14:02:03 -0700355 if (mTuner != nullptr) {
356 mTuner->removeDemux(mDemuxId);
357 mTuner = nullptr;
358 }
Hongguang4092f2f2021-07-08 18:49:12 -0700359
360 return ::ndk::ScopedAStatus::ok();
361}
362
Hongguang4092f2f2021-07-08 18:49:12 -0700363::ndk::ScopedAStatus Demux::connectCiCam(int32_t in_ciCamId) {
364 ALOGV("%s", __FUNCTION__);
365
366 mCiCamId = in_ciCamId;
367
368 return ::ndk::ScopedAStatus::ok();
369}
370
371::ndk::ScopedAStatus Demux::disconnectCiCam() {
372 ALOGV("%s", __FUNCTION__);
373
374 return ::ndk::ScopedAStatus::ok();
375}
376
377::ndk::ScopedAStatus Demux::removeFilter(int64_t filterId) {
378 ALOGV("%s", __FUNCTION__);
379
380 if (mDvrPlayback != nullptr) {
381 mDvrPlayback->removePlaybackFilter(filterId);
382 }
383 mPlaybackFilterIds.erase(filterId);
384 mRecordFilterIds.erase(filterId);
385 mFilters.erase(filterId);
386
387 return ::ndk::ScopedAStatus::ok();
388}
389
390void Demux::startBroadcastTsFilter(vector<int8_t> data) {
391 set<int64_t>::iterator it;
392 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
393 if (DEBUG_DEMUX) {
394 ALOGW("[Demux] start ts filter pid: %d", pid);
395 }
396 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
397 if (pid == mFilters[*it]->getTpid()) {
398 mFilters[*it]->updateFilterOutput(data);
399 }
400 }
401}
402
403void Demux::sendFrontendInputToRecord(vector<int8_t> data) {
404 set<int64_t>::iterator it;
405 if (DEBUG_DEMUX) {
406 ALOGW("[Demux] update record filter output");
407 }
408 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
409 mFilters[*it]->updateRecordOutput(data);
410 }
411}
412
413void Demux::sendFrontendInputToRecord(vector<int8_t> data, uint16_t pid, uint64_t pts) {
414 sendFrontendInputToRecord(data);
415 set<int64_t>::iterator it;
416 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
417 if (pid == mFilters[*it]->getTpid()) {
418 mFilters[*it]->updatePts(pts);
419 }
420 }
421}
422
423bool Demux::startBroadcastFilterDispatcher() {
424 set<int64_t>::iterator it;
425
426 // Handle the output data per filter type
427 for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
428 if (!mFilters[*it]->startFilterHandler().isOk()) {
429 return false;
430 }
431 }
432
433 return true;
434}
435
436bool Demux::startRecordFilterDispatcher() {
437 set<int64_t>::iterator it;
438
439 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
440 if (!mFilters[*it]->startRecordFilterHandler().isOk()) {
441 return false;
442 }
443 }
444
445 return true;
446}
447
448::ndk::ScopedAStatus Demux::startFilterHandler(int64_t filterId) {
449 return mFilters[filterId]->startFilterHandler();
450}
451
452void Demux::updateFilterOutput(int64_t filterId, vector<int8_t> data) {
453 mFilters[filterId]->updateFilterOutput(data);
454}
455
456void Demux::updateMediaFilterOutput(int64_t filterId, vector<int8_t> data, uint64_t pts) {
457 updateFilterOutput(filterId, data);
458 mFilters[filterId]->updatePts(pts);
459}
460
461uint16_t Demux::getFilterTpid(int64_t filterId) {
462 return mFilters[filterId]->getTpid();
463}
464
Kensuke Miyagi73b18ac2022-11-07 10:49:09 -0800465int32_t Demux::getDemuxId() {
466 return mDemuxId;
467}
468
469bool Demux::isInUse() {
470 return mInUse;
471}
472
473void Demux::setInUse(bool inUse) {
474 mInUse = inUse;
475}
476
477void Demux::getDemuxInfo(DemuxInfo* demuxInfo) {
478 *demuxInfo = {.filterTypes = mFilterTypes};
479}
480
Hongguang4092f2f2021-07-08 18:49:12 -0700481void Demux::startFrontendInputLoop() {
Hongguang76ca9a82021-10-06 17:11:09 -0700482 ALOGD("[Demux] start frontend on demux");
483 // Stop current Frontend thread loop first, in case the user starts a new
484 // tuning before stopping current tuning.
485 stopFrontendInput();
Hongguang4092f2f2021-07-08 18:49:12 -0700486 mFrontendInputThreadRunning = true;
Hongguang901aa7b2021-08-26 12:20:56 -0700487 mFrontendInputThread = std::thread(&Demux::frontendInputThreadLoop, this);
Hongguang4092f2f2021-07-08 18:49:12 -0700488}
489
490void Demux::frontendInputThreadLoop() {
491 if (!mFrontendInputThreadRunning) {
492 return;
493 }
494
Hongguang4092f2f2021-07-08 18:49:12 -0700495 if (!mDvrPlayback) {
496 ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
497 mFrontendInputThreadRunning = false;
498 return;
499 }
500
501 while (mFrontendInputThreadRunning) {
502 uint32_t efState = 0;
503 ::android::status_t status = mDvrPlayback->getDvrEventFlag()->wait(
504 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
505 true /* retry on spurious wake */);
506 if (status != ::android::OK) {
507 ALOGD("[Demux] wait for data ready on the playback FMQ");
508 continue;
509 }
510 if (mDvrPlayback->getSettings().get<DvrSettings::Tag::playback>().dataFormat ==
511 DataFormat::ES) {
512 if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
513 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
514 break;
515 }
516 continue;
517 }
518 // Our current implementation filter the data and write it into the filter FMQ immediately
519 // after the DATA_READY from the VTS/framework
520 // This is for the non-ES data source, real playback use case handling.
521 if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
522 !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
523 ALOGE("[Demux] playback data failed to be filtered. Ending thread");
524 break;
525 }
526 }
527
528 mFrontendInputThreadRunning = false;
529 ALOGW("[Demux] Frontend Input thread end.");
530}
531
532void Demux::stopFrontendInput() {
533 ALOGD("[Demux] stop frontend on demux");
534 mKeepFetchingDataFromFrontend = false;
535 mFrontendInputThreadRunning = false;
Hongguang901aa7b2021-08-26 12:20:56 -0700536 if (mFrontendInputThread.joinable()) {
537 mFrontendInputThread.join();
538 }
Hongguang4092f2f2021-07-08 18:49:12 -0700539}
540
541void Demux::setIsRecording(bool isRecording) {
542 mIsRecording = isRecording;
543}
544
545bool Demux::isRecording() {
546 return mIsRecording;
547}
548
Hongguang2ecfc392021-11-23 10:29:15 -0800549binder_status_t Demux::dump(int fd, const char** args, uint32_t numArgs) {
550 dprintf(fd, " Demux %d:\n", mDemuxId);
551 dprintf(fd, " mIsRecording %d\n", mIsRecording);
552 {
553 dprintf(fd, " Filters:\n");
554 map<int64_t, std::shared_ptr<Filter>>::iterator it;
555 for (it = mFilters.begin(); it != mFilters.end(); it++) {
556 it->second->dump(fd, args, numArgs);
557 }
558 }
559 {
560 dprintf(fd, " TimeFilter:\n");
561 if (mTimeFilter != nullptr) {
562 mTimeFilter->dump(fd, args, numArgs);
563 }
564 }
565 {
566 dprintf(fd, " DvrPlayback:\n");
567 if (mDvrPlayback != nullptr) {
568 mDvrPlayback->dump(fd, args, numArgs);
569 }
570 }
571 {
572 dprintf(fd, " DvrRecord:\n");
573 if (mDvrRecord != nullptr) {
574 mDvrRecord->dump(fd, args, numArgs);
575 }
576 }
577 return STATUS_OK;
578}
579
Hongguang4092f2f2021-07-08 18:49:12 -0700580bool Demux::attachRecordFilter(int64_t filterId) {
581 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
582 !mFilters[filterId]->isRecordFilter()) {
583 return false;
584 }
585
586 mRecordFilterIds.insert(filterId);
587 mFilters[filterId]->attachFilterToRecord(mDvrRecord);
588
589 return true;
590}
591
592bool Demux::detachRecordFilter(int64_t filterId) {
593 if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
594 return false;
595 }
596
597 mRecordFilterIds.erase(filterId);
598 mFilters[filterId]->detachFilterFromRecord();
599
600 return true;
601}
602
603} // namespace tuner
604} // namespace tv
605} // namespace hardware
606} // namespace android
607} // namespace aidl