Loading tv/tuner/1.0/default/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ cc_defaults { "libfmq", "libfmq", "libhidlbase", "libhidlbase", "libhidlmemory", "libhidlmemory", "libion", "liblog", "liblog", "libstagefright_foundation", "libstagefright_foundation", "libutils", "libutils", Loading tv/tuner/1.0/default/Filter.cpp +147 −19 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,8 @@ Return<Result> Filter::setDataSource(const sp<IFilter>& filter) { Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) { Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) { ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__); mIsUsingFMQ = true; _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc()); _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc()); return Void(); return Void(); } } Loading Loading @@ -120,9 +122,13 @@ Return<Result> Filter::flush() { return Result::SUCCESS; return Result::SUCCESS; } } Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t /*avDataId*/) { Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) { ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__); if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) { return Result::INVALID_ARGUMENT; } ::close(mDataId2Avfd[avDataId]); return Result::SUCCESS; return Result::SUCCESS; } } Loading Loading @@ -174,14 +180,21 @@ void Filter::filterThreadLoop() { // Event Callback without waiting for the DATA_CONSUMED to init the process. // Event Callback without waiting for the DATA_CONSUMED to init the process. while (mFilterThreadRunning) { while (mFilterThreadRunning) { if (mFilterEvent.events.size() == 0) { if (mFilterEvent.events.size() == 0) { if (DEBUG_FILTER) { ALOGD("[Filter] wait for filter data output."); ALOGD("[Filter] wait for filter data output."); } usleep(1000 * 1000); usleep(1000 * 1000); continue; continue; } } // After successfully write, send a callback and wait for the read to be done // After successfully write, send a callback and wait for the read to be done mCallback->onFilterEvent(mFilterEvent); mCallback->onFilterEvent(mFilterEvent); freeAvHandle(); mFilterEvent.events.resize(0); mFilterEvent.events.resize(0); mFilterStatus = DemuxFilterStatus::DATA_READY; mFilterStatus = DemuxFilterStatus::DATA_READY; if (mCallback == nullptr) { ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId); break; } mCallback->onFilterStatus(mFilterStatus); mCallback->onFilterStatus(mFilterStatus); break; break; } } Loading @@ -191,7 +204,7 @@ void Filter::filterThreadLoop() { // We do not wait for the last round of written data to be read to finish the thread // We do not wait for the last round of written data to be read to finish the thread // because the VTS can verify the reading itself. // because the VTS can verify the reading itself. for (int i = 0; i < SECTION_WRITE_COUNT; i++) { for (int i = 0; i < SECTION_WRITE_COUNT; i++) { while (mFilterThreadRunning) { while (mFilterThreadRunning && mIsUsingFMQ) { status_t status = mFilterEventFlag->wait( status_t status = mFilterEventFlag->wait( static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState, static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState, WAIT_TIMEOUT, true /* retry on spurious wake */); WAIT_TIMEOUT, true /* retry on spurious wake */); Loading @@ -202,11 +215,6 @@ void Filter::filterThreadLoop() { break; break; } } if (mCallback == nullptr) { ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId); break; } maySendFilterStatusCallback(); maySendFilterStatusCallback(); while (mFilterThreadRunning) { while (mFilterThreadRunning) { Loading @@ -232,7 +240,22 @@ void Filter::filterThreadLoop() { ALOGD("[Filter] filter thread ended."); ALOGD("[Filter] filter thread ended."); } } void Filter::freeAvHandle() { if (mType.mainType != DemuxFilterMainType::TS || (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO && mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO)) { return; } for (int i = 0; i < mFilterEvent.events.size(); i++) { ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]); native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle()); } } void Filter::maySendFilterStatusCallback() { void Filter::maySendFilterStatusCallback() { if (!mIsUsingFMQ) { return; } std::lock_guard<std::mutex> lock(mFilterStatusLock); std::lock_guard<std::mutex> lock(mFilterStatusLock); int availableToRead = mFilterMQ->availableToRead(); int availableToRead = mFilterMQ->availableToRead(); int availableToWrite = mFilterMQ->availableToWrite(); int availableToWrite = mFilterMQ->availableToWrite(); Loading Loading @@ -409,19 +432,88 @@ Result Filter::startTsFilterHandler() { } } Result Filter::startMediaFilterHandler() { Result Filter::startMediaFilterHandler() { std::lock_guard<std::mutex> lock(mFilterEventLock); if (mFilterOutput.empty()) { return Result::SUCCESS; } for (int i = 0; i < mFilterOutput.size(); i += 188) { if (mPesSizeLeft == 0) { uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) | mFilterOutput[i + 6]; if (DEBUG_FILTER) { ALOGD("[Filter] prefix %d", prefix); } if (prefix == 0x000001) { // TODO handle mulptiple Pes filters mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9]; mPesSizeLeft += 6; if (DEBUG_FILTER) { ALOGD("[Filter] pes data length %d", mPesSizeLeft); } } else { continue; } } int endPoint = min(184, mPesSizeLeft); // append data and check size vector<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4; vector<uint8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint; mPesOutput.insert(mPesOutput.end(), first, last); // size does not match then continue mPesSizeLeft -= endPoint; if (DEBUG_FILTER) { ALOGD("[Filter] pes data left %d", mPesSizeLeft); } if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) { 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; DemuxFilterMediaEvent mediaEvent; mediaEvent = { mediaEvent = { // temp dump meta data .avMemory = std::move(handle), .pts = 0, .dataLength = static_cast<uint32_t>(mPesOutput.size()), .dataLength = 530, .avDataId = dataId, .avMemory = nullptr, .isSecureMemory = false, }; }; mFilterEvent.events.resize(1); int size = mFilterEvent.events.size(); mFilterEvent.events[0].media(mediaEvent); 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); } } mFilterOutput.clear(); mFilterOutput.clear(); // TODO handle write FQM for media stream return Result::SUCCESS; return Result::SUCCESS; } } Loading Loading @@ -493,6 +585,42 @@ void Filter::detachFilterFromRecord() { mDvr = nullptr; mDvr = nullptr; } } int Filter::createAvIonFd(int size) { // Create an ion fd and allocate an av fd mapped to a buffer to it. int ion_fd = ion_open(); if (ion_fd == -1) { ALOGE("[Filter] Failed to open ion fd %d", errno); return -1; } int av_fd = -1; ion_alloc_fd(dup(ion_fd), size, 0 /*align*/, ION_HEAP_SYSTEM_MASK, 0 /*flags*/, &av_fd); if (av_fd == -1) { ALOGE("[Filter] Failed to create av fd %d", errno); return -1; } return av_fd; } uint8_t* Filter::getIonBuffer(int fd, int size) { uint8_t* avBuf = static_cast<uint8_t*>( mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/)); if (avBuf == MAP_FAILED) { ALOGE("[Filter] fail to allocate buffer %d", errno); return NULL; } return avBuf; } native_handle_t* Filter::createNativeHandle(int fd) { // Create a native handle to pass the av fd via the callback event. native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0); if (nativeHandle == NULL) { ALOGE("[Filter] Failed to create native_handle %d", errno); return NULL; } nativeHandle->data[0] = dup(fd); return nativeHandle; } } // namespace implementation } // namespace implementation } // namespace V1_0 } // namespace V1_0 } // namespace tuner } // namespace tuner Loading tv/tuner/1.0/default/Filter.h +12 −0 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <android/hardware/tv/tuner/1.0/IFilter.h> #include <android/hardware/tv/tuner/1.0/IFilter.h> #include <fmq/MessageQueue.h> #include <fmq/MessageQueue.h> #include <ion/ion.h> #include <math.h> #include <math.h> #include <set> #include <set> #include "Demux.h" #include "Demux.h" Loading Loading @@ -87,6 +88,7 @@ class Filter : public IFilter { Result startRecordFilterHandler(); Result startRecordFilterHandler(); void attachFilterToRecord(const sp<Dvr> dvr); void attachFilterToRecord(const sp<Dvr> dvr); void detachFilterFromRecord(); void detachFilterFromRecord(); void freeAvHandle(); private: private: // Tuner service // Tuner service Loading @@ -109,6 +111,7 @@ class Filter : public IFilter { vector<uint8_t> mFilterOutput; vector<uint8_t> mFilterOutput; vector<uint8_t> mRecordFilterOutput; vector<uint8_t> mRecordFilterOutput; unique_ptr<FilterMQ> mFilterMQ; unique_ptr<FilterMQ> mFilterMQ; bool mIsUsingFMQ = false; EventFlag* mFilterEventFlag; EventFlag* mFilterEventFlag; DemuxFilterEvent mFilterEvent; DemuxFilterEvent mFilterEvent; Loading Loading @@ -160,6 +163,10 @@ class Filter : public IFilter { static void* __threadLoopFilter(void* user); static void* __threadLoopFilter(void* user); void filterThreadLoop(); void filterThreadLoop(); int createAvIonFd(int size); uint8_t* getIonBuffer(int fd, int size); native_handle_t* createNativeHandle(int fd); /** /** * Lock to protect writes to the FMQs * Lock to protect writes to the FMQs */ */ Loading @@ -181,6 +188,11 @@ class Filter : public IFilter { // TODO handle mulptiple Pes filters // TODO handle mulptiple Pes filters int mPesSizeLeft = 0; int mPesSizeLeft = 0; vector<uint8_t> mPesOutput; vector<uint8_t> mPesOutput; // A map from data id to ion handle std::map<uint64_t, int> mDataId2Avfd; uint64_t mLastUsedDataId = 1; int mAvBufferCopyCount = 0; }; }; } // namespace implementation } // namespace implementation Loading tv/tuner/1.0/default/Frontend.cpp +1 −4 Original line number Original line Diff line number Diff line Loading @@ -63,9 +63,6 @@ Return<Result> Frontend::tune(const FrontendSettings& /* settings */) { return Result::INVALID_STATE; return Result::INVALID_STATE; } } // TODO dynamically allocate file to the source file mSourceStreamFile = FRONTEND_STREAM_FILE; mCallback->onEvent(FrontendEventType::LOCKED); mCallback->onEvent(FrontendEventType::LOCKED); return Result::SUCCESS; return Result::SUCCESS; } } Loading Loading @@ -180,7 +177,7 @@ FrontendId Frontend::getFrontendId() { } } string Frontend::getSourceFile() { string Frontend::getSourceFile() { return mSourceStreamFile; return FRONTEND_STREAM_FILE; } } } // namespace implementation } // namespace implementation Loading tv/tuner/1.0/default/Frontend.h +0 −1 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,6 @@ class Frontend : public IFrontend { FrontendId mId = 0; FrontendId mId = 0; const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts"; const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts"; string mSourceStreamFile; std::ifstream mFrontendData; std::ifstream mFrontendData; }; }; Loading Loading
tv/tuner/1.0/default/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ cc_defaults { "libfmq", "libfmq", "libhidlbase", "libhidlbase", "libhidlmemory", "libhidlmemory", "libion", "liblog", "liblog", "libstagefright_foundation", "libstagefright_foundation", "libutils", "libutils", Loading
tv/tuner/1.0/default/Filter.cpp +147 −19 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,8 @@ Return<Result> Filter::setDataSource(const sp<IFilter>& filter) { Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) { Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) { ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__); mIsUsingFMQ = true; _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc()); _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc()); return Void(); return Void(); } } Loading Loading @@ -120,9 +122,13 @@ Return<Result> Filter::flush() { return Result::SUCCESS; return Result::SUCCESS; } } Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t /*avDataId*/) { Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) { ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__); if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) { return Result::INVALID_ARGUMENT; } ::close(mDataId2Avfd[avDataId]); return Result::SUCCESS; return Result::SUCCESS; } } Loading Loading @@ -174,14 +180,21 @@ void Filter::filterThreadLoop() { // Event Callback without waiting for the DATA_CONSUMED to init the process. // Event Callback without waiting for the DATA_CONSUMED to init the process. while (mFilterThreadRunning) { while (mFilterThreadRunning) { if (mFilterEvent.events.size() == 0) { if (mFilterEvent.events.size() == 0) { if (DEBUG_FILTER) { ALOGD("[Filter] wait for filter data output."); ALOGD("[Filter] wait for filter data output."); } usleep(1000 * 1000); usleep(1000 * 1000); continue; continue; } } // After successfully write, send a callback and wait for the read to be done // After successfully write, send a callback and wait for the read to be done mCallback->onFilterEvent(mFilterEvent); mCallback->onFilterEvent(mFilterEvent); freeAvHandle(); mFilterEvent.events.resize(0); mFilterEvent.events.resize(0); mFilterStatus = DemuxFilterStatus::DATA_READY; mFilterStatus = DemuxFilterStatus::DATA_READY; if (mCallback == nullptr) { ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId); break; } mCallback->onFilterStatus(mFilterStatus); mCallback->onFilterStatus(mFilterStatus); break; break; } } Loading @@ -191,7 +204,7 @@ void Filter::filterThreadLoop() { // We do not wait for the last round of written data to be read to finish the thread // We do not wait for the last round of written data to be read to finish the thread // because the VTS can verify the reading itself. // because the VTS can verify the reading itself. for (int i = 0; i < SECTION_WRITE_COUNT; i++) { for (int i = 0; i < SECTION_WRITE_COUNT; i++) { while (mFilterThreadRunning) { while (mFilterThreadRunning && mIsUsingFMQ) { status_t status = mFilterEventFlag->wait( status_t status = mFilterEventFlag->wait( static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState, static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState, WAIT_TIMEOUT, true /* retry on spurious wake */); WAIT_TIMEOUT, true /* retry on spurious wake */); Loading @@ -202,11 +215,6 @@ void Filter::filterThreadLoop() { break; break; } } if (mCallback == nullptr) { ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId); break; } maySendFilterStatusCallback(); maySendFilterStatusCallback(); while (mFilterThreadRunning) { while (mFilterThreadRunning) { Loading @@ -232,7 +240,22 @@ void Filter::filterThreadLoop() { ALOGD("[Filter] filter thread ended."); ALOGD("[Filter] filter thread ended."); } } void Filter::freeAvHandle() { if (mType.mainType != DemuxFilterMainType::TS || (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO && mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO)) { return; } for (int i = 0; i < mFilterEvent.events.size(); i++) { ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]); native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle()); } } void Filter::maySendFilterStatusCallback() { void Filter::maySendFilterStatusCallback() { if (!mIsUsingFMQ) { return; } std::lock_guard<std::mutex> lock(mFilterStatusLock); std::lock_guard<std::mutex> lock(mFilterStatusLock); int availableToRead = mFilterMQ->availableToRead(); int availableToRead = mFilterMQ->availableToRead(); int availableToWrite = mFilterMQ->availableToWrite(); int availableToWrite = mFilterMQ->availableToWrite(); Loading Loading @@ -409,19 +432,88 @@ Result Filter::startTsFilterHandler() { } } Result Filter::startMediaFilterHandler() { Result Filter::startMediaFilterHandler() { std::lock_guard<std::mutex> lock(mFilterEventLock); if (mFilterOutput.empty()) { return Result::SUCCESS; } for (int i = 0; i < mFilterOutput.size(); i += 188) { if (mPesSizeLeft == 0) { uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) | mFilterOutput[i + 6]; if (DEBUG_FILTER) { ALOGD("[Filter] prefix %d", prefix); } if (prefix == 0x000001) { // TODO handle mulptiple Pes filters mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9]; mPesSizeLeft += 6; if (DEBUG_FILTER) { ALOGD("[Filter] pes data length %d", mPesSizeLeft); } } else { continue; } } int endPoint = min(184, mPesSizeLeft); // append data and check size vector<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4; vector<uint8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint; mPesOutput.insert(mPesOutput.end(), first, last); // size does not match then continue mPesSizeLeft -= endPoint; if (DEBUG_FILTER) { ALOGD("[Filter] pes data left %d", mPesSizeLeft); } if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) { 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; DemuxFilterMediaEvent mediaEvent; mediaEvent = { mediaEvent = { // temp dump meta data .avMemory = std::move(handle), .pts = 0, .dataLength = static_cast<uint32_t>(mPesOutput.size()), .dataLength = 530, .avDataId = dataId, .avMemory = nullptr, .isSecureMemory = false, }; }; mFilterEvent.events.resize(1); int size = mFilterEvent.events.size(); mFilterEvent.events[0].media(mediaEvent); 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); } } mFilterOutput.clear(); mFilterOutput.clear(); // TODO handle write FQM for media stream return Result::SUCCESS; return Result::SUCCESS; } } Loading Loading @@ -493,6 +585,42 @@ void Filter::detachFilterFromRecord() { mDvr = nullptr; mDvr = nullptr; } } int Filter::createAvIonFd(int size) { // Create an ion fd and allocate an av fd mapped to a buffer to it. int ion_fd = ion_open(); if (ion_fd == -1) { ALOGE("[Filter] Failed to open ion fd %d", errno); return -1; } int av_fd = -1; ion_alloc_fd(dup(ion_fd), size, 0 /*align*/, ION_HEAP_SYSTEM_MASK, 0 /*flags*/, &av_fd); if (av_fd == -1) { ALOGE("[Filter] Failed to create av fd %d", errno); return -1; } return av_fd; } uint8_t* Filter::getIonBuffer(int fd, int size) { uint8_t* avBuf = static_cast<uint8_t*>( mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/)); if (avBuf == MAP_FAILED) { ALOGE("[Filter] fail to allocate buffer %d", errno); return NULL; } return avBuf; } native_handle_t* Filter::createNativeHandle(int fd) { // Create a native handle to pass the av fd via the callback event. native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0); if (nativeHandle == NULL) { ALOGE("[Filter] Failed to create native_handle %d", errno); return NULL; } nativeHandle->data[0] = dup(fd); return nativeHandle; } } // namespace implementation } // namespace implementation } // namespace V1_0 } // namespace V1_0 } // namespace tuner } // namespace tuner Loading
tv/tuner/1.0/default/Filter.h +12 −0 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <android/hardware/tv/tuner/1.0/IFilter.h> #include <android/hardware/tv/tuner/1.0/IFilter.h> #include <fmq/MessageQueue.h> #include <fmq/MessageQueue.h> #include <ion/ion.h> #include <math.h> #include <math.h> #include <set> #include <set> #include "Demux.h" #include "Demux.h" Loading Loading @@ -87,6 +88,7 @@ class Filter : public IFilter { Result startRecordFilterHandler(); Result startRecordFilterHandler(); void attachFilterToRecord(const sp<Dvr> dvr); void attachFilterToRecord(const sp<Dvr> dvr); void detachFilterFromRecord(); void detachFilterFromRecord(); void freeAvHandle(); private: private: // Tuner service // Tuner service Loading @@ -109,6 +111,7 @@ class Filter : public IFilter { vector<uint8_t> mFilterOutput; vector<uint8_t> mFilterOutput; vector<uint8_t> mRecordFilterOutput; vector<uint8_t> mRecordFilterOutput; unique_ptr<FilterMQ> mFilterMQ; unique_ptr<FilterMQ> mFilterMQ; bool mIsUsingFMQ = false; EventFlag* mFilterEventFlag; EventFlag* mFilterEventFlag; DemuxFilterEvent mFilterEvent; DemuxFilterEvent mFilterEvent; Loading Loading @@ -160,6 +163,10 @@ class Filter : public IFilter { static void* __threadLoopFilter(void* user); static void* __threadLoopFilter(void* user); void filterThreadLoop(); void filterThreadLoop(); int createAvIonFd(int size); uint8_t* getIonBuffer(int fd, int size); native_handle_t* createNativeHandle(int fd); /** /** * Lock to protect writes to the FMQs * Lock to protect writes to the FMQs */ */ Loading @@ -181,6 +188,11 @@ class Filter : public IFilter { // TODO handle mulptiple Pes filters // TODO handle mulptiple Pes filters int mPesSizeLeft = 0; int mPesSizeLeft = 0; vector<uint8_t> mPesOutput; vector<uint8_t> mPesOutput; // A map from data id to ion handle std::map<uint64_t, int> mDataId2Avfd; uint64_t mLastUsedDataId = 1; int mAvBufferCopyCount = 0; }; }; } // namespace implementation } // namespace implementation Loading
tv/tuner/1.0/default/Frontend.cpp +1 −4 Original line number Original line Diff line number Diff line Loading @@ -63,9 +63,6 @@ Return<Result> Frontend::tune(const FrontendSettings& /* settings */) { return Result::INVALID_STATE; return Result::INVALID_STATE; } } // TODO dynamically allocate file to the source file mSourceStreamFile = FRONTEND_STREAM_FILE; mCallback->onEvent(FrontendEventType::LOCKED); mCallback->onEvent(FrontendEventType::LOCKED); return Result::SUCCESS; return Result::SUCCESS; } } Loading Loading @@ -180,7 +177,7 @@ FrontendId Frontend::getFrontendId() { } } string Frontend::getSourceFile() { string Frontend::getSourceFile() { return mSourceStreamFile; return FRONTEND_STREAM_FILE; } } } // namespace implementation } // namespace implementation Loading
tv/tuner/1.0/default/Frontend.h +0 −1 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,6 @@ class Frontend : public IFrontend { FrontendId mId = 0; FrontendId mId = 0; const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts"; const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts"; string mSourceStreamFile; std::ifstream mFrontendData; std::ifstream mFrontendData; }; }; Loading