• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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