Implement ES data process in Tuner default impl to support Sample TIS

This CL also provides a new VTS case to test ES input stream.
Please see the test.es https://drive.google.com/file/d/13ZDT9uhEO1LXDT2GcOhB91iIK6m_KEER/view?usp=sharing

ES Format(all the numbers are in decimal):
1. First line is a general meta data to describe the whole file

m:meta data size in bytes, l:ES frame line count X, V:video raw data size
int bytes, A:audio raw data size in bytes, pv:video pid, pa:audio pid

2. The following X lines(equals to the ES frame line count) are the size/pts information
of the video or audio ES frames. Starting with v means video, a means
audio. They are printed in the same order as how they presented in the
original ts.

v, Len:current ES frame size in bytes, PTS: current ES frame PTS

3. After the X lines of ES frame descriptions, there are the video ES raw
data connected with the audio ES raw data.

Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 159027928
Change-Id: I56bd799fd6eda867df54d593235510a5e4758257
This commit is contained in:
Amy Zhang
2020-06-19 16:44:52 -07:00
parent c152a361c2
commit 85a9ab32d7
10 changed files with 292 additions and 70 deletions

View File

@@ -294,6 +294,11 @@ void Demux::updateFilterOutput(uint16_t filterId, vector<uint8_t> data) {
mFilters[filterId]->updateFilterOutput(data);
}
void Demux::updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts) {
updateFilterOutput(filterId, data);
mFilters[filterId]->updatePts(pts);
}
uint16_t Demux::getFilterTpid(uint32_t filterId) {
return mFilters[filterId]->getTpid();
}
@@ -322,6 +327,12 @@ void Demux::frontendInputThreadLoop() {
ALOGD("[Demux] wait for data ready on the playback FMQ");
continue;
}
if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) {
if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
break;
}
}
// Our current implementation filter the data and write it into the filter FMQ immediately
// after the DATA_READY from the VTS/framework
if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||

View File

@@ -87,6 +87,7 @@ class Demux : public IDemux {
bool detachRecordFilter(int filterId);
Result startFilterHandler(uint32_t filterId);
void updateFilterOutput(uint16_t filterId, vector<uint8_t> data);
void updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts);
uint16_t getFilterTpid(uint32_t filterId);
void setIsRecording(bool isRecording);
void startFrontendInputLoop();

View File

