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