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/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     static const size_t kBinderMediaBuffers = 4; // buffers managed by BnMediaSource
128     static const size_t kTransferSharedAsSharedThreshold = 4 * 1024;  // if >= shared, else inline
129     static const size_t kTransferInlineAsSharedThreshold = 64 * 1024; // if >= shared, else inline
130     static const size_t kInlineMaxTransfer = 256 * 1024; // Binder size limited to BINDER_VM_SIZE.
131 
132 protected:
133     virtual ~BnMediaSource();
134 
135 private:
136     uint32_t mBuffersSinceStop; // Buffer tracking variable
137 
138     std::unique_ptr<MediaBufferGroup> mGroup;
139 
140     // To prevent marshalling IMemory with each read transaction, we cache the IMemory pointer
141     // into a map.
142     //
143     // This is converted into an index, which is used to identify the associated memory
144     // on the receiving side.  We hold a reference to the IMemory here to ensure it doesn't
145     // change underneath us.
146 
147     struct IndexCache {
IndexCacheIndexCache148         IndexCache() : mIndex(0) { }
149 
150         // Returns the index of the IMemory stored in cache or 0 if not found.
lookupIndexCache151         uint64_t lookup(const sp<IMemory> &mem) {
152             auto p = mMemoryToIndex.find(mem.get());
153             if (p == mMemoryToIndex.end()) {
154                 return 0;
155             }
156             if (MediaBuffer::isDeadObject(p->second.first)) {
157                 // this object's dead
158                 ALOGW("Attempting to lookup a dead IMemory");
159                 (void)mMemoryToIndex.erase(p);
160                 return 0;
161             }
162             ALOGW_IF(p->second.first.get() != mem.get(), "Mismatched buffers without reset");
163             return p->second.second;
164         }
165 
166         // Returns the index of the IMemory stored in the index cache.
insertIndexCache167         uint64_t insert(const sp<IMemory> &mem) {
168             auto p = mMemoryToIndex.find(mem.get());
169             if (p == mMemoryToIndex.end()) {
170                 if (mIndex == UINT64_MAX) {
171                     ALOGE("Index overflow");
172                     mIndex = 1; // skip overflow condition and hope for the best
173                 } else {
174                     ++mIndex;
175                 }
176                 (void)mMemoryToIndex.emplace(// C++11 mem.get(), std::make_pair(mem, mIndex))
177                         std::piecewise_construct,
178                         std::forward_as_tuple(mem.get()), std::forward_as_tuple(mem, mIndex));
179                 return mIndex;
180             }
181             ALOGW("IMemory already inserted into cache");
182             return p->second.second;
183         }
184 
resetIndexCache185         void reset() {
186             mMemoryToIndex.clear();
187             mIndex = 0;
188         }
189 
gcIndexCache190         void gc() {
191             for (auto it = mMemoryToIndex.begin(); it != mMemoryToIndex.end(); ) {
192                 if (MediaBuffer::isDeadObject(it->second.first)) {
193                     it = mMemoryToIndex.erase(it);
194                 } else {
195                     ++it;
196                 }
197             }
198         }
199 
200     private:
201         uint64_t mIndex;
202         // C++14 unordered_map erase on iterator is stable; C++11 has no guarantee.
203         // Could key on uintptr_t instead of IMemory *
204         std::map<IMemory *, std::pair<sp<IMemory>, uint64_t>> mMemoryToIndex;
205     } mIndexCache;
206 };
207 
208 }  // namespace android
209 
210 #endif  // IMEDIA_SOURCE_BASE_H_
211