blob: 04382b0f99a026df58b4f2ba730cbd27cef0e3ff [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
31const std::vector<uint8_t> fakeDataInputBuffer{
32 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
33 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
34 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
35 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
36 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
37 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
38 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
39 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
40 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
41 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
42 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
43 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
44 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
45 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
46 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
47 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
48 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
49 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
50 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
51 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
52 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
53 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
54 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
55 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
56 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
57 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
58 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
59 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
60 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
61 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
62 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
63 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
64 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
65 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
66 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
67 0x73, 0x63, 0x65, 0x6e, 0x65,
68};
69
Amy5094ae12019-10-04 18:43:21 -070070Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
Amyfd4243a2019-08-16 16:01:27 -070071 mDemuxId = demuxId;
Amy5094ae12019-10-04 18:43:21 -070072 mTunerService = tuner;
Amyfd4243a2019-08-16 16:01:27 -070073}
74
75Demux::~Demux() {}
76
77Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
78 ALOGV("%s", __FUNCTION__);
79
Amy5094ae12019-10-04 18:43:21 -070080 if (mTunerService == nullptr) {
81 return Result::NOT_INITIALIZED;
82 }
Amyfd4243a2019-08-16 16:01:27 -070083
Amy5094ae12019-10-04 18:43:21 -070084 mFrontend = mTunerService->getFrontendById(frontendId);
85
86 if (mFrontend == nullptr) {
87 return Result::INVALID_STATE;
88 }
89
90 mFrontendSourceFile = mFrontend->getSourceFile();
91
92 mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
93 return startBroadcastInputLoop();
Amyfd4243a2019-08-16 16:01:27 -070094}
95
Amya609d5a2019-08-23 14:38:31 -070096Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
97 const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) {
98 ALOGV("%s", __FUNCTION__);
99
Amya4885292019-09-06 10:30:53 -0700100 uint32_t filterId;
101
102 if (!mUnusedFilterIds.empty()) {
103 filterId = *mUnusedFilterIds.begin();
104
105 mUnusedFilterIds.erase(filterId);
106 } else {
107 filterId = ++mLastUsedFilterId;
108
109 mDemuxCallbacks.resize(filterId + 1);
110 mFilterMQs.resize(filterId + 1);
111 mFilterEvents.resize(filterId + 1);
112 mFilterEventFlags.resize(filterId + 1);
113 mFilterThreadRunning.resize(filterId + 1);
114 mFilterThreads.resize(filterId + 1);
Amy42a5b4b2019-10-03 16:49:48 -0700115 mFilterPids.resize(filterId + 1);
116 mFilterOutputs.resize(filterId + 1);
Amya4885292019-09-06 10:30:53 -0700117 }
118
119 mUsedFilterIds.insert(filterId);
Amya609d5a2019-08-23 14:38:31 -0700120
121 if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
122 ALOGW("callback can't be null");
123 _hidl_cb(Result::INVALID_ARGUMENT, filterId);
124 return Void();
125 }
Amya4885292019-09-06 10:30:53 -0700126
Amya609d5a2019-08-23 14:38:31 -0700127 // Add callback
Amya609d5a2019-08-23 14:38:31 -0700128 mDemuxCallbacks[filterId] = cb;
129
Amya4885292019-09-06 10:30:53 -0700130 // Mapping from the filter ID to the filter event
131 DemuxFilterEvent event{
132 .filterId = filterId,
133 .filterType = type,
134 };
135 mFilterEvents[filterId] = event;
Amya609d5a2019-08-23 14:38:31 -0700136
Amya4885292019-09-06 10:30:53 -0700137 if (!createFilterMQ(bufferSize, filterId)) {
Amya609d5a2019-08-23 14:38:31 -0700138 _hidl_cb(Result::UNKNOWN_ERROR, -1);
139 return Void();
140 }
141
142 _hidl_cb(Result::SUCCESS, filterId);
143 return Void();
144}
145
146Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
147 ALOGV("%s", __FUNCTION__);
148
Amya4885292019-09-06 10:30:53 -0700149 if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
150 ALOGW("No filter with id: %d exists to get desc", filterId);
Amya609d5a2019-08-23 14:38:31 -0700151 _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
152 return Void();
153 }
154
155 _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
156 return Void();
157}
158
Amy42a5b4b2019-10-03 16:49:48 -0700159Return<Result> Demux::configureFilter(uint32_t filterId, const DemuxFilterSettings& settings) {
Amya609d5a2019-08-23 14:38:31 -0700160 ALOGV("%s", __FUNCTION__);
161
Amy42a5b4b2019-10-03 16:49:48 -0700162 switch (mFilterEvents[filterId].filterType) {
163 case DemuxFilterType::SECTION:
164 mFilterPids[filterId] = settings.section().tpid;
165 break;
166 case DemuxFilterType::PES:
167 mFilterPids[filterId] = settings.pesData().tpid;
168 break;
169 case DemuxFilterType::TS:
170 mFilterPids[filterId] = settings.ts().tpid;
171 break;
172 case DemuxFilterType::AUDIO:
173 mFilterPids[filterId] = settings.audio().tpid;
174 break;
175 case DemuxFilterType::VIDEO:
176 mFilterPids[filterId] = settings.video().tpid;
177 break;
178 case DemuxFilterType::RECORD:
179 mFilterPids[filterId] = settings.record().tpid;
180 break;
181 case DemuxFilterType::PCR:
182 mFilterPids[filterId] = settings.pcr().tpid;
183 break;
184 default:
185 return Result::UNKNOWN_ERROR;
186 }
Amya609d5a2019-08-23 14:38:31 -0700187 return Result::SUCCESS;
188}
189
190Return<Result> Demux::startFilter(uint32_t filterId) {
191 ALOGV("%s", __FUNCTION__);
Amya4885292019-09-06 10:30:53 -0700192 Result result;
Amya609d5a2019-08-23 14:38:31 -0700193
Amya4885292019-09-06 10:30:53 -0700194 if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
195 ALOGW("No filter with id: %d exists to start filter", filterId);
Amya609d5a2019-08-23 14:38:31 -0700196 return Result::INVALID_ARGUMENT;
197 }
198
Amy42a5b4b2019-10-03 16:49:48 -0700199 result = startFilterLoop(filterId);
Amya609d5a2019-08-23 14:38:31 -0700200
201 return result;
202}
203
Amy42a5b4b2019-10-03 16:49:48 -0700204Return<Result> Demux::stopFilter(uint32_t filterId) {
Amya609d5a2019-08-23 14:38:31 -0700205 ALOGV("%s", __FUNCTION__);
206
Amy42a5b4b2019-10-03 16:49:48 -0700207 mFilterThreadRunning[filterId] = false;
208
Amy5094ae12019-10-04 18:43:21 -0700209 std::lock_guard<std::mutex> lock(mFilterThreadLock);
210
Amya609d5a2019-08-23 14:38:31 -0700211 return Result::SUCCESS;
212}
213
214Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
215 ALOGV("%s", __FUNCTION__);
216
217 return Result::SUCCESS;
218}
219
Amya4885292019-09-06 10:30:53 -0700220Return<Result> Demux::removeFilter(uint32_t filterId) {
Amya609d5a2019-08-23 14:38:31 -0700221 ALOGV("%s", __FUNCTION__);
222
Amya4885292019-09-06 10:30:53 -0700223 // resetFilterRecords(filterId);
224 mUsedFilterIds.erase(filterId);
225 mUnusedFilterIds.insert(filterId);
226
Amya609d5a2019-08-23 14:38:31 -0700227 return Result::SUCCESS;
228}
229
230Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
231 ALOGV("%s", __FUNCTION__);
232
233 AvSyncHwId avSyncHwId = 0;
234
235 _hidl_cb(Result::SUCCESS, avSyncHwId);
236 return Void();
237}
238
239Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
240 ALOGV("%s", __FUNCTION__);
241
242 uint64_t avSyncTime = 0;
243
244 _hidl_cb(Result::SUCCESS, avSyncTime);
245 return Void();
246}
247
Amyfd4243a2019-08-16 16:01:27 -0700248Return<Result> Demux::close() {
249 ALOGV("%s", __FUNCTION__);
250
Amya4885292019-09-06 10:30:53 -0700251 set<uint32_t>::iterator it;
252 mInputThread = 0;
253 mOutputThread = 0;
254 mFilterThreads.clear();
255 mUnusedFilterIds.clear();
256 mUsedFilterIds.clear();
257 mDemuxCallbacks.clear();
258 mFilterMQs.clear();
259 mFilterEvents.clear();
260 mFilterEventFlags.clear();
Amy42a5b4b2019-10-03 16:49:48 -0700261 mFilterOutputs.clear();
262 mFilterPids.clear();
Amya4885292019-09-06 10:30:53 -0700263 mLastUsedFilterId = -1;
264
Amyfd4243a2019-08-16 16:01:27 -0700265 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700266}
267
Amya4885292019-09-06 10:30:53 -0700268Return<Result> Demux::addOutput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
269 ALOGV("%s", __FUNCTION__);
270
271 // Create a synchronized FMQ that supports blocking read/write
272 std::unique_ptr<FilterMQ> tmpFilterMQ =
273 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
274 if (!tmpFilterMQ->isValid()) {
275 ALOGW("Failed to create output FMQ");
276 return Result::UNKNOWN_ERROR;
Amya609d5a2019-08-23 14:38:31 -0700277 }
Amya4885292019-09-06 10:30:53 -0700278
279 mOutputMQ = std::move(tmpFilterMQ);
280
281 if (EventFlag::createEventFlag(mOutputMQ->getEventFlagWord(), &mOutputEventFlag) != OK) {
282 return Result::UNKNOWN_ERROR;
283 }
284
285 mOutputCallback = cb;
286
287 return Result::SUCCESS;
288}
289
290Return<void> Demux::getOutputQueueDesc(getOutputQueueDesc_cb _hidl_cb) {
291 ALOGV("%s", __FUNCTION__);
292
293 if (!mOutputMQ) {
294 _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
295 return Void();
296 }
297
298 _hidl_cb(Result::SUCCESS, *mOutputMQ->getDesc());
299 return Void();
300}
301
Amy42a5b4b2019-10-03 16:49:48 -0700302Return<Result> Demux::configureOutput(const DemuxOutputSettings& settings) {
303 ALOGV("%s", __FUNCTION__);
304
305 mOutputConfigured = true;
306 mOutputSettings = settings;
307 return Result::SUCCESS;
308}
309
310Return<Result> Demux::attachOutputFilter(uint32_t /*filterId*/) {
Amya4885292019-09-06 10:30:53 -0700311 ALOGV("%s", __FUNCTION__);
312
313 return Result::SUCCESS;
314}
315
Amy42a5b4b2019-10-03 16:49:48 -0700316Return<Result> Demux::detachOutputFilter(uint32_t /* filterId */) {
Amya4885292019-09-06 10:30:53 -0700317 ALOGV("%s", __FUNCTION__);
318
319 return Result::SUCCESS;
320}
321
322Return<Result> Demux::startOutput() {
323 ALOGV("%s", __FUNCTION__);
324
325 return Result::SUCCESS;
326}
327
328Return<Result> Demux::stopOutput() {
329 ALOGV("%s", __FUNCTION__);
330
331 return Result::SUCCESS;
332}
333
334Return<Result> Demux::flushOutput() {
335 ALOGV("%s", __FUNCTION__);
336
337 return Result::SUCCESS;
338}
339
340Return<Result> Demux::removeOutput() {
341 ALOGV("%s", __FUNCTION__);
342
343 return Result::SUCCESS;
344}
345
346Return<Result> Demux::addInput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
347 ALOGV("%s", __FUNCTION__);
348
349 // Create a synchronized FMQ that supports blocking read/write
350 std::unique_ptr<FilterMQ> tmpInputMQ =
351 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
352 if (!tmpInputMQ->isValid()) {
353 ALOGW("Failed to create input FMQ");
354 return Result::UNKNOWN_ERROR;
355 }
356
357 mInputMQ = std::move(tmpInputMQ);
358
359 if (EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputEventFlag) != OK) {
360 return Result::UNKNOWN_ERROR;
361 }
362
363 mInputCallback = cb;
364
365 return Result::SUCCESS;
366}
367
368Return<void> Demux::getInputQueueDesc(getInputQueueDesc_cb _hidl_cb) {
369 ALOGV("%s", __FUNCTION__);
370
371 if (!mInputMQ) {
372 _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
373 return Void();
374 }
375
376 _hidl_cb(Result::SUCCESS, *mInputMQ->getDesc());
377 return Void();
378}
379
Amy42a5b4b2019-10-03 16:49:48 -0700380Return<Result> Demux::configureInput(const DemuxInputSettings& settings) {
Amya4885292019-09-06 10:30:53 -0700381 ALOGV("%s", __FUNCTION__);
382
Amy42a5b4b2019-10-03 16:49:48 -0700383 mInputConfigured = true;
384 mInputSettings = settings;
385
Amya4885292019-09-06 10:30:53 -0700386 return Result::SUCCESS;
387}
388
389Return<Result> Demux::startInput() {
390 ALOGV("%s", __FUNCTION__);
391
Amy42a5b4b2019-10-03 16:49:48 -0700392 if (!mInputCallback) {
393 return Result::NOT_INITIALIZED;
394 }
395
396 if (!mInputConfigured) {
397 return Result::INVALID_STATE;
398 }
399
Amya4885292019-09-06 10:30:53 -0700400 pthread_create(&mInputThread, NULL, __threadLoopInput, this);
401 pthread_setname_np(mInputThread, "demux_input_waiting_loop");
402
403 // TODO start another thread to send filter status callback to the framework
404
405 return Result::SUCCESS;
406}
407
408Return<Result> Demux::stopInput() {
409 ALOGV("%s", __FUNCTION__);
410
Amy42a5b4b2019-10-03 16:49:48 -0700411 mInputThreadRunning = false;
412
Amy5094ae12019-10-04 18:43:21 -0700413 std::lock_guard<std::mutex> lock(mInputThreadLock);
414
Amya4885292019-09-06 10:30:53 -0700415 return Result::SUCCESS;
416}
417
418Return<Result> Demux::flushInput() {
419 ALOGV("%s", __FUNCTION__);
420
421 return Result::SUCCESS;
422}
423
424Return<Result> Demux::removeInput() {
425 ALOGV("%s", __FUNCTION__);
426
427 mInputMQ = nullptr;
428
429 return Result::SUCCESS;
430}
431
432Result Demux::startFilterLoop(uint32_t filterId) {
433 struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
434 threadArgs->user = this;
435 threadArgs->filterId = filterId;
436
437 pthread_t mFilterThread;
438 pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
439 mFilterThreads[filterId] = mFilterThread;
440 pthread_setname_np(mFilterThread, "demux_filter_waiting_loop");
441
442 return Result::SUCCESS;
443}
444
Amy42a5b4b2019-10-03 16:49:48 -0700445Result Demux::startSectionFilterHandler(uint32_t filterId) {
446 if (mFilterOutputs[filterId].empty()) {
447 return Result::SUCCESS;
448 }
449 if (!writeSectionsAndCreateEvent(filterId, mFilterOutputs[filterId])) {
Amya4885292019-09-06 10:30:53 -0700450 ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
451 return Result::UNKNOWN_ERROR;
452 }
453
Amy42a5b4b2019-10-03 16:49:48 -0700454 mFilterOutputs[filterId].clear();
455
Amya4885292019-09-06 10:30:53 -0700456 return Result::SUCCESS;
457}
458
459Result Demux::startPesFilterHandler(uint32_t filterId) {
Amy42a5b4b2019-10-03 16:49:48 -0700460 std::lock_guard<std::mutex> lock(mFilterEventLock);
Amya4885292019-09-06 10:30:53 -0700461 DemuxFilterPesEvent pesEvent;
Amy42a5b4b2019-10-03 16:49:48 -0700462 if (mFilterOutputs[filterId].empty()) {
463 return Result::SUCCESS;
464 }
465
Amy5094ae12019-10-04 18:43:21 -0700466 for (int i = 0; i < mFilterOutputs[filterId].size(); i += 188) {
467 uint8_t pusi = mFilterOutputs[filterId][i + 1] & 0x40;
468 uint8_t adaptFieldControl = (mFilterOutputs[filterId][i + 3] & 0x30) >> 4;
469 ALOGD("[Demux] pusi %d, adaptFieldControl %d", pusi, adaptFieldControl);
470 if (pusi && (adaptFieldControl == 0x01)) {
471 vector<uint8_t>::const_iterator first = mFilterOutputs[filterId].begin() + i + 4;
472 vector<uint8_t>::const_iterator last = mFilterOutputs[filterId].begin() + i + 187;
473 vector<uint8_t> filterOutData(first, last);
474 if (!writeDataToFilterMQ(filterOutData, filterId)) {
475 mFilterOutputs[filterId].clear();
476 return Result::INVALID_STATE;
477 }
478 pesEvent = {
479 // temp dump meta data
480 .streamId = filterOutData[3],
481 .dataLength = static_cast<uint16_t>(filterOutData.size()),
482 };
483 int size = mFilterEvents[filterId].events.size();
484 mFilterEvents[filterId].events.resize(size + 1);
485 mFilterEvents[filterId].events[size].pes(pesEvent);
486 }
Amy42a5b4b2019-10-03 16:49:48 -0700487 }
Amya4885292019-09-06 10:30:53 -0700488
Amy42a5b4b2019-10-03 16:49:48 -0700489 mFilterOutputs[filterId].clear();
Amya4885292019-09-06 10:30:53 -0700490
Amya4885292019-09-06 10:30:53 -0700491 return Result::SUCCESS;
492}
493
494Result Demux::startTsFilterHandler() {
495 // TODO handle starting TS filter
496 return Result::SUCCESS;
497}
498
499Result Demux::startMediaFilterHandler(uint32_t filterId) {
500 DemuxFilterMediaEvent mediaEvent;
501 mediaEvent = {
502 // temp dump meta data
503 .pts = 0,
504 .dataLength = 530,
505 .secureMemory = nullptr,
506 };
507 mFilterEvents[filterId].events.resize(1);
508 mFilterEvents[filterId].events[0].media() = mediaEvent;
Amy5094ae12019-10-04 18:43:21 -0700509
510 mFilterOutputs[filterId].clear();
Amya4885292019-09-06 10:30:53 -0700511 // TODO handle write FQM for media stream
512 return Result::SUCCESS;
513}
514
515Result Demux::startRecordFilterHandler(uint32_t filterId) {
516 DemuxFilterRecordEvent recordEvent;
517 recordEvent = {
518 // temp dump meta data
519 .tpid = 0,
520 .packetNum = 0,
521 };
522 recordEvent.indexMask.tsIndexMask() = 0x01;
523 mFilterEvents[filterId].events.resize(1);
524 mFilterEvents[filterId].events[0].ts() = recordEvent;
Amy5094ae12019-10-04 18:43:21 -0700525
526 mFilterOutputs[filterId].clear();
Amya4885292019-09-06 10:30:53 -0700527 return Result::SUCCESS;
528}
529
530Result Demux::startPcrFilterHandler() {
531 // TODO handle starting PCR filter
532 return Result::SUCCESS;
533}
534
535bool Demux::createFilterMQ(uint32_t bufferSize, uint32_t filterId) {
536 ALOGV("%s", __FUNCTION__);
537
538 // Create a synchronized FMQ that supports blocking read/write
539 std::unique_ptr<FilterMQ> tmpFilterMQ =
540 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
541 if (!tmpFilterMQ->isValid()) {
542 ALOGW("Failed to create FMQ of filter with id: %d", filterId);
543 return false;
544 }
545
546 mFilterMQs[filterId] = std::move(tmpFilterMQ);
547
548 EventFlag* filterEventFlag;
549 if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &filterEventFlag) !=
550 OK) {
551 return false;
552 }
553 mFilterEventFlags[filterId] = filterEventFlag;
554
555 return true;
556}
557
558bool Demux::writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data) {
559 // TODO check how many sections has been read
560 std::lock_guard<std::mutex> lock(mFilterEventLock);
Amya4885292019-09-06 10:30:53 -0700561 if (!writeDataToFilterMQ(data, filterId)) {
562 return false;
563 }
Amy42a5b4b2019-10-03 16:49:48 -0700564 int size = mFilterEvents[filterId].events.size();
565 mFilterEvents[filterId].events.resize(size + 1);
Amya4885292019-09-06 10:30:53 -0700566 DemuxFilterSectionEvent secEvent;
567 secEvent = {
568 // temp dump meta data
569 .tableId = 0,
570 .version = 1,
571 .sectionNum = 1,
Amy42a5b4b2019-10-03 16:49:48 -0700572 .dataLength = static_cast<uint16_t>(data.size()),
Amya4885292019-09-06 10:30:53 -0700573 };
574 mFilterEvents[filterId].events[size].section(secEvent);
Amya609d5a2019-08-23 14:38:31 -0700575 return true;
576}
577
578bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
579 std::lock_guard<std::mutex> lock(mWriteLock);
580 if (mFilterMQs[filterId]->write(data.data(), data.size())) {
581 return true;
582 }
583 return false;
584}
585
Amy5094ae12019-10-04 18:43:21 -0700586bool Demux::readInputFMQ() {
Amya4885292019-09-06 10:30:53 -0700587 // Read input data from the input FMQ
588 int size = mInputMQ->availableToRead();
Amy42a5b4b2019-10-03 16:49:48 -0700589 int inputPacketSize = mInputSettings.packetSize;
Amya4885292019-09-06 10:30:53 -0700590 vector<uint8_t> dataOutputBuffer;
Amy42a5b4b2019-10-03 16:49:48 -0700591 dataOutputBuffer.resize(inputPacketSize);
Amya609d5a2019-08-23 14:38:31 -0700592
Amy42a5b4b2019-10-03 16:49:48 -0700593 // Dispatch the packet to the PID matching filter output buffer
594 for (int i = 0; i < size / inputPacketSize; i++) {
Amy5094ae12019-10-04 18:43:21 -0700595 if (!mInputMQ->read(dataOutputBuffer.data(), inputPacketSize)) {
596 return false;
597 }
598 startTsFilter(dataOutputBuffer);
599 }
600
601 return true;
602}
603
604void Demux::startTsFilter(vector<uint8_t> data) {
605 set<uint32_t>::iterator it;
606 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
607 uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
608 ALOGW("start ts filter pid: %d", pid);
609 if (pid == mFilterPids[*it]) {
610 mFilterOutputs[*it].insert(mFilterOutputs[*it].end(), data.begin(), data.end());
Amy42a5b4b2019-10-03 16:49:48 -0700611 }
612 }
Amy5094ae12019-10-04 18:43:21 -0700613}
614
615bool Demux::startFilterDispatcher() {
616 Result result;
617 set<uint32_t>::iterator it;
Amy42a5b4b2019-10-03 16:49:48 -0700618
619 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700620 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
621 switch (mFilterEvents[*it].filterType) {
622 case DemuxFilterType::SECTION:
Amy42a5b4b2019-10-03 16:49:48 -0700623 result = startSectionFilterHandler(*it);
Amya4885292019-09-06 10:30:53 -0700624 break;
625 case DemuxFilterType::PES:
626 result = startPesFilterHandler(*it);
627 break;
628 case DemuxFilterType::TS:
629 result = startTsFilterHandler();
630 break;
631 case DemuxFilterType::AUDIO:
632 case DemuxFilterType::VIDEO:
633 result = startMediaFilterHandler(*it);
634 break;
635 case DemuxFilterType::RECORD:
636 result = startRecordFilterHandler(*it);
637 break;
638 case DemuxFilterType::PCR:
639 result = startPcrFilterHandler();
640 break;
641 default:
642 return false;
643 }
Amya609d5a2019-08-23 14:38:31 -0700644 }
645
Amya4885292019-09-06 10:30:53 -0700646 return result == Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700647}
648
Amya4885292019-09-06 10:30:53 -0700649void* Demux::__threadLoopFilter(void* threadArg) {
Amya609d5a2019-08-23 14:38:31 -0700650 Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
Amya4885292019-09-06 10:30:53 -0700651 self->filterThreadLoop(((struct ThreadArgs*)threadArg)->filterId);
Amya609d5a2019-08-23 14:38:31 -0700652 return 0;
653}
654
Amya4885292019-09-06 10:30:53 -0700655void* Demux::__threadLoopInput(void* user) {
656 Demux* const self = static_cast<Demux*>(user);
657 self->inputThreadLoop();
658 return 0;
659}
Amya609d5a2019-08-23 14:38:31 -0700660
Amya4885292019-09-06 10:30:53 -0700661void Demux::filterThreadLoop(uint32_t filterId) {
662 ALOGD("[Demux] filter %d threadLoop start.", filterId);
Amy5094ae12019-10-04 18:43:21 -0700663 std::lock_guard<std::mutex> lock(mFilterThreadLock);
Amya4885292019-09-06 10:30:53 -0700664 mFilterThreadRunning[filterId] = true;
665
666 // For the first time of filter output, implementation needs to send the filter
667 // Event Callback without waiting for the DATA_CONSUMED to init the process.
668 while (mFilterThreadRunning[filterId]) {
669 if (mFilterEvents[filterId].events.size() == 0) {
670 ALOGD("[Demux] wait for filter data output.");
671 usleep(1000 * 1000);
672 continue;
673 }
674 // After successfully write, send a callback and wait for the read to be done
675 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
676 mFilterEvents[filterId].events.resize(0);
677 break;
678 }
679
680 while (mFilterThreadRunning[filterId]) {
Amya609d5a2019-08-23 14:38:31 -0700681 uint32_t efState = 0;
682 // We do not wait for the last round of writen data to be read to finish the thread
683 // because the VTS can verify the reading itself.
684 for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
Amya4885292019-09-06 10:30:53 -0700685 while (mFilterThreadRunning[filterId]) {
Amya609d5a2019-08-23 14:38:31 -0700686 status_t status = mFilterEventFlags[filterId]->wait(
687 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
688 WAIT_TIMEOUT, true /* retry on spurious wake */);
689 if (status != OK) {
690 ALOGD("[Demux] wait for data consumed");
691 continue;
692 }
693 break;
694 }
Amya609d5a2019-08-23 14:38:31 -0700695
Amya4885292019-09-06 10:30:53 -0700696 if (mDemuxCallbacks[filterId] == nullptr) {
697 ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
698 break;
699 }
700
701 while (mFilterThreadRunning[filterId]) {
702 std::lock_guard<std::mutex> lock(mFilterEventLock);
703 if (mFilterEvents[filterId].events.size() == 0) {
704 continue;
705 }
706 // After successfully write, send a callback and wait for the read to be done
707 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
708 mFilterEvents[filterId].events.resize(0);
709 break;
710 }
711 // We do not wait for the last read to be done
712 // VTS can verify the read result itself.
713 if (i == SECTION_WRITE_COUNT - 1) {
714 ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
715 break;
716 }
717 }
718 mFilterThreadRunning[filterId] = false;
Amya609d5a2019-08-23 14:38:31 -0700719 }
720
721 ALOGD("[Demux] filter thread ended.");
Amyfd4243a2019-08-16 16:01:27 -0700722}
723
Amya4885292019-09-06 10:30:53 -0700724void Demux::inputThreadLoop() {
725 ALOGD("[Demux] input threadLoop start.");
Amy5094ae12019-10-04 18:43:21 -0700726 std::lock_guard<std::mutex> lock(mInputThreadLock);
Amya4885292019-09-06 10:30:53 -0700727 mInputThreadRunning = true;
728
729 while (mInputThreadRunning) {
730 uint32_t efState = 0;
731 status_t status =
732 mInputEventFlag->wait(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY),
733 &efState, WAIT_TIMEOUT, true /* retry on spurious wake */);
734 if (status != OK) {
735 ALOGD("[Demux] wait for data ready on the input FMQ");
736 continue;
737 }
738 // Our current implementation filter the data and write it into the filter FMQ immedaitely
739 // after the DATA_READY from the VTS/framework
Amy5094ae12019-10-04 18:43:21 -0700740 if (!readInputFMQ() || !startFilterDispatcher()) {
Amya4885292019-09-06 10:30:53 -0700741 ALOGD("[Demux] input data failed to be filtered. Ending thread");
742 break;
743 }
Amy42a5b4b2019-10-03 16:49:48 -0700744
745 maySendInputStatusCallback();
Amya4885292019-09-06 10:30:53 -0700746 }
747
748 mInputThreadRunning = false;
749 ALOGD("[Demux] input thread ended.");
750}
751
Amy42a5b4b2019-10-03 16:49:48 -0700752void Demux::maySendInputStatusCallback() {
753 std::lock_guard<std::mutex> lock(mInputStatusLock);
754 int availableToRead = mInputMQ->availableToRead();
755 int availableToWrite = mInputMQ->availableToWrite();
756
757 DemuxInputStatus newStatus =
758 checkStatusChange(availableToWrite, availableToRead, mInputSettings.highThreshold,
759 mInputSettings.lowThreshold);
760 if (mIntputStatus != newStatus) {
761 mInputCallback->onInputStatus(newStatus);
762 mIntputStatus = newStatus;
763 }
764}
765
766DemuxInputStatus Demux::checkStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
767 uint32_t highThreshold, uint32_t lowThreshold) {
768 if (availableToWrite == 0) {
769 return DemuxInputStatus::SPACE_FULL;
770 } else if (availableToRead > highThreshold) {
771 return DemuxInputStatus::SPACE_ALMOST_FULL;
772 } else if (availableToRead < lowThreshold) {
773 return DemuxInputStatus::SPACE_ALMOST_EMPTY;
774 } else if (availableToRead == 0) {
775 return DemuxInputStatus::SPACE_EMPTY;
776 }
777 return mIntputStatus;
778}
779
Amy5094ae12019-10-04 18:43:21 -0700780Result Demux::startBroadcastInputLoop() {
781 pthread_create(&mBroadcastInputThread, NULL, __threadLoopBroadcast, this);
782 pthread_setname_np(mBroadcastInputThread, "broadcast_input_thread");
783
784 return Result::SUCCESS;
785}
786
787void* Demux::__threadLoopBroadcast(void* user) {
788 Demux* const self = static_cast<Demux*>(user);
789 self->broadcastInputThreadLoop();
790 return 0;
791}
792
793void Demux::broadcastInputThreadLoop() {
794 std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
795 mBroadcastInputThreadRunning = true;
796 mKeepFetchingDataFromFrontend = true;
797
798 // open the stream and get its length
799 std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
800 // TODO take the packet size from the frontend setting
801 int packetSize = 188;
802 int writePacketAmount = 6;
803 char* buffer = new char[packetSize];
804 ALOGW("[Demux] broadcast input thread loop start %s", mFrontendSourceFile.c_str());
805 if (!inputData.is_open()) {
806 mBroadcastInputThreadRunning = false;
807 ALOGW("[Demux] Error %s", strerror(errno));
808 }
809
810 while (mBroadcastInputThreadRunning) {
811 // move the stream pointer for packet size * 6 every read until the end
812 while (mKeepFetchingDataFromFrontend) {
813 for (int i = 0; i < writePacketAmount; i++) {
814 inputData.read(buffer, packetSize);
815 if (!inputData) {
816 mBroadcastInputThreadRunning = false;
817 break;
818 }
819 // filter and dispatch filter output
820 vector<uint8_t> byteBuffer;
821 byteBuffer.resize(sizeof(buffer));
822 for (int index = 0; index < byteBuffer.size(); index++) {
823 byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
824 }
825 startTsFilter(byteBuffer);
826 inputData.seekg(packetSize, inputData.cur);
827 }
828 startFilterDispatcher();
829 sleep(1);
830 }
831 }
832
833 ALOGW("[Demux] Broadcast Input thread end.");
834 delete[] buffer;
835 inputData.close();
836}
837
838void Demux::stopBroadcastInput() {
839 mKeepFetchingDataFromFrontend = false;
840 mBroadcastInputThreadRunning = false;
841 std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
842}
843
Amyfd4243a2019-08-16 16:01:27 -0700844} // namespace implementation
845} // namespace V1_0
846} // namespace tuner
847} // namespace tv
848} // namespace hardware
849} // namespace android