Merge "Make dvr tests a separate module" into rvc-dev am: d8040b86f7 am: 469196a204 am: 38f5760b30 am: f6d560ad52

Change-Id: Iaf7e76e422e9960e9ed934125594f8fc6df43856
This commit is contained in:
Amy Zhang
2020-04-25 02:02:29 +00:00
committed by Automerger Merge Worker
13 changed files with 674 additions and 392 deletions

View File

@@ -52,7 +52,7 @@ Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
return startFrontendInputLoop();
return Result::SUCCESS;
}
Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
@@ -60,7 +60,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
ALOGV("%s", __FUNCTION__);
uint32_t filterId;
if (!mUnusedFilterIds.empty()) {
filterId = *mUnusedFilterIds.begin();
@@ -83,7 +82,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
_hidl_cb(Result::UNKNOWN_ERROR, filter);
return Void();
}
mFilters[filterId] = filter;
_hidl_cb(Result::SUCCESS, filter);
@@ -234,11 +232,9 @@ uint16_t Demux::getFilterTpid(uint32_t filterId) {
return mFilters[filterId]->getTpid();
}
Result Demux::startFrontendInputLoop() {
void Demux::startFrontendInputLoop() {
pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
return Result::SUCCESS;
}
void* Demux::__threadLoopFrontend(void* user) {

View File

@@ -89,6 +89,7 @@ class Demux : public IDemux {
void updateFilterOutput(uint16_t filterId, vector<uint8_t> data);
uint16_t getFilterTpid(uint32_t filterId);
void setIsRecording(bool isRecording);
void startFrontendInputLoop();
private:
// Tuner service
@@ -104,7 +105,6 @@ class Demux : public IDemux {
uint32_t filterId;
};
Result startFrontendInputLoop();
static void* __threadLoopFrontend(void* user);
void frontendInputThreadLoop();

View File

@@ -64,6 +64,7 @@ Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
return Result::INVALID_STATE;
}
mTunerService->frontendStartTune(mId);
mCallback->onEvent(FrontendEventType::LOCKED);
mIsLocked = false;
return Result::SUCCESS;

View File

@@ -247,6 +247,15 @@ void Tuner::frontendStopTune(uint32_t frontendId) {
}
}
void Tuner::frontendStartTune(uint32_t frontendId) {
map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId);
uint32_t demuxId;
if (it != mFrontendToDemux.end()) {
demuxId = it->second;
mDemuxes[demuxId]->startFrontendInputLoop();
}
}
} // namespace implementation
} // namespace V1_0
} // namespace tuner

View File

