1 /*
2 * Copyright 2020 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 #include "FilterTests.h"
18
startFilterEventThread(DemuxFilterEvent event)19 void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
20 struct FilterThreadArgs* threadArgs =
21 (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
22 threadArgs->user = this;
23 threadArgs->event = event;
24
25 pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
26 pthread_setname_np(mFilterThread, "test_playback_input_loop");
27 }
28
testFilterDataOutput()29 void FilterCallback::testFilterDataOutput() {
30 android::Mutex::Autolock autoLock(mMsgLock);
31 while (mPidFilterOutputCount < 1) {
32 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
33 EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
34 return;
35 }
36 }
37 mPidFilterOutputCount = 0;
38 ALOGW("[vts] pass and stop");
39 }
40
updateFilterMQ(MQDesc & filterMQDescriptor)41 void FilterCallback::updateFilterMQ(MQDesc& filterMQDescriptor) {
42 mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
43 EXPECT_TRUE(mFilterMQ);
44 EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
45 android::OK);
46 }
47
updateGoldenOutputMap(string goldenOutputFile)48 void FilterCallback::updateGoldenOutputMap(string goldenOutputFile) {
49 mFilterIdToGoldenOutput = goldenOutputFile;
50 }
51
__threadLoopFilter(void * threadArgs)52 void* FilterCallback::__threadLoopFilter(void* threadArgs) {
53 FilterCallback* const self =
54 static_cast<FilterCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
55 self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
56 return 0;
57 }
58
filterThreadLoop(DemuxFilterEvent &)59 void FilterCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
60 android::Mutex::Autolock autoLock(mFilterOutputLock);
61 // Read from mFilterMQ[event.filterId] per event and filter type
62
63 // Assemble to filterOutput[filterId]
64
65 // check if filterOutput[filterId] matches goldenOutput[filterId]
66
67 // If match, remove filterId entry from MQ map
68
69 // end thread
70 }
71
readFilterEventData()72 bool FilterCallback::readFilterEventData() {
73 bool result = false;
74 DemuxFilterEvent filterEvent = mFilterEvent;
75 ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
76 // todo separate filter handlers
77 for (int i = 0; i < filterEvent.events.size(); i++) {
78 switch (mFilterEventType) {
79 case FilterEventType::SECTION:
80 mDataLength = filterEvent.events[i].section().dataLength;
81 break;
82 case FilterEventType::PES:
83 mDataLength = filterEvent.events[i].pes().dataLength;
84 break;
85 case FilterEventType::MEDIA:
86 return dumpAvData(filterEvent.events[i].media());
87 case FilterEventType::RECORD:
88 break;
89 case FilterEventType::MMTPRECORD:
90 break;
91 case FilterEventType::DOWNLOAD:
92 break;
93 default:
94 break;
95 }
96 // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
97 // match";
98
99 mDataOutputBuffer.resize(mDataLength);
100 result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength);
101 EXPECT_TRUE(result) << "can't read from Filter MQ";
102
103 /*for (int i = 0; i < mDataLength; i++) {
104 EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
105 }*/
106 }
107 mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
108 return result;
109 }
110
dumpAvData(DemuxFilterMediaEvent event)111 bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
112 uint32_t length = event.dataLength;
113 uint64_t dataId = event.avDataId;
114 // read data from buffer pointed by a handle
115 hidl_handle handle = event.avMemory;
116
117 int av_fd = handle.getNativeHandle()->data[0];
118 uint8_t* buffer = static_cast<uint8_t*>(
119 mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
120 if (buffer == MAP_FAILED) {
121 ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
122 return false;
123 }
124 uint8_t output[length + 1];
125 memcpy(output, buffer, length);
126 // print buffer and check with golden output.
127 EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
128 return true;
129 }
130
openFilterInDemux(DemuxFilterType type,uint32_t bufferSize)131 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
132 Result status;
133 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
134
135 // Create demux callback
136 mFilterCallback = new FilterCallback();
137
138 // Add filter to the local demux
139 mDemux->openFilter(type, bufferSize, mFilterCallback,
140 [&](Result result, const sp<IFilter>& filter) {
141 mFilter = filter;
142 status = result;
143 });
144
145 if (status == Result::SUCCESS) {
146 mFilterCallback->setFilterEventType(getFilterEventType(type));
147 }
148
149 return AssertionResult(status == Result::SUCCESS);
150 }
151
openTimeFilterInDemux()152 AssertionResult FilterTests::openTimeFilterInDemux() {
153 if (!mDemux) {
154 ALOGW("[vts] Test with openDemux first.");
155 return failure();
156 }
157
158 // Add time filter to the local demux
159 Result status;
160 mDemux->openTimeFilter([&](Result result, const sp<ITimeFilter>& filter) {
161 mTimeFilter = filter;
162 status = result;
163 });
164
165 return AssertionResult(status == Result::SUCCESS);
166 }
167
setTimeStamp(uint64_t timeStamp)168 AssertionResult FilterTests::setTimeStamp(uint64_t timeStamp) {
169 if (!mTimeFilter) {
170 ALOGW("[vts] Test with openTimeFilterInDemux first.");
171 return failure();
172 }
173
174 mBeginTimeStamp = timeStamp;
175 return AssertionResult(mTimeFilter->setTimeStamp(timeStamp) == Result::SUCCESS);
176 }
177
getTimeStamp()178 AssertionResult FilterTests::getTimeStamp() {
179 if (!mTimeFilter) {
180 ALOGW("[vts] Test with openTimeFilterInDemux first.");
181 return failure();
182 }
183
184 Result status;
185 mTimeFilter->getTimeStamp([&](Result result, uint64_t /*timeStamp*/) { status = result; });
186
187 return AssertionResult(status == Result::SUCCESS);
188 }
189
getNewlyOpenedFilterId(uint32_t & filterId)190 AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
191 Result status;
192 EXPECT_TRUE(mDemux) << "Test with openDemux first.";
193 EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
194 EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
195
196 mFilter->getId([&](Result result, uint32_t filterId) {
197 mFilterId = filterId;
198 status = result;
199 });
200
201 if (status == Result::SUCCESS) {
202 mFilterCallback->setFilterId(mFilterId);
203 mFilterCallback->setFilterInterface(mFilter);
204 mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
205 mFilters[mFilterId] = mFilter;
206 mFilterCallbacks[mFilterId] = mFilterCallback;
207 filterId = mFilterId;
208 }
209
210 return AssertionResult(status == Result::SUCCESS);
211 }
212
configFilter(DemuxFilterSettings setting,uint32_t filterId)213 AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
214 Result status;
215 EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
216 status = mFilters[filterId]->configure(setting);
217
218 return AssertionResult(status == Result::SUCCESS);
219 }
220
getFilterMQDescriptor(uint32_t filterId)221 AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId) {
222 Result status;
223 EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
224 EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
225
226 mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
227 mFilterMQDescriptor = filterMQDesc;
228 status = result;
229 });
230
231 if (status == Result::SUCCESS) {
232 mFilterCallbacks[filterId]->updateFilterMQ(mFilterMQDescriptor);
233 }
234
235 return AssertionResult(status == Result::SUCCESS);
236 }
237
setFilterDataSource(uint32_t sourceFilterId,uint32_t sinkFilterId)238 AssertionResult FilterTests::setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId) {
239 if (!mFilters[sourceFilterId] || !mFilters[sinkFilterId]) {
240 ALOGE("[vts] setFilterDataSource filter not opened.");
241 return failure();
242 }
243
244 auto status = mFilters[sinkFilterId]->setDataSource(mFilters[sourceFilterId]);
245 return AssertionResult(status == Result::SUCCESS);
246 }
247
setFilterDataSourceToDemux(uint32_t filterId)248 AssertionResult FilterTests::setFilterDataSourceToDemux(uint32_t filterId) {
249 if (!mFilters[filterId]) {
250 ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
251 return failure();
252 }
253
254 auto status = mFilters[filterId]->setDataSource(NULL);
255 return AssertionResult(status == Result::SUCCESS);
256 }
257
startFilter(uint32_t filterId)258 AssertionResult FilterTests::startFilter(uint32_t filterId) {
259 EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
260 Result status = mFilters[filterId]->start();
261 return AssertionResult(status == Result::SUCCESS);
262 }
263
stopFilter(uint32_t filterId)264 AssertionResult FilterTests::stopFilter(uint32_t filterId) {
265 EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
266 Result status = mFilters[filterId]->stop();
267 return AssertionResult(status == Result::SUCCESS);
268 }
269
clearTimeStamp()270 AssertionResult FilterTests::clearTimeStamp() {
271 if (!mTimeFilter) {
272 ALOGW("[vts] Test with openTimeFilterInDemux first.");
273 return failure();
274 }
275
276 return AssertionResult(mTimeFilter->clearTimeStamp() == Result::SUCCESS);
277 }
278
closeFilter(uint32_t filterId)279 AssertionResult FilterTests::closeFilter(uint32_t filterId) {
280 EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
281 Result status = mFilters[filterId]->close();
282 if (status == Result::SUCCESS) {
283 for (int i = 0; i < mUsedFilterIds.size(); i++) {
284 if (mUsedFilterIds[i] == filterId) {
285 mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
286 break;
287 }
288 }
289 mFilterCallbacks.erase(filterId);
290 mFilters.erase(filterId);
291 }
292 return AssertionResult(status == Result::SUCCESS);
293 }
294
closeTimeFilter()295 AssertionResult FilterTests::closeTimeFilter() {
296 if (!mTimeFilter) {
297 ALOGW("[vts] Test with openTimeFilterInDemux first.");
298 return failure();
299 }
300
301 return AssertionResult(mTimeFilter->close() == Result::SUCCESS);
302 }
303