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 <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
38 namespace android {
39
40 class C2SoftAvcEnc::IntfImpl : public C2InterfaceHelper {
41 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)42 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
43 : C2InterfaceHelper(helper) {
44
45 setDerivedInstance(this);
46
47 addParameter(
48 DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING)
49 .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatVideo))
50 .build());
51
52 addParameter(
53 DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING)
54 .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatCompressed))
55 .build());
56
57 addParameter(
58 DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING)
59 .withConstValue(AllocSharedString<C2PortMimeConfig::input>(
60 MEDIA_MIMETYPE_VIDEO_RAW))
61 .build());
62
63 addParameter(
64 DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING)
65 .withConstValue(AllocSharedString<C2PortMimeConfig::output>(
66 MEDIA_MIMETYPE_VIDEO_AVC))
67 .build());
68
69 addParameter(
70 DefineParam(mUsage, C2_NAME_INPUT_STREAM_USAGE_SETTING)
71 .withConstValue(new C2StreamUsageTuning::input(
72 0u, (uint64_t)C2MemoryUsage::CPU_READ))
73 .build());
74
75 addParameter(
76 DefineParam(mSize, C2_NAME_STREAM_VIDEO_SIZE_SETTING)
77 .withDefault(new C2VideoSizeStreamTuning::input(0u, 320, 240))
78 .withFields({
79 C2F(mSize, width).inRange(2, 2560, 2),
80 C2F(mSize, height).inRange(2, 2560, 2),
81 })
82 .withSetter(SizeSetter)
83 .build());
84
85 addParameter(
86 DefineParam(mFrameRate, C2_NAME_STREAM_FRAME_RATE_SETTING)
87 .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
88 // TODO: More restriction?
89 .withFields({C2F(mFrameRate, value).greaterThan(0.)})
90 .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
91 .build());
92
93 addParameter(
94 DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING)
95 .withDefault(new C2BitrateTuning::output(0u, 64000))
96 .withFields({C2F(mBitrate, value).inRange(1, 12000000)})
97 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
98 .build());
99 }
100
SizeSetter(bool mayBlock,C2P<C2VideoSizeStreamTuning::input> & me)101 static C2R SizeSetter(bool mayBlock, C2P<C2VideoSizeStreamTuning::input> &me) {
102 (void)mayBlock;
103 // TODO: maybe apply block limit?
104 C2R res = C2R::Ok();
105 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
106 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
107 }
108 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
109 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
110 }
111 return res;
112 }
113
getWidth() const114 uint32_t getWidth() const { return mSize->width; }
getHeight() const115 uint32_t getHeight() const { return mSize->height; }
getFrameRate() const116 float getFrameRate() const { return mFrameRate->value; }
getBitrate() const117 uint32_t getBitrate() const { return mBitrate->value; }
118
119 private:
120 std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
121 std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
122 std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
123 std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
124 std::shared_ptr<C2StreamUsageTuning::input> mUsage;
125 std::shared_ptr<C2VideoSizeStreamTuning::input> mSize;
126 std::shared_ptr<C2StreamFrameRateInfo::output> mFrameRate;
127 std::shared_ptr<C2BitrateTuning::output> mBitrate;
128 };
129
130 #define ive_api_function ih264e_api_function
131
132 constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
133
134 namespace {
135
136 // From external/libavc/encoder/ih264e_bitstream.h
137 constexpr uint32_t MIN_STREAM_SIZE = 0x800;
138
GetCPUCoreCount()139 static size_t GetCPUCoreCount() {
140 long cpuCoreCount = 1;
141 #if defined(_SC_NPROCESSORS_ONLN)
142 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
143 #else
144 // _SC_NPROC_ONLN must be defined...
145 cpuCoreCount = sysconf(_SC_NPROC_ONLN);
146 #endif
147 CHECK(cpuCoreCount >= 1);
148 ALOGV("Number of CPU cores: %ld", cpuCoreCount);
149 return (size_t)cpuCoreCount;
150 }
151
152 } // namespace
153
C2SoftAvcEnc(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)154 C2SoftAvcEnc::C2SoftAvcEnc(
155 const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl)
156 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
157 mIntf(intfImpl),
158 mUpdateFlag(0),
159 mIvVideoColorFormat(IV_YUV_420P),
160 mAVCEncProfile(IV_PROFILE_BASE),
161 mAVCEncLevel(41),
162 mStarted(false),
163 mSawInputEOS(false),
164 mSawOutputEOS(false),
165 mSignalledError(false),
166 mCodecCtx(NULL),
167 // TODO: output buffer size
168 mOutBufferSize(524288) {
169
170 // If dump is enabled, then open create an empty file
171 GENERATE_FILE_NAMES();
172 CREATE_DUMP_FILE(mInFile);
173 CREATE_DUMP_FILE(mOutFile);
174
175 initEncParams();
176 }
177
~C2SoftAvcEnc()178 C2SoftAvcEnc::~C2SoftAvcEnc() {
179 releaseEncoder();
180 }
181
onInit()182 c2_status_t C2SoftAvcEnc::onInit() {
183 return C2_OK;
184 }
185
onStop()186 c2_status_t C2SoftAvcEnc::onStop() {
187 return C2_OK;
188 }
189
onReset()190 void C2SoftAvcEnc::onReset() {
191 // TODO: use IVE_CMD_CTL_RESET?
192 releaseEncoder();
193 initEncParams();
194 }
195
onRelease()196 void C2SoftAvcEnc::onRelease() {
197 releaseEncoder();
198 }
199
onFlush_sm()200 c2_status_t C2SoftAvcEnc::onFlush_sm() {
201 // TODO: use IVE_CMD_CTL_FLUSH?
202 return C2_OK;
203 }
204
initEncParams()205 void C2SoftAvcEnc::initEncParams() {
206 mCodecCtx = NULL;
207 mMemRecords = NULL;
208 mNumMemRecords = DEFAULT_MEM_REC_CNT;
209 mHeaderGenerated = 0;
210 mNumCores = GetCPUCoreCount();
211 mArch = DEFAULT_ARCH;
212 mSliceMode = DEFAULT_SLICE_MODE;
213 mSliceParam = DEFAULT_SLICE_PARAM;
214 mHalfPelEnable = DEFAULT_HPEL;
215 mIInterval = DEFAULT_I_INTERVAL;
216 mIDRInterval = DEFAULT_IDR_INTERVAL;
217 mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
218 mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
219 mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
220 mEncSpeed = DEFAULT_ENC_SPEED;
221 mIntra4x4 = DEFAULT_INTRA4x4;
222 mConstrainedIntraFlag = DEFAULT_CONSTRAINED_INTRA;
223 mAIRMode = DEFAULT_AIR;
224 mAIRRefreshPeriod = DEFAULT_AIR_REFRESH_PERIOD;
225 mPSNREnable = DEFAULT_PSNR_ENABLE;
226 mReconEnable = DEFAULT_RECON_ENABLE;
227 mEntropyMode = DEFAULT_ENTROPY_MODE;
228 mBframes = DEFAULT_B_FRAMES;
229
230 gettimeofday(&mTimeStart, NULL);
231 gettimeofday(&mTimeEnd, NULL);
232 }
233
setDimensions()234 c2_status_t C2SoftAvcEnc::setDimensions() {
235 ive_ctl_set_dimensions_ip_t s_dimensions_ip;
236 ive_ctl_set_dimensions_op_t s_dimensions_op;
237 IV_STATUS_T status;
238
239 s_dimensions_ip.e_cmd = IVE_CMD_VIDEO_CTL;
240 s_dimensions_ip.e_sub_cmd = IVE_CMD_CTL_SET_DIMENSIONS;
241 s_dimensions_ip.u4_ht = mIntf->getHeight();
242 s_dimensions_ip.u4_wd = mIntf->getWidth();
243
244 s_dimensions_ip.u4_timestamp_high = -1;
245 s_dimensions_ip.u4_timestamp_low = -1;
246
247 s_dimensions_ip.u4_size = sizeof(ive_ctl_set_dimensions_ip_t);
248 s_dimensions_op.u4_size = sizeof(ive_ctl_set_dimensions_op_t);
249
250 status = ive_api_function(mCodecCtx, &s_dimensions_ip, &s_dimensions_op);
251 if (status != IV_SUCCESS) {
252 ALOGE("Unable to set frame dimensions = 0x%x\n",
253 s_dimensions_op.u4_error_code);
254 return C2_CORRUPTED;
255 }
256 return C2_OK;
257 }
258
setNumCores()259 c2_status_t C2SoftAvcEnc::setNumCores() {
260 IV_STATUS_T status;
261 ive_ctl_set_num_cores_ip_t s_num_cores_ip;
262 ive_ctl_set_num_cores_op_t s_num_cores_op;
263 s_num_cores_ip.e_cmd = IVE_CMD_VIDEO_CTL;
264 s_num_cores_ip.e_sub_cmd = IVE_CMD_CTL_SET_NUM_CORES;
265 s_num_cores_ip.u4_num_cores = MIN(mNumCores, CODEC_MAX_CORES);
266 s_num_cores_ip.u4_timestamp_high = -1;
267 s_num_cores_ip.u4_timestamp_low = -1;
268 s_num_cores_ip.u4_size = sizeof(ive_ctl_set_num_cores_ip_t);
269
270 s_num_cores_op.u4_size = sizeof(ive_ctl_set_num_cores_op_t);
271
272 status = ive_api_function(
273 mCodecCtx, (void *) &s_num_cores_ip, (void *) &s_num_cores_op);
274 if (status != IV_SUCCESS) {
275 ALOGE("Unable to set processor params = 0x%x\n",
276 s_num_cores_op.u4_error_code);
277 return C2_CORRUPTED;
278 }
279 return C2_OK;
280 }
281
setFrameRate()282 c2_status_t C2SoftAvcEnc::setFrameRate() {
283 ive_ctl_set_frame_rate_ip_t s_frame_rate_ip;
284 ive_ctl_set_frame_rate_op_t s_frame_rate_op;
285 IV_STATUS_T status;
286
287 s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
288 s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
289
290 s_frame_rate_ip.u4_src_frame_rate = mIntf->getFrameRate();
291 s_frame_rate_ip.u4_tgt_frame_rate = mIntf->getFrameRate();
292
293 s_frame_rate_ip.u4_timestamp_high = -1;
294 s_frame_rate_ip.u4_timestamp_low = -1;
295
296 s_frame_rate_ip.u4_size = sizeof(ive_ctl_set_frame_rate_ip_t);
297 s_frame_rate_op.u4_size = sizeof(ive_ctl_set_frame_rate_op_t);
298
299 status = ive_api_function(mCodecCtx, &s_frame_rate_ip, &s_frame_rate_op);
300 if (status != IV_SUCCESS) {
301 ALOGE("Unable to set frame rate = 0x%x\n",
302 s_frame_rate_op.u4_error_code);
303 return C2_CORRUPTED;
304 }
305 return C2_OK;
306 }
307
setIpeParams()308 c2_status_t C2SoftAvcEnc::setIpeParams() {
309 ive_ctl_set_ipe_params_ip_t s_ipe_params_ip;
310 ive_ctl_set_ipe_params_op_t s_ipe_params_op;
311 IV_STATUS_T status;
312
313 s_ipe_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
314 s_ipe_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_IPE_PARAMS;
315
316 s_ipe_params_ip.u4_enable_intra_4x4 = mIntra4x4;
317 s_ipe_params_ip.u4_enc_speed_preset = mEncSpeed;
318 s_ipe_params_ip.u4_constrained_intra_pred = mConstrainedIntraFlag;
319
320 s_ipe_params_ip.u4_timestamp_high = -1;
321 s_ipe_params_ip.u4_timestamp_low = -1;
322
323 s_ipe_params_ip.u4_size = sizeof(ive_ctl_set_ipe_params_ip_t);
324 s_ipe_params_op.u4_size = sizeof(ive_ctl_set_ipe_params_op_t);
325
326 status = ive_api_function(mCodecCtx, &s_ipe_params_ip, &s_ipe_params_op);
327 if (status != IV_SUCCESS) {
328 ALOGE("Unable to set ipe params = 0x%x\n",
329 s_ipe_params_op.u4_error_code);
330 return C2_CORRUPTED;
331 }
332 return C2_OK;
333 }
334
setBitRate()335 c2_status_t C2SoftAvcEnc::setBitRate() {
336 ive_ctl_set_bitrate_ip_t s_bitrate_ip;
337 ive_ctl_set_bitrate_op_t s_bitrate_op;
338 IV_STATUS_T status;
339
340 s_bitrate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
341 s_bitrate_ip.e_sub_cmd = IVE_CMD_CTL_SET_BITRATE;
342
343 s_bitrate_ip.u4_target_bitrate = mIntf->getBitrate();
344
345 s_bitrate_ip.u4_timestamp_high = -1;
346 s_bitrate_ip.u4_timestamp_low = -1;
347
348 s_bitrate_ip.u4_size = sizeof(ive_ctl_set_bitrate_ip_t);
349 s_bitrate_op.u4_size = sizeof(ive_ctl_set_bitrate_op_t);
350
351 status = ive_api_function(mCodecCtx, &s_bitrate_ip, &s_bitrate_op);
352 if (status != IV_SUCCESS) {
353 ALOGE("Unable to set bit rate = 0x%x\n", s_bitrate_op.u4_error_code);
354 return C2_CORRUPTED;
355 }
356 return C2_OK;
357 }
358
setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type)359 c2_status_t C2SoftAvcEnc::setFrameType(IV_PICTURE_CODING_TYPE_T e_frame_type) {
360 ive_ctl_set_frame_type_ip_t s_frame_type_ip;
361 ive_ctl_set_frame_type_op_t s_frame_type_op;
362 IV_STATUS_T status;
363 s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
364 s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
365
366 s_frame_type_ip.e_frame_type = e_frame_type;
367
368 s_frame_type_ip.u4_timestamp_high = -1;
369 s_frame_type_ip.u4_timestamp_low = -1;
370
371 s_frame_type_ip.u4_size = sizeof(ive_ctl_set_frame_type_ip_t);
372 s_frame_type_op.u4_size = sizeof(ive_ctl_set_frame_type_op_t);
373
374 status = ive_api_function(mCodecCtx, &s_frame_type_ip, &s_frame_type_op);
375 if (status != IV_SUCCESS) {
376 ALOGE("Unable to set frame type = 0x%x\n",
377 s_frame_type_op.u4_error_code);
378 return C2_CORRUPTED;
379 }
380 return C2_OK;
381 }
382
setQp()383 c2_status_t C2SoftAvcEnc::setQp() {
384 ive_ctl_set_qp_ip_t s_qp_ip;
385 ive_ctl_set_qp_op_t s_qp_op;
386 IV_STATUS_T status;
387
388 s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
389 s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
390
391 s_qp_ip.u4_i_qp = DEFAULT_I_QP;
392 s_qp_ip.u4_i_qp_max = DEFAULT_QP_MAX;
393 s_qp_ip.u4_i_qp_min = DEFAULT_QP_MIN;
394
395 s_qp_ip.u4_p_qp = DEFAULT_P_QP;
396 s_qp_ip.u4_p_qp_max = DEFAULT_QP_MAX;
397 s_qp_ip.u4_p_qp_min = DEFAULT_QP_MIN;
398
399 s_qp_ip.u4_b_qp = DEFAULT_P_QP;
400 s_qp_ip.u4_b_qp_max = DEFAULT_QP_MAX;
401 s_qp_ip.u4_b_qp_min = DEFAULT_QP_MIN;
402
403 s_qp_ip.u4_timestamp_high = -1;
404 s_qp_ip.u4_timestamp_low = -1;
405
406 s_qp_ip.u4_size = sizeof(ive_ctl_set_qp_ip_t);
407 s_qp_op.u4_size = sizeof(ive_ctl_set_qp_op_t);
408
409 status = ive_api_function(mCodecCtx, &s_qp_ip, &s_qp_op);
410 if (status != IV_SUCCESS) {
411 ALOGE("Unable to set qp 0x%x\n", s_qp_op.u4_error_code);
412 return C2_CORRUPTED;
413 }
414 return C2_OK;
415 }
416
setEncMode(IVE_ENC_MODE_T e_enc_mode)417 c2_status_t C2SoftAvcEnc::setEncMode(IVE_ENC_MODE_T e_enc_mode) {
418 IV_STATUS_T status;
419 ive_ctl_set_enc_mode_ip_t s_enc_mode_ip;
420 ive_ctl_set_enc_mode_op_t s_enc_mode_op;
421
422 s_enc_mode_ip.e_cmd = IVE_CMD_VIDEO_CTL;
423 s_enc_mode_ip.e_sub_cmd = IVE_CMD_CTL_SET_ENC_MODE;
424
425 s_enc_mode_ip.e_enc_mode = e_enc_mode;
426
427 s_enc_mode_ip.u4_timestamp_high = -1;
428 s_enc_mode_ip.u4_timestamp_low = -1;
429
430 s_enc_mode_ip.u4_size = sizeof(ive_ctl_set_enc_mode_ip_t);
431 s_enc_mode_op.u4_size = sizeof(ive_ctl_set_enc_mode_op_t);
432
433 status = ive_api_function(mCodecCtx, &s_enc_mode_ip, &s_enc_mode_op);
434 if (status != IV_SUCCESS) {
435 ALOGE("Unable to set in header encode mode = 0x%x\n",
436 s_enc_mode_op.u4_error_code);
437 return C2_CORRUPTED;
438 }
439 return C2_OK;
440 }
441
setVbvParams()442 c2_status_t C2SoftAvcEnc::setVbvParams() {
443 ive_ctl_set_vbv_params_ip_t s_vbv_ip;
444 ive_ctl_set_vbv_params_op_t s_vbv_op;
445 IV_STATUS_T status;
446
447 s_vbv_ip.e_cmd = IVE_CMD_VIDEO_CTL;
448 s_vbv_ip.e_sub_cmd = IVE_CMD_CTL_SET_VBV_PARAMS;
449
450 s_vbv_ip.u4_vbv_buf_size = 0;
451 s_vbv_ip.u4_vbv_buffer_delay = 1000;
452
453 s_vbv_ip.u4_timestamp_high = -1;
454 s_vbv_ip.u4_timestamp_low = -1;
455
456 s_vbv_ip.u4_size = sizeof(ive_ctl_set_vbv_params_ip_t);
457 s_vbv_op.u4_size = sizeof(ive_ctl_set_vbv_params_op_t);
458
459 status = ive_api_function(mCodecCtx, &s_vbv_ip, &s_vbv_op);
460 if (status != IV_SUCCESS) {
461 ALOGE("Unable to set VBV params = 0x%x\n", s_vbv_op.u4_error_code);
462 return C2_CORRUPTED;
463 }
464 return C2_OK;
465 }
466
setAirParams()467 c2_status_t C2SoftAvcEnc::setAirParams() {
468 ive_ctl_set_air_params_ip_t s_air_ip;
469 ive_ctl_set_air_params_op_t s_air_op;
470 IV_STATUS_T status;
471
472 s_air_ip.e_cmd = IVE_CMD_VIDEO_CTL;
473 s_air_ip.e_sub_cmd = IVE_CMD_CTL_SET_AIR_PARAMS;
474
475 s_air_ip.e_air_mode = mAIRMode;
476 s_air_ip.u4_air_refresh_period = mAIRRefreshPeriod;
477
478 s_air_ip.u4_timestamp_high = -1;
479 s_air_ip.u4_timestamp_low = -1;
480
481 s_air_ip.u4_size = sizeof(ive_ctl_set_air_params_ip_t);
482 s_air_op.u4_size = sizeof(ive_ctl_set_air_params_op_t);
483
484 status = ive_api_function(mCodecCtx, &s_air_ip, &s_air_op);
485 if (status != IV_SUCCESS) {
486 ALOGE("Unable to set air params = 0x%x\n", s_air_op.u4_error_code);
487 return C2_CORRUPTED;
488 }
489 return C2_OK;
490 }
491
setMeParams()492 c2_status_t C2SoftAvcEnc::setMeParams() {
493 IV_STATUS_T status;
494 ive_ctl_set_me_params_ip_t s_me_params_ip;
495 ive_ctl_set_me_params_op_t s_me_params_op;
496
497 s_me_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
498 s_me_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_ME_PARAMS;
499
500 s_me_params_ip.u4_enable_fast_sad = mEnableFastSad;
501 s_me_params_ip.u4_enable_alt_ref = mEnableAltRef;
502
503 s_me_params_ip.u4_enable_hpel = mHalfPelEnable;
504 s_me_params_ip.u4_enable_qpel = DEFAULT_QPEL;
505 s_me_params_ip.u4_me_speed_preset = DEFAULT_ME_SPEED;
506 s_me_params_ip.u4_srch_rng_x = DEFAULT_SRCH_RNG_X;
507 s_me_params_ip.u4_srch_rng_y = DEFAULT_SRCH_RNG_Y;
508
509 s_me_params_ip.u4_timestamp_high = -1;
510 s_me_params_ip.u4_timestamp_low = -1;
511
512 s_me_params_ip.u4_size = sizeof(ive_ctl_set_me_params_ip_t);
513 s_me_params_op.u4_size = sizeof(ive_ctl_set_me_params_op_t);
514
515 status = ive_api_function(mCodecCtx, &s_me_params_ip, &s_me_params_op);
516 if (status != IV_SUCCESS) {
517 ALOGE("Unable to set me params = 0x%x\n", s_me_params_op.u4_error_code);
518 return C2_CORRUPTED;
519 }
520 return C2_OK;
521 }
522
setGopParams()523 c2_status_t C2SoftAvcEnc::setGopParams() {
524 IV_STATUS_T status;
525 ive_ctl_set_gop_params_ip_t s_gop_params_ip;
526 ive_ctl_set_gop_params_op_t s_gop_params_op;
527
528 s_gop_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
529 s_gop_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_GOP_PARAMS;
530
531 s_gop_params_ip.u4_i_frm_interval = mIInterval;
532 s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
533
534 s_gop_params_ip.u4_timestamp_high = -1;
535 s_gop_params_ip.u4_timestamp_low = -1;
536
537 s_gop_params_ip.u4_size = sizeof(ive_ctl_set_gop_params_ip_t);
538 s_gop_params_op.u4_size = sizeof(ive_ctl_set_gop_params_op_t);
539
540 status = ive_api_function(mCodecCtx, &s_gop_params_ip, &s_gop_params_op);
541 if (status != IV_SUCCESS) {
542 ALOGE("Unable to set GOP params = 0x%x\n",
543 s_gop_params_op.u4_error_code);
544 return C2_CORRUPTED;
545 }
546 return C2_OK;
547 }
548
setProfileParams()549 c2_status_t C2SoftAvcEnc::setProfileParams() {
550 IV_STATUS_T status;
551 ive_ctl_set_profile_params_ip_t s_profile_params_ip;
552 ive_ctl_set_profile_params_op_t s_profile_params_op;
553
554 s_profile_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
555 s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
556
557 s_profile_params_ip.e_profile = DEFAULT_EPROFILE;
558 s_profile_params_ip.u4_entropy_coding_mode = mEntropyMode;
559 s_profile_params_ip.u4_timestamp_high = -1;
560 s_profile_params_ip.u4_timestamp_low = -1;
561
562 s_profile_params_ip.u4_size = sizeof(ive_ctl_set_profile_params_ip_t);
563 s_profile_params_op.u4_size = sizeof(ive_ctl_set_profile_params_op_t);
564
565 status = ive_api_function(mCodecCtx, &s_profile_params_ip, &s_profile_params_op);
566 if (status != IV_SUCCESS) {
567 ALOGE("Unable to set profile params = 0x%x\n",
568 s_profile_params_op.u4_error_code);
569 return C2_CORRUPTED;
570 }
571 return C2_OK;
572 }
573
setDeblockParams()574 c2_status_t C2SoftAvcEnc::setDeblockParams() {
575 IV_STATUS_T status;
576 ive_ctl_set_deblock_params_ip_t s_deblock_params_ip;
577 ive_ctl_set_deblock_params_op_t s_deblock_params_op;
578
579 s_deblock_params_ip.e_cmd = IVE_CMD_VIDEO_CTL;
580 s_deblock_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_DEBLOCK_PARAMS;
581
582 s_deblock_params_ip.u4_disable_deblock_level = mDisableDeblkLevel;
583
584 s_deblock_params_ip.u4_timestamp_high = -1;
585 s_deblock_params_ip.u4_timestamp_low = -1;
586
587 s_deblock_params_ip.u4_size = sizeof(ive_ctl_set_deblock_params_ip_t);
588 s_deblock_params_op.u4_size = sizeof(ive_ctl_set_deblock_params_op_t);
589
590 status = ive_api_function(mCodecCtx, &s_deblock_params_ip, &s_deblock_params_op);
591 if (status != IV_SUCCESS) {
592 ALOGE("Unable to enable/disable deblock params = 0x%x\n",
593 s_deblock_params_op.u4_error_code);
594 return C2_CORRUPTED;
595 }
596 return C2_OK;
597 }
598
logVersion()599 void C2SoftAvcEnc::logVersion() {
600 ive_ctl_getversioninfo_ip_t s_ctl_ip;
601 ive_ctl_getversioninfo_op_t s_ctl_op;
602 UWORD8 au1_buf[512];
603 IV_STATUS_T status;
604
605 s_ctl_ip.e_cmd = IVE_CMD_VIDEO_CTL;
606 s_ctl_ip.e_sub_cmd = IVE_CMD_CTL_GETVERSION;
607 s_ctl_ip.u4_size = sizeof(ive_ctl_getversioninfo_ip_t);
608 s_ctl_op.u4_size = sizeof(ive_ctl_getversioninfo_op_t);
609 s_ctl_ip.pu1_version = au1_buf;
610 s_ctl_ip.u4_version_bufsize = sizeof(au1_buf);
611
612 status = ive_api_function(mCodecCtx, (void *) &s_ctl_ip, (void *) &s_ctl_op);
613
614 if (status != IV_SUCCESS) {
615 ALOGE("Error in getting version: 0x%x", s_ctl_op.u4_error_code);
616 } else {
617 ALOGV("Ittiam encoder version: %s", (char *)s_ctl_ip.pu1_version);
618 }
619 return;
620 }
621
initEncoder()622 c2_status_t C2SoftAvcEnc::initEncoder() {
623 IV_STATUS_T status;
624 WORD32 level;
625 uint32_t displaySizeY;
626
627 CHECK(!mStarted);
628
629 c2_status_t errType = C2_OK;
630
631 uint32_t width = mIntf->getWidth();
632 uint32_t height = mIntf->getHeight();
633 displaySizeY = width * height;
634 if (displaySizeY > (1920 * 1088)) {
635 level = 50;
636 } else if (displaySizeY > (1280 * 720)) {
637 level = 40;
638 } else if (displaySizeY > (720 * 576)) {
639 level = 31;
640 } else if (displaySizeY > (624 * 320)) {
641 level = 30;
642 } else if (displaySizeY > (352 * 288)) {
643 level = 21;
644 } else if (displaySizeY > (176 * 144)) {
645 level = 20;
646 } else {
647 level = 10;
648 }
649 mAVCEncLevel = MAX(level, mAVCEncLevel);
650
651 mStride = width;
652
653 // TODO
654 mIvVideoColorFormat = IV_YUV_420P;
655
656 ALOGD("Params width %d height %d level %d colorFormat %d", width,
657 height, mAVCEncLevel, mIvVideoColorFormat);
658
659 /* Getting Number of MemRecords */
660 {
661 iv_num_mem_rec_ip_t s_num_mem_rec_ip;
662 iv_num_mem_rec_op_t s_num_mem_rec_op;
663
664 s_num_mem_rec_ip.u4_size = sizeof(iv_num_mem_rec_ip_t);
665 s_num_mem_rec_op.u4_size = sizeof(iv_num_mem_rec_op_t);
666
667 s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
668
669 status = ive_api_function(0, &s_num_mem_rec_ip, &s_num_mem_rec_op);
670
671 if (status != IV_SUCCESS) {
672 ALOGE("Get number of memory records failed = 0x%x\n",
673 s_num_mem_rec_op.u4_error_code);
674 return C2_CORRUPTED;
675 }
676
677 mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
678 }
679
680 /* Allocate array to hold memory records */
681 if (mNumMemRecords > SIZE_MAX / sizeof(iv_mem_rec_t)) {
682 ALOGE("requested memory size is too big.");
683 return C2_CORRUPTED;
684 }
685 mMemRecords = (iv_mem_rec_t *)malloc(mNumMemRecords * sizeof(iv_mem_rec_t));
686 if (NULL == mMemRecords) {
687 ALOGE("Unable to allocate memory for hold memory records: Size %zu",
688 mNumMemRecords * sizeof(iv_mem_rec_t));
689 mSignalledError = true;
690 return C2_CORRUPTED;
691 }
692
693 {
694 iv_mem_rec_t *ps_mem_rec;
695 ps_mem_rec = mMemRecords;
696 for (size_t i = 0; i < mNumMemRecords; i++) {
697 ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
698 ps_mem_rec->pv_base = NULL;
699 ps_mem_rec->u4_mem_size = 0;
700 ps_mem_rec->u4_mem_alignment = 0;
701 ps_mem_rec->e_mem_type = IV_NA_MEM_TYPE;
702
703 ps_mem_rec++;
704 }
705 }
706
707 /* Getting MemRecords Attributes */
708 {
709 iv_fill_mem_rec_ip_t s_fill_mem_rec_ip;
710 iv_fill_mem_rec_op_t s_fill_mem_rec_op;
711
712 s_fill_mem_rec_ip.u4_size = sizeof(iv_fill_mem_rec_ip_t);
713 s_fill_mem_rec_op.u4_size = sizeof(iv_fill_mem_rec_op_t);
714
715 s_fill_mem_rec_ip.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
716 s_fill_mem_rec_ip.ps_mem_rec = mMemRecords;
717 s_fill_mem_rec_ip.u4_num_mem_rec = mNumMemRecords;
718 s_fill_mem_rec_ip.u4_max_wd = width;
719 s_fill_mem_rec_ip.u4_max_ht = height;
720 s_fill_mem_rec_ip.u4_max_level = mAVCEncLevel;
721 s_fill_mem_rec_ip.e_color_format = DEFAULT_INP_COLOR_FORMAT;
722 s_fill_mem_rec_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
723 s_fill_mem_rec_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
724 s_fill_mem_rec_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
725 s_fill_mem_rec_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
726
727 status = ive_api_function(0, &s_fill_mem_rec_ip, &s_fill_mem_rec_op);
728
729 if (status != IV_SUCCESS) {
730 ALOGE("Fill memory records failed = 0x%x\n",
731 s_fill_mem_rec_op.u4_error_code);
732 return C2_CORRUPTED;
733 }
734 }
735
736 /* Allocating Memory for Mem Records */
737 {
738 WORD32 total_size;
739 iv_mem_rec_t *ps_mem_rec;
740 total_size = 0;
741 ps_mem_rec = mMemRecords;
742
743 for (size_t i = 0; i < mNumMemRecords; i++) {
744 ps_mem_rec->pv_base = ive_aligned_malloc(
745 ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
746 if (ps_mem_rec->pv_base == NULL) {
747 ALOGE("Allocation failure for mem record id %zu size %u\n", i,
748 ps_mem_rec->u4_mem_size);
749 return C2_CORRUPTED;
750
751 }
752 total_size += ps_mem_rec->u4_mem_size;
753
754 ps_mem_rec++;
755 }
756 }
757
758 /* Codec Instance Creation */
759 {
760 ive_init_ip_t s_init_ip;
761 ive_init_op_t s_init_op;
762
763 mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
764 mCodecCtx->u4_size = sizeof(iv_obj_t);
765 mCodecCtx->pv_fxns = (void *)ive_api_function;
766
767 s_init_ip.u4_size = sizeof(ive_init_ip_t);
768 s_init_op.u4_size = sizeof(ive_init_op_t);
769
770 s_init_ip.e_cmd = IV_CMD_INIT;
771 s_init_ip.u4_num_mem_rec = mNumMemRecords;
772 s_init_ip.ps_mem_rec = mMemRecords;
773 s_init_ip.u4_max_wd = width;
774 s_init_ip.u4_max_ht = height;
775 s_init_ip.u4_max_ref_cnt = DEFAULT_MAX_REF_FRM;
776 s_init_ip.u4_max_reorder_cnt = DEFAULT_MAX_REORDER_FRM;
777 s_init_ip.u4_max_level = mAVCEncLevel;
778 s_init_ip.e_inp_color_fmt = mIvVideoColorFormat;
779
780 if (mReconEnable || mPSNREnable) {
781 s_init_ip.u4_enable_recon = 1;
782 } else {
783 s_init_ip.u4_enable_recon = 0;
784 }
785 s_init_ip.e_recon_color_fmt = DEFAULT_RECON_COLOR_FORMAT;
786 s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
787 s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
788 s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
789 s_init_ip.u4_num_bframes = mBframes;
790 s_init_ip.e_content_type = IV_PROGRESSIVE;
791 s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
792 s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
793 s_init_ip.e_slice_mode = mSliceMode;
794 s_init_ip.u4_slice_param = mSliceParam;
795 s_init_ip.e_arch = mArch;
796 s_init_ip.e_soc = DEFAULT_SOC;
797
798 status = ive_api_function(mCodecCtx, &s_init_ip, &s_init_op);
799
800 if (status != IV_SUCCESS) {
801 ALOGE("Init encoder failed = 0x%x\n", s_init_op.u4_error_code);
802 return C2_CORRUPTED;
803 }
804 }
805
806 /* Get Codec Version */
807 logVersion();
808
809 /* set processor details */
810 setNumCores();
811
812 /* Video control Set Frame dimensions */
813 setDimensions();
814
815 /* Video control Set Frame rates */
816 setFrameRate();
817
818 /* Video control Set IPE Params */
819 setIpeParams();
820
821 /* Video control Set Bitrate */
822 setBitRate();
823
824 /* Video control Set QP */
825 setQp();
826
827 /* Video control Set AIR params */
828 setAirParams();
829
830 /* Video control Set VBV params */
831 setVbvParams();
832
833 /* Video control Set Motion estimation params */
834 setMeParams();
835
836 /* Video control Set GOP params */
837 setGopParams();
838
839 /* Video control Set Deblock params */
840 setDeblockParams();
841
842 /* Video control Set Profile params */
843 setProfileParams();
844
845 /* Video control Set in Encode header mode */
846 setEncMode(IVE_ENC_MODE_HEADER);
847
848 ALOGV("init_codec successfull");
849
850 mSpsPpsHeaderReceived = false;
851 mStarted = true;
852
853 return C2_OK;
854 }
855
releaseEncoder()856 c2_status_t C2SoftAvcEnc::releaseEncoder() {
857 IV_STATUS_T status = IV_SUCCESS;
858 iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
859 iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
860 iv_mem_rec_t *ps_mem_rec;
861
862 if (!mStarted) {
863 return C2_OK;
864 }
865
866 s_retrieve_mem_ip.u4_size = sizeof(iv_retrieve_mem_rec_ip_t);
867 s_retrieve_mem_op.u4_size = sizeof(iv_retrieve_mem_rec_op_t);
868 s_retrieve_mem_ip.e_cmd = IV_CMD_RETRIEVE_MEMREC;
869 s_retrieve_mem_ip.ps_mem_rec = mMemRecords;
870
871 status = ive_api_function(mCodecCtx, &s_retrieve_mem_ip, &s_retrieve_mem_op);
872
873 if (status != IV_SUCCESS) {
874 ALOGE("Unable to retrieve memory records = 0x%x\n",
875 s_retrieve_mem_op.u4_error_code);
876 return C2_CORRUPTED;
877 }
878
879 /* Free memory records */
880 ps_mem_rec = mMemRecords;
881 for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
882 ive_aligned_free(ps_mem_rec->pv_base);
883 ps_mem_rec++;
884 }
885
886 free(mMemRecords);
887
888 // clear other pointers into the space being free()d
889 mCodecCtx = NULL;
890
891 mStarted = false;
892
893 return C2_OK;
894 }
895
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 timestamp)896 c2_status_t C2SoftAvcEnc::setEncodeArgs(
897 ive_video_encode_ip_t *ps_encode_ip,
898 ive_video_encode_op_t *ps_encode_op,
899 const C2GraphicView *const input,
900 uint8_t *base,
901 uint32_t capacity,
902 uint64_t timestamp) {
903 iv_raw_buf_t *ps_inp_raw_buf;
904
905 ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
906 ps_encode_ip->s_out_buf.pv_buf = base;
907 ps_encode_ip->s_out_buf.u4_bytes = 0;
908 ps_encode_ip->s_out_buf.u4_bufsize = capacity;
909 ps_encode_ip->u4_size = sizeof(ive_video_encode_ip_t);
910 ps_encode_op->u4_size = sizeof(ive_video_encode_op_t);
911
912 ps_encode_ip->e_cmd = IVE_CMD_VIDEO_ENCODE;
913 ps_encode_ip->pv_bufs = NULL;
914 ps_encode_ip->pv_mb_info = NULL;
915 ps_encode_ip->pv_pic_info = NULL;
916 ps_encode_ip->u4_mb_info_type = 0;
917 ps_encode_ip->u4_pic_info_type = 0;
918 ps_encode_ip->u4_is_last = 0;
919 ps_encode_ip->u4_timestamp_high = timestamp >> 32;
920 ps_encode_ip->u4_timestamp_low = timestamp & 0xFFFFFFFF;
921 ps_encode_op->s_out_buf.pv_buf = NULL;
922
923 /* Initialize color formats */
924 memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
925 ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
926 ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
927 if (input == nullptr) {
928 if (mSawInputEOS){
929 ps_encode_ip->u4_is_last = 1;
930 }
931 return C2_OK;
932 }
933
934 ALOGV("width = %d, height = %d", input->width(), input->height());
935 const C2PlanarLayout &layout = input->layout();
936 uint8_t *yPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_Y]);
937 uint8_t *uPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_U]);
938 uint8_t *vPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_V]);
939 int32_t yStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
940 int32_t uStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
941 int32_t vStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
942
943 uint32_t width = mIntf->getWidth();
944 uint32_t height = mIntf->getHeight();
945 // width and height are always even (as block size is 16x16)
946 CHECK_EQ((width & 1u), 0u);
947 CHECK_EQ((height & 1u), 0u);
948 size_t yPlaneSize = width * height;
949
950 switch (layout.type) {
951 case C2PlanarLayout::TYPE_RGB:
952 // fall-through
953 case C2PlanarLayout::TYPE_RGBA: {
954 ALOGV("yPlaneSize = %zu", yPlaneSize);
955 MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
956 mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
957 yPlane = conversionBuffer.data();
958 uPlane = yPlane + yPlaneSize;
959 vPlane = uPlane + yPlaneSize / 4;
960 yStride = width;
961 uStride = vStride = yStride / 2;
962 ConvertRGBToPlanarYUV(yPlane, yStride, height, conversionBuffer.size(), *input);
963 break;
964 }
965 case C2PlanarLayout::TYPE_YUV: {
966 if (!IsYUV420(*input)) {
967 ALOGE("input is not YUV420");
968 return C2_BAD_VALUE;
969 }
970
971 if (layout.planes[layout.PLANE_Y].colInc == 1
972 && layout.planes[layout.PLANE_U].colInc == 1
973 && layout.planes[layout.PLANE_V].colInc == 1) {
974 // I420 compatible - already set up above
975 break;
976 }
977
978 // copy to I420
979 yStride = width;
980 uStride = vStride = yStride / 2;
981 MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
982 mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
983 MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, yStride, height);
984 status_t err = ImageCopy(conversionBuffer.data(), &img, *input);
985 if (err != OK) {
986 ALOGE("Buffer conversion failed: %d", err);
987 return C2_BAD_VALUE;
988 }
989 yPlane = conversionBuffer.data();
990 uPlane = yPlane + yPlaneSize;
991 vPlane = uPlane + yPlaneSize / 4;
992 break;
993
994 }
995
996 case C2PlanarLayout::TYPE_YUVA:
997 ALOGE("YUVA plane type is not supported");
998 return C2_BAD_VALUE;
999
1000 default:
1001 ALOGE("Unrecognized plane type: %d", layout.type);
1002 return C2_BAD_VALUE;
1003 }
1004
1005 switch (mIvVideoColorFormat) {
1006 case IV_YUV_420P:
1007 {
1008 // input buffer is supposed to be const but Ittiam API wants bare pointer.
1009 ps_inp_raw_buf->apv_bufs[0] = yPlane;
1010 ps_inp_raw_buf->apv_bufs[1] = uPlane;
1011 ps_inp_raw_buf->apv_bufs[2] = vPlane;
1012
1013 ps_inp_raw_buf->au4_wd[0] = input->width();
1014 ps_inp_raw_buf->au4_wd[1] = input->width() / 2;
1015 ps_inp_raw_buf->au4_wd[2] = input->width() / 2;
1016
1017 ps_inp_raw_buf->au4_ht[0] = input->height();
1018 ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
1019 ps_inp_raw_buf->au4_ht[2] = input->height() / 2;
1020
1021 ps_inp_raw_buf->au4_strd[0] = yStride;
1022 ps_inp_raw_buf->au4_strd[1] = uStride;
1023 ps_inp_raw_buf->au4_strd[2] = vStride;
1024 break;
1025 }
1026
1027 case IV_YUV_422ILE:
1028 {
1029 // TODO
1030 // ps_inp_raw_buf->apv_bufs[0] = pu1_buf;
1031 // ps_inp_raw_buf->au4_wd[0] = mWidth * 2;
1032 // ps_inp_raw_buf->au4_ht[0] = mHeight;
1033 // ps_inp_raw_buf->au4_strd[0] = mStride * 2;
1034 break;
1035 }
1036
1037 case IV_YUV_420SP_UV:
1038 case IV_YUV_420SP_VU:
1039 default:
1040 {
1041 ps_inp_raw_buf->apv_bufs[0] = yPlane;
1042 ps_inp_raw_buf->apv_bufs[1] = uPlane;
1043
1044 ps_inp_raw_buf->au4_wd[0] = input->width();
1045 ps_inp_raw_buf->au4_wd[1] = input->width();
1046
1047 ps_inp_raw_buf->au4_ht[0] = input->height();
1048 ps_inp_raw_buf->au4_ht[1] = input->height() / 2;
1049
1050 ps_inp_raw_buf->au4_strd[0] = yStride;
1051 ps_inp_raw_buf->au4_strd[1] = uStride;
1052 break;
1053 }
1054 }
1055 return C2_OK;
1056 }
1057
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)1058 void C2SoftAvcEnc::process(
1059 const std::unique_ptr<C2Work> &work,
1060 const std::shared_ptr<C2BlockPool> &pool) {
1061 work->result = C2_OK;
1062 work->workletsProcessed = 0u;
1063
1064 IV_STATUS_T status;
1065 WORD32 timeDelay, timeTaken;
1066 uint64_t timestamp = work->input.ordinal.timestamp.peekull();
1067
1068 // Initialize encoder if not already initialized
1069 if (mCodecCtx == NULL) {
1070 if (C2_OK != initEncoder()) {
1071 ALOGE("Failed to initialize encoder");
1072 work->workletsProcessed = 1u;
1073 work->result = C2_CORRUPTED;
1074 return;
1075 }
1076 }
1077 if (mSignalledError) {
1078 return;
1079 }
1080
1081 // while (!mSawOutputEOS && !outQueue.empty()) {
1082 c2_status_t error;
1083 ive_video_encode_ip_t s_encode_ip;
1084 ive_video_encode_op_t s_encode_op;
1085
1086 if (!mSpsPpsHeaderReceived) {
1087 constexpr uint32_t kHeaderLength = MIN_STREAM_SIZE;
1088 uint8_t header[kHeaderLength];
1089 error = setEncodeArgs(
1090 &s_encode_ip, &s_encode_op, NULL, header, kHeaderLength, timestamp);
1091 if (error != C2_OK) {
1092 ALOGE("setEncodeArgs failed: %d", error);
1093 mSignalledError = true;
1094 work->workletsProcessed = 1u;
1095 work->result = C2_CORRUPTED;
1096 return;
1097 }
1098 status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1099
1100 if (IV_SUCCESS != status) {
1101 ALOGE("Encode header failed = 0x%x\n",
1102 s_encode_op.u4_error_code);
1103 return;
1104 } else {
1105 ALOGV("Bytes Generated in header %d\n",
1106 s_encode_op.s_out_buf.u4_bytes);
1107 }
1108
1109 mSpsPpsHeaderReceived = true;
1110
1111 std::unique_ptr<C2StreamCsdInfo::output> csd =
1112 C2StreamCsdInfo::output::AllocUnique(s_encode_op.s_out_buf.u4_bytes, 0u);
1113 memcpy(csd->m.value, header, s_encode_op.s_out_buf.u4_bytes);
1114 work->worklets.front()->output.configUpdate.push_back(std::move(csd));
1115
1116 DUMP_TO_FILE(
1117 mOutFile, csd->m.value, csd->flexCount());
1118 }
1119
1120 if (mUpdateFlag) {
1121 if (mUpdateFlag & kUpdateBitrate) {
1122 setBitRate();
1123 }
1124 if (mUpdateFlag & kRequestKeyFrame) {
1125 setFrameType(IV_IDR_FRAME);
1126 }
1127 if (mUpdateFlag & kUpdateAIRMode) {
1128 setAirParams();
1129 // notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
1130 // OMX_IndexConfigAndroidIntraRefresh, NULL);
1131 }
1132 mUpdateFlag = 0;
1133 }
1134
1135 if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
1136 mSawInputEOS = true;
1137 }
1138
1139 /* In normal mode, store inputBufferInfo and this will be returned
1140 when encoder consumes this input */
1141 // if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
1142 // for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
1143 // if (NULL == mInputBufferInfo[i]) {
1144 // mInputBufferInfo[i] = inputBufferInfo;
1145 // break;
1146 // }
1147 // }
1148 // }
1149 std::shared_ptr<const C2GraphicView> view;
1150 std::shared_ptr<C2Buffer> inputBuffer;
1151 if (!work->input.buffers.empty()) {
1152 inputBuffer = work->input.buffers[0];
1153 view = std::make_shared<const C2GraphicView>(
1154 inputBuffer->data().graphicBlocks().front().map().get());
1155 if (view->error() != C2_OK) {
1156 ALOGE("graphic view map err = %d", view->error());
1157 return;
1158 }
1159 }
1160
1161 std::shared_ptr<C2LinearBlock> block;
1162
1163 do {
1164 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1165 // TODO: error handling, proper usage, etc.
1166 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
1167 if (err != C2_OK) {
1168 ALOGE("fetch linear block err = %d", err);
1169 work->workletsProcessed = 1u;
1170 work->result = err;
1171 return;
1172 }
1173 C2WriteView wView = block->map().get();
1174 if (wView.error() != C2_OK) {
1175 ALOGE("write view map err = %d", wView.error());
1176 work->workletsProcessed = 1u;
1177 work->result = wView.error();
1178 return;
1179 }
1180
1181 error = setEncodeArgs(
1182 &s_encode_ip, &s_encode_op, view.get(), wView.base(), wView.capacity(), timestamp);
1183 if (error != C2_OK) {
1184 mSignalledError = true;
1185 ALOGE("setEncodeArgs failed : %d", error);
1186 work->workletsProcessed = 1u;
1187 work->result = error;
1188 return;
1189 }
1190
1191 // DUMP_TO_FILE(
1192 // mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
1193 // (mHeight * mStride * 3 / 2));
1194
1195 GETTIME(&mTimeStart, NULL);
1196 /* Compute time elapsed between end of previous decode()
1197 * to start of current decode() */
1198 TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
1199 status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
1200
1201 if (IV_SUCCESS != status) {
1202 if ((s_encode_op.u4_error_code & 0xFF) == IH264E_BITSTREAM_BUFFER_OVERFLOW) {
1203 // TODO: use IVE_CMD_CTL_GETBUFINFO for proper max input size?
1204 mOutBufferSize *= 2;
1205 continue;
1206 }
1207 ALOGE("Encode Frame failed = 0x%x\n",
1208 s_encode_op.u4_error_code);
1209 mSignalledError = true;
1210 work->workletsProcessed = 1u;
1211 work->result = C2_CORRUPTED;
1212 return;
1213 }
1214 } while (IV_SUCCESS != status);
1215
1216 // Hold input buffer reference
1217 if (inputBuffer) {
1218 mBuffers[s_encode_ip.s_inp_buf.apv_bufs[0]] = inputBuffer;
1219 }
1220
1221 GETTIME(&mTimeEnd, NULL);
1222 /* Compute time taken for decode() */
1223 TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
1224
1225 ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
1226 s_encode_op.s_out_buf.u4_bytes);
1227
1228 void *freed = s_encode_op.s_inp_buf.apv_bufs[0];
1229 /* If encoder frees up an input buffer, mark it as free */
1230 if (freed != NULL) {
1231 if (mBuffers.count(freed) == 0u) {
1232 ALOGD("buffer not tracked");
1233 } else {
1234 // Release input buffer reference
1235 mBuffers.erase(freed);
1236 mConversionBuffersInUse.erase(freed);
1237 }
1238 }
1239
1240 work->worklets.front()->output.flags = work->input.flags;
1241 work->worklets.front()->output.ordinal = work->input.ordinal;
1242 work->worklets.front()->output.ordinal.timestamp =
1243 ((uint64_t)s_encode_op.u4_timestamp_high << 32) | s_encode_op.u4_timestamp_low;
1244 work->worklets.front()->output.buffers.clear();
1245 std::shared_ptr<C2Buffer> buffer =
1246 createLinearBuffer(block, 0, s_encode_op.s_out_buf.u4_bytes);
1247 work->worklets.front()->output.buffers.push_back(buffer);
1248 work->workletsProcessed = 1u;
1249
1250 if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
1251 buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
1252 0u /* stream id */, C2PictureTypeKeyFrame));
1253 }
1254
1255 if (s_encode_op.u4_is_last) {
1256 // outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
1257 mSawOutputEOS = true;
1258 } else {
1259 // outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
1260 }
1261 }
1262
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)1263 c2_status_t C2SoftAvcEnc::drain(
1264 uint32_t drainMode,
1265 const std::shared_ptr<C2BlockPool> &pool) {
1266 // TODO: use IVE_CMD_CTL_FLUSH?
1267 (void)drainMode;
1268 (void)pool;
1269 return C2_OK;
1270 }
1271
1272
1273 class C2SoftAvcEncFactory : public C2ComponentFactory {
1274 public:
C2SoftAvcEncFactory()1275 C2SoftAvcEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
1276 GetCodec2PlatformComponentStore()->getParamReflector())) {
1277 }
1278
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)1279 virtual c2_status_t createComponent(
1280 c2_node_id_t id,
1281 std::shared_ptr<C2Component>* const component,
1282 std::function<void(C2Component*)> deleter) override {
1283 *component = std::shared_ptr<C2Component>(
1284 new C2SoftAvcEnc(COMPONENT_NAME,
1285 id,
1286 std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)),
1287 deleter);
1288 return C2_OK;
1289 }
1290
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)1291 virtual c2_status_t createInterface(
1292 c2_node_id_t id,
1293 std::shared_ptr<C2ComponentInterface>* const interface,
1294 std::function<void(C2ComponentInterface*)> deleter) override {
1295 *interface = std::shared_ptr<C2ComponentInterface>(
1296 new SimpleInterface<C2SoftAvcEnc::IntfImpl>(
1297 COMPONENT_NAME, id, std::make_shared<C2SoftAvcEnc::IntfImpl>(mHelper)),
1298 deleter);
1299 return C2_OK;
1300 }
1301
1302 virtual ~C2SoftAvcEncFactory() override = default;
1303
1304 private:
1305 std::shared_ptr<C2ReflectorHelper> mHelper;
1306 };
1307
1308 } // namespace android
1309
CreateCodec2Factory()1310 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
1311 ALOGV("in %s", __func__);
1312 return new ::android::C2SoftAvcEncFactory();
1313 }
1314
DestroyCodec2Factory(::C2ComponentFactory * factory)1315 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
1316 ALOGV("in %s", __func__);
1317 delete factory;
1318 }
1319