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