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