Tuner HAL Demux Playback interface VTS
Test: manual
Bug: 135708935
Change-Id: Ifb93bbd5920f7998d9716a55cba983f8a5ace425
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 66adb2a..d272d71 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -34,6 +34,8 @@
#include <hidlmemory/FrameworkUtils.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
#define WAIT_TIMEOUT 3000000000
@@ -53,11 +55,16 @@
using android::hardware::MQDescriptorSync;
using android::hardware::Return;
using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxDataFormat;
using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxInputSettings;
+using android::hardware::tv::tuner::V1_0::DemuxInputStatus;
+using android::hardware::tv::tuner::V1_0::DemuxOutputStatus;
using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
@@ -77,9 +84,9 @@
namespace {
using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using FilterMQDesc = MQDescriptorSync<uint8_t>;
+using MQDesc = MQDescriptorSync<uint8_t>;
-const std::vector<uint8_t> goldenDataInputBuffer{
+const std::vector<uint8_t> goldenDataOutputBuffer{
0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
@@ -119,10 +126,21 @@
};
const uint16_t FMQ_SIZE_4K = 0x1000;
+const uint32_t FMQ_SIZE_1M = 0x100000;
// Equal to SECTION_WRITE_COUNT on the HAL impl side
// The HAL impl will repeatedly write to the FMQ the count times
const uint16_t SECTION_READ_COUNT = 10;
+struct FilterConf {
+ DemuxFilterType type;
+ DemuxFilterSettings setting;
+};
+
+struct InputConf {
+ string inputDataFile;
+ DemuxInputSettings setting;
+};
+
class FrontendCallback : public IFrontendCallback {
public:
virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
@@ -184,8 +202,10 @@
class DemuxCallback : public IDemuxCallback {
public:
virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
+ ALOGW("[VTS] FILTER EVENT %d", filterEvent.filterId);
android::Mutex::Autolock autoLock(mMsgLock);
mFilterEventReceived = true;
+ // maybe assemble here??
mFilterEvent = filterEvent;
mMsgCondition.signal();
return Void();
@@ -196,24 +216,53 @@
return Void();
}
+ virtual Return<void> onOutputStatus(DemuxOutputStatus /*status*/) override { return Void(); }
+
+ virtual Return<void> onInputStatus(DemuxInputStatus status) override {
+ // android::Mutex::Autolock autoLock(mMsgLock);
+ switch (status) {
+ case DemuxInputStatus::SPACE_EMPTY:
+ case DemuxInputStatus::SPACE_ALMOST_EMPTY:
+ mKeepWritingInputFMQ = true;
+ break;
+ case DemuxInputStatus::SPACE_ALMOST_FULL:
+ case DemuxInputStatus::SPACE_FULL:
+ mKeepWritingInputFMQ = false;
+ break;
+ }
+ return Void();
+ }
+
void testOnFilterEvent(uint32_t filterId);
- void testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId,
- FilterMQDesc& filterMQDescriptor);
- void testOnPesFilterEvent(sp<IDemux>& demux, uint32_t filterId,
- FilterMQDesc& filterMQDescriptor);
- void readAndCompareSectionEventData();
- void readAndComparePesEventData();
+ void testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId, MQDesc& filterMQDescriptor,
+ MQDesc& inputMQDescriptor);
+ void startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor);
+ bool readAndCompareSectionEventData();
+
+ static void* __threadLoopInput(void* threadArgs);
+ void inputThreadLoop(InputConf inputConf, bool* keepWritingInputFMQ, MQDesc& inputMQDescriptor);
private:
+ struct InputThreadArgs {
+ DemuxCallback* user;
+ InputConf inputConf;
+ bool* keepWritingInputFMQ;
+ MQDesc& inputMQDesc;
+ };
bool mFilterEventReceived = false;
std::vector<uint8_t> mDataOutputBuffer;
std::unique_ptr<FilterMQ> mFilterMQ;
+ std::unique_ptr<FilterMQ> mInputMQ;
uint16_t mDataLength = 0;
DemuxFilterEvent mFilterEvent;
android::Mutex mMsgLock;
android::Mutex mReadLock;
android::Condition mMsgCondition;
EventFlag* mFilterMQEventFlag;
+ EventFlag* mInputMQEventFlag;
+ bool mKeepWritingInputFMQ;
+ bool mInputThreadRunning;
+ pthread_t mInputThread;
};
void DemuxCallback::testOnFilterEvent(uint32_t filterId) {
@@ -230,83 +279,138 @@
EXPECT_TRUE(filterId == mFilterEvent.filterId) << "filter id match";
}
+void DemuxCallback::startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor) {
+ struct InputThreadArgs* threadArgs =
+ (struct InputThreadArgs*)malloc(sizeof(struct InputThreadArgs));
+ threadArgs->user = this;
+ threadArgs->inputConf = inputConf;
+ threadArgs->keepWritingInputFMQ = &mKeepWritingInputFMQ;
+ threadArgs->inputMQDesc = inputMQDescriptor;
+
+ pthread_create(&mInputThread, NULL, __threadLoopInput, (void*)threadArgs);
+ pthread_setname_np(mInputThread, "test_playback_input_loop");
+}
+
+/*void DemuxCallback::testPlaybackDataFlow(bool* keepWritingInputFMQ) {
+ // timeout logic here
+
+ // assemble logic here
+
+
+}*/
+
void DemuxCallback::testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId,
- FilterMQDesc& filterMQDescriptor) {
+ MQDesc& filterMQDescriptor,
+ MQDesc& inputMQDescriptor) {
Result status;
// Create MQ to read the output into the local buffer
mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
EXPECT_TRUE(mFilterMQ);
+ // Get the MQ to write the input to the HAL
+ mInputMQ = std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(mInputMQ);
// Create the EventFlag that is used to signal the HAL impl that data have been
// read the Filter FMQ
EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
android::OK);
+ // Create the EventFlag that is used to signal the HAL impl that data have been
+ // written into the Input FMQ
+ EXPECT_TRUE(EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputMQEventFlag) ==
+ android::OK);
// Start filter
status = demux->startFilter(filterId);
+ status = demux->startInput();
+
EXPECT_EQ(status, Result::SUCCESS);
// Test start filter and receive callback event
for (int i = 0; i < SECTION_READ_COUNT; i++) {
+ // Write input FMQ and notify the Tuner Implementation
+ EXPECT_TRUE(mInputMQ->write(goldenDataOutputBuffer.data(), goldenDataOutputBuffer.size()));
+ mInputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
testOnFilterEvent(filterId);
// checksum of mDataOutputBuffer and Input golden input
- readAndCompareSectionEventData();
+ if (readAndCompareSectionEventData() && i < SECTION_READ_COUNT - 1) {
+ mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ }
}
}
-void DemuxCallback::testOnPesFilterEvent(sp<IDemux>& demux, uint32_t filterId,
- FilterMQDesc& filterMQDescriptor) {
- Result status;
- // Create MQ to read the output into the local buffer
- mFilterMQ = std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mFilterMQ);
- // Create the EventFlag that is used to signal the HAL impl that data have been
- // read the Filter FMQ
- EXPECT_TRUE(EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag) ==
- android::OK);
- // Start filter
- status = demux->startFilter(filterId);
- EXPECT_EQ(status, Result::SUCCESS);
- // Test start filter and receive callback event
- testOnFilterEvent(filterId);
- // checksum of mDataOutputBuffer and Input golden input
- readAndComparePesEventData();
-}
-
-void DemuxCallback::readAndCompareSectionEventData() {
+bool DemuxCallback::readAndCompareSectionEventData() {
bool result = false;
for (int i = 0; i < mFilterEvent.events.size(); i++) {
DemuxFilterSectionEvent event = mFilterEvent.events[i].section();
mDataLength = event.dataLength;
- EXPECT_TRUE(mDataLength == goldenDataInputBuffer.size()) << "buffer size does not match";
+ EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not match";
mDataOutputBuffer.resize(mDataLength);
result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength);
EXPECT_TRUE(result) << "can't read from Filter MQ";
for (int i = 0; i < mDataLength; i++) {
- EXPECT_TRUE(goldenDataInputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
+ EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
}
}
- if (result) {
- mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
- }
+ return result;
}
-void DemuxCallback::readAndComparePesEventData() {
- // TODO handle multiple events in one filter callback event
- DemuxFilterPesEvent event = mFilterEvent.events[0].pes();
- mDataLength = event.dataLength;
- EXPECT_TRUE(mDataLength == goldenDataInputBuffer.size()) << "buffer size does not match";
+void* DemuxCallback::__threadLoopInput(void* threadArgs) {
+ DemuxCallback* const self =
+ static_cast<DemuxCallback*>(((struct InputThreadArgs*)threadArgs)->user);
+ self->inputThreadLoop(((struct InputThreadArgs*)threadArgs)->inputConf,
+ ((struct InputThreadArgs*)threadArgs)->keepWritingInputFMQ,
+ ((struct InputThreadArgs*)threadArgs)->inputMQDesc);
+ return 0;
+}
- mDataOutputBuffer.resize(mDataLength);
- bool result = mFilterMQ->read(mDataOutputBuffer.data(), mDataLength);
- EXPECT_TRUE(result) << "can't read from Filter MQ";
+void DemuxCallback::inputThreadLoop(InputConf inputConf, bool* keepWritingInputFMQ,
+ MQDesc& inputMQDescriptor) {
+ mInputThreadRunning = true;
- if (result) {
- mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ std::unique_ptr inputMQ =
+ std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(inputMQ);
+
+ // Create the EventFlag that is used to signal the HAL impl that data have been
+ // written into the Input FMQ
+ EventFlag* inputMQEventFlag;
+ EXPECT_TRUE(EventFlag::createEventFlag(inputMQ->getEventFlagWord(), &inputMQEventFlag) ==
+ android::OK);
+
+ // open the stream and get its length
+ std::ifstream inputData(inputConf.inputDataFile /*"ts/test1.ts"*/, std::ifstream::binary);
+ int writeSize = inputConf.setting.packetSize * 6;
+ char* buffer = new char[writeSize];
+ if (!inputData) {
+ // log
+ mInputThreadRunning = false;
}
- for (int i = 0; i < mDataLength; i++) {
- EXPECT_TRUE(goldenDataInputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
+ while (mInputThreadRunning) {
+ // move the stream pointer for packet size * 2k? every read until end
+ while (*keepWritingInputFMQ) {
+ inputData.read(buffer, writeSize);
+ if (!inputData) {
+ int leftSize = inputData.gcount();
+ inputData.clear();
+ inputData.read(buffer, leftSize);
+ // Write the left over of the input data and quit the thread
+ if (leftSize > 0) {
+ EXPECT_TRUE(inputMQ->write((unsigned char*)&buffer[0],
+ leftSize / inputConf.setting.packetSize));
+ inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+ }
+ mInputThreadRunning = false;
+ break;
+ }
+ // Write input FMQ and notify the Tuner Implementation
+ EXPECT_TRUE(inputMQ->write((unsigned char*)&buffer[0], 6));
+ inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+ inputData.seekg(writeSize, inputData.cur);
+ }
}
+
+ delete[] buffer;
+ inputData.close();
}
// Test environment for Tuner HIDL HAL.
@@ -341,24 +445,33 @@
sp<IDescrambler> mDescrambler;
sp<IDemux> mDemux;
sp<DemuxCallback> mDemuxCallback;
- FilterMQDesc mFilterMQDescriptor;
+ MQDesc mFilterMQDescriptor;
+ MQDesc mInputMQDescriptor;
+
uint32_t mDemuxId;
uint32_t mFilterId;
+ pthread_t mInputThread;
+ bool mInputThreadRunning;
+
::testing::AssertionResult createFrontend(int32_t frontendId);
::testing::AssertionResult tuneFrontend(int32_t frontendId);
::testing::AssertionResult stopTuneFrontend(int32_t frontendId);
::testing::AssertionResult closeFrontend(int32_t frontendId);
::testing::AssertionResult createDemux();
::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId);
+ ::testing::AssertionResult getInputMQDescriptor();
+ ::testing::AssertionResult addInputToDemux(DemuxInputSettings setting);
::testing::AssertionResult addSectionFilterToDemux();
- ::testing::AssertionResult addPesFilterToDemux();
- ::testing::AssertionResult getFilterMQDescriptor(sp<IDemux>& demux, const uint32_t filterId);
- ::testing::AssertionResult readSectionFilterDataOutput();
- ::testing::AssertionResult readPesFilterDataOutput();
+ ::testing::AssertionResult addFilterToDemux(DemuxFilterType type, DemuxFilterSettings setting);
+ ::testing::AssertionResult getFilterMQDescriptor(const uint32_t filterId);
::testing::AssertionResult closeDemux();
::testing::AssertionResult createDescrambler();
::testing::AssertionResult closeDescrambler();
+
+ ::testing::AssertionResult readSectionFilterDataOutput();
+ ::testing::AssertionResult playbackDataFlowTest(vector<FilterConf> filterConf,
+ InputConf inputConf, string goldenOutput);
};
::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) {
@@ -405,7 +518,7 @@
::testing::AssertionResult TunerHidlTest::stopTuneFrontend(int32_t frontendId) {
Result status;
- if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
@@ -415,11 +528,12 @@
::testing::AssertionResult TunerHidlTest::closeFrontend(int32_t frontendId) {
Result status;
- if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
status = mFrontend->close();
+ mFrontend = nullptr;
return ::testing::AssertionResult(status == Result::SUCCESS);
}
@@ -437,11 +551,11 @@
::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId) {
Result status;
- if (createDemux() == ::testing::AssertionFailure()) {
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
- if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
@@ -450,111 +564,14 @@
return ::testing::AssertionResult(status == Result::SUCCESS);
}
-::testing::AssertionResult TunerHidlTest::addSectionFilterToDemux() {
- Result status;
-
- if (createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Create demux callback
- mDemuxCallback = new DemuxCallback();
-
- // Add section filter to the local demux
- mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback,
- [&](Result result, uint32_t filterId) {
- mFilterId = filterId;
- status = result;
- });
-
- // Add another section filter to the local demux
- mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback,
- [&](Result result, uint32_t filterId) {
- mFilterId = filterId;
- status = result;
- });
-
- // TODO Test configure the filter
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::addPesFilterToDemux() {
- Result status;
-
- if (createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Create demux callback
- mDemuxCallback = new DemuxCallback();
-
- // Add PES filter to the local demux
- mDemux->addFilter(DemuxFilterType::PES, FMQ_SIZE_4K, mDemuxCallback,
- [&](Result result, uint32_t filterId) {
- mFilterId = filterId;
- status = result;
- });
-
- // Add another PES filter to the local demux
- mDemux->addFilter(DemuxFilterType::PES, FMQ_SIZE_4K, mDemuxCallback,
- [&](Result result, uint32_t filterId) {
- mFilterId = filterId;
- status = result;
- });
-
- // TODO Test configure the filter
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor(sp<IDemux>& demux,
- const uint32_t filterId) {
- Result status;
-
- if (!demux) {
- return ::testing::AssertionFailure();
- }
-
- mDemux->getFilterQueueDesc(filterId, [&](Result result, const FilterMQDesc& filterMQDesc) {
- mFilterMQDescriptor = filterMQDesc;
- status = result;
- });
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
-::testing::AssertionResult TunerHidlTest::readSectionFilterDataOutput() {
- if (addSectionFilterToDemux() == ::testing::AssertionFailure() ||
- getFilterMQDescriptor(mDemux, mFilterId) == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Test start filter and read the output data
- mDemuxCallback->testOnSectionFilterEvent(mDemux, mFilterId, mFilterMQDescriptor);
-
- return ::testing::AssertionResult(true);
-}
-
-::testing::AssertionResult TunerHidlTest::readPesFilterDataOutput() {
- if (addPesFilterToDemux() == ::testing::AssertionFailure() ||
- getFilterMQDescriptor(mDemux, mFilterId) == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Test start filter and read the output data
- mDemuxCallback->testOnPesFilterEvent(mDemux, mFilterId, mFilterMQDescriptor);
-
- return ::testing::AssertionResult(true);
-}
-
::testing::AssertionResult TunerHidlTest::closeDemux() {
Result status;
- if (createDemux() == ::testing::AssertionFailure()) {
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
status = mDemux->close();
+ mDemux = nullptr;
return ::testing::AssertionResult(status == Result::SUCCESS);
}
@@ -569,7 +586,7 @@
return ::testing::AssertionFailure();
}
- if (createDemux() == ::testing::AssertionFailure()) {
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
@@ -585,14 +602,185 @@
::testing::AssertionResult TunerHidlTest::closeDescrambler() {
Result status;
- if (createDescrambler() == ::testing::AssertionFailure()) {
+ if (!mDescrambler && createDescrambler() == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
status = mDescrambler->close();
+ mDescrambler = nullptr;
return ::testing::AssertionResult(status == Result::SUCCESS);
}
+::testing::AssertionResult TunerHidlTest::addInputToDemux(DemuxInputSettings setting) {
+ Result status;
+
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Create demux callback
+ if (!mDemuxCallback) {
+ mDemuxCallback = new DemuxCallback();
+ }
+
+ // Add section filter to the local demux
+ status = mDemux->addInput(FMQ_SIZE_1M, mDemuxCallback);
+
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mDemux->configureInput(setting);
+
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::getInputMQDescriptor() {
+ Result status;
+
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ mDemux->getInputQueueDesc([&](Result result, const MQDesc& inputMQDesc) {
+ mInputMQDescriptor = inputMQDesc;
+ status = result;
+ });
+
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::addSectionFilterToDemux() {
+ Result status;
+
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Create demux callback
+ if (!mDemuxCallback) {
+ mDemuxCallback = new DemuxCallback();
+ }
+
+ // Add section filter to the local demux
+ mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback,
+ [&](Result result, uint32_t filterId) {
+ mFilterId = filterId;
+ status = result;
+ });
+
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::addFilterToDemux(DemuxFilterType type,
+ DemuxFilterSettings setting) {
+ Result status;
+
+ if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Create demux callback
+ if (!mDemuxCallback) {
+ mDemuxCallback = new DemuxCallback();
+ }
+
+ // Add filter to the local demux
+ mDemux->addFilter(type, FMQ_SIZE_4K, mDemuxCallback, [&](Result result, uint32_t filterId) {
+ // TODO use a map to save all the filter id and FMQ
+ mFilterId = filterId;
+ status = result;
+ });
+
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Configure the filter
+ status = mDemux->configureFilter(mFilterId, setting);
+
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor(const uint32_t filterId) {
+ Result status;
+
+ if (!mDemux) {
+ return ::testing::AssertionFailure();
+ }
+
+ mDemux->getFilterQueueDesc(filterId, [&](Result result, const MQDesc& filterMQDesc) {
+ mFilterMQDescriptor = filterMQDesc;
+ status = result;
+ });
+
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::readSectionFilterDataOutput() {
+ // Filter Configuration Module
+ DemuxInputSettings setting{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x100000,
+ .dataFormat = DemuxDataFormat::TS,
+ .packetSize = 188,
+ };
+ if (addSectionFilterToDemux() == ::testing::AssertionFailure() ||
+ getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure() ||
+ addInputToDemux(setting) == ::testing::AssertionFailure() ||
+ getInputMQDescriptor() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Data Verify Module
+ // Test start filter and read the output data
+ mDemuxCallback->testOnSectionFilterEvent(mDemux, mFilterId, mFilterMQDescriptor,
+ mInputMQDescriptor);
+
+ // Clean Up Module
+ return closeDemux(); //::testing::AssertionSuccess();
+}
+
+::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(vector<FilterConf> filterConf,
+ InputConf inputConf,
+ string /*goldenOutput*/) {
+ Result status;
+ // Filter Configuration Module
+ for (int i = 0; i < filterConf.size(); i++) {
+ if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
+ ::testing::AssertionFailure() ||
+ // TODO use a map to save the FMQs/EvenFlags and pass to callback
+ getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+ }
+
+ // Playback Input Module
+ DemuxInputSettings inputSetting = inputConf.setting;
+ if (addInputToDemux(inputSetting) == ::testing::AssertionFailure() ||
+ getInputMQDescriptor() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+ mDemuxCallback->startPlaybackInputThread(inputConf, mInputMQDescriptor);
+ status = mDemux->startInput();
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Data Verify Module
+ // golden output, created FMQ to read and EventFlags to DATA_CONSUMED
+ // Maintain each filter's real output (and how to assemble?????)
+ // mDemuxCallback->testPlaybackDataFlow();
+
+ // Clean Up Module
+ // TODO what about remove input, remove filters
+ return closeDemux();
+}
+
+/*
+ * API STATUS TESTS
+ */
TEST_F(TunerHidlTest, CreateFrontend) {
Result status;
hidl_vec<FrontendId> feIds;
@@ -673,12 +861,6 @@
}
}
-TEST_F(TunerHidlTest, CreateDemux) {
- description("Create Demux");
-
- ASSERT_TRUE(createDemux());
-}
-
TEST_F(TunerHidlTest, CreateDemuxWithFrontend) {
Result status;
hidl_vec<FrontendId> feIds;
@@ -699,50 +881,34 @@
}
}
-TEST_F(TunerHidlTest, AddSectionFilterToDemux) {
- description("Add a section filter to a created demux");
- ASSERT_TRUE(addSectionFilterToDemux());
-}
-
-TEST_F(TunerHidlTest, AddPesFilterToDemux) {
- description("Add a pes filter to a created demux");
- ASSERT_TRUE(addPesFilterToDemux());
-}
-
-TEST_F(TunerHidlTest, GetFilterMQDescriptor) {
- description("Get MQ Descriptor from a created filter");
- ASSERT_TRUE(addSectionFilterToDemux());
- ASSERT_TRUE(getFilterMQDescriptor(mDemux, mFilterId));
-}
-
-TEST_F(TunerHidlTest, ReadSectionFilterOutput) {
- description("Read data output from FMQ of a Section Filter");
- ASSERT_TRUE(readSectionFilterDataOutput());
-}
-
-TEST_F(TunerHidlTest, ReadPesFilterOutput) {
- description("Read data output from FMQ of a PES Filter");
- ASSERT_TRUE(readPesFilterDataOutput());
+TEST_F(TunerHidlTest, CreateDemux) {
+ description("Create Demux");
+ ASSERT_TRUE(createDemux());
}
TEST_F(TunerHidlTest, CloseDemux) {
description("Close Demux");
-
ASSERT_TRUE(closeDemux());
}
TEST_F(TunerHidlTest, CreateDescrambler) {
description("Create Descrambler");
-
ASSERT_TRUE(createDescrambler());
}
TEST_F(TunerHidlTest, CloseDescrambler) {
description("Close Descrambler");
-
ASSERT_TRUE(closeDescrambler());
}
+/*
+ * DATA FLOW TESTS
+ */
+TEST_F(TunerHidlTest, ReadSectionFilterOutput) {
+ description("Read data output from FMQ of a Section Filter");
+ ASSERT_TRUE(readSectionFilterDataOutput());
+}
+
} // namespace
int main(int argc, char** argv) {