Loading tv/tuner/1.0/default/Demux.cpp +69 −67 Original line number Diff line number Diff line Loading @@ -48,8 +48,6 @@ Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) { return Result::INVALID_STATE; } mFrontendSourceFile = mFrontend->getSourceFile(); mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId); return Result::SUCCESS; Loading @@ -62,8 +60,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, uint32_t filterId; filterId = ++mLastUsedFilterId; mUsedFilterIds.insert(filterId); if (cb == nullptr) { ALOGW("[Demux] callback can't be null"); _hidl_cb(Result::INVALID_ARGUMENT, new Filter()); Loading @@ -82,8 +78,13 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, mPcrFilterIds.insert(filterId); } bool result = true; if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) { result = mDvr->addPlaybackFilter(filter); if (!filter->isRecordFilter()) { // Only save non-record filters for now. Record filters are saved when the // IDvr.attacheFilter is called. mPlaybackFilterIds.insert(filterId); if (mDvrPlayback != nullptr) { result = mDvrPlayback->addPlaybackFilter(filterId, filter); } } _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter); Loading Loading @@ -154,7 +155,13 @@ Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_ Return<Result> Demux::close() { ALOGV("%s", __FUNCTION__); mUsedFilterIds.clear(); set<uint32_t>::iterator it; for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { mDvrPlayback->removePlaybackFilter(*it); } mPlaybackFilterIds.clear(); mRecordFilterIds.clear(); mFilters.clear(); mLastUsedFilterId = -1; return Result::SUCCESS; Loading @@ -170,15 +177,38 @@ Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCall return Void(); } mDvr = new Dvr(type, bufferSize, cb, this); set<uint32_t>::iterator it; switch (type) { case DvrType::PLAYBACK: mDvrPlayback = new Dvr(type, bufferSize, cb, this); if (!mDvrPlayback->createDvrMQ()) { _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback); return Void(); } for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) { ALOGE("[Demux] Can't get filter info for DVR playback"); _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback); return Void(); } } if (!mDvr->createDvrMQ()) { _hidl_cb(Result::UNKNOWN_ERROR, mDvr); _hidl_cb(Result::SUCCESS, mDvrPlayback); return Void(); case DvrType::RECORD: mDvrRecord = new Dvr(type, bufferSize, cb, this); if (!mDvrRecord->createDvrMQ()) { _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord); return Void(); } _hidl_cb(Result::SUCCESS, mDvr); _hidl_cb(Result::SUCCESS, mDvrRecord); return Void(); default: _hidl_cb(Result::INVALID_ARGUMENT, nullptr); return Void(); } } Return<Result> Demux::connectCiCam(uint32_t ciCamId) { Loading @@ -198,8 +228,10 @@ Return<Result> Demux::disconnectCiCam() { Result Demux::removeFilter(uint32_t filterId) { ALOGV("%s", __FUNCTION__); // resetFilterRecords(filterId); mUsedFilterIds.erase(filterId); if (mDvrPlayback != nullptr) { mDvrPlayback->removePlaybackFilter(filterId); } mPlaybackFilterIds.erase(filterId); mRecordFilterIds.erase(filterId); mFilters.erase(filterId); Loading @@ -212,7 +244,7 @@ void Demux::startBroadcastTsFilter(vector<uint8_t> data) { if (DEBUG_DEMUX) { ALOGW("[Demux] start ts filter pid: %d", pid); } for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) { for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { if (pid == mFilters[*it]->getTpid()) { mFilters[*it]->updateFilterOutput(data); } Loading @@ -233,7 +265,7 @@ bool Demux::startBroadcastFilterDispatcher() { set<uint32_t>::iterator it; // Handle the output data per filter type for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) { for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) { return false; } Loading Loading @@ -280,58 +312,27 @@ void* Demux::__threadLoopFrontend(void* user) { void Demux::frontendInputThreadLoop() { std::lock_guard<std::mutex> lock(mFrontendInputThreadLock); mFrontendInputThreadRunning = true; mKeepFetchingDataFromFrontend = true; // open the stream and get its length std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary); // TODO take the packet size from the frontend setting int packetSize = 188; int writePacketAmount = 6; char* buffer = new char[packetSize]; ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str()); if (!inputData.is_open()) { mFrontendInputThreadRunning = false; ALOGW("[Demux] Error %s", strerror(errno)); } while (mFrontendInputThreadRunning) { // move the stream pointer for packet size * 6 every read until the end while (mKeepFetchingDataFromFrontend) { for (int i = 0; i < writePacketAmount; i++) { inputData.read(buffer, packetSize); if (!inputData) { mKeepFetchingDataFromFrontend = false; mFrontendInputThreadRunning = false; uint32_t efState = 0; status_t status = mDvrPlayback->getDvrEventFlag()->wait( static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT, true /* retry on spurious wake */); if (status != OK) { ALOGD("[Demux] wait for data ready on the playback 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 (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) || !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) { ALOGE("[Demux] playback data failed to be filtered. Ending thread"); break; } // filter and dispatch filter output vector<uint8_t> byteBuffer; byteBuffer.resize(packetSize); for (int index = 0; index < byteBuffer.size(); index++) { byteBuffer[index] = static_cast<uint8_t>(buffer[index]); } if (mIsRecording) { // Feed the data into the Dvr recording input sendFrontendInputToRecord(byteBuffer); } else { // Feed the data into the broadcast demux filter startBroadcastTsFilter(byteBuffer); } } if (mIsRecording) { // Dispatch the data into the broadcasting filters. startRecordFilterDispatcher(); } else { // Dispatch the data into the broadcasting filters. startBroadcastFilterDispatcher(); } usleep(100); } } mFrontendInputThreadRunning = false; ALOGW("[Demux] Frontend Input thread end."); delete[] buffer; inputData.close(); } void Demux::stopFrontendInput() { Loading @@ -346,18 +347,19 @@ void Demux::setIsRecording(bool isRecording) { } bool Demux::attachRecordFilter(int filterId) { if (mFilters[filterId] == nullptr || mDvr == nullptr) { if (mFilters[filterId] == nullptr || mDvrRecord == nullptr || !mFilters[filterId]->isRecordFilter()) { return false; } mRecordFilterIds.insert(filterId); mFilters[filterId]->attachFilterToRecord(mDvr); mFilters[filterId]->attachFilterToRecord(mDvrRecord); return true; } bool Demux::detachRecordFilter(int filterId) { if (mFilters[filterId] == nullptr || mDvr == nullptr) { if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) { return false; } Loading tv/tuner/1.0/default/Demux.h +16 −15 Original line number Diff line number Diff line Loading @@ -91,13 +91,23 @@ class Demux : public IDemux { void setIsRecording(bool isRecording); void startFrontendInputLoop(); /** * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. * Note that recording filters are not included. */ bool startBroadcastFilterDispatcher(); void startBroadcastTsFilter(vector<uint8_t> data); void sendFrontendInputToRecord(vector<uint8_t> data); bool startRecordFilterDispatcher(); private: // Tuner service sp<Tuner> mTunerService; // Frontend source sp<Frontend> mFrontend; string mFrontendSourceFile; // A struct that passes the arguments to a newly created filter thread struct ThreadArgs { Loading @@ -117,16 +127,6 @@ class Demux : public IDemux { */ void deleteEventFlag(); bool readDataFromMQ(); /** * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. * Note that recording filters are not included. */ bool startBroadcastFilterDispatcher(); void startBroadcastTsFilter(vector<uint8_t> data); void sendFrontendInputToRecord(vector<uint8_t> data); bool startRecordFilterDispatcher(); uint32_t mDemuxId; uint32_t mCiCamId; Loading @@ -137,17 +137,17 @@ class Demux : public IDemux { */ uint32_t mLastUsedFilterId = -1; /** * Record all the used filter Ids. * Record all the used playback filter Ids. * Any removed filter id should be removed from this set. */ set<uint32_t> mUsedFilterIds; set<uint32_t> mPlaybackFilterIds; /** * Record all the attached record filter Ids. * Any removed filter id should be removed from this set. */ set<uint32_t> mRecordFilterIds; /** * A list of created FilterMQ ptrs. * A list of created Filter sp. * The array number is the filter ID. */ std::map<uint32_t, sp<Filter>> mFilters; Loading @@ -160,7 +160,8 @@ class Demux : public IDemux { /** * Local reference to the opened DVR object. */ sp<Dvr> mDvr; sp<Dvr> mDvrPlayback; sp<Dvr> mDvrRecord; // Thread handlers pthread_t mFrontendInputThread; Loading tv/tuner/1.0/default/Dvr.cpp +33 −36 Original line number Diff line number Diff line Loading @@ -70,8 +70,7 @@ Return<Result> Dvr::attachFilter(const sp<IFilter>& filter) { return status; } // check if the attached filter is a record filter mFilters[filterId] = filter; // TODO check if the attached filter is a record filter if (!mDemux->attachRecordFilter(filterId)) { return Result::INVALID_ARGUMENT; } Loading @@ -94,20 +93,9 @@ Return<Result> Dvr::detachFilter(const sp<IFilter>& filter) { return status; } std::map<uint32_t, sp<IFilter>>::iterator it; it = mFilters.find(filterId); if (it != mFilters.end()) { mFilters.erase(filterId); if (!mDemux->detachRecordFilter(filterId)) { return Result::INVALID_ARGUMENT; } } // If all the filters are detached, record can't be started if (mFilters.empty()) { mIsRecordFilterAttached = false; } return Result::SUCCESS; } Loading Loading @@ -183,6 +171,10 @@ bool Dvr::createDvrMQ() { return true; } EventFlag* Dvr::getDvrEventFlag() { return mDvrEventFlag; } void* Dvr::__threadLoopPlayback(void* user) { Dvr* const self = static_cast<Dvr*>(user); self->playbackThreadLoop(); Loading @@ -205,8 +197,9 @@ void Dvr::playbackThreadLoop() { } // Our current implementation filter the data and write it into the filter FMQ immediately // after the DATA_READY from the VTS/framework if (!readPlaybackFMQ() || !startFilterDispatcher()) { ALOGD("[Dvr] playback data failed to be filtered. Ending thread"); if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) || !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) { ALOGE("[Dvr] playback data failed to be filtered. Ending thread"); break; } Loading Loading @@ -245,7 +238,7 @@ PlaybackStatus Dvr::checkPlaybackStatusChange(uint32_t availableToWrite, uint32_ return mPlaybackStatus; } bool Dvr::readPlaybackFMQ() { bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) { // Read playback data from the input FMQ int size = mDvrMQ->availableToRead(); int playbackPacketSize = mDvrSettings.playback().packetSize; Loading @@ -256,8 +249,16 @@ bool Dvr::readPlaybackFMQ() { if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) { return false; } if (isVirtualFrontend) { if (isRecording) { mDemux->sendFrontendInputToRecord(dataOutputBuffer); } else { mDemux->startBroadcastTsFilter(dataOutputBuffer); } } else { startTpidFilter(dataOutputBuffer); } } return true; } Loading @@ -275,7 +276,15 @@ void Dvr::startTpidFilter(vector<uint8_t> data) { } } bool Dvr::startFilterDispatcher() { bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) { if (isVirtualFrontend) { if (isRecording) { return mDemux->startRecordFilterDispatcher(); } else { return mDemux->startBroadcastFilterDispatcher(); } } std::map<uint32_t, sp<IFilter>>::iterator it; // Handle the output data per filter type for (it = mFilters.begin(); it != mFilters.end(); it++) { Loading Loading @@ -329,27 +338,15 @@ RecordStatus Dvr::checkRecordStatusChange(uint32_t availableToWrite, uint32_t av return mRecordStatus; } bool Dvr::addPlaybackFilter(sp<IFilter> filter) { uint32_t filterId; Result status; filter->getId([&](Result result, uint32_t id) { filterId = id; status = result; }); if (status != Result::SUCCESS) { return false; } bool Dvr::addPlaybackFilter(uint32_t filterId, sp<IFilter> filter) { mFilters[filterId] = filter; return true; } DvrType Dvr::getType() { return mType; bool Dvr::removePlaybackFilter(uint32_t filterId) { mFilters.erase(filterId); return true; } } // namespace implementation } // namespace V1_0 } // namespace tuner Loading tv/tuner/1.0/default/Dvr.h +5 −8 Original line number Diff line number Diff line Loading @@ -81,8 +81,11 @@ class Dvr : public IDvr { bool createDvrMQ(); void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer); bool writeRecordFMQ(const std::vector<uint8_t>& data); DvrType getType(); bool addPlaybackFilter(sp<IFilter> filter); bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter); bool removePlaybackFilter(uint32_t filterId); bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording); bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording); EventFlag* getDvrEventFlag(); private: // Demux service Loading @@ -105,9 +108,7 @@ class Dvr : public IDvr { * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. */ bool readPlaybackFMQ(); void startTpidFilter(vector<uint8_t> data); bool startFilterDispatcher(); static void* __threadLoopPlayback(void* user); static void* __threadLoopRecord(void* user); void playbackThreadLoop(); Loading @@ -123,7 +124,6 @@ class Dvr : public IDvr { // Thread handlers pthread_t mDvrThread; pthread_t mBroadcastInputThread; // FMQ status local records PlaybackStatus mPlaybackStatus; Loading @@ -132,7 +132,6 @@ class Dvr : public IDvr { * If a specific filter's writing loop is still running */ bool mDvrThreadRunning; bool mBroadcastInputThreadRunning; bool mKeepFetchingDataFromFrontend; /** * Lock to protect writes to the FMQs Loading @@ -143,7 +142,6 @@ class Dvr : public IDvr { */ std::mutex mPlaybackStatusLock; std::mutex mRecordStatusLock; std::mutex mBroadcastInputThreadLock; std::mutex mDvrThreadLock; const bool DEBUG_DVR = false; Loading @@ -151,7 +149,6 @@ class Dvr : public IDvr { // Booleans to check if recording is running. // Recording is ready when both of the following are set to true. bool mIsRecordStarted = false; bool mIsRecordFilterAttached = false; }; } // namespace implementation Loading tv/tuner/1.0/default/Filter.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -47,12 +47,18 @@ Filter::Filter(DemuxFilterType type, uint32_t filterId, uint32_t bufferSize, if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) { mIsPcrFilter = true; } if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) { mIsRecordFilter = true; } break; case DemuxFilterMainType::MMTP: if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO || mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) { mIsMediaFilter = true; } if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) { mIsRecordFilter = true; } break; case DemuxFilterMainType::IP: break; Loading Loading @@ -535,12 +541,6 @@ Result Filter::startMediaFilterHandler() { } Result Filter::startRecordFilterHandler() { /*DemuxFilterTsRecordEvent tsRecordEvent; tsRecordEvent.pid.tPid(0); tsRecordEvent.indexMask.tsIndexMask(0x01); mFilterEvent.events.resize(1); mFilterEvent.events[0].tsRecord(tsRecordEvent); */ std::lock_guard<std::mutex> lock(mRecordFilterOutputLock); if (mRecordFilterOutput.empty()) { return Result::SUCCESS; Loading @@ -567,7 +567,7 @@ Result Filter::startTemiFilterHandler() { bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) { // TODO check how many sections has been read ALOGD("[Filter] section hander"); ALOGD("[Filter] section handler"); std::lock_guard<std::mutex> lock(mFilterEventLock); if (!writeDataToFilterMQ(data)) { return false; Loading Loading
tv/tuner/1.0/default/Demux.cpp +69 −67 Original line number Diff line number Diff line Loading @@ -48,8 +48,6 @@ Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) { return Result::INVALID_STATE; } mFrontendSourceFile = mFrontend->getSourceFile(); mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId); return Result::SUCCESS; Loading @@ -62,8 +60,6 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, uint32_t filterId; filterId = ++mLastUsedFilterId; mUsedFilterIds.insert(filterId); if (cb == nullptr) { ALOGW("[Demux] callback can't be null"); _hidl_cb(Result::INVALID_ARGUMENT, new Filter()); Loading @@ -82,8 +78,13 @@ Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize, mPcrFilterIds.insert(filterId); } bool result = true; if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) { result = mDvr->addPlaybackFilter(filter); if (!filter->isRecordFilter()) { // Only save non-record filters for now. Record filters are saved when the // IDvr.attacheFilter is called. mPlaybackFilterIds.insert(filterId); if (mDvrPlayback != nullptr) { result = mDvrPlayback->addPlaybackFilter(filterId, filter); } } _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter); Loading Loading @@ -154,7 +155,13 @@ Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_ Return<Result> Demux::close() { ALOGV("%s", __FUNCTION__); mUsedFilterIds.clear(); set<uint32_t>::iterator it; for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { mDvrPlayback->removePlaybackFilter(*it); } mPlaybackFilterIds.clear(); mRecordFilterIds.clear(); mFilters.clear(); mLastUsedFilterId = -1; return Result::SUCCESS; Loading @@ -170,15 +177,38 @@ Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCall return Void(); } mDvr = new Dvr(type, bufferSize, cb, this); set<uint32_t>::iterator it; switch (type) { case DvrType::PLAYBACK: mDvrPlayback = new Dvr(type, bufferSize, cb, this); if (!mDvrPlayback->createDvrMQ()) { _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback); return Void(); } for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) { ALOGE("[Demux] Can't get filter info for DVR playback"); _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback); return Void(); } } if (!mDvr->createDvrMQ()) { _hidl_cb(Result::UNKNOWN_ERROR, mDvr); _hidl_cb(Result::SUCCESS, mDvrPlayback); return Void(); case DvrType::RECORD: mDvrRecord = new Dvr(type, bufferSize, cb, this); if (!mDvrRecord->createDvrMQ()) { _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord); return Void(); } _hidl_cb(Result::SUCCESS, mDvr); _hidl_cb(Result::SUCCESS, mDvrRecord); return Void(); default: _hidl_cb(Result::INVALID_ARGUMENT, nullptr); return Void(); } } Return<Result> Demux::connectCiCam(uint32_t ciCamId) { Loading @@ -198,8 +228,10 @@ Return<Result> Demux::disconnectCiCam() { Result Demux::removeFilter(uint32_t filterId) { ALOGV("%s", __FUNCTION__); // resetFilterRecords(filterId); mUsedFilterIds.erase(filterId); if (mDvrPlayback != nullptr) { mDvrPlayback->removePlaybackFilter(filterId); } mPlaybackFilterIds.erase(filterId); mRecordFilterIds.erase(filterId); mFilters.erase(filterId); Loading @@ -212,7 +244,7 @@ void Demux::startBroadcastTsFilter(vector<uint8_t> data) { if (DEBUG_DEMUX) { ALOGW("[Demux] start ts filter pid: %d", pid); } for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) { for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { if (pid == mFilters[*it]->getTpid()) { mFilters[*it]->updateFilterOutput(data); } Loading @@ -233,7 +265,7 @@ bool Demux::startBroadcastFilterDispatcher() { set<uint32_t>::iterator it; // Handle the output data per filter type for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) { for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) { if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) { return false; } Loading Loading @@ -280,58 +312,27 @@ void* Demux::__threadLoopFrontend(void* user) { void Demux::frontendInputThreadLoop() { std::lock_guard<std::mutex> lock(mFrontendInputThreadLock); mFrontendInputThreadRunning = true; mKeepFetchingDataFromFrontend = true; // open the stream and get its length std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary); // TODO take the packet size from the frontend setting int packetSize = 188; int writePacketAmount = 6; char* buffer = new char[packetSize]; ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str()); if (!inputData.is_open()) { mFrontendInputThreadRunning = false; ALOGW("[Demux] Error %s", strerror(errno)); } while (mFrontendInputThreadRunning) { // move the stream pointer for packet size * 6 every read until the end while (mKeepFetchingDataFromFrontend) { for (int i = 0; i < writePacketAmount; i++) { inputData.read(buffer, packetSize); if (!inputData) { mKeepFetchingDataFromFrontend = false; mFrontendInputThreadRunning = false; uint32_t efState = 0; status_t status = mDvrPlayback->getDvrEventFlag()->wait( static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT, true /* retry on spurious wake */); if (status != OK) { ALOGD("[Demux] wait for data ready on the playback 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 (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) || !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) { ALOGE("[Demux] playback data failed to be filtered. Ending thread"); break; } // filter and dispatch filter output vector<uint8_t> byteBuffer; byteBuffer.resize(packetSize); for (int index = 0; index < byteBuffer.size(); index++) { byteBuffer[index] = static_cast<uint8_t>(buffer[index]); } if (mIsRecording) { // Feed the data into the Dvr recording input sendFrontendInputToRecord(byteBuffer); } else { // Feed the data into the broadcast demux filter startBroadcastTsFilter(byteBuffer); } } if (mIsRecording) { // Dispatch the data into the broadcasting filters. startRecordFilterDispatcher(); } else { // Dispatch the data into the broadcasting filters. startBroadcastFilterDispatcher(); } usleep(100); } } mFrontendInputThreadRunning = false; ALOGW("[Demux] Frontend Input thread end."); delete[] buffer; inputData.close(); } void Demux::stopFrontendInput() { Loading @@ -346,18 +347,19 @@ void Demux::setIsRecording(bool isRecording) { } bool Demux::attachRecordFilter(int filterId) { if (mFilters[filterId] == nullptr || mDvr == nullptr) { if (mFilters[filterId] == nullptr || mDvrRecord == nullptr || !mFilters[filterId]->isRecordFilter()) { return false; } mRecordFilterIds.insert(filterId); mFilters[filterId]->attachFilterToRecord(mDvr); mFilters[filterId]->attachFilterToRecord(mDvrRecord); return true; } bool Demux::detachRecordFilter(int filterId) { if (mFilters[filterId] == nullptr || mDvr == nullptr) { if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) { return false; } Loading
tv/tuner/1.0/default/Demux.h +16 −15 Original line number Diff line number Diff line Loading @@ -91,13 +91,23 @@ class Demux : public IDemux { void setIsRecording(bool isRecording); void startFrontendInputLoop(); /** * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. * Note that recording filters are not included. */ bool startBroadcastFilterDispatcher(); void startBroadcastTsFilter(vector<uint8_t> data); void sendFrontendInputToRecord(vector<uint8_t> data); bool startRecordFilterDispatcher(); private: // Tuner service sp<Tuner> mTunerService; // Frontend source sp<Frontend> mFrontend; string mFrontendSourceFile; // A struct that passes the arguments to a newly created filter thread struct ThreadArgs { Loading @@ -117,16 +127,6 @@ class Demux : public IDemux { */ void deleteEventFlag(); bool readDataFromMQ(); /** * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. * Note that recording filters are not included. */ bool startBroadcastFilterDispatcher(); void startBroadcastTsFilter(vector<uint8_t> data); void sendFrontendInputToRecord(vector<uint8_t> data); bool startRecordFilterDispatcher(); uint32_t mDemuxId; uint32_t mCiCamId; Loading @@ -137,17 +137,17 @@ class Demux : public IDemux { */ uint32_t mLastUsedFilterId = -1; /** * Record all the used filter Ids. * Record all the used playback filter Ids. * Any removed filter id should be removed from this set. */ set<uint32_t> mUsedFilterIds; set<uint32_t> mPlaybackFilterIds; /** * Record all the attached record filter Ids. * Any removed filter id should be removed from this set. */ set<uint32_t> mRecordFilterIds; /** * A list of created FilterMQ ptrs. * A list of created Filter sp. * The array number is the filter ID. */ std::map<uint32_t, sp<Filter>> mFilters; Loading @@ -160,7 +160,8 @@ class Demux : public IDemux { /** * Local reference to the opened DVR object. */ sp<Dvr> mDvr; sp<Dvr> mDvrPlayback; sp<Dvr> mDvrRecord; // Thread handlers pthread_t mFrontendInputThread; Loading
tv/tuner/1.0/default/Dvr.cpp +33 −36 Original line number Diff line number Diff line Loading @@ -70,8 +70,7 @@ Return<Result> Dvr::attachFilter(const sp<IFilter>& filter) { return status; } // check if the attached filter is a record filter mFilters[filterId] = filter; // TODO check if the attached filter is a record filter if (!mDemux->attachRecordFilter(filterId)) { return Result::INVALID_ARGUMENT; } Loading @@ -94,20 +93,9 @@ Return<Result> Dvr::detachFilter(const sp<IFilter>& filter) { return status; } std::map<uint32_t, sp<IFilter>>::iterator it; it = mFilters.find(filterId); if (it != mFilters.end()) { mFilters.erase(filterId); if (!mDemux->detachRecordFilter(filterId)) { return Result::INVALID_ARGUMENT; } } // If all the filters are detached, record can't be started if (mFilters.empty()) { mIsRecordFilterAttached = false; } return Result::SUCCESS; } Loading Loading @@ -183,6 +171,10 @@ bool Dvr::createDvrMQ() { return true; } EventFlag* Dvr::getDvrEventFlag() { return mDvrEventFlag; } void* Dvr::__threadLoopPlayback(void* user) { Dvr* const self = static_cast<Dvr*>(user); self->playbackThreadLoop(); Loading @@ -205,8 +197,9 @@ void Dvr::playbackThreadLoop() { } // Our current implementation filter the data and write it into the filter FMQ immediately // after the DATA_READY from the VTS/framework if (!readPlaybackFMQ() || !startFilterDispatcher()) { ALOGD("[Dvr] playback data failed to be filtered. Ending thread"); if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) || !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) { ALOGE("[Dvr] playback data failed to be filtered. Ending thread"); break; } Loading Loading @@ -245,7 +238,7 @@ PlaybackStatus Dvr::checkPlaybackStatusChange(uint32_t availableToWrite, uint32_ return mPlaybackStatus; } bool Dvr::readPlaybackFMQ() { bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) { // Read playback data from the input FMQ int size = mDvrMQ->availableToRead(); int playbackPacketSize = mDvrSettings.playback().packetSize; Loading @@ -256,8 +249,16 @@ bool Dvr::readPlaybackFMQ() { if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) { return false; } if (isVirtualFrontend) { if (isRecording) { mDemux->sendFrontendInputToRecord(dataOutputBuffer); } else { mDemux->startBroadcastTsFilter(dataOutputBuffer); } } else { startTpidFilter(dataOutputBuffer); } } return true; } Loading @@ -275,7 +276,15 @@ void Dvr::startTpidFilter(vector<uint8_t> data) { } } bool Dvr::startFilterDispatcher() { bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) { if (isVirtualFrontend) { if (isRecording) { return mDemux->startRecordFilterDispatcher(); } else { return mDemux->startBroadcastFilterDispatcher(); } } std::map<uint32_t, sp<IFilter>>::iterator it; // Handle the output data per filter type for (it = mFilters.begin(); it != mFilters.end(); it++) { Loading Loading @@ -329,27 +338,15 @@ RecordStatus Dvr::checkRecordStatusChange(uint32_t availableToWrite, uint32_t av return mRecordStatus; } bool Dvr::addPlaybackFilter(sp<IFilter> filter) { uint32_t filterId; Result status; filter->getId([&](Result result, uint32_t id) { filterId = id; status = result; }); if (status != Result::SUCCESS) { return false; } bool Dvr::addPlaybackFilter(uint32_t filterId, sp<IFilter> filter) { mFilters[filterId] = filter; return true; } DvrType Dvr::getType() { return mType; bool Dvr::removePlaybackFilter(uint32_t filterId) { mFilters.erase(filterId); return true; } } // namespace implementation } // namespace V1_0 } // namespace tuner Loading
tv/tuner/1.0/default/Dvr.h +5 −8 Original line number Diff line number Diff line Loading @@ -81,8 +81,11 @@ class Dvr : public IDvr { bool createDvrMQ(); void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer); bool writeRecordFMQ(const std::vector<uint8_t>& data); DvrType getType(); bool addPlaybackFilter(sp<IFilter> filter); bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter); bool removePlaybackFilter(uint32_t filterId); bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording); bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording); EventFlag* getDvrEventFlag(); private: // Demux service Loading @@ -105,9 +108,7 @@ class Dvr : public IDvr { * A dispatcher to read and dispatch input data to all the started filters. * Each filter handler handles the data filtering/output writing/filterEvent updating. */ bool readPlaybackFMQ(); void startTpidFilter(vector<uint8_t> data); bool startFilterDispatcher(); static void* __threadLoopPlayback(void* user); static void* __threadLoopRecord(void* user); void playbackThreadLoop(); Loading @@ -123,7 +124,6 @@ class Dvr : public IDvr { // Thread handlers pthread_t mDvrThread; pthread_t mBroadcastInputThread; // FMQ status local records PlaybackStatus mPlaybackStatus; Loading @@ -132,7 +132,6 @@ class Dvr : public IDvr { * If a specific filter's writing loop is still running */ bool mDvrThreadRunning; bool mBroadcastInputThreadRunning; bool mKeepFetchingDataFromFrontend; /** * Lock to protect writes to the FMQs Loading @@ -143,7 +142,6 @@ class Dvr : public IDvr { */ std::mutex mPlaybackStatusLock; std::mutex mRecordStatusLock; std::mutex mBroadcastInputThreadLock; std::mutex mDvrThreadLock; const bool DEBUG_DVR = false; Loading @@ -151,7 +149,6 @@ class Dvr : public IDvr { // Booleans to check if recording is running. // Recording is ready when both of the following are set to true. bool mIsRecordStarted = false; bool mIsRecordFilterAttached = false; }; } // namespace implementation Loading
tv/tuner/1.0/default/Filter.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -47,12 +47,18 @@ Filter::Filter(DemuxFilterType type, uint32_t filterId, uint32_t bufferSize, if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) { mIsPcrFilter = true; } if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) { mIsRecordFilter = true; } break; case DemuxFilterMainType::MMTP: if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO || mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) { mIsMediaFilter = true; } if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) { mIsRecordFilter = true; } break; case DemuxFilterMainType::IP: break; Loading Loading @@ -535,12 +541,6 @@ Result Filter::startMediaFilterHandler() { } Result Filter::startRecordFilterHandler() { /*DemuxFilterTsRecordEvent tsRecordEvent; tsRecordEvent.pid.tPid(0); tsRecordEvent.indexMask.tsIndexMask(0x01); mFilterEvent.events.resize(1); mFilterEvent.events[0].tsRecord(tsRecordEvent); */ std::lock_guard<std::mutex> lock(mRecordFilterOutputLock); if (mRecordFilterOutput.empty()) { return Result::SUCCESS; Loading @@ -567,7 +567,7 @@ Result Filter::startTemiFilterHandler() { bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) { // TODO check how many sections has been read ALOGD("[Filter] section hander"); ALOGD("[Filter] section handler"); std::lock_guard<std::mutex> lock(mFilterEventLock); if (!writeDataToFilterMQ(data)) { return false; Loading