@@ -63,6 +63,7 @@ class Tuner : public ITuner {
void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
void frontendStartTune(uint32_t frontendId);
void frontendStopTune(uint32_t frontendId);
private:

View File

@@ -22,6 +22,7 @@ cc_test {
"FrontendTests.cpp",
"DemuxTests.cpp",
"FilterTests.cpp",
"DvrTests.cpp",
],
static_libs: [
"android.hardware.tv.tuner@1.0",

View File

@@ -38,8 +38,6 @@ using ::testing::AssertionResult;
class DemuxTests {
public:
sp<ITuner> mService;
void setService(sp<ITuner> tuner) { mService = tuner; }
AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
@@ -51,5 +49,6 @@ class DemuxTests {
static AssertionResult success() { return ::testing::AssertionSuccess(); }
sp<ITuner> mService;
sp<IDemux> mDemux;
};

View File

@@ -0,0 +1,267 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DvrTests.h"
void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
MQDesc& playbackMQDescriptor) {
mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
EXPECT_TRUE(mPlaybackMQ);
struct PlaybackThreadArgs* threadArgs =
(struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs));
threadArgs->user = this;
threadArgs->playbackConf = &playbackConf;
threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ;
pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs);
pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
}
void DvrCallback::stopPlaybackThread() {
mPlaybackThreadRunning = false;
mKeepWritingPlaybackFMQ = false;
android::Mutex::Autolock autoLock(mPlaybackThreadLock);
}
void* DvrCallback::__threadLoopPlayback(void* threadArgs) {
DvrCallback* const self =
static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user);
self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf,
((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ);
return 0;
}
void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) {
android::Mutex::Autolock autoLock(mPlaybackThreadLock);
mPlaybackThreadRunning = true;
// Create the EventFlag that is used to signal the HAL impl that data have been
// written into the Playback FMQ
EventFlag* playbackMQEventFlag;
EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
android::OK);
// open the stream and get its length
std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary);
int writeSize = playbackConf->setting.packetSize * 6;
char* buffer = new char[writeSize];
ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str());
if (!inputData.is_open()) {
mPlaybackThreadRunning = false;
ALOGW("[vts] Error %s", strerror(errno));
}
while (mPlaybackThreadRunning) {
// move the stream pointer for packet size * 6 every read until the end
while (*keepWritingPlaybackFMQ) {
inputData.read(buffer, writeSize);
if (!inputData) {
int leftSize = inputData.gcount();
if (leftSize == 0) {
mPlaybackThreadRunning = false;
break;
}
inputData.clear();
inputData.read(buffer, leftSize);
// Write the left over of the input data and quit the thread
if (leftSize > 0) {
EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
playbackMQEventFlag->wake(
static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
}
mPlaybackThreadRunning = false;
break;
}
// Write input FMQ and notify the Tuner Implementation
EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
inputData.seekg(writeSize, inputData.cur);
sleep(1);
}
}
ALOGW("[vts] Playback thread end.");
delete[] buffer;
inputData.close();
}
void DvrCallback::testRecordOutput() {
android::Mutex::Autolock autoLock(mMsgLock);
while (mDataOutputBuffer.empty()) {
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
return;
}
}
stopRecordThread();
ALOGW("[vts] record pass and stop");
}
void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
MQDesc& recordMQDescriptor) {
mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
EXPECT_TRUE(mRecordMQ);
struct RecordThreadArgs* threadArgs =
(struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
threadArgs->user = this;
threadArgs->recordSettings = &recordSettings;
threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
pthread_setname_np(mRecordThread, "test_record_input_loop");
}
void* DvrCallback::__threadLoopRecord(void* threadArgs) {
DvrCallback* const self =
static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
return 0;
}
void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
ALOGD("[vts] DvrCallback record threadLoop start.");
android::Mutex::Autolock autoLock(mRecordThreadLock);
mRecordThreadRunning = true;
// Create the EventFlag that is used to signal the HAL impl that data have been
// read from the Record FMQ
EventFlag* recordMQEventFlag;
EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
android::OK);
while (mRecordThreadRunning) {
while (*keepReadingRecordFMQ) {
uint32_t efState = 0;
android::status_t status = recordMQEventFlag->wait(
static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
true /* retry on spurious wake */);
if (status != android::OK) {
ALOGD("[vts] wait for data ready on the record FMQ");
continue;
}
// Our current implementation filter the data and write it into the filter FMQ
// immediately after the DATA_READY from the VTS/framework
if (!readRecordFMQ()) {
ALOGD("[vts] record data failed to be filtered. Ending thread");
mRecordThreadRunning = false;
break;
}
}
}
mRecordThreadRunning = false;
ALOGD("[vts] record thread ended.");
}
bool DvrCallback::readRecordFMQ() {
android::Mutex::Autolock autoLock(mMsgLock);
bool result = false;
mDataOutputBuffer.clear();
mDataOutputBuffer.resize(mRecordMQ->availableToRead());
result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
EXPECT_TRUE(result) << "can't read from Record MQ";
mMsgCondition.signal();
return result;
}
void DvrCallback::stopRecordThread() {
mKeepReadingRecordFMQ = false;
mRecordThreadRunning = false;
android::Mutex::Autolock autoLock(mRecordThreadLock);
}
AssertionResult DvrTests::openDvrInDemux(DvrType type) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
// Create dvr callback
mDvrCallback = new DvrCallback();
mDemux->openDvr(type, FMQ_SIZE_1M, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
mDvr = dvr;
status = result;
});
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult DvrTests::configDvr(DvrSettings setting) {
Result status = mDvr->configure(setting);
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult DvrTests::getDvrMQDescriptor() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
mDvrMQDescriptor = dvrMQDesc;
status = result;
});
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
status = mDvr->attachFilter(filter);
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
status = mDvr->detachFilter(filter);
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult DvrTests::startDvr() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
status = mDvr->start();
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult DvrTests::stopDvr() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
status = mDvr->stop();
return AssertionResult(status == Result::SUCCESS);
}
void DvrTests::closeDvr() {
ASSERT_TRUE(mDemux);
ASSERT_TRUE(mDvr);
ASSERT_TRUE(mDvr->close() == Result::SUCCESS);
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/tv/tuner/1.0/IDvr.h>
#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <android/hardware/tv/tuner/1.0/types.h>
#include <fmq/MessageQueue.h>
#include <hidl/Status.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <fstream>
#include <iostream>
#include <map>
#include "FilterTests.h"
using android::Condition;
using android::Mutex;
using android::sp;
using android::hardware::EventFlag;
using android::hardware::kSynchronizedReadWrite;
using android::hardware::MessageQueue;
using android::hardware::MQDescriptorSync;
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using android::hardware::tv::tuner::V1_0::DvrSettings;
using android::hardware::tv::tuner::V1_0::DvrType;
using android::hardware::tv::tuner::V1_0::IDvr;
using android::hardware::tv::tuner::V1_0::IDvrCallback;
using android::hardware::tv::tuner::V1_0::ITuner;
using android::hardware::tv::tuner::V1_0::PlaybackSettings;
using android::hardware::tv::tuner::V1_0::PlaybackStatus;
using android::hardware::tv::tuner::V1_0::RecordSettings;
using android::hardware::tv::tuner::V1_0::RecordStatus;
using android::hardware::tv::tuner::V1_0::Result;
#define WAIT_TIMEOUT 3000000000
struct PlaybackConf {
string inputDataFile;
PlaybackSettings setting;
};
class DvrCallback : public IDvrCallback {
public:
virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
ALOGW("[vts] record status %hhu", status);
switch (status) {
case DemuxFilterStatus::DATA_READY:
break;
case DemuxFilterStatus::LOW_WATER:
break;
case DemuxFilterStatus::HIGH_WATER:
case DemuxFilterStatus::OVERFLOW:
ALOGW("[vts] record overflow. Flushing");
break;
}
return Void();
}
virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
// android::Mutex::Autolock autoLock(mMsgLock);
ALOGW("[vts] playback status %d", status);
switch (status) {
case PlaybackStatus::SPACE_EMPTY:
case PlaybackStatus::SPACE_ALMOST_EMPTY:
ALOGW("[vts] keep playback inputing %d", status);
mKeepWritingPlaybackFMQ = true;
break;
case PlaybackStatus::SPACE_ALMOST_FULL:
case PlaybackStatus::SPACE_FULL:
ALOGW("[vts] stop playback inputing %d", status);
mKeepWritingPlaybackFMQ = false;
break;
}
return Void();
}
void stopPlaybackThread();
void testRecordOutput();
void stopRecordThread();
void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor);
void startRecordOutputThread(RecordSettings recordSettings, MQDesc& recordMQDescriptor);
static void* __threadLoopPlayback(void* threadArgs);
static void* __threadLoopRecord(void* threadArgs);
void playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ);
void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
bool readRecordFMQ();
private:
struct PlaybackThreadArgs {
DvrCallback* user;
PlaybackConf* playbackConf;
bool* keepWritingPlaybackFMQ;
};
struct RecordThreadArgs {
DvrCallback* user;
RecordSettings* recordSettings;
bool* keepReadingRecordFMQ;
};
// uint16_t mDataLength = 0;
std::vector<uint8_t> mDataOutputBuffer;
std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
std::unique_ptr<FilterMQ> mPlaybackMQ;
std::unique_ptr<FilterMQ> mRecordMQ;
std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
android::Mutex mMsgLock;
android::Mutex mPlaybackThreadLock;
android::Mutex mRecordThreadLock;
android::Condition mMsgCondition;
bool mKeepWritingPlaybackFMQ = true;
bool mKeepReadingRecordFMQ = true;
bool mPlaybackThreadRunning;
bool mRecordThreadRunning;
pthread_t mPlaybackThread;
pthread_t mRecordThread;
// int mPidFilterOutputCount = 0;
};
class DvrTests {
public:
void setService(sp<ITuner> tuner) { mService = tuner; }
void setDemux(sp<IDemux> demux) { mDemux = demux; }
void startPlaybackInputThread(string dataInputFile, PlaybackSettings settings) {
PlaybackConf conf{
.inputDataFile = dataInputFile,
.setting = settings,
};
mDvrCallback->startPlaybackInputThread(conf, mDvrMQDescriptor);
};
void startRecordOutputThread(RecordSettings settings) {
mDvrCallback->startRecordOutputThread(settings, mDvrMQDescriptor);
};
void stopPlaybackThread() { mDvrCallback->stopPlaybackThread(); }
void testRecordOutput() { mDvrCallback->testRecordOutput(); }
void stopRecordThread() { mDvrCallback->stopPlaybackThread(); }
AssertionResult openDvrInDemux(DvrType type);
AssertionResult configDvr(DvrSettings setting);
AssertionResult getDvrMQDescriptor();
AssertionResult attachFilterToDvr(sp<IFilter> filter);
AssertionResult detachFilterToDvr(sp<IFilter> filter);
AssertionResult stopDvr();
AssertionResult startDvr();
void closeDvr();
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
static AssertionResult success() { return ::testing::AssertionSuccess(); }
sp<ITuner> mService;
sp<IDvr> mDvr;
sp<IDemux> mDemux;
sp<DvrCallback> mDvrCallback;
MQDesc mDvrMQDescriptor;
pthread_t mPlaybackshread;
bool mPlaybackThreadRunning;
};

