blob: b74f6eca202e862f7e029223d024cad9f07051b1 [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;
Amy Zhangb717eb52020-05-15 18:35:42 -070063 filterId = ++mLastUsedFilterId;
Amya4885292019-09-06 10:30:53 -070064
65 mUsedFilterIds.insert(filterId);
Amya609d5a2019-08-23 14:38:31 -070066
Amyb4b68012019-10-15 17:38:19 -070067 if (cb == nullptr) {
Amy Zhang6e8163a2020-04-24 15:41:21 -070068 ALOGW("[Demux] callback can't be null");
Amyb4b68012019-10-15 17:38:19 -070069 _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
Amya609d5a2019-08-23 14:38:31 -070070 return Void();
71 }
Amya4885292019-09-06 10:30:53 -070072
Amyb4b68012019-10-15 17:38:19 -070073 sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
Amya609d5a2019-08-23 14:38:31 -070074
Amyb4b68012019-10-15 17:38:19 -070075 if (!filter->createFilterMQ()) {
76 _hidl_cb(Result::UNKNOWN_ERROR, filter);
Amya609d5a2019-08-23 14:38:31 -070077 return Void();
78 }
Amyb4b68012019-10-15 17:38:19 -070079
Amy Zhang6e8163a2020-04-24 15:41:21 -070080 mFilters[filterId] = filter;
Amy Zhangb717eb52020-05-15 18:35:42 -070081 if (filter->isPcrFilter()) {
82 mPcrFilterIds.insert(filterId);
83 }
Amy Zhang6e8163a2020-04-24 15:41:21 -070084 bool result = true;
85 if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
86 result = mDvr->addPlaybackFilter(filter);
87 }
88
89 _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, 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
Amy Zhangb717eb52020-05-15 18:35:42 -0700102Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700103 ALOGV("%s", __FUNCTION__);
104
Amy Zhangb717eb52020-05-15 18:35:42 -0700105 uint32_t avSyncHwId = -1;
106 int id;
107 Result status;
Amya609d5a2019-08-23 14:38:31 -0700108
Amy Zhangb717eb52020-05-15 18:35:42 -0700109 filter->getId([&](Result result, uint32_t filterId) {
110 id = filterId;
111 status = result;
112 });
113
114 if (status != Result::SUCCESS) {
115 ALOGE("[Demux] Can't get filter Id.");
116 _hidl_cb(Result::INVALID_STATE, avSyncHwId);
117 return Void();
118 }
119
120 if (!mFilters[id]->isMediaFilter()) {
121 ALOGE("[Demux] Given filter is not a media filter.");
122 _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
123 return Void();
124 }
125
126 if (!mPcrFilterIds.empty()) {
Amy Zhangb717eb52020-05-15 18:35:42 -0700127 // Return the lowest pcr filter id in the default implementation as the av sync id
128 _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
129 return Void();
130 }
131
Amy Zhange5a9da22020-06-01 19:12:29 -0700132 ALOGE("[Demux] No PCR filter opened.");
Amy Zhangb717eb52020-05-15 18:35:42 -0700133 _hidl_cb(Result::INVALID_STATE, avSyncHwId);
Amya609d5a2019-08-23 14:38:31 -0700134 return Void();
135}
136
Amy Zhangb717eb52020-05-15 18:35:42 -0700137Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
Amya609d5a2019-08-23 14:38:31 -0700138 ALOGV("%s", __FUNCTION__);
139
Amy Zhangb717eb52020-05-15 18:35:42 -0700140 uint64_t avSyncTime = -1;
141 if (mPcrFilterIds.empty()) {
142 _hidl_cb(Result::INVALID_STATE, avSyncTime);
143 return Void();
144 }
145 if (avSyncHwId != *mPcrFilterIds.begin()) {
146 _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime);
147 return Void();
148 }
Amya609d5a2019-08-23 14:38:31 -0700149
150 _hidl_cb(Result::SUCCESS, avSyncTime);
151 return Void();
152}
153
Amyfd4243a2019-08-16 16:01:27 -0700154Return<Result> Demux::close() {
155 ALOGV("%s", __FUNCTION__);
156
Amya4885292019-09-06 10:30:53 -0700157 mUsedFilterIds.clear();
Amya4885292019-09-06 10:30:53 -0700158 mLastUsedFilterId = -1;
159
Amyfd4243a2019-08-16 16:01:27 -0700160 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700161}
162
Amyb4b68012019-10-15 17:38:19 -0700163Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
164 openDvr_cb _hidl_cb) {
Amya4885292019-09-06 10:30:53 -0700165 ALOGV("%s", __FUNCTION__);
166
Amyb4b68012019-10-15 17:38:19 -0700167 if (cb == nullptr) {
Amy Zhang6e8163a2020-04-24 15:41:21 -0700168 ALOGW("[Demux] DVR callback can't be null");
Amyb4b68012019-10-15 17:38:19 -0700169 _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
Amya4885292019-09-06 10:30:53 -0700170 return Void();
171 }
172
Amy5ed13572019-12-11 15:33:51 -0800173 mDvr = new Dvr(type, bufferSize, cb, this);
Amya4885292019-09-06 10:30:53 -0700174
Amy5ed13572019-12-11 15:33:51 -0800175 if (!mDvr->createDvrMQ()) {
176 _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
Amya4885292019-09-06 10:30:53 -0700177 return Void();
178 }
179
Amy5ed13572019-12-11 15:33:51 -0800180 _hidl_cb(Result::SUCCESS, mDvr);
Amya4885292019-09-06 10:30:53 -0700181 return Void();
182}
183
Henry Fang89f12f52019-11-05 13:48:59 -0800184Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
185 ALOGV("%s", __FUNCTION__);
186
187 mCiCamId = ciCamId;
188
189 return Result::SUCCESS;
190}
191
192Return<Result> Demux::disconnectCiCam() {
193 ALOGV("%s", __FUNCTION__);
194
195 return Result::SUCCESS;
196}
197
Amyb4b68012019-10-15 17:38:19 -0700198Result Demux::removeFilter(uint32_t filterId) {
Amya4885292019-09-06 10:30:53 -0700199 ALOGV("%s", __FUNCTION__);
200
Amyb4b68012019-10-15 17:38:19 -0700201 // resetFilterRecords(filterId);
202 mUsedFilterIds.erase(filterId);
Amy5ed13572019-12-11 15:33:51 -0800203 mRecordFilterIds.erase(filterId);
Amyb4b68012019-10-15 17:38:19 -0700204 mFilters.erase(filterId);
Amy42a5b4b2019-10-03 16:49:48 -0700205
Amya4885292019-09-06 10:30:53 -0700206 return Result::SUCCESS;
207}
208
Amy5ed13572019-12-11 15:33:51 -0800209void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
Amy5094ae12019-10-04 18:43:21 -0700210 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700211 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
212 if (DEBUG_DEMUX) {
213 ALOGW("[Demux] start ts filter pid: %d", pid);
214 }
Amy5094ae12019-10-04 18:43:21 -0700215 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700216 if (pid == mFilters[*it]->getTpid()) {
217 mFilters[*it]->updateFilterOutput(data);
Amy42a5b4b2019-10-03 16:49:48 -0700218 }
219 }
Amy5094ae12019-10-04 18:43:21 -0700220}
221
Amy5ed13572019-12-11 15:33:51 -0800222void Demux::sendFrontendInputToRecord(vector<uint8_t> data) {
223 set<uint32_t>::iterator it;
Amy Zhang6e8163a2020-04-24 15:41:21 -0700224 if (DEBUG_DEMUX) {
225 ALOGW("[Demux] update record filter output");
226 }
Amy5ed13572019-12-11 15:33:51 -0800227 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
Amy5ed13572019-12-11 15:33:51 -0800228 mFilters[*it]->updateRecordOutput(data);
229 }
230}
231
232bool Demux::startBroadcastFilterDispatcher() {
Amy5094ae12019-10-04 18:43:21 -0700233 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700234
235 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700236 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
Amyb4b68012019-10-15 17:38:19 -0700237 if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
238 return false;
Amya4885292019-09-06 10:30:53 -0700239 }
Amya609d5a2019-08-23 14:38:31 -0700240 }
241
Amyb4b68012019-10-15 17:38:19 -0700242 return true;
Amya609d5a2019-08-23 14:38:31 -0700243}
244
Amy5ed13572019-12-11 15:33:51 -0800245bool Demux::startRecordFilterDispatcher() {
246 set<uint32_t>::iterator it;
247
248 for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
249 if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
250 return false;
251 }
252 }
253
254 return true;
255}
256
Amyb4b68012019-10-15 17:38:19 -0700257Result Demux::startFilterHandler(uint32_t filterId) {
258 return mFilters[filterId]->startFilterHandler();
Amya609d5a2019-08-23 14:38:31 -0700259}
260
Amyb4b68012019-10-15 17:38:19 -0700261void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
262 mFilters[filterId]->updateFilterOutput(data);
Amya4885292019-09-06 10:30:53 -0700263}
Amya609d5a2019-08-23 14:38:31 -0700264
Amyb4b68012019-10-15 17:38:19 -0700265uint16_t Demux::getFilterTpid(uint32_t filterId) {
266 return mFilters[filterId]->getTpid();
Amy79125022019-10-10 15:30:17 -0700267}
268
Amy Zhang0fe25be2020-04-08 17:30:52 -0700269void Demux::startFrontendInputLoop() {
Amy5ed13572019-12-11 15:33:51 -0800270 pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
271 pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
Amy5094ae12019-10-04 18:43:21 -0700272}
273
Amy5ed13572019-12-11 15:33:51 -0800274void* Demux::__threadLoopFrontend(void* user) {
Amy5094ae12019-10-04 18:43:21 -0700275 Demux* const self = static_cast<Demux*>(user);
Amy5ed13572019-12-11 15:33:51 -0800276 self->frontendInputThreadLoop();
Amy5094ae12019-10-04 18:43:21 -0700277 return 0;
278}
279
Amy5ed13572019-12-11 15:33:51 -0800280void Demux::frontendInputThreadLoop() {
281 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
282 mFrontendInputThreadRunning = true;
Amy5094ae12019-10-04 18:43:21 -0700283 mKeepFetchingDataFromFrontend = true;
284
285 // open the stream and get its length
286 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
287 // TODO take the packet size from the frontend setting
288 int packetSize = 188;
289 int writePacketAmount = 6;
290 char* buffer = new char[packetSize];
Amy5ed13572019-12-11 15:33:51 -0800291 ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
Amy5094ae12019-10-04 18:43:21 -0700292 if (!inputData.is_open()) {
Amy5ed13572019-12-11 15:33:51 -0800293 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700294 ALOGW("[Demux] Error %s", strerror(errno));
295 }
296
Amy5ed13572019-12-11 15:33:51 -0800297 while (mFrontendInputThreadRunning) {
Amy5094ae12019-10-04 18:43:21 -0700298 // move the stream pointer for packet size * 6 every read until the end
299 while (mKeepFetchingDataFromFrontend) {
300 for (int i = 0; i < writePacketAmount; i++) {
301 inputData.read(buffer, packetSize);
302 if (!inputData) {
Amyb4b68012019-10-15 17:38:19 -0700303 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800304 mFrontendInputThreadRunning = false;
Amy5094ae12019-10-04 18:43:21 -0700305 break;
306 }
307 // filter and dispatch filter output
308 vector<uint8_t> byteBuffer;
Amy79125022019-10-10 15:30:17 -0700309 byteBuffer.resize(packetSize);
Amy5094ae12019-10-04 18:43:21 -0700310 for (int index = 0; index < byteBuffer.size(); index++) {
311 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
312 }
Amy5ed13572019-12-11 15:33:51 -0800313 if (mIsRecording) {
314 // Feed the data into the Dvr recording input
315 sendFrontendInputToRecord(byteBuffer);
316 } else {
317 // Feed the data into the broadcast demux filter
318 startBroadcastTsFilter(byteBuffer);
319 }
Amy5094ae12019-10-04 18:43:21 -0700320 }
Amy5ed13572019-12-11 15:33:51 -0800321 if (mIsRecording) {
322 // Dispatch the data into the broadcasting filters.
323 startRecordFilterDispatcher();
324 } else {
325 // Dispatch the data into the broadcasting filters.
326 startBroadcastFilterDispatcher();
327 }
Amyb4b68012019-10-15 17:38:19 -0700328 usleep(100);
Amy5094ae12019-10-04 18:43:21 -0700329 }
330 }
331
Amy5ed13572019-12-11 15:33:51 -0800332 ALOGW("[Demux] Frontend Input thread end.");
Amy5094ae12019-10-04 18:43:21 -0700333 delete[] buffer;
334 inputData.close();
335}
336
Amy5ed13572019-12-11 15:33:51 -0800337void Demux::stopFrontendInput() {
Amyb4b68012019-10-15 17:38:19 -0700338 ALOGD("[Demux] stop frontend on demux");
Amy5094ae12019-10-04 18:43:21 -0700339 mKeepFetchingDataFromFrontend = false;
Amy5ed13572019-12-11 15:33:51 -0800340 mFrontendInputThreadRunning = false;
341 std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
342}
343
344void Demux::setIsRecording(bool isRecording) {
345 mIsRecording = isRecording;
346}
347
348bool Demux::attachRecordFilter(int filterId) {
349 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
350 return false;
351 }
352
353 mRecordFilterIds.insert(filterId);
354 mFilters[filterId]->attachFilterToRecord(mDvr);
355
356 return true;
357}
358
359bool Demux::detachRecordFilter(int filterId) {
360 if (mFilters[filterId] == nullptr || mDvr == nullptr) {
361 return false;
362 }
363
364 mRecordFilterIds.erase(filterId);
365 mFilters[filterId]->detachFilterFromRecord();
366
367 return true;
Amy5094ae12019-10-04 18:43:21 -0700368}
369
Amyfd4243a2019-08-16 16:01:27 -0700370} // namespace implementation
371} // namespace V1_0
372} // namespace tuner
373} // namespace tv
374} // namespace hardware
375} // namespace android