1*0ec5a0ecSAndroid Build Coastguard Worker // Copyright 2023 The Chromium Authors. All rights reserved.
2*0ec5a0ecSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*0ec5a0ecSAndroid Build Coastguard Worker // found in the LICENSE file.
4*0ec5a0ecSAndroid Build Coastguard Worker
5*0ec5a0ecSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
6*0ec5a0ecSAndroid Build Coastguard Worker #define LOG_TAG "V4L2EncodeInterface"
7*0ec5a0ecSAndroid Build Coastguard Worker
8*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/components/EncodeInterface.h>
9*0ec5a0ecSAndroid Build Coastguard Worker
10*0ec5a0ecSAndroid Build Coastguard Worker #include <inttypes.h>
11*0ec5a0ecSAndroid Build Coastguard Worker #include <algorithm>
12*0ec5a0ecSAndroid Build Coastguard Worker
13*0ec5a0ecSAndroid Build Coastguard Worker #include <C2PlatformSupport.h>
14*0ec5a0ecSAndroid Build Coastguard Worker #include <SimpleC2Interface.h>
15*0ec5a0ecSAndroid Build Coastguard Worker #include <android/hardware/graphics/common/1.0/types.h>
16*0ec5a0ecSAndroid Build Coastguard Worker #include <media/stagefright/MediaDefs.h>
17*0ec5a0ecSAndroid Build Coastguard Worker #include <utils/Log.h>
18*0ec5a0ecSAndroid Build Coastguard Worker
19*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/common/Common.h>
20*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/common/H264.h>
21*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/common/VideoTypes.h>
22*0ec5a0ecSAndroid Build Coastguard Worker
23*0ec5a0ecSAndroid Build Coastguard Worker using android::hardware::graphics::common::V1_0::BufferUsage;
24*0ec5a0ecSAndroid Build Coastguard Worker
25*0ec5a0ecSAndroid Build Coastguard Worker namespace android {
26*0ec5a0ecSAndroid Build Coastguard Worker
27*0ec5a0ecSAndroid Build Coastguard Worker namespace {
28*0ec5a0ecSAndroid Build Coastguard Worker
29*0ec5a0ecSAndroid Build Coastguard Worker // Use basic linear block pool/allocator as default.
30*0ec5a0ecSAndroid Build Coastguard Worker constexpr C2BlockPool::local_id_t kDefaultOutputBlockPool = C2BlockPool::BASIC_LINEAR;
31*0ec5a0ecSAndroid Build Coastguard Worker // Default input and output allocators.
32*0ec5a0ecSAndroid Build Coastguard Worker constexpr C2Allocator::id_t kDefaultInputAllocator = C2PlatformAllocatorStore::GRALLOC;
33*0ec5a0ecSAndroid Build Coastguard Worker constexpr C2Allocator::id_t kDefaultOutputAllocator = C2PlatformAllocatorStore::BLOB;
34*0ec5a0ecSAndroid Build Coastguard Worker
35*0ec5a0ecSAndroid Build Coastguard Worker // The default output framerate in frames per second.
36*0ec5a0ecSAndroid Build Coastguard Worker // TODO: increase to 60 fps in the future.
37*0ec5a0ecSAndroid Build Coastguard Worker constexpr float kDefaultFrameRate = 30.0;
38*0ec5a0ecSAndroid Build Coastguard Worker // The default output bitrate in bits per second. Use the max bitrate of AVC Level1.0 as default.
39*0ec5a0ecSAndroid Build Coastguard Worker constexpr uint32_t kDefaultBitrate = 64000;
40*0ec5a0ecSAndroid Build Coastguard Worker
41*0ec5a0ecSAndroid Build Coastguard Worker // The maximal output bitrate in bits per second. It's the max bitrate of AVC Level4.1.
42*0ec5a0ecSAndroid Build Coastguard Worker // TODO: increase this in the future for supporting higher level/resolution encoding.
43*0ec5a0ecSAndroid Build Coastguard Worker constexpr uint32_t kMaxBitrate = 50000000;
44*0ec5a0ecSAndroid Build Coastguard Worker } // namespace
45*0ec5a0ecSAndroid Build Coastguard Worker
46*0ec5a0ecSAndroid Build Coastguard Worker //static
47*0ec5a0ecSAndroid Build Coastguard Worker C2Config::level_t EncodeInterface::lowestConfigLevel = C2Config::LEVEL_UNUSED;
48*0ec5a0ecSAndroid Build Coastguard Worker
49*0ec5a0ecSAndroid Build Coastguard Worker // static
H264ProfileLevelSetter(bool,C2P<C2StreamProfileLevelInfo::output> & info,const C2P<C2StreamPictureSizeInfo::input> & videoSize,const C2P<C2StreamFrameRateInfo::output> & frameRate,const C2P<C2StreamBitrateInfo::output> & bitrate)50*0ec5a0ecSAndroid Build Coastguard Worker C2R EncodeInterface::H264ProfileLevelSetter(bool /*mayBlock*/,
51*0ec5a0ecSAndroid Build Coastguard Worker C2P<C2StreamProfileLevelInfo::output>& info,
52*0ec5a0ecSAndroid Build Coastguard Worker const C2P<C2StreamPictureSizeInfo::input>& videoSize,
53*0ec5a0ecSAndroid Build Coastguard Worker const C2P<C2StreamFrameRateInfo::output>& frameRate,
54*0ec5a0ecSAndroid Build Coastguard Worker const C2P<C2StreamBitrateInfo::output>& bitrate) {
55*0ec5a0ecSAndroid Build Coastguard Worker // Adopt default minimal profile instead if the requested profile is not supported, or lower
56*0ec5a0ecSAndroid Build Coastguard Worker // than the default minimal one.
57*0ec5a0ecSAndroid Build Coastguard Worker constexpr C2Config::profile_t minProfile = C2Config::PROFILE_AVC_BASELINE;
58*0ec5a0ecSAndroid Build Coastguard Worker if (!info.F(info.v.profile).supportsAtAll(info.v.profile) || info.v.profile < minProfile) {
59*0ec5a0ecSAndroid Build Coastguard Worker if (info.F(info.v.profile).supportsAtAll(minProfile)) {
60*0ec5a0ecSAndroid Build Coastguard Worker ALOGV("Set profile to default (%u) instead.", minProfile);
61*0ec5a0ecSAndroid Build Coastguard Worker info.set().profile = minProfile;
62*0ec5a0ecSAndroid Build Coastguard Worker } else {
63*0ec5a0ecSAndroid Build Coastguard Worker ALOGE("Unable to set either requested profile (%u) or default profile (%u).",
64*0ec5a0ecSAndroid Build Coastguard Worker info.v.profile, minProfile);
65*0ec5a0ecSAndroid Build Coastguard Worker return C2R(C2SettingResultBuilder::BadValue(info.F(info.v.profile)));
66*0ec5a0ecSAndroid Build Coastguard Worker }
67*0ec5a0ecSAndroid Build Coastguard Worker }
68*0ec5a0ecSAndroid Build Coastguard Worker
69*0ec5a0ecSAndroid Build Coastguard Worker uint64_t targetFS =
70*0ec5a0ecSAndroid Build Coastguard Worker static_cast<uint64_t>((videoSize.v.width + 15) / 16) * ((videoSize.v.height + 15) / 16);
71*0ec5a0ecSAndroid Build Coastguard Worker float targetMBPS = static_cast<float>(targetFS) * frameRate.v.value;
72*0ec5a0ecSAndroid Build Coastguard Worker
73*0ec5a0ecSAndroid Build Coastguard Worker // Try the recorded lowest configed level. This level should become adaptable after input size,
74*0ec5a0ecSAndroid Build Coastguard Worker // frame rate, and bitrate are all set.
75*0ec5a0ecSAndroid Build Coastguard Worker if (lowestConfigLevel != C2Config::LEVEL_UNUSED && lowestConfigLevel < info.v.level) {
76*0ec5a0ecSAndroid Build Coastguard Worker info.set().level = lowestConfigLevel;
77*0ec5a0ecSAndroid Build Coastguard Worker }
78*0ec5a0ecSAndroid Build Coastguard Worker
79*0ec5a0ecSAndroid Build Coastguard Worker // Check if the supplied level meets the requirements. If not, update the level with the lowest
80*0ec5a0ecSAndroid Build Coastguard Worker // level meeting the requirements.
81*0ec5a0ecSAndroid Build Coastguard Worker
82*0ec5a0ecSAndroid Build Coastguard Worker bool found = false;
83*0ec5a0ecSAndroid Build Coastguard Worker bool needsUpdate = !info.F(info.v.level).supportsAtAll(info.v.level);
84*0ec5a0ecSAndroid Build Coastguard Worker for (const H264LevelLimits& limit : kH264Limits) {
85*0ec5a0ecSAndroid Build Coastguard Worker if (!info.F(info.v.level).supportsAtAll(limit.level)) {
86*0ec5a0ecSAndroid Build Coastguard Worker continue;
87*0ec5a0ecSAndroid Build Coastguard Worker }
88*0ec5a0ecSAndroid Build Coastguard Worker
89*0ec5a0ecSAndroid Build Coastguard Worker // Table A-2 in spec
90*0ec5a0ecSAndroid Build Coastguard Worker // The maximum bit rate for High Profile is 1.25 times that of the Base/Extended/Main
91*0ec5a0ecSAndroid Build Coastguard Worker // Profiles, 3 times for Hi10P, and 4 times for Hi422P/Hi444PP.
92*0ec5a0ecSAndroid Build Coastguard Worker uint32_t maxBR = limit.maxBR;
93*0ec5a0ecSAndroid Build Coastguard Worker if (info.v.profile >= C2Config::PROFILE_AVC_HIGH_422) {
94*0ec5a0ecSAndroid Build Coastguard Worker maxBR *= 4;
95*0ec5a0ecSAndroid Build Coastguard Worker } else if (info.v.profile >= C2Config::PROFILE_AVC_HIGH_10) {
96*0ec5a0ecSAndroid Build Coastguard Worker maxBR *= 3;
97*0ec5a0ecSAndroid Build Coastguard Worker } else if (info.v.profile >= C2Config::PROFILE_AVC_HIGH) {
98*0ec5a0ecSAndroid Build Coastguard Worker maxBR = maxBR * 5.0 / 4.0;
99*0ec5a0ecSAndroid Build Coastguard Worker }
100*0ec5a0ecSAndroid Build Coastguard Worker
101*0ec5a0ecSAndroid Build Coastguard Worker if (targetFS <= limit.maxFS && targetMBPS <= limit.maxMBPS && bitrate.v.value <= maxBR) {
102*0ec5a0ecSAndroid Build Coastguard Worker // This is the lowest level that meets the requirements, and if
103*0ec5a0ecSAndroid Build Coastguard Worker // we haven't seen the supplied level yet, that means we don't
104*0ec5a0ecSAndroid Build Coastguard Worker // need the update.
105*0ec5a0ecSAndroid Build Coastguard Worker if (needsUpdate) {
106*0ec5a0ecSAndroid Build Coastguard Worker // Since current config update is sequential, there is an issue when we want to set
107*0ec5a0ecSAndroid Build Coastguard Worker // lower level for small input size, frame rate, and bitrate, if we set level first,
108*0ec5a0ecSAndroid Build Coastguard Worker // it will be adjusted to a higher one because the default input size or others are
109*0ec5a0ecSAndroid Build Coastguard Worker // above the limit. Use lowestConfigLevel to record the level we have tried to
110*0ec5a0ecSAndroid Build Coastguard Worker // config (but failed).
111*0ec5a0ecSAndroid Build Coastguard Worker // TODO(johnylin): remove this solution after b/140407694 has proper fix.
112*0ec5a0ecSAndroid Build Coastguard Worker lowestConfigLevel = info.v.level;
113*0ec5a0ecSAndroid Build Coastguard Worker
114*0ec5a0ecSAndroid Build Coastguard Worker ALOGD("Given level %u does not cover current configuration: "
115*0ec5a0ecSAndroid Build Coastguard Worker "adjusting to %u",
116*0ec5a0ecSAndroid Build Coastguard Worker info.v.level, limit.level);
117*0ec5a0ecSAndroid Build Coastguard Worker info.set().level = limit.level;
118*0ec5a0ecSAndroid Build Coastguard Worker }
119*0ec5a0ecSAndroid Build Coastguard Worker found = true;
120*0ec5a0ecSAndroid Build Coastguard Worker break;
121*0ec5a0ecSAndroid Build Coastguard Worker }
122*0ec5a0ecSAndroid Build Coastguard Worker if (info.v.level <= limit.level) {
123*0ec5a0ecSAndroid Build Coastguard Worker // We break out of the loop when the lowest feasible level is found. The fact that we're
124*0ec5a0ecSAndroid Build Coastguard Worker // here means that our level doesn't meet the requirement and needs to be updated.
125*0ec5a0ecSAndroid Build Coastguard Worker needsUpdate = true;
126*0ec5a0ecSAndroid Build Coastguard Worker }
127*0ec5a0ecSAndroid Build Coastguard Worker }
128*0ec5a0ecSAndroid Build Coastguard Worker if (!found) {
129*0ec5a0ecSAndroid Build Coastguard Worker ALOGE("Unable to find proper level with current config, requested level (%u).",
130*0ec5a0ecSAndroid Build Coastguard Worker info.v.level);
131*0ec5a0ecSAndroid Build Coastguard Worker return C2R(C2SettingResultBuilder::BadValue(info.F(info.v.level)));
132*0ec5a0ecSAndroid Build Coastguard Worker }
133*0ec5a0ecSAndroid Build Coastguard Worker
134*0ec5a0ecSAndroid Build Coastguard Worker return C2R::Ok();
135*0ec5a0ecSAndroid Build Coastguard Worker }
136*0ec5a0ecSAndroid Build Coastguard Worker
VP9ProfileLevelSetter(bool,C2P<C2StreamProfileLevelInfo::output> & info,const C2P<C2StreamPictureSizeInfo::input> &,const C2P<C2StreamFrameRateInfo::output> &,const C2P<C2StreamBitrateInfo::output> &)137*0ec5a0ecSAndroid Build Coastguard Worker C2R EncodeInterface::VP9ProfileLevelSetter(bool /*mayBlock*/,
138*0ec5a0ecSAndroid Build Coastguard Worker C2P<C2StreamProfileLevelInfo::output>& info,
139*0ec5a0ecSAndroid Build Coastguard Worker const C2P<C2StreamPictureSizeInfo::input>& /*videoSize*/,
140*0ec5a0ecSAndroid Build Coastguard Worker const C2P<C2StreamFrameRateInfo::output>& /*frameRate*/,
141*0ec5a0ecSAndroid Build Coastguard Worker const C2P<C2StreamBitrateInfo::output>& /*bitrate*/) {
142*0ec5a0ecSAndroid Build Coastguard Worker // Adopt default minimal profile instead if the requested profile is not supported, or lower
143*0ec5a0ecSAndroid Build Coastguard Worker // than the default minimal one.
144*0ec5a0ecSAndroid Build Coastguard Worker constexpr C2Config::profile_t defaultMinProfile = C2Config::PROFILE_VP9_0;
145*0ec5a0ecSAndroid Build Coastguard Worker if (!info.F(info.v.profile).supportsAtAll(info.v.profile) ||
146*0ec5a0ecSAndroid Build Coastguard Worker info.v.profile < defaultMinProfile) {
147*0ec5a0ecSAndroid Build Coastguard Worker if (info.F(info.v.profile).supportsAtAll(defaultMinProfile)) {
148*0ec5a0ecSAndroid Build Coastguard Worker ALOGV("Set profile to default (%u) instead.", defaultMinProfile);
149*0ec5a0ecSAndroid Build Coastguard Worker info.set().profile = defaultMinProfile;
150*0ec5a0ecSAndroid Build Coastguard Worker } else {
151*0ec5a0ecSAndroid Build Coastguard Worker ALOGE("Unable to set either requested profile (%u) or default profile (%u).",
152*0ec5a0ecSAndroid Build Coastguard Worker info.v.profile, defaultMinProfile);
153*0ec5a0ecSAndroid Build Coastguard Worker return C2R(C2SettingResultBuilder::BadValue(info.F(info.v.profile)));
154*0ec5a0ecSAndroid Build Coastguard Worker }
155*0ec5a0ecSAndroid Build Coastguard Worker }
156*0ec5a0ecSAndroid Build Coastguard Worker
157*0ec5a0ecSAndroid Build Coastguard Worker return C2R::Ok();
158*0ec5a0ecSAndroid Build Coastguard Worker }
159*0ec5a0ecSAndroid Build Coastguard Worker
160*0ec5a0ecSAndroid Build Coastguard Worker // static
SizeSetter(bool mayBlock,C2P<C2StreamPictureSizeInfo::input> & videoSize)161*0ec5a0ecSAndroid Build Coastguard Worker C2R EncodeInterface::SizeSetter(bool mayBlock, C2P<C2StreamPictureSizeInfo::input>& videoSize) {
162*0ec5a0ecSAndroid Build Coastguard Worker (void)mayBlock;
163*0ec5a0ecSAndroid Build Coastguard Worker // TODO: maybe apply block limit?
164*0ec5a0ecSAndroid Build Coastguard Worker return videoSize.F(videoSize.v.width)
165*0ec5a0ecSAndroid Build Coastguard Worker .validatePossible(videoSize.v.width)
166*0ec5a0ecSAndroid Build Coastguard Worker .plus(videoSize.F(videoSize.v.height).validatePossible(videoSize.v.height));
167*0ec5a0ecSAndroid Build Coastguard Worker }
168*0ec5a0ecSAndroid Build Coastguard Worker
169*0ec5a0ecSAndroid Build Coastguard Worker // static
IntraRefreshPeriodSetter(bool mayBlock,C2P<C2StreamIntraRefreshTuning::output> & period)170*0ec5a0ecSAndroid Build Coastguard Worker C2R EncodeInterface::IntraRefreshPeriodSetter(bool mayBlock,
171*0ec5a0ecSAndroid Build Coastguard Worker C2P<C2StreamIntraRefreshTuning::output>& period) {
172*0ec5a0ecSAndroid Build Coastguard Worker (void)mayBlock;
173*0ec5a0ecSAndroid Build Coastguard Worker if (period.v.period < 1) {
174*0ec5a0ecSAndroid Build Coastguard Worker period.set().mode = C2Config::INTRA_REFRESH_DISABLED;
175*0ec5a0ecSAndroid Build Coastguard Worker period.set().period = 0;
176*0ec5a0ecSAndroid Build Coastguard Worker } else {
177*0ec5a0ecSAndroid Build Coastguard Worker // Only support arbitrary mode (cyclic in our case).
178*0ec5a0ecSAndroid Build Coastguard Worker period.set().mode = C2Config::INTRA_REFRESH_ARBITRARY;
179*0ec5a0ecSAndroid Build Coastguard Worker }
180*0ec5a0ecSAndroid Build Coastguard Worker return C2R::Ok();
181*0ec5a0ecSAndroid Build Coastguard Worker }
182*0ec5a0ecSAndroid Build Coastguard Worker
EncodeInterface(const C2String & name,std::shared_ptr<C2ReflectorHelper> helper,const SupportedCapabilities & caps)183*0ec5a0ecSAndroid Build Coastguard Worker EncodeInterface::EncodeInterface(const C2String& name, std::shared_ptr<C2ReflectorHelper> helper,
184*0ec5a0ecSAndroid Build Coastguard Worker const SupportedCapabilities& caps)
185*0ec5a0ecSAndroid Build Coastguard Worker : C2InterfaceHelper(std::move(helper)) {
186*0ec5a0ecSAndroid Build Coastguard Worker ALOGV("%s(%s)", __func__, name.c_str());
187*0ec5a0ecSAndroid Build Coastguard Worker
188*0ec5a0ecSAndroid Build Coastguard Worker setDerivedInstance(this);
189*0ec5a0ecSAndroid Build Coastguard Worker
190*0ec5a0ecSAndroid Build Coastguard Worker Initialize(name, caps);
191*0ec5a0ecSAndroid Build Coastguard Worker }
192*0ec5a0ecSAndroid Build Coastguard Worker
Initialize(const C2String & name,const SupportedCapabilities & caps)193*0ec5a0ecSAndroid Build Coastguard Worker void EncodeInterface::Initialize(const C2String& name, const SupportedCapabilities& caps) {
194*0ec5a0ecSAndroid Build Coastguard Worker // Note: unsigned int is used here, since std::vector<C2Config::profile_t> cannot convert to
195*0ec5a0ecSAndroid Build Coastguard Worker // std::vector<unsigned int> required by the c2 framework below.
196*0ec5a0ecSAndroid Build Coastguard Worker std::vector<unsigned int> profiles;
197*0ec5a0ecSAndroid Build Coastguard Worker ui::Size maxSize;
198*0ec5a0ecSAndroid Build Coastguard Worker for (const auto& supportedProfile : caps.supportedProfiles) {
199*0ec5a0ecSAndroid Build Coastguard Worker if (!isValidProfileForCodec(caps.codec, supportedProfile.profile)) {
200*0ec5a0ecSAndroid Build Coastguard Worker continue; // Ignore unrecognizable or unsupported profiles.
201*0ec5a0ecSAndroid Build Coastguard Worker }
202*0ec5a0ecSAndroid Build Coastguard Worker ALOGV("Queried c2_profile = 0x%x : max_size = %d x %d", supportedProfile.profile,
203*0ec5a0ecSAndroid Build Coastguard Worker supportedProfile.max_resolution.width, supportedProfile.max_resolution.height);
204*0ec5a0ecSAndroid Build Coastguard Worker profiles.push_back(static_cast<unsigned int>(supportedProfile.profile));
205*0ec5a0ecSAndroid Build Coastguard Worker maxSize.setWidth(std::max(maxSize.width, supportedProfile.max_resolution.width));
206*0ec5a0ecSAndroid Build Coastguard Worker maxSize.setHeight(std::max(maxSize.height, supportedProfile.max_resolution.height));
207*0ec5a0ecSAndroid Build Coastguard Worker }
208*0ec5a0ecSAndroid Build Coastguard Worker
209*0ec5a0ecSAndroid Build Coastguard Worker if (profiles.empty()) {
210*0ec5a0ecSAndroid Build Coastguard Worker ALOGE("No supported profiles");
211*0ec5a0ecSAndroid Build Coastguard Worker mInitStatus = C2_BAD_VALUE;
212*0ec5a0ecSAndroid Build Coastguard Worker return;
213*0ec5a0ecSAndroid Build Coastguard Worker }
214*0ec5a0ecSAndroid Build Coastguard Worker
215*0ec5a0ecSAndroid Build Coastguard Worker // Special note: the order of addParameter matters if your setters are dependent on other
216*0ec5a0ecSAndroid Build Coastguard Worker // parameters. Please make sure the dependent parameters are added prior to the
217*0ec5a0ecSAndroid Build Coastguard Worker // one needs the setter dependency.
218*0ec5a0ecSAndroid Build Coastguard Worker
219*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND)
220*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(new C2ComponentKindSetting(C2Component::KIND_ENCODER))
221*0ec5a0ecSAndroid Build Coastguard Worker .build());
222*0ec5a0ecSAndroid Build Coastguard Worker
223*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mInputVisibleSize, C2_PARAMKEY_PICTURE_SIZE)
224*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
225*0ec5a0ecSAndroid Build Coastguard Worker .withFields({
226*0ec5a0ecSAndroid Build Coastguard Worker C2F(mInputVisibleSize, width).inRange(2, maxSize.width, 2),
227*0ec5a0ecSAndroid Build Coastguard Worker C2F(mInputVisibleSize, height).inRange(2, maxSize.height, 2),
228*0ec5a0ecSAndroid Build Coastguard Worker })
229*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(SizeSetter)
230*0ec5a0ecSAndroid Build Coastguard Worker .build());
231*0ec5a0ecSAndroid Build Coastguard Worker
232*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
233*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamFrameRateInfo::output(0u, kDefaultFrameRate))
234*0ec5a0ecSAndroid Build Coastguard Worker // TODO: More restriction?
235*0ec5a0ecSAndroid Build Coastguard Worker .withFields({C2F(mFrameRate, value).greaterThan(0.)})
236*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
237*0ec5a0ecSAndroid Build Coastguard Worker .build());
238*0ec5a0ecSAndroid Build Coastguard Worker
239*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
240*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamBitrateInfo::output(0u, kDefaultBitrate))
241*0ec5a0ecSAndroid Build Coastguard Worker .withFields({C2F(mBitrate, value).inRange(0, kMaxBitrate)})
242*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(Setter<decltype(*mBitrate)>::StrictValueWithNoDeps)
243*0ec5a0ecSAndroid Build Coastguard Worker .build());
244*0ec5a0ecSAndroid Build Coastguard Worker
245*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
246*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mBitrateMode, C2_PARAMKEY_BITRATE_MODE)
247*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamBitrateModeTuning::output(0u, C2Config::BITRATE_CONST))
248*0ec5a0ecSAndroid Build Coastguard Worker .withFields(
249*0ec5a0ecSAndroid Build Coastguard Worker {C2F(mBitrateMode, value)
250*0ec5a0ecSAndroid Build Coastguard Worker .oneOf({C2Config::BITRATE_CONST, C2Config::BITRATE_VARIABLE})})
251*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps)
252*0ec5a0ecSAndroid Build Coastguard Worker .build());
253*0ec5a0ecSAndroid Build Coastguard Worker
254*0ec5a0ecSAndroid Build Coastguard Worker std::string outputMime;
255*0ec5a0ecSAndroid Build Coastguard Worker if (caps.codec == VideoCodec::H264) {
256*0ec5a0ecSAndroid Build Coastguard Worker outputMime = MEDIA_MIMETYPE_VIDEO_AVC;
257*0ec5a0ecSAndroid Build Coastguard Worker C2Config::profile_t minProfile = static_cast<C2Config::profile_t>(
258*0ec5a0ecSAndroid Build Coastguard Worker *std::min_element(profiles.begin(), profiles.end()));
259*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
260*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
261*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamProfileLevelInfo::output(0u, minProfile,
262*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_4_1))
263*0ec5a0ecSAndroid Build Coastguard Worker .withFields(
264*0ec5a0ecSAndroid Build Coastguard Worker {C2F(mProfileLevel, profile).oneOf(profiles),
265*0ec5a0ecSAndroid Build Coastguard Worker C2F(mProfileLevel, level)
266*0ec5a0ecSAndroid Build Coastguard Worker // TODO: query supported levels from adaptor.
267*0ec5a0ecSAndroid Build Coastguard Worker .oneOf({C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B,
268*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_1_1, C2Config::LEVEL_AVC_1_2,
269*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_1_3, C2Config::LEVEL_AVC_2,
270*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2,
271*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_3, C2Config::LEVEL_AVC_3_1,
272*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_3_2, C2Config::LEVEL_AVC_4,
273*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2,
274*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_AVC_5, C2Config::LEVEL_AVC_5_1})})
275*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(H264ProfileLevelSetter, mInputVisibleSize, mFrameRate, mBitrate)
276*0ec5a0ecSAndroid Build Coastguard Worker .build());
277*0ec5a0ecSAndroid Build Coastguard Worker } else if (caps.codec == VideoCodec::VP8) {
278*0ec5a0ecSAndroid Build Coastguard Worker outputMime = MEDIA_MIMETYPE_VIDEO_VP8;
279*0ec5a0ecSAndroid Build Coastguard Worker // VP8 doesn't have conventional profiles, we'll use profile0 if the VP8 codec is requested.
280*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
281*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(new C2StreamProfileLevelInfo::output(
282*0ec5a0ecSAndroid Build Coastguard Worker 0u, C2Config::PROFILE_VP8_0, C2Config::LEVEL_UNUSED))
283*0ec5a0ecSAndroid Build Coastguard Worker .build());
284*0ec5a0ecSAndroid Build Coastguard Worker } else if (caps.codec == VideoCodec::VP9) {
285*0ec5a0ecSAndroid Build Coastguard Worker outputMime = MEDIA_MIMETYPE_VIDEO_VP9;
286*0ec5a0ecSAndroid Build Coastguard Worker C2Config::profile_t minProfile = static_cast<C2Config::profile_t>(
287*0ec5a0ecSAndroid Build Coastguard Worker *std::min_element(profiles.begin(), profiles.end()));
288*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
289*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
290*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamProfileLevelInfo::output(0u, minProfile,
291*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_1))
292*0ec5a0ecSAndroid Build Coastguard Worker .withFields(
293*0ec5a0ecSAndroid Build Coastguard Worker {C2F(mProfileLevel, profile).oneOf(profiles),
294*0ec5a0ecSAndroid Build Coastguard Worker C2F(mProfileLevel, level)
295*0ec5a0ecSAndroid Build Coastguard Worker // TODO(dstaessens) query supported levels from adaptor.
296*0ec5a0ecSAndroid Build Coastguard Worker .oneOf({C2Config::LEVEL_VP9_1, C2Config::LEVEL_VP9_1_1,
297*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_2, C2Config::LEVEL_VP9_2_1,
298*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_3, C2Config::LEVEL_VP9_3_1,
299*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_4, C2Config::LEVEL_VP9_4_1,
300*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_5, C2Config::LEVEL_VP9_5_1,
301*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_5_2, C2Config::LEVEL_VP9_6,
302*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_6_1,
303*0ec5a0ecSAndroid Build Coastguard Worker C2Config::LEVEL_VP9_6_2})})
304*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(VP9ProfileLevelSetter, mInputVisibleSize, mFrameRate, mBitrate)
305*0ec5a0ecSAndroid Build Coastguard Worker .build());
306*0ec5a0ecSAndroid Build Coastguard Worker } else {
307*0ec5a0ecSAndroid Build Coastguard Worker ALOGE("Unsupported component name: %s", name.c_str());
308*0ec5a0ecSAndroid Build Coastguard Worker mInitStatus = C2_BAD_VALUE;
309*0ec5a0ecSAndroid Build Coastguard Worker return;
310*0ec5a0ecSAndroid Build Coastguard Worker }
311*0ec5a0ecSAndroid Build Coastguard Worker
312*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
313*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mInputFormat, C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE)
314*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(new C2StreamBufferTypeSetting::input(0u, C2BufferData::GRAPHIC))
315*0ec5a0ecSAndroid Build Coastguard Worker .build());
316*0ec5a0ecSAndroid Build Coastguard Worker
317*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mInputMemoryUsage, C2_PARAMKEY_INPUT_STREAM_USAGE)
318*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(new C2StreamUsageTuning::input(
319*0ec5a0ecSAndroid Build Coastguard Worker 0u, static_cast<uint64_t>(BufferUsage::VIDEO_ENCODER)))
320*0ec5a0ecSAndroid Build Coastguard Worker .build());
321*0ec5a0ecSAndroid Build Coastguard Worker
322*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
323*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mOutputFormat, C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE)
324*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(new C2StreamBufferTypeSetting::output(0u, C2BufferData::LINEAR))
325*0ec5a0ecSAndroid Build Coastguard Worker .build());
326*0ec5a0ecSAndroid Build Coastguard Worker
327*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE)
328*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(AllocSharedString<C2PortMediaTypeSetting::input>(
329*0ec5a0ecSAndroid Build Coastguard Worker MEDIA_MIMETYPE_VIDEO_RAW))
330*0ec5a0ecSAndroid Build Coastguard Worker .build());
331*0ec5a0ecSAndroid Build Coastguard Worker
332*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE)
333*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(AllocSharedString<C2PortMediaTypeSetting::output>(
334*0ec5a0ecSAndroid Build Coastguard Worker outputMime.c_str()))
335*0ec5a0ecSAndroid Build Coastguard Worker .build());
336*0ec5a0ecSAndroid Build Coastguard Worker
337*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mIntraRefreshPeriod, C2_PARAMKEY_INTRA_REFRESH)
338*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamIntraRefreshTuning::output(
339*0ec5a0ecSAndroid Build Coastguard Worker 0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
340*0ec5a0ecSAndroid Build Coastguard Worker .withFields({C2F(mIntraRefreshPeriod, mode)
341*0ec5a0ecSAndroid Build Coastguard Worker .oneOf({C2Config::INTRA_REFRESH_DISABLED,
342*0ec5a0ecSAndroid Build Coastguard Worker C2Config::INTRA_REFRESH_ARBITRARY}),
343*0ec5a0ecSAndroid Build Coastguard Worker C2F(mIntraRefreshPeriod, period).any()})
344*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(IntraRefreshPeriodSetter)
345*0ec5a0ecSAndroid Build Coastguard Worker .build());
346*0ec5a0ecSAndroid Build Coastguard Worker
347*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mRequestKeyFrame, C2_PARAMKEY_REQUEST_SYNC_FRAME)
348*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
349*0ec5a0ecSAndroid Build Coastguard Worker .withFields({C2F(mRequestKeyFrame, value).oneOf({C2_FALSE, C2_TRUE})})
350*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(Setter<decltype(*mRequestKeyFrame)>::NonStrictValueWithNoDeps)
351*0ec5a0ecSAndroid Build Coastguard Worker .build());
352*0ec5a0ecSAndroid Build Coastguard Worker
353*0ec5a0ecSAndroid Build Coastguard Worker addParameter(DefineParam(mKeyFramePeriodUs, C2_PARAMKEY_SYNC_FRAME_INTERVAL)
354*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000))
355*0ec5a0ecSAndroid Build Coastguard Worker .withFields({C2F(mKeyFramePeriodUs, value).any()})
356*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(Setter<decltype(*mKeyFramePeriodUs)>::StrictValueWithNoDeps)
357*0ec5a0ecSAndroid Build Coastguard Worker .build());
358*0ec5a0ecSAndroid Build Coastguard Worker
359*0ec5a0ecSAndroid Build Coastguard Worker C2Allocator::id_t inputAllocators[] = {kDefaultInputAllocator};
360*0ec5a0ecSAndroid Build Coastguard Worker
361*0ec5a0ecSAndroid Build Coastguard Worker C2Allocator::id_t outputAllocators[] = {kDefaultOutputAllocator};
362*0ec5a0ecSAndroid Build Coastguard Worker
363*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
364*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mInputAllocatorIds, C2_PARAMKEY_INPUT_ALLOCATORS)
365*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(C2PortAllocatorsTuning::input::AllocShared(inputAllocators))
366*0ec5a0ecSAndroid Build Coastguard Worker .build());
367*0ec5a0ecSAndroid Build Coastguard Worker
368*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
369*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mOutputAllocatorIds, C2_PARAMKEY_OUTPUT_ALLOCATORS)
370*0ec5a0ecSAndroid Build Coastguard Worker .withConstValue(C2PortAllocatorsTuning::output::AllocShared(outputAllocators))
371*0ec5a0ecSAndroid Build Coastguard Worker .build());
372*0ec5a0ecSAndroid Build Coastguard Worker
373*0ec5a0ecSAndroid Build Coastguard Worker C2BlockPool::local_id_t outputBlockPools[] = {kDefaultOutputBlockPool};
374*0ec5a0ecSAndroid Build Coastguard Worker
375*0ec5a0ecSAndroid Build Coastguard Worker addParameter(
376*0ec5a0ecSAndroid Build Coastguard Worker DefineParam(mOutputBlockPoolIds, C2_PARAMKEY_OUTPUT_BLOCK_POOLS)
377*0ec5a0ecSAndroid Build Coastguard Worker .withDefault(C2PortBlockPoolsTuning::output::AllocShared(outputBlockPools))
378*0ec5a0ecSAndroid Build Coastguard Worker .withFields({C2F(mOutputBlockPoolIds, m.values[0]).any(),
379*0ec5a0ecSAndroid Build Coastguard Worker C2F(mOutputBlockPoolIds, m.values).inRange(0, 1)})
380*0ec5a0ecSAndroid Build Coastguard Worker .withSetter(Setter<C2PortBlockPoolsTuning::output>::NonStrictValuesWithNoDeps)
381*0ec5a0ecSAndroid Build Coastguard Worker .build());
382*0ec5a0ecSAndroid Build Coastguard Worker
383*0ec5a0ecSAndroid Build Coastguard Worker mInitStatus = C2_OK;
384*0ec5a0ecSAndroid Build Coastguard Worker }
385*0ec5a0ecSAndroid Build Coastguard Worker
getKeyFramePeriod() const386*0ec5a0ecSAndroid Build Coastguard Worker uint32_t EncodeInterface::getKeyFramePeriod() const {
387*0ec5a0ecSAndroid Build Coastguard Worker if (mKeyFramePeriodUs->value < 0 || mKeyFramePeriodUs->value == INT64_MAX) {
388*0ec5a0ecSAndroid Build Coastguard Worker return 0;
389*0ec5a0ecSAndroid Build Coastguard Worker }
390*0ec5a0ecSAndroid Build Coastguard Worker double period = mKeyFramePeriodUs->value / 1e6 * mFrameRate->value;
391*0ec5a0ecSAndroid Build Coastguard Worker return static_cast<uint32_t>(std::max(std::min(std::round(period), double(UINT32_MAX)), 1.));
392*0ec5a0ecSAndroid Build Coastguard Worker }
393*0ec5a0ecSAndroid Build Coastguard Worker
394*0ec5a0ecSAndroid Build Coastguard Worker } // namespace android
395