blob: 43c4e3a086ef05afde5cdfdb31afe90f83214cc1 [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
55 return startFrontendInputLoop();
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;
63
64 if (!mUnusedFilterIds.empty()) {
65 filterId = *mUnusedFilterIds.begin();
66
67 mUnusedFilterIds.erase(filterId);
68 } else {
69 filterId = ++mLastUsedFilterId;
Amya4885292019-09-06 10:30:53 -070070 }
71
72 mUsedFilterIds.insert(filterId);
Amya609d5a2019-08-23 14:38:31 -070073
Amyb4b68012019-10-15 17:38:19 -070074 if (cb == nullptr) {
Amya609d5a2019-08-23 14:38:31 -070075 ALOGW("callback can't be null");
Amyb4b68012019-10-15 17:38:19 -070076 _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
Amya609d5a2019-08-23 14:38:31 -070077 return Void();
78 }
Amya4885292019-09-06 10:30:53 -070079
Amyb4b68012019-10-15 17:38:19 -070080 sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
Amya609d5a2019-08-23 14:38:31 -070081
Amyb4b68012019-10-15 17:38:19 -070082 if (!filter->createFilterMQ()) {
83 _hidl_cb(Result::UNKNOWN_ERROR, filter);
Amya609d5a2019-08-23 14:38:31 -070084 return Void();
85 }
86
Amyb4b68012019-10-15 17:38:19 -070087 mFilters[filterId] = filter;
88
89 _hidl_cb(Result::SUCCESS, filter);
Amya609d5a2019-08-23 14:38:31 -070090 return Void();
91}
92
Amyb4b68012019-10-15 17:38:19 -070093Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070094 ALOGV("%s", __FUNCTION__);
95
Amyb4b68012019-10-15 17:38:19 -070096 sp<TimeFilter> timeFilter = new TimeFilter(this);
Amya609d5a2019-08-23 14:38:31 -070097
Amyb4b68012019-10-15 17:38:19 -070098 _hidl_cb(Result::SUCCESS, timeFilter);
Amya609d5a2019-08-23 14:38:31 -070099 return Void();
100}
101
Amyb4b68012019-10-15 17:38:19 -0700102Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700103 ALOGV("%s", __FUNCTION__);
104
105 AvSyncHwId avSyncHwId = 0;
106
107 _hidl_cb(Result::SUCCESS, avSyncHwId);
108 return Void();
109}
110
111Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
112 ALOGV("%s", __FUNCTION__);
113
114 uint64_t avSyncTime = 0;
115
116 _hidl_cb(Result::SUCCESS, avSyncTime);
117 return Void();
118}
119
Amyfd4243a2019-08-16 16:01:27 -0700120Return<Result> Demux::close() {
121 ALOGV("%s", __FUNCTION__);
122
Amya4885292019-09-06 10:30:53 -0700123 mUnusedFilterIds.clear();
124 mUsedFilterIds.clear();
Amya4885292019-09-06 10:30:53 -0700125 mLastUsedFilterId = -1;
126
Amyfd4243a2019-08-16 16:01:27 -0700127 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700128}
129
Amyb4b68012019-10-15 17:38:19 -0700130Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
131 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700132 ALOGV("%s", __FUNCTION__);
133
Amyb4b68012019-10-15 17:38:19 -0700134 if (cb == nullptr) {
135 ALOGW("DVR callback can't be null");
136 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700137 return Void();
138 }
139
Amy5ed13572019-12-11 15:33:51 -0800140 mDvr = new Dvr(type, bufferSize, cb, this);
Amya4885292019-09-06 10:30:53 -0700141
Amy5ed13572019-12-11 15:33:51 -0800142 if (!mDvr->createDvrMQ()) {
143 _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
Amya4885292019-09-06 10:30:53 -0700144 return Void();
145 }
146
Amy5ed13572019-12-11 15:33:51 -0800147 _hidl_cb(Result::SUCCESS, mDvr);
Amya4885292019-09-06 10:30:53 -0700148 return Void();
149}
150
Henry Fang89f12f52019-11-05 13:48:59 -0800151Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
152 ALOGV("%s", __FUNCTION__);
153
154 mCiCamId = ciCamId;
155
156 return Result::SUCCESS;
157}
158
159Return<Result> Demux::disconnectCiCam() {
160 ALOGV("%s", __FUNCTION__);
161
162 return Result::SUCCESS;
163}
164
Amyb4b68012019-10-15 17:38:19 -0700165Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700166 ALOGV("%s", __FUNCTION__);
167
Amyb4b68012019-10-15 17:38:19 -0700168 // resetFilterRecords(filterId);
169 mUsedFilterIds.erase(filterId);
Amy5ed13572019-12-11 15:33:51 -0800170 mRecordFilterIds.erase(filterId);
Amyb4b68012019-10-15 17:38:19 -0700171 mUnusedFilterIds.insert(filterId);
172 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700173
Amya4885292019-09-06 10:30:53 -0700174 return Result::SUCCESS;
175}
176
Amy5ed13572019-12-11 15:33:51 -0800177void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
Amy5094ae12019-10-04 18:43:21 -0700178 set<uint32_t>::iterator it;
179 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
180 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
Amyb4b68012019-10-15 17:38:19 -0700181 if (DEBUG_FILTER) {
182 ALOGW("start ts filter pid: %d", pid);
183 }
184 if (pid == mFilters[*it]->getTpid()) {
185 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700186 }
187 }
Amy5094ae12019-10-04 18:43:21 -0700188}
189
Amy5ed13572019-12-11 15:33:51 -0800190void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
191 set<uint32_t>::iterator it;
192 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
193 if (DEBUG_FILTER) {
194 ALOGW("update record filter output");
195 }
196 mFilters[*it]->updateRecordOutput(data);
197 }
198}
199
200bool Demux::startBroadcastFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700201 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700202
203 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700204 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700205 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
206 return false;
Amya4885292019-09-06 10:30:53 -0700207 }
Amya609d5a2019-08-23 14:38:31 -0700208 }
209
Amyb4b68012019-10-15 17:38:19 -0700210 return true;
Amya609d5a2019-08-23 14:38:31 -0700211}
212
Amy5ed13572019-12-11 15:33:51 -0800213bool Demux::startRecordFilterDispatcher() {
214 set<uint32_t>::iterator it;
215
216 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
217 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
218 return false;
219 }
220 }
221
222 return true;
223}
224
Amyb4b68012019-10-15 17:38:19 -0700225Result Demux::startFilterHandler(uint32_t filterId) {
226 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700227}
228
Amyb4b68012019-10-15 17:38:19 -0700229void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
230 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700231}
Amya609d5a2019-08-23 14:38:31 -0700232
Amyb4b68012019-10-15 17:38:19 -0700233uint16_t Demux::getFilterTpid(uint32_t filterId) {
234 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700235}
236
Amy5ed13572019-12-11 15:33:51 -0800237Result Demux::startFrontendInputLoop() {
238 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
239 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
Amy5094ae12019-10-04 18:43:21 -0700240
241 return Result::SUCCESS;
242}
243
Amy5ed13572019-12-11 15:33:51 -0800244void* Demux::__threadLoopFrontend(void* user) {
Amy5094ae12019-10-04 18:43:21 -0700245 Demux* const self = static_cast<Demux*>(user);
Amy5ed13572019-12-11 15:33:51 -0800246 self->frontendInputThreadLoop();
Amy5094ae12019-10-04 18:43:21 -0700247 return 0;
248}
249
Amy5ed13572019-12-11 15:33:51 -0800250void Demux::frontendInputThreadLoop() {
251 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
252 mFrontendInputThreadRunning = true;
Amy5094ae12019-10-04 18:43:21 -0700253 mKeepFetchingDataFromFrontend = true;
254
255 // open the stream and get its length
256 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
257 // TODO take the packet size from the frontend setting
258 int packetSize = 188;
259 int writePacketAmount = 6;
260 char* buffer = new char[packetSize];
Amy5ed13572019-12-11 15:33:51 -0800261 ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
Amy5094ae12019-10-04 18:43:21 -0700262 if (!inputData.is_open()) {
Amy5ed13572019-12-11 15:33:51 -0800263 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700264 ALOGW("[Demux] Error %s", strerror(errno));
265 }
266
Amy5ed13572019-12-11 15:33:51 -0800267 while (mFrontendInputThreadRunning) {
Amy5094ae12019-10-04 18:43:21 -0700268 // move the stream pointer for packet size * 6 every read until the end
269 while (mKeepFetchingDataFromFrontend) {
270 for (int i = 0; i < writePacketAmount; i++) {
271 inputData.read(buffer, packetSize);
272 if (!inputData) {
Amyb4b68012019-10-15 17:38:19 -0700273 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800274 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700275 break;
276 }
277 // filter and dispatch filter output
278 vector<uint8_t> byteBuffer;
Amy79125022019-10-10 15:30:17 -0700279 byteBuffer.resize(packetSize);
Amy5094ae12019-10-04 18:43:21 -0700280 for (int index = 0; index < byteBuffer.size(); index++) {
281 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
282 }
Amy5ed13572019-12-11 15:33:51 -0800283 if (mIsRecording) {
284 // Feed the data into the Dvr recording input
285 sendFrontendInputToRecord(byteBuffer);
286 } else {
287 // Feed the data into the broadcast demux filter
288 startBroadcastTsFilter(byteBuffer);
289 }
Amy5094ae12019-10-04 18:43:21 -0700290 }
Amy5ed13572019-12-11 15:33:51 -0800291 if (mIsRecording) {
292 // Dispatch the data into the broadcasting filters.
293 startRecordFilterDispatcher();
294 } else {
295 // Dispatch the data into the broadcasting filters.
296 startBroadcastFilterDispatcher();
297 }
Amyb4b68012019-10-15 17:38:19 -0700298 usleep(100);
Amy5094ae12019-10-04 18:43:21 -0700299 }
300 }
301
Amy5ed13572019-12-11 15:33:51 -0800302 ALOGW("[Demux] Frontend Input thread end.");
Amy5094ae12019-10-04 18:43:21 -0700303 delete[] buffer;
304 inputData.close();
305}
306
Amy5ed13572019-12-11 15:33:51 -0800307void Demux::stopFrontendInput() {
Amyb4b68012019-10-15 17:38:19 -0700308 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700309 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800310 mFrontendInputThreadRunning = false;
311 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
312}
313
314void Demux::setIsRecording(bool isRecording) {
315 mIsRecording = isRecording;
316}
317
318bool Demux::attachRecordFilter(int filterId) {
319 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
320 return false;
321 }
322
323 mRecordFilterIds.insert(filterId);
324 mFilters[filterId]->attachFilterToRecord(mDvr);
325
326 return true;
327}
328
329bool Demux::detachRecordFilter(int filterId) {
330 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
331 return false;
332 }
333
334 mRecordFilterIds.erase(filterId);
335 mFilters[filterId]->detachFilterFromRecord();
336
337 return true;
Amy5094ae12019-10-04 18:43:21 -0700338}
339
Amyfd4243a2019-08-16 16:01:27 -0700340} // namespace implementation
341} // namespace V1_0
342} // namespace tuner
343} // namespace tv
344} // namespace hardware
345} // namespace android