blob: c5921f74a9ccd3b8d764d72e70d5be8901ac743e [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
Amyb4b68012019-10-15 17:38:19 -0700150Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700151 ALOGV("%s", __FUNCTION__);
152
Amyb4b68012019-10-15 17:38:19 -0700153 // resetFilterRecords(filterId);
154 mUsedFilterIds.erase(filterId);
155 mUnusedFilterIds.insert(filterId);
156 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700157
Amya4885292019-09-06 10:30:53 -0700158 return Result::SUCCESS;
159}
160
Amy5094ae12019-10-04 18:43:21 -0700161void Demux::startTsFilter(vector<uint8_t> data) {
162 set<uint32_t>::iterator it;
163 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
164 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
Amyb4b68012019-10-15 17:38:19 -0700165 if (DEBUG_FILTER) {
166 ALOGW("start ts filter pid: %d", pid);
167 }
168 if (pid == mFilters[*it]->getTpid()) {
169 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700170 }
171 }
Amy5094ae12019-10-04 18:43:21 -0700172}
173
174bool Demux::startFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700175 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700176
177 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700178 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700179 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
180 return false;
Amya4885292019-09-06 10:30:53 -0700181 }
Amya609d5a2019-08-23 14:38:31 -0700182 }
183
Amyb4b68012019-10-15 17:38:19 -0700184 return true;
Amya609d5a2019-08-23 14:38:31 -0700185}
186
Amyb4b68012019-10-15 17:38:19 -0700187Result Demux::startFilterHandler(uint32_t filterId) {
188 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700189}
190
Amyb4b68012019-10-15 17:38:19 -0700191void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
192 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700193}
Amya609d5a2019-08-23 14:38:31 -0700194
Amyb4b68012019-10-15 17:38:19 -0700195uint16_t Demux::getFilterTpid(uint32_t filterId) {
196 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700197}
198
Amy5094ae12019-10-04 18:43:21 -0700199Result Demux::startBroadcastInputLoop() {
200 pthread_create(&mBroadcastInputThread, NULL, __threadLoopBroadcast, this);
201 pthread_setname_np(mBroadcastInputThread, "broadcast_input_thread");
202
203 return Result::SUCCESS;
204}
205
206void* Demux::__threadLoopBroadcast(void* user) {
207 Demux* const self = static_cast<Demux*>(user);
208 self->broadcastInputThreadLoop();
209 return 0;
210}
211
212void Demux::broadcastInputThreadLoop() {
213 std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
214 mBroadcastInputThreadRunning = true;
215 mKeepFetchingDataFromFrontend = true;
216
217 // open the stream and get its length
218 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
219 // TODO take the packet size from the frontend setting
220 int packetSize = 188;
221 int writePacketAmount = 6;
222 char* buffer = new char[packetSize];
223 ALOGW("[Demux] broadcast input thread loop start %s", mFrontendSourceFile.c_str());
224 if (!inputData.is_open()) {
225 mBroadcastInputThreadRunning = false;
226 ALOGW("[Demux] Error %s", strerror(errno));
227 }
228
229 while (mBroadcastInputThreadRunning) {
230 // move the stream pointer for packet size * 6 every read until the end
231 while (mKeepFetchingDataFromFrontend) {
232 for (int i = 0; i < writePacketAmount; i++) {
233 inputData.read(buffer, packetSize);
234 if (!inputData) {
Amyb4b68012019-10-15 17:38:19 -0700235 mKeepFetchingDataFromFrontend = false;
Amy5094ae12019-10-04 18:43:21 -0700236 mBroadcastInputThreadRunning = false;
237 break;
238 }
239 // filter and dispatch filter output
240 vector<uint8_t> byteBuffer;
Amy79125022019-10-10 15:30:17 -0700241 byteBuffer.resize(packetSize);
Amy5094ae12019-10-04 18:43:21 -0700242 for (int index = 0; index < byteBuffer.size(); index++) {
243 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
244 }
245 startTsFilter(byteBuffer);
Amy5094ae12019-10-04 18:43:21 -0700246 }
247 startFilterDispatcher();
Amyb4b68012019-10-15 17:38:19 -0700248 usleep(100);
Amy5094ae12019-10-04 18:43:21 -0700249 }
250 }
251
252 ALOGW("[Demux] Broadcast Input thread end.");
253 delete[] buffer;
254 inputData.close();
255}
256
257void Demux::stopBroadcastInput() {
Amyb4b68012019-10-15 17:38:19 -0700258 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700259 mKeepFetchingDataFromFrontend = false;
260 mBroadcastInputThreadRunning = false;
261 std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
262}
263
Amyfd4243a2019-08-16 16:01:27 -0700264} // namespace implementation
265} // namespace V1_0
266} // namespace tuner
267} // namespace tv
268} // namespace hardware
269} // namespace android