blob: 95b4ebc7a6593de8cc3ffc77aadc0030826db5bc [file] [log] [blame]
Amyfd4243a2019-08-16 16:01:27 -07001/*
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
22namespace android {
23namespace hardware {
24namespace tv {
25namespace tuner {
26namespace V1_0 {
27namespace implementation {
28
Amya609d5a2019-08-23 14:38:31 -070029#define WAIT_TIMEOUT 3000000000
30
Amy5094ae12019-10-04 18:43:21 -070031Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
Amyfd4243a2019-08-16 16:01:27 -070032 mDemuxId = demuxId;
Amy5094ae12019-10-04 18:43:21 -070033 mTunerService = tuner;
Amyfd4243a2019-08-16 16:01:27 -070034}
35
36Demux::~Demux() {}
37
38Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
39 ALOGV("%s", __FUNCTION__);
40
Amy5094ae12019-10-04 18:43:21 -070041 if (mTunerService == nullptr) {
42 return Result::NOT_INITIALIZED;
43 }
Amyfd4243a2019-08-16 16:01:27 -070044
Amy5094ae12019-10-04 18:43:21 -070045 mFrontend = mTunerService->getFrontendById(frontendId);
46
47 if (mFrontend == nullptr) {
48 return Result::INVALID_STATE;
49 }
50
51 mFrontendSourceFile = mFrontend->getSourceFile();
52
53 mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
Amy5ed13572019-12-11 15:33:51 -080054
Amy Zhang0fe25be2020-04-08 17:30:52 -070055 return Result::SUCCESS;
Amyfd4243a2019-08-16 16:01:27 -070056}
57
Amyb4b68012019-10-15 17:38:19 -070058Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
59 const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070060 ALOGV("%s", __FUNCTION__);
61
Amya4885292019-09-06 10:30:53 -070062 uint32_t filterId;
Amya4885292019-09-06 10:30:53 -070063 if (!mUnusedFilterIds.empty()) {
64 filterId = *mUnusedFilterIds.begin();
65
66 mUnusedFilterIds.erase(filterId);
67 } else {
68 filterId = ++mLastUsedFilterId;
Amya4885292019-09-06 10:30:53 -070069 }
70
71 mUsedFilterIds.insert(filterId);
Amya609d5a2019-08-23 14:38:31 -070072
Amyb4b68012019-10-15 17:38:19 -070073 if (cb == nullptr) {
Amya609d5a2019-08-23 14:38:31 -070074 ALOGW("callback can't be null");
Amyb4b68012019-10-15 17:38:19 -070075 _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
Amya609d5a2019-08-23 14:38:31 -070076 return Void();
77 }
Amya4885292019-09-06 10:30:53 -070078
Amyb4b68012019-10-15 17:38:19 -070079 sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
Amya609d5a2019-08-23 14:38:31 -070080
Amyb4b68012019-10-15 17:38:19 -070081 if (!filter->createFilterMQ()) {
82 _hidl_cb(Result::UNKNOWN_ERROR, filter);
Amya609d5a2019-08-23 14:38:31 -070083 return Void();
84 }
Amyb4b68012019-10-15 17:38:19 -070085 mFilters[filterId] = filter;
86
87 _hidl_cb(Result::SUCCESS, filter);
Amya609d5a2019-08-23 14:38:31 -070088 return Void();
89}
90
Amyb4b68012019-10-15 17:38:19 -070091Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070092 ALOGV("%s", __FUNCTION__);
93
Amyb4b68012019-10-15 17:38:19 -070094 sp<TimeFilter> timeFilter = new TimeFilter(this);
Amya609d5a2019-08-23 14:38:31 -070095
Amyb4b68012019-10-15 17:38:19 -070096 _hidl_cb(Result::SUCCESS, timeFilter);
Amya609d5a2019-08-23 14:38:31 -070097 return Void();
98}
99
Amyb4b68012019-10-15 17:38:19 -0700100Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700101 ALOGV("%s", __FUNCTION__);
102
103 AvSyncHwId avSyncHwId = 0;
104
105 _hidl_cb(Result::SUCCESS, avSyncHwId);
106 return Void();
107}
108
109Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
110 ALOGV("%s", __FUNCTION__);
111
112 uint64_t avSyncTime = 0;
113
114 _hidl_cb(Result::SUCCESS, avSyncTime);
115 return Void();
116}
117
Amyfd4243a2019-08-16 16:01:27 -0700118Return<Result> Demux::close() {
119 ALOGV("%s", __FUNCTION__);
120
Amya4885292019-09-06 10:30:53 -0700121 mUnusedFilterIds.clear();
122 mUsedFilterIds.clear();
Amya4885292019-09-06 10:30:53 -0700123 mLastUsedFilterId = -1;
124
Amyfd4243a2019-08-16 16:01:27 -0700125 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700126}
127
Amyb4b68012019-10-15 17:38:19 -0700128Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
129 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700130 ALOGV("%s", __FUNCTION__);
131
Amyb4b68012019-10-15 17:38:19 -0700132 if (cb == nullptr) {
133 ALOGW("DVR callback can't be null");
134 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700135 return Void();
136 }
137
Amy5ed13572019-12-11 15:33:51 -0800138 mDvr = new Dvr(type, bufferSize, cb, this);
Amya4885292019-09-06 10:30:53 -0700139
Amy5ed13572019-12-11 15:33:51 -0800140 if (!mDvr->createDvrMQ()) {
141 _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
Amya4885292019-09-06 10:30:53 -0700142 return Void();
143 }
144
Amy5ed13572019-12-11 15:33:51 -0800145 _hidl_cb(Result::SUCCESS, mDvr);
Amya4885292019-09-06 10:30:53 -0700146 return Void();
147}
148
Henry Fang89f12f52019-11-05 13:48:59 -0800149Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
150 ALOGV("%s", __FUNCTION__);
151
152 mCiCamId = ciCamId;
153
154 return Result::SUCCESS;
155}
156
157Return<Result> Demux::disconnectCiCam() {
158 ALOGV("%s", __FUNCTION__);
159
160 return Result::SUCCESS;
161}
162
Amyb4b68012019-10-15 17:38:19 -0700163Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700164 ALOGV("%s", __FUNCTION__);
165
Amyb4b68012019-10-15 17:38:19 -0700166 // resetFilterRecords(filterId);
167 mUsedFilterIds.erase(filterId);
Amy5ed13572019-12-11 15:33:51 -0800168 mRecordFilterIds.erase(filterId);
Amyb4b68012019-10-15 17:38:19 -0700169 mUnusedFilterIds.insert(filterId);
170 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700171
Amya4885292019-09-06 10:30:53 -0700172 return Result::SUCCESS;
173}
174
Amy5ed13572019-12-11 15:33:51 -0800175void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
Amy5094ae12019-10-04 18:43:21 -0700176 set<uint32_t>::iterator it;
177 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
178 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
Amyb4b68012019-10-15 17:38:19 -0700179 if (DEBUG_FILTER) {
180 ALOGW("start ts filter pid: %d", pid);
181 }
182 if (pid == mFilters[*it]->getTpid()) {
183 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700184 }
185 }
Amy5094ae12019-10-04 18:43:21 -0700186}
187
Amy5ed13572019-12-11 15:33:51 -0800188void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
189 set<uint32_t>::iterator it;
190 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
191 if (DEBUG_FILTER) {
192 ALOGW("update record filter output");
193 }
194 mFilters[*it]->updateRecordOutput(data);
195 }
196}
197
198bool Demux::startBroadcastFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700199 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700200
201 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700202 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700203 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
204 return false;
Amya4885292019-09-06 10:30:53 -0700205 }
Amya609d5a2019-08-23 14:38:31 -0700206 }
207
Amyb4b68012019-10-15 17:38:19 -0700208 return true;
Amya609d5a2019-08-23 14:38:31 -0700209}
210
Amy5ed13572019-12-11 15:33:51 -0800211bool Demux::startRecordFilterDispatcher() {
212 set<uint32_t>::iterator it;
213
214 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
215 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
216 return false;
217 }
218 }
219
220 return true;
221}
222
Amyb4b68012019-10-15 17:38:19 -0700223Result Demux::startFilterHandler(uint32_t filterId) {
224 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700225}
226
Amyb4b68012019-10-15 17:38:19 -0700227void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
228 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700229}
Amya609d5a2019-08-23 14:38:31 -0700230
Amyb4b68012019-10-15 17:38:19 -0700231uint16_t Demux::getFilterTpid(uint32_t filterId) {
232 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700233}
234
Amy Zhang0fe25be2020-04-08 17:30:52 -0700235void Demux::startFrontendInputLoop() {
Amy5ed13572019-12-11 15:33:51 -0800236 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
237 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
Amy5094ae12019-10-04 18:43:21 -0700238}
239
Amy5ed13572019-12-11 15:33:51 -0800240void* Demux::__threadLoopFrontend(void* user) {
Amy5094ae12019-10-04 18:43:21 -0700241 Demux* const self = static_cast<Demux*>(user);
Amy5ed13572019-12-11 15:33:51 -0800242 self->frontendInputThreadLoop();
Amy5094ae12019-10-04 18:43:21 -0700243 return 0;
244}
245
Amy5ed13572019-12-11 15:33:51 -0800246void Demux::frontendInputThreadLoop() {
247 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
248 mFrontendInputThreadRunning = true;
Amy5094ae12019-10-04 18:43:21 -0700249 mKeepFetchingDataFromFrontend = true;
250
251 // open the stream and get its length
252 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
253 // TODO take the packet size from the frontend setting
254 int packetSize = 188;
255 int writePacketAmount = 6;
256 char* buffer = new char[packetSize];
Amy5ed13572019-12-11 15:33:51 -0800257 ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
Amy5094ae12019-10-04 18:43:21 -0700258 if (!inputData.is_open()) {
Amy5ed13572019-12-11 15:33:51 -0800259 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700260 ALOGW("[Demux] Error %s", strerror(errno));
261 }
262
Amy5ed13572019-12-11 15:33:51 -0800263 while (mFrontendInputThreadRunning) {
Amy5094ae12019-10-04 18:43:21 -0700264 // move the stream pointer for packet size * 6 every read until the end
265 while (mKeepFetchingDataFromFrontend) {
266 for (int i = 0; i < writePacketAmount; i++) {
267 inputData.read(buffer, packetSize);
268 if (!inputData) {
Amyb4b68012019-10-15 17:38:19 -0700269 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800270 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700271 break;
272 }
273 // filter and dispatch filter output
274 vector<uint8_t> byteBuffer;
Amy79125022019-10-10 15:30:17 -0700275 byteBuffer.resize(packetSize);
Amy5094ae12019-10-04 18:43:21 -0700276 for (int index = 0; index < byteBuffer.size(); index++) {
277 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
278 }
Amy5ed13572019-12-11 15:33:51 -0800279 if (mIsRecording) {
280 // Feed the data into the Dvr recording input
281 sendFrontendInputToRecord(byteBuffer);
282 } else {
283 // Feed the data into the broadcast demux filter
284 startBroadcastTsFilter(byteBuffer);
285 }
Amy5094ae12019-10-04 18:43:21 -0700286 }
Amy5ed13572019-12-11 15:33:51 -0800287 if (mIsRecording) {
288 // Dispatch the data into the broadcasting filters.
289 startRecordFilterDispatcher();
290 } else {
291 // Dispatch the data into the broadcasting filters.
292 startBroadcastFilterDispatcher();
293 }
Amyb4b68012019-10-15 17:38:19 -0700294 usleep(100);
Amy5094ae12019-10-04 18:43:21 -0700295 }
296 }
297
Amy5ed13572019-12-11 15:33:51 -0800298 ALOGW("[Demux] Frontend Input thread end.");
Amy5094ae12019-10-04 18:43:21 -0700299 delete[] buffer;
300 inputData.close();
301}
302
Amy5ed13572019-12-11 15:33:51 -0800303void Demux::stopFrontendInput() {
Amyb4b68012019-10-15 17:38:19 -0700304 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700305 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800306 mFrontendInputThreadRunning = false;
307 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
308}
309
310void Demux::setIsRecording(bool isRecording) {
311 mIsRecording = isRecording;
312}
313
314bool Demux::attachRecordFilter(int filterId) {
315 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
316 return false;
317 }
318
319 mRecordFilterIds.insert(filterId);
320 mFilters[filterId]->attachFilterToRecord(mDvr);
321
322 return true;
323}
324
325bool Demux::detachRecordFilter(int filterId) {
326 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
327 return false;
328 }
329
330 mRecordFilterIds.erase(filterId);
331 mFilters[filterId]->detachFilterFromRecord();
332
333 return true;
Amy5094ae12019-10-04 18:43:21 -0700334}
335
Amyfd4243a2019-08-16 16:01:27 -0700336} // namespace implementation
337} // namespace V1_0
338} // namespace tuner
339} // namespace tv
340} // namespace hardware
341} // namespace android