Home | History | Annotate | Download | only in libmediandkjni
      1 /*
      2  * Copyright (C) 2017 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 _NATIVE_MEDIA_UTILS_H_
     18 #define _NATIVE_MEDIA_UTILS_H_
     19 
     20 #include <pthread.h>
     21 #include <sys/cdefs.h>
     22 #include <stddef.h>
     23 #include <assert.h>
     24 #include <vector>
     25 
     26 #include <android/native_window_jni.h>
     27 
     28 #include "media/NdkMediaFormat.h"
     29 #include "media/NdkMediaExtractor.h"
     30 #include "media/NdkMediaCodec.h"
     31 #include "media/NdkMediaMuxer.h"
     32 
     33 namespace Utils {
     34 
     35 // constants not defined in NDK api
     36 extern const char * TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME;
     37 extern const char * TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE;
     38 static const uint32_t TBD_AMEDIACODEC_BUFFER_FLAG_KEY_FRAME = 0x1;
     39 
     40 extern const char * TBD_AMEDIAFORMAT_KEY_BIT_RATE_MODE;
     41 static const int32_t kBitrateModeConstant = 2;
     42 static const int32_t kColorFormatSurface = 0x7f000789;
     43 
     44 // tolerances
     45 static const float kBitrateDeviationPercentMax = 10.0;
     46 static const int32_t kSyncFrameDeviationFramesMax = 5;
     47 
     48 enum Status : int32_t {
     49     FAIL = -1,
     50     OK = 0,
     51 };
     52 
     53 class Thread {
     54 public:
     55     Thread()
     56         : mHandle(0) {
     57     }
     58     virtual ~Thread() {
     59         assert(mExited);
     60         mHandle = 0;
     61     }
     62     Thread(const Thread& ) = delete;
     63     Status startThread();
     64     Status joinThread();
     65 
     66 protected:
     67     virtual void run() = 0;
     68 
     69 private:
     70     static void* thread_wrapper(void *);
     71     pthread_t mHandle;
     72 };
     73 
     74 static inline void deleter_AMediExtractor(AMediaExtractor *_a) {
     75     AMediaExtractor_delete(_a);
     76 }
     77 
     78 static inline void deleter_AMediaCodec(AMediaCodec *_a) {
     79     AMediaCodec_delete(_a);
     80 }
     81 
     82 static inline void deleter_AMediaFormat(AMediaFormat *_a) {
     83     AMediaFormat_delete(_a);
     84 }
     85 
     86 static inline void deleter_AMediaMuxer(AMediaMuxer *_a) {
     87     AMediaMuxer_delete(_a);
     88 }
     89 
     90 static inline void deleter_ANativeWindow(ANativeWindow *_a) {
     91     ANativeWindow_release(_a);
     92 }
     93 
     94 /*
     95  * Dynamic paramater that will be applied via AMediaCodec_setParamater(..)
     96  *  during the encoding process, at the given frame number
     97  */
     98 struct DynamicParam {
     99     DynamicParam() = delete;
    100     DynamicParam(const DynamicParam&) = delete;
    101     ~DynamicParam() = default;
    102 
    103     static std::shared_ptr<DynamicParam> newBitRate(int atFrame, int32_t bitrate) {
    104         DynamicParam *d = new DynamicParam(atFrame);
    105         AMediaFormat_setInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_VIDEO_BITRATE, bitrate);
    106         return std::shared_ptr<DynamicParam>(d);
    107     }
    108     static std::shared_ptr<DynamicParam> newRequestSync(int atFrame) {
    109         DynamicParam *d = new DynamicParam(atFrame);
    110         AMediaFormat_setInt32(d->param(), TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME, 0 /*ignore*/);
    111         return std::shared_ptr<DynamicParam>(d);
    112     }
    113 
    114     inline int frameNum() const {
    115         return mFrameNum;
    116     }
    117     inline AMediaFormat *param() const {
    118         return mParam.get();
    119     }
    120 
    121 private:
    122     DynamicParam(int _at)
    123         : mFrameNum(_at) {
    124         mParam = std::shared_ptr<AMediaFormat>(AMediaFormat_new(), deleter_AMediaFormat);
    125     }
    126 
    127     int mFrameNum;
    128     std::shared_ptr<AMediaFormat> mParam;
    129 };
    130 
    131 using DParamRef = std::shared_ptr<DynamicParam>;
    132 
    133 /*
    134  * Configuration to the encoder (static + dynamic)
    135  */
    136 struct RunConfig {
    137     RunConfig(const RunConfig&) = delete;
    138     RunConfig(int32_t numFramesToEncode, std::shared_ptr<AMediaFormat> staticParams)
    139         : mNumFramesToEncode (numFramesToEncode),
    140           mStaticParams(staticParams) {
    141     }
    142     void add(const DParamRef& p) {
    143         mParams.push_back(p);
    144     }
    145 
    146     AMediaFormat* format() const {
    147         return mStaticParams.get();
    148     }
    149     const std::vector<DParamRef>& dynamicParams() const {
    150         return mParams;
    151     }
    152     int32_t frameCount() const {
    153         return mNumFramesToEncode;
    154     }
    155     int32_t dynamicParamsOfKind(
    156         const char *key, std::vector<DParamRef>& ) const;
    157 
    158 private:
    159     int32_t mNumFramesToEncode;
    160     std::vector<DParamRef> mParams;
    161     std::shared_ptr<AMediaFormat> mStaticParams;
    162 };
    163 
    164 /*
    165  * Encoded output statistics
    166  * provides helpers to compute windowed average of bitrate and search for I-frames
    167  */
    168 struct Stats {
    169     Stats() = default;
    170     Stats(const Stats&) = delete;
    171     void add(const AMediaCodecBufferInfo &info) {
    172         mInfos.push_back(info);
    173     }
    174     void setOutputFormat(std::shared_ptr<AMediaFormat> fmt) {
    175         mOutputFormat = fmt;
    176     }
    177     int32_t frameCount() const {
    178         return (int32_t)mInfos.size();
    179     }
    180     const std::vector<AMediaCodecBufferInfo>& infos() const {
    181         return mInfos;
    182     }
    183 
    184     int32_t getBitrateAverage(int32_t frameNumFrom, int32_t frameNumTo) const;
    185     int32_t getBitratePeak(int32_t frameNumFrom, int32_t frameNumTo, int32_t windowSize) const;
    186     int32_t getSyncFrameNext(int32_t frameNumWhence) const;
    187 
    188 private:
    189     std::vector<AMediaCodecBufferInfo> mInfos;
    190     std::shared_ptr<AMediaFormat> mOutputFormat;
    191 };
    192 
    193 /*
    194  * Helpers to validate output (Stats) based on expected settings (RunConfig)
    195  * Check for validity of both static and dynamic settings
    196  */
    197 struct Validator {
    198     static Status checkOverallBitrate(const Stats&, const RunConfig&);
    199     static Status checkFramerate(const Stats&, const RunConfig&);
    200     static Status checkIntraPeriod(const Stats&, const RunConfig&);
    201     static Status checkDynamicKeyFrames(const Stats&, const RunConfig&);
    202     static Status checkDynamicBitrate(const Stats&, const RunConfig&);
    203 };
    204 
    205 }; //namespace Utils
    206 
    207 #endif // _NATIVE_MEDIA_UTILS_H_
    208