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