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:
Thread()55 Thread()
56 : mHandle(0) {
57 }
~Thread()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
deleter_AMediExtractor(AMediaExtractor * _a)74 static inline void deleter_AMediExtractor(AMediaExtractor *_a) {
75 AMediaExtractor_delete(_a);
76 }
77
deleter_AMediaCodec(AMediaCodec * _a)78 static inline void deleter_AMediaCodec(AMediaCodec *_a) {
79 AMediaCodec_delete(_a);
80 }
81
deleter_AMediaFormat(AMediaFormat * _a)82 static inline void deleter_AMediaFormat(AMediaFormat *_a) {
83 AMediaFormat_delete(_a);
84 }
85
deleter_AMediaMuxer(AMediaMuxer * _a)86 static inline void deleter_AMediaMuxer(AMediaMuxer *_a) {
87 AMediaMuxer_delete(_a);
88 }
89
deleter_ANativeWindow(ANativeWindow * _a)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
newBitRateDynamicParam103 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 }
newRequestSyncDynamicParam108 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
frameNumDynamicParam114 inline int frameNum() const {
115 return mFrameNum;
116 }
paramDynamicParam117 inline AMediaFormat *param() const {
118 return mParam.get();
119 }
120
121 private:
DynamicParamDynamicParam122 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;
RunConfigRunConfig138 RunConfig(int32_t numFramesToEncode, std::shared_ptr<AMediaFormat> staticParams)
139 : mNumFramesToEncode (numFramesToEncode),
140 mStaticParams(staticParams) {
141 }
addRunConfig142 void add(const DParamRef& p) {
143 mParams.push_back(p);
144 }
145
formatRunConfig146 AMediaFormat* format() const {
147 return mStaticParams.get();
148 }
dynamicParamsRunConfig149 const std::vector<DParamRef>& dynamicParams() const {
150 return mParams;
151 }
frameCountRunConfig152 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;
addStats171 void add(const AMediaCodecBufferInfo &info) {
172 mInfos.push_back(info);
173 }
setOutputFormatStats174 void setOutputFormat(std::shared_ptr<AMediaFormat> fmt) {
175 mOutputFormat = fmt;
176 }
frameCountStats177 int32_t frameCount() const {
178 return (int32_t)mInfos.size();
179 }
infosStats180 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