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