blob: 4016c5a0e9477f712d3df588962163ef939091df [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
Amya609d5a2019-08-23 14:38:31 -070076bool Demux::createAndSaveMQ(uint32_t bufferSize, uint32_t filterId) {
77 ALOGV("%s", __FUNCTION__);
78
79 // Create a synchronized FMQ that supports blocking read/write
80 std::unique_ptr<FilterMQ> tmpFilterMQ =
81 std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
82 if (!tmpFilterMQ->isValid()) {
83 ALOGW("Failed to create FMQ of filter with id: %d", filterId);
84 return false;
85 }
86
87 mFilterMQs.resize(filterId + 1);
88 mFilterMQs[filterId] = std::move(tmpFilterMQ);
89
90 EventFlag* mFilterEventFlag;
91 if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &mFilterEventFlag) !=
92 OK) {
93 return false;
94 }
95 mFilterEventFlags.resize(filterId + 1);
96 mFilterEventFlags[filterId] = mFilterEventFlag;
97 mFilterWriteCount.resize(filterId + 1);
98 mFilterWriteCount[filterId] = 0;
99 mThreadRunning.resize(filterId + 1);
100
101 return true;
102}
103
Amyfd4243a2019-08-16 16:01:27 -0700104Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
105 ALOGV("%s", __FUNCTION__);
106
107 mSourceFrontendId = frontendId;
108
109 return Result::SUCCESS;
110}
111
Amya609d5a2019-08-23 14:38:31 -0700112Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
113 const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) {
114 ALOGV("%s", __FUNCTION__);
115
116 uint32_t filterId = mLastUsedFilterId + 1;
117 mLastUsedFilterId += 1;
118
119 if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
120 ALOGW("callback can't be null");
121 _hidl_cb(Result::INVALID_ARGUMENT, filterId);
122 return Void();
123 }
124 // Add callback
125 mDemuxCallbacks.resize(filterId + 1);
126 mDemuxCallbacks[filterId] = cb;
127
128 // Mapping from the filter ID to the filter type
129 mFilterTypes.resize(filterId + 1);
130 mFilterTypes[filterId] = type;
131
132 if (!createAndSaveMQ(bufferSize, filterId)) {
133 _hidl_cb(Result::UNKNOWN_ERROR, -1);
134 return Void();
135 }
136
137 _hidl_cb(Result::SUCCESS, filterId);
138 return Void();
139}
140
141Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
142 ALOGV("%s", __FUNCTION__);
143
144 if (filterId < 0 || filterId > mLastUsedFilterId) {
145 ALOGW("No filter with id: %d exists", filterId);
146 _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
147 return Void();
148 }
149
150 _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
151 return Void();
152}
153
154Return<Result> Demux::configureFilter(uint32_t /* filterId */,
155 const DemuxFilterSettings& /* settings */) {
156 ALOGV("%s", __FUNCTION__);
157
158 return Result::SUCCESS;
159}
160
161Return<Result> Demux::startFilter(uint32_t filterId) {
162 ALOGV("%s", __FUNCTION__);
163
164 if (filterId < 0 || filterId > mLastUsedFilterId) {
165 ALOGW("No filter with id: %d exists", filterId);
166 return Result::INVALID_ARGUMENT;
167 }
168
169 DemuxFilterType filterType = mFilterTypes[filterId];
170 Result result;
171 DemuxFilterEvent event{
172 .filterId = filterId,
173 .filterType = filterType,
174 };
175
176 switch (filterType) {
177 case DemuxFilterType::SECTION:
178 result = startSectionFilterHandler(event);
179 break;
180 case DemuxFilterType::PES:
181 result = startPesFilterHandler(event);
182 break;
183 case DemuxFilterType::TS:
184 result = startTsFilterHandler();
185 return Result::SUCCESS;
186 case DemuxFilterType::AUDIO:
187 case DemuxFilterType::VIDEO:
188 result = startMediaFilterHandler(event);
189 break;
190 case DemuxFilterType::RECORD:
191 result = startRecordFilterHandler(event);
192 break;
193 case DemuxFilterType::PCR:
194 result = startPcrFilterHandler();
195 return Result::SUCCESS;
196 default:
197 return Result::UNKNOWN_ERROR;
198 }
199
200 return result;
201}
202
203Return<Result> Demux::stopFilter(uint32_t /* filterId */) {
204 ALOGV("%s", __FUNCTION__);
205
206 return Result::SUCCESS;
207}
208
209Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
210 ALOGV("%s", __FUNCTION__);
211
212 return Result::SUCCESS;
213}
214
215Return<Result> Demux::removeFilter(uint32_t /* filterId */) {
216 ALOGV("%s", __FUNCTION__);
217
218 return Result::SUCCESS;
219}
220
221Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
222 ALOGV("%s", __FUNCTION__);
223
224 AvSyncHwId avSyncHwId = 0;
225
226 _hidl_cb(Result::SUCCESS, avSyncHwId);
227 return Void();
228}
229
230Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
231 ALOGV("%s", __FUNCTION__);
232
233 uint64_t avSyncTime = 0;
234
235 _hidl_cb(Result::SUCCESS, avSyncTime);
236 return Void();
237}
238
Amyfd4243a2019-08-16 16:01:27 -0700239Return<Result> Demux::close() {
240 ALOGV("%s", __FUNCTION__);
241
242 return Result::SUCCESS;
Amya609d5a2019-08-23 14:38:31 -0700243}
244
245bool Demux::writeSectionsAndCreateEvent(DemuxFilterEvent& event, uint32_t sectionNum) {
246 event.events.resize(sectionNum);
247 for (int i = 0; i < sectionNum; i++) {
248 DemuxFilterSectionEvent secEvent;
249 secEvent = {
250 // temp dump meta data
251 .tableId = 0,
252 .version = 1,
253 .sectionNum = 1,
254 .dataLength = 530,
255 };
256 event.events[i].section(secEvent);
257 if (!writeDataToFilterMQ(fakeDataInputBuffer, event.filterId)) {
258 return false;
259 }
260 }
261 return true;
262}
263
264bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
265 std::lock_guard<std::mutex> lock(mWriteLock);
266 if (mFilterMQs[filterId]->write(data.data(), data.size())) {
267 return true;
268 }
269 return false;
270}
271
272Result Demux::startSectionFilterHandler(DemuxFilterEvent event) {
273 struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
274 threadArgs->user = this;
275 threadArgs->event = &event;
276
277 pthread_create(&mThreadId, NULL, __threadLoop, (void*)threadArgs);
278 pthread_setname_np(mThreadId, "demux_filter_waiting_loop");
279
280 return Result::SUCCESS;
281}
282
283Result Demux::startPesFilterHandler(DemuxFilterEvent& event) {
284 // TODO generate multiple events in one event callback
285 DemuxFilterPesEvent pesEvent;
286 pesEvent = {
287 // temp dump meta data
288 .streamId = 0,
289 .dataLength = 530,
290 };
291 event.events.resize(1);
292 event.events[0].pes(pesEvent);
293 /*pthread_create(&mThreadId, NULL, __threadLoop, this);
294 pthread_setname_np(mThreadId, "demux_section_filter_waiting_loop");*/
295 if (!writeDataToFilterMQ(fakeDataInputBuffer, event.filterId)) {
296 return Result::INVALID_STATE;
297 }
298
299 if (mDemuxCallbacks[event.filterId] == nullptr) {
300 return Result::NOT_INITIALIZED;
301 }
302
303 mDemuxCallbacks[event.filterId]->onFilterEvent(event);
304 return Result::SUCCESS;
305}
306
307Result Demux::startTsFilterHandler() {
308 // TODO handle starting TS filter
309 return Result::SUCCESS;
310}
311
312Result Demux::startMediaFilterHandler(DemuxFilterEvent& event) {
313 DemuxFilterMediaEvent mediaEvent;
314 mediaEvent = {
315 // temp dump meta data
316 .pts = 0,
317 .dataLength = 530,
318 .secureMemory = nullptr,
319 };
320 event.events.resize(1);
321 event.events[0].media() = mediaEvent;
322 // TODO handle write FQM for media stream
323 return Result::SUCCESS;
324}
325
326Result Demux::startRecordFilterHandler(DemuxFilterEvent& event) {
327 DemuxFilterRecordEvent recordEvent;
328 recordEvent = {
329 // temp dump meta data
330 .tpid = 0,
331 .packetNum = 0,
332 };
333 recordEvent.indexMask.tsIndexMask() = 0x01;
334 event.events.resize(1);
335 event.events[0].ts() = recordEvent;
336 return Result::SUCCESS;
337}
338
339Result Demux::startPcrFilterHandler() {
340 // TODO handle starting PCR filter
341 return Result::SUCCESS;
342}
343
344void* Demux::__threadLoop(void* threadArg) {
345 Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
346 self->filterThreadLoop(((struct ThreadArgs*)threadArg)->event);
347 return 0;
348}
349
350void Demux::filterThreadLoop(DemuxFilterEvent* event) {
351 uint32_t filterId = event->filterId;
352 ALOGD("[Demux] filter %d threadLoop start.", filterId);
353 mThreadRunning[filterId] = true;
354
355 while (mThreadRunning[filterId]) {
356 uint32_t efState = 0;
357 // We do not wait for the last round of writen data to be read to finish the thread
358 // because the VTS can verify the reading itself.
359 for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
360 DemuxFilterEvent filterEvent{
361 .filterId = filterId,
362 .filterType = event->filterType,
363 };
364 if (!writeSectionsAndCreateEvent(filterEvent, 2)) {
365 ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
366 break;
367 }
368 mFilterWriteCount[filterId]++;
369 if (mDemuxCallbacks[filterId] == nullptr) {
370 ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
371 break;
372 }
373 // After successfully write, send a callback and wait for the read to be done
374 mDemuxCallbacks[filterId]->onFilterEvent(filterEvent);
375 // We do not wait for the last read to be done
376 // VTS can verify the read result itself.
377 if (i == SECTION_WRITE_COUNT - 1) {
378 ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
379 break;
380 }
381 while (mThreadRunning[filterId]) {
382 status_t status = mFilterEventFlags[filterId]->wait(
383 static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
384 WAIT_TIMEOUT, true /* retry on spurious wake */);
385 if (status != OK) {
386 ALOGD("[Demux] wait for data consumed");
387 continue;
388 }
389 break;
390 }
391 }
392
393 mFilterWriteCount[filterId] = 0;
394 mThreadRunning[filterId] = false;
395 }
396
397 ALOGD("[Demux] filter thread ended.");
Amyfd4243a2019-08-16 16:01:27 -0700398}
399
400} // namespace implementation
401} // namespace V1_0
402} // namespace tuner
403} // namespace tv
404} // namespace hardware
405} // namespace android