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 <memory>
     22 #include <vector>
     23 
     24 #include <gui/IGraphicBufferProducer.h>
     25 #include <media/hardware/CryptoAPI.h>
     26 #include <media/MediaCodecInfo.h>
     27 #include <media/MediaResource.h>
     28 #include <media/MediaAnalyticsItem.h>
     29 #include <media/stagefright/foundation/AHandler.h>
     30 #include <media/stagefright/FrameRenderTracker.h>
     31 #include <utils/Vector.h>
     32 
     33 namespace android {
     34 
     35 struct ABuffer;
     36 struct AMessage;
     37 struct AReplyToken;
     38 struct AString;
     39 class BufferChannelBase;
     40 struct CodecBase;
     41 class IBatteryStats;
     42 struct ICrypto;
     43 class MediaCodecBuffer;
     44 class IMemory;
     45 class IResourceManagerClient;
     46 class IResourceManagerService;
     47 struct PersistentSurface;
     48 class SoftwareRenderer;
     49 class Surface;
     50 namespace hardware {
     51 namespace cas {
     52 namespace native {
     53 namespace V1_0 {
     54 struct IDescrambler;
     55 }}}}
     56 using hardware::cas::native::V1_0::IDescrambler;
     57 
     58 struct MediaCodec : public AHandler {
     59     enum ConfigureFlags {
     60         CONFIGURE_FLAG_ENCODE   = 1,
     61     };
     62 
     63     enum BufferFlags {
     64         BUFFER_FLAG_SYNCFRAME     = 1,
     65         BUFFER_FLAG_CODECCONFIG   = 2,
     66         BUFFER_FLAG_EOS           = 4,
     67         BUFFER_FLAG_PARTIAL_FRAME = 8,
     68         BUFFER_FLAG_MUXER_DATA    = 16,
     69     };
     70 
     71     enum {
     72         CB_INPUT_AVAILABLE = 1,
     73         CB_OUTPUT_AVAILABLE = 2,
     74         CB_ERROR = 3,
     75         CB_OUTPUT_FORMAT_CHANGED = 4,
     76         CB_RESOURCE_RECLAIMED = 5,
     77     };
     78 
     79     static const pid_t kNoPid = -1;
     80     static const uid_t kNoUid = -1;
     81 
     82     static sp<MediaCodec> CreateByType(
     83             const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err = NULL,
     84             pid_t pid = kNoPid, uid_t uid = kNoUid);
     85 
     86     static sp<MediaCodec> CreateByComponentName(
     87             const sp<ALooper> &looper, const AString &name, status_t *err = NULL,
     88             pid_t pid = kNoPid, uid_t uid = kNoUid);
     89 
     90     static sp<PersistentSurface> CreatePersistentInputSurface();
     91 
     92     status_t configure(
     93             const sp<AMessage> &format,
     94             const sp<Surface> &nativeWindow,
     95             const sp<ICrypto> &crypto,
     96             uint32_t flags);
     97 
     98     status_t configure(
     99             const sp<AMessage> &format,
    100             const sp<Surface> &nativeWindow,
    101             const sp<ICrypto> &crypto,
    102             const sp<IDescrambler> &descrambler,
    103             uint32_t flags);
    104 
    105     status_t releaseCrypto();
    106 
    107     status_t setCallback(const sp<AMessage> &callback);
    108 
    109     status_t setOnFrameRenderedNotification(const sp<AMessage> &notify);
    110 
    111     status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
    112 
    113     status_t setInputSurface(const sp<PersistentSurface> &surface);
    114 
    115     status_t start();
    116 
    117     // Returns to a state in which the component remains allocated but
    118     // unconfigured.
    119     status_t stop();
    120 
    121     // Resets the codec to the INITIALIZED state.  Can be called after an error
    122     // has occured to make the codec usable.
    123     status_t reset();
    124 
    125     // Client MUST call release before releasing final reference to this
    126     // object.
    127     status_t release();
    128 
    129     status_t flush();
    130 
    131     status_t queueInputBuffer(
    132             size_t index,
    133             size_t offset,
    134             size_t size,
    135             int64_t presentationTimeUs,
    136             uint32_t flags,
    137             AString *errorDetailMsg = NULL);
    138 
    139     status_t queueSecureInputBuffer(
    140             size_t index,
    141             size_t offset,
    142             const CryptoPlugin::SubSample *subSamples,
    143             size_t numSubSamples,
    144             const uint8_t key[16],
    145             const uint8_t iv[16],
    146             CryptoPlugin::Mode mode,
    147             const CryptoPlugin::Pattern &pattern,
    148             int64_t presentationTimeUs,
    149             uint32_t flags,
    150             AString *errorDetailMsg = NULL);
    151 
    152     status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);
    153 
    154     status_t dequeueOutputBuffer(
    155             size_t *index,
    156             size_t *offset,
    157             size_t *size,
    158             int64_t *presentationTimeUs,
    159             uint32_t *flags,
    160             int64_t timeoutUs = 0ll);
    161 
    162     status_t renderOutputBufferAndRelease(size_t index, int64_t timestampNs);
    163     status_t renderOutputBufferAndRelease(size_t index);
    164     status_t releaseOutputBuffer(size_t index);
    165 
    166     status_t signalEndOfInputStream();
    167 
    168     status_t getOutputFormat(sp<AMessage> *format) const;
    169     status_t getInputFormat(sp<AMessage> *format) const;
    170 
    171     status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
    172     status_t getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
    173 
    174     status_t getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer);
    175     status_t getOutputFormat(size_t index, sp<AMessage> *format);
    176     status_t getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer);
    177 
    178     status_t setSurface(const sp<Surface> &nativeWindow);
    179 
    180     status_t requestIDRFrame();
    181 
    182     // Notification will be posted once there "is something to do", i.e.
    183     // an input/output buffer has become available, a format change is
    184     // pending, an error is pending.
    185     void requestActivityNotification(const sp<AMessage> &notify);
    186 
    187     status_t getName(AString *componentName) const;
    188 
    189     status_t getCodecInfo(sp<MediaCodecInfo> *codecInfo) const;
    190 
    191     status_t getMetrics(MediaAnalyticsItem * &reply);
    192 
    193     status_t setParameters(const sp<AMessage> &params);
    194 
    195     // Create a MediaCodec notification message from a list of rendered or dropped render infos
    196     // by adding rendered frame information to a base notification message. Returns the number
    197     // of frames that were rendered.
    198     static size_t CreateFramesRenderedMessage(
    199             const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg);
    200 
    201 protected:
    202     virtual ~MediaCodec();
    203     virtual void onMessageReceived(const sp<AMessage> &msg);
    204 
    205 private:
    206     // used by ResourceManagerClient
    207     status_t reclaim(bool force = false);
    208     friend struct ResourceManagerClient;
    209 
    210 private:
    211     enum State {
    212         UNINITIALIZED,
    213         INITIALIZING,
    214         INITIALIZED,
    215         CONFIGURING,
    216         CONFIGURED,
    217         STARTING,
    218         STARTED,
    219         FLUSHING,
    220         FLUSHED,
    221         STOPPING,
    222         RELEASING,
    223     };
    224     std::string stateString(State state);
    225 
    226     enum {
    227         kPortIndexInput         = 0,
    228         kPortIndexOutput        = 1,
    229     };
    230 
    231     enum {
    232         kWhatInit                           = 'init',
    233         kWhatConfigure                      = 'conf',
    234         kWhatSetSurface                     = 'sSur',
    235         kWhatCreateInputSurface             = 'cisf',
    236         kWhatSetInputSurface                = 'sisf',
    237         kWhatStart                          = 'strt',
    238         kWhatStop                           = 'stop',
    239         kWhatRelease                        = 'rele',
    240         kWhatDequeueInputBuffer             = 'deqI',
    241         kWhatQueueInputBuffer               = 'queI',
    242         kWhatDequeueOutputBuffer            = 'deqO',
    243         kWhatReleaseOutputBuffer            = 'relO',
    244         kWhatSignalEndOfInputStream         = 'eois',
    245         kWhatGetBuffers                     = 'getB',
    246         kWhatFlush                          = 'flus',
    247         kWhatGetOutputFormat                = 'getO',
    248         kWhatGetInputFormat                 = 'getI',
    249         kWhatDequeueInputTimedOut           = 'dITO',
    250         kWhatDequeueOutputTimedOut          = 'dOTO',
    251         kWhatCodecNotify                    = 'codc',
    252         kWhatRequestIDRFrame                = 'ridr',
    253         kWhatRequestActivityNotification    = 'racN',
    254         kWhatGetName                        = 'getN',
    255         kWhatGetCodecInfo                   = 'gCoI',
    256         kWhatSetParameters                  = 'setP',
    257         kWhatSetCallback                    = 'setC',
    258         kWhatSetNotification                = 'setN',
    259         kWhatDrmReleaseCrypto               = 'rDrm',
    260     };
    261 
    262     enum {
    263         kFlagUsesSoftwareRenderer       = 1,
    264         kFlagOutputFormatChanged        = 2,
    265         kFlagOutputBuffersChanged       = 4,
    266         kFlagStickyError                = 8,
    267         kFlagDequeueInputPending        = 16,
    268         kFlagDequeueOutputPending       = 32,
    269         kFlagIsSecure                   = 64,
    270         kFlagSawMediaServerDie          = 128,
    271         kFlagIsEncoder                  = 256,
    272         // 512 skipped
    273         kFlagIsAsync                    = 1024,
    274         kFlagIsComponentAllocated       = 2048,
    275         kFlagPushBlankBuffersOnShutdown = 4096,
    276     };
    277 
    278     struct BufferInfo {
    279         BufferInfo();
    280 
    281         sp<MediaCodecBuffer> mData;
    282         bool mOwnedByClient;
    283     };
    284 
    285     struct ResourceManagerServiceProxy : public IBinder::DeathRecipient {
    286         ResourceManagerServiceProxy(pid_t pid);
    287         ~ResourceManagerServiceProxy();
    288 
    289         void init();
    290 
    291         // implements DeathRecipient
    292         virtual void binderDied(const wp<IBinder>& /*who*/);
    293 
    294         void addResource(
    295                 int64_t clientId,
    296                 const sp<IResourceManagerClient> &client,
    297                 const Vector<MediaResource> &resources);
    298 
    299         void removeResource(int64_t clientId);
    300 
    301         bool reclaimResource(const Vector<MediaResource> &resources);
    302 
    303     private:
    304         Mutex mLock;
    305         sp<IResourceManagerService> mService;
    306         pid_t mPid;
    307     };
    308 
    309     State mState;
    310     uid_t mUid;
    311     bool mReleasedByResourceManager;
    312     sp<ALooper> mLooper;
    313     sp<ALooper> mCodecLooper;
    314     sp<CodecBase> mCodec;
    315     AString mComponentName;
    316     sp<MediaCodecInfo> mCodecInfo;
    317     sp<AReplyToken> mReplyID;
    318     uint32_t mFlags;
    319     status_t mStickyError;
    320     sp<Surface> mSurface;
    321     SoftwareRenderer *mSoftRenderer;
    322 
    323     MediaAnalyticsItem *mAnalyticsItem;
    324     void initAnalyticsItem();
    325     void updateAnalyticsItem();
    326     void flushAnalyticsItem();
    327     void updateEphemeralAnalytics(MediaAnalyticsItem *item);
    328 
    329     sp<AMessage> mOutputFormat;
    330     sp<AMessage> mInputFormat;
    331     sp<AMessage> mCallback;
    332     sp<AMessage> mOnFrameRenderedNotification;
    333 
    334     sp<IResourceManagerClient> mResourceManagerClient;
    335     sp<ResourceManagerServiceProxy> mResourceManagerService;
    336 
    337     bool mBatteryStatNotified;
    338     bool mIsVideo;
    339     int32_t mVideoWidth;
    340     int32_t mVideoHeight;
    341     int32_t mRotationDegrees;
    342 
    343     // initial create parameters
    344     AString mInitName;
    345 
    346     // configure parameter
    347     sp<AMessage> mConfigureMsg;
    348 
    349     // Used only to synchronize asynchronous getBufferAndFormat
    350     // across all the other (synchronous) buffer state change
    351     // operations, such as de/queueIn/OutputBuffer, start and
    352     // stop/flush/reset/release.
    353     Mutex mBufferLock;
    354 
    355     List<size_t> mAvailPortBuffers[2];
    356     std::vector<BufferInfo> mPortBuffers[2];
    357 
    358     int32_t mDequeueInputTimeoutGeneration;
    359     sp<AReplyToken> mDequeueInputReplyID;
    360 
    361     int32_t mDequeueOutputTimeoutGeneration;
    362     sp<AReplyToken> mDequeueOutputReplyID;
    363 
    364     sp<ICrypto> mCrypto;
    365 
    366     sp<IDescrambler> mDescrambler;
    367 
    368     List<sp<ABuffer> > mCSD;
    369 
    370     sp<AMessage> mActivityNotify;
    371 
    372     bool mHaveInputSurface;
    373     bool mHavePendingInputBuffers;
    374     bool mCpuBoostRequested;
    375 
    376     std::shared_ptr<BufferChannelBase> mBufferChannel;
    377 
    378     MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
    379 
    380     static sp<CodecBase> GetCodecBase(const AString &name);
    381 
    382     static status_t PostAndAwaitResponse(
    383             const sp<AMessage> &msg, sp<AMessage> *response);
    384 
    385     void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
    386 
    387     status_t init(const AString &name);
    388 
    389     void setState(State newState);
    390     void returnBuffersToCodec(bool isReclaim = false);
    391     void returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim = false);
    392     size_t updateBuffers(int32_t portIndex, const sp<AMessage> &msg);
    393     status_t onQueueInputBuffer(const sp<AMessage> &msg);
    394     status_t onReleaseOutputBuffer(const sp<AMessage> &msg);
    395     ssize_t dequeuePortBuffer(int32_t portIndex);
    396 
    397     status_t getBufferAndFormat(
    398             size_t portIndex, size_t index,
    399             sp<MediaCodecBuffer> *buffer, sp<AMessage> *format);
    400 
    401     bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
    402     bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
    403     void cancelPendingDequeueOperations();
    404 
    405     void extractCSD(const sp<AMessage> &format);
    406     status_t queueCSDInputBuffer(size_t bufferIndex);
    407 
    408     status_t handleSetSurface(const sp<Surface> &surface);
    409     status_t connectToSurface(const sp<Surface> &surface);
    410     status_t disconnectFromSurface();
    411 
    412     bool hasCryptoOrDescrambler() {
    413         return mCrypto != NULL || mDescrambler != NULL;
    414     }
    415 
    416     void postActivityNotificationIfPossible();
    417 
    418     void onInputBufferAvailable();
    419     void onOutputBufferAvailable();
    420     void onError(status_t err, int32_t actionCode, const char *detail = NULL);
    421     void onOutputFormatChanged();
    422 
    423     status_t onSetParameters(const sp<AMessage> &params);
    424 
    425     status_t amendOutputFormatWithCodecSpecificData(const sp<MediaCodecBuffer> &buffer);
    426     void updateBatteryStat();
    427     bool isExecuting() const;
    428 
    429     uint64_t getGraphicBufferSize();
    430     void addResource(MediaResource::Type type, MediaResource::SubType subtype, uint64_t value);
    431     void requestCpuBoostIfNeeded();
    432 
    433     bool hasPendingBuffer(int portIndex);
    434     bool hasPendingBuffer();
    435 
    436     /* called to get the last codec error when the sticky flag is set.
    437      * if no such codec error is found, returns UNKNOWN_ERROR.
    438      */
    439     inline status_t getStickyError() const {
    440         return mStickyError != 0 ? mStickyError : UNKNOWN_ERROR;
    441     }
    442 
    443     inline void setStickyError(status_t err) {
    444         mFlags |= kFlagStickyError;
    445         mStickyError = err;
    446     }
    447 
    448     void onReleaseCrypto(const sp<AMessage>& msg);
    449 
    450     // managing time-of-flight aka latency
    451     typedef struct {
    452             int64_t presentationUs;
    453             int64_t startedNs;
    454     } BufferFlightTiming_t;
    455     std::deque<BufferFlightTiming_t> mBuffersInFlight;
    456     Mutex mLatencyLock;
    457     int64_t mLatencyUnknown;    // buffers for which we couldn't calculate latency
    458 
    459     void statsBufferSent(int64_t presentationUs);
    460     void statsBufferReceived(int64_t presentationUs);
    461 
    462     enum {
    463         // the default shape of our latency histogram buckets
    464         // XXX: should these be configurable in some way?
    465         kLatencyHistBuckets = 20,
    466         kLatencyHistWidth = 2000,
    467         kLatencyHistFloor = 2000,
    468 
    469         // how many samples are in the 'recent latency' histogram
    470         // 300 frames = 5 sec @ 60fps or ~12 sec @ 24fps
    471         kRecentLatencyFrames = 300,
    472 
    473         // how we initialize mRecentSamples
    474         kRecentSampleInvalid = -1,
    475     };
    476 
    477     int64_t mRecentSamples[kRecentLatencyFrames];
    478     int mRecentHead;
    479     Mutex mRecentLock;
    480 
    481     class Histogram {
    482       public:
    483         Histogram() : mFloor(0), mWidth(0), mBelow(0), mAbove(0),
    484                       mMin(INT64_MAX), mMax(INT64_MIN), mSum(0), mCount(0),
    485                       mBucketCount(0), mBuckets(NULL) {};
    486         ~Histogram() { clear(); };
    487         void clear() { if (mBuckets != NULL) free(mBuckets); mBuckets = NULL; };
    488         bool setup(int nbuckets, int64_t width, int64_t floor = 0);
    489         void insert(int64_t sample);
    490         int64_t getMin() const { return mMin; }
    491         int64_t getMax() const { return mMax; }
    492         int64_t getCount() const { return mCount; }
    493         int64_t getSum() const { return mSum; }
    494         int64_t getAvg() const { return mSum / (mCount == 0 ? 1 : mCount); }
    495         std::string emit();
    496       private:
    497         int64_t mFloor, mCeiling, mWidth;
    498         int64_t mBelow, mAbove;
    499         int64_t mMin, mMax, mSum, mCount;
    500 
    501         int mBucketCount;
    502         int64_t *mBuckets;
    503     };
    504 
    505     Histogram mLatencyHist;
    506 
    507     DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
    508 };
    509 
    510 }  // namespace android
    511 
    512 #endif  // MEDIA_CODEC_H_
    513