/* * Copyright (C) 2019 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_0_DVR_H_ #define ANDROID_HARDWARE_TV_TUNER_V1_0_DVR_H_ #include #include #include #include #include "Demux.h" #include "Frontend.h" #include "Tuner.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 ::android::hardware::tv::tuner::V1_0::IDemux; using ::android::hardware::tv::tuner::V1_0::IDvrCallback; using ::android::hardware::tv::tuner::V1_0::Result; using DvrMQ = MessageQueue; struct MediaEsMetaData { bool isAudio; int startIndex; int len; int pts; }; class Demux; class Filter; class Frontend; class Tuner; class Dvr : public IDvr { public: Dvr(); Dvr(DvrType type, uint32_t bufferSize, const sp& cb, sp demux); ~Dvr(); virtual Return getQueueDesc(getQueueDesc_cb _hidl_cb) override; virtual Return configure(const DvrSettings& settings) override; virtual Return attachFilter(const sp& filter) override; virtual Return detachFilter(const sp& filter) override; virtual Return start() override; virtual Return stop() override; virtual Return flush() override; virtual Return close() override; /** * To create a DvrMQ and its Event Flag. * * Return false is any of the above processes fails. */ bool createDvrMQ(); void sendBroadcastInputToDvrRecord(vector byteBuffer); bool writeRecordFMQ(const std::vector& data); bool addPlaybackFilter(uint32_t filterId, sp 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 sp mDemux; DvrType mType; uint32_t mBufferSize; sp mCallback; std::map> mFilters; 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, uint32_t highThreshold, uint32_t lowThreshold); RecordStatus checkRecordStatusChange(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 startTpidFilter(vector data); static void* __threadLoopPlayback(void* user); static void* __threadLoopRecord(void* user); void playbackThreadLoop(); void recordThreadLoop(); unique_ptr mDvrMQ; EventFlag* mDvrEventFlag; /** * Demux callbacks used on filter events or IO buffer status */ bool mDvrConfigured = false; DvrSettings mDvrSettings; // Thread handlers pthread_t mDvrThread; // FMQ status local records PlaybackStatus mPlaybackStatus; RecordStatus mRecordStatus; /** * If a specific filter's writing loop is still running */ bool mDvrThreadRunning; bool mKeepFetchingDataFromFrontend; /** * Lock to protect writes to the FMQs */ std::mutex mWriteLock; /** * Lock to protect writes to the input status */ std::mutex mPlaybackStatusLock; std::mutex mRecordStatusLock; std::mutex mDvrThreadLock; const bool DEBUG_DVR = false; // Booleans to check if recording is running. // Recording is ready when both of the following are set to true. bool mIsRecordStarted = false; }; } // namespace implementation } // namespace V1_0 } // namespace tuner } // namespace tv } // namespace hardware } // namespace android #endif // ANDROID_HARDWARE_TV_TUNER_V1_0_DVR_H_