blob: 0ae2a5a573e580d534197679a4c5101d60034cfb [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
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 <media/hardware/VideoAPI.h>
23#include <media/stagefright/MediaDefs.h>
24#include <media/stagefright/MediaErrors.h>
25#include <media/stagefright/MetaData.h>
26#include <media/stagefright/foundation/AUtils.h>
27
28#include <C2Debug.h>
29#include <C2PlatformSupport.h>
30#include <Codec2BufferUtils.h>
31#include <SimpleC2Interface.h>
32#include <util/C2InterfaceHelper.h>
33
34#include "C2SoftAvcEnc.h"
35#include "ih264e.h"
36#include "ih264e_error.h"
37
38namespace android {
39
Manisha Jajoo9acd73d2019-03-12 14:08:05 +053040namespace {
41
42constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
43
44} // namespace
45
46class C2SoftAvcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
Pawin Vongmasa36653902018-11-15 00:10:25 -080047public:
48 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
Manisha Jajoo9acd73d2019-03-12 14:08:05 +053049 : SimpleInterface<void>::BaseParams(
50 helper,
51 COMPONENT_NAME,
52 C2Component::KIND_ENCODER,
53 C2Component::DOMAIN_VIDEO,
54 MEDIA_MIMETYPE_VIDEO_AVC) {
55 noPrivateBuffers(); // TODO: account for our buffers here
56 noInputReferences();
57 noOutputReferences();
58 noInputLatency();
59 noTimeStretch();
Pawin Vongmasa36653902018-11-15 00:10:25 -080060 setDerivedInstance(this);
61
62 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080063 DefineParam(mUsage, C2_PARAMKEY_INPUT_STREAM_USAGE)
Pawin Vongmasa36653902018-11-15 00:10:25 -080064 .withConstValue(new C2StreamUsageTuning::input(
65 0u, (uint64_t)C2MemoryUsage::CPU_READ))
66 .build());
67
68 addParameter(
Manisha Jajoo9acd73d2019-03-12 14:08:05 +053069 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
70 .withConstValue(new C2ComponentAttributesSetting(
71 C2Component::ATTRIB_IS_TEMPORAL))
72 .build());
73
74 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080075 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
76 .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
Pawin Vongmasa36653902018-11-15 00:10:25 -080077 .withFields({
78 C2F(mSize, width).inRange(2, 2560, 2),
79 C2F(mSize, height).inRange(2, 2560, 2),
80 })
81 .withSetter(SizeSetter)
82 .build());
83
84 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080085 DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
Pawin Vongmasa36653902018-11-15 00:10:25 -080086 .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
87 // TODO: More restriction?
88 .withFields({C2F(mFrameRate, value).greaterThan(0.)})
89 .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
90 .build());
91
92 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080093 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
94 .withDefault(new C2StreamBitrateInfo::output(0u, 64000))
Pawin Vongmasa36653902018-11-15 00:10:25 -080095 .withFields({C2F(mBitrate, value).inRange(4096, 12000000)})
96 .withSetter(BitrateSetter)
97 .build());
98
99 addParameter(
100 DefineParam(mIntraRefresh, C2_PARAMKEY_INTRA_REFRESH)
101 .withDefault(new C2StreamIntraRefreshTuning::output(
102 0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
103 .withFields({
104 C2F(mIntraRefresh, mode).oneOf({
105 C2Config::INTRA_REFRESH_DISABLED, C2Config::INTRA_REFRESH_ARBITRARY }),
106 C2F(mIntraRefresh, period).any()
107 })
108 .withSetter(IntraRefreshSetter)
109 .build());
110
111 addParameter(
112 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
113 .withDefault(new C2StreamProfileLevelInfo::output(
114 0u, PROFILE_AVC_CONSTRAINED_BASELINE, LEVEL_AVC_4_1))
115 .withFields({
116 C2F(mProfileLevel, profile).oneOf({
117 PROFILE_AVC_BASELINE,
118 PROFILE_AVC_CONSTRAINED_BASELINE,
119 PROFILE_AVC_MAIN,
120 }),
121 C2F(mProfileLevel, level).oneOf({
122 LEVEL_AVC_1,
123 LEVEL_AVC_1B,
124 LEVEL_AVC_1_1,
125 LEVEL_AVC_1_2,
126 LEVEL_AVC_1_3,
127 LEVEL_AVC_2,
128 LEVEL_AVC_2_1,
129 LEVEL_AVC_2_2,
130 LEVEL_AVC_3,
131 LEVEL_AVC_3_1,
132 LEVEL_AVC_3_2,
133 LEVEL_AVC_4,
134 LEVEL_AVC_4_1,
135 LEVEL_AVC_4_2,
136 LEVEL_AVC_5,
137 }),
138 })
139 .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
140 .build());
141
142 addParameter(
143 DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME)
144 .withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
145 .withFields({C2F(mRequestSync, value).oneOf({ C2_FALSE, C2_TRUE }) })
146 .withSetter(Setter<decltype(*mRequestSync)>::NonStrictValueWithNoDeps)
147 .build());
148
149 addParameter(
150 DefineParam(mSyncFramePeriod, C2_PARAMKEY_SYNC_FRAME_INTERVAL)
151 .withDefault(new C2StreamSyncFrameIntervalTuning::output(0u, 1000000))
152 .withFields({C2F(mSyncFramePeriod, value).any()})
153 .withSetter(Setter<decltype(*mSyncFramePeriod)>::StrictValueWithNoDeps)
154 .build());
155 }
156
157 static C2R BitrateSetter(bool mayBlock, C2P<C2StreamBitrateInfo::output> &me) {
158 (void)mayBlock;
159 C2R res = C2R::Ok();
160 if (me.v.value <= 4096) {
161 me.set().value = 4096;
162 }
163 return res;
164 }
165
166 static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe,
167 C2P<C2StreamPictureSizeInfo::input> &me) {
168 (void)mayBlock;
169 C2R res = C2R::Ok();
170 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
171 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
172 me.set().width = oldMe.v.width;
173 }
174 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
175 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
176 me.set().height = oldMe.v.height;
177 }
178 return res;
179 }
180
181 static C2R ProfileLevelSetter(
182 bool mayBlock,
183 C2P<C2StreamProfileLevelInfo::output> &me,
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800184 const C2P<C2StreamPictureSizeInfo::input> &size,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800185 const C2P<C2StreamFrameRateInfo::output> &frameRate,
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800186 const C2P<C2StreamBitrateInfo::output> &bitrate) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800187 (void)mayBlock;
188 if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
189 me.set().profile = PROFILE_AVC_CONSTRAINED_BASELINE;
190 }
191
192 struct LevelLimits {
193 C2Config::level_t level;
194 float mbsPerSec;
195 uint64_t mbs;
196 uint32_t bitrate;
197 };
198 constexpr LevelLimits kLimits[] = {
199 { LEVEL_AVC_1, 1485, 99, 64000 },
200 // Decoder does not properly handle level 1b.
201 // { LEVEL_AVC_1B, 1485, 99, 128000 },
202 { LEVEL_AVC_1_1, 3000, 396, 192000 },
203 { LEVEL_AVC_1_2, 6000, 396, 384000 },
204 { LEVEL_AVC_1_3, 11880, 396, 768000 },
205 { LEVEL_AVC_2, 11880, 396, 2000000 },
206 { LEVEL_AVC_2_1, 19800, 792, 4000000 },
207 { LEVEL_AVC_2_2, 20250, 1620, 4000000 },
208 { LEVEL_AVC_3, 40500, 1620, 10000000 },
209 { LEVEL_AVC_3_1, 108000, 3600, 14000000 },
210 { LEVEL_AVC_3_2, 216000, 5120, 20000000 },
211 { LEVEL_AVC_4, 245760, 8192, 20000000 },
212 { LEVEL_AVC_4_1, 245760, 8192, 50000000 },
213 { LEVEL_AVC_4_2, 522240, 8704, 50000000 },
214 { LEVEL_AVC_5, 589824, 22080, 135000000 },
215 };
216
217 uint64_t mbs = uint64_t((size.v.width + 15) / 16) * ((size.v.height + 15) / 16);
Pawin Vongmasa1f213362019-01-24 06:59:16 -0800218 float mbsPerSec = float(mbs) * frameRate.v.value;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800219
220 // Check if the supplied level meets the MB / bitrate requirements. If
221 // not, update the level with the lowest level meeting the requirements.
222
223 bool found = false;
224 // By default needsUpdate = false in case the supplied level does meet
225 // the requirements. For Level 1b, we want to update the level anyway,
226 // so we set it to true in that case.
227 bool needsUpdate = (me.v.level == LEVEL_AVC_1B);
228 for (const LevelLimits &limit : kLimits) {
229 if (mbs <= limit.mbs && mbsPerSec <= limit.mbsPerSec &&
230 bitrate.v.value <= limit.bitrate) {
231 // This is the lowest level that meets the requirements, and if
232 // we haven't seen the supplied level yet, that means we don't
233 // need the update.
234 if (needsUpdate) {
235 ALOGD("Given level %x does not cover current configuration: "
236 "adjusting to %x", me.v.level, limit.level);
237 me.set().level = limit.level;
238 }
239 found = true;
240 break;
241 }
242 if (me.v.level == limit.level) {
243 // We break out of the loop when the lowest feasible level is
244 // found. The fact that we're here means that our level doesn't
245 // meet the requirement and needs to be updated.
246 needsUpdate = true;
247 }
248 }
249 if (!found) {
250 // We set to the highest supported level.
251 me.set().level = LEVEL_AVC_5;
252 }
253
254 return C2R::Ok();
255 }
256
257 static C2R IntraRefreshSetter(bool mayBlock, C2P<C2StreamIntraRefreshTuning::output> &me) {
258 (void)mayBlock;
259 C2R res = C2R::Ok();
260 if (me.v.period < 1) {
261 me.set().mode = C2Config::INTRA_REFRESH_DISABLED;
262 me.set().period = 0;
263 } else {
264 // only support arbitrary mode (cyclic in our case)
265 me.set().mode = C2Config::INTRA_REFRESH_ARBITRARY;
266 }
267 return res;
268 }
269
270 IV_PROFILE_T getProfile_l() const {
271 switch (mProfileLevel->profile) {
272 case PROFILE_AVC_CONSTRAINED_BASELINE: [[fallthrough]];
273 case PROFILE_AVC_BASELINE: return IV_PROFILE_BASE;
274 case PROFILE_AVC_MAIN: return IV_PROFILE_MAIN;
275 default:
276 ALOGD("Unrecognized profile: %x", mProfileLevel->profile);
277 return IV_PROFILE_DEFAULT;
278 }
279 }
280
281 UWORD32 getLevel_l() const {
282 struct Level {
283 C2Config::level_t c2Level;
284 UWORD32 avcLevel;
285 };
286 constexpr Level levels[] = {
287 { LEVEL_AVC_1, 10 },
288 { LEVEL_AVC_1B, 9 },
289 { LEVEL_AVC_1_1, 11 },
290 { LEVEL_AVC_1_2, 12 },
291 { LEVEL_AVC_1_3, 13 },
292 { LEVEL_AVC_2, 20 },
293 { LEVEL_AVC_2_1, 21 },
294 { LEVEL_AVC_2_2, 22 },
295 { LEVEL_AVC_3, 30 },
296 { LEVEL_AVC_3_1, 31 },
297 { LEVEL_AVC_3_2, 32 },
298 { LEVEL_AVC_4, 40 },
299 { LEVEL_AVC_4_1, 41 },
300 { LEVEL_AVC_4_2, 42 },
301 { LEVEL_AVC_5, 50 },
302 };
303 for (const Level &level : levels) {
304 if (mProfileLevel->level == level.c2Level) {
305 return level.avcLevel;
306 }
307 }
308 ALOGD("Unrecognized level: %x", mProfileLevel->level);
309 return 41;
310 }
311 uint32_t getSyncFramePeriod_l() const {
312 if (mSyncFramePeriod->value < 0 || mSyncFramePeriod->value == INT64_MAX) {
313 return 0;
314 }
315 double period = mSyncFramePeriod->value / 1e6 * mFrameRate->value;
316 return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
317 }
318
319 // unsafe getters
320 std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const { return mSize; }
321 std::shared_ptr<C2StreamIntraRefreshTuning::output> getIntraRefresh_l() const { return mIntraRefresh; }
322 std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const { return mFrameRate; }
323 std::shared_ptr<C2StreamBitrateInfo::output> getBitrate_l() const { return mBitrate; }
324 std::shared_ptr<C2StreamRequestSyncFrameTuning::output> getRequestSync_l() const { return mRequestSync; }
325
326private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800327 std::shared_ptr<C2StreamUsageTuning::input> mUsage;
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800328 std::shared_ptr<C2StreamPictureSizeInfo::input> mSize;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800329 std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
330 std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
331 std::shared_ptr<C2StreamIntraRefreshTuning::output> mIntraRefresh;
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800332 std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800333 std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
334 std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
335};
336
337#define ive_api_function ih264e_api_function
338
Pawin Vongmasa36653902018-11-15 00:10:25 -0800339namespace {
340
341// From external/libavc/encoder/ih264e_bitstream.h
342constexpr uint32_t MIN_STREAM_SIZE = 0x800;
343
344static size_t GetCPUCoreCount() {
345 long cpuCoreCount = 1;
346#if defined(_SC_NPROCESSORS_ONLN)
347 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
348#else
349 // _SC_NPROC_ONLN must be defined...
350 cpuCoreCount = sysconf(_SC_NPROC_ONLN);
351#endif
352 CHECK(cpuCoreCount >= 1);
353 ALOGV("Number of CPU cores: %ld", cpuCoreCount);
354 return (size_t)cpuCoreCount;
355}
356
357} // namespace
358
359C2SoftAvcEnc::C2SoftAvcEnc(
360 const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl)
361 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
362 mIntf(intfImpl),
363 mIvVideoColorFormat(IV_YUV_420P),
364 mAVCEncProfile(IV_PROFILE_BASE),
365 mAVCEncLevel(41),
366 mStarted(false),
367 mSawInputEOS(false),
368 mSawOutputEOS(false),
369 mSignalledError(false),
370 mCodecCtx(nullptr),
371 // TODO: output buffer size
372 mOutBufferSize(524288) {
373
374 // If dump is enabled, then open create an empty file
375 GENERATE_FILE_NAMES();
376 CREATE_DUMP_FILE(mInFile);
377 CREATE_DUMP_FILE(mOutFile);
378
379 initEncParams();
380}
381
382C2SoftAvcEnc::~C2SoftAvcEnc() {
383 releaseEncoder();
384}
385
386c2_status_t C2SoftAvcEnc::onInit() {
387 return C2_OK;
388}
389
390c2_status_t C2SoftAvcEnc::onStop() {
391 return C2_OK;
392}
393
394void C2SoftAvcEnc::onReset() {
395 // TODO: use IVE_CMD_CTL_RESET?
396 releaseEncoder();
397 initEncParams();
398}
399
400void C2SoftAvcEnc::onRelease() {
401 releaseEncoder();
402}
403
404c2_status_t C2SoftAvcEnc::onFlush_sm() {
405 // TODO: use IVE_CMD_CTL_FLUSH?
406 return C2_OK;
407}
408
409void C2SoftAvcEnc::initEncParams() {
410 mCodecCtx = nullptr;
411 mMemRecords = nullptr;
412 mNumMemRecords = DEFAULT_MEM_REC_CNT;
413 mHeaderGenerated = 0;
414 mNumCores = GetCPUCoreCount();
415 mArch = DEFAULT_ARCH;
416 mSliceMode = DEFAULT_SLICE_MODE;
417 mSliceParam = DEFAULT_SLICE_PARAM;
418 mHalfPelEnable = DEFAULT_HPEL;
419 mIInterval = DEFAULT_I_INTERVAL;
420 mIDRInterval = DEFAULT_IDR_INTERVAL;
421 mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
422 mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
423 mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
424 mEncSpeed = DEFAULT_ENC_SPEED;
425 mIntra4x4 = DEFAULT_INTRA4x4;
426 mConstrainedIntraFlag = DEFAULT_CONSTRAINED_INTRA;
427 mPSNREnable = DEFAULT_PSNR_ENABLE;
428 mReconEnable = DEFAULT_RECON_ENABLE;
429 mEntropyMode = DEFAULT_ENTROPY_MODE;
430 mBframes = DEFAULT_B_FRAMES;
431
432 gettimeofday(&mTimeStart, nullptr);
433 gettimeofday(&mTimeEnd, nullptr);
434}
435
436c2_status_t C2SoftAvcEnc::setDimensions() {
437 ive_ctl_set_dimensions_ip_t s_dimensions_ip;
438 ive_ctl_set_dimensions_op_t s_dimensions_op;
439 IV_STATUS_T status;
440
441 s_dimensions_ip.e_cmd = IVE_CMD_VIDEO_CTL;
442 s_dimensions_ip.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
443 s_dimensions_ip.u4_ht = mSize->height;
444 s_dimensions_ip.u4_wd = mSize->width;
445
446 s_dimensions_ip.u4_timestamp_high = -1;
447 s_dimensions_ip.u4_timestamp_low = -1;
448
449 s_dimensions_ip.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
450 s_dimensions_op.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
451
452 status = ive_api_function(mCodecCtx, &s_dimensions_ip, &s_dimensions_op);
453 if (status != IV_SUCCESS) {
454 ALOGE("Unable to set frame dimensions = 0x%x\n",
455 s_dimensions_op.u4_error_code);
456 return C2_CORRUPTED;
457 }
458 return C2_OK;
459}
460
461c2_status_t C2SoftAvcEnc::setNumCores() {
462 IV_STATUS_T status;
463 ive_ctl_set_num_cores_ip_t s_num_cores_ip;
464 ive_ctl_set_num_cores_op_t s_num_cores_op;
465 s_num_cores_ip.e_cmd = IVE_CMD_VIDEO_CTL;
466 s_num_cores_ip.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
467 s_num_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_CORES);
468 s_num_cores_ip.u4_timestamp_high = -1;
469 s_num_cores_ip.u4_timestamp_low = -1;
470 s_num_cores_ip.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
471
472 s_num_cores_op.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
473
474 status = ive_api_function(
475 mCodecCtx, (void *) &s_num_cores_ip, (void *) &s_num_cores_op);
476 if (status != IV_SUCCESS) {
477 ALOGE("Unable to set processor params = 0x%x\n",
478 s_num_cores_op.u4_error_code);
479 return C2_CORRUPTED;
480 }
481 return C2_OK;
482}
483
484c2_status_t C2SoftAvcEnc::setFrameRate() {
485 ive_ctl_set_frame_rate_ip_t s_frame_rate_ip;
486 ive_ctl_set_frame_rate_op_t s_frame_rate_op;
487 IV_STATUS_T status;
488
489 s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
490 s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
491
492 s_frame_rate_ip.u4_src_frame_rate = mFrameRate->value + 0.5;
493 s_frame_rate_ip.u4_tgt_frame_rate = mFrameRate->value + 0.5;
494
495 s_frame_rate_ip.u4_timestamp_high = -1;
496 s_frame_rate_ip.u4_timestamp_low = -1;
497
498 s_frame_rate_ip.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
499 s_frame_rate_op.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
500
501 status = ive_api_function(mCodecCtx, &s_frame_rate_ip, &s_frame_rate_op);
502 if (status != IV_SUCCESS) {
503 ALOGE("Unable to set frame rate = 0x%x\n",
504 s_frame_rate_op.u4_error_code);
505 return C2_CORRUPTED;
506 }
507 return C2_OK;
508}
509
510c2_status_t C2SoftAvcEnc::setIpeParams() {
511 ive_ctl_set_ipe_params_ip_t s_ipe_params_ip;
512 ive_ctl_set_ipe_params_op_t s_ipe_params_op;
513 IV_STATUS_T status;
514
515 s_ipe_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
516 s_ipe_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
517
518 s_ipe_params_ip.u4_enable_intra_4x4 = mIntra4x4;
519 s_ipe_params_ip.u4_enc_speed_preset = mEncSpeed;
520 s_ipe_params_ip.u4_constrained_intra_pred = mConstrainedIntraFlag;
521
522 s_ipe_params_ip.u4_timestamp_high = -1;
523 s_ipe_params_ip.u4_timestamp_low = -1;
524
525 s_ipe_params_ip.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
526 s_ipe_params_op.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
527
528 status = ive_api_function(mCodecCtx, &s_ipe_params_ip, &s_ipe_params_op);
529 if (status != IV_SUCCESS) {
530 ALOGE("Unable to set ipe params = 0x%x\n",
531 s_ipe_params_op.u4_error_code);
532 return C2_CORRUPTED;
533 }
534 return C2_OK;
535}
536
537c2_status_t C2SoftAvcEnc::setBitRate() {
538 ive_ctl_set_bitrate_ip_t s_bitrate_ip;
539 ive_ctl_set_bitrate_op_t s_bitrate_op;
540 IV_STATUS_T status;
541
542 s_bitrate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
543 s_bitrate_ip.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
544
545 s_bitrate_ip.u4_target_bitrate = mBitrate->value;
546
547 s_bitrate_ip.u4_timestamp_high = -1;
548 s_bitrate_ip.u4_timestamp_low = -1;
549
550 s_bitrate_ip.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
551 s_bitrate_op.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
552
553 status = ive_api_function(mCodecCtx, &s_bitrate_ip, &s_bitrate_op);
554 if (status != IV_SUCCESS) {
555 ALOGE("Unable to set bit rate = 0x%x\n", s_bitrate_op.u4_error_code);
556 return C2_CORRUPTED;
557 }
558 return C2_OK;
559}
560
561c2_status_t C2SoftAvcEnc::setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type) {
562 ive_ctl_set_frame_type_ip_t s_frame_type_ip;
563 ive_ctl_set_frame_type_op_t s_frame_type_op;
564 IV_STATUS_T status;
565 s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
566 s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
567
568 s_frame_type_ip.e_frame_type = e_frame_type;
569
570 s_frame_type_ip.u4_timestamp_high = -1;
571 s_frame_type_ip.u4_timestamp_low = -1;
572
573 s_frame_type_ip.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
574 s_frame_type_op.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
575
576 status = ive_api_function(mCodecCtx, &s_frame_type_ip, &s_frame_type_op);
577 if (status != IV_SUCCESS) {
578 ALOGE("Unable to set frame type = 0x%x\n",
579 s_frame_type_op.u4_error_code);
580 return C2_CORRUPTED;
581 }
582 return C2_OK;
583}
584
585c2_status_t C2SoftAvcEnc::setQp() {
586 ive_ctl_set_qp_ip_t s_qp_ip;
587 ive_ctl_set_qp_op_t s_qp_op;
588 IV_STATUS_T status;
589
590 s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
591 s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
592
593 s_qp_ip.u4_i_qp = DEFAULT_I_QP;
594 s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX;
595 s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN;
596
597 s_qp_ip.u4_p_qp = DEFAULT_P_QP;
598 s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX;
599 s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN;
600
601 s_qp_ip.u4_b_qp = DEFAULT_P_QP;
602 s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX;
603 s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN;
604
605 s_qp_ip.u4_timestamp_high = -1;
606 s_qp_ip.u4_timestamp_low = -1;
607
608 s_qp_ip.u4_size = sizeof(ive_ctl_set_qp_ip_t);
609 s_qp_op.u4_size = sizeof(ive_ctl_set_qp_op_t);
610
611 status = ive_api_function(mCodecCtx, &s_qp_ip, &s_qp_op);
612 if (status != IV_SUCCESS) {
613 ALOGE("Unable to set qp 0x%x\n", s_qp_op.u4_error_code);
614 return C2_CORRUPTED;
615 }
616 return C2_OK;
617}
618
619c2_status_t C2SoftAvcEnc::setEncMode(IVE_ENC_MODE_T e_enc_mode) {
620 IV_STATUS_T status;
621 ive_ctl_set_enc_mode_ip_t s_enc_mode_ip;
622 ive_ctl_set_enc_mode_op_t s_enc_mode_op;
623
624 s_enc_mode_ip.e_cmd = IVE_CMD_VIDEO_CTL;
625 s_enc_mode_ip.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
626
627 s_enc_mode_ip.e_enc_mode = e_enc_mode;
628
629 s_enc_mode_ip.u4_timestamp_high = -1;
630 s_enc_mode_ip.u4_timestamp_low = -1;
631
632 s_enc_mode_ip.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
633 s_enc_mode_op.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
634
635 status = ive_api_function(mCodecCtx, &s_enc_mode_ip, &s_enc_mode_op);
636 if (status != IV_SUCCESS) {
637 ALOGE("Unable to set in header encode mode = 0x%x\n",
638 s_enc_mode_op.u4_error_code);
639 return C2_CORRUPTED;
640 }
641 return C2_OK;
642}
643
644c2_status_t C2SoftAvcEnc::setVbvParams() {
645 ive_ctl_set_vbv_params_ip_t s_vbv_ip;
646 ive_ctl_set_vbv_params_op_t s_vbv_op;
647 IV_STATUS_T status;
648
649 s_vbv_ip.e_cmd = IVE_CMD_VIDEO_CTL;
650 s_vbv_ip.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
651
652 s_vbv_ip.u4_vbv_buf_size = 0;
653 s_vbv_ip.u4_vbv_buffer_delay = 1000;
654
655 s_vbv_ip.u4_timestamp_high = -1;
656 s_vbv_ip.u4_timestamp_low = -1;
657
658 s_vbv_ip.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
659 s_vbv_op.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
660
661 status = ive_api_function(mCodecCtx, &s_vbv_ip, &s_vbv_op);
662 if (status != IV_SUCCESS) {
663 ALOGE("Unable to set VBV params = 0x%x\n", s_vbv_op.u4_error_code);
664 return C2_CORRUPTED;
665 }
666 return C2_OK;
667}
668
669c2_status_t C2SoftAvcEnc::setAirParams() {
670 ive_ctl_set_air_params_ip_t s_air_ip;
671 ive_ctl_set_air_params_op_t s_air_op;
672 IV_STATUS_T status;
673
674 s_air_ip.e_cmd = IVE_CMD_VIDEO_CTL;
675 s_air_ip.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
676
677 s_air_ip.e_air_mode =
678 (mIntraRefresh->mode == C2Config::INTRA_REFRESH_DISABLED || mIntraRefresh->period < 1)
679 ? IVE_AIR_MODE_NONE : IVE_AIR_MODE_CYCLIC;
680 s_air_ip.u4_air_refresh_period = mIntraRefresh->period;
681
682 s_air_ip.u4_timestamp_high = -1;
683 s_air_ip.u4_timestamp_low = -1;
684
685 s_air_ip.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
686 s_air_op.u4_size = sizeof(ive_ctl_set_air_params_op_t);
687
688 status = ive_api_function(mCodecCtx, &s_air_ip, &s_air_op);
689 if (status != IV_SUCCESS) {
690 ALOGE("Unable to set air params = 0x%x\n", s_air_op.u4_error_code);
691 return C2_CORRUPTED;
692 }
693 return C2_OK;
694}
695
696c2_status_t C2SoftAvcEnc::setMeParams() {
697 IV_STATUS_T status;
698 ive_ctl_set_me_params_ip_t s_me_params_ip;
699 ive_ctl_set_me_params_op_t s_me_params_op;
700
701 s_me_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
702 s_me_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
703
704 s_me_params_ip.u4_enable_fast_sad = mEnableFastSad;
705 s_me_params_ip.u4_enable_alt_ref = mEnableAltRef;
706
707 s_me_params_ip.u4_enable_hpel = mHalfPelEnable;
708 s_me_params_ip.u4_enable_qpel = DEFAULT_QPEL;
709 s_me_params_ip.u4_me_speed_preset = DEFAULT_ME_SPEED;
710 s_me_params_ip.u4_srch_rng_x = DEFAULT_SRCH_RNG_X;
711 s_me_params_ip.u4_srch_rng_y = DEFAULT_SRCH_RNG_Y;
712
713 s_me_params_ip.u4_timestamp_high = -1;
714 s_me_params_ip.u4_timestamp_low = -1;
715
716 s_me_params_ip.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
717 s_me_params_op.u4_size = sizeof(ive_ctl_set_me_params_op_t);
718
719 status = ive_api_function(mCodecCtx, &s_me_params_ip, &s_me_params_op);
720 if (status != IV_SUCCESS) {
721 ALOGE("Unable to set me params = 0x%x\n", s_me_params_op.u4_error_code);
722 return C2_CORRUPTED;
723 }
724 return C2_OK;
725}
726
727c2_status_t C2SoftAvcEnc::setGopParams() {
728 IV_STATUS_T status;
729 ive_ctl_set_gop_params_ip_t s_gop_params_ip;
730 ive_ctl_set_gop_params_op_t s_gop_params_op;
731
732 s_gop_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
733 s_gop_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
734
735 s_gop_params_ip.u4_i_frm_interval = mIInterval;
736 s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
737
738 s_gop_params_ip.u4_timestamp_high = -1;
739 s_gop_params_ip.u4_timestamp_low = -1;
740
741 s_gop_params_ip.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
742 s_gop_params_op.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
743
744 status = ive_api_function(mCodecCtx, &s_gop_params_ip, &s_gop_params_op);
745 if (status != IV_SUCCESS) {
746 ALOGE("Unable to set GOP params = 0x%x\n",
747 s_gop_params_op.u4_error_code);
748 return C2_CORRUPTED;
749 }
750 return C2_OK;
751}
752
753c2_status_t C2SoftAvcEnc::setProfileParams() {
754 IntfImpl::Lock lock = mIntf->lock();
755
756 IV_STATUS_T status;
757 ive_ctl_set_profile_params_ip_t s_profile_params_ip;
758 ive_ctl_set_profile_params_op_t s_profile_params_op;
759
760 s_profile_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
761 s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
762
763 s_profile_params_ip.e_profile = mIntf->getProfile_l();
Harish Mahendrakar8725ae02018-08-31 10:33:56 -0700764 if (s_profile_params_ip.e_profile == IV_PROFILE_BASE) {
765 s_profile_params_ip.u4_entropy_coding_mode = 0;
766 } else {
767 s_profile_params_ip.u4_entropy_coding_mode = 1;
768 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800769 s_profile_params_ip.u4_timestamp_high = -1;
770 s_profile_params_ip.u4_timestamp_low = -1;
771
772 s_profile_params_ip.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
773 s_profile_params_op.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
774 lock.unlock();
775
776 status = ive_api_function(mCodecCtx, &s_profile_params_ip, &s_profile_params_op);
777 if (status != IV_SUCCESS) {
778 ALOGE("Unable to set profile params = 0x%x\n",
779 s_profile_params_op.u4_error_code);
780 return C2_CORRUPTED;
781 }
782 return C2_OK;
783}
784
785c2_status_t C2SoftAvcEnc::setDeblockParams() {
786 IV_STATUS_T status;
787 ive_ctl_set_deblock_params_ip_t s_deblock_params_ip;
788 ive_ctl_set_deblock_params_op_t s_deblock_params_op;
789
790 s_deblock_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
791 s_deblock_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
792
793 s_deblock_params_ip.u4_disable_deblock_level = mDisableDeblkLevel;
794
795 s_deblock_params_ip.u4_timestamp_high = -1;
796 s_deblock_params_ip.u4_timestamp_low = -1;
797
798 s_deblock_params_ip.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
799 s_deblock_params_op.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
800
801 status = ive_api_function(mCodecCtx, &s_deblock_params_ip, &s_deblock_params_op);
802 if (status != IV_SUCCESS) {
803 ALOGE("Unable to enable/disable deblock params = 0x%x\n",
804 s_deblock_params_op.u4_error_code);
805 return C2_CORRUPTED;
806 }
807 return C2_OK;
808}
809
810void C2SoftAvcEnc::logVersion() {
811 ive_ctl_getversioninfo_ip_t s_ctl_ip;
812 ive_ctl_getversioninfo_op_t s_ctl_op;
813 UWORD8 au1_buf[512];
814 IV_STATUS_T status;
815
816 s_ctl_ip.e_cmd = IVE_CMD_VIDEO_CTL;
817 s_ctl_ip.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
818 s_ctl_ip.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
819 s_ctl_op.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
820 s_ctl_ip.pu1_version = au1_buf;
821 s_ctl_ip.u4_version_bufsize = sizeof(au1_buf);
822
823 status = ive_api_function(mCodecCtx, (void *) &s_ctl_ip, (void *) &s_ctl_op);
824
825 if (status != IV_SUCCESS) {
826 ALOGE("Error in getting version: 0x%x", s_ctl_op.u4_error_code);
827 } else {
828 ALOGV("Ittiam encoder version: %s", (char *)s_ctl_ip.pu1_version);
829 }
830 return;
831}
832
833c2_status_t C2SoftAvcEnc::initEncoder() {
834 IV_STATUS_T status;
835 WORD32 level;
836
837 CHECK(!mStarted);
838
839 c2_status_t errType = C2_OK;
840
841 {
842 IntfImpl::Lock lock = mIntf->lock();
843 mSize = mIntf->getSize_l();
844 mBitrate = mIntf->getBitrate_l();
845 mFrameRate = mIntf->getFrameRate_l();
846 mIntraRefresh = mIntf->getIntraRefresh_l();
847 mAVCEncLevel = mIntf->getLevel_l();
848 mIInterval = mIntf->getSyncFramePeriod_l();
849 mIDRInterval = mIntf->getSyncFramePeriod_l();
850 }
851 uint32_t width = mSize->width;
852 uint32_t height = mSize->height;
853
854 mStride = width;
855
856 // TODO
857 mIvVideoColorFormat = IV_YUV_420P;
858
859 ALOGD("Params width %d height %d level %d colorFormat %d", width,
860 height, mAVCEncLevel, mIvVideoColorFormat);
861
862 /* Getting Number of MemRecords */
863 {
864 iv_num_mem_rec_ip_t s_num_mem_rec_ip;
865 iv_num_mem_rec_op_t s_num_mem_rec_op;
866
867 s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
868 s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
869
870 s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
871
872 status = ive_api_function(nullptr, &s_num_mem_rec_ip, &s_num_mem_rec_op);
873
874 if (status != IV_SUCCESS) {
875 ALOGE("Get number of memory records failed = 0x%x\n",
876 s_num_mem_rec_op.u4_error_code);
877 return C2_CORRUPTED;
878 }
879
880 mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
881 }
882
883 /* Allocate array to hold memory records */
884 if (mNumMemRecords > SIZE_MAX / sizeof(iv_mem_rec_t)) {
885 ALOGE("requested memory size is too big.");
886 return C2_CORRUPTED;
887 }
888 mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
889 if (nullptr == mMemRecords) {
890 ALOGE("Unable to allocate memory for hold memory records: Size %zu",
891 mNumMemRecords * sizeof(iv_mem_rec_t));
892 mSignalledError = true;
893 return C2_CORRUPTED;
894 }
895
896 {
897 iv_mem_rec_t *ps_mem_rec;
898 ps_mem_rec = mMemRecords;
899 for (size_t i = 0; i < mNumMemRecords; i++) {
900 ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
901 ps_mem_rec->pv_base = nullptr;
902 ps_mem_rec->u4_mem_size = 0;
903 ps_mem_rec->u4_mem_alignment = 0;
904 ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
905
906 ps_mem_rec++;
907 }
908 }
909
910 /* Getting MemRecords Attributes */
911 {
912 iv_fill_mem_rec_ip_t s_fill_mem_rec_ip;
913 iv_fill_mem_rec_op_t s_fill_mem_rec_op;
914
915 s_fill_mem_rec_ip.u4_size = sizeof(iv_fill_mem_rec_ip_t);
916 s_fill_mem_rec_op.u4_size = sizeof(iv_fill_mem_rec_op_t);
917
918 s_fill_mem_rec_ip.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
919 s_fill_mem_rec_ip.ps_mem_rec = mMemRecords;
920 s_fill_mem_rec_ip.u4_num_mem_rec = mNumMemRecords;
921 s_fill_mem_rec_ip.u4_max_wd = width;
922 s_fill_mem_rec_ip.u4_max_ht = height;
923 s_fill_mem_rec_ip.u4_max_level = mAVCEncLevel;
924 s_fill_mem_rec_ip.e_color_format = DEFAULT_INP_COLOR_FORMAT;
925 s_fill_mem_rec_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
926 s_fill_mem_rec_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
927 s_fill_mem_rec_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
928 s_fill_mem_rec_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
929
930 status = ive_api_function(nullptr, &s_fill_mem_rec_ip, &s_fill_mem_rec_op);
931
932 if (status != IV_SUCCESS) {
933 ALOGE("Fill memory records failed = 0x%x\n",
934 s_fill_mem_rec_op.u4_error_code);
935 return C2_CORRUPTED;
936 }
937 }
938
939 /* Allocating Memory for Mem Records */
940 {
941 WORD32 total_size;
942 iv_mem_rec_t *ps_mem_rec;
943 total_size = 0;
944 ps_mem_rec = mMemRecords;
945
946 for (size_t i = 0; i < mNumMemRecords; i++) {
947 ps_mem_rec->pv_base = ive_aligned_malloc(
948 ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
949 if (ps_mem_rec->pv_base == nullptr) {
950 ALOGE("Allocation failure for mem record id %zu size %u\n", i,
951 ps_mem_rec->u4_mem_size);
952 return C2_CORRUPTED;
953
954 }
955 total_size += ps_mem_rec->u4_mem_size;
956
957 ps_mem_rec++;
958 }
959 }
960
961 /* Codec Instance Creation */
962 {
963 ive_init_ip_t s_init_ip;
964 ive_init_op_t s_init_op;
965
966 mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
967 mCodecCtx->u4_size = sizeof(iv_obj_t);
968 mCodecCtx->pv_fxns = (void *)ive_api_function;
969
970 s_init_ip.u4_size = sizeof(ive_init_ip_t);
971 s_init_op.u4_size = sizeof(ive_init_op_t);
972
973 s_init_ip.e_cmd = IV_CMD_INIT;
974 s_init_ip.u4_num_mem_rec = mNumMemRecords;
975 s_init_ip.ps_mem_rec = mMemRecords;
976 s_init_ip.u4_max_wd = width;
977 s_init_ip.u4_max_ht = height;
978 s_init_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
979 s_init_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
980 s_init_ip.u4_max_level = mAVCEncLevel;
981 s_init_ip.e_inp_color_fmt = mIvVideoColorFormat;
982
983 if (mReconEnable || mPSNREnable) {
984 s_init_ip.u4_enable_recon = 1;
985 } else {
986 s_init_ip.u4_enable_recon = 0;
987 }
988 s_init_ip.e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
989 s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
990 s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
991 s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
992 s_init_ip.u4_num_bframes = mBframes;
993 s_init_ip.e_content_type = IV_PROGRESSIVE;
994 s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
995 s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
996 s_init_ip.e_slice_mode = mSliceMode;
997 s_init_ip.u4_slice_param = mSliceParam;
998 s_init_ip.e_arch = mArch;
999 s_init_ip.e_soc = DEFAULT_SOC;
1000
1001 status = ive_api_function(mCodecCtx, &s_init_ip, &s_init_op);
1002
1003 if (status != IV_SUCCESS) {
1004 ALOGE("Init encoder failed = 0x%x\n", s_init_op.u4_error_code);
1005 return C2_CORRUPTED;
1006 }
1007 }
1008
1009 /* Get Codec Version */
1010 logVersion();
1011
1012 /* set processor details */
1013 setNumCores();
1014
1015 /* Video control Set Frame dimensions */
1016 setDimensions();
1017
1018 /* Video control Set Frame rates */
1019 setFrameRate();
1020
1021 /* Video control Set IPE Params */
1022 setIpeParams();
1023
1024 /* Video control Set Bitrate */
1025 setBitRate();
1026
1027 /* Video control Set QP */
1028 setQp();
1029
1030 /* Video control Set AIR params */
1031 setAirParams();
1032
1033 /* Video control Set VBV params */
1034 setVbvParams();
1035
1036 /* Video control Set Motion estimation params */
1037 setMeParams();
1038
1039 /* Video control Set GOP params */
1040 setGopParams();
1041
1042 /* Video control Set Deblock params */
1043 setDeblockParams();
1044
1045 /* Video control Set Profile params */
1046 setProfileParams();
1047
1048 /* Video control Set in Encode header mode */
1049 setEncMode(IVE_ENC_MODE_HEADER);
1050
1051 ALOGV("init_codec successfull");
1052
1053 mSpsPpsHeaderReceived = false;
1054 mStarted = true;
1055
1056 return C2_OK;
1057}
1058
1059c2_status_t C2SoftAvcEnc::releaseEncoder() {
1060 IV_STATUS_T status = IV_SUCCESS;
1061 iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
1062 iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
1063 iv_mem_rec_t *ps_mem_rec;
1064
1065 if (!mStarted) {
1066 return C2_OK;
1067 }
1068
1069 s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
1070 s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
1071 s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
1072 s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
1073
1074 status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
1075
1076 if (status != IV_SUCCESS) {
1077 ALOGE("Unable to retrieve memory records = 0x%x\n",
1078 s_retrieve_mem_op.u4_error_code);
1079 return C2_CORRUPTED;
1080 }
1081
1082 /* Free memory records */
1083 ps_mem_rec = mMemRecords;
1084 for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
1085 if (ps_mem_rec) ive_aligned_free(ps_mem_rec->pv_base);
1086 else {
1087 ALOGE("memory record is null.");
1088 return C2_CORRUPTED;
1089 }
1090 ps_mem_rec++;
1091 }
1092
1093 if (mMemRecords) free(mMemRecords);
1094
1095 // clear other pointers into the space being free()d
1096 mCodecCtx = nullptr;
1097
1098 mStarted = false;
1099
1100 return C2_OK;
1101}
1102
1103c2_status_t C2SoftAvcEnc::setEncodeArgs(
1104 ive_video_encode_ip_t *ps_encode_ip,
1105 ive_video_encode_op_t *ps_encode_op,
1106 const C2GraphicView *const input,
1107 uint8_t *base,
1108 uint32_t capacity,
1109 uint64_t timestamp) {
1110 iv_raw_buf_t *ps_inp_raw_buf;
1111
1112 ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
1113 ps_encode_ip->s_out_buf.pv_buf = base;
1114 ps_encode_ip->s_out_buf.u4_bytes = 0;
1115 ps_encode_ip->s_out_buf.u4_bufsize = capacity;
1116 ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
1117 ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
1118
1119 ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
1120 ps_encode_ip->pv_bufs = nullptr;
1121 ps_encode_ip->pv_mb_info = nullptr;
1122 ps_encode_ip->pv_pic_info = nullptr;
1123 ps_encode_ip->u4_mb_info_type = 0;
1124 ps_encode_ip->u4_pic_info_type = 0;
1125 ps_encode_ip->u4_is_last = 0;
1126 ps_encode_ip->u4_timestamp_high = timestamp >> 32;
1127 ps_encode_ip->u4_timestamp_low = timestamp & 0xFFFFFFFF;
1128 ps_encode_op->s_out_buf.pv_buf = nullptr;
1129
1130 /* Initialize color formats */
1131 memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
1132 ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
1133 ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
1134 if (input == nullptr) {
1135 if (mSawInputEOS){
1136 ps_encode_ip->u4_is_last = 1;
1137 }
1138 return C2_OK;
1139 }
1140
1141 if (input->width() < mSize->width ||
1142 input->height() < mSize->height) {
1143 /* Expect width height to be configured */
1144 ALOGW("unexpected Capacity Aspect %d(%d) x %d(%d)", input->width(),
1145 mSize->width, input->height(), mSize->height);
1146 return C2_BAD_VALUE;
1147 }
1148 ALOGV("width = %d, height = %d", input->width(), input->height());
1149 const C2PlanarLayout &layout = input->layout();
1150 uint8_t *yPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_Y]);
1151 uint8_t *uPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_U]);
1152 uint8_t *vPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_V]);
1153 int32_t yStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
1154 int32_t uStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
1155 int32_t vStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
1156
1157 uint32_t width = mSize->width;
1158 uint32_t height = mSize->height;
1159 // width and height are always even (as block size is 16x16)
1160 CHECK_EQ((width & 1u), 0u);
1161 CHECK_EQ((height & 1u), 0u);
1162 size_t yPlaneSize = width * height;
1163
1164 switch (layout.type) {
1165 case C2PlanarLayout::TYPE_RGB:
1166 [[fallthrough]];
1167 case C2PlanarLayout::TYPE_RGBA: {
1168 ALOGV("yPlaneSize = %zu", yPlaneSize);
1169 MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
1170 mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
1171 yPlane = conversionBuffer.data();
1172 uPlane = yPlane + yPlaneSize;
1173 vPlane = uPlane + yPlaneSize / 4;
1174 yStride = width;
1175 uStride = vStride = yStride / 2;
1176 ConvertRGBToPlanarYUV(yPlane, yStride, height, conversionBuffer.size(), *input);
1177 break;
1178 }
1179 case C2PlanarLayout::TYPE_YUV: {
1180 if (!IsYUV420(*input)) {
1181 ALOGE("input is not YUV420");
1182 return C2_BAD_VALUE;
1183 }
1184
1185 if (layout.planes[layout.PLANE_Y].colInc == 1
1186 && layout.planes[layout.PLANE_U].colInc == 1
1187 && layout.planes[layout.PLANE_V].colInc == 1
1188 && uStride == vStride
1189 && yStride == 2 * vStride) {
1190 // I420 compatible - already set up above
1191 break;
1192 }
1193
1194 // copy to I420
1195 yStride = width;
1196 uStride = vStride = yStride / 2;
1197 MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
1198 mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
1199 MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, yStride, height);
1200 status_t err = ImageCopy(conversionBuffer.data(), &img, *input);
1201 if (err != OK) {
1202 ALOGE("Buffer conversion failed: %d", err);
1203 return C2_BAD_VALUE;
1204 }
1205 yPlane = conversionBuffer.data();
1206 uPlane = yPlane + yPlaneSize;
1207 vPlane = uPlane + yPlaneSize / 4;
1208 break;
1209
1210 }
1211
1212 case C2PlanarLayout::TYPE_YUVA:
1213 ALOGE("YUVA plane type is not supported");
1214 return C2_BAD_VALUE;
1215
1216 default:
1217 ALOGE("Unrecognized plane type: %d", layout.type);
1218 return C2_BAD_VALUE;
1219 }
1220
1221 switch (mIvVideoColorFormat) {
1222 case IV_YUV_420P:
1223 {
1224 // input buffer is supposed to be const but Ittiam API wants bare pointer.
1225 ps_inp_raw_buf->apv_bufs[0] = yPlane;
1226 ps_inp_raw_buf->apv_bufs[1] = uPlane;
1227 ps_inp_raw_buf->apv_bufs[2] = vPlane;
1228
1229 ps_inp_raw_buf->au4_wd[0] = input->width();
1230 ps_inp_raw_buf->au4_wd[1] = input->width() / 2;
1231 ps_inp_raw_buf->au4_wd[2] = input->width() / 2;
1232
1233 ps_inp_raw_buf->au4_ht[0] = input->height();
1234 ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
1235 ps_inp_raw_buf->au4_ht[2] = input->height() / 2;
1236
1237 ps_inp_raw_buf->au4_strd[0] = yStride;
1238 ps_inp_raw_buf->au4_strd[1] = uStride;
1239 ps_inp_raw_buf->au4_strd[2] = vStride;
1240 break;
1241 }
1242
1243 case IV_YUV_422ILE:
1244 {
1245 // TODO
1246 // ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1247 // ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
1248 // ps_inp_raw_buf->au4_ht[0] = mHeight;
1249 // ps_inp_raw_buf->au4_strd[0] = mStride * 2;
1250 break;
1251 }
1252
1253 case IV_YUV_420SP_UV:
1254 case IV_YUV_420SP_VU:
1255 default:
1256 {
1257 ps_inp_raw_buf->apv_bufs[0] = yPlane;
1258 ps_inp_raw_buf->apv_bufs[1] = uPlane;
1259
1260 ps_inp_raw_buf->au4_wd[0] = input->width();
1261 ps_inp_raw_buf->au4_wd[1] = input->width();
1262
1263 ps_inp_raw_buf->au4_ht[0] = input->height();
1264 ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
1265
1266 ps_inp_raw_buf->au4_strd[0] = yStride;
1267 ps_inp_raw_buf->au4_strd[1] = uStride;
1268 break;
1269 }
1270 }
1271 return C2_OK;
1272}
1273
1274void C2SoftAvcEnc::process(
1275 const std::unique_ptr<C2Work> &work,
1276 const std::shared_ptr<C2BlockPool> &pool) {
1277 // Initialize output work
1278 work->result = C2_OK;
1279 work->workletsProcessed = 1u;
1280 work->worklets.front()->output.flags = work->input.flags;
1281
1282 IV_STATUS_T status;
1283 WORD32 timeDelay, timeTaken;
1284 uint64_t timestamp = work->input.ordinal.timestamp.peekull();
1285
1286 // Initialize encoder if not already initialized
1287 if (mCodecCtx == nullptr) {
1288 if (C2_OK != initEncoder()) {
1289 ALOGE("Failed to initialize encoder");
1290 mSignalledError = true;
1291 work->result = C2_CORRUPTED;
1292 return;
1293 }
1294 }
1295 if (mSignalledError) {
1296 return;
1297 }
1298
1299 // while (!mSawOutputEOS && !outQueue.empty()) {
1300 c2_status_t error;
1301 ive_video_encode_ip_t s_encode_ip;
1302 ive_video_encode_op_t s_encode_op;
1303
1304 if (!mSpsPpsHeaderReceived) {
1305 constexpr uint32_t kHeaderLength = MIN_STREAM_SIZE;
1306 uint8_t header[kHeaderLength];
1307 error = setEncodeArgs(
1308 &s_encode_ip, &s_encode_op, nullptr, header, kHeaderLength, timestamp);
1309 if (error != C2_OK) {
1310 ALOGE("setEncodeArgs failed: %d", error);
1311 mSignalledError = true;
1312 work->result = C2_CORRUPTED;
1313 return;
1314 }
1315 status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1316
1317 if (IV_SUCCESS != status) {
1318 ALOGE("Encode header failed = 0x%x\n",
1319 s_encode_op.u4_error_code);
1320 return;
1321 } else {
1322 ALOGV("Bytes Generated in header %d\n",
1323 s_encode_op.s_out_buf.u4_bytes);
1324 }
1325
1326 mSpsPpsHeaderReceived = true;
1327
Lajos Molnar3bb81cd2019-02-20 15:10:30 -08001328 std::unique_ptr<C2StreamInitDataInfo::output> csd =
1329 C2StreamInitDataInfo::output::AllocUnique(s_encode_op.s_out_buf.u4_bytes, 0u);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001330 if (!csd) {
1331 ALOGE("CSD allocation failed");
1332 mSignalledError = true;
1333 work->result = C2_NO_MEMORY;
1334 return;
1335 }
1336 memcpy(csd->m.value, header, s_encode_op.s_out_buf.u4_bytes);
1337 work->worklets.front()->output.configUpdate.push_back(std::move(csd));
1338
1339 DUMP_TO_FILE(
1340 mOutFile, csd->m.value, csd->flexCount());
1341 }
1342
1343 // handle dynamic config parameters
1344 {
1345 IntfImpl::Lock lock = mIntf->lock();
1346 std::shared_ptr<C2StreamIntraRefreshTuning::output> intraRefresh = mIntf->getIntraRefresh_l();
1347 std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
1348 std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync = mIntf->getRequestSync_l();
1349 lock.unlock();
1350
1351 if (bitrate != mBitrate) {
1352 mBitrate = bitrate;
1353 setBitRate();
1354 }
1355
1356 if (intraRefresh != mIntraRefresh) {
1357 mIntraRefresh = intraRefresh;
1358 setAirParams();
1359 }
1360
1361 if (requestSync != mRequestSync) {
1362 // we can handle IDR immediately
1363 if (requestSync->value) {
1364 // unset request
1365 C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE);
1366 std::vector<std::unique_ptr<C2SettingResult>> failures;
1367 mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures);
1368 ALOGV("Got sync request");
1369 setFrameType(IV_IDR_FRAME);
1370 }
1371 mRequestSync = requestSync;
1372 }
1373 }
1374
1375 if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
1376 mSawInputEOS = true;
1377 }
1378
1379 /* In normal mode, store inputBufferInfo and this will be returned
1380 when encoder consumes this input */
1381 // if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
1382 // for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1383 // if (NULL == mInputBufferInfo[i]) {
1384 // mInputBufferInfo[i] = inputBufferInfo;
1385 // break;
1386 // }
1387 // }
1388 // }
1389 std::shared_ptr<const C2GraphicView> view;
1390 std::shared_ptr<C2Buffer> inputBuffer;
1391 if (!work->input.buffers.empty()) {
1392 inputBuffer = work->input.buffers[0];
1393 view = std::make_shared<const C2GraphicView>(
1394 inputBuffer->data().graphicBlocks().front().map().get());
1395 if (view->error() != C2_OK) {
1396 ALOGE("graphic view map err = %d", view->error());
1397 return;
1398 }
1399 }
1400
1401 std::shared_ptr<C2LinearBlock> block;
1402
1403 do {
1404 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1405 // TODO: error handling, proper usage, etc.
1406 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
1407 if (err != C2_OK) {
1408 ALOGE("fetch linear block err = %d", err);
1409 work->result = err;
1410 return;
1411 }
1412 C2WriteView wView = block->map().get();
1413 if (wView.error() != C2_OK) {
1414 ALOGE("write view map err = %d", wView.error());
1415 work->result = wView.error();
1416 return;
1417 }
1418
1419 error = setEncodeArgs(
1420 &s_encode_ip, &s_encode_op, view.get(), wView.base(), wView.capacity(), timestamp);
1421 if (error != C2_OK) {
1422 ALOGE("setEncodeArgs failed : %d", error);
1423 mSignalledError = true;
1424 work->result = error;
1425 return;
1426 }
1427
1428 // DUMP_TO_FILE(
1429 // mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
1430 // (mHeight * mStride * 3 / 2));
1431
1432 GETTIME(&mTimeStart, nullptr);
1433 /* Compute time elapsed between end of previous decode()
1434 * to start of current decode() */
1435 TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
1436 status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1437
1438 if (IV_SUCCESS != status) {
1439 if ((s_encode_op.u4_error_code & 0xFF) == IH264E_BITSTREAM_BUFFER_OVERFLOW) {
1440 // TODO: use IVE_CMD_CTL_GETBUFINFO for proper max input size?
1441 mOutBufferSize *= 2;
1442 continue;
1443 }
1444 ALOGE("Encode Frame failed = 0x%x\n",
1445 s_encode_op.u4_error_code);
1446 mSignalledError = true;
1447 work->result = C2_CORRUPTED;
1448 return;
1449 }
1450 } while (IV_SUCCESS != status);
1451
1452 // Hold input buffer reference
1453 if (inputBuffer) {
1454 mBuffers[s_encode_ip.s_inp_buf.apv_bufs[0]] = inputBuffer;
1455 }
1456
1457 GETTIME(&mTimeEnd, nullptr);
1458 /* Compute time taken for decode() */
1459 TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
1460
1461 ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
1462 s_encode_op.s_out_buf.u4_bytes);
1463
1464 void *freed = s_encode_op.s_inp_buf.apv_bufs[0];
1465 /* If encoder frees up an input buffer, mark it as free */
1466 if (freed != nullptr) {
1467 if (mBuffers.count(freed) == 0u) {
1468 ALOGD("buffer not tracked");
1469 } else {
1470 // Release input buffer reference
1471 mBuffers.erase(freed);
1472 mConversionBuffersInUse.erase(freed);
1473 }
1474 }
1475
1476 work->worklets.front()->output.flags = work->input.flags;
1477 work->worklets.front()->output.ordinal = work->input.ordinal;
1478 work->worklets.front()->output.ordinal.timestamp =
1479 ((uint64_t)s_encode_op.u4_timestamp_high << 32) | s_encode_op.u4_timestamp_low;
1480 work->worklets.front()->output.buffers.clear();
1481
1482 if (s_encode_op.s_out_buf.u4_bytes) {
1483 std::shared_ptr<C2Buffer> buffer =
1484 createLinearBuffer(block, 0, s_encode_op.s_out_buf.u4_bytes);
1485 if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
1486 ALOGV("IDR frame produced");
1487 buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -08001488 0u /* stream id */, C2Config::SYNC_FRAME));
Pawin Vongmasa36653902018-11-15 00:10:25 -08001489 }
1490 work->worklets.front()->output.buffers.push_back(buffer);
1491 }
1492
1493 if (s_encode_op.u4_is_last) {
1494 // outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
1495 mSawOutputEOS = true;
1496 } else {
1497 // outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
1498 }
1499}
1500
1501c2_status_t C2SoftAvcEnc::drain(
1502 uint32_t drainMode,
1503 const std::shared_ptr<C2BlockPool> &pool) {
1504 // TODO: use IVE_CMD_CTL_FLUSH?
1505 (void)drainMode;
1506 (void)pool;
1507 return C2_OK;
1508}
1509
1510
1511class C2SoftAvcEncFactory : public C2ComponentFactory {
1512public:
1513 C2SoftAvcEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
1514 GetCodec2PlatformComponentStore()->getParamReflector())) {
1515 }
1516
1517 virtual c2_status_t createComponent(
1518 c2_node_id_t id,
1519 std::shared_ptr<C2Component>* const component,
1520 std::function<void(C2Component*)> deleter) override {
1521 *component = std::shared_ptr<C2Component>(
1522 new C2SoftAvcEnc(COMPONENT_NAME,
1523 id,
1524 std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)),
1525 deleter);
1526 return C2_OK;
1527 }
1528
1529 virtual c2_status_t createInterface(
1530 c2_node_id_t id,
1531 std::shared_ptr<C2ComponentInterface>* const interface,
1532 std::function<void(C2ComponentInterface*)> deleter) override {
1533 *interface = std::shared_ptr<C2ComponentInterface>(
1534 new SimpleInterface<C2SoftAvcEnc::IntfImpl>(
1535 COMPONENT_NAME, id, std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)),
1536 deleter);
1537 return C2_OK;
1538 }
1539
1540 virtual ~C2SoftAvcEncFactory() override = default;
1541
1542private:
1543 std::shared_ptr<C2ReflectorHelper> mHelper;
1544};
1545
1546} // namespace android
1547
1548extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
1549 ALOGV("in %s", __func__);
1550 return new ::android::C2SoftAvcEncFactory();
1551}
1552
1553extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
1554 ALOGV("in %s", __func__);
1555 delete factory;
1556}