blob: 080116c4a99005fcd2327ac2bda43f51bd074034 [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);
Amy42a5b4b2019-10-03 16:49:48 -0700103 mFilterPids.resize(filterId + 1);
104 mFilterOutputs.resize(filterId + 1);
Amya4885292019-09-06 10:30:53 -0700105 }
106
107 mUsedFilterIds.insert(filterId);
Amya609d5a2019-08-23 14:38:31 -0700108
109 if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
110 ALOGW("callback can't be null");
111 _hidl_cb(Result::INVALID_ARGUMENT, filterId);
112 return Void();
113 }
Amya4885292019-09-06 10:30:53 -0700114
Amya609d5a2019-08-23 14:38:31 -0700115 // Add callback
Amya609d5a2019-08-23 14:38:31 -0700116 mDemuxCallbacks[filterId] = cb;
117
Amya4885292019-09-06 10:30:53 -0700118 // Mapping from the filter ID to the filter event
119 DemuxFilterEvent event{
120 .filterId = filterId,
121 .filterType = type,
122 };
123 mFilterEvents[filterId] = event;
Amya609d5a2019-08-23 14:38:31 -0700124
Amya4885292019-09-06 10:30:53 -0700125 if (!createFilterMQ(bufferSize, filterId)) {
Amya609d5a2019-08-23 14:38:31 -0700126 _hidl_cb(Result::UNKNOWN_ERROR, -1);
127 return Void();
128 }
129
130 _hidl_cb(Result::SUCCESS, filterId);
131 return Void();
132}
133
134Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
135 ALOGV("%s", __FUNCTION__);
136
Amya4885292019-09-06 10:30:53 -0700137 if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
138 ALOGW("No filter with id: %d exists to get desc", filterId);
Amya609d5a2019-08-23 14:38:31 -0700139 _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
140 return Void();
141 }
142
143 _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
144 return Void();
145}
146
Amy42a5b4b2019-10-03 16:49:48 -0700147Return<Result> Demux::configureFilter(uint32_t filterId, const DemuxFilterSettings& settings) {
Amya609d5a2019-08-23 14:38:31 -0700148 ALOGV("%s", __FUNCTION__);
149
Amy42a5b4b2019-10-03 16:49:48 -0700150 switch (mFilterEvents[filterId].filterType) {
151 case DemuxFilterType::SECTION:
152 mFilterPids[filterId] = settings.section().tpid;
153 break;
154 case DemuxFilterType::PES:
155 mFilterPids[filterId] = settings.pesData().tpid;
156 break;
157 case DemuxFilterType::TS:
158 mFilterPids[filterId] = settings.ts().tpid;
159 break;
160 case DemuxFilterType::AUDIO:
161 mFilterPids[filterId] = settings.audio().tpid;
162 break;
163 case DemuxFilterType::VIDEO:
164 mFilterPids[filterId] = settings.video().tpid;
165 break;
166 case DemuxFilterType::RECORD:
167 mFilterPids[filterId] = settings.record().tpid;
168 break;
169 case DemuxFilterType::PCR:
170 mFilterPids[filterId] = settings.pcr().tpid;
171 break;
172 default:
173 return Result::UNKNOWN_ERROR;
174 }
Amya609d5a2019-08-23 14:38:31 -0700175 return Result::SUCCESS;
176}
177
178Return<Result> Demux::startFilter(uint32_t filterId) {
179 ALOGV("%s", __FUNCTION__);
Amya4885292019-09-06 10:30:53 -0700180 Result result;
Amya609d5a2019-08-23 14:38:31 -0700181
Amya4885292019-09-06 10:30:53 -0700182 if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
183 ALOGW("No filter with id: %d exists to start filter", filterId);
Amya609d5a2019-08-23 14:38:31 -0700184 return Result::INVALID_ARGUMENT;
185 }
186
Amy42a5b4b2019-10-03 16:49:48 -0700187 result = startFilterLoop(filterId);
Amya609d5a2019-08-23 14:38:31 -0700188
189 return result;
190}
191
Amy42a5b4b2019-10-03 16:49:48 -0700192Return<Result> Demux::stopFilter(uint32_t filterId) {
Amya609d5a2019-08-23 14:38:31 -0700193 ALOGV("%s", __FUNCTION__);
194
Amy42a5b4b2019-10-03 16:49:48 -0700195 mFilterThreadRunning[filterId] = false;
196
Amya609d5a2019-08-23 14:38:31 -0700197 return Result::SUCCESS;
198}
199
200Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
201 ALOGV("%s", __FUNCTION__);
202
203 return Result::SUCCESS;
204}
205
Amya4885292019-09-06 10:30:53 -0700206Return<Result> Demux::removeFilter(uint32_t filterId) {
Amya609d5a2019-08-23 14:38:31 -0700207 ALOGV("%s", __FUNCTION__);
208
Amya4885292019-09-06 10:30:53 -0700209 // resetFilterRecords(filterId);
210 mUsedFilterIds.erase(filterId);
211 mUnusedFilterIds.insert(filterId);
212
Amya609d5a2019-08-23 14:38:31 -0700213 return Result::SUCCESS;
214}
215
216Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
217 ALOGV("%s", __FUNCTION__);
218
219 AvSyncHwId avSyncHwId = 0;
220
221 _hidl_cb(Result::SUCCESS, avSyncHwId);
222 return Void();
223}
224
225Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
226 ALOGV("%s", __FUNCTION__);
227
228 uint64_t avSyncTime = 0;
229
230 _hidl_cb(Result::SUCCESS, avSyncTime);
231 return Void();
232}
233
Amyfd4243a2019-08-16 16:01:27 -0700234Return<Result> Demux::close() {
235 ALOGV("%s", __FUNCTION__);
236
Amya4885292019-09-06 10:30:53 -0700237 set<uint32_t>::iterator it;
238 mInputThread = 0;
239 mOutputThread = 0;
240 mFilterThreads.clear();
241 mUnusedFilterIds.clear();
242 mUsedFilterIds.clear();
243 mDemuxCallbacks.clear();
244 mFilterMQs.clear();
245 mFilterEvents.clear();
246 mFilterEventFlags.clear();
Amy42a5b4b2019-10-03 16:49:48 -0700247 mFilterOutputs.clear();
248 mFilterPids.clear();
Amya4885292019-09-06 10:30:53 -0700249 mLastUsedFilterId = -1;
250
Amyfd4243a2019-08-16 16:01:27 -0700251 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700252}
253
Amya4885292019-09-06 10:30:53 -0700254Return<Result> Demux::addOutput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
255 ALOGV("%s", __FUNCTION__);
256
257 // Create a synchronized FMQ that supports blocking read/write
258 std::unique_ptr<FilterMQ> tmpFilterMQ =
259 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
260 if (!tmpFilterMQ->isValid()) {
261 ALOGW("Failed to create output FMQ");
262 return Result::UNKNOWN_ERROR;
Amya609d5a2019-08-23 14:38:31 -0700263 }
Amya4885292019-09-06 10:30:53 -0700264
265 mOutputMQ = std::move(tmpFilterMQ);
266
267 if (EventFlag::createEventFlag(mOutputMQ->getEventFlagWord(), &mOutputEventFlag) != OK) {
268 return Result::UNKNOWN_ERROR;
269 }
270
271 mOutputCallback = cb;
272
273 return Result::SUCCESS;
274}
275
276Return<void> Demux::getOutputQueueDesc(getOutputQueueDesc_cb _hidl_cb) {
277 ALOGV("%s", __FUNCTION__);
278
279 if (!mOutputMQ) {
280 _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
281 return Void();
282 }
283
284 _hidl_cb(Result::SUCCESS, *mOutputMQ->getDesc());
285 return Void();
286}
287
Amy42a5b4b2019-10-03 16:49:48 -0700288Return<Result> Demux::configureOutput(const DemuxOutputSettings& settings) {
289 ALOGV("%s", __FUNCTION__);
290
291 mOutputConfigured = true;
292 mOutputSettings = settings;
293 return Result::SUCCESS;
294}
295
296Return<Result> Demux::attachOutputFilter(uint32_t /*filterId*/) {
Amya4885292019-09-06 10:30:53 -0700297 ALOGV("%s", __FUNCTION__);
298
299 return Result::SUCCESS;
300}
301
Amy42a5b4b2019-10-03 16:49:48 -0700302Return<Result> Demux::detachOutputFilter(uint32_t /* filterId */) {
Amya4885292019-09-06 10:30:53 -0700303 ALOGV("%s", __FUNCTION__);
304
305 return Result::SUCCESS;
306}
307
308Return<Result> Demux::startOutput() {
309 ALOGV("%s", __FUNCTION__);
310
311 return Result::SUCCESS;
312}
313
314Return<Result> Demux::stopOutput() {
315 ALOGV("%s", __FUNCTION__);
316
317 return Result::SUCCESS;
318}
319
320Return<Result> Demux::flushOutput() {
321 ALOGV("%s", __FUNCTION__);
322
323 return Result::SUCCESS;
324}
325
326Return<Result> Demux::removeOutput() {
327 ALOGV("%s", __FUNCTION__);
328
329 return Result::SUCCESS;
330}
331
332Return<Result> Demux::addInput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
333 ALOGV("%s", __FUNCTION__);
334
335 // Create a synchronized FMQ that supports blocking read/write
336 std::unique_ptr<FilterMQ> tmpInputMQ =
337 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
338 if (!tmpInputMQ->isValid()) {
339 ALOGW("Failed to create input FMQ");
340 return Result::UNKNOWN_ERROR;
341 }
342
343 mInputMQ = std::move(tmpInputMQ);
344
345 if (EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputEventFlag) != OK) {
346 return Result::UNKNOWN_ERROR;
347 }
348
349 mInputCallback = cb;
350
351 return Result::SUCCESS;
352}
353
354Return<void> Demux::getInputQueueDesc(getInputQueueDesc_cb _hidl_cb) {
355 ALOGV("%s", __FUNCTION__);
356
357 if (!mInputMQ) {
358 _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
359 return Void();
360 }
361
362 _hidl_cb(Result::SUCCESS, *mInputMQ->getDesc());
363 return Void();
364}
365
Amy42a5b4b2019-10-03 16:49:48 -0700366Return<Result> Demux::configureInput(const DemuxInputSettings& settings) {
Amya4885292019-09-06 10:30:53 -0700367 ALOGV("%s", __FUNCTION__);
368
Amy42a5b4b2019-10-03 16:49:48 -0700369 mInputConfigured = true;
370 mInputSettings = settings;
371
Amya4885292019-09-06 10:30:53 -0700372 return Result::SUCCESS;
373}
374
375Return<Result> Demux::startInput() {
376 ALOGV("%s", __FUNCTION__);
377
Amy42a5b4b2019-10-03 16:49:48 -0700378 if (!mInputCallback) {
379 return Result::NOT_INITIALIZED;
380 }
381
382 if (!mInputConfigured) {
383 return Result::INVALID_STATE;
384 }
385
Amya4885292019-09-06 10:30:53 -0700386 pthread_create(&mInputThread, NULL, __threadLoopInput, this);
387 pthread_setname_np(mInputThread, "demux_input_waiting_loop");
388
389 // TODO start another thread to send filter status callback to the framework
390
391 return Result::SUCCESS;
392}
393
394Return<Result> Demux::stopInput() {
395 ALOGV("%s", __FUNCTION__);
396
Amy42a5b4b2019-10-03 16:49:48 -0700397 mInputThreadRunning = false;
398
Amya4885292019-09-06 10:30:53 -0700399 return Result::SUCCESS;
400}
401
402Return<Result> Demux::flushInput() {
403 ALOGV("%s", __FUNCTION__);
404
405 return Result::SUCCESS;
406}
407
408Return<Result> Demux::removeInput() {
409 ALOGV("%s", __FUNCTION__);
410
411 mInputMQ = nullptr;
412
413 return Result::SUCCESS;
414}
415
416Result Demux::startFilterLoop(uint32_t filterId) {
417 struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
418 threadArgs->user = this;
419 threadArgs->filterId = filterId;
420
421 pthread_t mFilterThread;
422 pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
423 mFilterThreads[filterId] = mFilterThread;
424 pthread_setname_np(mFilterThread, "demux_filter_waiting_loop");
425
426 return Result::SUCCESS;
427}
428
Amy42a5b4b2019-10-03 16:49:48 -0700429Result Demux::startSectionFilterHandler(uint32_t filterId) {
430 if (mFilterOutputs[filterId].empty()) {
431 return Result::SUCCESS;
432 }
433 if (!writeSectionsAndCreateEvent(filterId, mFilterOutputs[filterId])) {
Amya4885292019-09-06 10:30:53 -0700434 ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
435 return Result::UNKNOWN_ERROR;
436 }
437
Amy42a5b4b2019-10-03 16:49:48 -0700438 mFilterOutputs[filterId].clear();
439
Amya4885292019-09-06 10:30:53 -0700440 return Result::SUCCESS;
441}
442
443Result Demux::startPesFilterHandler(uint32_t filterId) {
Amy42a5b4b2019-10-03 16:49:48 -0700444 std::lock_guard<std::mutex> lock(mFilterEventLock);
Amya4885292019-09-06 10:30:53 -0700445 DemuxFilterPesEvent pesEvent;
Amy42a5b4b2019-10-03 16:49:48 -0700446 if (mFilterOutputs[filterId].empty()) {
447 return Result::SUCCESS;
448 }
449
450 // TODO extract PES from TS
451 if (!writeDataToFilterMQ(mFilterOutputs[filterId], filterId)) {
452 mFilterOutputs[filterId].clear();
453 return Result::INVALID_STATE;
454 }
Amya4885292019-09-06 10:30:53 -0700455 pesEvent = {
456 // temp dump meta data
457 .streamId = 0,
Amy42a5b4b2019-10-03 16:49:48 -0700458 .dataLength = static_cast<uint16_t>(mFilterOutputs[filterId].size()),
Amya4885292019-09-06 10:30:53 -0700459 };
Amy42a5b4b2019-10-03 16:49:48 -0700460 int size = mFilterEvents[filterId].events.size();
461 mFilterEvents[filterId].events.resize(size + 1);
462 mFilterEvents[filterId].events[size].pes(pesEvent);
Amya4885292019-09-06 10:30:53 -0700463
Amy42a5b4b2019-10-03 16:49:48 -0700464 mFilterOutputs[filterId].clear();
Amya4885292019-09-06 10:30:53 -0700465
Amya4885292019-09-06 10:30:53 -0700466 return Result::SUCCESS;
467}
468
469Result Demux::startTsFilterHandler() {
470 // TODO handle starting TS filter
471 return Result::SUCCESS;
472}
473
474Result Demux::startMediaFilterHandler(uint32_t filterId) {
475 DemuxFilterMediaEvent mediaEvent;
476 mediaEvent = {
477 // temp dump meta data
478 .pts = 0,
479 .dataLength = 530,
480 .secureMemory = nullptr,
481 };
482 mFilterEvents[filterId].events.resize(1);
483 mFilterEvents[filterId].events[0].media() = mediaEvent;
484 // TODO handle write FQM for media stream
485 return Result::SUCCESS;
486}
487
488Result Demux::startRecordFilterHandler(uint32_t filterId) {
489 DemuxFilterRecordEvent recordEvent;
490 recordEvent = {
491 // temp dump meta data
492 .tpid = 0,
493 .packetNum = 0,
494 };
495 recordEvent.indexMask.tsIndexMask() = 0x01;
496 mFilterEvents[filterId].events.resize(1);
497 mFilterEvents[filterId].events[0].ts() = recordEvent;
498 return Result::SUCCESS;
499}
500
501Result Demux::startPcrFilterHandler() {
502 // TODO handle starting PCR filter
503 return Result::SUCCESS;
504}
505
506bool Demux::createFilterMQ(uint32_t bufferSize, uint32_t filterId) {
507 ALOGV("%s", __FUNCTION__);
508
509 // Create a synchronized FMQ that supports blocking read/write
510 std::unique_ptr<FilterMQ> tmpFilterMQ =
511 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
512 if (!tmpFilterMQ->isValid()) {
513 ALOGW("Failed to create FMQ of filter with id: %d", filterId);
514 return false;
515 }
516
517 mFilterMQs[filterId] = std::move(tmpFilterMQ);
518
519 EventFlag* filterEventFlag;
520 if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &filterEventFlag) !=
521 OK) {
522 return false;
523 }
524 mFilterEventFlags[filterId] = filterEventFlag;
525
526 return true;
527}
528
529bool Demux::writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data) {
530 // TODO check how many sections has been read
531 std::lock_guard<std::mutex> lock(mFilterEventLock);
Amya4885292019-09-06 10:30:53 -0700532 if (!writeDataToFilterMQ(data, filterId)) {
533 return false;
534 }
Amy42a5b4b2019-10-03 16:49:48 -0700535 int size = mFilterEvents[filterId].events.size();
536 mFilterEvents[filterId].events.resize(size + 1);
Amya4885292019-09-06 10:30:53 -0700537 DemuxFilterSectionEvent secEvent;
538 secEvent = {
539 // temp dump meta data
540 .tableId = 0,
541 .version = 1,
542 .sectionNum = 1,
Amy42a5b4b2019-10-03 16:49:48 -0700543 .dataLength = static_cast<uint16_t>(data.size()),
Amya4885292019-09-06 10:30:53 -0700544 };
545 mFilterEvents[filterId].events[size].section(secEvent);
Amya609d5a2019-08-23 14:38:31 -0700546 return true;
547}
548
549bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
550 std::lock_guard<std::mutex> lock(mWriteLock);
551 if (mFilterMQs[filterId]->write(data.data(), data.size())) {
552 return true;
553 }
554 return false;
555}
556
Amya4885292019-09-06 10:30:53 -0700557bool Demux::filterAndOutputData() {
Amy42a5b4b2019-10-03 16:49:48 -0700558 Result result;
559 set<uint32_t>::iterator it;
560
Amya4885292019-09-06 10:30:53 -0700561 // Read input data from the input FMQ
562 int size = mInputMQ->availableToRead();
Amy42a5b4b2019-10-03 16:49:48 -0700563 int inputPacketSize = mInputSettings.packetSize;
Amya4885292019-09-06 10:30:53 -0700564 vector<uint8_t> dataOutputBuffer;
Amy42a5b4b2019-10-03 16:49:48 -0700565 dataOutputBuffer.resize(inputPacketSize);
Amya609d5a2019-08-23 14:38:31 -0700566
Amy42a5b4b2019-10-03 16:49:48 -0700567 // Dispatch the packet to the PID matching filter output buffer
568 for (int i = 0; i < size / inputPacketSize; i++) {
569 mInputMQ->read(dataOutputBuffer.data(), inputPacketSize);
570 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
571 uint16_t pid = ((dataOutputBuffer[1] & 0x1f) << 8) | ((dataOutputBuffer[2] & 0xff));
572 if (pid == mFilterPids[*it]) {
573 mFilterOutputs[*it].insert(mFilterOutputs[*it].end(), dataOutputBuffer.begin(),
574 dataOutputBuffer.end());
575 }
576 }
577 }
578
579 // Handle the output data per filter type
Amya4885292019-09-06 10:30:53 -0700580 for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
581 switch (mFilterEvents[*it].filterType) {
582 case DemuxFilterType::SECTION:
Amy42a5b4b2019-10-03 16:49:48 -0700583 result = startSectionFilterHandler(*it);
Amya4885292019-09-06 10:30:53 -0700584 break;
585 case DemuxFilterType::PES:
586 result = startPesFilterHandler(*it);
587 break;
588 case DemuxFilterType::TS:
589 result = startTsFilterHandler();
590 break;
591 case DemuxFilterType::AUDIO:
592 case DemuxFilterType::VIDEO:
593 result = startMediaFilterHandler(*it);
594 break;
595 case DemuxFilterType::RECORD:
596 result = startRecordFilterHandler(*it);
597 break;
598 case DemuxFilterType::PCR:
599 result = startPcrFilterHandler();
600 break;
601 default:
602 return false;
603 }
Amya609d5a2019-08-23 14:38:31 -0700604 }
605
Amya4885292019-09-06 10:30:53 -0700606 return result == Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700607}
608
Amya4885292019-09-06 10:30:53 -0700609void* Demux::__threadLoopFilter(void* threadArg) {
Amya609d5a2019-08-23 14:38:31 -0700610 Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
Amya4885292019-09-06 10:30:53 -0700611 self->filterThreadLoop(((struct ThreadArgs*)threadArg)->filterId);
Amya609d5a2019-08-23 14:38:31 -0700612 return 0;
613}
614
Amya4885292019-09-06 10:30:53 -0700615void* Demux::__threadLoopInput(void* user) {
616 Demux* const self = static_cast<Demux*>(user);
617 self->inputThreadLoop();
618 return 0;
619}
Amya609d5a2019-08-23 14:38:31 -0700620
Amya4885292019-09-06 10:30:53 -0700621void Demux::filterThreadLoop(uint32_t filterId) {
622 ALOGD("[Demux] filter %d threadLoop start.", filterId);
623 mFilterThreadRunning[filterId] = true;
624
625 // For the first time of filter output, implementation needs to send the filter
626 // Event Callback without waiting for the DATA_CONSUMED to init the process.
627 while (mFilterThreadRunning[filterId]) {
628 if (mFilterEvents[filterId].events.size() == 0) {
629 ALOGD("[Demux] wait for filter data output.");
630 usleep(1000 * 1000);
631 continue;
632 }
633 // After successfully write, send a callback and wait for the read to be done
634 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
635 mFilterEvents[filterId].events.resize(0);
636 break;
637 }
638
639 while (mFilterThreadRunning[filterId]) {
Amya609d5a2019-08-23 14:38:31 -0700640 uint32_t efState = 0;
641 // We do not wait for the last round of writen data to be read to finish the thread
642 // because the VTS can verify the reading itself.
643 for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
Amya4885292019-09-06 10:30:53 -0700644 while (mFilterThreadRunning[filterId]) {
Amya609d5a2019-08-23 14:38:31 -0700645 status_t status = mFilterEventFlags[filterId]->wait(
646 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
647 WAIT_TIMEOUT, true /* retry on spurious wake */);
648 if (status != OK) {
649 ALOGD("[Demux] wait for data consumed");
650 continue;
651 }
652 break;
653 }
Amya609d5a2019-08-23 14:38:31 -0700654
Amya4885292019-09-06 10:30:53 -0700655 if (mDemuxCallbacks[filterId] == nullptr) {
656 ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
657 break;
658 }
659
660 while (mFilterThreadRunning[filterId]) {
661 std::lock_guard<std::mutex> lock(mFilterEventLock);
662 if (mFilterEvents[filterId].events.size() == 0) {
663 continue;
664 }
665 // After successfully write, send a callback and wait for the read to be done
666 mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
667 mFilterEvents[filterId].events.resize(0);
668 break;
669 }
670 // We do not wait for the last read to be done
671 // VTS can verify the read result itself.
672 if (i == SECTION_WRITE_COUNT - 1) {
673 ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
674 break;
675 }
676 }
677 mFilterThreadRunning[filterId] = false;
Amya609d5a2019-08-23 14:38:31 -0700678 }
679
680 ALOGD("[Demux] filter thread ended.");
Amyfd4243a2019-08-16 16:01:27 -0700681}
682
Amya4885292019-09-06 10:30:53 -0700683void Demux::inputThreadLoop() {
684 ALOGD("[Demux] input threadLoop start.");
685 mInputThreadRunning = true;
686
687 while (mInputThreadRunning) {
688 uint32_t efState = 0;
689 status_t status =
690 mInputEventFlag->wait(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY),
691 &efState, WAIT_TIMEOUT, true /* retry on spurious wake */);
692 if (status != OK) {
693 ALOGD("[Demux] wait for data ready on the input FMQ");
694 continue;
695 }
696 // Our current implementation filter the data and write it into the filter FMQ immedaitely
697 // after the DATA_READY from the VTS/framework
698 if (!filterAndOutputData()) {
699 ALOGD("[Demux] input data failed to be filtered. Ending thread");
700 break;
701 }
Amy42a5b4b2019-10-03 16:49:48 -0700702
703 maySendInputStatusCallback();
Amya4885292019-09-06 10:30:53 -0700704 }
705
706 mInputThreadRunning = false;
707 ALOGD("[Demux] input thread ended.");
708}
709
Amy42a5b4b2019-10-03 16:49:48 -0700710void Demux::maySendInputStatusCallback() {
711 std::lock_guard<std::mutex> lock(mInputStatusLock);
712 int availableToRead = mInputMQ->availableToRead();
713 int availableToWrite = mInputMQ->availableToWrite();
714
715 DemuxInputStatus newStatus =
716 checkStatusChange(availableToWrite, availableToRead, mInputSettings.highThreshold,
717 mInputSettings.lowThreshold);
718 if (mIntputStatus != newStatus) {
719 mInputCallback->onInputStatus(newStatus);
720 mIntputStatus = newStatus;
721 }
722}
723
724DemuxInputStatus Demux::checkStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
725 uint32_t highThreshold, uint32_t lowThreshold) {
726 if (availableToWrite == 0) {
727 return DemuxInputStatus::SPACE_FULL;
728 } else if (availableToRead > highThreshold) {
729 return DemuxInputStatus::SPACE_ALMOST_FULL;
730 } else if (availableToRead < lowThreshold) {
731 return DemuxInputStatus::SPACE_ALMOST_EMPTY;
732 } else if (availableToRead == 0) {
733 return DemuxInputStatus::SPACE_EMPTY;
734 }
735 return mIntputStatus;
736}
737
Amyfd4243a2019-08-16 16:01:27 -0700738} // namespace implementation
739} // namespace V1_0
740} // namespace tuner
741} // namespace tv
742} // namespace hardware
743} // namespace android