1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_MEDIA_SAMPLE_READER_NDK_H 18 #define ANDROID_MEDIA_SAMPLE_READER_NDK_H 19 20 #include <media/MediaSampleReader.h> 21 #include <media/NdkMediaExtractor.h> 22 23 #include <map> 24 #include <memory> 25 #include <mutex> 26 #include <vector> 27 28 namespace android { 29 30 /** 31 * MediaSampleReaderNDK is a concrete implementation of the MediaSampleReader interface based on the 32 * media NDK extractor. 33 */ 34 class MediaSampleReaderNDK : public MediaSampleReader { 35 public: 36 /** 37 * Creates a new MediaSampleReaderNDK instance wrapped in a shared pointer. 38 * @param fd Source file descriptor. The caller is responsible for closing the fd and it is safe 39 * to do so when this method returns. 40 * @param offset Source data offset. 41 * @param size Source data size. 42 * @return A shared pointer referencing the new MediaSampleReaderNDK instance on success, or an 43 * empty shared pointer if an error occurred. 44 */ 45 static std::shared_ptr<MediaSampleReader> createFromFd(int fd, size_t offset, size_t size); 46 47 AMediaFormat* getFileFormat() override; 48 size_t getTrackCount() const override; 49 AMediaFormat* getTrackFormat(int trackIndex) override; 50 media_status_t selectTrack(int trackIndex) override; 51 media_status_t unselectTrack(int trackIndex) override; 52 media_status_t setEnforceSequentialAccess(bool enforce) override; 53 media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) override; 54 media_status_t getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) override; 55 media_status_t readSampleDataForTrack(int trackIndex, uint8_t* buffer, 56 size_t bufferSize) override; 57 void advanceTrack(int trackIndex) override; 58 59 virtual ~MediaSampleReaderNDK() override; 60 61 private: 62 /** 63 * SamplePosition describes the position of a single sample in the media file using its 64 * timestamp and index in the file. 65 */ 66 struct SamplePosition { 67 uint64_t index = 0; 68 int64_t timeStampUs = 0; 69 bool isSet = false; 70 setSamplePosition71 void set(uint64_t sampleIndex, int64_t sampleTimeUs) { 72 index = sampleIndex; 73 timeStampUs = sampleTimeUs; 74 isSet = true; 75 } 76 resetSamplePosition77 void reset() { isSet = false; } 78 }; 79 80 /** 81 * SampleCursor keeps track of the sample position for a specific track. When the track is 82 * advanced, previous is set to current, current to next and next is reset. As the extractor 83 * advances over the combined timeline of tracks, it updates current and next for the track it 84 * points to if they are not already set. 85 */ 86 struct SampleCursor { 87 SamplePosition previous; 88 SamplePosition current; 89 SamplePosition next; 90 }; 91 92 /** 93 * Creates a new MediaSampleReaderNDK object from an AMediaExtractor. The extractor needs to be 94 * initialized with a valid data source before attempting to create a MediaSampleReaderNDK. 95 * @param extractor The initialized media extractor. 96 */ 97 MediaSampleReaderNDK(AMediaExtractor* extractor); 98 99 /** Advances the track to next sample. */ 100 void advanceTrack_l(int trackIndex); 101 102 /** Advances the extractor to next sample. */ 103 bool advanceExtractor_l(); 104 105 /** Moves the extractor backwards to the specified sample. */ 106 media_status_t seekExtractorBackwards_l(int64_t targetTimeUs, int targetTrackIndex, 107 uint64_t targetSampleIndex); 108 109 /** Moves the extractor to the specified sample. */ 110 media_status_t moveToSample_l(SamplePosition& pos, int trackIndex); 111 112 /** Moves the extractor to the next sample of the specified track. */ 113 media_status_t moveToTrack_l(int trackIndex); 114 115 /** In sequential mode, waits for the extractor to reach the next sample for the track. */ 116 media_status_t waitForTrack_l(int trackIndex, std::unique_lock<std::mutex>& lockHeld); 117 118 /** 119 * Ensures the extractor is ready for the next sample of the track regardless of access mode. 120 */ 121 media_status_t primeExtractorForTrack_l(int trackIndex, std::unique_lock<std::mutex>& lockHeld); 122 123 AMediaExtractor* mExtractor = nullptr; 124 std::mutex mExtractorMutex; 125 const size_t mTrackCount; 126 127 int mExtractorTrackIndex = -1; 128 uint64_t mExtractorSampleIndex = 0; 129 130 bool mEosReached = false; 131 bool mEnforceSequentialAccess = false; 132 133 // Maps selected track indices to condition variables for sequential sample access control. 134 std::map<int, std::condition_variable> mTrackSignals; 135 136 // Samples cursor for each track in the file. 137 std::vector<SampleCursor> mTrackCursors; 138 }; 139 140 } // namespace android 141 #endif // ANDROID_MEDIA_SAMPLE_READER_NDK_H 142