xref: /aosp_15_r20/hardware/interfaces/tv/tuner/1.0/default/Demux.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker 
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "[email protected]"
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include "Demux.h"
20*4d7e907cSAndroid Build Coastguard Worker #include <utils/Log.h>
21*4d7e907cSAndroid Build Coastguard Worker 
22*4d7e907cSAndroid Build Coastguard Worker namespace android {
23*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
24*4d7e907cSAndroid Build Coastguard Worker namespace tv {
25*4d7e907cSAndroid Build Coastguard Worker namespace tuner {
26*4d7e907cSAndroid Build Coastguard Worker namespace V1_0 {
27*4d7e907cSAndroid Build Coastguard Worker namespace implementation {
28*4d7e907cSAndroid Build Coastguard Worker 
29*4d7e907cSAndroid Build Coastguard Worker #define WAIT_TIMEOUT 3000000000
30*4d7e907cSAndroid Build Coastguard Worker 
Demux(uint32_t demuxId,sp<Tuner> tuner)31*4d7e907cSAndroid Build Coastguard Worker Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
32*4d7e907cSAndroid Build Coastguard Worker     mDemuxId = demuxId;
33*4d7e907cSAndroid Build Coastguard Worker     mTunerService = tuner;
34*4d7e907cSAndroid Build Coastguard Worker }
35*4d7e907cSAndroid Build Coastguard Worker 
~Demux()36*4d7e907cSAndroid Build Coastguard Worker Demux::~Demux() {}
37*4d7e907cSAndroid Build Coastguard Worker 
setFrontendDataSource(uint32_t frontendId)38*4d7e907cSAndroid Build Coastguard Worker Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
39*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
40*4d7e907cSAndroid Build Coastguard Worker 
41*4d7e907cSAndroid Build Coastguard Worker     if (mTunerService == nullptr) {
42*4d7e907cSAndroid Build Coastguard Worker         return Result::NOT_INITIALIZED;
43*4d7e907cSAndroid Build Coastguard Worker     }
44*4d7e907cSAndroid Build Coastguard Worker 
45*4d7e907cSAndroid Build Coastguard Worker     mFrontend = mTunerService->getFrontendById(frontendId);
46*4d7e907cSAndroid Build Coastguard Worker 
47*4d7e907cSAndroid Build Coastguard Worker     if (mFrontend == nullptr) {
48*4d7e907cSAndroid Build Coastguard Worker         return Result::INVALID_STATE;
49*4d7e907cSAndroid Build Coastguard Worker     }
50*4d7e907cSAndroid Build Coastguard Worker 
51*4d7e907cSAndroid Build Coastguard Worker     mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
52*4d7e907cSAndroid Build Coastguard Worker 
53*4d7e907cSAndroid Build Coastguard Worker     return Result::SUCCESS;
54*4d7e907cSAndroid Build Coastguard Worker }
55*4d7e907cSAndroid Build Coastguard Worker 
openFilter(const DemuxFilterType & type,uint32_t bufferSize,const sp<IFilterCallback> & cb,openFilter_cb _hidl_cb)56*4d7e907cSAndroid Build Coastguard Worker Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
57*4d7e907cSAndroid Build Coastguard Worker                                const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
58*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
59*4d7e907cSAndroid Build Coastguard Worker 
60*4d7e907cSAndroid Build Coastguard Worker     uint32_t filterId;
61*4d7e907cSAndroid Build Coastguard Worker     filterId = ++mLastUsedFilterId;
62*4d7e907cSAndroid Build Coastguard Worker 
63*4d7e907cSAndroid Build Coastguard Worker     if (cb == nullptr) {
64*4d7e907cSAndroid Build Coastguard Worker         ALOGW("[Demux] callback can't be null");
65*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
66*4d7e907cSAndroid Build Coastguard Worker         return Void();
67*4d7e907cSAndroid Build Coastguard Worker     }
68*4d7e907cSAndroid Build Coastguard Worker 
69*4d7e907cSAndroid Build Coastguard Worker     sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
70*4d7e907cSAndroid Build Coastguard Worker 
71*4d7e907cSAndroid Build Coastguard Worker     if (!filter->createFilterMQ()) {
72*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::UNKNOWN_ERROR, filter);
73*4d7e907cSAndroid Build Coastguard Worker         return Void();
74*4d7e907cSAndroid Build Coastguard Worker     }
75*4d7e907cSAndroid Build Coastguard Worker 
76*4d7e907cSAndroid Build Coastguard Worker     mFilters[filterId] = filter;
77*4d7e907cSAndroid Build Coastguard Worker     if (filter->isPcrFilter()) {
78*4d7e907cSAndroid Build Coastguard Worker         mPcrFilterIds.insert(filterId);
79*4d7e907cSAndroid Build Coastguard Worker     }
80*4d7e907cSAndroid Build Coastguard Worker     bool result = true;
81*4d7e907cSAndroid Build Coastguard Worker     if (!filter->isRecordFilter()) {
82*4d7e907cSAndroid Build Coastguard Worker         // Only save non-record filters for now. Record filters are saved when the
83*4d7e907cSAndroid Build Coastguard Worker         // IDvr.attacheFilter is called.
84*4d7e907cSAndroid Build Coastguard Worker         mPlaybackFilterIds.insert(filterId);
85*4d7e907cSAndroid Build Coastguard Worker         if (mDvrPlayback != nullptr) {
86*4d7e907cSAndroid Build Coastguard Worker             result = mDvrPlayback->addPlaybackFilter(filterId, filter);
87*4d7e907cSAndroid Build Coastguard Worker         }
88*4d7e907cSAndroid Build Coastguard Worker     }
89*4d7e907cSAndroid Build Coastguard Worker 
90*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
91*4d7e907cSAndroid Build Coastguard Worker     return Void();
92*4d7e907cSAndroid Build Coastguard Worker }
93*4d7e907cSAndroid Build Coastguard Worker 
openTimeFilter(openTimeFilter_cb _hidl_cb)94*4d7e907cSAndroid Build Coastguard Worker Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
95*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
96*4d7e907cSAndroid Build Coastguard Worker 
97*4d7e907cSAndroid Build Coastguard Worker     mTimeFilter = new TimeFilter(this);
98*4d7e907cSAndroid Build Coastguard Worker 
99*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb(Result::SUCCESS, mTimeFilter);
100*4d7e907cSAndroid Build Coastguard Worker     return Void();
101*4d7e907cSAndroid Build Coastguard Worker }
102*4d7e907cSAndroid Build Coastguard Worker 
getAvSyncHwId(const sp<IFilter> & filter,getAvSyncHwId_cb _hidl_cb)103*4d7e907cSAndroid Build Coastguard Worker Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
104*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
105*4d7e907cSAndroid Build Coastguard Worker 
106*4d7e907cSAndroid Build Coastguard Worker     uint32_t avSyncHwId = -1;
107*4d7e907cSAndroid Build Coastguard Worker     int id;
108*4d7e907cSAndroid Build Coastguard Worker     Result status;
109*4d7e907cSAndroid Build Coastguard Worker 
110*4d7e907cSAndroid Build Coastguard Worker     filter->getId([&](Result result, uint32_t filterId) {
111*4d7e907cSAndroid Build Coastguard Worker         id = filterId;
112*4d7e907cSAndroid Build Coastguard Worker         status = result;
113*4d7e907cSAndroid Build Coastguard Worker     });
114*4d7e907cSAndroid Build Coastguard Worker 
115*4d7e907cSAndroid Build Coastguard Worker     if (status != Result::SUCCESS) {
116*4d7e907cSAndroid Build Coastguard Worker         ALOGE("[Demux] Can't get filter Id.");
117*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::INVALID_STATE, avSyncHwId);
118*4d7e907cSAndroid Build Coastguard Worker         return Void();
119*4d7e907cSAndroid Build Coastguard Worker     }
120*4d7e907cSAndroid Build Coastguard Worker 
121*4d7e907cSAndroid Build Coastguard Worker     if (!mFilters[id]->isMediaFilter()) {
122*4d7e907cSAndroid Build Coastguard Worker         ALOGE("[Demux] Given filter is not a media filter.");
123*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
124*4d7e907cSAndroid Build Coastguard Worker         return Void();
125*4d7e907cSAndroid Build Coastguard Worker     }
126*4d7e907cSAndroid Build Coastguard Worker 
127*4d7e907cSAndroid Build Coastguard Worker     if (!mPcrFilterIds.empty()) {
128*4d7e907cSAndroid Build Coastguard Worker         // Return the lowest pcr filter id in the default implementation as the av sync id
129*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
130*4d7e907cSAndroid Build Coastguard Worker         return Void();
131*4d7e907cSAndroid Build Coastguard Worker     }
132*4d7e907cSAndroid Build Coastguard Worker 
133*4d7e907cSAndroid Build Coastguard Worker     ALOGE("[Demux] No PCR filter opened.");
134*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb(Result::INVALID_STATE, avSyncHwId);
135*4d7e907cSAndroid Build Coastguard Worker     return Void();
136*4d7e907cSAndroid Build Coastguard Worker }
137*4d7e907cSAndroid Build Coastguard Worker 
getAvSyncTime(AvSyncHwId avSyncHwId,getAvSyncTime_cb _hidl_cb)138*4d7e907cSAndroid Build Coastguard Worker Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
139*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
140*4d7e907cSAndroid Build Coastguard Worker 
141*4d7e907cSAndroid Build Coastguard Worker     uint64_t avSyncTime = -1;
142*4d7e907cSAndroid Build Coastguard Worker     if (mPcrFilterIds.empty()) {
143*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::INVALID_STATE, avSyncTime);
144*4d7e907cSAndroid Build Coastguard Worker         return Void();
145*4d7e907cSAndroid Build Coastguard Worker     }
146*4d7e907cSAndroid Build Coastguard Worker     if (avSyncHwId != *mPcrFilterIds.begin()) {
147*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime);
148*4d7e907cSAndroid Build Coastguard Worker         return Void();
149*4d7e907cSAndroid Build Coastguard Worker     }
150*4d7e907cSAndroid Build Coastguard Worker 
151*4d7e907cSAndroid Build Coastguard Worker     _hidl_cb(Result::SUCCESS, avSyncTime);
152*4d7e907cSAndroid Build Coastguard Worker     return Void();
153*4d7e907cSAndroid Build Coastguard Worker }
154*4d7e907cSAndroid Build Coastguard Worker 
close()155*4d7e907cSAndroid Build Coastguard Worker Return<Result> Demux::close() {
156*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
157*4d7e907cSAndroid Build Coastguard Worker 
158*4d7e907cSAndroid Build Coastguard Worker     set<uint32_t>::iterator it;
159*4d7e907cSAndroid Build Coastguard Worker     for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
160*4d7e907cSAndroid Build Coastguard Worker         mDvrPlayback->removePlaybackFilter(*it);
161*4d7e907cSAndroid Build Coastguard Worker     }
162*4d7e907cSAndroid Build Coastguard Worker     mPlaybackFilterIds.clear();
163*4d7e907cSAndroid Build Coastguard Worker     mRecordFilterIds.clear();
164*4d7e907cSAndroid Build Coastguard Worker     mFilters.clear();
165*4d7e907cSAndroid Build Coastguard Worker     mLastUsedFilterId = -1;
166*4d7e907cSAndroid Build Coastguard Worker     mTunerService->removeDemux(mDemuxId);
167*4d7e907cSAndroid Build Coastguard Worker 
168*4d7e907cSAndroid Build Coastguard Worker     return Result::SUCCESS;
169*4d7e907cSAndroid Build Coastguard Worker }
170*4d7e907cSAndroid Build Coastguard Worker 
openDvr(DvrType type,uint32_t bufferSize,const sp<IDvrCallback> & cb,openDvr_cb _hidl_cb)171*4d7e907cSAndroid Build Coastguard Worker Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
172*4d7e907cSAndroid Build Coastguard Worker                             openDvr_cb _hidl_cb) {
173*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
174*4d7e907cSAndroid Build Coastguard Worker 
175*4d7e907cSAndroid Build Coastguard Worker     if (cb == nullptr) {
176*4d7e907cSAndroid Build Coastguard Worker         ALOGW("[Demux] DVR callback can't be null");
177*4d7e907cSAndroid Build Coastguard Worker         _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
178*4d7e907cSAndroid Build Coastguard Worker         return Void();
179*4d7e907cSAndroid Build Coastguard Worker     }
180*4d7e907cSAndroid Build Coastguard Worker 
181*4d7e907cSAndroid Build Coastguard Worker     set<uint32_t>::iterator it;
182*4d7e907cSAndroid Build Coastguard Worker     switch (type) {
183*4d7e907cSAndroid Build Coastguard Worker         case DvrType::PLAYBACK:
184*4d7e907cSAndroid Build Coastguard Worker             mDvrPlayback = new Dvr(type, bufferSize, cb, this);
185*4d7e907cSAndroid Build Coastguard Worker             if (!mDvrPlayback->createDvrMQ()) {
186*4d7e907cSAndroid Build Coastguard Worker                 _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
187*4d7e907cSAndroid Build Coastguard Worker                 return Void();
188*4d7e907cSAndroid Build Coastguard Worker             }
189*4d7e907cSAndroid Build Coastguard Worker 
190*4d7e907cSAndroid Build Coastguard Worker             for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
191*4d7e907cSAndroid Build Coastguard Worker                 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
192*4d7e907cSAndroid Build Coastguard Worker                     ALOGE("[Demux] Can't get filter info for DVR playback");
193*4d7e907cSAndroid Build Coastguard Worker                     _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
194*4d7e907cSAndroid Build Coastguard Worker                     return Void();
195*4d7e907cSAndroid Build Coastguard Worker                 }
196*4d7e907cSAndroid Build Coastguard Worker             }
197*4d7e907cSAndroid Build Coastguard Worker 
198*4d7e907cSAndroid Build Coastguard Worker             _hidl_cb(Result::SUCCESS, mDvrPlayback);
199*4d7e907cSAndroid Build Coastguard Worker             return Void();
200*4d7e907cSAndroid Build Coastguard Worker         case DvrType::RECORD:
201*4d7e907cSAndroid Build Coastguard Worker             mDvrRecord = new Dvr(type, bufferSize, cb, this);
202*4d7e907cSAndroid Build Coastguard Worker             if (!mDvrRecord->createDvrMQ()) {
203*4d7e907cSAndroid Build Coastguard Worker                 _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
204*4d7e907cSAndroid Build Coastguard Worker                 return Void();
205*4d7e907cSAndroid Build Coastguard Worker             }
206*4d7e907cSAndroid Build Coastguard Worker 
207*4d7e907cSAndroid Build Coastguard Worker             _hidl_cb(Result::SUCCESS, mDvrRecord);
208*4d7e907cSAndroid Build Coastguard Worker             return Void();
209*4d7e907cSAndroid Build Coastguard Worker         default:
210*4d7e907cSAndroid Build Coastguard Worker             _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
211*4d7e907cSAndroid Build Coastguard Worker             return Void();
212*4d7e907cSAndroid Build Coastguard Worker     }
213*4d7e907cSAndroid Build Coastguard Worker }
214*4d7e907cSAndroid Build Coastguard Worker 
connectCiCam(uint32_t ciCamId)215*4d7e907cSAndroid Build Coastguard Worker Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
216*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
217*4d7e907cSAndroid Build Coastguard Worker 
218*4d7e907cSAndroid Build Coastguard Worker     mCiCamId = ciCamId;
219*4d7e907cSAndroid Build Coastguard Worker 
220*4d7e907cSAndroid Build Coastguard Worker     return Result::SUCCESS;
221*4d7e907cSAndroid Build Coastguard Worker }
222*4d7e907cSAndroid Build Coastguard Worker 
disconnectCiCam()223*4d7e907cSAndroid Build Coastguard Worker Return<Result> Demux::disconnectCiCam() {
224*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
225*4d7e907cSAndroid Build Coastguard Worker 
226*4d7e907cSAndroid Build Coastguard Worker     return Result::SUCCESS;
227*4d7e907cSAndroid Build Coastguard Worker }
228*4d7e907cSAndroid Build Coastguard Worker 
removeFilter(uint32_t filterId)229*4d7e907cSAndroid Build Coastguard Worker Result Demux::removeFilter(uint32_t filterId) {
230*4d7e907cSAndroid Build Coastguard Worker     ALOGV("%s", __FUNCTION__);
231*4d7e907cSAndroid Build Coastguard Worker 
232*4d7e907cSAndroid Build Coastguard Worker     if (mDvrPlayback != nullptr) {
233*4d7e907cSAndroid Build Coastguard Worker         mDvrPlayback->removePlaybackFilter(filterId);
234*4d7e907cSAndroid Build Coastguard Worker     }
235*4d7e907cSAndroid Build Coastguard Worker     mPlaybackFilterIds.erase(filterId);
236*4d7e907cSAndroid Build Coastguard Worker     mRecordFilterIds.erase(filterId);
237*4d7e907cSAndroid Build Coastguard Worker     mFilters.erase(filterId);
238*4d7e907cSAndroid Build Coastguard Worker 
239*4d7e907cSAndroid Build Coastguard Worker     return Result::SUCCESS;
240*4d7e907cSAndroid Build Coastguard Worker }
241*4d7e907cSAndroid Build Coastguard Worker 
startBroadcastTsFilter(vector<uint8_t> data)242*4d7e907cSAndroid Build Coastguard Worker void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
243*4d7e907cSAndroid Build Coastguard Worker     set<uint32_t>::iterator it;
244*4d7e907cSAndroid Build Coastguard Worker     uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
245*4d7e907cSAndroid Build Coastguard Worker     if (DEBUG_DEMUX) {
246*4d7e907cSAndroid Build Coastguard Worker         ALOGW("[Demux] start ts filter pid: %d", pid);
247*4d7e907cSAndroid Build Coastguard Worker     }
248*4d7e907cSAndroid Build Coastguard Worker     for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
249*4d7e907cSAndroid Build Coastguard Worker         if (pid == mFilters[*it]->getTpid()) {
250*4d7e907cSAndroid Build Coastguard Worker             mFilters[*it]->updateFilterOutput(data);
251*4d7e907cSAndroid Build Coastguard Worker         }
252*4d7e907cSAndroid Build Coastguard Worker     }
253*4d7e907cSAndroid Build Coastguard Worker }
254*4d7e907cSAndroid Build Coastguard Worker 
sendFrontendInputToRecord(vector<uint8_t> data)255*4d7e907cSAndroid Build Coastguard Worker void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
256*4d7e907cSAndroid Build Coastguard Worker     set<uint32_t>::iterator it;
257*4d7e907cSAndroid Build Coastguard Worker     if (DEBUG_DEMUX) {
258*4d7e907cSAndroid Build Coastguard Worker         ALOGW("[Demux] update record filter output");
259*4d7e907cSAndroid Build Coastguard Worker     }
260*4d7e907cSAndroid Build Coastguard Worker     for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
261*4d7e907cSAndroid Build Coastguard Worker         mFilters[*it]->updateRecordOutput(data);
262*4d7e907cSAndroid Build Coastguard Worker     }
263*4d7e907cSAndroid Build Coastguard Worker }
264*4d7e907cSAndroid Build Coastguard Worker 
startBroadcastFilterDispatcher()265*4d7e907cSAndroid Build Coastguard Worker bool Demux::startBroadcastFilterDispatcher() {
266*4d7e907cSAndroid Build Coastguard Worker     set<uint32_t>::iterator it;
267*4d7e907cSAndroid Build Coastguard Worker 
268*4d7e907cSAndroid Build Coastguard Worker     // Handle the output data per filter type
269*4d7e907cSAndroid Build Coastguard Worker     for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
270*4d7e907cSAndroid Build Coastguard Worker         if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
271*4d7e907cSAndroid Build Coastguard Worker             return false;
272*4d7e907cSAndroid Build Coastguard Worker         }
273*4d7e907cSAndroid Build Coastguard Worker     }
274*4d7e907cSAndroid Build Coastguard Worker 
275*4d7e907cSAndroid Build Coastguard Worker     return true;
276*4d7e907cSAndroid Build Coastguard Worker }
277*4d7e907cSAndroid Build Coastguard Worker 
startRecordFilterDispatcher()278*4d7e907cSAndroid Build Coastguard Worker bool Demux::startRecordFilterDispatcher() {
279*4d7e907cSAndroid Build Coastguard Worker     set<uint32_t>::iterator it;
280*4d7e907cSAndroid Build Coastguard Worker 
281*4d7e907cSAndroid Build Coastguard Worker     for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
282*4d7e907cSAndroid Build Coastguard Worker         if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
283*4d7e907cSAndroid Build Coastguard Worker             return false;
284*4d7e907cSAndroid Build Coastguard Worker         }
285*4d7e907cSAndroid Build Coastguard Worker     }
286*4d7e907cSAndroid Build Coastguard Worker 
287*4d7e907cSAndroid Build Coastguard Worker     return true;
288*4d7e907cSAndroid Build Coastguard Worker }
289*4d7e907cSAndroid Build Coastguard Worker 
startFilterHandler(uint32_t filterId)290*4d7e907cSAndroid Build Coastguard Worker Result Demux::startFilterHandler(uint32_t filterId) {
291*4d7e907cSAndroid Build Coastguard Worker     return mFilters[filterId]->startFilterHandler();
292*4d7e907cSAndroid Build Coastguard Worker }
293*4d7e907cSAndroid Build Coastguard Worker 
updateFilterOutput(uint16_t filterId,vector<uint8_t> data)294*4d7e907cSAndroid Build Coastguard Worker void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
295*4d7e907cSAndroid Build Coastguard Worker     mFilters[filterId]->updateFilterOutput(data);
296*4d7e907cSAndroid Build Coastguard Worker }
297*4d7e907cSAndroid Build Coastguard Worker 
updateMediaFilterOutput(uint16_t filterId,vector<uint8_t> data,uint64_t pts)298*4d7e907cSAndroid Build Coastguard Worker void Demux::updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts) {
299*4d7e907cSAndroid Build Coastguard Worker     updateFilterOutput(filterId, data);
300*4d7e907cSAndroid Build Coastguard Worker     mFilters[filterId]->updatePts(pts);
301*4d7e907cSAndroid Build Coastguard Worker }
302*4d7e907cSAndroid Build Coastguard Worker 
getFilterTpid(uint32_t filterId)303*4d7e907cSAndroid Build Coastguard Worker uint16_t Demux::getFilterTpid(uint32_t filterId) {
304*4d7e907cSAndroid Build Coastguard Worker     return mFilters[filterId]->getTpid();
305*4d7e907cSAndroid Build Coastguard Worker }
306*4d7e907cSAndroid Build Coastguard Worker 
startFrontendInputLoop()307*4d7e907cSAndroid Build Coastguard Worker void Demux::startFrontendInputLoop() {
308*4d7e907cSAndroid Build Coastguard Worker     pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
309*4d7e907cSAndroid Build Coastguard Worker     pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
310*4d7e907cSAndroid Build Coastguard Worker }
311*4d7e907cSAndroid Build Coastguard Worker 
__threadLoopFrontend(void * user)312*4d7e907cSAndroid Build Coastguard Worker void* Demux::__threadLoopFrontend(void* user) {
313*4d7e907cSAndroid Build Coastguard Worker     Demux* const self = static_cast<Demux*>(user);
314*4d7e907cSAndroid Build Coastguard Worker     self->frontendInputThreadLoop();
315*4d7e907cSAndroid Build Coastguard Worker     return 0;
316*4d7e907cSAndroid Build Coastguard Worker }
317*4d7e907cSAndroid Build Coastguard Worker 
frontendInputThreadLoop()318*4d7e907cSAndroid Build Coastguard Worker void Demux::frontendInputThreadLoop() {
319*4d7e907cSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
320*4d7e907cSAndroid Build Coastguard Worker     mFrontendInputThreadRunning = true;
321*4d7e907cSAndroid Build Coastguard Worker 
322*4d7e907cSAndroid Build Coastguard Worker     if (!mDvrPlayback) {
323*4d7e907cSAndroid Build Coastguard Worker         ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
324*4d7e907cSAndroid Build Coastguard Worker         mFrontendInputThreadRunning = false;
325*4d7e907cSAndroid Build Coastguard Worker         return;
326*4d7e907cSAndroid Build Coastguard Worker     }
327*4d7e907cSAndroid Build Coastguard Worker 
328*4d7e907cSAndroid Build Coastguard Worker     while (mFrontendInputThreadRunning) {
329*4d7e907cSAndroid Build Coastguard Worker         uint32_t efState = 0;
330*4d7e907cSAndroid Build Coastguard Worker         status_t status = mDvrPlayback->getDvrEventFlag()->wait(
331*4d7e907cSAndroid Build Coastguard Worker                 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
332*4d7e907cSAndroid Build Coastguard Worker                 true /* retry on spurious wake */);
333*4d7e907cSAndroid Build Coastguard Worker         if (status != OK) {
334*4d7e907cSAndroid Build Coastguard Worker             ALOGD("[Demux] wait for data ready on the playback FMQ");
335*4d7e907cSAndroid Build Coastguard Worker             continue;
336*4d7e907cSAndroid Build Coastguard Worker         }
337*4d7e907cSAndroid Build Coastguard Worker         if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) {
338*4d7e907cSAndroid Build Coastguard Worker             if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
339*4d7e907cSAndroid Build Coastguard Worker                 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
340*4d7e907cSAndroid Build Coastguard Worker                 break;
341*4d7e907cSAndroid Build Coastguard Worker             }
342*4d7e907cSAndroid Build Coastguard Worker         }
343*4d7e907cSAndroid Build Coastguard Worker         // Our current implementation filter the data and write it into the filter FMQ immediately
344*4d7e907cSAndroid Build Coastguard Worker         // after the DATA_READY from the VTS/framework
345*4d7e907cSAndroid Build Coastguard Worker         if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
346*4d7e907cSAndroid Build Coastguard Worker             !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
347*4d7e907cSAndroid Build Coastguard Worker             ALOGE("[Demux] playback data failed to be filtered. Ending thread");
348*4d7e907cSAndroid Build Coastguard Worker             break;
349*4d7e907cSAndroid Build Coastguard Worker         }
350*4d7e907cSAndroid Build Coastguard Worker     }
351*4d7e907cSAndroid Build Coastguard Worker 
352*4d7e907cSAndroid Build Coastguard Worker     mFrontendInputThreadRunning = false;
353*4d7e907cSAndroid Build Coastguard Worker     ALOGW("[Demux] Frontend Input thread end.");
354*4d7e907cSAndroid Build Coastguard Worker }
355*4d7e907cSAndroid Build Coastguard Worker 
stopFrontendInput()356*4d7e907cSAndroid Build Coastguard Worker void Demux::stopFrontendInput() {
357*4d7e907cSAndroid Build Coastguard Worker     ALOGD("[Demux] stop frontend on demux");
358*4d7e907cSAndroid Build Coastguard Worker     mKeepFetchingDataFromFrontend = false;
359*4d7e907cSAndroid Build Coastguard Worker     mFrontendInputThreadRunning = false;
360*4d7e907cSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
361*4d7e907cSAndroid Build Coastguard Worker }
362*4d7e907cSAndroid Build Coastguard Worker 
setIsRecording(bool isRecording)363*4d7e907cSAndroid Build Coastguard Worker void Demux::setIsRecording(bool isRecording) {
364*4d7e907cSAndroid Build Coastguard Worker     mIsRecording = isRecording;
365*4d7e907cSAndroid Build Coastguard Worker }
366*4d7e907cSAndroid Build Coastguard Worker 
attachRecordFilter(int filterId)367*4d7e907cSAndroid Build Coastguard Worker bool Demux::attachRecordFilter(int filterId) {
368*4d7e907cSAndroid Build Coastguard Worker     if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
369*4d7e907cSAndroid Build Coastguard Worker         !mFilters[filterId]->isRecordFilter()) {
370*4d7e907cSAndroid Build Coastguard Worker         return false;
371*4d7e907cSAndroid Build Coastguard Worker     }
372*4d7e907cSAndroid Build Coastguard Worker 
373*4d7e907cSAndroid Build Coastguard Worker     mRecordFilterIds.insert(filterId);
374*4d7e907cSAndroid Build Coastguard Worker     mFilters[filterId]->attachFilterToRecord(mDvrRecord);
375*4d7e907cSAndroid Build Coastguard Worker 
376*4d7e907cSAndroid Build Coastguard Worker     return true;
377*4d7e907cSAndroid Build Coastguard Worker }
378*4d7e907cSAndroid Build Coastguard Worker 
detachRecordFilter(int filterId)379*4d7e907cSAndroid Build Coastguard Worker bool Demux::detachRecordFilter(int filterId) {
380*4d7e907cSAndroid Build Coastguard Worker     if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
381*4d7e907cSAndroid Build Coastguard Worker         return false;
382*4d7e907cSAndroid Build Coastguard Worker     }
383*4d7e907cSAndroid Build Coastguard Worker 
384*4d7e907cSAndroid Build Coastguard Worker     mRecordFilterIds.erase(filterId);
385*4d7e907cSAndroid Build Coastguard Worker     mFilters[filterId]->detachFilterFromRecord();
386*4d7e907cSAndroid Build Coastguard Worker 
387*4d7e907cSAndroid Build Coastguard Worker     return true;
388*4d7e907cSAndroid Build Coastguard Worker }
389*4d7e907cSAndroid Build Coastguard Worker 
390*4d7e907cSAndroid Build Coastguard Worker }  // namespace implementation
391*4d7e907cSAndroid Build Coastguard Worker }  // namespace V1_0
392*4d7e907cSAndroid Build Coastguard Worker }  // namespace tuner
393*4d7e907cSAndroid Build Coastguard Worker }  // namespace tv
394*4d7e907cSAndroid Build Coastguard Worker }  // namespace hardware
395*4d7e907cSAndroid Build Coastguard Worker }  // namespace android
396