• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 IMEDIA_SOURCE_BASE_H_
18 
19 #define IMEDIA_SOURCE_BASE_H_
20 
21 #include <map>
22 
23 #include <binder/IInterface.h>
24 #include <binder/IMemory.h>
25 #include <media/stagefright/MediaSource.h>
26 #include <media/stagefright/MediaBuffer.h>
27 #include <media/stagefright/MediaErrors.h>
28 
29 namespace android {
30 
31 class MediaBufferGroup;
32 
33 class IMediaSource : public IInterface {
34 public:
35     DECLARE_META_INTERFACE(MediaSource);
36 
37     enum {
38         // Maximum number of buffers would be read in readMultiple.
39         kMaxNumReadMultiple = 128,
40     };
41 
42     // To be called before any other methods on this object, except
43     // getFormat().
44     virtual status_t start(MetaData *params = NULL) = 0;
45 
46     // Any blocking read call returns immediately with a result of NO_INIT.
47     // It is an error to call any methods other than start after this call
48     // returns. Any buffers the object may be holding onto at the time of
49     // the stop() call are released.
50     // Also, it is imperative that any buffers output by this object and
51     // held onto by callers be released before a call to stop() !!!
52     virtual status_t stop() = 0;
53 
54     // Returns the format of the data output by this media source.
55     virtual sp<MetaData> getFormat() = 0;
56 
57     // Returns a new buffer of data. Call blocks until a
58     // buffer is available, an error is encountered or the end of the stream
59     // is reached.
60     // End of stream is signalled by a result of ERROR_END_OF_STREAM.
61     // A result of INFO_FORMAT_CHANGED indicates that the format of this
62     // MediaSource has changed mid-stream, the client can continue reading
63     // but should be prepared for buffers of the new configuration.
64     //
65     // TODO: consider removing read() in favor of readMultiple().
66     virtual status_t read(
67             MediaBufferBase **buffer,
68             const MediaSource::ReadOptions *options = NULL) = 0;
69 
70     // Returns a vector of new buffers of data, where the new buffers are added
71     // to the end of the vector.
72     // Call blocks until an error is encountered, or the end of the stream is
73     // reached, or format change is hit, or |kMaxNumReadMultiple| buffers have
74     // been read.
75     // End of stream is signaled by a result of ERROR_END_OF_STREAM.
76     // A result of INFO_FORMAT_CHANGED indicates that the format of this
77     // MediaSource has changed mid-stream, the client can continue reading
78     // but should be prepared for buffers of the new configuration.
79     //
80     // ReadOptions may be specified. Persistent options apply to all reads;
81     // non-persistent options (e.g. seek) apply only to the first read.
82     virtual status_t readMultiple(
83             Vector<MediaBufferBase *> *buffers, uint32_t maxNumBuffers = 1,
84             const MediaSource::ReadOptions *options = nullptr) = 0;
85 
86     // Returns true if |readMultiple| is supported, otherwise false.
87     virtual bool supportReadMultiple() = 0;
88 
89     // Returns true if |read| supports nonblocking option, otherwise false.
90     // |readMultiple| if supported, always allows the nonblocking option.
91     virtual bool supportNonblockingRead() = 0;
92 
93     // Causes this source to suspend pulling data from its upstream source
94     // until a subsequent read-with-seek. Currently only supported by
95     // OMXCodec.
96     virtual status_t pause()  = 0;
97 };
98 
99 class BnMediaSource: public BnInterface<IMediaSource>
100 {
101 public:
102     BnMediaSource();
103 
104     virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
105                                 uint32_t flags = 0);
106 
pause()107     virtual status_t pause() {
108         return ERROR_UNSUPPORTED;
109     }
110 
111     // TODO: Implement this for local media sources.
readMultiple(Vector<MediaBufferBase * > *,uint32_t,const MediaSource::ReadOptions *)112     virtual status_t readMultiple(
113             Vector<MediaBufferBase *> * /* buffers */, uint32_t /* maxNumBuffers = 1 */,
114             const MediaSource::ReadOptions * /* options = nullptr */) {
115         return ERROR_UNSUPPORTED;
116     }
117 
supportReadMultiple()118     virtual bool supportReadMultiple() {
119         return false;
120     }
121 
122     // Override in source if nonblocking reads are supported.
supportNonblockingRead()123     virtual bool supportNonblockingRead() {
124         return false;
125     }
126 
127     // align buffer count with video request size in NuMediaExtractor::selectTrack()
128     static const size_t kBinderMediaBuffers = 8; // buffers managed by BnMediaSource
129     static const size_t kTransferSharedAsSharedThreshold = 4 * 1024;  // if >= shared, else inline
130     static const size_t kTransferInlineAsSharedThreshold = 8 * 1024; // if >= shared, else inline
131     static const size_t kInlineMaxTransfer = 64 * 1024; // Binder size limited to BINDER_VM_SIZE.
132 
133 protected:
134     virtual ~BnMediaSource();
135 
136 private:
137     uint32_t mBuffersSinceStop; // Buffer tracking variable
138     Mutex mBnLock; // to guard readMultiple against concurrent access to the buffer cache
139 
140     std::unique_ptr<MediaBufferGroup> mGroup;
141 
142     // To prevent marshalling IMemory with each read transaction, we cache the IMemory pointer
143     // into a map.
144     //
145     // This is converted into an index, which is used to identify the associated memory
146     // on the receiving side.  We hold a reference to the IMemory here to ensure it doesn't
147     // change underneath us.
148 
149     struct IndexCache {
IndexCacheIndexCache150         IndexCache() : mIndex(0) { }
151 
152         // Returns the index of the IMemory stored in cache or 0 if not found.
lookupIndexCache153         uint64_t lookup(const sp<IMemory> &mem) {
154             auto p = mMemoryToIndex.find(mem.get());
155             if (p == mMemoryToIndex.end()) {
156                 return 0;
157             }
158             if (MediaBuffer::isDeadObject(p->second.first)) {
159                 // this object's dead
160                 ALOGW("Attempting to lookup a dead IMemory");
161                 (void)mMemoryToIndex.erase(p);
162                 return 0;
163             }
164             ALOGW_IF(p->second.first.get() != mem.get(), "Mismatched buffers without reset");
165             return p->second.second;
166         }
167 
168         // Returns the index of the IMemory stored in the index cache.
insertIndexCache169         uint64_t insert(const sp<IMemory> &mem) {
170             auto p = mMemoryToIndex.find(mem.get());
171             if (p == mMemoryToIndex.end()) {
172                 if (mIndex == UINT64_MAX) {
173                     ALOGE("Index overflow");
174                     mIndex = 1; // skip overflow condition and hope for the best
175                 } else {
176                     ++mIndex;
177                 }
178                 (void)mMemoryToIndex.emplace(// C++11 mem.get(), std::make_pair(mem, mIndex))
179                         std::piecewise_construct,
180                         std::forward_as_tuple(mem.get()), std::forward_as_tuple(mem, mIndex));
181                 return mIndex;
182             }
183             ALOGW("IMemory already inserted into cache");
184             return p->second.second;
185         }
186 
resetIndexCache187         void reset() {
188             mMemoryToIndex.clear();
189             mIndex = 0;
190         }
191 
gcIndexCache192         void gc() {
193             for (auto it = mMemoryToIndex.begin(); it != mMemoryToIndex.end(); ) {
194                 if (MediaBuffer::isDeadObject(it->second.first)) {
195                     it = mMemoryToIndex.erase(it);
196                 } else {
197                     ++it;
198                 }
199             }
200         }
201 
202     private:
203         uint64_t mIndex;
204         // C++14 unordered_map erase on iterator is stable; C++11 has no guarantee.
205         // Could key on uintptr_t instead of IMemory *
206         std::map<IMemory *, std::pair<sp<IMemory>, uint64_t>> mMemoryToIndex;
207     } mIndexCache;
208 };
209 
210 }  // namespace android
211 
212 #endif  // IMEDIA_SOURCE_BASE_H_
213