blob: 4e5ae4b626fd0b673c867197c4261977ce25424e [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) {
Amy Zhang6e8163a2020-04-24 15:41:21 -070074 ALOGW("[Demux] 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
Amy Zhang6e8163a2020-04-24 15:41:21 -070086 mFilters[filterId] = filter;
87 bool result = true;
88 if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
89 result = mDvr->addPlaybackFilter(filter);
90 }
91
92 _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
Amya609d5a2019-08-23 14:38:31 -070093 return Void();
94}
95
Amyb4b68012019-10-15 17:38:19 -070096Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -070097 ALOGV("%s", __FUNCTION__);
98
Amyb4b68012019-10-15 17:38:19 -070099 sp<TimeFilter> timeFilter = new TimeFilter(this);
Amya609d5a2019-08-23 14:38:31 -0700100
Amyb4b68012019-10-15 17:38:19 -0700101 _hidl_cb(Result::SUCCESS, timeFilter);
Amya609d5a2019-08-23 14:38:31 -0700102 return Void();
103}
104
Amyb4b68012019-10-15 17:38:19 -0700105Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700106 ALOGV("%s", __FUNCTION__);
107
108 AvSyncHwId avSyncHwId = 0;
109
110 _hidl_cb(Result::SUCCESS, avSyncHwId);
111 return Void();
112}
113
114Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
115 ALOGV("%s", __FUNCTION__);
116
117 uint64_t avSyncTime = 0;
118
119 _hidl_cb(Result::SUCCESS, avSyncTime);
120 return Void();
121}
122
Amyfd4243a2019-08-16 16:01:27 -0700123Return<Result> Demux::close() {
124 ALOGV("%s", __FUNCTION__);
125
Amya4885292019-09-06 10:30:53 -0700126 mUnusedFilterIds.clear();
127 mUsedFilterIds.clear();
Amya4885292019-09-06 10:30:53 -0700128 mLastUsedFilterId = -1;
129
Amyfd4243a2019-08-16 16:01:27 -0700130 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700131}
132
Amyb4b68012019-10-15 17:38:19 -0700133Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
134 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700135 ALOGV("%s", __FUNCTION__);
136
Amyb4b68012019-10-15 17:38:19 -0700137 if (cb == nullptr) {
Amy Zhang6e8163a2020-04-24 15:41:21 -0700138 ALOGW("[Demux] DVR callback can't be null");
Amyb4b68012019-10-15 17:38:19 -0700139 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700140 return Void();
141 }
142
Amy5ed13572019-12-11 15:33:51 -0800143 mDvr = new Dvr(type, bufferSize, cb, this);
Amya4885292019-09-06 10:30:53 -0700144
Amy5ed13572019-12-11 15:33:51 -0800145 if (!mDvr->createDvrMQ()) {
146 _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
Amya4885292019-09-06 10:30:53 -0700147 return Void();
148 }
149
Amy5ed13572019-12-11 15:33:51 -0800150 _hidl_cb(Result::SUCCESS, mDvr);
Amya4885292019-09-06 10:30:53 -0700151 return Void();
152}
153
Henry Fang89f12f52019-11-05 13:48:59 -0800154Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
155 ALOGV("%s", __FUNCTION__);
156
157 mCiCamId = ciCamId;
158
159 return Result::SUCCESS;
160}
161
162Return<Result> Demux::disconnectCiCam() {
163 ALOGV("%s", __FUNCTION__);
164
165 return Result::SUCCESS;
166}
167
Amyb4b68012019-10-15 17:38:19 -0700168Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700169 ALOGV("%s", __FUNCTION__);
170
Amyb4b68012019-10-15 17:38:19 -0700171 // resetFilterRecords(filterId);
172 mUsedFilterIds.erase(filterId);
Amy5ed13572019-12-11 15:33:51 -0800173 mRecordFilterIds.erase(filterId);
Amyb4b68012019-10-15 17:38:19 -0700174 mUnusedFilterIds.insert(filterId);
175 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700176
Amya4885292019-09-06 10:30:53 -0700177 return Result::SUCCESS;
178}
179
Amy5ed13572019-12-11 15:33:51 -0800180void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
Amy5094ae12019-10-04 18:43:21 -0700181 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700182 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
183 if (DEBUG_DEMUX) {
184 ALOGW("[Demux] start ts filter pid: %d", pid);
185 }
Amy5094ae12019-10-04 18:43:21 -0700186 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700187 if (pid == mFilters[*it]->getTpid()) {
188 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700189 }
190 }
Amy5094ae12019-10-04 18:43:21 -0700191}
192
Amy5ed13572019-12-11 15:33:51 -0800193void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
194 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700195 if (DEBUG_DEMUX) {
196 ALOGW("[Demux] update record filter output");
197 }
Amy5ed13572019-12-11 15:33:51 -0800198 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
Amy5ed13572019-12-11 15:33:51 -0800199 mFilters[*it]->updateRecordOutput(data);
200 }
201}
202
203bool Demux::startBroadcastFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700204 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700205
206 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700207 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700208 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
209 return false;
Amya4885292019-09-06 10:30:53 -0700210 }
Amya609d5a2019-08-23 14:38:31 -0700211 }
212
Amyb4b68012019-10-15 17:38:19 -0700213 return true;
Amya609d5a2019-08-23 14:38:31 -0700214}
215
Amy5ed13572019-12-11 15:33:51 -0800216bool Demux::startRecordFilterDispatcher() {
217 set<uint32_t>::iterator it;
218
219 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
220 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
221 return false;
222 }
223 }
224
225 return true;
226}
227
Amyb4b68012019-10-15 17:38:19 -0700228Result Demux::startFilterHandler(uint32_t filterId) {
229 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700230}
231
Amyb4b68012019-10-15 17:38:19 -0700232void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
233 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700234}
Amya609d5a2019-08-23 14:38:31 -0700235
Amyb4b68012019-10-15 17:38:19 -0700236uint16_t Demux::getFilterTpid(uint32_t filterId) {
237 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700238}
239
Amy Zhang0fe25be2020-04-08 17:30:52 -0700240void Demux::startFrontendInputLoop() {
Amy5ed13572019-12-11 15:33:51 -0800241 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
242 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
Amy5094ae12019-10-04 18:43:21 -0700243}
244
Amy5ed13572019-12-11 15:33:51 -0800245void* Demux::__threadLoopFrontend(void* user) {
Amy5094ae12019-10-04 18:43:21 -0700246 Demux* const self = static_cast<Demux*>(user);
Amy5ed13572019-12-11 15:33:51 -0800247 self->frontendInputThreadLoop();
Amy5094ae12019-10-04 18:43:21 -0700248 return 0;
249}
250
Amy5ed13572019-12-11 15:33:51 -0800251void Demux::frontendInputThreadLoop() {
252 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
253 mFrontendInputThreadRunning = true;
Amy5094ae12019-10-04 18:43:21 -0700254 mKeepFetchingDataFromFrontend = true;
255
256 // open the stream and get its length
257 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
258 // TODO take the packet size from the frontend setting
259 int packetSize = 188;
260 int writePacketAmount = 6;
261 char* buffer = new char[packetSize];
Amy5ed13572019-12-11 15:33:51 -0800262 ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
Amy5094ae12019-10-04 18:43:21 -0700263 if (!inputData.is_open()) {
Amy5ed13572019-12-11 15:33:51 -0800264 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700265 ALOGW("[Demux] Error %s", strerror(errno));
266 }
267
Amy5ed13572019-12-11 15:33:51 -0800268 while (mFrontendInputThreadRunning) {
Amy5094ae12019-10-04 18:43:21 -0700269 // move the stream pointer for packet size * 6 every read until the end
270 while (mKeepFetchingDataFromFrontend) {
271 for (int i = 0; i < writePacketAmount; i++) {
272 inputData.read(buffer, packetSize);
273 if (!inputData) {
Amyb4b68012019-10-15 17:38:19 -0700274 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800275 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700276 break;
277 }
278 // filter and dispatch filter output
279 vector<uint8_t> byteBuffer;
Amy79125022019-10-10 15:30:17 -0700280 byteBuffer.resize(packetSize);
Amy5094ae12019-10-04 18:43:21 -0700281 for (int index = 0; index < byteBuffer.size(); index++) {
282 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
283 }
Amy5ed13572019-12-11 15:33:51 -0800284 if (mIsRecording) {
285 // Feed the data into the Dvr recording input
286 sendFrontendInputToRecord(byteBuffer);
287 } else {
288 // Feed the data into the broadcast demux filter
289 startBroadcastTsFilter(byteBuffer);
290 }
Amy5094ae12019-10-04 18:43:21 -0700291 }
Amy5ed13572019-12-11 15:33:51 -0800292 if (mIsRecording) {
293 // Dispatch the data into the broadcasting filters.
294 startRecordFilterDispatcher();
295 } else {
296 // Dispatch the data into the broadcasting filters.
297 startBroadcastFilterDispatcher();
298 }
Amyb4b68012019-10-15 17:38:19 -0700299 usleep(100);
Amy5094ae12019-10-04 18:43:21 -0700300 }
301 }
302
Amy5ed13572019-12-11 15:33:51 -0800303 ALOGW("[Demux] Frontend Input thread end.");
Amy5094ae12019-10-04 18:43:21 -0700304 delete[] buffer;
305 inputData.close();
306}
307
Amy5ed13572019-12-11 15:33:51 -0800308void Demux::stopFrontendInput() {
Amyb4b68012019-10-15 17:38:19 -0700309 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700310 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800311 mFrontendInputThreadRunning = false;
312 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
313}
314
315void Demux::setIsRecording(bool isRecording) {
316 mIsRecording = isRecording;
317}
318
319bool Demux::attachRecordFilter(int filterId) {
320 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
321 return false;
322 }
323
324 mRecordFilterIds.insert(filterId);
325 mFilters[filterId]->attachFilterToRecord(mDvr);
326
327 return true;
328}
329
330bool Demux::detachRecordFilter(int filterId) {
331 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
332 return false;
333 }
334
335 mRecordFilterIds.erase(filterId);
336 mFilters[filterId]->detachFilterFromRecord();
337
338 return true;
Amy5094ae12019-10-04 18:43:21 -0700339}
340
Amyfd4243a2019-08-16 16:01:27 -0700341} // namespace implementation
342} // namespace V1_0
343} // namespace tuner
344} // namespace tv
345} // namespace hardware
346} // namespace android