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