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