@@ -129,7 +129,7 @@ Return<Result> Dvr::stop() {
mDvrThreadRunning = false;
std::lock_guard<std::mutex> lock(mDvrThreadLock);
lock_guard<mutex> lock(mDvrThreadLock);
mIsRecordStarted = false;
mDemux->setIsRecording(false);
@@ -155,14 +155,13 @@ bool Dvr::createDvrMQ() {
ALOGV("%s", __FUNCTION__);
// Create a synchronized FMQ that supports blocking read/write
std::unique_ptr<DvrMQ> tmpDvrMQ =
std::unique_ptr<DvrMQ>(new (std::nothrow) DvrMQ(mBufferSize, true));
unique_ptr<DvrMQ> tmpDvrMQ = unique_ptr<DvrMQ>(new (nothrow) DvrMQ(mBufferSize, true));
if (!tmpDvrMQ->isValid()) {
ALOGW("[Dvr] Failed to create FMQ of DVR");
return false;
}
mDvrMQ = std::move(tmpDvrMQ);
mDvrMQ = move(tmpDvrMQ);
if (EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrEventFlag) != OK) {
return false;
@@ -183,7 +182,7 @@ void* Dvr::__threadLoopPlayback(void* user) {
void Dvr::playbackThreadLoop() {
ALOGD("[Dvr] playback threadLoop start.");
std::lock_guard<std::mutex> lock(mDvrThreadLock);
lock_guard<mutex> lock(mDvrThreadLock);
mDvrThreadRunning = true;
while (mDvrThreadRunning) {
@@ -195,6 +194,14 @@ void Dvr::playbackThreadLoop() {
ALOGD("[Dvr] wait for data ready on the playback FMQ");
continue;
}
if (mDvrSettings.playback().dataFormat == DataFormat::ES) {
if (!processEsDataOnPlayback(false /*isVirtualFrontend*/, false /*isRecording*/)) {
ALOGE("[Dvr] playback es data failed to be filtered. Ending thread");
break;
}
maySendPlaybackStatusCallback();
}
// Our current implementation filter the data and write it into the filter FMQ immediately
// after the DATA_READY from the VTS/framework
if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) ||
@@ -211,7 +218,7 @@ void Dvr::playbackThreadLoop() {
}
void Dvr::maySendPlaybackStatusCallback() {
std::lock_guard<std::mutex> lock(mPlaybackStatusLock);
lock_guard<mutex> lock(mPlaybackStatusLock);
int availableToRead = mDvrMQ->availableToRead();
int availableToWrite = mDvrMQ->availableToWrite();
@@ -263,8 +270,128 @@ bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) {
return true;
}
bool Dvr::processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording) {
// Read ES from the DVR FMQ
// Note that currently we only provides ES with metaData in a specific format to be parsed.
// The ES size should be smaller than the Playback FMQ size to avoid reading truncated data.
int size = mDvrMQ->availableToRead();
vector<uint8_t> dataOutputBuffer;
dataOutputBuffer.resize(size);
if (!mDvrMQ->read(dataOutputBuffer.data(), size)) {
return false;
}
int metaDataSize = size;
int totalFrames = 0;
int videoEsDataSize = 0;
int audioEsDataSize = 0;
int audioPid = 0;
int videoPid = 0;
vector<MediaEsMetaData> esMeta;
int videoReadPointer = 0;
int audioReadPointer = 0;
int frameCount = 0;
// Get meta data from the es
for (int i = 0; i < metaDataSize; i++) {
switch (dataOutputBuffer[i]) {
case 'm':
metaDataSize = 0;
getMetaDataValue(i, dataOutputBuffer.data(), metaDataSize);
videoReadPointer = metaDataSize;
continue;
case 'l':
getMetaDataValue(i, dataOutputBuffer.data(), totalFrames);
esMeta.resize(totalFrames);
continue;
case 'V':
getMetaDataValue(i, dataOutputBuffer.data(), videoEsDataSize);
audioReadPointer = metaDataSize + videoEsDataSize;
continue;
case 'A':
getMetaDataValue(i, dataOutputBuffer.data(), audioEsDataSize);
continue;
case 'p':
if (dataOutputBuffer[++i] == 'a') {
getMetaDataValue(i, dataOutputBuffer.data(), audioPid);
} else if (dataOutputBuffer[i] == 'v') {
getMetaDataValue(i, dataOutputBuffer.data(), videoPid);
}
continue;
case 'v':
case 'a':
if (dataOutputBuffer[i + 1] != ',') {
ALOGE("[Dvr] Invalid format meta data.");
return false;
}
esMeta[frameCount] = {
.isAudio = dataOutputBuffer[i] == 'a' ? true : false,
};
i += 5; // Move to Len
getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].len);
if (esMeta[frameCount].isAudio) {
esMeta[frameCount].startIndex = audioReadPointer;
audioReadPointer += esMeta[frameCount].len;
} else {
esMeta[frameCount].startIndex = videoReadPointer;
videoReadPointer += esMeta[frameCount].len;
}
i += 4; // move to PTS
getMetaDataValue(i, dataOutputBuffer.data(), esMeta[frameCount].pts);
frameCount++;
continue;
default:
continue;
}
}
if (frameCount != totalFrames) {
ALOGE("[Dvr] Invalid meta data, frameCount=%d, totalFrames reported=%d", frameCount,
totalFrames);
return false;
}
if (metaDataSize + audioEsDataSize + videoEsDataSize != size) {
ALOGE("[Dvr] Invalid meta data, metaSize=%d, videoSize=%d, audioSize=%d, totolSize=%d",
metaDataSize, videoEsDataSize, audioEsDataSize, size);
return false;
}
// Read es raw data from the FMQ per meta data built previously
vector<uint8_t> frameData;
map<uint32_t, sp<IFilter>>::iterator it;
int pid = 0;
for (int i = 0; i < totalFrames; i++) {
frameData.resize(esMeta[i].len);
pid = esMeta[i].isAudio ? audioPid : videoPid;
memcpy(dataOutputBuffer.data() + esMeta[i].startIndex, frameData.data(), esMeta[i].len);
// Send to the media filter
if (isVirtualFrontend && isRecording) {
// TODO validate record
mDemux->sendFrontendInputToRecord(frameData);
} else {
for (it = mFilters.begin(); it != mFilters.end(); it++) {
if (pid == mDemux->getFilterTpid(it->first)) {
mDemux->updateMediaFilterOutput(it->first, frameData,
static_cast<uint64_t>(esMeta[i].pts));
startFilterDispatcher(isVirtualFrontend, isRecording);
}
}
}
}
return true;
}
void Dvr::getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value) {
index += 2; // Move the pointer across the ":" to the value
while (dataOutputBuffer[index] != ',' && dataOutputBuffer[index] != '\n') {
value = ((dataOutputBuffer[index++] - 48) + value * 10);
}
}
void Dvr::startTpidFilter(vector<uint8_t> data) {
std::map<uint32_t, sp<IFilter>>::iterator it;
map<uint32_t, sp<IFilter>>::iterator it;
for (it = mFilters.begin(); it != mFilters.end(); it++) {
uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
if (DEBUG_DVR) {
@@ -285,7 +412,7 @@ bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
}
}
std::map<uint32_t, sp<IFilter>>::iterator it;
map<uint32_t, sp<IFilter>>::iterator it;
// Handle the output data per filter type
for (it = mFilters.begin(); it != mFilters.end(); it++) {
if (mDemux->startFilterHandler(it->first) != Result::SUCCESS) {
@@ -296,8 +423,8 @@ bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
return true;
}
bool Dvr::writeRecordFMQ(const std::vector<uint8_t>& data) {
std::lock_guard<std::mutex> lock(mWriteLock);
bool Dvr::writeRecordFMQ(const vector<uint8_t>& data) {
lock_guard<mutex> lock(mWriteLock);
if (mRecordStatus == RecordStatus::OVERFLOW) {
ALOGW("[Dvr] stops writing and wait for the client side flushing.");
return true;
@@ -313,7 +440,7 @@ bool Dvr::writeRecordFMQ(const std::vector<uint8_t>& data) {
}
void Dvr::maySendRecordStatusCallback() {
std::lock_guard<std::mutex> lock(mRecordStatusLock);
lock_guard<mutex> lock(mRecordStatusLock);
int availableToRead = mDvrMQ->availableToRead();
int availableToWrite = mDvrMQ->availableToWrite();

View File

@@ -44,6 +44,13 @@ using ::android::hardware::tv::tuner::V1_0::Result;
using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
struct MediaEsMetaData {
bool isAudio;
int startIndex;
int len;
int pts;
};
class Demux;
class Filter;
class Frontend;
@@ -84,8 +91,10 @@ class Dvr : public IDvr {
bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter);
bool removePlaybackFilter(uint32_t filterId);
bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording);
bool processEsDataOnPlayback(bool isVirtualFrontend, bool isRecording);
bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording);
EventFlag* getDvrEventFlag();
DvrSettings getSettings() { return mDvrSettings; }
private:
// Demux service
@@ -98,6 +107,7 @@ class Dvr : public IDvr {
void deleteEventFlag();
bool readDataFromMQ();
void getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value);
void maySendPlaybackStatusCallback();
void maySendRecordStatusCallback();
PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,

View File

@@ -317,6 +317,11 @@ void Filter::updateFilterOutput(vector<uint8_t> data) {
mFilterOutput.insert(mFilterOutput.end(), data.begin(), data.end());
}
void Filter::updatePts(uint64_t pts) {
std::lock_guard<std::mutex> lock(mFilterOutputLock);
mPts = pts;
}
void Filter::updateRecordOutput(vector<uint8_t> data) {
std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end());
@@ -460,6 +465,11 @@ Result Filter::startMediaFilterHandler() {
if (mFilterOutput.empty()) {
return Result::SUCCESS;
}
if (mPts) {
return createMediaFilterEventWithIon(mFilterOutput);
}
for (int i = 0; i < mFilterOutput.size(); i += 188) {
if (mPesSizeLeft == 0) {
uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
@@ -493,46 +503,7 @@ Result Filter::startMediaFilterHandler() {
continue;
}
int av_fd = createAvIonFd(mPesOutput.size());
if (av_fd == -1) {
return Result::UNKNOWN_ERROR;
}
// copy the filtered data to the buffer
uint8_t* avBuffer = getIonBuffer(av_fd, mPesOutput.size());
if (avBuffer == NULL) {
return Result::UNKNOWN_ERROR;
}
memcpy(avBuffer, mPesOutput.data(), mPesOutput.size() * sizeof(uint8_t));
native_handle_t* nativeHandle = createNativeHandle(av_fd);
if (nativeHandle == NULL) {
return Result::UNKNOWN_ERROR;
}
hidl_handle handle;
handle.setTo(nativeHandle, /*shouldOwn=*/true);
// Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
mDataId2Avfd[dataId] = dup(av_fd);
// Create mediaEvent and send callback
DemuxFilterMediaEvent mediaEvent;
mediaEvent = {
.avMemory = std::move(handle),
.dataLength = static_cast<uint32_t>(mPesOutput.size()),
.avDataId = dataId,
};
int size = mFilterEvent.events.size();
mFilterEvent.events.resize(size + 1);
mFilterEvent.events[size].media(mediaEvent);
// Clear and log
mPesOutput.clear();
mAvBufferCopyCount = 0;
::close(av_fd);
if (DEBUG_FILTER) {
ALOGD("[Filter] assembled av data length %d", mediaEvent.dataLength);
}
createMediaFilterEventWithIon(mPesOutput);
}
mFilterOutput.clear();
@@ -540,6 +511,54 @@ Result Filter::startMediaFilterHandler() {
return Result::SUCCESS;
}
Result Filter::createMediaFilterEventWithIon(vector<uint8_t> output) {
int av_fd = createAvIonFd(output.size());
if (av_fd == -1) {
return Result::UNKNOWN_ERROR;
}
// copy the filtered data to the buffer
uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
if (avBuffer == NULL) {
return Result::UNKNOWN_ERROR;
}
memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
native_handle_t* nativeHandle = createNativeHandle(av_fd);
if (nativeHandle == NULL) {
return Result::UNKNOWN_ERROR;
}
hidl_handle handle;
handle.setTo(nativeHandle, /*shouldOwn=*/true);
// Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
mDataId2Avfd[dataId] = dup(av_fd);
// Create mediaEvent and send callback
DemuxFilterMediaEvent mediaEvent;
mediaEvent = {
.avMemory = std::move(handle),
.dataLength = static_cast<uint32_t>(output.size()),
.avDataId = dataId,
};
if (mPts) {
mediaEvent.pts = mPts;
mPts = 0;
}
int size = mFilterEvent.events.size();
mFilterEvent.events.resize(size + 1);
mFilterEvent.events[size].media(mediaEvent);
// Clear and log
output.clear();
mAvBufferCopyCount = 0;
::close(av_fd);
if (DEBUG_FILTER) {
ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
}
return Result::SUCCESS;
}
Result Filter::startRecordFilterHandler() {
std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
if (mRecordFilterOutput.empty()) {

View File

@@ -84,6 +84,7 @@ class Filter : public IFilter {
uint16_t getTpid();
void updateFilterOutput(vector<uint8_t> data);
void updateRecordOutput(vector<uint8_t> data);
void updatePts(uint64_t pts);
Result startFilterHandler();
Result startRecordFilterHandler();
void attachFilterToRecord(const sp<Dvr> dvr);
@@ -116,6 +117,7 @@ class Filter : public IFilter {
bool mIsDataSourceDemux = true;
vector<uint8_t> mFilterOutput;
vector<uint8_t> mRecordFilterOutput;
uint64_t mPts = 0;
unique_ptr<FilterMQ> mFilterMQ;
bool mIsUsingFMQ = false;
EventFlag* mFilterEventFlag;
@@ -172,6 +174,7 @@ class Filter : public IFilter {
int createAvIonFd(int size);
uint8_t* getIonBuffer(int fd, int size);
native_handle_t* createNativeHandle(int fd);
Result createMediaFilterEventWithIon(vector<uint8_t> output);
/**
* Lock to protect writes to the FMQs

View File

@@ -370,13 +370,11 @@ AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWith
mIsSoftwareFe = config.isSoftwareFe;
bool result = true;
if (mIsSoftwareFe && testWithDemux) {
DvrConfig dvrConfig;
getSoftwareFrontendPlaybackConfig(dvrConfig);
result &= mDvrTests.openDvrInDemux(dvrConfig.type, dvrConfig.bufferSize) == success();
result &= mDvrTests.configDvrPlayback(dvrConfig.settings) == success();
result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
mDvrTests.startPlaybackInputThread(dvrConfig.playbackInputFile,
dvrConfig.settings.playback());
mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
mDvrConfig.settings.playback());
if (!result) {
ALOGW("[vts] Software frontend dvr configure failed.");
return failure();

View File

@@ -104,6 +104,7 @@ class FrontendTests {
void setService(sp<ITuner> tuner) {
mService = tuner;
mDvrTests.setService(tuner);
getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
}
AssertionResult getFrontendIds();
@@ -125,12 +126,13 @@ class FrontendTests {
void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; }
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
static AssertionResult success() { return ::testing::AssertionSuccess(); }
void getSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) {
void getDefaultSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) {
PlaybackSettings playbackSettings{
.statusMask = 0xf,
.lowThreshold = 0x1000,
@@ -151,4 +153,5 @@ class FrontendTests {
DvrTests mDvrTests;
bool mIsSoftwareFe = false;
DvrConfig mDvrConfig;
};

View File

@@ -486,6 +486,62 @@ TEST_P(TunerBroadcastHidlTest, LnbBroadcastDataFlowVideoFilterTest) {
broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBS]);
}
TEST_P(TunerBroadcastHidlTest, BroadcastEsDataFlowMediaFiltersTest) {
description("Test Meida Filters functionality in Broadcast use case with ES input.");
uint32_t feId;
uint32_t demuxId;
sp<IDemux> demux;
uint32_t filterId;
mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
if (feId == INVALID_ID) {
// TODO broadcast test on Cuttlefish needs licensed ts input,
// these tests are runnable on vendor device with real frontend module
// or with manual ts installing and use DVBT frontend.
return;
}
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFrontendTests.setDemux(demux);
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_AUDIO1].type,
filterArray[TS_AUDIO1].bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_AUDIO1].settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO1].type,
filterArray[TS_VIDEO1].bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
PlaybackSettings playbackSettings{
.statusMask = 0xf,
.lowThreshold = 0x1000,
.highThreshold = 0x07fff,
.dataFormat = DataFormat::ES,
.packetSize = 188,
};
DvrConfig dvrConfig{
.type = DvrType::PLAYBACK,
.playbackInputFile = "/data/local/tmp/test.es",
.bufferSize = FMQ_SIZE_4M,
};
dvrConfig.settings.playback(playbackSettings);
mFrontendTests.setSoftwareFrontendDvrConfig(dvrConfig);
ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendArray[DVBT], true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
TEST_P(TunerPlaybackHidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
description("Feed ts data from playback and configure Ts section filter to get output");
playbackSingleFilterTest(filterArray[TS_SECTION0], dvrArray[DVR_PLAYBACK0]);

View File

@@ -77,6 +77,7 @@ typedef enum {
TS_VIDEO0,
TS_VIDEO1,
TS_AUDIO0,
TS_AUDIO1,
TS_PES0,
TS_PCR0,
TS_SECTION0,
@@ -121,7 +122,6 @@ typedef enum {
typedef enum {
DVR_RECORD0,
DVR_PLAYBACK0,
DVR_SOFTWARE_FE,
DVR_MAX,
} Dvr;
@@ -274,6 +274,11 @@ inline void initFilterConfig() {
filterArray[TS_AUDIO0].bufferSize = FMQ_SIZE_16M;
filterArray[TS_AUDIO0].settings.ts().tpid = 256;
filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false});
filterArray[TS_AUDIO1].type.mainType = DemuxFilterMainType::TS;
filterArray[TS_AUDIO1].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
filterArray[TS_AUDIO1].bufferSize = FMQ_SIZE_16M;
filterArray[TS_AUDIO1].settings.ts().tpid = 257;
filterArray[TS_AUDIO1].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);
@@ -362,17 +367,6 @@ inline void initDvrConfig() {
dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
PlaybackSettings softwareFePlaybackSettings{
.statusMask = 0xf,
.lowThreshold = 0x1000,
.highThreshold = 0x07fff,
.dataFormat = DataFormat::TS,
.packetSize = 188,
};
dvrArray[DVR_SOFTWARE_FE].type = DvrType::PLAYBACK;
dvrArray[DVR_SOFTWARE_FE].playbackInputFile = "/data/local/tmp/segment000000.ts";
dvrArray[DVR_SOFTWARE_FE].bufferSize = FMQ_SIZE_4M;
dvrArray[DVR_SOFTWARE_FE].settings.playback(softwareFePlaybackSettings);
};
/** Configuration array for the descrambler test */