• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "android.hardware.tv.tuner@1.0-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 
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     mTunerService->removeDemux(mDemuxId);
167 
168     return Result::SUCCESS;
169 }
170 
openDvr(DvrType type,uint32_t bufferSize,const sp<IDvrCallback> & cb,openDvr_cb _hidl_cb)171 Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
172                             openDvr_cb _hidl_cb) {
173     ALOGV("%s", __FUNCTION__);
174 
175     if (cb == nullptr) {
176         ALOGW("[Demux] DVR callback can't be null");
177         _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
178         return Void();
179     }
180 
181     set<uint32_t>::iterator it;
182     switch (type) {
183         case DvrType::PLAYBACK:
184             mDvrPlayback = new Dvr(type, bufferSize, cb, this);
185             if (!mDvrPlayback->createDvrMQ()) {
186                 _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
187                 return Void();
188             }
189 
190             for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
191                 if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
192                     ALOGE("[Demux] Can't get filter info for DVR playback");
193                     _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
194                     return Void();
195                 }
196             }
197 
198             _hidl_cb(Result::SUCCESS, mDvrPlayback);
199             return Void();
200         case DvrType::RECORD:
201             mDvrRecord = new Dvr(type, bufferSize, cb, this);
202             if (!mDvrRecord->createDvrMQ()) {
203                 _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
204                 return Void();
205             }
206 
207             _hidl_cb(Result::SUCCESS, mDvrRecord);
208             return Void();
209         default:
210             _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
211             return Void();
212     }
213 }
214 
connectCiCam(uint32_t ciCamId)215 Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
216     ALOGV("%s", __FUNCTION__);
217 
218     mCiCamId = ciCamId;
219 
220     return Result::SUCCESS;
221 }
222 
disconnectCiCam()223 Return<Result> Demux::disconnectCiCam() {
224     ALOGV("%s", __FUNCTION__);
225 
226     return Result::SUCCESS;
227 }
228 
removeFilter(uint32_t filterId)229 Result Demux::removeFilter(uint32_t filterId) {
230     ALOGV("%s", __FUNCTION__);
231 
232     if (mDvrPlayback != nullptr) {
233         mDvrPlayback->removePlaybackFilter(filterId);
234     }
235     mPlaybackFilterIds.erase(filterId);
236     mRecordFilterIds.erase(filterId);
237     mFilters.erase(filterId);
238 
239     return Result::SUCCESS;
240 }
241 
startBroadcastTsFilter(vector<uint8_t> data)242 void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
243     set<uint32_t>::iterator it;
244     uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
245     if (DEBUG_DEMUX) {
246         ALOGW("[Demux] start ts filter pid: %d", pid);
247     }
248     for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
249         if (pid == mFilters[*it]->getTpid()) {
250             mFilters[*it]->updateFilterOutput(data);
251         }
252     }
253 }
254 
sendFrontendInputToRecord(vector<uint8_t> data)255 void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
256     set<uint32_t>::iterator it;
257     if (DEBUG_DEMUX) {
258         ALOGW("[Demux] update record filter output");
259     }
260     for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
261         mFilters[*it]->updateRecordOutput(data);
262     }
263 }
264 
startBroadcastFilterDispatcher()265 bool Demux::startBroadcastFilterDispatcher() {
266     set<uint32_t>::iterator it;
267 
268     // Handle the output data per filter type
269     for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
270         if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
271             return false;
272         }
273     }
274 
275     return true;
276 }
277 
startRecordFilterDispatcher()278 bool Demux::startRecordFilterDispatcher() {
279     set<uint32_t>::iterator it;
280 
281     for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
282         if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
283             return false;
284         }
285     }
286 
287     return true;
288 }
289 
startFilterHandler(uint32_t filterId)290 Result Demux::startFilterHandler(uint32_t filterId) {
291     return mFilters[filterId]->startFilterHandler();
292 }
293 
updateFilterOutput(uint16_t filterId,vector<uint8_t> data)294 void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
295     mFilters[filterId]->updateFilterOutput(data);
296 }
297 
updateMediaFilterOutput(uint16_t filterId,vector<uint8_t> data,uint64_t pts)298 void Demux::updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts) {
299     updateFilterOutput(filterId, data);
300     mFilters[filterId]->updatePts(pts);
301 }
302 
getFilterTpid(uint32_t filterId)303 uint16_t Demux::getFilterTpid(uint32_t filterId) {
304     return mFilters[filterId]->getTpid();
305 }
306 
startFrontendInputLoop()307 void Demux::startFrontendInputLoop() {
308     pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
309     pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
310 }
311 
__threadLoopFrontend(void * user)312 void* Demux::__threadLoopFrontend(void* user) {
313     Demux* const self = static_cast<Demux*>(user);
314     self->frontendInputThreadLoop();
315     return 0;
316 }
317 
frontendInputThreadLoop()318 void Demux::frontendInputThreadLoop() {
319     std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
320     mFrontendInputThreadRunning = true;
321 
322     if (!mDvrPlayback) {
323         ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
324         mFrontendInputThreadRunning = false;
325         return;
326     }
327 
328     while (mFrontendInputThreadRunning) {
329         uint32_t efState = 0;
330         status_t status = mDvrPlayback->getDvrEventFlag()->wait(
331                 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
332                 true /* retry on spurious wake */);
333         if (status != OK) {
334             ALOGD("[Demux] wait for data ready on the playback FMQ");
335             continue;
336         }
337         if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) {
338             if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
339                 ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
340                 break;
341             }
342         }
343         // Our current implementation filter the data and write it into the filter FMQ immediately
344         // after the DATA_READY from the VTS/framework
345         if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
346             !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
347             ALOGE("[Demux] playback data failed to be filtered. Ending thread");
348             break;
349         }
350     }
351 
352     mFrontendInputThreadRunning = false;
353     ALOGW("[Demux] Frontend Input thread end.");
354 }
355 
stopFrontendInput()356 void Demux::stopFrontendInput() {
357     ALOGD("[Demux] stop frontend on demux");
358     mKeepFetchingDataFromFrontend = false;
359     mFrontendInputThreadRunning = false;
360     std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
361 }
362 
setIsRecording(bool isRecording)363 void Demux::setIsRecording(bool isRecording) {
364     mIsRecording = isRecording;
365 }
366 
attachRecordFilter(int filterId)367 bool Demux::attachRecordFilter(int filterId) {
368     if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
369         !mFilters[filterId]->isRecordFilter()) {
370         return false;
371     }
372 
373     mRecordFilterIds.insert(filterId);
374     mFilters[filterId]->attachFilterToRecord(mDvrRecord);
375 
376     return true;
377 }
378 
detachRecordFilter(int filterId)379 bool Demux::detachRecordFilter(int filterId) {
380     if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
381         return false;
382     }
383 
384     mRecordFilterIds.erase(filterId);
385     mFilters[filterId]->detachFilterFromRecord();
386 
387     return true;
388 }
389 
390 }  // namespace implementation
391 }  // namespace V1_0
392 }  // namespace tuner
393 }  // namespace tv
394 }  // namespace hardware
395 }  // namespace android
396