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