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