• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2SoftAvcEnc"
19 #include <log/log.h>
20 #include <utils/misc.h>
21 
22 #include <algorithm>
23 
24 #include <media/hardware/VideoAPI.h>
25 #include <media/stagefright/MediaDefs.h>
26 #include <media/stagefright/MediaErrors.h>
27 #include <media/stagefright/MetaData.h>
28 #include <media/stagefright/foundation/AUtils.h>
29 
30 #include <C2Debug.h>
31 #include <Codec2Mapper.h>
32 #include <C2PlatformSupport.h>
33 #include <Codec2BufferUtils.h>
34 #include <SimpleC2Interface.h>
35 #include <util/C2InterfaceHelper.h>
36 
37 #include "C2SoftAvcEnc.h"
38 #include "ih264e.h"
39 #include "ih264e_error.h"
40 
41 namespace android {
42 
43 namespace {
44 
45 constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
46 constexpr uint32_t kMinOutBufferSize = 524288;
ParseGop(const C2StreamGopTuning::output & gop,uint32_t * syncInterval,uint32_t * iInterval,uint32_t * maxBframes)47 void ParseGop(
48         const C2StreamGopTuning::output &gop,
49         uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
50     uint32_t syncInt = 1;
51     uint32_t iInt = 1;
52     for (size_t i = 0; i < gop.flexCount(); ++i) {
53         const C2GopLayerStruct &layer = gop.m.values[i];
54         if (layer.count == UINT32_MAX) {
55             syncInt = 0;
56         } else if (syncInt <= UINT32_MAX / (layer.count + 1)) {
57             syncInt *= (layer.count + 1);
58         }
59         if ((layer.type_ & I_FRAME) == 0) {
60             if (layer.count == UINT32_MAX) {
61                 iInt = 0;
62             } else if (iInt <= UINT32_MAX / (layer.count + 1)) {
63                 iInt *= (layer.count + 1);
64             }
65         }
66         if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME) && maxBframes) {
67             *maxBframes = layer.count;
68         }
69     }
70     if (syncInterval) {
71         *syncInterval = syncInt;
72     }
73     if (iInterval) {
74         *iInterval = iInt;
75     }
76 }
77 
78 }  // namespace
79 
80 class C2SoftAvcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
81 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)82     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
83         : SimpleInterface<void>::BaseParams(
84                 helper,
85                 COMPONENT_NAME,
86                 C2Component::KIND_ENCODER,
87                 C2Component::DOMAIN_VIDEO,
88                 MEDIA_MIMETYPE_VIDEO_AVC) {
89         noPrivateBuffers(); // TODO: account for our buffers here
90         noInputReferences();
91         noOutputReferences();
92         noTimeStretch();
93         setDerivedInstance(this);
94 
95         addParameter(
96                 DefineParam(mUsage, C2_PARAMKEY_INPUT_STREAM_USAGE)
97                 .withConstValue(new C2StreamUsageTuning::input(
98                         0u, (uint64_t)C2MemoryUsage::CPU_READ))
99                 .build());
100 
101         addParameter(
102                 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
103                 .withConstValue(new C2ComponentAttributesSetting(
104                     C2Component::ATTRIB_IS_TEMPORAL))
105                 .build());
106 
107         addParameter(
108                 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
109                 .withDefault(new C2StreamPictureSizeInfo::input(0u, 16, 16))
110                 .withFields({
111                     C2F(mSize, width).inRange(2, 2560, 2),
112                     C2F(mSize, height).inRange(2, 2560, 2),
113                 })
114                 .withSetter(SizeSetter)
115                 .build());
116 
117         addParameter(
118                 DefineParam(mGop, C2_PARAMKEY_GOP)
119                 .withDefault(C2StreamGopTuning::output::AllocShared(
120                         0 /* flexCount */, 0u /* stream */))
121                 .withFields({C2F(mGop, m.values[0].type_).any(),
122                              C2F(mGop, m.values[0].count).any()})
123                 .withSetter(GopSetter)
124                 .build());
125 
126         addParameter(
127                 DefineParam(mPictureQuantization, C2_PARAMKEY_PICTURE_QUANTIZATION)
128                 .withDefault(C2StreamPictureQuantizationTuning::output::AllocShared(
129                         0 /* flexCount */, 0u /* stream */))
130                 .withFields({C2F(mPictureQuantization, m.values[0].type_).oneOf(
131                                 {C2Config::picture_type_t(I_FRAME),
132                                   C2Config::picture_type_t(P_FRAME),
133                                   C2Config::picture_type_t(B_FRAME)}),
134                              C2F(mPictureQuantization, m.values[0].min).any(),
135                              C2F(mPictureQuantization, m.values[0].max).any()})
136                 .withSetter(PictureQuantizationSetter)
137                 .build());
138 
139         addParameter(
140                 DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
141                 .withDefault(new C2PortActualDelayTuning::input(DEFAULT_B_FRAMES))
142                 .withFields({C2F(mActualInputDelay, value).inRange(0, MAX_B_FRAMES)})
143                 .calculatedAs(InputDelaySetter, mGop)
144                 .build());
145 
146         addParameter(
147                 DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
148                 .withDefault(new C2StreamFrameRateInfo::output(0u, 1.))
149                 // TODO: More restriction?
150                 .withFields({C2F(mFrameRate, value).greaterThan(0.)})
151                 .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
152                 .build());
153 
154         addParameter(
155                 DefineParam(mBitrateMode, C2_PARAMKEY_BITRATE_MODE)
156                 .withDefault(new C2StreamBitrateModeTuning::output(0u, C2Config::BITRATE_VARIABLE))
157                 .withFields({C2F(mBitrateMode, value).oneOf({
158                                         C2Config::BITRATE_CONST,
159                                         C2Config::BITRATE_VARIABLE,
160                                         C2Config::BITRATE_IGNORE})
161                         })
162                 .withSetter(Setter<decltype(*mBitrateMode)>::StrictValueWithNoDeps)
163                 .build());
164 
165         addParameter(
166                 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
167                 .withDefault(new C2StreamBitrateInfo::output(0u, 64000))
168                 .withFields({C2F(mBitrate, value).inRange(4096, 12000000)})
169                 .withSetter(BitrateSetter)
170                 .build());
171 
172         addParameter(
173                 DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH)
174                 .withDefault(new C2StreamIntraRefreshTuning::output(
175                         0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
176                 .withFields({
177                     C2F(mIntraRefresh, mode).oneOf({
178                         C2Config::INTRA_REFRESH_DISABLED, C2Config::INTRA_REFRESH_ARBITRARY }),
179                     C2F(mIntraRefresh, period).any()
180                 })
181                 .withSetter(IntraRefreshSetter)
182                 .build());
183 
184         addParameter(
185                 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
186                 .withDefault(new C2StreamProfileLevelInfo::output(
187                         0u, PROFILE_AVC_CONSTRAINED_BASELINE, LEVEL_AVC_4_1))
188                 .withFields({
189                     C2F(mProfileLevel, profile).oneOf({
190                         PROFILE_AVC_BASELINE,
191                         PROFILE_AVC_CONSTRAINED_BASELINE,
192                         PROFILE_AVC_MAIN,
193                     }),
194                     C2F(mProfileLevel, level).oneOf({
195                         LEVEL_AVC_1,
196                         LEVEL_AVC_1B,
197                         LEVEL_AVC_1_1,
198                         LEVEL_AVC_1_2,
199                         LEVEL_AVC_1_3,
200                         LEVEL_AVC_2,
201                         LEVEL_AVC_2_1,
202                         LEVEL_AVC_2_2,
203                         LEVEL_AVC_3,
204                         LEVEL_AVC_3_1,
205                         LEVEL_AVC_3_2,
206                         LEVEL_AVC_4,
207                         LEVEL_AVC_4_1,
208                         LEVEL_AVC_4_2,
209                         LEVEL_AVC_5,
210                     }),
211                 })
212                 .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
213                 .build());
214 
215         addParameter(
216                 DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME)
217                 .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
218                 .withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) })
219                 .withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps)
220                 .build());
221 
222         addParameter(
223                 DefineParam(mSyncFramePeriod, C2_PARAMKEY_SYNC_FRAME_INTERVAL)
224                 .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000))
225                 .withFields({C2F(mSyncFramePeriod, value).any()})
226                 .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
227                 .build());
228 
229         addParameter(
230                 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
231                 .withDefault(new C2StreamColorAspectsInfo::input(
232                         0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
233                         C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
234                 .withFields({
235                     C2F(mColorAspects, range).inRange(
236                                 C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
237                     C2F(mColorAspects, primaries).inRange(
238                                 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
239                     C2F(mColorAspects, transfer).inRange(
240                                 C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
241                     C2F(mColorAspects, matrix).inRange(
242                                 C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
243                 })
244                 .withSetter(ColorAspectsSetter)
245                 .build());
246 
247         addParameter(
248                 DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
249                 .withDefault(new C2StreamColorAspectsInfo::output(
250                         0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
251                         C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
252                 .withFields({
253                     C2F(mCodedColorAspects, range).inRange(
254                                 C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
255                     C2F(mCodedColorAspects, primaries).inRange(
256                                 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
257                     C2F(mCodedColorAspects, transfer).inRange(
258                                 C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
259                     C2F(mCodedColorAspects, matrix).inRange(
260                                 C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
261                 })
262                 .withSetter(CodedColorAspectsSetter, mColorAspects)
263                 .build());
264     }
265 
InputDelaySetter(bool mayBlock,C2P<C2PortActualDelayTuning::input> & me,const C2P<C2StreamGopTuning::output> & gop)266     static C2R InputDelaySetter(
267             bool mayBlock,
268             C2P<C2PortActualDelayTuning::input> &me,
269             const C2P<C2StreamGopTuning::output> &gop) {
270         (void)mayBlock;
271         uint32_t maxBframes = 0;
272         ParseGop(gop.v, nullptr, nullptr, &maxBframes);
273         me.set().value = maxBframes;
274         return C2R::Ok();
275     }
276 
BitrateSetter(bool mayBlock,C2P<C2StreamBitrateInfo::output> & me)277     static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) {
278         (void)mayBlock;
279         C2R res = C2R::Ok();
280         if (me.v.value <= 4096) {
281             me.set().value = 4096;
282         }
283         return res;
284     }
285 
286 
SizeSetter(bool mayBlock,const C2P<C2StreamPictureSizeInfo::input> & oldMe,C2P<C2StreamPictureSizeInfo::input> & me)287     static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe,
288                           C2P<C2StreamPictureSizeInfo::input> &me) {
289         (void)mayBlock;
290         C2R res = C2R::Ok();
291         if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
292             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
293             me.set().width = oldMe.v.width;
294         }
295         if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
296             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
297             me.set().height = oldMe.v.height;
298         }
299         return res;
300     }
301 
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::output> & me,const C2P<C2StreamPictureSizeInfo::input> & size,const C2P<C2StreamFrameRateInfo::output> & frameRate,const C2P<C2StreamBitrateInfo::output> & bitrate)302     static C2R ProfileLevelSetter(
303             bool mayBlock,
304             C2P<C2StreamProfileLevelInfo::output> &me,
305             const C2P<C2StreamPictureSizeInfo::input> &size,
306             const C2P<C2StreamFrameRateInfo::output> &frameRate,
307             const C2P<C2StreamBitrateInfo::output> &bitrate) {
308         (void)mayBlock;
309         if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
310             me.set().profile = PROFILE_AVC_CONSTRAINED_BASELINE;
311         }
312 
313         struct LevelLimits {
314             C2Config::level_t level;
315             float mbsPerSec;
316             uint64_t mbs;
317             uint32_t bitrate;
318         };
319         constexpr LevelLimits kLimits[] = {
320             { LEVEL_AVC_1,     1485,    99,     64000 },
321             // Decoder does not properly handle level 1b.
322             // { LEVEL_AVC_1B,    1485,   99,   128000 },
323             { LEVEL_AVC_1_1,   3000,   396,    192000 },
324             { LEVEL_AVC_1_2,   6000,   396,    384000 },
325             { LEVEL_AVC_1_3,  11880,   396,    768000 },
326             { LEVEL_AVC_2,    11880,   396,   2000000 },
327             { LEVEL_AVC_2_1,  19800,   792,   4000000 },
328             { LEVEL_AVC_2_2,  20250,  1620,   4000000 },
329             { LEVEL_AVC_3,    40500,  1620,  10000000 },
330             { LEVEL_AVC_3_1, 108000,  3600,  14000000 },
331             { LEVEL_AVC_3_2, 216000,  5120,  20000000 },
332             { LEVEL_AVC_4,   245760,  8192,  20000000 },
333             { LEVEL_AVC_4_1, 245760,  8192,  50000000 },
334             { LEVEL_AVC_4_2, 522240,  8704,  50000000 },
335             { LEVEL_AVC_5,   589824, 22080, 135000000 },
336         };
337 
338         uint64_t mbs = uint64_t((size.v.width + 15) / 16) * ((size.v.height + 15) / 16);
339         float mbsPerSec = float(mbs) * frameRate.v.value;
340 
341         // Check if the supplied level meets the MB / bitrate requirements. If
342         // not, update the level with the lowest level meeting the requirements.
343 
344         bool found = false;
345         // By default needsUpdate = false in case the supplied level does meet
346         // the requirements. For Level 1b, we want to update the level anyway,
347         // so we set it to true in that case.
348         bool needsUpdate = false;
349         if (me.v.level == LEVEL_AVC_1B || !me.F(me.v.level).supportsAtAll(me.v.level)) {
350             needsUpdate = true;
351         }
352         for (const LevelLimits &limit : kLimits) {
353             if (mbs <= limit.mbs && mbsPerSec <= limit.mbsPerSec &&
354                     bitrate.v.value <= limit.bitrate) {
355                 // This is the lowest level that meets the requirements, and if
356                 // we haven't seen the supplied level yet, that means we don't
357                 // need the update.
358                 if (needsUpdate) {
359                     ALOGD("Given level %x does not cover current configuration: "
360                           "adjusting to %x", me.v.level, limit.level);
361                     me.set().level = limit.level;
362                 }
363                 found = true;
364                 break;
365             }
366             if (me.v.level == limit.level) {
367                 // We break out of the loop when the lowest feasible level is
368                 // found. The fact that we're here means that our level doesn't
369                 // meet the requirement and needs to be updated.
370                 needsUpdate = true;
371             }
372         }
373         if (!found || me.v.level > LEVEL_AVC_5) {
374             // We set to the highest supported level.
375             me.set().level = LEVEL_AVC_5;
376         }
377 
378         return C2R::Ok();
379     }
380 
IntraRefreshSetter(bool mayBlock,C2P<C2StreamIntraRefreshTuning::output> & me)381     static C2R IntraRefreshSetter(bool mayBlock, C2P<C2StreamIntraRefreshTuning::output> &me) {
382         (void)mayBlock;
383         C2R res = C2R::Ok();
384         if (me.v.period < 1) {
385             me.set().mode = C2Config::INTRA_REFRESH_DISABLED;
386             me.set().period = 0;
387         } else {
388             // only support arbitrary mode (cyclic in our case)
389             me.set().mode = C2Config::INTRA_REFRESH_ARBITRARY;
390         }
391         return res;
392     }
393 
GopSetter(bool mayBlock,C2P<C2StreamGopTuning::output> & me)394     static C2R GopSetter(bool mayBlock, C2P<C2StreamGopTuning::output> &me) {
395         (void)mayBlock;
396         for (size_t i = 0; i < me.v.flexCount(); ++i) {
397             const C2GopLayerStruct &layer = me.v.m.values[0];
398             if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME)
399                     && layer.count > MAX_B_FRAMES) {
400                 me.set().m.values[i].count = MAX_B_FRAMES;
401             }
402         }
403         return C2R::Ok();
404     }
405 
PictureQuantizationSetter(bool mayBlock,C2P<C2StreamPictureQuantizationTuning::output> & me)406     static C2R PictureQuantizationSetter(bool mayBlock,
407                                          C2P<C2StreamPictureQuantizationTuning::output> &me) {
408         (void)mayBlock;
409 
410         // these are the ones we're going to set, so want them to default
411         // to the DEFAULT values for the codec
412         int32_t iMin = DEFAULT_I_QP_MIN, pMin = DEFAULT_P_QP_MIN, bMin = DEFAULT_B_QP_MIN;
413         int32_t iMax = DEFAULT_I_QP_MAX, pMax = DEFAULT_P_QP_MAX, bMax = DEFAULT_B_QP_MAX;
414 
415         for (size_t i = 0; i < me.v.flexCount(); ++i) {
416             const C2PictureQuantizationStruct &layer = me.v.m.values[i];
417 
418             if (layer.type_ == C2Config::picture_type_t(I_FRAME)) {
419                 iMax = layer.max;
420                 iMin = layer.min;
421                 ALOGV("iMin %d iMax %d", iMin, iMax);
422             } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) {
423                 pMax = layer.max;
424                 pMin = layer.min;
425                 ALOGV("pMin %d pMax %d", pMin, pMax);
426             } else if (layer.type_ == C2Config::picture_type_t(B_FRAME)) {
427                 bMax = layer.max;
428                 bMin = layer.min;
429                 ALOGV("bMin %d bMax %d", bMin, bMax);
430             }
431         }
432 
433         ALOGV("PictureQuantizationSetter(entry): i %d-%d p %d-%d b %d-%d",
434               iMin, iMax, pMin, pMax, bMin, bMax);
435 
436         // min is clamped to [AVC_QP_MIN, max] to avoid error
437         // cases where layer.min > layer.max
438         iMax = std::clamp(iMax, AVC_QP_MIN, AVC_QP_MAX);
439         iMin = std::clamp(iMin, AVC_QP_MIN, iMax);
440         pMax = std::clamp(pMax, AVC_QP_MIN, AVC_QP_MAX);
441         pMin = std::clamp(pMin, AVC_QP_MIN, pMax);
442         bMax = std::clamp(bMax, AVC_QP_MIN, AVC_QP_MAX);
443         bMin = std::clamp(bMin, AVC_QP_MIN, bMax);
444 
445         // put them back into the structure
446         for (size_t i = 0; i < me.v.flexCount(); ++i) {
447             const C2PictureQuantizationStruct &layer = me.v.m.values[i];
448 
449             if (layer.type_ == C2Config::picture_type_t(I_FRAME)) {
450                 me.set().m.values[i].max = iMax;
451                 me.set().m.values[i].min = iMin;
452             }
453             if (layer.type_ == C2Config::picture_type_t(P_FRAME)) {
454                 me.set().m.values[i].max = pMax;
455                 me.set().m.values[i].min = pMin;
456             }
457             if (layer.type_ == C2Config::picture_type_t(B_FRAME)) {
458                 me.set().m.values[i].max = bMax;
459                 me.set().m.values[i].min = bMin;
460             }
461         }
462 
463         ALOGV("PictureQuantizationSetter(exit): i %d-%d p %d-%d b %d-%d",
464               iMin, iMax, pMin, pMax, bMin, bMax);
465 
466         return C2R::Ok();
467     }
468 
ColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::input> & me)469     static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
470         (void)mayBlock;
471         if (me.v.range > C2Color::RANGE_OTHER) {
472                 me.set().range = C2Color::RANGE_OTHER;
473         }
474         if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
475                 me.set().primaries = C2Color::PRIMARIES_OTHER;
476         }
477         if (me.v.transfer > C2Color::TRANSFER_OTHER) {
478                 me.set().transfer = C2Color::TRANSFER_OTHER;
479         }
480         if (me.v.matrix > C2Color::MATRIX_OTHER) {
481                 me.set().matrix = C2Color::MATRIX_OTHER;
482         }
483         return C2R::Ok();
484     }
485 
CodedColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::output> & me,const C2P<C2StreamColorAspectsInfo::input> & coded)486     static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
487                                        const C2P<C2StreamColorAspectsInfo::input> &coded) {
488         (void)mayBlock;
489         me.set().range = coded.v.range;
490         me.set().primaries = coded.v.primaries;
491         me.set().transfer = coded.v.transfer;
492         me.set().matrix = coded.v.matrix;
493         return C2R::Ok();
494     }
495 
getProfile_l() const496     IV_PROFILE_T getProfile_l() const {
497         switch (mProfileLevel->profile) {
498         case PROFILE_AVC_CONSTRAINED_BASELINE:  [[fallthrough]];
499         case PROFILE_AVC_BASELINE: return IV_PROFILE_BASE;
500         case PROFILE_AVC_MAIN:     return IV_PROFILE_MAIN;
501         default:
502             ALOGD("Unrecognized profile: %x", mProfileLevel->profile);
503             return IV_PROFILE_DEFAULT;
504         }
505     }
506 
getLevel_l() const507     UWORD32 getLevel_l() const {
508         struct Level {
509             C2Config::level_t c2Level;
510             UWORD32 avcLevel;
511         };
512         constexpr Level levels[] = {
513             { LEVEL_AVC_1,   10 },
514             { LEVEL_AVC_1B,   9 },
515             { LEVEL_AVC_1_1, 11 },
516             { LEVEL_AVC_1_2, 12 },
517             { LEVEL_AVC_1_3, 13 },
518             { LEVEL_AVC_2,   20 },
519             { LEVEL_AVC_2_1, 21 },
520             { LEVEL_AVC_2_2, 22 },
521             { LEVEL_AVC_3,   30 },
522             { LEVEL_AVC_3_1, 31 },
523             { LEVEL_AVC_3_2, 32 },
524             { LEVEL_AVC_4,   40 },
525             { LEVEL_AVC_4_1, 41 },
526             { LEVEL_AVC_4_2, 42 },
527             { LEVEL_AVC_5,   50 },
528         };
529         for (const Level &level : levels) {
530             if (mProfileLevel->level == level.c2Level) {
531                 return level.avcLevel;
532             }
533         }
534         ALOGD("Unrecognized level: %x", mProfileLevel->level);
535         return 41;
536     }
537 
getSyncFramePeriod_l() const538     uint32_t getSyncFramePeriod_l() const {
539         if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) {
540             return 0;
541         }
542         double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value;
543         return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
544     }
545 
546     // unsafe getters
getSize_l() const547     std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const { return mSize; }
getIntraRefresh_l() const548     std::shared_ptr<C2StreamIntraRefreshTuning::output> getIntraRefresh_l() const { return mIntraRefresh; }
getFrameRate_l() const549     std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; }
getBitrateMode_l() const550     std::shared_ptr<C2StreamBitrateModeTuning::output> getBitrateMode_l() const {
551         return mBitrateMode;
552     }
getBitrate_l() const553     std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; }
getRequestSync_l() const554     std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; }
getGop_l() const555     std::shared_ptr<C2StreamGopTuning::output> getGop_l() const { return mGop; }
getPictureQuantization_l() const556     std::shared_ptr<C2StreamPictureQuantizationTuning::output> getPictureQuantization_l() const
557     { return mPictureQuantization; }
getCodedColorAspects_l() const558     std::shared_ptr<C2StreamColorAspectsInfo::output> getCodedColorAspects_l() const {
559         return mCodedColorAspects;
560     }
561 
562 private:
563     std::shared_ptr<C2StreamUsageTuning::input> mUsage;
564     std::shared_ptr<C2StreamPictureSizeInfo::input> mSize;
565     std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
566     std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
567     std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh;
568     std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
569     std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
570     std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
571     std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
572     std::shared_ptr<C2StreamGopTuning::output> mGop;
573     std::shared_ptr<C2StreamPictureQuantizationTuning::output> mPictureQuantization;
574     std::shared_ptr<C2StreamColorAspectsInfo::input> mColorAspects;
575     std::shared_ptr<C2StreamColorAspectsInfo::output> mCodedColorAspects;
576 };
577 
578 #define ive_api_function  ih264e_api_function
579 
580 namespace {
581 
582 // From external/libavc/encoder/ih264e_bitstream.h
583 constexpr uint32_t MIN_STREAM_SIZE = 0x800;
584 
GetCPUCoreCount()585 static size_t GetCPUCoreCount() {
586     long cpuCoreCount = 1;
587 #if defined(_SC_NPROCESSORS_ONLN)
588     cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
589 #else
590     // _SC_NPROC_ONLN must be defined...
591     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
592 #endif
593     CHECK(cpuCoreCount >= 1);
594     ALOGV("Number of CPU cores: %ld", cpuCoreCount);
595     return (size_t)cpuCoreCount;
596 }
597 
598 }  // namespace
599 
C2SoftAvcEnc(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)600 C2SoftAvcEnc::C2SoftAvcEnc(
601         const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl)
602     : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
603       mIntf(intfImpl),
604       mIvVideoColorFormat(IV_YUV_420P),
605       mAVCEncProfile(IV_PROFILE_BASE),
606       mAVCEncLevel(41),
607       mStarted(false),
608       mSawInputEOS(false),
609       mSignalledError(false),
610       mCodecCtx(nullptr),
611       mOutBlock(nullptr),
612       mOutBufferSize(kMinOutBufferSize) {
613 
614     // If dump is enabled, then open create an empty file
615     GENERATE_FILE_NAMES();
616     CREATE_DUMP_FILE(mInFile);
617     CREATE_DUMP_FILE(mOutFile);
618 
619     initEncParams();
620 }
621 
C2SoftAvcEnc(const char * name,c2_node_id_t id,const std::shared_ptr<C2ReflectorHelper> & helper)622 C2SoftAvcEnc::C2SoftAvcEnc(
623         const char *name, c2_node_id_t id, const std::shared_ptr<C2ReflectorHelper> &helper)
624     : C2SoftAvcEnc(name, id, std::make_shared<IntfImpl>(helper)) {
625 }
626 
~C2SoftAvcEnc()627 C2SoftAvcEnc::~C2SoftAvcEnc() {
628     onRelease();
629 }
630 
onInit()631 c2_status_t C2SoftAvcEnc::onInit() {
632     return C2_OK;
633 }
634 
onStop()635 c2_status_t C2SoftAvcEnc::onStop() {
636     return C2_OK;
637 }
638 
onReset()639 void C2SoftAvcEnc::onReset() {
640     // TODO: use IVE_CMD_CTL_RESET?
641     releaseEncoder();
642     if (mOutBlock) {
643         mOutBlock.reset();
644     }
645     initEncParams();
646 }
647 
onRelease()648 void C2SoftAvcEnc::onRelease() {
649     releaseEncoder();
650     if (mOutBlock) {
651         mOutBlock.reset();
652     }
653 }
654 
onFlush_sm()655 c2_status_t C2SoftAvcEnc::onFlush_sm() {
656     // TODO: use IVE_CMD_CTL_FLUSH?
657     return C2_OK;
658 }
659 
initEncParams()660 void  C2SoftAvcEnc::initEncParams() {
661     mCodecCtx = nullptr;
662     mMemRecords = nullptr;
663     mNumMemRecords = DEFAULT_MEM_REC_CNT;
664     mHeaderGenerated = 0;
665     mNumCores = GetCPUCoreCount();
666     mArch = DEFAULT_ARCH;
667     mSliceMode = DEFAULT_SLICE_MODE;
668     mSliceParam = DEFAULT_SLICE_PARAM;
669     mHalfPelEnable = DEFAULT_HPEL;
670     mIInterval = DEFAULT_I_INTERVAL;
671     mIDRInterval = DEFAULT_IDR_INTERVAL;
672     mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
673     mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
674     mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
675     mEncSpeed = DEFAULT_ENC_SPEED;
676     mIntra4x4 = DEFAULT_INTRA4x4;
677     mConstrainedIntraFlag = DEFAULT_CONSTRAINED_INTRA;
678     mPSNREnable = DEFAULT_PSNR_ENABLE;
679     mReconEnable = DEFAULT_RECON_ENABLE;
680     mEntropyMode = DEFAULT_ENTROPY_MODE;
681     mBframes = DEFAULT_B_FRAMES;
682 
683     mTimeStart = mTimeEnd = systemTime();
684 }
685 
setDimensions()686 c2_status_t C2SoftAvcEnc::setDimensions() {
687     ive_ctl_set_dimensions_ip_t s_dimensions_ip;
688     ive_ctl_set_dimensions_op_t s_dimensions_op;
689     IV_STATUS_T status;
690 
691     s_dimensions_ip.e_cmd = IVE_CMD_VIDEO_CTL;
692     s_dimensions_ip.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
693     s_dimensions_ip.u4_ht = mSize->height;
694     s_dimensions_ip.u4_wd = mSize->width;
695 
696     s_dimensions_ip.u4_timestamp_high = -1;
697     s_dimensions_ip.u4_timestamp_low = -1;
698 
699     s_dimensions_ip.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
700     s_dimensions_op.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
701 
702     status = ive_api_function(mCodecCtx, &s_dimensions_ip, &s_dimensions_op);
703     if (status != IV_SUCCESS) {
704         ALOGE("Unable to set frame dimensions = 0x%x\n",
705                 s_dimensions_op.u4_error_code);
706         return C2_CORRUPTED;
707     }
708     return C2_OK;
709 }
710 
setNumCores()711 c2_status_t C2SoftAvcEnc::setNumCores() {
712     IV_STATUS_T status;
713     ive_ctl_set_num_cores_ip_t s_num_cores_ip;
714     ive_ctl_set_num_cores_op_t s_num_cores_op;
715     s_num_cores_ip.e_cmd = IVE_CMD_VIDEO_CTL;
716     s_num_cores_ip.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
717     s_num_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_CORES);
718     s_num_cores_ip.u4_timestamp_high = -1;
719     s_num_cores_ip.u4_timestamp_low = -1;
720     s_num_cores_ip.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
721 
722     s_num_cores_op.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
723 
724     status = ive_api_function(
725             mCodecCtx, (void *) &s_num_cores_ip, (void *) &s_num_cores_op);
726     if (status != IV_SUCCESS) {
727         ALOGE("Unable to set processor params = 0x%x\n",
728                 s_num_cores_op.u4_error_code);
729         return C2_CORRUPTED;
730     }
731     return C2_OK;
732 }
733 
setFrameRate()734 c2_status_t C2SoftAvcEnc::setFrameRate() {
735     ive_ctl_set_frame_rate_ip_t s_frame_rate_ip;
736     ive_ctl_set_frame_rate_op_t s_frame_rate_op;
737     IV_STATUS_T status;
738 
739     s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
740     s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
741 
742     s_frame_rate_ip.u4_src_frame_rate = mFrameRate->value + 0.5;
743     s_frame_rate_ip.u4_tgt_frame_rate = mFrameRate->value + 0.5;
744 
745     s_frame_rate_ip.u4_timestamp_high = -1;
746     s_frame_rate_ip.u4_timestamp_low = -1;
747 
748     s_frame_rate_ip.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
749     s_frame_rate_op.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
750 
751     status = ive_api_function(mCodecCtx, &s_frame_rate_ip, &s_frame_rate_op);
752     if (status != IV_SUCCESS) {
753         ALOGE("Unable to set frame rate = 0x%x\n",
754                 s_frame_rate_op.u4_error_code);
755         return C2_CORRUPTED;
756     }
757     return C2_OK;
758 }
759 
setIpeParams()760 c2_status_t C2SoftAvcEnc::setIpeParams() {
761     ive_ctl_set_ipe_params_ip_t s_ipe_params_ip;
762     ive_ctl_set_ipe_params_op_t s_ipe_params_op;
763     IV_STATUS_T status;
764 
765     s_ipe_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
766     s_ipe_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
767 
768     s_ipe_params_ip.u4_enable_intra_4x4 = mIntra4x4;
769     s_ipe_params_ip.u4_enc_speed_preset = mEncSpeed;
770     s_ipe_params_ip.u4_constrained_intra_pred = mConstrainedIntraFlag;
771 
772     s_ipe_params_ip.u4_timestamp_high = -1;
773     s_ipe_params_ip.u4_timestamp_low = -1;
774 
775     s_ipe_params_ip.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
776     s_ipe_params_op.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
777 
778     status = ive_api_function(mCodecCtx, &s_ipe_params_ip, &s_ipe_params_op);
779     if (status != IV_SUCCESS) {
780         ALOGE("Unable to set ipe params = 0x%x\n",
781                 s_ipe_params_op.u4_error_code);
782         return C2_CORRUPTED;
783     }
784     return C2_OK;
785 }
786 
setBitRate()787 c2_status_t C2SoftAvcEnc::setBitRate() {
788     ive_ctl_set_bitrate_ip_t s_bitrate_ip;
789     ive_ctl_set_bitrate_op_t s_bitrate_op;
790     IV_STATUS_T status;
791 
792     s_bitrate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
793     s_bitrate_ip.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
794 
795     s_bitrate_ip.u4_target_bitrate = mBitrate->value;
796 
797     s_bitrate_ip.u4_timestamp_high = -1;
798     s_bitrate_ip.u4_timestamp_low = -1;
799 
800     s_bitrate_ip.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
801     s_bitrate_op.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
802 
803     status = ive_api_function(mCodecCtx, &s_bitrate_ip, &s_bitrate_op);
804     if (status != IV_SUCCESS) {
805         ALOGE("Unable to set bit rate = 0x%x\n", s_bitrate_op.u4_error_code);
806         return C2_CORRUPTED;
807     }
808     return C2_OK;
809 }
810 
setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type)811 c2_status_t C2SoftAvcEnc::setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type) {
812     ive_ctl_set_frame_type_ip_t s_frame_type_ip;
813     ive_ctl_set_frame_type_op_t s_frame_type_op;
814     IV_STATUS_T status;
815     s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
816     s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
817 
818     s_frame_type_ip.e_frame_type = e_frame_type;
819 
820     s_frame_type_ip.u4_timestamp_high = -1;
821     s_frame_type_ip.u4_timestamp_low = -1;
822 
823     s_frame_type_ip.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
824     s_frame_type_op.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
825 
826     status = ive_api_function(mCodecCtx, &s_frame_type_ip, &s_frame_type_op);
827     if (status != IV_SUCCESS) {
828         ALOGE("Unable to set frame type = 0x%x\n",
829                 s_frame_type_op.u4_error_code);
830         return C2_CORRUPTED;
831     }
832     return C2_OK;
833 }
834 
setQp()835 c2_status_t C2SoftAvcEnc::setQp() {
836     ive_ctl_set_qp_ip_t s_qp_ip;
837     ive_ctl_set_qp_op_t s_qp_op;
838     IV_STATUS_T status;
839 
840     ALOGV("in setQp()");
841 
842     // set the defaults
843     s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
844     s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
845 
846     // we resolved out-of-bound and unspecified values in PictureQuantizationSetter()
847     // so we can start with defaults that are overridden as needed.
848     int32_t iMin = DEFAULT_I_QP_MIN, pMin = DEFAULT_P_QP_MIN, bMin = DEFAULT_B_QP_MIN;
849     int32_t iMax = DEFAULT_I_QP_MAX, pMax = DEFAULT_P_QP_MAX, bMax = DEFAULT_B_QP_MAX;
850 
851     IntfImpl::Lock lock = mIntf->lock();
852 
853     std::shared_ptr<C2StreamPictureQuantizationTuning::output> qp =
854                     mIntf->getPictureQuantization_l();
855     for (size_t i = 0; i < qp->flexCount(); ++i) {
856         const C2PictureQuantizationStruct &layer = qp->m.values[i];
857 
858         if (layer.type_ == C2Config::picture_type_t(I_FRAME)) {
859             iMax = layer.max;
860             iMin = layer.min;
861             ALOGV("iMin %d iMax %d", iMin, iMax);
862         } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) {
863             pMax = layer.max;
864             pMin = layer.min;
865             ALOGV("pMin %d pMax %d", pMin, pMax);
866         } else if (layer.type_ == C2Config::picture_type_t(B_FRAME)) {
867             bMax = layer.max;
868             bMin = layer.min;
869             ALOGV("bMin %d bMax %d", bMin, bMax);
870         }
871     }
872 
873     s_qp_ip.u4_i_qp_max = iMax;
874     s_qp_ip.u4_i_qp_min = iMin;
875     s_qp_ip.u4_p_qp_max = pMax;
876     s_qp_ip.u4_p_qp_min = pMin;
877     s_qp_ip.u4_b_qp_max = bMax;
878     s_qp_ip.u4_b_qp_min = bMin;
879 
880     // ensure initial qp values are within our newly configured bounds...
881     s_qp_ip.u4_i_qp = std::clamp(DEFAULT_I_QP, iMin, iMax);
882     s_qp_ip.u4_p_qp = std::clamp(DEFAULT_P_QP, pMin, pMax);
883     s_qp_ip.u4_b_qp = std::clamp(DEFAULT_B_QP, bMin, bMax);
884 
885     ALOGV("setQp(): i %d-%d p %d-%d b %d-%d", iMin, iMax, pMin, pMax, bMin, bMax);
886 
887 
888     s_qp_ip.u4_timestamp_high = -1;
889     s_qp_ip.u4_timestamp_low = -1;
890 
891     s_qp_ip.u4_size = sizeof(ive_ctl_set_qp_ip_t);
892     s_qp_op.u4_size = sizeof(ive_ctl_set_qp_op_t);
893 
894     status = ive_api_function(mCodecCtx, &s_qp_ip, &s_qp_op);
895     if (status != IV_SUCCESS) {
896         ALOGE("Unable to set qp 0x%x\n", s_qp_op.u4_error_code);
897         return C2_CORRUPTED;
898     }
899     return C2_OK;
900 }
901 
setEncMode(IVE_ENC_MODE_T e_enc_mode)902 c2_status_t C2SoftAvcEnc::setEncMode(IVE_ENC_MODE_T e_enc_mode) {
903     IV_STATUS_T status;
904     ive_ctl_set_enc_mode_ip_t s_enc_mode_ip;
905     ive_ctl_set_enc_mode_op_t s_enc_mode_op;
906 
907     s_enc_mode_ip.e_cmd = IVE_CMD_VIDEO_CTL;
908     s_enc_mode_ip.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
909 
910     s_enc_mode_ip.e_enc_mode = e_enc_mode;
911 
912     s_enc_mode_ip.u4_timestamp_high = -1;
913     s_enc_mode_ip.u4_timestamp_low = -1;
914 
915     s_enc_mode_ip.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
916     s_enc_mode_op.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
917 
918     status = ive_api_function(mCodecCtx, &s_enc_mode_ip, &s_enc_mode_op);
919     if (status != IV_SUCCESS) {
920         ALOGE("Unable to set in header encode mode = 0x%x\n",
921                 s_enc_mode_op.u4_error_code);
922         return C2_CORRUPTED;
923     }
924     return C2_OK;
925 }
926 
setVbvParams()927 c2_status_t C2SoftAvcEnc::setVbvParams() {
928     ive_ctl_set_vbv_params_ip_t s_vbv_ip;
929     ive_ctl_set_vbv_params_op_t s_vbv_op;
930     IV_STATUS_T status;
931 
932     s_vbv_ip.e_cmd = IVE_CMD_VIDEO_CTL;
933     s_vbv_ip.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
934 
935     s_vbv_ip.u4_vbv_buf_size = 0;
936     s_vbv_ip.u4_vbv_buffer_delay = 1000;
937 
938     s_vbv_ip.u4_timestamp_high = -1;
939     s_vbv_ip.u4_timestamp_low = -1;
940 
941     s_vbv_ip.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
942     s_vbv_op.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
943 
944     status = ive_api_function(mCodecCtx, &s_vbv_ip, &s_vbv_op);
945     if (status != IV_SUCCESS) {
946         ALOGE("Unable to set VBV params = 0x%x\n", s_vbv_op.u4_error_code);
947         return C2_CORRUPTED;
948     }
949     return C2_OK;
950 }
951 
setAirParams()952 c2_status_t C2SoftAvcEnc::setAirParams() {
953     ive_ctl_set_air_params_ip_t s_air_ip;
954     ive_ctl_set_air_params_op_t s_air_op;
955     IV_STATUS_T status;
956 
957     s_air_ip.e_cmd = IVE_CMD_VIDEO_CTL;
958     s_air_ip.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
959 
960     s_air_ip.e_air_mode =
961         (mIntraRefresh->mode == C2Config::INTRA_REFRESH_DISABLED || mIntraRefresh->period < 1)
962             ? IVE_AIR_MODE_NONE : IVE_AIR_MODE_CYCLIC;
963     s_air_ip.u4_air_refresh_period = mIntraRefresh->period;
964 
965     s_air_ip.u4_timestamp_high = -1;
966     s_air_ip.u4_timestamp_low = -1;
967 
968     s_air_ip.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
969     s_air_op.u4_size = sizeof(ive_ctl_set_air_params_op_t);
970 
971     status = ive_api_function(mCodecCtx, &s_air_ip, &s_air_op);
972     if (status != IV_SUCCESS) {
973         ALOGE("Unable to set air params = 0x%x\n", s_air_op.u4_error_code);
974         return C2_CORRUPTED;
975     }
976     return C2_OK;
977 }
978 
setMeParams()979 c2_status_t C2SoftAvcEnc::setMeParams() {
980     IV_STATUS_T status;
981     ive_ctl_set_me_params_ip_t s_me_params_ip;
982     ive_ctl_set_me_params_op_t s_me_params_op;
983 
984     s_me_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
985     s_me_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
986 
987     s_me_params_ip.u4_enable_fast_sad = mEnableFastSad;
988     s_me_params_ip.u4_enable_alt_ref = mEnableAltRef;
989 
990     s_me_params_ip.u4_enable_hpel = mHalfPelEnable;
991     s_me_params_ip.u4_enable_qpel = DEFAULT_QPEL;
992     s_me_params_ip.u4_me_speed_preset = DEFAULT_ME_SPEED;
993     s_me_params_ip.u4_srch_rng_x = DEFAULT_SRCH_RNG_X;
994     s_me_params_ip.u4_srch_rng_y = DEFAULT_SRCH_RNG_Y;
995 
996     s_me_params_ip.u4_timestamp_high = -1;
997     s_me_params_ip.u4_timestamp_low = -1;
998 
999     s_me_params_ip.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
1000     s_me_params_op.u4_size = sizeof(ive_ctl_set_me_params_op_t);
1001 
1002     status = ive_api_function(mCodecCtx, &s_me_params_ip, &s_me_params_op);
1003     if (status != IV_SUCCESS) {
1004         ALOGE("Unable to set me params = 0x%x\n", s_me_params_op.u4_error_code);
1005         return C2_CORRUPTED;
1006     }
1007     return C2_OK;
1008 }
1009 
setGopParams()1010 c2_status_t C2SoftAvcEnc::setGopParams() {
1011     IV_STATUS_T status;
1012     ive_ctl_set_gop_params_ip_t s_gop_params_ip;
1013     ive_ctl_set_gop_params_op_t s_gop_params_op;
1014 
1015     s_gop_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
1016     s_gop_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
1017 
1018     s_gop_params_ip.u4_i_frm_interval = mIInterval;
1019     s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
1020 
1021     s_gop_params_ip.u4_timestamp_high = -1;
1022     s_gop_params_ip.u4_timestamp_low = -1;
1023 
1024     s_gop_params_ip.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
1025     s_gop_params_op.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
1026 
1027     status = ive_api_function(mCodecCtx, &s_gop_params_ip, &s_gop_params_op);
1028     if (status != IV_SUCCESS) {
1029         ALOGE("Unable to set GOP params = 0x%x\n",
1030                 s_gop_params_op.u4_error_code);
1031         return C2_CORRUPTED;
1032     }
1033     return C2_OK;
1034 }
1035 
setProfileParams()1036 c2_status_t C2SoftAvcEnc::setProfileParams() {
1037     IntfImpl::Lock lock = mIntf->lock();
1038 
1039     IV_STATUS_T status;
1040     ive_ctl_set_profile_params_ip_t s_profile_params_ip;
1041     ive_ctl_set_profile_params_op_t s_profile_params_op;
1042 
1043     s_profile_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
1044     s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
1045 
1046     s_profile_params_ip.e_profile = mIntf->getProfile_l();
1047     if (s_profile_params_ip.e_profile == IV_PROFILE_BASE) {
1048         s_profile_params_ip.u4_entropy_coding_mode = 0;
1049     } else {
1050         s_profile_params_ip.u4_entropy_coding_mode = 1;
1051     }
1052     s_profile_params_ip.u4_timestamp_high = -1;
1053     s_profile_params_ip.u4_timestamp_low = -1;
1054 
1055     s_profile_params_ip.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
1056     s_profile_params_op.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
1057     lock.unlock();
1058 
1059     status = ive_api_function(mCodecCtx, &s_profile_params_ip, &s_profile_params_op);
1060     if (status != IV_SUCCESS) {
1061         ALOGE("Unable to set profile params = 0x%x\n",
1062                 s_profile_params_op.u4_error_code);
1063         return C2_CORRUPTED;
1064     }
1065     return C2_OK;
1066 }
1067 
setDeblockParams()1068 c2_status_t C2SoftAvcEnc::setDeblockParams() {
1069     IV_STATUS_T status;
1070     ive_ctl_set_deblock_params_ip_t s_deblock_params_ip;
1071     ive_ctl_set_deblock_params_op_t s_deblock_params_op;
1072 
1073     s_deblock_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
1074     s_deblock_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
1075 
1076     s_deblock_params_ip.u4_disable_deblock_level = mDisableDeblkLevel;
1077 
1078     s_deblock_params_ip.u4_timestamp_high = -1;
1079     s_deblock_params_ip.u4_timestamp_low = -1;
1080 
1081     s_deblock_params_ip.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
1082     s_deblock_params_op.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
1083 
1084     status = ive_api_function(mCodecCtx, &s_deblock_params_ip, &s_deblock_params_op);
1085     if (status != IV_SUCCESS) {
1086         ALOGE("Unable to enable/disable deblock params = 0x%x\n",
1087                 s_deblock_params_op.u4_error_code);
1088         return C2_CORRUPTED;
1089     }
1090     return C2_OK;
1091 }
1092 
logVersion()1093 void C2SoftAvcEnc::logVersion() {
1094     ive_ctl_getversioninfo_ip_t s_ctl_ip;
1095     ive_ctl_getversioninfo_op_t s_ctl_op;
1096     UWORD8 au1_buf[512];
1097     IV_STATUS_T status;
1098 
1099     s_ctl_ip.e_cmd = IVE_CMD_VIDEO_CTL;
1100     s_ctl_ip.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
1101     s_ctl_ip.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
1102     s_ctl_op.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
1103     s_ctl_ip.pu1_version = au1_buf;
1104     s_ctl_ip.u4_version_bufsize = sizeof(au1_buf);
1105 
1106     status = ive_api_function(mCodecCtx, (void *) &s_ctl_ip, (void *) &s_ctl_op);
1107 
1108     if (status != IV_SUCCESS) {
1109         ALOGE("Error in getting version: 0x%x", s_ctl_op.u4_error_code);
1110     } else {
1111         ALOGV("Ittiam encoder version: %s", (char *)s_ctl_ip.pu1_version);
1112     }
1113     return;
1114 }
1115 
setVuiParams()1116 c2_status_t C2SoftAvcEnc::setVuiParams()
1117 {
1118     ColorAspects sfAspects;
1119     if (!C2Mapper::map(mColorAspects->primaries, &sfAspects.mPrimaries)) {
1120         sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
1121     }
1122     if (!C2Mapper::map(mColorAspects->range, &sfAspects.mRange)) {
1123         sfAspects.mRange = android::ColorAspects::RangeUnspecified;
1124     }
1125     if (!C2Mapper::map(mColorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
1126         sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
1127     }
1128     if (!C2Mapper::map(mColorAspects->transfer, &sfAspects.mTransfer)) {
1129         sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
1130     }
1131     int32_t primaries, transfer, matrixCoeffs;
1132     bool range;
1133     ColorUtils::convertCodecColorAspectsToIsoAspects(sfAspects,
1134             &primaries,
1135             &transfer,
1136             &matrixCoeffs,
1137             &range);
1138     ih264e_vui_ip_t s_vui_params_ip {};
1139     ih264e_vui_op_t s_vui_params_op {};
1140 
1141     s_vui_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
1142     s_vui_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_VUI_PARAMS;
1143 
1144     s_vui_params_ip.u1_video_signal_type_present_flag = 1;
1145     s_vui_params_ip.u1_colour_description_present_flag = 1;
1146     s_vui_params_ip.u1_colour_primaries = primaries;
1147     s_vui_params_ip.u1_transfer_characteristics = transfer;
1148     s_vui_params_ip.u1_matrix_coefficients = matrixCoeffs;
1149     s_vui_params_ip.u1_video_full_range_flag = range;
1150 
1151     s_vui_params_ip.u4_size = sizeof(ih264e_vui_ip_t);
1152     s_vui_params_op.u4_size = sizeof(ih264e_vui_op_t);
1153 
1154     IV_STATUS_T status = ih264e_api_function(mCodecCtx, &s_vui_params_ip,
1155                                              &s_vui_params_op);
1156     if(status != IV_SUCCESS)
1157     {
1158         ALOGE("Unable to set vui params = 0x%x\n",
1159                 s_vui_params_op.u4_error_code);
1160         return C2_CORRUPTED;
1161     }
1162     return C2_OK;
1163 }
1164 
initEncoder()1165 c2_status_t C2SoftAvcEnc::initEncoder() {
1166     IV_STATUS_T status;
1167     WORD32 level;
1168 
1169     CHECK(!mStarted);
1170 
1171     c2_status_t errType = C2_OK;
1172 
1173     std::shared_ptr<C2StreamGopTuning::output> gop;
1174     {
1175         IntfImpl::Lock lock = mIntf->lock();
1176         mSize = mIntf->getSize_l();
1177         mBitrateMode = mIntf->getBitrateMode_l();
1178         mBitrate = mIntf->getBitrate_l();
1179         mFrameRate = mIntf->getFrameRate_l();
1180         mIntraRefresh = mIntf->getIntraRefresh_l();
1181         mAVCEncLevel = mIntf->getLevel_l();
1182         mIInterval = mIntf->getSyncFramePeriod_l();
1183         mIDRInterval = mIntf->getSyncFramePeriod_l();
1184         gop = mIntf->getGop_l();
1185         mColorAspects = mIntf->getCodedColorAspects_l();
1186     }
1187     if (gop && gop->flexCount() > 0) {
1188         uint32_t syncInterval = 1;
1189         uint32_t iInterval = 1;
1190         uint32_t maxBframes = 0;
1191         ParseGop(*gop, &syncInterval, &iInterval, &maxBframes);
1192         if (syncInterval > 0) {
1193             ALOGD("Updating IDR interval from GOP: old %u new %u", mIDRInterval, syncInterval);
1194             mIDRInterval = syncInterval;
1195         }
1196         if (iInterval > 0) {
1197             ALOGD("Updating I interval from GOP: old %u new %u", mIInterval, iInterval);
1198             mIInterval = iInterval;
1199         }
1200         if (mBframes != maxBframes) {
1201             ALOGD("Updating max B frames from GOP: old %u new %u", mBframes, maxBframes);
1202             mBframes = maxBframes;
1203         }
1204     }
1205     uint32_t width = mSize->width;
1206     uint32_t height = mSize->height;
1207 
1208     mStride = width;
1209 
1210     // Assume worst case output buffer size to be equal to number of bytes in input
1211     mOutBufferSize = std::max(width * height * 3 / 2, kMinOutBufferSize);
1212 
1213     // TODO
1214     mIvVideoColorFormat = IV_YUV_420P;
1215 
1216     ALOGD("Params width %d height %d level %d colorFormat %d bframes %d", width,
1217             height, mAVCEncLevel, mIvVideoColorFormat, mBframes);
1218 
1219     /* Getting Number of MemRecords */
1220     {
1221         iv_num_mem_rec_ip_t s_num_mem_rec_ip;
1222         iv_num_mem_rec_op_t s_num_mem_rec_op;
1223 
1224         s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
1225         s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
1226 
1227         s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
1228 
1229         status = ive_api_function(nullptr, &s_num_mem_rec_ip, &s_num_mem_rec_op);
1230 
1231         if (status != IV_SUCCESS) {
1232             ALOGE("Get number of memory records failed = 0x%x\n",
1233                     s_num_mem_rec_op.u4_error_code);
1234             return C2_CORRUPTED;
1235         }
1236 
1237         mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
1238     }
1239 
1240     /* Allocate array to hold memory records */
1241     if (mNumMemRecords > SIZE_MAX / sizeof(iv_mem_rec_t)) {
1242         ALOGE("requested memory size is too big.");
1243         return C2_CORRUPTED;
1244     }
1245     mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
1246     if (nullptr == mMemRecords) {
1247         ALOGE("Unable to allocate memory for hold memory records: Size %zu",
1248                 mNumMemRecords * sizeof(iv_mem_rec_t));
1249         mSignalledError = true;
1250         return C2_CORRUPTED;
1251     }
1252 
1253     {
1254         iv_mem_rec_t *ps_mem_rec;
1255         ps_mem_rec = mMemRecords;
1256         for (size_t i = 0; i < mNumMemRecords; i++) {
1257             ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
1258             ps_mem_rec->pv_base = nullptr;
1259             ps_mem_rec->u4_mem_size = 0;
1260             ps_mem_rec->u4_mem_alignment = 0;
1261             ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
1262 
1263             ps_mem_rec++;
1264         }
1265     }
1266 
1267     /* Getting MemRecords Attributes */
1268     {
1269         ih264e_fill_mem_rec_ip_t s_ih264e_mem_rec_ip = {};
1270         ih264e_fill_mem_rec_op_t s_ih264e_mem_rec_op = {};
1271         iv_fill_mem_rec_ip_t *ps_fill_mem_rec_ip = &s_ih264e_mem_rec_ip.s_ive_ip;
1272         iv_fill_mem_rec_op_t *ps_fill_mem_rec_op = &s_ih264e_mem_rec_op.s_ive_op;
1273 
1274         ps_fill_mem_rec_ip->u4_size = sizeof(ih264e_fill_mem_rec_ip_t);
1275         ps_fill_mem_rec_op->u4_size = sizeof(ih264e_fill_mem_rec_op_t);
1276 
1277         ps_fill_mem_rec_ip->e_cmd = IV_CMD_FILL_NUM_MEM_REC;
1278         ps_fill_mem_rec_ip->ps_mem_rec = mMemRecords;
1279         ps_fill_mem_rec_ip->u4_num_mem_rec = mNumMemRecords;
1280         ps_fill_mem_rec_ip->u4_max_wd = width;
1281         ps_fill_mem_rec_ip->u4_max_ht = height;
1282         ps_fill_mem_rec_ip->u4_max_level = mAVCEncLevel;
1283         ps_fill_mem_rec_ip->e_color_format = DEFAULT_INP_COLOR_FORMAT;
1284         ps_fill_mem_rec_ip->u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
1285         ps_fill_mem_rec_ip->u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
1286         ps_fill_mem_rec_ip->u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
1287         ps_fill_mem_rec_ip->u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
1288 
1289         status = ive_api_function(nullptr, &s_ih264e_mem_rec_ip, &s_ih264e_mem_rec_op);
1290 
1291         if (status != IV_SUCCESS) {
1292             ALOGE("Fill memory records failed = 0x%x\n",
1293                     ps_fill_mem_rec_op->u4_error_code);
1294             return C2_CORRUPTED;
1295         }
1296     }
1297 
1298     /* Allocating Memory for Mem Records */
1299     {
1300         WORD32 total_size;
1301         iv_mem_rec_t *ps_mem_rec;
1302         total_size = 0;
1303         ps_mem_rec = mMemRecords;
1304 
1305         for (size_t i = 0; i < mNumMemRecords; i++) {
1306             ps_mem_rec->pv_base = ive_aligned_malloc(
1307                     ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
1308             if (ps_mem_rec->pv_base == nullptr) {
1309                 ALOGE("Allocation failure for mem record id %zu size %u\n", i,
1310                         ps_mem_rec->u4_mem_size);
1311                 return C2_CORRUPTED;
1312 
1313             }
1314             total_size += ps_mem_rec->u4_mem_size;
1315 
1316             ps_mem_rec++;
1317         }
1318     }
1319 
1320     /* Codec Instance Creation */
1321     {
1322         ih264e_init_ip_t s_enc_ip = {};
1323         ih264e_init_op_t s_enc_op = {};
1324 
1325         ive_init_ip_t *ps_init_ip = &s_enc_ip.s_ive_ip;
1326         ive_init_op_t *ps_init_op = &s_enc_op.s_ive_op;
1327 
1328         mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
1329         mCodecCtx->u4_size = sizeof(iv_obj_t);
1330         mCodecCtx->pv_fxns = (void *)ive_api_function;
1331 
1332         ps_init_ip->u4_size = sizeof(ih264e_init_ip_t);
1333         ps_init_op->u4_size = sizeof(ih264e_init_op_t);
1334 
1335         ps_init_ip->e_cmd = IV_CMD_INIT;
1336         ps_init_ip->u4_num_mem_rec = mNumMemRecords;
1337         ps_init_ip->ps_mem_rec = mMemRecords;
1338         ps_init_ip->u4_max_wd = width;
1339         ps_init_ip->u4_max_ht = height;
1340         ps_init_ip->u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
1341         ps_init_ip->u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
1342         ps_init_ip->u4_max_level = mAVCEncLevel;
1343         ps_init_ip->e_inp_color_fmt = mIvVideoColorFormat;
1344 
1345         if (mReconEnable || mPSNREnable) {
1346             ps_init_ip->u4_enable_recon = 1;
1347         } else {
1348             ps_init_ip->u4_enable_recon = 0;
1349         }
1350 
1351         switch (mBitrateMode->value) {
1352             case C2Config::BITRATE_IGNORE:
1353                 ps_init_ip->e_rc_mode = IVE_RC_NONE;
1354                 break;
1355             case C2Config::BITRATE_CONST:
1356                 ps_init_ip->e_rc_mode = IVE_RC_CBR_NON_LOW_DELAY;
1357                 break;
1358             case C2Config::BITRATE_VARIABLE:
1359                 ps_init_ip->e_rc_mode = IVE_RC_STORAGE;
1360                 break;
1361             default:
1362                 ps_init_ip->e_rc_mode = DEFAULT_RC_MODE;
1363                 break;
1364             break;
1365         }
1366         ps_init_ip->e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
1367         ps_init_ip->u4_max_framerate = DEFAULT_MAX_FRAMERATE;
1368         ps_init_ip->u4_max_bitrate = DEFAULT_MAX_BITRATE;
1369         ps_init_ip->u4_num_bframes = mBframes;
1370         ps_init_ip->e_content_type = IV_PROGRESSIVE;
1371         ps_init_ip->u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
1372         ps_init_ip->u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
1373         ps_init_ip->e_slice_mode = mSliceMode;
1374         ps_init_ip->u4_slice_param = mSliceParam;
1375         ps_init_ip->e_arch = mArch;
1376         ps_init_ip->e_soc = DEFAULT_SOC;
1377 
1378         status = ive_api_function(mCodecCtx, &s_enc_ip, &s_enc_op);
1379 
1380         if (status != IV_SUCCESS) {
1381             ALOGE("Init encoder failed = 0x%x\n", ps_init_op->u4_error_code);
1382             return C2_CORRUPTED;
1383         }
1384     }
1385 
1386     /* Get Codec Version */
1387     logVersion();
1388 
1389     /* set processor details */
1390     setNumCores();
1391 
1392     /* Video control Set Frame dimensions */
1393     setDimensions();
1394 
1395     /* Video control Set Frame rates */
1396     setFrameRate();
1397 
1398     /* Video control Set IPE Params */
1399     setIpeParams();
1400 
1401     /* Video control Set Bitrate */
1402     setBitRate();
1403 
1404     /* Video control Set QP */
1405     setQp();
1406 
1407     /* Video control Set AIR params */
1408     setAirParams();
1409 
1410     /* Video control Set VBV params */
1411     setVbvParams();
1412 
1413     /* Video control Set Motion estimation params */
1414     setMeParams();
1415 
1416     /* Video control Set GOP params */
1417     setGopParams();
1418 
1419     /* Video control Set Deblock params */
1420     setDeblockParams();
1421 
1422     /* Video control Set Profile params */
1423     setProfileParams();
1424 
1425     /* Video control Set VUI params */
1426     setVuiParams();
1427 
1428     /* Video control Set in Encode header mode */
1429     setEncMode(IVE_ENC_MODE_HEADER);
1430 
1431     ALOGV("init_codec successfull");
1432 
1433     mSpsPpsHeaderReceived = false;
1434     mStarted = true;
1435 
1436     return C2_OK;
1437 }
1438 
releaseEncoder()1439 c2_status_t C2SoftAvcEnc::releaseEncoder() {
1440     IV_STATUS_T status = IV_SUCCESS;
1441     iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
1442     iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
1443     iv_mem_rec_t *ps_mem_rec;
1444 
1445     if (!mStarted) {
1446         return C2_OK;
1447     }
1448 
1449     s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
1450     s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
1451     s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
1452     s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
1453 
1454     status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
1455 
1456     if (status != IV_SUCCESS) {
1457         ALOGE("Unable to retrieve memory records = 0x%x\n",
1458                 s_retrieve_mem_op.u4_error_code);
1459         return C2_CORRUPTED;
1460     }
1461 
1462     /* Free memory records */
1463     ps_mem_rec = mMemRecords;
1464     for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
1465         if (ps_mem_rec) ive_aligned_free(ps_mem_rec->pv_base);
1466         else {
1467             ALOGE("memory record is null.");
1468             return C2_CORRUPTED;
1469         }
1470         ps_mem_rec++;
1471     }
1472 
1473     if (mMemRecords) free(mMemRecords);
1474 
1475     // clear other pointers into the space being free()d
1476     mCodecCtx = nullptr;
1477 
1478     mStarted = false;
1479 
1480     return C2_OK;
1481 }
1482 
setEncodeArgs(ive_video_encode_ip_t * ps_encode_ip,ive_video_encode_op_t * ps_encode_op,const C2GraphicView * const input,uint8_t * base,uint32_t capacity,uint64_t workIndex)1483 c2_status_t C2SoftAvcEnc::setEncodeArgs(
1484         ive_video_encode_ip_t *ps_encode_ip,
1485         ive_video_encode_op_t *ps_encode_op,
1486         const C2GraphicView *const input,
1487         uint8_t *base,
1488         uint32_t capacity,
1489         uint64_t workIndex) {
1490     iv_raw_buf_t *ps_inp_raw_buf;
1491     memset(ps_encode_ip, 0, sizeof(*ps_encode_ip));
1492     memset(ps_encode_op, 0, sizeof(*ps_encode_op));
1493 
1494     ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
1495     ps_encode_ip->s_out_buf.pv_buf = base;
1496     ps_encode_ip->s_out_buf.u4_bytes = 0;
1497     ps_encode_ip->s_out_buf.u4_bufsize = capacity;
1498     ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
1499     ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
1500 
1501     ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
1502     ps_encode_ip->pv_bufs = nullptr;
1503     ps_encode_ip->pv_mb_info = nullptr;
1504     ps_encode_ip->pv_pic_info = nullptr;
1505     ps_encode_ip->u4_mb_info_type = 0;
1506     ps_encode_ip->u4_pic_info_type = 0;
1507     ps_encode_ip->u4_is_last = 0;
1508     ps_encode_ip->u4_timestamp_high = workIndex >> 32;
1509     ps_encode_ip->u4_timestamp_low = workIndex & 0xFFFFFFFF;
1510     ps_encode_op->s_out_buf.pv_buf = nullptr;
1511 
1512     /* Initialize color formats */
1513     memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
1514     ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
1515     ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
1516     if (input == nullptr) {
1517         if (mSawInputEOS) {
1518             ps_encode_ip->u4_is_last = 1;
1519         }
1520         return C2_OK;
1521     }
1522 
1523     if (input->width() < mSize->width ||
1524         input->height() < mSize->height) {
1525         /* Expect width height to be configured */
1526         ALOGW("unexpected Capacity Aspect %d(%d) x %d(%d)", input->width(),
1527               mSize->width, input->height(), mSize->height);
1528         return C2_BAD_VALUE;
1529     }
1530     ALOGV("width = %d, height = %d", input->width(), input->height());
1531     const C2PlanarLayout &layout = input->layout();
1532     uint8_t *yPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_Y]);
1533     uint8_t *uPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_U]);
1534     uint8_t *vPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_V]);
1535     int32_t yStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
1536     int32_t uStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
1537     int32_t vStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
1538 
1539     uint32_t width = mSize->width;
1540     uint32_t height = mSize->height;
1541     // width and height are always even (as block size is 16x16)
1542     CHECK_EQ((width & 1u), 0u);
1543     CHECK_EQ((height & 1u), 0u);
1544     size_t yPlaneSize = width * height;
1545 
1546     switch (layout.type) {
1547         case C2PlanarLayout::TYPE_RGB:
1548             [[fallthrough]];
1549         case C2PlanarLayout::TYPE_RGBA: {
1550             ALOGV("yPlaneSize = %zu", yPlaneSize);
1551             MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
1552             mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
1553             yPlane = conversionBuffer.data();
1554             uPlane = yPlane + yPlaneSize;
1555             vPlane = uPlane + yPlaneSize / 4;
1556             yStride = width;
1557             uStride = vStride = yStride / 2;
1558             ConvertRGBToPlanarYUV(yPlane, yStride, height, conversionBuffer.size(), *input,
1559                                   mColorAspects->matrix, mColorAspects->range);
1560             break;
1561         }
1562         case C2PlanarLayout::TYPE_YUV: {
1563             if (!IsYUV420(*input)) {
1564                 ALOGE("input is not YUV420");
1565                 return C2_BAD_VALUE;
1566             }
1567 
1568             if (layout.planes[layout.PLANE_Y].colInc == 1
1569                     && layout.planes[layout.PLANE_U].colInc == 1
1570                     && layout.planes[layout.PLANE_V].colInc == 1
1571                     && uStride == vStride
1572                     && yStride == 2 * vStride) {
1573                 // I420 compatible - already set up above
1574                 break;
1575             }
1576 
1577             // copy to I420
1578             yStride = width;
1579             uStride = vStride = yStride / 2;
1580             MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
1581             mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
1582             MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, yStride, height);
1583             status_t err = ImageCopy(conversionBuffer.data(), &img, *input);
1584             if (err != OK) {
1585                 ALOGE("Buffer conversion failed: %d", err);
1586                 return C2_BAD_VALUE;
1587             }
1588             yPlane = conversionBuffer.data();
1589             uPlane = yPlane + yPlaneSize;
1590             vPlane = uPlane + yPlaneSize / 4;
1591             break;
1592 
1593         }
1594 
1595         case C2PlanarLayout::TYPE_YUVA:
1596             ALOGE("YUVA plane type is not supported");
1597             return C2_BAD_VALUE;
1598 
1599         default:
1600             ALOGE("Unrecognized plane type: %d", layout.type);
1601             return C2_BAD_VALUE;
1602     }
1603 
1604     switch (mIvVideoColorFormat) {
1605         case IV_YUV_420P:
1606         {
1607             // input buffer is supposed to be const but Ittiam API wants bare pointer.
1608             ps_inp_raw_buf->apv_bufs[0] = yPlane;
1609             ps_inp_raw_buf->apv_bufs[1] = uPlane;
1610             ps_inp_raw_buf->apv_bufs[2] = vPlane;
1611 
1612             ps_inp_raw_buf->au4_wd[0] = mSize->width;
1613             ps_inp_raw_buf->au4_wd[1] = mSize->width / 2;
1614             ps_inp_raw_buf->au4_wd[2] = mSize->width / 2;
1615 
1616             ps_inp_raw_buf->au4_ht[0] = mSize->height;
1617             ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
1618             ps_inp_raw_buf->au4_ht[2] = mSize->height / 2;
1619 
1620             ps_inp_raw_buf->au4_strd[0] = yStride;
1621             ps_inp_raw_buf->au4_strd[1] = uStride;
1622             ps_inp_raw_buf->au4_strd[2] = vStride;
1623             break;
1624         }
1625 
1626         case IV_YUV_422ILE:
1627         {
1628             // TODO
1629             // ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1630             // ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
1631             // ps_inp_raw_buf->au4_ht[0] = mHeight;
1632             // ps_inp_raw_buf->au4_strd[0] = mStride * 2;
1633             break;
1634         }
1635 
1636         case IV_YUV_420SP_UV:
1637         case IV_YUV_420SP_VU:
1638         default:
1639         {
1640             ps_inp_raw_buf->apv_bufs[0] = yPlane;
1641             ps_inp_raw_buf->apv_bufs[1] = uPlane;
1642 
1643             ps_inp_raw_buf->au4_wd[0] = mSize->width;
1644             ps_inp_raw_buf->au4_wd[1] = mSize->width;
1645 
1646             ps_inp_raw_buf->au4_ht[0] = mSize->height;
1647             ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
1648 
1649             ps_inp_raw_buf->au4_strd[0] = yStride;
1650             ps_inp_raw_buf->au4_strd[1] = uStride;
1651             break;
1652         }
1653     }
1654     return C2_OK;
1655 }
1656 
finishWork(uint64_t workIndex,const std::unique_ptr<C2Work> & work,ive_video_encode_op_t * ps_encode_op)1657 void C2SoftAvcEnc::finishWork(uint64_t workIndex, const std::unique_ptr<C2Work> &work,
1658                               ive_video_encode_op_t *ps_encode_op) {
1659     std::shared_ptr<C2Buffer> buffer =
1660             createLinearBuffer(mOutBlock, 0, ps_encode_op->s_out_buf.u4_bytes);
1661     if (IV_IDR_FRAME == ps_encode_op->u4_encoded_frame_type) {
1662         ALOGV("IDR frame produced");
1663         buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
1664                 0u /* stream id */, C2Config::SYNC_FRAME));
1665     }
1666     mOutBlock = nullptr;
1667 
1668     auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
1669         work->worklets.front()->output.flags = (C2FrameData::flags_t)0;
1670         work->worklets.front()->output.buffers.clear();
1671         work->worklets.front()->output.buffers.push_back(buffer);
1672         work->worklets.front()->output.ordinal = work->input.ordinal;
1673         work->workletsProcessed = 1u;
1674     };
1675     if (work && c2_cntr64_t(workIndex) == work->input.ordinal.frameIndex) {
1676         fillWork(work);
1677         if (mSawInputEOS) {
1678             work->worklets.front()->output.flags = C2FrameData::FLAG_END_OF_STREAM;
1679         }
1680     } else {
1681         finish(workIndex, fillWork);
1682     }
1683 }
1684 
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)1685 void C2SoftAvcEnc::process(
1686         const std::unique_ptr<C2Work> &work,
1687         const std::shared_ptr<C2BlockPool> &pool) {
1688     // Initialize output work
1689     work->result = C2_OK;
1690     work->workletsProcessed = 0u;
1691     work->worklets.front()->output.flags = work->input.flags;
1692 
1693     IV_STATUS_T status;
1694     nsecs_t timeDelay = 0;
1695     uint64_t workIndex = work->input.ordinal.frameIndex.peekull();
1696 
1697     // Initialize encoder if not already initialized
1698     if (mCodecCtx == nullptr) {
1699         if (C2_OK != initEncoder()) {
1700             ALOGE("Failed to initialize encoder");
1701             mSignalledError = true;
1702             work->result = C2_CORRUPTED;
1703             work->workletsProcessed = 1u;
1704             return;
1705         }
1706     }
1707     if (mSignalledError) {
1708         return;
1709     }
1710     // while (!mSawOutputEOS && !outQueue.empty()) {
1711     c2_status_t error;
1712     ih264e_video_encode_ip_t s_video_encode_ip = {};
1713     ih264e_video_encode_op_t s_video_encode_op = {};
1714     ive_video_encode_ip_t *ps_encode_ip = &s_video_encode_ip.s_ive_ip;
1715     ive_video_encode_op_t *ps_encode_op = &s_video_encode_op.s_ive_op;
1716     memset(ps_encode_op, 0, sizeof(*ps_encode_op));
1717 
1718     if (!mSpsPpsHeaderReceived) {
1719         constexpr uint32_t kHeaderLength = MIN_STREAM_SIZE;
1720         uint8_t header[kHeaderLength];
1721         error = setEncodeArgs(
1722                 ps_encode_ip, ps_encode_op, nullptr, header, kHeaderLength, workIndex);
1723         if (error != C2_OK) {
1724             ALOGE("setEncodeArgs failed: %d", error);
1725             mSignalledError = true;
1726             work->result = C2_CORRUPTED;
1727             work->workletsProcessed = 1u;
1728             return;
1729         }
1730         status = ive_api_function(mCodecCtx, ps_encode_ip, ps_encode_op);
1731 
1732         if (IV_SUCCESS != status) {
1733             ALOGE("Encode header failed = 0x%x\n",
1734                     ps_encode_op->u4_error_code);
1735             work->workletsProcessed = 1u;
1736             return;
1737         } else {
1738             ALOGV("Bytes Generated in header %d\n",
1739                     ps_encode_op->s_out_buf.u4_bytes);
1740         }
1741 
1742         mSpsPpsHeaderReceived = true;
1743 
1744         std::unique_ptr<C2StreamInitDataInfo::output> csd =
1745             C2StreamInitDataInfo::output::AllocUnique(ps_encode_op->s_out_buf.u4_bytes, 0u);
1746         if (!csd) {
1747             ALOGE("CSD allocation failed");
1748             mSignalledError = true;
1749             work->result = C2_NO_MEMORY;
1750             work->workletsProcessed = 1u;
1751             return;
1752         }
1753         memcpy(csd->m.value, header, ps_encode_op->s_out_buf.u4_bytes);
1754         work->worklets.front()->output.configUpdate.push_back(std::move(csd));
1755 
1756         DUMP_TO_FILE(
1757                 mOutFile, csd->m.value, csd->flexCount());
1758         if (work->input.buffers.empty()) {
1759             work->workletsProcessed = 1u;
1760             return;
1761         }
1762     }
1763 
1764     // handle dynamic config parameters
1765     {
1766         IntfImpl::Lock lock = mIntf->lock();
1767         std::shared_ptr<C2StreamIntraRefreshTuning::output> intraRefresh = mIntf->getIntraRefresh_l();
1768         std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
1769         std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync = mIntf->getRequestSync_l();
1770         lock.unlock();
1771 
1772         if (bitrate != mBitrate) {
1773             mBitrate = bitrate;
1774             setBitRate();
1775         }
1776 
1777         if (intraRefresh != mIntraRefresh) {
1778             mIntraRefresh = intraRefresh;
1779             setAirParams();
1780         }
1781 
1782         if (requestSync != mRequestSync) {
1783             // we can handle IDR immediately
1784             if (requestSync->value) {
1785                 // unset request
1786                 C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE);
1787                 std::vector<std::unique_ptr<C2SettingResult>> failures;
1788                 mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures);
1789                 ALOGV("Got sync request");
1790                 setFrameType(IV_IDR_FRAME);
1791             }
1792             mRequestSync = requestSync;
1793         }
1794     }
1795 
1796     if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
1797         mSawInputEOS = true;
1798     }
1799 
1800     /* In normal mode, store inputBufferInfo and this will be returned
1801        when encoder consumes this input */
1802     // if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
1803     //     for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1804     //         if (NULL == mInputBufferInfo[i]) {
1805     //             mInputBufferInfo[i] = inputBufferInfo;
1806     //             break;
1807     //         }
1808     //     }
1809     // }
1810     std::shared_ptr<C2GraphicView> view;
1811     std::shared_ptr<C2Buffer> inputBuffer;
1812     if (!work->input.buffers.empty()) {
1813         inputBuffer = work->input.buffers[0];
1814         view = std::make_shared<C2GraphicView>(
1815                 inputBuffer->data().graphicBlocks().front().map().get());
1816         if (view->error() != C2_OK) {
1817             ALOGE("graphic view map err = %d", view->error());
1818             work->workletsProcessed = 1u;
1819             return;
1820         }
1821         //(b/232396154)
1822         //workaround for incorrect crop size in view when using surface mode
1823         view->setCrop_be(C2Rect(mSize->width, mSize->height));
1824     }
1825 
1826     do {
1827         if (mSawInputEOS && work->input.buffers.empty()) break;
1828         if (!mOutBlock) {
1829             C2MemoryUsage usage = {C2MemoryUsage::CPU_READ,
1830                                    C2MemoryUsage::CPU_WRITE};
1831             // TODO: error handling, proper usage, etc.
1832             c2_status_t err =
1833                 pool->fetchLinearBlock(mOutBufferSize, usage, &mOutBlock);
1834             if (err != C2_OK) {
1835                 ALOGE("fetch linear block err = %d", err);
1836                 work->result = err;
1837                 work->workletsProcessed = 1u;
1838                 return;
1839             }
1840         }
1841         C2WriteView wView = mOutBlock->map().get();
1842         if (wView.error() != C2_OK) {
1843             ALOGE("write view map err = %d", wView.error());
1844             work->result = wView.error();
1845             work->workletsProcessed = 1u;
1846             return;
1847         }
1848 
1849         error = setEncodeArgs(
1850                 ps_encode_ip, ps_encode_op, view.get(), wView.base(), wView.capacity(), workIndex);
1851         if (error != C2_OK) {
1852             ALOGE("setEncodeArgs failed : %d", error);
1853             mSignalledError = true;
1854             work->result = error;
1855             work->workletsProcessed = 1u;
1856             return;
1857         }
1858 
1859         // DUMP_TO_FILE(
1860         //         mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
1861         //         (mHeight * mStride * 3 / 2));
1862 
1863         /* Compute time elapsed between end of previous decode()
1864          * to start of current decode() */
1865         mTimeStart = systemTime();
1866         timeDelay = mTimeStart - mTimeEnd;
1867         status = ive_api_function(mCodecCtx, &s_video_encode_ip, &s_video_encode_op);
1868 
1869         if (IV_SUCCESS != status) {
1870             if ((ps_encode_op->u4_error_code & 0xFF) == IH264E_BITSTREAM_BUFFER_OVERFLOW) {
1871                 // TODO: use IVE_CMD_CTL_GETBUFINFO for proper max input size?
1872                 mOutBufferSize *= 2;
1873                 mOutBlock.reset();
1874                 continue;
1875             }
1876             ALOGE("Encode Frame failed = 0x%x\n",
1877                     ps_encode_op->u4_error_code);
1878             mSignalledError = true;
1879             work->result = C2_CORRUPTED;
1880             work->workletsProcessed = 1u;
1881             return;
1882         }
1883     } while (IV_SUCCESS != status);
1884 
1885     // Hold input buffer reference
1886     if (inputBuffer) {
1887         mBuffers[ps_encode_ip->s_inp_buf.apv_bufs[0]] = inputBuffer;
1888     }
1889 
1890     /* Compute time taken for decode() */
1891     mTimeEnd = systemTime();
1892     nsecs_t timeTaken = mTimeEnd - mTimeStart;
1893 
1894     ALOGV("timeTaken=%" PRId64 "d delay=%" PRId64 " numBytes=%6d", timeTaken, timeDelay,
1895             ps_encode_op->s_out_buf.u4_bytes);
1896 
1897     void *freed = ps_encode_op->s_inp_buf.apv_bufs[0];
1898     /* If encoder frees up an input buffer, mark it as free */
1899     if (freed != nullptr) {
1900         if (mBuffers.count(freed) == 0u) {
1901             ALOGD("buffer not tracked");
1902         } else {
1903             // Release input buffer reference
1904             mBuffers.erase(freed);
1905             mConversionBuffersInUse.erase(freed);
1906         }
1907     }
1908 
1909     if (ps_encode_op->output_present) {
1910         if (!ps_encode_op->s_out_buf.u4_bytes) {
1911             ALOGE("Error: Output present but bytes generated is zero");
1912             mSignalledError = true;
1913             work->result = C2_CORRUPTED;
1914             work->workletsProcessed = 1u;
1915             return;
1916         }
1917         uint64_t workId = ((uint64_t)ps_encode_op->u4_timestamp_high << 32) |
1918                       ps_encode_op->u4_timestamp_low;
1919         finishWork(workId, work, ps_encode_op);
1920     }
1921     if (mSawInputEOS) {
1922         drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
1923     }
1924 }
1925 
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)1926 c2_status_t C2SoftAvcEnc::drainInternal(
1927         uint32_t drainMode,
1928         const std::shared_ptr<C2BlockPool> &pool,
1929         const std::unique_ptr<C2Work> &work) {
1930 
1931     if (drainMode == NO_DRAIN) {
1932         ALOGW("drain with NO_DRAIN: no-op");
1933         return C2_OK;
1934     }
1935     if (drainMode == DRAIN_CHAIN) {
1936         ALOGW("DRAIN_CHAIN not supported");
1937         return C2_OMITTED;
1938     }
1939 
1940     while (true) {
1941         if (!mOutBlock) {
1942             C2MemoryUsage usage = {C2MemoryUsage::CPU_READ,
1943                                    C2MemoryUsage::CPU_WRITE};
1944             // TODO: error handling, proper usage, etc.
1945             c2_status_t err =
1946                 pool->fetchLinearBlock(mOutBufferSize, usage, &mOutBlock);
1947             if (err != C2_OK) {
1948                 ALOGE("fetch linear block err = %d", err);
1949                 work->result = err;
1950                 work->workletsProcessed = 1u;
1951                 return err;
1952             }
1953         }
1954         C2WriteView wView = mOutBlock->map().get();
1955         if (wView.error()) {
1956             ALOGE("graphic view map failed %d", wView.error());
1957             return C2_CORRUPTED;
1958         }
1959         ih264e_video_encode_ip_t s_video_encode_ip = {};
1960         ih264e_video_encode_op_t s_video_encode_op = {};
1961         ive_video_encode_ip_t *ps_encode_ip = &s_video_encode_ip.s_ive_ip;
1962         ive_video_encode_op_t *ps_encode_op = &s_video_encode_op.s_ive_op;
1963         if (C2_OK != setEncodeArgs(ps_encode_ip, ps_encode_op, nullptr,
1964                                    wView.base(), wView.capacity(), 0)) {
1965             ALOGE("setEncodeArgs failed for drainInternal");
1966             mSignalledError = true;
1967             work->result = C2_CORRUPTED;
1968             work->workletsProcessed = 1u;
1969             return C2_CORRUPTED;
1970         }
1971         (void)ive_api_function(mCodecCtx, &s_video_encode_ip, &s_video_encode_op);
1972 
1973         void *freed = ps_encode_op->s_inp_buf.apv_bufs[0];
1974         /* If encoder frees up an input buffer, mark it as free */
1975         if (freed != nullptr) {
1976             if (mBuffers.count(freed) == 0u) {
1977                 ALOGD("buffer not tracked");
1978             } else {
1979                 // Release input buffer reference
1980                 mBuffers.erase(freed);
1981                 mConversionBuffersInUse.erase(freed);
1982             }
1983         }
1984 
1985         if (ps_encode_op->output_present) {
1986             uint64_t workId = ((uint64_t)ps_encode_op->u4_timestamp_high << 32) |
1987                           ps_encode_op->u4_timestamp_low;
1988             finishWork(workId, work, ps_encode_op);
1989         } else {
1990             if (work->workletsProcessed != 1u) {
1991                 work->worklets.front()->output.flags = work->input.flags;
1992                 work->worklets.front()->output.ordinal = work->input.ordinal;
1993                 work->worklets.front()->output.buffers.clear();
1994                 work->workletsProcessed = 1u;
1995             }
1996             break;
1997         }
1998     }
1999 
2000     return C2_OK;
2001 }
2002 
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)2003 c2_status_t C2SoftAvcEnc::drain(
2004         uint32_t drainMode,
2005         const std::shared_ptr<C2BlockPool> &pool) {
2006     return drainInternal(drainMode, pool, nullptr);
2007 }
2008 
2009 class C2SoftAvcEncFactory : public C2ComponentFactory {
2010 public:
C2SoftAvcEncFactory()2011     C2SoftAvcEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
2012         GetCodec2PlatformComponentStore()->getParamReflector())) {
2013     }
2014 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)2015     virtual c2_status_t createComponent(
2016             c2_node_id_t id,
2017             std::shared_ptr<C2Component>* const component,
2018             std::function<void(C2Component*)> deleter) override {
2019         *component = std::shared_ptr<C2Component>(
2020                 new C2SoftAvcEnc(COMPONENT_NAME,
2021                                  id,
2022                                  std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)),
2023                 deleter);
2024         return C2_OK;
2025     }
2026 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)2027     virtual c2_status_t createInterface(
2028             c2_node_id_t id,
2029             std::shared_ptr<C2ComponentInterface>* const interface,
2030             std::function<void(C2ComponentInterface*)> deleter) override {
2031         *interface = std::shared_ptr<C2ComponentInterface>(
2032                 new SimpleInterface<C2SoftAvcEnc::IntfImpl>(
2033                         COMPONENT_NAME, id, std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)),
2034                 deleter);
2035         return C2_OK;
2036     }
2037 
2038     virtual ~C2SoftAvcEncFactory() override = default;
2039 
2040 private:
2041     std::shared_ptr<C2ReflectorHelper> mHelper;
2042 };
2043 
2044 }  // namespace android
2045 
2046 __attribute__((cfi_canonical_jump_table))
CreateCodec2Factory()2047 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
2048     ALOGV("in %s", __func__);
2049     return new ::android::C2SoftAvcEncFactory();
2050 }
2051 
2052 __attribute__((cfi_canonical_jump_table))
DestroyCodec2Factory(::C2ComponentFactory * factory)2053 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
2054     ALOGV("in %s", __func__);
2055     delete factory;
2056 }
2057