1 /*
2 * Copyright 2017 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 "C2SoftAvcDec"
19 #include <log/log.h>
20
21 #include <media/stagefright/foundation/MediaDefs.h>
22
23 #include <C2Debug.h>
24 #include <C2PlatformSupport.h>
25 #include <Codec2Mapper.h>
26 #include <SimpleC2Interface.h>
27
28 #include "C2SoftAvcDec.h"
29 #include "ih264d.h"
30
31 namespace android {
32
33 namespace {
34
35 constexpr char COMPONENT_NAME[] = "c2.android.avc.decoder";
36
37 } // namespace
38
39 class C2SoftAvcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
40 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)41 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
42 : SimpleInterface<void>::BaseParams(
43 helper,
44 COMPONENT_NAME,
45 C2Component::KIND_DECODER,
46 C2Component::DOMAIN_VIDEO,
47 MEDIA_MIMETYPE_VIDEO_AVC) {
48 noPrivateBuffers(); // TODO: account for our buffers here
49 noInputReferences();
50 noOutputReferences();
51 noInputLatency();
52 noTimeStretch();
53
54 // TODO: Proper support for reorder depth.
55 addParameter(
56 DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
57 .withConstValue(new C2PortActualDelayTuning::output(8u))
58 .build());
59
60 // TODO: output latency and reordering
61
62 addParameter(
63 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
64 .withConstValue(new C2ComponentAttributesSetting(C2Component::ATTRIB_IS_TEMPORAL))
65 .build());
66
67 // coded and output picture size is the same for this codec
68 addParameter(
69 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
70 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
71 .withFields({
72 C2F(mSize, width).inRange(2, 4080, 2),
73 C2F(mSize, height).inRange(2, 4080, 2),
74 })
75 .withSetter(SizeSetter)
76 .build());
77
78 addParameter(
79 DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
80 .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
81 .withFields({
82 C2F(mSize, width).inRange(2, 4080, 2),
83 C2F(mSize, height).inRange(2, 4080, 2),
84 })
85 .withSetter(MaxPictureSizeSetter, mSize)
86 .build());
87
88 addParameter(
89 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
90 .withDefault(new C2StreamProfileLevelInfo::input(0u,
91 C2Config::PROFILE_AVC_CONSTRAINED_BASELINE, C2Config::LEVEL_AVC_5_2))
92 .withFields({
93 C2F(mProfileLevel, profile).oneOf({
94 C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
95 C2Config::PROFILE_AVC_BASELINE,
96 C2Config::PROFILE_AVC_MAIN,
97 C2Config::PROFILE_AVC_CONSTRAINED_HIGH,
98 C2Config::PROFILE_AVC_PROGRESSIVE_HIGH,
99 C2Config::PROFILE_AVC_HIGH}),
100 C2F(mProfileLevel, level).oneOf({
101 C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B, C2Config::LEVEL_AVC_1_1,
102 C2Config::LEVEL_AVC_1_2, C2Config::LEVEL_AVC_1_3,
103 C2Config::LEVEL_AVC_2, C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2,
104 C2Config::LEVEL_AVC_3, C2Config::LEVEL_AVC_3_1, C2Config::LEVEL_AVC_3_2,
105 C2Config::LEVEL_AVC_4, C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2,
106 C2Config::LEVEL_AVC_5, C2Config::LEVEL_AVC_5_1, C2Config::LEVEL_AVC_5_2
107 })
108 })
109 .withSetter(ProfileLevelSetter, mSize)
110 .build());
111
112 addParameter(
113 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
114 .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
115 .withFields({
116 C2F(mMaxInputSize, value).any(),
117 })
118 .calculatedAs(MaxInputSizeSetter, mMaxSize)
119 .build());
120
121 C2ChromaOffsetStruct locations[1] = { C2ChromaOffsetStruct::ITU_YUV_420_0() };
122 std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
123 C2StreamColorInfo::output::AllocShared(
124 1u, 0u, 8u /* bitDepth */, C2Color::YUV_420);
125 memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
126
127 defaultColorInfo =
128 C2StreamColorInfo::output::AllocShared(
129 { C2ChromaOffsetStruct::ITU_YUV_420_0() },
130 0u, 8u /* bitDepth */, C2Color::YUV_420);
131 helper->addStructDescriptors<C2ChromaOffsetStruct>();
132
133 addParameter(
134 DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
135 .withConstValue(defaultColorInfo)
136 .build());
137
138 addParameter(
139 DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
140 .withDefault(new C2StreamColorAspectsTuning::output(
141 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
142 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
143 .withFields({
144 C2F(mDefaultColorAspects, range).inRange(
145 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
146 C2F(mDefaultColorAspects, primaries).inRange(
147 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
148 C2F(mDefaultColorAspects, transfer).inRange(
149 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
150 C2F(mDefaultColorAspects, matrix).inRange(
151 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
152 })
153 .withSetter(DefaultColorAspectsSetter)
154 .build());
155
156 addParameter(
157 DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
158 .withDefault(new C2StreamColorAspectsInfo::input(
159 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
160 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
161 .withFields({
162 C2F(mCodedColorAspects, range).inRange(
163 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
164 C2F(mCodedColorAspects, primaries).inRange(
165 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
166 C2F(mCodedColorAspects, transfer).inRange(
167 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
168 C2F(mCodedColorAspects, matrix).inRange(
169 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
170 })
171 .withSetter(CodedColorAspectsSetter)
172 .build());
173
174 addParameter(
175 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
176 .withDefault(new C2StreamColorAspectsInfo::output(
177 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
178 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
179 .withFields({
180 C2F(mColorAspects, range).inRange(
181 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
182 C2F(mColorAspects, primaries).inRange(
183 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
184 C2F(mColorAspects, transfer).inRange(
185 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
186 C2F(mColorAspects, matrix).inRange(
187 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
188 })
189 .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
190 .build());
191
192 // TODO: support more formats?
193 addParameter(
194 DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
195 .withConstValue(new C2StreamPixelFormatInfo::output(
196 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
197 .build());
198 }
199
SizeSetter(bool mayBlock,const C2P<C2StreamPictureSizeInfo::output> & oldMe,C2P<C2StreamPictureSizeInfo::output> & me)200 static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe,
201 C2P<C2StreamPictureSizeInfo::output> &me) {
202 (void)mayBlock;
203 C2R res = C2R::Ok();
204 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
205 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
206 me.set().width = oldMe.v.width;
207 }
208 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
209 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
210 me.set().height = oldMe.v.height;
211 }
212 return res;
213 }
214
MaxPictureSizeSetter(bool mayBlock,C2P<C2StreamMaxPictureSizeTuning::output> & me,const C2P<C2StreamPictureSizeInfo::output> & size)215 static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me,
216 const C2P<C2StreamPictureSizeInfo::output> &size) {
217 (void)mayBlock;
218 // TODO: get max width/height from the size's field helpers vs. hardcoding
219 me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4080u);
220 me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4080u);
221 return C2R::Ok();
222 }
223
MaxInputSizeSetter(bool mayBlock,C2P<C2StreamMaxBufferSizeInfo::input> & me,const C2P<C2StreamMaxPictureSizeTuning::output> & maxSize)224 static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
225 const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
226 (void)mayBlock;
227 // assume compression ratio of 2
228 me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 192);
229 return C2R::Ok();
230 }
231
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::input> & me,const C2P<C2StreamPictureSizeInfo::output> & size)232 static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
233 const C2P<C2StreamPictureSizeInfo::output> &size) {
234 (void)mayBlock;
235 (void)size;
236 (void)me; // TODO: validate
237 return C2R::Ok();
238 }
239
DefaultColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsTuning::output> & me)240 static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
241 (void)mayBlock;
242 if (me.v.range > C2Color::RANGE_OTHER) {
243 me.set().range = C2Color::RANGE_OTHER;
244 }
245 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
246 me.set().primaries = C2Color::PRIMARIES_OTHER;
247 }
248 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
249 me.set().transfer = C2Color::TRANSFER_OTHER;
250 }
251 if (me.v.matrix > C2Color::MATRIX_OTHER) {
252 me.set().matrix = C2Color::MATRIX_OTHER;
253 }
254 return C2R::Ok();
255 }
256
CodedColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::input> & me)257 static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
258 (void)mayBlock;
259 if (me.v.range > C2Color::RANGE_OTHER) {
260 me.set().range = C2Color::RANGE_OTHER;
261 }
262 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
263 me.set().primaries = C2Color::PRIMARIES_OTHER;
264 }
265 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
266 me.set().transfer = C2Color::TRANSFER_OTHER;
267 }
268 if (me.v.matrix > C2Color::MATRIX_OTHER) {
269 me.set().matrix = C2Color::MATRIX_OTHER;
270 }
271 return C2R::Ok();
272 }
273
ColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::output> & me,const C2P<C2StreamColorAspectsTuning::output> & def,const C2P<C2StreamColorAspectsInfo::input> & coded)274 static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
275 const C2P<C2StreamColorAspectsTuning::output> &def,
276 const C2P<C2StreamColorAspectsInfo::input> &coded) {
277 (void)mayBlock;
278 // take default values for all unspecified fields, and coded values for specified ones
279 me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
280 me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
281 ? def.v.primaries : coded.v.primaries;
282 me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
283 ? def.v.transfer : coded.v.transfer;
284 me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
285 return C2R::Ok();
286 }
287
getColorAspects_l()288 std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
289 return mColorAspects;
290 }
291
292 private:
293 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
294 std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
295 std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
296 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
297 std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
298 std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
299 std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
300 std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
301 std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
302 };
303
getCpuCoreCount()304 static size_t getCpuCoreCount() {
305 long cpuCoreCount = 1;
306 #if defined(_SC_NPROCESSORS_ONLN)
307 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
308 #else
309 // _SC_NPROC_ONLN must be defined...
310 cpuCoreCount = sysconf(_SC_NPROC_ONLN);
311 #endif
312 CHECK(cpuCoreCount >= 1);
313 ALOGV("Number of CPU cores: %ld", cpuCoreCount);
314 return (size_t)cpuCoreCount;
315 }
316
ivd_aligned_malloc(void * ctxt,WORD32 alignment,WORD32 size)317 static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
318 (void) ctxt;
319 return memalign(alignment, size);
320 }
321
ivd_aligned_free(void * ctxt,void * mem)322 static void ivd_aligned_free(void *ctxt, void *mem) {
323 (void) ctxt;
324 free(mem);
325 }
326
C2SoftAvcDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)327 C2SoftAvcDec::C2SoftAvcDec(
328 const char *name,
329 c2_node_id_t id,
330 const std::shared_ptr<IntfImpl> &intfImpl)
331 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
332 mIntf(intfImpl),
333 mDecHandle(nullptr),
334 mOutBufferFlush(nullptr),
335 mIvColorFormat(IV_YUV_420P),
336 mWidth(320),
337 mHeight(240),
338 mHeaderDecoded(false),
339 mOutIndex(0u) {
340 GENERATE_FILE_NAMES();
341 CREATE_DUMP_FILE(mInFile);
342 }
343
~C2SoftAvcDec()344 C2SoftAvcDec::~C2SoftAvcDec() {
345 onRelease();
346 }
347
onInit()348 c2_status_t C2SoftAvcDec::onInit() {
349 status_t err = initDecoder();
350 return err == OK ? C2_OK : C2_CORRUPTED;
351 }
352
onStop()353 c2_status_t C2SoftAvcDec::onStop() {
354 if (OK != resetDecoder()) return C2_CORRUPTED;
355 resetPlugin();
356 return C2_OK;
357 }
358
onReset()359 void C2SoftAvcDec::onReset() {
360 (void) onStop();
361 }
362
onRelease()363 void C2SoftAvcDec::onRelease() {
364 (void) deleteDecoder();
365 if (mOutBufferFlush) {
366 ivd_aligned_free(nullptr, mOutBufferFlush);
367 mOutBufferFlush = nullptr;
368 }
369 if (mOutBlock) {
370 mOutBlock.reset();
371 }
372 }
373
onFlush_sm()374 c2_status_t C2SoftAvcDec::onFlush_sm() {
375 if (OK != setFlushMode()) return C2_CORRUPTED;
376
377 uint32_t bufferSize = mStride * mHeight * 3 / 2;
378 mOutBufferFlush = (uint8_t *)ivd_aligned_malloc(nullptr, 128, bufferSize);
379 if (!mOutBufferFlush) {
380 ALOGE("could not allocate tmp output buffer (for flush) of size %u ", bufferSize);
381 return C2_NO_MEMORY;
382 }
383
384 while (true) {
385 ivd_video_decode_ip_t s_decode_ip;
386 ivd_video_decode_op_t s_decode_op;
387
388 setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, nullptr, 0, 0, 0);
389 (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
390 if (0 == s_decode_op.u4_output_present) {
391 resetPlugin();
392 break;
393 }
394 }
395
396 if (mOutBufferFlush) {
397 ivd_aligned_free(nullptr, mOutBufferFlush);
398 mOutBufferFlush = nullptr;
399 }
400
401 return C2_OK;
402 }
403
createDecoder()404 status_t C2SoftAvcDec::createDecoder() {
405 ivdext_create_ip_t s_create_ip;
406 ivdext_create_op_t s_create_op;
407
408 s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
409 s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
410 s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
411 s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat;
412 s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
413 s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
414 s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = nullptr;
415 s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
416 IV_API_CALL_STATUS_T status = ivdec_api_function(nullptr,
417 &s_create_ip,
418 &s_create_op);
419 if (status != IV_SUCCESS) {
420 ALOGE("error in %s: 0x%x", __func__,
421 s_create_op.s_ivd_create_op_t.u4_error_code);
422 return UNKNOWN_ERROR;
423 }
424 mDecHandle = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
425 mDecHandle->pv_fxns = (void *)ivdec_api_function;
426 mDecHandle->u4_size = sizeof(iv_obj_t);
427
428 return OK;
429 }
430
setNumCores()431 status_t C2SoftAvcDec::setNumCores() {
432 ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip;
433 ivdext_ctl_set_num_cores_op_t s_set_num_cores_op;
434
435 s_set_num_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
436 s_set_num_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
437 s_set_num_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES;
438 s_set_num_cores_ip.u4_num_cores = mNumCores;
439 s_set_num_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t);
440 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
441 &s_set_num_cores_ip,
442 &s_set_num_cores_op);
443 if (IV_SUCCESS != status) {
444 ALOGD("error in %s: 0x%x", __func__, s_set_num_cores_op.u4_error_code);
445 return UNKNOWN_ERROR;
446 }
447
448 return OK;
449 }
450
setParams(size_t stride,IVD_VIDEO_DECODE_MODE_T dec_mode)451 status_t C2SoftAvcDec::setParams(size_t stride, IVD_VIDEO_DECODE_MODE_T dec_mode) {
452 ivd_ctl_set_config_ip_t s_set_dyn_params_ip;
453 ivd_ctl_set_config_op_t s_set_dyn_params_op;
454
455 s_set_dyn_params_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
456 s_set_dyn_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
457 s_set_dyn_params_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
458 s_set_dyn_params_ip.u4_disp_wd = (UWORD32) stride;
459 s_set_dyn_params_ip.e_frm_skip_mode = IVD_SKIP_NONE;
460 s_set_dyn_params_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
461 s_set_dyn_params_ip.e_vid_dec_mode = dec_mode;
462 s_set_dyn_params_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
463 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
464 &s_set_dyn_params_ip,
465 &s_set_dyn_params_op);
466 if (status != IV_SUCCESS) {
467 ALOGE("error in %s: 0x%x", __func__, s_set_dyn_params_op.u4_error_code);
468 return UNKNOWN_ERROR;
469 }
470
471 return OK;
472 }
473
getVersion()474 void C2SoftAvcDec::getVersion() {
475 ivd_ctl_getversioninfo_ip_t s_get_versioninfo_ip;
476 ivd_ctl_getversioninfo_op_t s_get_versioninfo_op;
477 UWORD8 au1_buf[512];
478
479 s_get_versioninfo_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t);
480 s_get_versioninfo_ip.e_cmd = IVD_CMD_VIDEO_CTL;
481 s_get_versioninfo_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION;
482 s_get_versioninfo_ip.pv_version_buffer = au1_buf;
483 s_get_versioninfo_ip.u4_version_buffer_size = sizeof(au1_buf);
484 s_get_versioninfo_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t);
485 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
486 &s_get_versioninfo_ip,
487 &s_get_versioninfo_op);
488 if (status != IV_SUCCESS) {
489 ALOGD("error in %s: 0x%x", __func__,
490 s_get_versioninfo_op.u4_error_code);
491 } else {
492 ALOGV("ittiam decoder version number: %s",
493 (char *) s_get_versioninfo_ip.pv_version_buffer);
494 }
495 }
496
initDecoder()497 status_t C2SoftAvcDec::initDecoder() {
498 if (OK != createDecoder()) return UNKNOWN_ERROR;
499 mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
500 mStride = ALIGN64(mWidth);
501 mSignalledError = false;
502 resetPlugin();
503 (void) setNumCores();
504 if (OK != setParams(mStride, IVD_DECODE_FRAME)) return UNKNOWN_ERROR;
505 (void) getVersion();
506
507 return OK;
508 }
509
setDecodeArgs(ivd_video_decode_ip_t * ps_decode_ip,ivd_video_decode_op_t * ps_decode_op,C2ReadView * inBuffer,C2GraphicView * outBuffer,size_t inOffset,size_t inSize,uint32_t tsMarker)510 bool C2SoftAvcDec::setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
511 ivd_video_decode_op_t *ps_decode_op,
512 C2ReadView *inBuffer,
513 C2GraphicView *outBuffer,
514 size_t inOffset,
515 size_t inSize,
516 uint32_t tsMarker) {
517 uint32_t displayStride = mStride;
518 uint32_t displayHeight = mHeight;
519 size_t lumaSize = displayStride * displayHeight;
520 size_t chromaSize = lumaSize >> 2;
521
522 ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
523 ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
524 if (inBuffer) {
525 ps_decode_ip->u4_ts = tsMarker;
526 ps_decode_ip->pv_stream_buffer = const_cast<uint8_t *>(inBuffer->data() + inOffset);
527 ps_decode_ip->u4_num_Bytes = inSize;
528 } else {
529 ps_decode_ip->u4_ts = 0;
530 ps_decode_ip->pv_stream_buffer = nullptr;
531 ps_decode_ip->u4_num_Bytes = 0;
532 }
533 ps_decode_ip->s_out_buffer.u4_min_out_buf_size[0] = lumaSize;
534 ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
535 ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
536 if (outBuffer) {
537 if (outBuffer->width() < displayStride || outBuffer->height() < displayHeight) {
538 ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
539 outBuffer->width(), outBuffer->height(), displayStride, displayHeight);
540 return false;
541 }
542 ps_decode_ip->s_out_buffer.pu1_bufs[0] = outBuffer->data()[C2PlanarLayout::PLANE_Y];
543 ps_decode_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[C2PlanarLayout::PLANE_U];
544 ps_decode_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[C2PlanarLayout::PLANE_V];
545 } else {
546 ps_decode_ip->s_out_buffer.pu1_bufs[0] = mOutBufferFlush;
547 ps_decode_ip->s_out_buffer.pu1_bufs[1] = mOutBufferFlush + lumaSize;
548 ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferFlush + lumaSize + chromaSize;
549 }
550 ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
551 ps_decode_op->u4_size = sizeof(ivd_video_decode_op_t);
552
553 return true;
554 }
555
getVuiParams()556 bool C2SoftAvcDec::getVuiParams() {
557 ivdext_ctl_get_vui_params_ip_t s_get_vui_params_ip;
558 ivdext_ctl_get_vui_params_op_t s_get_vui_params_op;
559
560 s_get_vui_params_ip.u4_size = sizeof(ivdext_ctl_get_vui_params_ip_t);
561 s_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL;
562 s_get_vui_params_ip.e_sub_cmd =
563 (IVD_CONTROL_API_COMMAND_TYPE_T) IH264D_CMD_CTL_GET_VUI_PARAMS;
564 s_get_vui_params_op.u4_size = sizeof(ivdext_ctl_get_vui_params_op_t);
565 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
566 &s_get_vui_params_ip,
567 &s_get_vui_params_op);
568 if (status != IV_SUCCESS) {
569 ALOGD("error in %s: 0x%x", __func__, s_get_vui_params_op.u4_error_code);
570 return false;
571 }
572
573 VuiColorAspects vuiColorAspects;
574 vuiColorAspects.primaries = s_get_vui_params_op.u1_colour_primaries;
575 vuiColorAspects.transfer = s_get_vui_params_op.u1_tfr_chars;
576 vuiColorAspects.coeffs = s_get_vui_params_op.u1_matrix_coeffs;
577 vuiColorAspects.fullRange = s_get_vui_params_op.u1_video_full_range_flag;
578
579 // convert vui aspects to C2 values if changed
580 if (!(vuiColorAspects == mBitstreamColorAspects)) {
581 mBitstreamColorAspects = vuiColorAspects;
582 ColorAspects sfAspects;
583 C2StreamColorAspectsInfo::input codedAspects = { 0u };
584 ColorUtils::convertIsoColorAspectsToCodecAspects(
585 vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
586 vuiColorAspects.fullRange, sfAspects);
587 if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
588 codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
589 }
590 if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
591 codedAspects.range = C2Color::RANGE_UNSPECIFIED;
592 }
593 if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
594 codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
595 }
596 if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
597 codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
598 }
599 std::vector<std::unique_ptr<C2SettingResult>> failures;
600 (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
601 }
602 return true;
603 }
604
setFlushMode()605 status_t C2SoftAvcDec::setFlushMode() {
606 ivd_ctl_flush_ip_t s_set_flush_ip;
607 ivd_ctl_flush_op_t s_set_flush_op;
608
609 s_set_flush_ip.u4_size = sizeof(ivd_ctl_flush_ip_t);
610 s_set_flush_ip.e_cmd = IVD_CMD_VIDEO_CTL;
611 s_set_flush_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH;
612 s_set_flush_op.u4_size = sizeof(ivd_ctl_flush_op_t);
613 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
614 &s_set_flush_ip,
615 &s_set_flush_op);
616 if (status != IV_SUCCESS) {
617 ALOGE("error in %s: 0x%x", __func__, s_set_flush_op.u4_error_code);
618 return UNKNOWN_ERROR;
619 }
620
621 return OK;
622 }
623
resetDecoder()624 status_t C2SoftAvcDec::resetDecoder() {
625 ivd_ctl_reset_ip_t s_reset_ip;
626 ivd_ctl_reset_op_t s_reset_op;
627
628 s_reset_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
629 s_reset_ip.e_cmd = IVD_CMD_VIDEO_CTL;
630 s_reset_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
631 s_reset_op.u4_size = sizeof(ivd_ctl_reset_op_t);
632 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
633 &s_reset_ip,
634 &s_reset_op);
635 if (IV_SUCCESS != status) {
636 ALOGE("error in %s: 0x%x", __func__, s_reset_op.u4_error_code);
637 return UNKNOWN_ERROR;
638 }
639 mStride = 0;
640 (void) setNumCores();
641 mSignalledError = false;
642 mHeaderDecoded = false;
643
644 return OK;
645 }
646
resetPlugin()647 void C2SoftAvcDec::resetPlugin() {
648 mSignalledOutputEos = false;
649 gettimeofday(&mTimeStart, nullptr);
650 gettimeofday(&mTimeEnd, nullptr);
651 }
652
deleteDecoder()653 status_t C2SoftAvcDec::deleteDecoder() {
654 if (mDecHandle) {
655 ivdext_delete_ip_t s_delete_ip;
656 ivdext_delete_op_t s_delete_op;
657
658 s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
659 s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
660 s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
661 IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle,
662 &s_delete_ip,
663 &s_delete_op);
664 if (status != IV_SUCCESS) {
665 ALOGE("error in %s: 0x%x", __func__,
666 s_delete_op.s_ivd_delete_op_t.u4_error_code);
667 return UNKNOWN_ERROR;
668 }
669 mDecHandle = nullptr;
670 }
671
672 return OK;
673 }
674
fillEmptyWork(const std::unique_ptr<C2Work> & work)675 static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
676 uint32_t flags = 0;
677 if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
678 flags |= C2FrameData::FLAG_END_OF_STREAM;
679 ALOGV("signalling eos");
680 }
681 work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
682 work->worklets.front()->output.buffers.clear();
683 work->worklets.front()->output.ordinal = work->input.ordinal;
684 work->workletsProcessed = 1u;
685 }
686
finishWork(uint64_t index,const std::unique_ptr<C2Work> & work)687 void C2SoftAvcDec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
688 std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mOutBlock),
689 C2Rect(mWidth, mHeight));
690 mOutBlock = nullptr;
691 {
692 IntfImpl::Lock lock = mIntf->lock();
693 buffer->setInfo(mIntf->getColorAspects_l());
694 }
695
696 class FillWork {
697 public:
698 FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
699 const std::shared_ptr<C2Buffer>& buffer)
700 : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
701 ~FillWork() = default;
702
703 void operator()(const std::unique_ptr<C2Work>& work) {
704 work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
705 work->worklets.front()->output.buffers.clear();
706 work->worklets.front()->output.ordinal = mOrdinal;
707 work->workletsProcessed = 1u;
708 work->result = C2_OK;
709 if (mBuffer) {
710 work->worklets.front()->output.buffers.push_back(mBuffer);
711 }
712 ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
713 mOrdinal.timestamp.peekll(), mOrdinal.frameIndex.peekll(),
714 mBuffer ? "" : "o");
715 }
716
717 private:
718 const uint32_t mFlags;
719 const C2WorkOrdinalStruct mOrdinal;
720 const std::shared_ptr<C2Buffer> mBuffer;
721 };
722
723 auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
724 work->worklets.front()->output.flags = (C2FrameData::flags_t)0;
725 work->worklets.front()->output.buffers.clear();
726 work->worklets.front()->output.buffers.push_back(buffer);
727 work->worklets.front()->output.ordinal = work->input.ordinal;
728 work->workletsProcessed = 1u;
729 };
730 if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
731 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
732 // TODO: Check if cloneAndSend can be avoided by tracking number of frames remaining
733 if (eos) {
734 if (buffer) {
735 mOutIndex = index;
736 C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
737 cloneAndSend(
738 mOutIndex, work,
739 FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
740 buffer.reset();
741 }
742 } else {
743 fillWork(work);
744 }
745 } else {
746 finish(index, fillWork);
747 }
748 }
749
ensureDecoderState(const std::shared_ptr<C2BlockPool> & pool)750 c2_status_t C2SoftAvcDec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
751 if (!mDecHandle) {
752 ALOGE("not supposed to be here, invalid decoder context");
753 return C2_CORRUPTED;
754 }
755 if (mStride != ALIGN64(mWidth)) {
756 mStride = ALIGN64(mWidth);
757 if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
758 }
759 if (mOutBlock &&
760 (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
761 mOutBlock.reset();
762 }
763 if (!mOutBlock) {
764 uint32_t format = HAL_PIXEL_FORMAT_YV12;
765 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
766 c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
767 if (err != C2_OK) {
768 ALOGE("fetchGraphicBlock for Output failed with status %d", err);
769 return err;
770 }
771 ALOGV("provided (%dx%d) required (%dx%d)",
772 mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
773 }
774
775 return C2_OK;
776 }
777
778 // TODO: can overall error checking be improved?
779 // TODO: allow configuration of color format and usage for graphic buffers instead
780 // of hard coding them to HAL_PIXEL_FORMAT_YV12
781 // TODO: pass coloraspects information to surface
782 // TODO: test support for dynamic change in resolution
783 // TODO: verify if the decoder sent back all frames
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)784 void C2SoftAvcDec::process(
785 const std::unique_ptr<C2Work> &work,
786 const std::shared_ptr<C2BlockPool> &pool) {
787 // Initialize output work
788 work->result = C2_OK;
789 work->workletsProcessed = 0u;
790 work->worklets.front()->output.flags = work->input.flags;
791 if (mSignalledError || mSignalledOutputEos) {
792 work->result = C2_BAD_VALUE;
793 return;
794 }
795
796 size_t inOffset = 0u;
797 size_t inSize = 0u;
798 uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
799 C2ReadView rView = mDummyReadView;
800 if (!work->input.buffers.empty()) {
801 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
802 inSize = rView.capacity();
803 if (inSize && rView.error()) {
804 ALOGE("read view map failed %d", rView.error());
805 work->result = rView.error();
806 return;
807 }
808 }
809 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
810 bool hasPicture = false;
811
812 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
813 inSize, (int)work->input.ordinal.timestamp.peeku(),
814 (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
815 size_t inPos = 0;
816 while (inPos < inSize) {
817 if (C2_OK != ensureDecoderState(pool)) {
818 mSignalledError = true;
819 work->workletsProcessed = 1u;
820 work->result = C2_CORRUPTED;
821 return;
822 }
823
824 ivd_video_decode_ip_t s_decode_ip;
825 ivd_video_decode_op_t s_decode_op;
826 {
827 C2GraphicView wView = mOutBlock->map().get();
828 if (wView.error()) {
829 ALOGE("graphic view map failed %d", wView.error());
830 work->result = wView.error();
831 return;
832 }
833 if (!setDecodeArgs(&s_decode_ip, &s_decode_op, &rView, &wView,
834 inOffset + inPos, inSize - inPos, workIndex)) {
835 mSignalledError = true;
836 work->workletsProcessed = 1u;
837 work->result = C2_CORRUPTED;
838 return;
839 }
840
841 if (false == mHeaderDecoded) {
842 /* Decode header and get dimensions */
843 setParams(mStride, IVD_DECODE_HEADER);
844 }
845
846 WORD32 delay;
847 GETTIME(&mTimeStart, nullptr);
848 TIME_DIFF(mTimeEnd, mTimeStart, delay);
849 (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
850 WORD32 decodeTime;
851 GETTIME(&mTimeEnd, nullptr);
852 TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
853 ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
854 s_decode_op.u4_num_bytes_consumed);
855 }
856 if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
857 ALOGE("allocation failure in decoder");
858 mSignalledError = true;
859 work->workletsProcessed = 1u;
860 work->result = C2_CORRUPTED;
861 return;
862 } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
863 ALOGE("unsupported resolution : %dx%d", mWidth, mHeight);
864 mSignalledError = true;
865 work->workletsProcessed = 1u;
866 work->result = C2_CORRUPTED;
867 return;
868 } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
869 ALOGV("resolution changed");
870 drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
871 resetDecoder();
872 resetPlugin();
873 work->workletsProcessed = 0u;
874
875 /* Decode header and get new dimensions */
876 setParams(mStride, IVD_DECODE_HEADER);
877 (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
878 } else if (IS_IVD_FATAL_ERROR(s_decode_op.u4_error_code)) {
879 ALOGE("Fatal error in decoder 0x%x", s_decode_op.u4_error_code);
880 mSignalledError = true;
881 work->workletsProcessed = 1u;
882 work->result = C2_CORRUPTED;
883 return;
884 }
885 if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
886 if (mHeaderDecoded == false) {
887 mHeaderDecoded = true;
888 setParams(ALIGN64(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
889 }
890 if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
891 mWidth = s_decode_op.u4_pic_wd;
892 mHeight = s_decode_op.u4_pic_ht;
893 CHECK_EQ(0u, s_decode_op.u4_output_present);
894
895 C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
896 std::vector<std::unique_ptr<C2SettingResult>> failures;
897 c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
898 if (err == OK) {
899 work->worklets.front()->output.configUpdate.push_back(
900 C2Param::Copy(size));
901 } else {
902 ALOGE("Cannot set width and height");
903 mSignalledError = true;
904 work->workletsProcessed = 1u;
905 work->result = C2_CORRUPTED;
906 return;
907 }
908 continue;
909 }
910 }
911 (void)getVuiParams();
912 hasPicture |= (1 == s_decode_op.u4_frame_decoded_flag);
913 if (s_decode_op.u4_output_present) {
914 finishWork(s_decode_op.u4_ts, work);
915 }
916 if (0 == s_decode_op.u4_num_bytes_consumed) {
917 ALOGD("Bytes consumed is zero. Ignoring remaining bytes");
918 break;
919 }
920 inPos += s_decode_op.u4_num_bytes_consumed;
921 if (hasPicture && (inSize - inPos)) {
922 ALOGD("decoded frame in current access nal, ignoring further trailing bytes %d",
923 (int)inSize - (int)inPos);
924 break;
925 }
926 }
927 if (eos) {
928 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
929 mSignalledOutputEos = true;
930 } else if (!hasPicture) {
931 fillEmptyWork(work);
932 }
933
934 work->input.buffers.clear();
935 }
936
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)937 c2_status_t C2SoftAvcDec::drainInternal(
938 uint32_t drainMode,
939 const std::shared_ptr<C2BlockPool> &pool,
940 const std::unique_ptr<C2Work> &work) {
941 if (drainMode == NO_DRAIN) {
942 ALOGW("drain with NO_DRAIN: no-op");
943 return C2_OK;
944 }
945 if (drainMode == DRAIN_CHAIN) {
946 ALOGW("DRAIN_CHAIN not supported");
947 return C2_OMITTED;
948 }
949
950 if (OK != setFlushMode()) return C2_CORRUPTED;
951 while (true) {
952 if (C2_OK != ensureDecoderState(pool)) {
953 mSignalledError = true;
954 work->workletsProcessed = 1u;
955 work->result = C2_CORRUPTED;
956 return C2_CORRUPTED;
957 }
958 C2GraphicView wView = mOutBlock->map().get();
959 if (wView.error()) {
960 ALOGE("graphic view map failed %d", wView.error());
961 return C2_CORRUPTED;
962 }
963 ivd_video_decode_ip_t s_decode_ip;
964 ivd_video_decode_op_t s_decode_op;
965 if (!setDecodeArgs(&s_decode_ip, &s_decode_op, nullptr, &wView, 0, 0, 0)) {
966 mSignalledError = true;
967 work->workletsProcessed = 1u;
968 return C2_CORRUPTED;
969 }
970 (void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
971 if (s_decode_op.u4_output_present) {
972 finishWork(s_decode_op.u4_ts, work);
973 } else {
974 fillEmptyWork(work);
975 break;
976 }
977 }
978
979 return C2_OK;
980 }
981
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)982 c2_status_t C2SoftAvcDec::drain(
983 uint32_t drainMode,
984 const std::shared_ptr<C2BlockPool> &pool) {
985 return drainInternal(drainMode, pool, nullptr);
986 }
987
988 class C2SoftAvcDecFactory : public C2ComponentFactory {
989 public:
C2SoftAvcDecFactory()990 C2SoftAvcDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
991 GetCodec2PlatformComponentStore()->getParamReflector())) {
992 }
993
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)994 virtual c2_status_t createComponent(
995 c2_node_id_t id,
996 std::shared_ptr<C2Component>* const component,
997 std::function<void(C2Component*)> deleter) override {
998 *component = std::shared_ptr<C2Component>(
999 new C2SoftAvcDec(COMPONENT_NAME,
1000 id,
1001 std::make_shared<C2SoftAvcDec::IntfImpl>(mHelper)),
1002 deleter);
1003 return C2_OK;
1004 }
1005
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)1006 virtual c2_status_t createInterface(
1007 c2_node_id_t id,
1008 std::shared_ptr<C2ComponentInterface>* const interface,
1009 std::function<void(C2ComponentInterface*)> deleter) override {
1010 *interface = std::shared_ptr<C2ComponentInterface>(
1011 new SimpleInterface<C2SoftAvcDec::IntfImpl>(
1012 COMPONENT_NAME, id, std::make_shared<C2SoftAvcDec::IntfImpl>(mHelper)),
1013 deleter);
1014 return C2_OK;
1015 }
1016
1017 virtual ~C2SoftAvcDecFactory() override = default;
1018
1019 private:
1020 std::shared_ptr<C2ReflectorHelper> mHelper;
1021 };
1022
1023 } // namespace android
1024
CreateCodec2Factory()1025 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
1026 ALOGV("in %s", __func__);
1027 return new ::android::C2SoftAvcDecFactory();
1028 }
1029
DestroyCodec2Factory(::C2ComponentFactory * factory)1030 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
1031 ALOGV("in %s", __func__);
1032 delete factory;
1033 }
1034