blob: 889e42ed062a816b8f782b501996a7fb2104c153 [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
Amyfd4243a2019-08-16 16:01:27 -070070Demux::Demux(uint32_t demuxId) {
71 mDemuxId = demuxId;
72}
73
74Demux::~Demux() {}
75
76Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
77 ALOGV("%s", __FUNCTION__);
78
79 mSourceFrontendId = frontendId;
80
81 return Result::SUCCESS;
82}
83
Amya609d5a2019-08-23 14:38:31 -070084Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
85 const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) {
86 ALOGV("%s", __FUNCTION__);
87
Amya4885292019-09-06 10:30:53 -070088 uint32_t filterId;
89
90 if (!mUnusedFilterIds.empty()) {
91 filterId = *mUnusedFilterIds.begin();
92
93 mUnusedFilterIds.erase(filterId);
94 } else {
95 filterId = ++mLastUsedFilterId;
96
97 mDemuxCallbacks.resize(filterId + 1);
98 mFilterMQs.resize(filterId + 1);
99 mFilterEvents.resize(filterId + 1);
100 mFilterEventFlags.resize(filterId + 1);
101 mFilterThreadRunning.resize(filterId + 1);
102 mFilterThreads.resize(filterId + 1);
103 }
104
105 mUsedFilterIds.insert(filterId);
Amya609d5a2019-08-23 14:38:31 -0700106
107 if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
108 ALOGW("callback can't be null");
109 _hidl_cb(Result::INVALID_ARGUMENT, filterId);
110 return Void();
111 }
Amya4885292019-09-06 10:30:53 -0700112
Amya609d5a2019-08-23 14:38:31 -0700113 // Add callback
Amya609d5a2019-08-23 14:38:31 -0700114 mDemuxCallbacks[filterId] = cb;
115
Amya4885292019-09-06 10:30:53 -0700116 // Mapping from the filter ID to the filter event
117 DemuxFilterEvent event{
118 .filterId = filterId,
119 .filterType = type,
120 };
121 mFilterEvents[filterId] = event;
Amya609d5a2019-08-23 14:38:31 -0700122
Amya4885292019-09-06 10:30:53 -0700123 if (!createFilterMQ(bufferSize, filterId)) {
Amya609d5a2019-08-23 14:38:31 -0700124 _hidl_cb(Result::UNKNOWN_ERROR, -1);
125 return Void();
126 }
127
128 _hidl_cb(Result::SUCCESS, filterId);
129 return Void();
130}
131
132Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
133 ALOGV("%s", __FUNCTION__);
134
Amya4885292019-09-06 10:30:53 -0700135 if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
136 ALOGW("No filter with id: %d exists to get desc", filterId);
Amya609d5a2019-08-23 14:38:31 -0700137 _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
138 return Void();
139 }
140
141 _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
142 return Void();
143}
144
145Return<Result> Demux::configureFilter(uint32_t /* filterId */,
146 const DemuxFilterSettings& /* settings */) {
147 ALOGV("%s", __FUNCTION__);
148
149 return Result::SUCCESS;
150}
151
152Return<Result> Demux::startFilter(uint32_t filterId) {
153 ALOGV("%s", __FUNCTION__);
Amya4885292019-09-06 10:30:53 -0700154 Result result;
Amya609d5a2019-08-23 14:38:31 -0700155
Amya4885292019-09-06 10:30:53 -0700156 if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
157 ALOGW("No filter with id: %d exists to start filter", filterId);
Amya609d5a2019-08-23 14:38:31 -0700158 return Result::INVALID_ARGUMENT;
159 }
160
Amya4885292019-09-06 10:30:53 -0700161 switch (mFilterEvents[filterId].filterType) {
Amya609d5a2019-08-23 14:38:31 -0700162 case DemuxFilterType::SECTION:
Amya4885292019-09-06 10:30:53 -0700163 result = startFilterLoop(filterId);
Amya609d5a2019-08-23 14:38:31 -0700164 break;
165 case DemuxFilterType::PES:
Amya4885292019-09-06 10:30:53 -0700166 result = startPesFilterHandler(filterId);
Amya609d5a2019-08-23 14:38:31 -0700167 break;
168 case DemuxFilterType::TS:
169 result = startTsFilterHandler();
170 return Result::SUCCESS;
171 case DemuxFilterType::AUDIO:
172 case DemuxFilterType::VIDEO:
Amya4885292019-09-06 10:30:53 -0700173 result = startMediaFilterHandler(filterId);
Amya609d5a2019-08-23 14:38:31 -0700174 break;
175 case DemuxFilterType::RECORD:
Amya4885292019-09-06 10:30:53 -0700176 result = startRecordFilterHandler(filterId);
Amya609d5a2019-08-23 14:38:31 -0700177 break;
178 case DemuxFilterType::PCR:
179 result = startPcrFilterHandler();
180 return Result::SUCCESS;
181 default:
182 return Result::UNKNOWN_ERROR;
183 }
184
185 return result;
186}
187
188Return<Result> Demux::stopFilter(uint32_t /* filterId */) {
189 ALOGV("%s", __FUNCTION__);
190
191 return Result::SUCCESS;
192}
193
194Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
195 ALOGV("%s", __FUNCTION__);
196
197 return Result::SUCCESS;
198}
199
Amya4885292019-09-06 10:30:53 -0700200Return<Result> Demux::removeFilter(uint32_t filterId) {
Amya609d5a2019-08-23 14:38:31 -0700201 ALOGV("%s", __FUNCTION__);
202
Amya4885292019-09-06 10:30:53 -0700203 // resetFilterRecords(filterId);
204 mUsedFilterIds.erase(filterId);
205 mUnusedFilterIds.insert(filterId);
206
Amya609d5a2019-08-23 14:38:31 -0700207 return Result::SUCCESS;
208}
209
210Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
211 ALOGV("%s", __FUNCTION__);
212
213 AvSyncHwId avSyncHwId = 0;
214
215 _hidl_cb(Result::SUCCESS, avSyncHwId);
216 return Void();
217}
218
219Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
220 ALOGV("%s", __FUNCTION__);
221
222 uint64_t avSyncTime = 0;
223
224 _hidl_cb(Result::SUCCESS, avSyncTime);
225 return Void();
226}
227
Amyfd4243a2019-08-16 16:01:27 -0700228Return<Result> Demux::close() {
229 ALOGV("%s", __FUNCTION__);
230
Amya4885292019-09-06 10:30:53 -0700231 set<uint32_t>::iterator it;
232 mInputThread = 0;
233 mOutputThread = 0;
234 mFilterThreads.clear();
235 mUnusedFilterIds.clear();
236 mUsedFilterIds.clear();
237 mDemuxCallbacks.clear();
238 mFilterMQs.clear();
239 mFilterEvents.clear();
240 mFilterEventFlags.clear();
241 mLastUsedFilterId = -1;
242
Amyfd4243a2019-08-16 16:01:27 -0700243 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700244}
245
Amya4885292019-09-06 10:30:53 -0700246Return<Result> Demux::addOutput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
247 ALOGV("%s", __FUNCTION__);
248
249 // Create a synchronized FMQ that supports blocking read/write
250 std::unique_ptr<FilterMQ> tmpFilterMQ =
251 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
252 if (!tmpFilterMQ->isValid()) {
253 ALOGW("Failed to create output FMQ");
254 return Result::UNKNOWN_ERROR;
Amya609d5a2019-08-23 14:38:31 -0700255 }
Amya4885292019-09-06 10:30:53 -0700256
257 mOutputMQ = std::move(tmpFilterMQ);
258
259 if (EventFlag::createEventFlag(mOutputMQ->getEventFlagWord(), &mOutputEventFlag) != OK) {
260 return Result::UNKNOWN_ERROR;
261 }
262
263 mOutputCallback = cb;
264
265 return Result::SUCCESS;
266}
267
268Return<void> Demux::getOutputQueueDesc(getOutputQueueDesc_cb _hidl_cb) {
269 ALOGV("%s", __FUNCTION__);
270
271 if (!mOutputMQ) {
272 _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
273 return Void();
274 }
275
276 _hidl_cb(Result::SUCCESS, *mOutputMQ->getDesc());
277 return Void();
278}
279
280Return<Result> Demux::configureOutput(const DemuxOutputSettings& /* settings */) {
281 ALOGV("%s", __FUNCTION__);
282
283 return Result::SUCCESS;
284}
285
286Return<Result> Demux::attachOutputTsFilter(uint32_t /*filterId*/) {
287 ALOGV("%s", __FUNCTION__);
288
289 return Result::SUCCESS;
290}
291
292Return<Result> Demux::detachOutputTsFilter(uint32_t /* filterId */) {
293 ALOGV("%s", __FUNCTION__);
294
295 return Result::SUCCESS;
296}
297
298Return<Result> Demux::startOutput() {
299 ALOGV("%s", __FUNCTION__);
300
301 return Result::SUCCESS;
302}
303
304Return<Result> Demux::stopOutput() {
305 ALOGV("%s", __FUNCTION__);
306
307 return Result::SUCCESS;
308}
309
310Return<Result> Demux::flushOutput() {
311 ALOGV("%s", __FUNCTION__);
312
313 return Result::SUCCESS;
314}
315
316Return<Result> Demux::removeOutput() {
317 ALOGV("%s", __FUNCTION__);
318
319 return Result::SUCCESS;
320}
321
322Return<Result> Demux::addInput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
323 ALOGV("%s", __FUNCTION__);
324
325 // Create a synchronized FMQ that supports blocking read/write
326 std::unique_ptr<FilterMQ> tmpInputMQ =
327 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
328 if (!tmpInputMQ->isValid()) {
329 ALOGW("Failed to create input FMQ");
330 return Result::UNKNOWN_ERROR;
331 }
332
333 mInputMQ = std::move(tmpInputMQ);
334
335 if (EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputEventFlag) != OK) {
336 return Result::UNKNOWN_ERROR;
337 }
338
339 mInputCallback = cb;
340
341 return Result::SUCCESS;
342}
343
344Return<void> Demux::getInputQueueDesc(getInputQueueDesc_cb _hidl_cb) {
345 ALOGV("%s", __FUNCTION__);
346
347 if (!mInputMQ) {
348 _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
349 return Void();
350 }
351
352 _hidl_cb(Result::SUCCESS, *mInputMQ->getDesc());
353 return Void();
354}
355
356Return<Result> Demux::configureInput(const DemuxInputSettings& /* settings */) {
357 ALOGV("%s", __FUNCTION__);
358
359 return Result::SUCCESS;
360}
361
362Return<Result> Demux::startInput() {
363 ALOGV("%s", __FUNCTION__);
364
365 pthread_create(&mInputThread, NULL, __threadLoopInput, this);
366 pthread_setname_np(mInputThread, "demux_input_waiting_loop");
367
368 // TODO start another thread to send filter status callback to the framework
369
370 return Result::SUCCESS;
371}
372
373Return<Result> Demux::stopInput() {
374 ALOGV("%s", __FUNCTION__);
375
376 return Result::SUCCESS;
377}
378
379Return<Result> Demux::flushInput() {
380 ALOGV("%s", __FUNCTION__);
381
382 return Result::SUCCESS;
383}
384
385Return<Result> Demux::removeInput() {
386 ALOGV("%s", __FUNCTION__);
387
388 mInputMQ = nullptr;
389
390 return Result::SUCCESS;
391}
392
393Result Demux::startFilterLoop(uint32_t filterId) {
394 struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
395 threadArgs->user = this;
396 threadArgs->filterId = filterId;
397
398 pthread_t mFilterThread;
399 pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
400 mFilterThreads[filterId] = mFilterThread;
401 pthread_setname_np(mFilterThread, "demux_filter_waiting_loop");
402
403 return Result::SUCCESS;
404}
405
406Result Demux::startSectionFilterHandler(uint32_t filterId, vector<uint8_t> data) {
407 if (!writeSectionsAndCreateEvent(filterId, data)) {
408 ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
409 return Result::UNKNOWN_ERROR;
410 }
411
412 return Result::SUCCESS;
413}
414
415Result Demux::startPesFilterHandler(uint32_t filterId) {
416 // TODO generate multiple events in one event callback
417 DemuxFilterPesEvent pesEvent;
418 pesEvent = {
419 // temp dump meta data
420 .streamId = 0,
421 .dataLength = 530,
422 };
423 mFilterEvents[filterId].events.resize(1);
424 mFilterEvents[filterId].events[0].pes(pesEvent);
425 /*pthread_create(&mThreadId, NULL, __threadLoop, this);
426 pthread_setname_np(mThreadId, "demux_section_filter_waiting_loop");*/
427 if (!writeDataToFilterMQ(fakeDataInputBuffer, filterId)) {
428 return Result::INVALID_STATE;
429 }
430
431 if (mDemuxCallbacks[filterId] == nullptr) {
432 return Result::NOT_INITIALIZED;
433 }
434
435 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
436 return Result::SUCCESS;
437}
438
439Result Demux::startTsFilterHandler() {
440 // TODO handle starting TS filter
441 return Result::SUCCESS;
442}
443
444Result Demux::startMediaFilterHandler(uint32_t filterId) {
445 DemuxFilterMediaEvent mediaEvent;
446 mediaEvent = {
447 // temp dump meta data
448 .pts = 0,
449 .dataLength = 530,
450 .secureMemory = nullptr,
451 };
452 mFilterEvents[filterId].events.resize(1);
453 mFilterEvents[filterId].events[0].media() = mediaEvent;
454 // TODO handle write FQM for media stream
455 return Result::SUCCESS;
456}
457
458Result Demux::startRecordFilterHandler(uint32_t filterId) {
459 DemuxFilterRecordEvent recordEvent;
460 recordEvent = {
461 // temp dump meta data
462 .tpid = 0,
463 .packetNum = 0,
464 };
465 recordEvent.indexMask.tsIndexMask() = 0x01;
466 mFilterEvents[filterId].events.resize(1);
467 mFilterEvents[filterId].events[0].ts() = recordEvent;
468 return Result::SUCCESS;
469}
470
471Result Demux::startPcrFilterHandler() {
472 // TODO handle starting PCR filter
473 return Result::SUCCESS;
474}
475
476bool Demux::createFilterMQ(uint32_t bufferSize, uint32_t filterId) {
477 ALOGV("%s", __FUNCTION__);
478
479 // Create a synchronized FMQ that supports blocking read/write
480 std::unique_ptr<FilterMQ> tmpFilterMQ =
481 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
482 if (!tmpFilterMQ->isValid()) {
483 ALOGW("Failed to create FMQ of filter with id: %d", filterId);
484 return false;
485 }
486
487 mFilterMQs[filterId] = std::move(tmpFilterMQ);
488
489 EventFlag* filterEventFlag;
490 if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &filterEventFlag) !=
491 OK) {
492 return false;
493 }
494 mFilterEventFlags[filterId] = filterEventFlag;
495
496 return true;
497}
498
499bool Demux::writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data) {
500 // TODO check how many sections has been read
501 std::lock_guard<std::mutex> lock(mFilterEventLock);
502 int size = mFilterEvents[filterId].events.size();
503 mFilterEvents[filterId].events.resize(size + 1);
504 if (!writeDataToFilterMQ(data, filterId)) {
505 return false;
506 }
507 DemuxFilterSectionEvent secEvent;
508 secEvent = {
509 // temp dump meta data
510 .tableId = 0,
511 .version = 1,
512 .sectionNum = 1,
513 .dataLength = 530,
514 };
515 mFilterEvents[filterId].events[size].section(secEvent);
Amya609d5a2019-08-23 14:38:31 -0700516 return true;
517}
518
519bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
520 std::lock_guard<std::mutex> lock(mWriteLock);
521 if (mFilterMQs[filterId]->write(data.data(), data.size())) {
522 return true;
523 }
524 return false;
525}
526
Amya4885292019-09-06 10:30:53 -0700527bool Demux::filterAndOutputData() {
528 ALOGD("[Demux] start to dispatch data to filters");
529 // Read input data from the input FMQ
530 int size = mInputMQ->availableToRead();
531 vector<uint8_t> dataOutputBuffer;
532 dataOutputBuffer.resize(size);
533 mInputMQ->read(dataOutputBuffer.data(), size);
Amya609d5a2019-08-23 14:38:31 -0700534
Amya4885292019-09-06 10:30:53 -0700535 Result result;
536 // Filter the data and feed the output to each filter
537 set<uint32_t>::iterator it;
538 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
539 switch (mFilterEvents[*it].filterType) {
540 case DemuxFilterType::SECTION:
541 result = startSectionFilterHandler(*it, dataOutputBuffer);
542 break;
543 case DemuxFilterType::PES:
544 result = startPesFilterHandler(*it);
545 break;
546 case DemuxFilterType::TS:
547 result = startTsFilterHandler();
548 break;
549 case DemuxFilterType::AUDIO:
550 case DemuxFilterType::VIDEO:
551 result = startMediaFilterHandler(*it);
552 break;
553 case DemuxFilterType::RECORD:
554 result = startRecordFilterHandler(*it);
555 break;
556 case DemuxFilterType::PCR:
557 result = startPcrFilterHandler();
558 break;
559 default:
560 return false;
561 }
Amya609d5a2019-08-23 14:38:31 -0700562 }
563
Amya4885292019-09-06 10:30:53 -0700564 return result == Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700565}
566
Amya4885292019-09-06 10:30:53 -0700567void* Demux::__threadLoopFilter(void* threadArg) {
Amya609d5a2019-08-23 14:38:31 -0700568 Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
Amya4885292019-09-06 10:30:53 -0700569 self->filterThreadLoop(((struct ThreadArgs*)threadArg)->filterId);
Amya609d5a2019-08-23 14:38:31 -0700570 return 0;
571}
572
Amya4885292019-09-06 10:30:53 -0700573void* Demux::__threadLoopInput(void* user) {
574 Demux* const self = static_cast<Demux*>(user);
575 self->inputThreadLoop();
576 return 0;
577}
Amya609d5a2019-08-23 14:38:31 -0700578
Amya4885292019-09-06 10:30:53 -0700579void Demux::filterThreadLoop(uint32_t filterId) {
580 ALOGD("[Demux] filter %d threadLoop start.", filterId);
581 mFilterThreadRunning[filterId] = true;
582
583 // For the first time of filter output, implementation needs to send the filter
584 // Event Callback without waiting for the DATA_CONSUMED to init the process.
585 while (mFilterThreadRunning[filterId]) {
586 if (mFilterEvents[filterId].events.size() == 0) {
587 ALOGD("[Demux] wait for filter data output.");
588 usleep(1000 * 1000);
589 continue;
590 }
591 // After successfully write, send a callback and wait for the read to be done
592 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
593 mFilterEvents[filterId].events.resize(0);
594 break;
595 }
596
597 while (mFilterThreadRunning[filterId]) {
Amya609d5a2019-08-23 14:38:31 -0700598 uint32_t efState = 0;
599 // We do not wait for the last round of writen data to be read to finish the thread
600 // because the VTS can verify the reading itself.
601 for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
Amya4885292019-09-06 10:30:53 -0700602 while (mFilterThreadRunning[filterId]) {
Amya609d5a2019-08-23 14:38:31 -0700603 status_t status = mFilterEventFlags[filterId]->wait(
604 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
605 WAIT_TIMEOUT, true /* retry on spurious wake */);
606 if (status != OK) {
607 ALOGD("[Demux] wait for data consumed");
608 continue;
609 }
610 break;
611 }
Amya609d5a2019-08-23 14:38:31 -0700612
Amya4885292019-09-06 10:30:53 -0700613 if (mDemuxCallbacks[filterId] == nullptr) {
614 ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
615 break;
616 }
617
618 while (mFilterThreadRunning[filterId]) {
619 std::lock_guard<std::mutex> lock(mFilterEventLock);
620 if (mFilterEvents[filterId].events.size() == 0) {
621 continue;
622 }
623 // After successfully write, send a callback and wait for the read to be done
624 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
625 mFilterEvents[filterId].events.resize(0);
626 break;
627 }
628 // We do not wait for the last read to be done
629 // VTS can verify the read result itself.
630 if (i == SECTION_WRITE_COUNT - 1) {
631 ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
632 break;
633 }
634 }
635 mFilterThreadRunning[filterId] = false;
Amya609d5a2019-08-23 14:38:31 -0700636 }
637
638 ALOGD("[Demux] filter thread ended.");
Amyfd4243a2019-08-16 16:01:27 -0700639}
640
Amya4885292019-09-06 10:30:53 -0700641void Demux::inputThreadLoop() {
642 ALOGD("[Demux] input threadLoop start.");
643 mInputThreadRunning = true;
644
645 while (mInputThreadRunning) {
646 uint32_t efState = 0;
647 status_t status =
648 mInputEventFlag->wait(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY),
649 &efState, WAIT_TIMEOUT, true /* retry on spurious wake */);
650 if (status != OK) {
651 ALOGD("[Demux] wait for data ready on the input FMQ");
652 continue;
653 }
654 // Our current implementation filter the data and write it into the filter FMQ immedaitely
655 // after the DATA_READY from the VTS/framework
656 if (!filterAndOutputData()) {
657 ALOGD("[Demux] input data failed to be filtered. Ending thread");
658 break;
659 }
660 }
661
662 mInputThreadRunning = false;
663 ALOGD("[Demux] input thread ended.");
664}
665
Amyfd4243a2019-08-16 16:01:27 -0700666} // namespace implementation
667} // namespace V1_0
668} // namespace tuner
669} // namespace tv
670} // namespace hardware
671} // namespace android