View File

@@ -149,6 +149,7 @@ class FilterTests {
public:
void setService(sp<ITuner> tuner) { mService = tuner; }
void setDemux(sp<IDemux> demux) { mDemux = demux; }
sp<IFilter> getFilterById(uint32_t filterId) { return mFilters[filterId]; }
std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }

View File

@@ -17,181 +17,8 @@
#include "VtsHalTvTunerV1_0TargetTest.h"
namespace {
/******************************** Start DvrCallback **********************************/
void DvrCallback::startPlaybackInputThread(PlaybackConf playbackConf,
MQDesc& playbackMQDescriptor) {
mPlaybackMQ = std::make_unique<FilterMQ>(playbackMQDescriptor, true /* resetPointers */);
EXPECT_TRUE(mPlaybackMQ);
struct PlaybackThreadArgs* threadArgs =
(struct PlaybackThreadArgs*)malloc(sizeof(struct PlaybackThreadArgs));
threadArgs->user = this;
threadArgs->playbackConf = &playbackConf;
threadArgs->keepWritingPlaybackFMQ = &mKeepWritingPlaybackFMQ;
pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, (void*)threadArgs);
pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
}
void DvrCallback::stopPlaybackThread() {
mPlaybackThreadRunning = false;
mKeepWritingPlaybackFMQ = false;
android::Mutex::Autolock autoLock(mPlaybackThreadLock);
}
void* DvrCallback::__threadLoopPlayback(void* threadArgs) {
DvrCallback* const self =
static_cast<DvrCallback*>(((struct PlaybackThreadArgs*)threadArgs)->user);
self->playbackThreadLoop(((struct PlaybackThreadArgs*)threadArgs)->playbackConf,
((struct PlaybackThreadArgs*)threadArgs)->keepWritingPlaybackFMQ);
return 0;
}
void DvrCallback::playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ) {
android::Mutex::Autolock autoLock(mPlaybackThreadLock);
mPlaybackThreadRunning = true;
// Create the EventFlag that is used to signal the HAL impl that data have been
// written into the Playback FMQ
EventFlag* playbackMQEventFlag;
EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
android::OK);
// open the stream and get its length
std::ifstream inputData(playbackConf->inputDataFile, std::ifstream::binary);
int writeSize = playbackConf->setting.packetSize * 6;
char* buffer = new char[writeSize];
ALOGW("[vts] playback thread loop start %s", playbackConf->inputDataFile.c_str());
if (!inputData.is_open()) {
mPlaybackThreadRunning = false;
ALOGW("[vts] Error %s", strerror(errno));
}
while (mPlaybackThreadRunning) {
// move the stream pointer for packet size * 6 every read until the end
while (*keepWritingPlaybackFMQ) {
inputData.read(buffer, writeSize);
if (!inputData) {
int leftSize = inputData.gcount();
if (leftSize == 0) {
mPlaybackThreadRunning = false;
break;
}
inputData.clear();
inputData.read(buffer, leftSize);
// Write the left over of the input data and quit the thread
if (leftSize > 0) {
EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
playbackMQEventFlag->wake(
static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
}
mPlaybackThreadRunning = false;
break;
}
// Write input FMQ and notify the Tuner Implementation
EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
inputData.seekg(writeSize, inputData.cur);
sleep(1);
}
}
ALOGW("[vts] Playback thread end.");
delete[] buffer;
inputData.close();
}
void DvrCallback::testRecordOutput() {
android::Mutex::Autolock autoLock(mMsgLock);
while (mDataOutputBuffer.empty()) {
if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
EXPECT_TRUE(false) << "record output matching pid does not output within timeout";
return;
}
}
stopRecordThread();
ALOGW("[vts] record pass and stop");
}
void DvrCallback::startRecordOutputThread(RecordSettings recordSetting,
MQDesc& recordMQDescriptor) {
mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
EXPECT_TRUE(mRecordMQ);
struct RecordThreadArgs* threadArgs =
(struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
threadArgs->user = this;
threadArgs->recordSetting = &recordSetting;
threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
pthread_setname_np(mRecordThread, "test_record_input_loop");
}
void* DvrCallback::__threadLoopRecord(void* threadArgs) {
DvrCallback* const self =
static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSetting,
((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
return 0;
}
void DvrCallback::recordThreadLoop(RecordSettings* /*recordSetting*/, bool* keepReadingRecordFMQ) {
ALOGD("[vts] DvrCallback record threadLoop start.");
android::Mutex::Autolock autoLock(mRecordThreadLock);
mRecordThreadRunning = true;
// Create the EventFlag that is used to signal the HAL impl that data have been
// read from the Record FMQ
EventFlag* recordMQEventFlag;
EXPECT_TRUE(EventFlag::createEventFlag(mRecordMQ->getEventFlagWord(), &recordMQEventFlag) ==
android::OK);
while (mRecordThreadRunning) {
while (*keepReadingRecordFMQ) {
uint32_t efState = 0;
android::status_t status = recordMQEventFlag->wait(
static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
true /* retry on spurious wake */);
if (status != android::OK) {
ALOGD("[vts] wait for data ready on the record FMQ");
continue;
}
// Our current implementation filter the data and write it into the filter FMQ
// immediately after the DATA_READY from the VTS/framework
if (!readRecordFMQ()) {
ALOGD("[vts] record data failed to be filtered. Ending thread");
mRecordThreadRunning = false;
break;
}
}
}
mRecordThreadRunning = false;
ALOGD("[vts] record thread ended.");
}
bool DvrCallback::readRecordFMQ() {
android::Mutex::Autolock autoLock(mMsgLock);
bool result = false;
mDataOutputBuffer.clear();
mDataOutputBuffer.resize(mRecordMQ->availableToRead());
result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
EXPECT_TRUE(result) << "can't read from Record MQ";
mMsgCondition.signal();
return result;
}
void DvrCallback::stopRecordThread() {
mKeepReadingRecordFMQ = false;
mRecordThreadRunning = false;
android::Mutex::Autolock autoLock(mRecordThreadLock);
}
/********************************** End DvrCallback ************************************/
/*======================== Start Descrambler APIs Tests Implementation ========================*/
AssertionResult TunerHidlTest::createDescrambler() {
AssertionResult TunerHidlTest::createDescrambler(uint32_t demuxId) {
Result status;
mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
mDescrambler = descrambler;
@@ -201,21 +28,19 @@ AssertionResult TunerHidlTest::createDescrambler() {
return failure();
}
status = mDescrambler->setDemuxSource(mDemuxId);
status = mDescrambler->setDemuxSource(demuxId);
if (status != Result::SUCCESS) {
return failure();
}
// Test if demux source can be set more than once.
status = mDescrambler->setDemuxSource(mDemuxId);
status = mDescrambler->setDemuxSource(demuxId);
return AssertionResult(status == Result::INVALID_STATE);
}
AssertionResult TunerHidlTest::closeDescrambler() {
Result status;
if (!mDescrambler && createDescrambler() == failure()) {
return failure();
}
EXPECT_TRUE(mDescrambler);
status = mDescrambler->close();
mDescrambler = nullptr;
@@ -223,40 +48,6 @@ AssertionResult TunerHidlTest::closeDescrambler() {
}
/*========================= End Descrambler APIs Tests Implementation =========================*/
/*============================ Start Dvr APIs Tests Implementation ============================*/
AssertionResult TunerHidlTest::openDvrInDemux(DvrType type) {
Result status;
// Create dvr callback
mDvrCallback = new DvrCallback();
mDemux->openDvr(type, FMQ_SIZE_1M, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
mDvr = dvr;
status = result;
});
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult TunerHidlTest::configDvr(DvrSettings setting) {
Result status = mDvr->configure(setting);
return AssertionResult(status == Result::SUCCESS);
}
AssertionResult TunerHidlTest::getDvrMQDescriptor() {
Result status;
EXPECT_TRUE(mDvr) << "Test with openDvr first.";
mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
mDvrMQDescriptor = dvrMQDesc;
status = result;
});
return AssertionResult(status == Result::SUCCESS);
}
/*============================ End Dvr APIs Tests Implementation ============================*/
/*========================== Start Data Flow Tests Implementation ==========================*/
AssertionResult TunerHidlTest::broadcastDataFlowTest(vector<string> /*goldenOutputFiles*/) {
// Data Verify Module
@@ -417,6 +208,10 @@ AssertionResult TunerHidlTest::recordDataFlowTest(vector<FilterConf> filterConf,
void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
uint32_t filterId;
mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
if (feId == INVALID_ID) {
// TODO broadcast test on Cuttlefish needs licensed ts input,
@@ -426,13 +221,12 @@ void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
}
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId));
mFilterTests.setDemux(mDemux);
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type));
uint32_t filterId;
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.setting, filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
@@ -445,6 +239,67 @@ void TunerHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
void TunerDvrHidlTest::attachSingleFilterToDvrTest(FilterConfig filterConf,
FrontendConfig frontendConf, DvrConfig dvrConf) {
description("Open and configure a Dvr in Demux.");
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
uint32_t filterId;
sp<IFilter> filter;
mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type));
ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
filter = mFilterTests.getFilterById(filterId);
ASSERT_TRUE(filter != nullptr);
ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
mDvrTests.closeDvr();
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
uint32_t filterId;
mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
/*================================== End Test Module ==================================*/
/***************************** End Test Implementation *****************************/
@@ -467,50 +322,56 @@ TEST_P(TunerFrontendHidlTest, BlindScanFrontend) {
TEST_P(TunerDemuxHidlTest, openDemux) {
description("Open and close a Demux.");
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId));
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
ASSERT_TRUE(mDemuxTests.closeDemux());
}
TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
description("Open and start a filter in Demux.");
uint32_t feId;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(mDemux, mDemuxId));
mFilterTests.setDemux(mDemux);
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO0].type));
uint32_t filterId;
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO0].setting, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
// TODO use paramterized tests
configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
}
TEST_P(TunerDvrHidlTest, AttachFiltersToRecordTest) {
description("Attach a single filter to the record dvr test.");
// TODO use paramterized tests
attachSingleFilterToDvrTest(filterArray[TS_VIDEO0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
}
TEST_P(TunerDvrHidlTest, AttachFiltersToPlaybackTest) {
description("Attach a single filter to the playback dvr test.");
// TODO use paramterized tests
attachSingleFilterToDvrTest(filterArray[TS_VIDEO0], frontendArray[DVBT],
dvrArray[DVR_PLAYBACK0]);
}
/*============================ Start Descrambler Tests ============================*/
/*
* TODO: re-enable the tests after finalizing the test refactoring.
*/
/*TEST_P(TunerHidlTest, CreateDescrambler) {
TEST_P(TunerHidlTest, CreateDescrambler) {
description("Create Descrambler");
ASSERT_TRUE(createDescrambler());
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
ASSERT_TRUE(createDescrambler(demuxId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(closeDescrambler());
}
TEST_P(TunerHidlTest, CloseDescrambler) {
description("Close Descrambler");
ASSERT_TRUE(closeDescrambler());
}*/
/*============================== End Descrambler Tests ==============================*/
/*============================== Start Data Flow Tests ==============================*/
@@ -642,4 +503,9 @@ INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerFilterHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerDvrHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
} // namespace

View File

@@ -15,30 +15,13 @@
*/
#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
#include <android/hardware/tv/tuner/1.0/IDvr.h>
#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
#include <fstream>
#include <iostream>
#include "DemuxTests.h"
#include "FilterTests.h"
#include "DvrTests.h"
#include "FrontendTests.h"
using android::hardware::tv::tuner::V1_0::DataFormat;
using android::hardware::tv::tuner::V1_0::DvrSettings;
using android::hardware::tv::tuner::V1_0::DvrType;
using android::hardware::tv::tuner::V1_0::IDescrambler;
using android::hardware::tv::tuner::V1_0::IDvr;
using android::hardware::tv::tuner::V1_0::IDvrCallback;
using android::hardware::tv::tuner::V1_0::PlaybackSettings;
using android::hardware::tv::tuner::V1_0::PlaybackStatus;
using android::hardware::tv::tuner::V1_0::RecordSettings;
using android::hardware::tv::tuner::V1_0::RecordStatus;
struct PlaybackConf {
string inputDataFile;
PlaybackSettings setting;
};
static AssertionResult failure() {
return ::testing::AssertionFailure();
@@ -50,89 +33,6 @@ static AssertionResult success() {
namespace {
class DvrCallback : public IDvrCallback {
public:
virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
ALOGW("[vts] record status %hhu", status);
switch (status) {
case DemuxFilterStatus::DATA_READY:
break;
case DemuxFilterStatus::LOW_WATER:
break;
case DemuxFilterStatus::HIGH_WATER:
case DemuxFilterStatus::OVERFLOW:
ALOGW("[vts] record overflow. Flushing");
break;
}
return Void();
}
virtual Return<void> onPlaybackStatus(PlaybackStatus status) override {
// android::Mutex::Autolock autoLock(mMsgLock);
ALOGW("[vts] playback status %d", status);
switch (status) {
case PlaybackStatus::SPACE_EMPTY:
case PlaybackStatus::SPACE_ALMOST_EMPTY:
ALOGW("[vts] keep playback inputing %d", status);
mKeepWritingPlaybackFMQ = true;
break;
case PlaybackStatus::SPACE_ALMOST_FULL:
case PlaybackStatus::SPACE_FULL:
ALOGW("[vts] stop playback inputing %d", status);
mKeepWritingPlaybackFMQ = false;
break;
}
return Void();
}
void testFilterDataOutput();
void stopPlaybackThread();
void testRecordOutput();
void stopRecordThread();
void startPlaybackInputThread(PlaybackConf playbackConf, MQDesc& playbackMQDescriptor);
void startRecordOutputThread(RecordSettings recordSetting, MQDesc& recordMQDescriptor);
static void* __threadLoopPlayback(void* threadArgs);
static void* __threadLoopRecord(void* threadArgs);
void playbackThreadLoop(PlaybackConf* playbackConf, bool* keepWritingPlaybackFMQ);
void recordThreadLoop(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
bool readRecordFMQ();
private:
struct PlaybackThreadArgs {
DvrCallback* user;
PlaybackConf* playbackConf;
bool* keepWritingPlaybackFMQ;
};
struct RecordThreadArgs {
DvrCallback* user;
RecordSettings* recordSetting;
bool* keepReadingRecordFMQ;
};
uint16_t mDataLength = 0;
std::vector<uint8_t> mDataOutputBuffer;
std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterMQ;
std::unique_ptr<FilterMQ> mPlaybackMQ;
std::unique_ptr<FilterMQ> mRecordMQ;
std::map<uint32_t, EventFlag*> mFilterMQEventFlag;
android::Mutex mMsgLock;
android::Mutex mPlaybackThreadLock;
android::Mutex mRecordThreadLock;
android::Condition mMsgCondition;
bool mKeepWritingPlaybackFMQ = true;
bool mKeepReadingRecordFMQ = true;
bool mPlaybackThreadRunning;
bool mRecordThreadRunning;
pthread_t mPlaybackThread;
pthread_t mRecordThread;
int mPidFilterOutputCount = 0;
};
class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -174,8 +74,6 @@ class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
sp<IDemux> mDemux;
uint32_t mDemuxId;
};
class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
@@ -197,21 +95,47 @@ class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
RecordProperty("description", description);
}
void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
sp<IDemux> mDemux;
uint32_t mDemuxId;
};
class TunerDvrHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
mService = ITuner::getService(GetParam());
ASSERT_NE(mService, nullptr);
initFrontendConfig();
initFrontendScanConfig();
initFilterConfig();
initDvrConfig();
mFrontendTests.setService(mService);
mDemuxTests.setService(mService);
mFilterTests.setService(mService);
mDvrTests.setService(mService);
}
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
void attachSingleFilterToDvrTest(FilterConfig filterConf, FrontendConfig frontendConf,
DvrConfig dvrConf);
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
DvrTests mDvrTests;
};
class TunerHidlTest : public testing::TestWithParam<std::string> {
public:
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
virtual void SetUp() override {
mService = ITuner::getService(GetParam());
ASSERT_NE(mService, nullptr);
@@ -229,23 +153,14 @@ class TunerHidlTest : public testing::TestWithParam<std::string> {
RecordProperty("description", description);
}
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
sp<IDescrambler> mDescrambler;
sp<IDvr> mDvr;
sp<IDemux> mDemux;
uint32_t mDemuxId;
sp<DvrCallback> mDvrCallback;
MQDesc mDvrMQDescriptor;
MQDesc mRecordMQDescriptor;
pthread_t mPlaybackshread;
bool mPlaybackThreadRunning;
AssertionResult openDvrInDemux(DvrType type);
AssertionResult configDvr(DvrSettings setting);
AssertionResult getDvrMQDescriptor();
AssertionResult createDescrambler();
AssertionResult createDescrambler(uint32_t demuxId);
AssertionResult closeDescrambler();
AssertionResult playbackDataFlowTest(vector<FilterConfig> filterConf, PlaybackConf playbackConf,
@@ -257,4 +172,4 @@ class TunerHidlTest : public testing::TestWithParam<std::string> {
void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
};
} // namespace
} // namespace

View File

@@ -21,12 +21,15 @@
#include <hidl/Status.h>
#include <hidlmemory/FrameworkUtils.h>
using android::hardware::tv::tuner::V1_0::DataFormat;
using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterType;
using android::hardware::tv::tuner::V1_0::DemuxTpid;
using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using android::hardware::tv::tuner::V1_0::DvrSettings;
using android::hardware::tv::tuner::V1_0::DvrType;
using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
@@ -37,6 +40,8 @@ using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
using android::hardware::tv::tuner::V1_0::FrontendSettings;
using android::hardware::tv::tuner::V1_0::FrontendType;
using android::hardware::tv::tuner::V1_0::PlaybackSettings;
using android::hardware::tv::tuner::V1_0::RecordSettings;
using namespace std;
@@ -62,9 +67,15 @@ typedef enum {
SCAN_MAX,
} FrontendScan;
typedef enum {
DVR_RECORD0,
DVR_PLAYBACK0,
DVR_MAX,
} Dvr;
struct FilterConfig {
DemuxFilterType type;
DemuxFilterSettings setting;
DemuxFilterSettings settings;
};
struct FrontendConfig {
@@ -80,10 +91,16 @@ struct ChannelConfig {
DemuxTpid audioPid;
};
struct DvrConfig {
DvrType type;
DvrSettings settings;
};
static FrontendConfig frontendArray[FILTER_MAX];
static FrontendConfig frontendScanArray[SCAN_MAX];
static ChannelConfig channelArray[FRONTEND_MAX];
static FilterConfig filterArray[FILTER_MAX];
static DvrConfig dvrArray[DVR_MAX];
static vector<string> goldenOutputFiles;
/** Configuration array for the frontend tune test */
@@ -126,40 +143,62 @@ inline void initFilterConfig() {
// TS VIDEO filter setting for default implementation testing
filterArray[TS_VIDEO0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_VIDEO0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
filterArray[TS_VIDEO0].setting.ts().tpid = 119;
filterArray[TS_VIDEO0].setting.ts().filterSettings.av({.isPassthrough = false});
filterArray[TS_VIDEO0].settings.ts().tpid = 119;
filterArray[TS_VIDEO0].settings.ts().filterSettings.av({.isPassthrough = false});
filterArray[TS_VIDEO1].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_VIDEO1].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
filterArray[TS_VIDEO1].setting.ts().tpid = 81;
filterArray[TS_VIDEO1].setting.ts().filterSettings.av({.isPassthrough = false});
filterArray[TS_VIDEO1].settings.ts().tpid = 81;
filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false});
// TS AUDIO filter setting
filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
filterArray[TS_AUDIO0].setting.ts().tpid = 84;
filterArray[TS_AUDIO0].setting.ts().filterSettings.av({.isPassthrough = false});
filterArray[TS_AUDIO0].settings.ts().tpid = 84;
filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false});
// TS PES filter setting
filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
filterArray[TS_PES0].setting.ts().tpid = 256;
filterArray[TS_PES0].setting.ts().filterSettings.pesData({
filterArray[TS_PES0].settings.ts().tpid = 256;
filterArray[TS_PES0].settings.ts().filterSettings.pesData({
.isRaw = false,
.streamId = 0xbd,
});
// TS PCR filter setting
filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR);
filterArray[TS_PCR0].setting.ts().tpid = 81;
filterArray[TS_PCR0].setting.ts().filterSettings.noinit();
filterArray[TS_PCR0].settings.ts().tpid = 81;
filterArray[TS_PCR0].settings.ts().filterSettings.noinit();
// TS filter setting
filterArray[TS_TS0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_TS0].type.subType.tsFilterType(DemuxTsFilterType::TS);
filterArray[TS_TS0].setting.ts().tpid = 48;
filterArray[TS_TS0].setting.ts().filterSettings.noinit();
filterArray[TS_TS0].settings.ts().tpid = 48;
filterArray[TS_TS0].settings.ts().filterSettings.noinit();
// TS SECTION filter setting
filterArray[TS_SECTION0].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_SECTION0].type.subType.tsFilterType(DemuxTsFilterType::SECTION);
filterArray[TS_SECTION0].setting.ts().tpid = 48;
filterArray[TS_SECTION0].setting.ts().filterSettings.section({
filterArray[TS_SECTION0].settings.ts().tpid = 48;
filterArray[TS_SECTION0].settings.ts().filterSettings.section({
.isRaw = false,
});
};
/** Configuration array for the dvr test */
inline void initDvrConfig() {
RecordSettings recordSettings{
.statusMask = 0xf,
.lowThreshold = 0x1000,
.highThreshold = 0x07fff,
.dataFormat = DataFormat::TS,
.packetSize = 188,
};
dvrArray[DVR_RECORD0].type = DvrType::RECORD;
dvrArray[DVR_RECORD0].settings.record(recordSettings);
PlaybackSettings playbackSettings{
.statusMask = 0xf,
.lowThreshold = 0x1000,
.highThreshold = 0x07fff,
.dataFormat = DataFormat::TS,
.packetSize = 188,
};
dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
};