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