| /* |
| * 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. |
| */ |
| |
| #ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_ |
| #define ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_ |
| |
| #include <android/hardware/tv/tuner/1.1/IFilter.h> |
| #include <android/hardware/tv/tuner/1.1/IFilterCallback.h> |
| #include <fmq/MessageQueue.h> |
| #include <inttypes.h> |
| #include <ion/ion.h> |
| #include <math.h> |
| #include <sys/stat.h> |
| #include <set> |
| #include "Demux.h" |
| #include "Dvr.h" |
| #include "Frontend.h" |
| |
| using namespace std; |
| |
| namespace android { |
| namespace hardware { |
| namespace tv { |
| namespace tuner { |
| namespace V1_0 { |
| namespace implementation { |
| |
| using ::android::hardware::EventFlag; |
| using ::android::hardware::kSynchronizedReadWrite; |
| using ::android::hardware::MessageQueue; |
| using ::android::hardware::MQDescriptorSync; |
| |
| using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>; |
| const uint32_t BUFFER_SIZE_16M = 0x1000000; |
| |
| class Demux; |
| class Dvr; |
| |
| class Filter : public V1_1::IFilter { |
| public: |
| Filter(); |
| |
| Filter(DemuxFilterType type, uint64_t filterId, uint32_t bufferSize, |
| const sp<IFilterCallback>& cb, sp<Demux> demux); |
| |
| ~Filter(); |
| |
| virtual Return<void> getId64Bit(getId64Bit_cb _hidl_cb) override; |
| |
| virtual Return<void> getId(getId_cb _hidl_cb) override; |
| |
| virtual Return<Result> setDataSource(const sp<V1_0::IFilter>& filter) override; |
| |
| virtual Return<void> getQueueDesc(getQueueDesc_cb _hidl_cb) override; |
| |
| virtual Return<Result> configure(const DemuxFilterSettings& settings) override; |
| |
| virtual Return<Result> start() override; |
| |
| virtual Return<Result> stop() override; |
| |
| virtual Return<Result> flush() override; |
| |
| virtual Return<Result> releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) override; |
| |
| virtual Return<Result> close() override; |
| |
| virtual Return<Result> configureIpCid(uint32_t ipCid) override; |
| |
| virtual Return<void> getAvSharedHandle(getAvSharedHandle_cb _hidl_cb) override; |
| |
| /** |
| * To create a FilterMQ and its Event Flag. |
| * |
| * Return false is any of the above processes fails. |
| */ |
| bool createFilterMQ(); |
| 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); |
| void detachFilterFromRecord(); |
| void freeAvHandle(); |
| void freeSharedAvHandle(); |
| bool isMediaFilter() { return mIsMediaFilter; }; |
| bool isPcrFilter() { return mIsPcrFilter; }; |
| bool isRecordFilter() { return mIsRecordFilter; }; |
| |
| private: |
| // Tuner service |
| sp<Demux> mDemux; |
| // Dvr reference once the filter is attached to any |
| sp<Dvr> mDvr = nullptr; |
| /** |
| * Filter callbacks used on filter events or FMQ status |
| */ |
| sp<IFilterCallback> mCallback = nullptr; |
| |
| /** |
| * V1_1 Filter callbacks used on filter events or FMQ status |
| */ |
| sp<V1_1::IFilterCallback> mCallback_1_1 = nullptr; |
| |
| uint64_t mFilterId; |
| uint32_t mCid = static_cast<uint32_t>(V1_1::Constant::INVALID_IP_FILTER_CONTEXT_ID); |
| uint32_t mBufferSize; |
| DemuxFilterType mType; |
| bool mIsMediaFilter = false; |
| bool mIsPcrFilter = false; |
| bool mIsRecordFilter = false; |
| DemuxFilterSettings mFilterSettings; |
| |
| uint16_t mTpid; |
| sp<V1_0::IFilter> mDataSource; |
| bool mIsDataSourceDemux = true; |
| vector<uint8_t> mFilterOutput; |
| vector<uint8_t> mRecordFilterOutput; |
| uint64_t mPts = 0; |
| unique_ptr<FilterMQ> mFilterMQ; |
| bool mIsUsingFMQ = false; |
| EventFlag* mFilterEventFlag; |
| DemuxFilterEvent mFilterEvent; |
| V1_1::DemuxFilterEventExt mFilterEventExt; |
| |
| // Thread handlers |
| pthread_t mFilterThread; |
| |
| // FMQ status local records |
| DemuxFilterStatus mFilterStatus; |
| /** |
| * If a specific filter's writing loop is still running |
| */ |
| bool mFilterThreadRunning; |
| bool mKeepFetchingDataFromFrontend; |
| |
| /** |
| * How many times a filter should write |
| * TODO make this dynamic/random/can take as a parameter |
| */ |
| const uint16_t SECTION_WRITE_COUNT = 10; |
| |
| bool DEBUG_FILTER = false; |
| |
| /** |
| * Filter handlers to handle the data filtering. |
| * They are also responsible to write the filtered output into the filter FMQ |
| * and update the filterEvent bound with the same filterId. |
| */ |
| Result startSectionFilterHandler(); |
| Result startPesFilterHandler(); |
| Result startTsFilterHandler(); |
| Result startMediaFilterHandler(); |
| Result startPcrFilterHandler(); |
| Result startTemiFilterHandler(); |
| Result startFilterLoop(); |
| |
| void deleteEventFlag(); |
| bool writeDataToFilterMQ(const std::vector<uint8_t>& data); |
| bool readDataFromMQ(); |
| bool writeSectionsAndCreateEvent(vector<uint8_t> data); |
| void maySendFilterStatusCallback(); |
| DemuxFilterStatus checkFilterStatusChange(uint32_t availableToWrite, uint32_t availableToRead, |
| uint32_t highThreshold, uint32_t lowThreshold); |
| /** |
| * A dispatcher to read and dispatch input data to all the started filters. |
| * Each filter handler handles the data filtering/output writing/filterEvent updating. |
| */ |
| void startTsFilter(vector<uint8_t> data); |
| bool startFilterDispatcher(); |
| static void* __threadLoopFilter(void* user); |
| void filterThreadLoop(); |
| |
| int createAvIonFd(int size); |
| uint8_t* getIonBuffer(int fd, int size); |
| native_handle_t* createNativeHandle(int fd); |
| Result createMediaFilterEventWithIon(vector<uint8_t> output); |
| Result createIndependentMediaEvents(vector<uint8_t> output); |
| Result createShareMemMediaEvents(vector<uint8_t> output); |
| bool sameFile(int fd1, int fd2); |
| |
| /** |
| * Lock to protect writes to the FMQs |
| */ |
| std::mutex mWriteLock; |
| /** |
| * Lock to protect writes to the filter event |
| */ |
| // TODO make each filter separate event lock |
| std::mutex mFilterEventLock; |
| /** |
| * Lock to protect writes to the input status |
| */ |
| std::mutex mFilterStatusLock; |
| std::mutex mFilterThreadLock; |
| std::mutex mFilterOutputLock; |
| std::mutex mRecordFilterOutputLock; |
| |
| // temp handle single PES filter |
| // TODO handle mulptiple Pes filters |
| int mPesSizeLeft = 0; |
| 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; |
| |
| // Shared A/V memory handle |
| hidl_handle mSharedAvMemHandle; |
| bool mUsingSharedAvMem = true; |
| uint32_t mSharedAvMemOffset = 0; |
| }; |
| |
| } // namespace implementation |
| } // namespace V1_0 |
| } // namespace tuner |
| } // namespace tv |
| } // namespace hardware |
| } // namespace android |
| |
| #endif // ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_ |