blob: 71a26ab6ec4313a908ea6c0f3986acfde41e90f3 [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);
54 return startBroadcastInputLoop();
Amyfd4243a2019-08-16 16:01:27 -070055}
56
Amyb4b68012019-10-15 17:38:19 -070057Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
58 const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070059 ALOGV("%s", __FUNCTION__);
60
Amya4885292019-09-06 10:30:53 -070061 uint32_t filterId;
62
63 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 }
85
Amyb4b68012019-10-15 17:38:19 -070086 mFilters[filterId] = filter;
87
88 _hidl_cb(Result::SUCCESS, filter);
Amya609d5a2019-08-23 14:38:31 -070089 return Void();
90}
91
Amyb4b68012019-10-15 17:38:19 -070092Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070093 ALOGV("%s", __FUNCTION__);
94
Amyb4b68012019-10-15 17:38:19 -070095 sp<TimeFilter> timeFilter = new TimeFilter(this);
Amya609d5a2019-08-23 14:38:31 -070096
Amyb4b68012019-10-15 17:38:19 -070097 _hidl_cb(Result::SUCCESS, timeFilter);
Amya609d5a2019-08-23 14:38:31 -070098 return Void();
99}
100
Amyb4b68012019-10-15 17:38:19 -0700101Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700102 ALOGV("%s", __FUNCTION__);
103
104 AvSyncHwId avSyncHwId = 0;
105
106 _hidl_cb(Result::SUCCESS, avSyncHwId);
107 return Void();
108}
109
110Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
111 ALOGV("%s", __FUNCTION__);
112
113 uint64_t avSyncTime = 0;
114
115 _hidl_cb(Result::SUCCESS, avSyncTime);
116 return Void();
117}
118
Amyfd4243a2019-08-16 16:01:27 -0700119Return<Result> Demux::close() {
120 ALOGV("%s", __FUNCTION__);
121
Amya4885292019-09-06 10:30:53 -0700122 mUnusedFilterIds.clear();
123 mUsedFilterIds.clear();
Amya4885292019-09-06 10:30:53 -0700124 mLastUsedFilterId = -1;
125
Amyfd4243a2019-08-16 16:01:27 -0700126 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700127}
128
Amyb4b68012019-10-15 17:38:19 -0700129Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
130 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700131 ALOGV("%s", __FUNCTION__);
132
Amyb4b68012019-10-15 17:38:19 -0700133 if (cb == nullptr) {
134 ALOGW("DVR callback can't be null");
135 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700136 return Void();
137 }
138
Amyb4b68012019-10-15 17:38:19 -0700139 sp<Dvr> dvr = new Dvr(type, bufferSize, cb, this);
Amya4885292019-09-06 10:30:53 -0700140
Amyb4b68012019-10-15 17:38:19 -0700141 if (!dvr->createDvrMQ()) {
142 _hidl_cb(Result::UNKNOWN_ERROR, dvr);
Amya4885292019-09-06 10:30:53 -0700143 return Void();
144 }
145
Amyb4b68012019-10-15 17:38:19 -0700146 _hidl_cb(Result::SUCCESS, dvr);
Amya4885292019-09-06 10:30:53 -0700147 return Void();
148}
149
Henry Fang89f12f52019-11-05 13:48:59 -0800150Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
151 ALOGV("%s", __FUNCTION__);
152
153 mCiCamId = ciCamId;
154
155 return Result::SUCCESS;
156}
157
158Return<Result> Demux::disconnectCiCam() {
159 ALOGV("%s", __FUNCTION__);
160
161 return Result::SUCCESS;
162}
163
Amyb4b68012019-10-15 17:38:19 -0700164Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700165 ALOGV("%s", __FUNCTION__);
166
Amyb4b68012019-10-15 17:38:19 -0700167 // resetFilterRecords(filterId);
168 mUsedFilterIds.erase(filterId);
169 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
Amy5094ae12019-10-04 18:43:21 -0700175void Demux::startTsFilter(vector<uint8_t> data) {
176 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
188bool Demux::startFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700189 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700190
191 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700192 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700193 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
194 return false;
Amya4885292019-09-06 10:30:53 -0700195 }
Amya609d5a2019-08-23 14:38:31 -0700196 }
197
Amyb4b68012019-10-15 17:38:19 -0700198 return true;
Amya609d5a2019-08-23 14:38:31 -0700199}
200
Amyb4b68012019-10-15 17:38:19 -0700201Result Demux::startFilterHandler(uint32_t filterId) {
202 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700203}
204
Amyb4b68012019-10-15 17:38:19 -0700205void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
206 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700207}
Amya609d5a2019-08-23 14:38:31 -0700208
Amyb4b68012019-10-15 17:38:19 -0700209uint16_t Demux::getFilterTpid(uint32_t filterId) {
210 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700211}
212
Amy5094ae12019-10-04 18:43:21 -0700213Result Demux::startBroadcastInputLoop() {
214 pthread_create(&mBroadcastInputThread, NULL, __threadLoopBroadcast, this);
215 pthread_setname_np(mBroadcastInputThread, "broadcast_input_thread");
216
217 return Result::SUCCESS;
218}
219
220void* Demux::__threadLoopBroadcast(void* user) {
221 Demux* const self = static_cast<Demux*>(user);
222 self->broadcastInputThreadLoop();
223 return 0;
224}
225
226void Demux::broadcastInputThreadLoop() {
227 std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
228 mBroadcastInputThreadRunning = true;
229 mKeepFetchingDataFromFrontend = true;
230
231 // open the stream and get its length
232 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
233 // TODO take the packet size from the frontend setting
234 int packetSize = 188;
235 int writePacketAmount = 6;
236 char* buffer = new char[packetSize];
237 ALOGW("[Demux] broadcast input thread loop start %s", mFrontendSourceFile.c_str());
238 if (!inputData.is_open()) {
239 mBroadcastInputThreadRunning = false;
240 ALOGW("[Demux] Error %s", strerror(errno));
241 }
242
243 while (mBroadcastInputThreadRunning) {
244 // move the stream pointer for packet size * 6 every read until the end
245 while (mKeepFetchingDataFromFrontend) {
246 for (int i = 0; i < writePacketAmount; i++) {
247 inputData.read(buffer, packetSize);
248 if (!inputData) {
Amyb4b68012019-10-15 17:38:19 -0700249 mKeepFetchingDataFromFrontend = false;
Amy5094ae12019-10-04 18:43:21 -0700250 mBroadcastInputThreadRunning = false;
251 break;
252 }
253 // filter and dispatch filter output
254 vector<uint8_t> byteBuffer;
Amy79125022019-10-10 15:30:17 -0700255 byteBuffer.resize(packetSize);
Amy5094ae12019-10-04 18:43:21 -0700256 for (int index = 0; index < byteBuffer.size(); index++) {
257 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
258 }
259 startTsFilter(byteBuffer);
Amy5094ae12019-10-04 18:43:21 -0700260 }
261 startFilterDispatcher();
Amyb4b68012019-10-15 17:38:19 -0700262 usleep(100);
Amy5094ae12019-10-04 18:43:21 -0700263 }
264 }
265
266 ALOGW("[Demux] Broadcast Input thread end.");
267 delete[] buffer;
268 inputData.close();
269}
270
271void Demux::stopBroadcastInput() {
Amyb4b68012019-10-15 17:38:19 -0700272 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700273 mKeepFetchingDataFromFrontend = false;
274 mBroadcastInputThreadRunning = false;
275 std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
276}
277
Amyfd4243a2019-08-16 16:01:27 -0700278} // namespace implementation
279} // namespace V1_0
280} // namespace tuner
281} // namespace tv
282} // namespace hardware
283} // namespace android