1 /*
2 * Copyright (C) 2012 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 "C2SoftAacEnc"
19 #include <utils/Log.h>
20
21 #include <inttypes.h>
22
23 #include <C2PlatformSupport.h>
24 #include <SimpleC2Interface.h>
25 #include <media/stagefright/foundation/MediaDefs.h>
26 #include <media/stagefright/foundation/hexdump.h>
27
28 #include "C2SoftAacEnc.h"
29
30 namespace android {
31
32 class C2SoftAacEnc::IntfImpl : public C2InterfaceHelper {
33 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)34 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
35 : C2InterfaceHelper(helper) {
36
37 setDerivedInstance(this);
38
39 addParameter(
40 DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING)
41 .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatAudio))
42 .build());
43
44 addParameter(
45 DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING)
46 .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatCompressed))
47 .build());
48
49 addParameter(
50 DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING)
51 .withConstValue(AllocSharedString<C2PortMimeConfig::input>(
52 MEDIA_MIMETYPE_AUDIO_RAW))
53 .build());
54
55 addParameter(
56 DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING)
57 .withConstValue(AllocSharedString<C2PortMimeConfig::output>(
58 MEDIA_MIMETYPE_AUDIO_AAC))
59 .build());
60
61 addParameter(
62 DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING)
63 .withDefault(new C2StreamSampleRateInfo::input(0u, 44100))
64 .withFields({C2F(mSampleRate, value).oneOf({
65 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
66 })})
67 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
68 .build());
69
70 addParameter(
71 DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING)
72 .withDefault(new C2StreamChannelCountInfo::input(0u, 1))
73 .withFields({C2F(mChannelCount, value).inRange(1, 6)})
74 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
75 .build());
76
77 addParameter(
78 DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING)
79 .withDefault(new C2BitrateTuning::output(0u, 64000))
80 .withFields({C2F(mBitrate, value).inRange(8000, 960000)})
81 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
82 .build());
83
84 addParameter(
85 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
86 .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 8192))
87 .calculatedAs(MaxBufSizeCalculator, mChannelCount)
88 .build());
89
90 addParameter(
91 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
92 .withDefault(new C2StreamProfileLevelInfo::output(0u,
93 C2Config::PROFILE_AAC_LC, C2Config::LEVEL_UNUSED))
94 .withFields({
95 C2F(mProfileLevel, profile).oneOf({
96 C2Config::PROFILE_AAC_LC,
97 C2Config::PROFILE_AAC_HE,
98 C2Config::PROFILE_AAC_HE_PS,
99 C2Config::PROFILE_AAC_LD,
100 C2Config::PROFILE_AAC_ELD}),
101 C2F(mProfileLevel, level).oneOf({
102 C2Config::LEVEL_UNUSED
103 })
104 })
105 .withSetter(ProfileLevelSetter)
106 .build());
107 }
108
getSampleRate() const109 uint32_t getSampleRate() const { return mSampleRate->value; }
getChannelCount() const110 uint32_t getChannelCount() const { return mChannelCount->value; }
getBitrate() const111 uint32_t getBitrate() const { return mBitrate->value; }
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::output> & me)112 static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output> &me) {
113 (void)mayBlock;
114 (void)me; // TODO: validate
115 return C2R::Ok();
116 }
117
MaxBufSizeCalculator(bool mayBlock,C2P<C2StreamMaxBufferSizeInfo::input> & me,const C2P<C2StreamChannelCountInfo::input> & channelCount)118 static C2R MaxBufSizeCalculator(
119 bool mayBlock,
120 C2P<C2StreamMaxBufferSizeInfo::input> &me,
121 const C2P<C2StreamChannelCountInfo::input> &channelCount) {
122 (void)mayBlock;
123 me.set().value = 1024 * sizeof(short) * channelCount.v.value;
124 return C2R::Ok();
125 }
126
127 private:
128 std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
129 std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
130 std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
131 std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
132 std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate;
133 std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
134 std::shared_ptr<C2BitrateTuning::output> mBitrate;
135 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
136 std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
137 };
138
139 constexpr char COMPONENT_NAME[] = "c2.android.aac.encoder";
140
C2SoftAacEnc(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)141 C2SoftAacEnc::C2SoftAacEnc(
142 const char *name,
143 c2_node_id_t id,
144 const std::shared_ptr<IntfImpl> &intfImpl)
145 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
146 mIntf(intfImpl),
147 mAACEncoder(nullptr),
148 mSBRMode(-1),
149 mSBRRatio(0),
150 mAACProfile(AOT_AAC_LC),
151 mNumBytesPerInputFrame(0u),
152 mOutBufferSize(0u),
153 mSentCodecSpecificData(false),
154 mInputSize(0),
155 mInputTimeUs(-1ll),
156 mSignalledError(false),
157 mOutIndex(0u) {
158 }
159
~C2SoftAacEnc()160 C2SoftAacEnc::~C2SoftAacEnc() {
161 onReset();
162 }
163
onInit()164 c2_status_t C2SoftAacEnc::onInit() {
165 status_t err = initEncoder();
166 return err == OK ? C2_OK : C2_CORRUPTED;
167 }
168
initEncoder()169 status_t C2SoftAacEnc::initEncoder() {
170 if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
171 ALOGE("Failed to init AAC encoder");
172 return UNKNOWN_ERROR;
173 }
174 return setAudioParams();
175 }
176
onStop()177 c2_status_t C2SoftAacEnc::onStop() {
178 mSentCodecSpecificData = false;
179 mInputSize = 0u;
180 mInputTimeUs = -1ll;
181 mSignalledError = false;
182 return C2_OK;
183 }
184
onReset()185 void C2SoftAacEnc::onReset() {
186 (void)onStop();
187 aacEncClose(&mAACEncoder);
188 }
189
onRelease()190 void C2SoftAacEnc::onRelease() {
191 // no-op
192 }
193
onFlush_sm()194 c2_status_t C2SoftAacEnc::onFlush_sm() {
195 mSentCodecSpecificData = false;
196 mInputSize = 0u;
197 return C2_OK;
198 }
199
getChannelMode(uint32_t nChannels)200 static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
201 CHANNEL_MODE chMode = MODE_INVALID;
202 switch (nChannels) {
203 case 1: chMode = MODE_1; break;
204 case 2: chMode = MODE_2; break;
205 case 3: chMode = MODE_1_2; break;
206 case 4: chMode = MODE_1_2_1; break;
207 case 5: chMode = MODE_1_2_2; break;
208 case 6: chMode = MODE_1_2_2_1; break;
209 default: chMode = MODE_INVALID;
210 }
211 return chMode;
212 }
213
214 //static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
215 // if (profile == OMX_AUDIO_AACObjectLC) {
216 // return AOT_AAC_LC;
217 // } else if (profile == OMX_AUDIO_AACObjectHE) {
218 // return AOT_SBR;
219 // } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
220 // return AOT_PS;
221 // } else if (profile == OMX_AUDIO_AACObjectLD) {
222 // return AOT_ER_AAC_LD;
223 // } else if (profile == OMX_AUDIO_AACObjectELD) {
224 // return AOT_ER_AAC_ELD;
225 // } else {
226 // ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
227 // return AOT_AAC_LC;
228 // }
229 //}
230
setAudioParams()231 status_t C2SoftAacEnc::setAudioParams() {
232 // We call this whenever sample rate, number of channels, bitrate or SBR mode change
233 // in reponse to setParameter calls.
234
235 ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
236 mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(), mSBRMode, mSBRRatio);
237
238 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
239 ALOGE("Failed to set AAC encoder parameters");
240 return UNKNOWN_ERROR;
241 }
242
243 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mIntf->getSampleRate())) {
244 ALOGE("Failed to set AAC encoder parameters");
245 return UNKNOWN_ERROR;
246 }
247 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mIntf->getBitrate())) {
248 ALOGE("Failed to set AAC encoder parameters");
249 return UNKNOWN_ERROR;
250 }
251 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
252 getChannelMode(mIntf->getChannelCount()))) {
253 ALOGE("Failed to set AAC encoder parameters");
254 return UNKNOWN_ERROR;
255 }
256 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
257 ALOGE("Failed to set AAC encoder parameters");
258 return UNKNOWN_ERROR;
259 }
260
261 if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
262 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
263 ALOGE("Failed to set AAC encoder parameters");
264 return UNKNOWN_ERROR;
265 }
266 }
267
268 /* SBR ratio parameter configurations:
269 0: Default configuration wherein SBR ratio is configured depending on audio object type by
270 the FDK.
271 1: Downsampled SBR (default for ELD)
272 2: Dualrate SBR (default for HE-AAC)
273 */
274 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
275 ALOGE("Failed to set AAC encoder parameters");
276 return UNKNOWN_ERROR;
277 }
278
279 return OK;
280 }
281
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)282 void C2SoftAacEnc::process(
283 const std::unique_ptr<C2Work> &work,
284 const std::shared_ptr<C2BlockPool> &pool) {
285 // Initialize output work
286 work->result = C2_OK;
287 work->workletsProcessed = 1u;
288 work->worklets.front()->output.flags = work->input.flags;
289
290 if (mSignalledError) {
291 return;
292 }
293 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
294
295 uint32_t sampleRate = mIntf->getSampleRate();
296 uint32_t channelCount = mIntf->getChannelCount();
297
298 if (!mSentCodecSpecificData) {
299 // The very first thing we want to output is the codec specific
300 // data.
301
302 if (AACENC_OK != aacEncEncode(mAACEncoder, nullptr, nullptr, nullptr, nullptr)) {
303 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
304 mSignalledError = true;
305 work->result = C2_CORRUPTED;
306 return;
307 }
308
309 uint32_t bitrate = mIntf->getBitrate();
310 uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
311 if (bitrate != actualBitRate) {
312 ALOGW("Requested bitrate %u unsupported, using %u", bitrate, actualBitRate);
313 }
314
315 AACENC_InfoStruct encInfo;
316 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
317 ALOGE("Failed to get AAC encoder info");
318 mSignalledError = true;
319 work->result = C2_CORRUPTED;
320 return;
321 }
322
323 std::unique_ptr<C2StreamCsdInfo::output> csd =
324 C2StreamCsdInfo::output::AllocUnique(encInfo.confSize, 0u);
325 if (!csd) {
326 ALOGE("CSD allocation failed");
327 mSignalledError = true;
328 work->result = C2_NO_MEMORY;
329 return;
330 }
331 memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
332 ALOGV("put csd");
333 #if defined(LOG_NDEBUG) && !LOG_NDEBUG
334 hexdump(csd->m.value, csd->flexCount());
335 #endif
336 work->worklets.front()->output.configUpdate.push_back(std::move(csd));
337
338 mOutBufferSize = encInfo.maxOutBufBytes;
339 mNumBytesPerInputFrame = encInfo.frameLength * channelCount * sizeof(int16_t);
340 mInputTimeUs = work->input.ordinal.timestamp;
341
342 mSentCodecSpecificData = true;
343 }
344
345 uint8_t temp[1];
346 C2ReadView view = mDummyReadView;
347 const uint8_t *data = temp;
348 size_t capacity = 0u;
349 if (!work->input.buffers.empty()) {
350 view = work->input.buffers[0]->data().linearBlocks().front().map().get();
351 data = view.data();
352 capacity = view.capacity();
353 }
354
355 size_t numFrames = (capacity + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
356 / mNumBytesPerInputFrame;
357 ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu mNumBytesPerInputFrame = %u",
358 capacity, mInputSize, numFrames, mNumBytesPerInputFrame);
359
360 std::shared_ptr<C2LinearBlock> block;
361 std::shared_ptr<C2Buffer> buffer;
362 std::unique_ptr<C2WriteView> wView;
363 uint8_t *outPtr = temp;
364 size_t outAvailable = 0u;
365 uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
366
367 AACENC_InArgs inargs;
368 AACENC_OutArgs outargs;
369 memset(&inargs, 0, sizeof(inargs));
370 memset(&outargs, 0, sizeof(outargs));
371 inargs.numInSamples = capacity / sizeof(int16_t);
372
373 void* inBuffer[] = { (unsigned char *)data };
374 INT inBufferIds[] = { IN_AUDIO_DATA };
375 INT inBufferSize[] = { (INT)capacity };
376 INT inBufferElSize[] = { sizeof(int16_t) };
377
378 AACENC_BufDesc inBufDesc;
379 inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*);
380 inBufDesc.bufs = (void**)&inBuffer;
381 inBufDesc.bufferIdentifiers = inBufferIds;
382 inBufDesc.bufSizes = inBufferSize;
383 inBufDesc.bufElSizes = inBufferElSize;
384
385 void* outBuffer[] = { outPtr };
386 INT outBufferIds[] = { OUT_BITSTREAM_DATA };
387 INT outBufferSize[] = { 0 };
388 INT outBufferElSize[] = { sizeof(UCHAR) };
389
390 AACENC_BufDesc outBufDesc;
391 outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*);
392 outBufDesc.bufs = (void**)&outBuffer;
393 outBufDesc.bufferIdentifiers = outBufferIds;
394 outBufDesc.bufSizes = outBufferSize;
395 outBufDesc.bufElSizes = outBufferElSize;
396
397 AACENC_ERROR encoderErr = AACENC_OK;
398
399 class FillWork {
400 public:
401 FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
402 const std::shared_ptr<C2Buffer> &buffer)
403 : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {
404 }
405 ~FillWork() = default;
406
407 void operator()(const std::unique_ptr<C2Work> &work) {
408 work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
409 work->worklets.front()->output.buffers.clear();
410 work->worklets.front()->output.ordinal = mOrdinal;
411 work->workletsProcessed = 1u;
412 work->result = C2_OK;
413 if (mBuffer) {
414 work->worklets.front()->output.buffers.push_back(mBuffer);
415 }
416 ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
417 mOrdinal.timestamp.peekll(),
418 mOrdinal.frameIndex.peekll(),
419 mBuffer ? "" : "o");
420 }
421
422 private:
423 const uint32_t mFlags;
424 const C2WorkOrdinalStruct mOrdinal;
425 const std::shared_ptr<C2Buffer> mBuffer;
426 };
427
428 C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
429
430 while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
431 if (numFrames && !block) {
432 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
433 // TODO: error handling, proper usage, etc.
434 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
435 if (err != C2_OK) {
436 ALOGE("fetchLinearBlock failed : err = %d", err);
437 work->result = C2_NO_MEMORY;
438 return;
439 }
440
441 wView.reset(new C2WriteView(block->map().get()));
442 outPtr = wView->data();
443 outAvailable = wView->size();
444 --numFrames;
445 }
446
447 memset(&outargs, 0, sizeof(outargs));
448
449 outBuffer[0] = outPtr;
450 outBufferSize[0] = outAvailable;
451
452 encoderErr = aacEncEncode(mAACEncoder,
453 &inBufDesc,
454 &outBufDesc,
455 &inargs,
456 &outargs);
457
458 if (encoderErr == AACENC_OK) {
459 if (buffer) {
460 outOrdinal.frameIndex = mOutIndex++;
461 outOrdinal.timestamp = mInputTimeUs;
462 cloneAndSend(
463 inputIndex,
464 work,
465 FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
466 buffer.reset();
467 }
468
469 if (outargs.numOutBytes > 0) {
470 mInputSize = 0;
471 int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
472 + outargs.numInSamples;
473 mInputTimeUs = work->input.ordinal.timestamp
474 + (consumed * 1000000ll / channelCount / sampleRate);
475 buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
476 #if defined(LOG_NDEBUG) && !LOG_NDEBUG
477 hexdump(outPtr, std::min(outargs.numOutBytes, 256));
478 #endif
479 outPtr = temp;
480 outAvailable = 0;
481 block.reset();
482 } else {
483 mInputSize += outargs.numInSamples * sizeof(int16_t);
484 }
485
486 if (outargs.numInSamples > 0) {
487 inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples;
488 inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
489 inargs.numInSamples -= outargs.numInSamples;
490 }
491 }
492 ALOGV("encoderErr = %d mInputSize = %zu inargs.numInSamples = %d, mInputTimeUs = %lld",
493 encoderErr, mInputSize, inargs.numInSamples, mInputTimeUs.peekll());
494 }
495
496 if (eos && inBufferSize[0] > 0) {
497 if (numFrames && !block) {
498 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
499 // TODO: error handling, proper usage, etc.
500 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
501 if (err != C2_OK) {
502 ALOGE("fetchLinearBlock failed : err = %d", err);
503 work->result = C2_NO_MEMORY;
504 return;
505 }
506
507 wView.reset(new C2WriteView(block->map().get()));
508 outPtr = wView->data();
509 outAvailable = wView->size();
510 --numFrames;
511 }
512
513 memset(&outargs, 0, sizeof(outargs));
514
515 outBuffer[0] = outPtr;
516 outBufferSize[0] = outAvailable;
517
518 // Flush
519 inargs.numInSamples = -1;
520
521 (void)aacEncEncode(mAACEncoder,
522 &inBufDesc,
523 &outBufDesc,
524 &inargs,
525 &outargs);
526 }
527
528 outOrdinal.frameIndex = mOutIndex++;
529 outOrdinal.timestamp = mInputTimeUs;
530 FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
531 outOrdinal, buffer)(work);
532 }
533
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)534 c2_status_t C2SoftAacEnc::drain(
535 uint32_t drainMode,
536 const std::shared_ptr<C2BlockPool> &pool) {
537 switch (drainMode) {
538 case DRAIN_COMPONENT_NO_EOS:
539 [[fallthrough]];
540 case NO_DRAIN:
541 // no-op
542 return C2_OK;
543 case DRAIN_CHAIN:
544 return C2_OMITTED;
545 case DRAIN_COMPONENT_WITH_EOS:
546 break;
547 default:
548 return C2_BAD_VALUE;
549 }
550
551 (void)pool;
552 mSentCodecSpecificData = false;
553 mInputSize = 0u;
554
555 // TODO: we don't have any pending work at this time to drain.
556 return C2_OK;
557 }
558
559 class C2SoftAacEncFactory : public C2ComponentFactory {
560 public:
C2SoftAacEncFactory()561 C2SoftAacEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
562 GetCodec2PlatformComponentStore()->getParamReflector())) {
563 }
564
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)565 virtual c2_status_t createComponent(
566 c2_node_id_t id,
567 std::shared_ptr<C2Component>* const component,
568 std::function<void(C2Component*)> deleter) override {
569 *component = std::shared_ptr<C2Component>(
570 new C2SoftAacEnc(COMPONENT_NAME,
571 id,
572 std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
573 deleter);
574 return C2_OK;
575 }
576
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)577 virtual c2_status_t createInterface(
578 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
579 std::function<void(C2ComponentInterface*)> deleter) override {
580 *interface = std::shared_ptr<C2ComponentInterface>(
581 new SimpleInterface<C2SoftAacEnc::IntfImpl>(
582 COMPONENT_NAME, id, std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
583 deleter);
584 return C2_OK;
585 }
586
587 virtual ~C2SoftAacEncFactory() override = default;
588
589 private:
590 std::shared_ptr<C2ReflectorHelper> mHelper;
591 };
592
593 } // namespace android
594
CreateCodec2Factory()595 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
596 ALOGV("in %s", __func__);
597 return new ::android::C2SoftAacEncFactory();
598 }
599
DestroyCodec2Factory(::C2ComponentFactory * factory)600 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
601 ALOGV("in %s", __func__);
602 delete factory;
603 }
604