MediaCodec.h revision 1dcdfead2971c1fa7c02f24ba86f706890c9f99e
1/*
2 * Copyright 2012, 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 MEDIA_CODEC_H_
18
19#define MEDIA_CODEC_H_
20
21#include <gui/IGraphicBufferProducer.h>
22#include <media/hardware/CryptoAPI.h>
23#include <media/MediaResource.h>
24#include <media/stagefright/foundation/AHandler.h>
25#include <utils/Vector.h>
26
27namespace android {
28
29struct ABuffer;
30struct AMessage;
31struct AReplyToken;
32struct AString;
33struct CodecBase;
34struct IBatteryStats;
35struct ICrypto;
36class IMemory;
37struct MemoryDealer;
38class IResourceManagerClient;
39class IResourceManagerService;
40struct SoftwareRenderer;
41struct Surface;
42
43struct MediaCodec : public AHandler {
44    enum ConfigureFlags {
45        CONFIGURE_FLAG_ENCODE   = 1,
46    };
47
48    enum BufferFlags {
49        BUFFER_FLAG_SYNCFRAME   = 1,
50        BUFFER_FLAG_CODECCONFIG = 2,
51        BUFFER_FLAG_EOS         = 4,
52    };
53
54    enum {
55        CB_INPUT_AVAILABLE = 1,
56        CB_OUTPUT_AVAILABLE = 2,
57        CB_ERROR = 3,
58        CB_OUTPUT_FORMAT_CHANGED = 4,
59        CB_RESOURCE_RECLAIMED = 5,
60    };
61
62    struct BatteryNotifier;
63
64    static sp<MediaCodec> CreateByType(
65            const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err = NULL);
66
67    static sp<MediaCodec> CreateByComponentName(
68            const sp<ALooper> &looper, const char *name, status_t *err = NULL);
69
70    status_t configure(
71            const sp<AMessage> &format,
72            const sp<Surface> &nativeWindow,
73            const sp<ICrypto> &crypto,
74            uint32_t flags);
75
76    status_t setCallback(const sp<AMessage> &callback);
77
78    status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
79
80    status_t start();
81
82    // Returns to a state in which the component remains allocated but
83    // unconfigured.
84    status_t stop();
85
86    // Resets the codec to the INITIALIZED state.  Can be called after an error
87    // has occured to make the codec usable.
88    status_t reset();
89
90    // Client MUST call release before releasing final reference to this
91    // object.
92    status_t release();
93
94    status_t flush();
95
96    status_t queueInputBuffer(
97            size_t index,
98            size_t offset,
99            size_t size,
100            int64_t presentationTimeUs,
101            uint32_t flags,
102            AString *errorDetailMsg = NULL);
103
104    status_t queueSecureInputBuffer(
105            size_t index,
106            size_t offset,
107            const CryptoPlugin::SubSample *subSamples,
108            size_t numSubSamples,
109            const uint8_t key[16],
110            const uint8_t iv[16],
111            CryptoPlugin::Mode mode,
112            int64_t presentationTimeUs,
113            uint32_t flags,
114            AString *errorDetailMsg = NULL);
115
116    status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);
117
118    status_t dequeueOutputBuffer(
119            size_t *index,
120            size_t *offset,
121            size_t *size,
122            int64_t *presentationTimeUs,
123            uint32_t *flags,
124            int64_t timeoutUs = 0ll);
125
126    status_t renderOutputBufferAndRelease(size_t index, int64_t timestampNs);
127    status_t renderOutputBufferAndRelease(size_t index);
128    status_t releaseOutputBuffer(size_t index);
129
130    status_t signalEndOfInputStream();
131
132    status_t getOutputFormat(sp<AMessage> *format) const;
133    status_t getInputFormat(sp<AMessage> *format) const;
134
135    status_t getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const;
136
137    status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const;
138    status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const;
139
140    status_t getOutputBuffer(size_t index, sp<ABuffer> *buffer);
141    status_t getOutputFormat(size_t index, sp<AMessage> *format);
142    status_t getInputBuffer(size_t index, sp<ABuffer> *buffer);
143
144    status_t setSurface(const sp<Surface> &nativeWindow);
145
146    status_t requestIDRFrame();
147
148    // Notification will be posted once there "is something to do", i.e.
149    // an input/output buffer has become available, a format change is
150    // pending, an error is pending.
151    void requestActivityNotification(const sp<AMessage> &notify);
152
153    status_t getName(AString *componentName) const;
154
155    status_t setParameters(const sp<AMessage> &params);
156
157protected:
158    virtual ~MediaCodec();
159    virtual void onMessageReceived(const sp<AMessage> &msg);
160
161private:
162    enum State {
163        UNINITIALIZED,
164        INITIALIZING,
165        INITIALIZED,
166        CONFIGURING,
167        CONFIGURED,
168        STARTING,
169        STARTED,
170        FLUSHING,
171        FLUSHED,
172        STOPPING,
173        RELEASING,
174    };
175
176    enum {
177        kPortIndexInput         = 0,
178        kPortIndexOutput        = 1,
179    };
180
181    enum {
182        kWhatInit                           = 'init',
183        kWhatConfigure                      = 'conf',
184        kWhatSetSurface                     = 'sSur',
185        kWhatCreateInputSurface             = 'cisf',
186        kWhatStart                          = 'strt',
187        kWhatStop                           = 'stop',
188        kWhatRelease                        = 'rele',
189        kWhatDequeueInputBuffer             = 'deqI',
190        kWhatQueueInputBuffer               = 'queI',
191        kWhatDequeueOutputBuffer            = 'deqO',
192        kWhatReleaseOutputBuffer            = 'relO',
193        kWhatSignalEndOfInputStream         = 'eois',
194        kWhatGetBuffers                     = 'getB',
195        kWhatFlush                          = 'flus',
196        kWhatGetOutputFormat                = 'getO',
197        kWhatGetInputFormat                 = 'getI',
198        kWhatDequeueInputTimedOut           = 'dITO',
199        kWhatDequeueOutputTimedOut          = 'dOTO',
200        kWhatCodecNotify                    = 'codc',
201        kWhatRequestIDRFrame                = 'ridr',
202        kWhatRequestActivityNotification    = 'racN',
203        kWhatGetName                        = 'getN',
204        kWhatSetParameters                  = 'setP',
205        kWhatSetCallback                    = 'setC',
206    };
207
208    enum {
209        kFlagUsesSoftwareRenderer       = 1,
210        kFlagOutputFormatChanged        = 2,
211        kFlagOutputBuffersChanged       = 4,
212        kFlagStickyError                = 8,
213        kFlagDequeueInputPending        = 16,
214        kFlagDequeueOutputPending       = 32,
215        kFlagIsSecure                   = 64,
216        kFlagSawMediaServerDie          = 128,
217        kFlagIsEncoder                  = 256,
218        kFlagGatherCodecSpecificData    = 512,
219        kFlagIsAsync                    = 1024,
220        kFlagIsComponentAllocated       = 2048,
221    };
222
223    struct BufferInfo {
224        uint32_t mBufferID;
225        sp<ABuffer> mData;
226        sp<ABuffer> mEncryptedData;
227        sp<IMemory> mSharedEncryptedBuffer;
228        sp<AMessage> mNotify;
229        sp<AMessage> mFormat;
230        bool mOwnedByClient;
231    };
232
233    struct ResourceManagerServiceProxy : public IBinder::DeathRecipient {
234        ResourceManagerServiceProxy();
235        ~ResourceManagerServiceProxy();
236
237        void init();
238
239        // implements DeathRecipient
240        virtual void binderDied(const wp<IBinder>& /*who*/);
241
242        void addResource(
243                int pid,
244                int64_t clientId,
245                const sp<IResourceManagerClient> client,
246                const Vector<MediaResource> &resources);
247
248        void removeResource(int64_t clientId);
249
250        bool reclaimResource(int callingPid, const Vector<MediaResource> &resources);
251
252    private:
253        Mutex mLock;
254        sp<IResourceManagerService> mService;
255    };
256
257    State mState;
258    sp<ALooper> mLooper;
259    sp<ALooper> mCodecLooper;
260    sp<CodecBase> mCodec;
261    AString mComponentName;
262    sp<AReplyToken> mReplyID;
263    uint32_t mFlags;
264    status_t mStickyError;
265    sp<Surface> mSurface;
266    SoftwareRenderer *mSoftRenderer;
267    sp<AMessage> mOutputFormat;
268    sp<AMessage> mInputFormat;
269    sp<AMessage> mCallback;
270    sp<MemoryDealer> mDealer;
271
272    sp<IResourceManagerClient> mResourceManagerClient;
273    sp<ResourceManagerServiceProxy> mResourceManagerService;
274
275    bool mBatteryStatNotified;
276    bool mIsVideo;
277    int32_t mVideoWidth;
278    int32_t mVideoHeight;
279
280    // initial create parameters
281    AString mInitName;
282    bool mInitNameIsType;
283    bool mInitIsEncoder;
284
285    // configure parameter
286    sp<AMessage> mConfigureMsg;
287
288    // Used only to synchronize asynchronous getBufferAndFormat
289    // across all the other (synchronous) buffer state change
290    // operations, such as de/queueIn/OutputBuffer, start and
291    // stop/flush/reset/release.
292    Mutex mBufferLock;
293
294    List<size_t> mAvailPortBuffers[2];
295    Vector<BufferInfo> mPortBuffers[2];
296
297    int32_t mDequeueInputTimeoutGeneration;
298    sp<AReplyToken> mDequeueInputReplyID;
299
300    int32_t mDequeueOutputTimeoutGeneration;
301    sp<AReplyToken> mDequeueOutputReplyID;
302
303    sp<ICrypto> mCrypto;
304
305    List<sp<ABuffer> > mCSD;
306
307    sp<AMessage> mActivityNotify;
308
309    bool mHaveInputSurface;
310    bool mHavePendingInputBuffers;
311
312    MediaCodec(const sp<ALooper> &looper);
313
314    static status_t PostAndAwaitResponse(
315            const sp<AMessage> &msg, sp<AMessage> *response);
316
317    static void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
318
319    status_t init(const AString &name, bool nameIsType, bool encoder);
320
321    void setState(State newState);
322    void returnBuffersToCodec();
323    void returnBuffersToCodecOnPort(int32_t portIndex);
324    size_t updateBuffers(int32_t portIndex, const sp<AMessage> &msg);
325    status_t onQueueInputBuffer(const sp<AMessage> &msg);
326    status_t onReleaseOutputBuffer(const sp<AMessage> &msg);
327    ssize_t dequeuePortBuffer(int32_t portIndex);
328
329    status_t getBufferAndFormat(
330            size_t portIndex, size_t index,
331            sp<ABuffer> *buffer, sp<AMessage> *format);
332
333    bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
334    bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
335    void cancelPendingDequeueOperations();
336
337    void extractCSD(const sp<AMessage> &format);
338    status_t queueCSDInputBuffer(size_t bufferIndex);
339
340    status_t handleSetSurface(const sp<Surface> &surface);
341    status_t connectToSurface(const sp<Surface> &surface);
342    status_t disconnectFromSurface();
343
344    void postActivityNotificationIfPossible();
345
346    void onInputBufferAvailable();
347    void onOutputBufferAvailable();
348    void onError(status_t err, int32_t actionCode, const char *detail = NULL);
349    void onOutputFormatChanged();
350
351    status_t onSetParameters(const sp<AMessage> &params);
352
353    status_t amendOutputFormatWithCodecSpecificData(const sp<ABuffer> &buffer);
354    void updateBatteryStat();
355    bool isExecuting() const;
356
357    uint64_t getGraphicBufferSize();
358    void addResource(const String8 &type, const String8 &subtype, uint64_t value);
359
360    /* called to get the last codec error when the sticky flag is set.
361     * if no such codec error is found, returns UNKNOWN_ERROR.
362     */
363    inline status_t getStickyError() const {
364        return mStickyError != 0 ? mStickyError : UNKNOWN_ERROR;
365    }
366
367    inline void setStickyError(status_t err) {
368        mFlags |= kFlagStickyError;
369        mStickyError = err;
370    }
371
372    DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
373};
374
375}  // namespace android
376
377#endif  // MEDIA_CODEC_H_
378