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