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