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