blob: d1bdf0d5136d8e811c197f31dce32b6e929f1cc8 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
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
30namespace android {
31
32class C2SoftAacEnc::IntfImpl : public C2InterfaceHelper {
33public:
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
109 uint32_t getSampleRate() const { return mSampleRate->value; }
110 uint32_t getChannelCount() const { return mChannelCount->value; }
111 uint32_t getBitrate() const { return mBitrate->value; }
112 static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output> &me) {
113 (void)mayBlock;
114 (void)me; // TODO: validate
115 return C2R::Ok();
116 }
117
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
127private:
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
139constexpr char COMPONENT_NAME[] = "c2.android.aac.encoder";
140
141C2SoftAacEnc::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),
Wonsik Kim353e1672019-01-07 16:31:29 -0800154 mInputTimeSet(false),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800155 mInputSize(0),
156 mInputTimeUs(-1ll),
157 mSignalledError(false),
158 mOutIndex(0u) {
159}
160
161C2SoftAacEnc::~C2SoftAacEnc() {
162 onReset();
163}
164
165c2_status_t C2SoftAacEnc::onInit() {
166 status_t err = initEncoder();
167 return err == OK ? C2_OK : C2_CORRUPTED;
168}
169
170status_t C2SoftAacEnc::initEncoder() {
171 if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
172 ALOGE("Failed to init AAC encoder");
173 return UNKNOWN_ERROR;
174 }
175 return setAudioParams();
176}
177
178c2_status_t C2SoftAacEnc::onStop() {
179 mSentCodecSpecificData = false;
Wonsik Kim353e1672019-01-07 16:31:29 -0800180 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800181 mInputSize = 0u;
182 mInputTimeUs = -1ll;
183 mSignalledError = false;
184 return C2_OK;
185}
186
187void C2SoftAacEnc::onReset() {
188 (void)onStop();
189 aacEncClose(&mAACEncoder);
190}
191
192void C2SoftAacEnc::onRelease() {
193 // no-op
194}
195
196c2_status_t C2SoftAacEnc::onFlush_sm() {
197 mSentCodecSpecificData = false;
Wonsik Kim353e1672019-01-07 16:31:29 -0800198 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800199 mInputSize = 0u;
200 return C2_OK;
201}
202
203static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
204 CHANNEL_MODE chMode = MODE_INVALID;
205 switch (nChannels) {
206 case 1: chMode = MODE_1; break;
207 case 2: chMode = MODE_2; break;
208 case 3: chMode = MODE_1_2; break;
209 case 4: chMode = MODE_1_2_1; break;
210 case 5: chMode = MODE_1_2_2; break;
211 case 6: chMode = MODE_1_2_2_1; break;
212 default: chMode = MODE_INVALID;
213 }
214 return chMode;
215}
216
217//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
218// if (profile == OMX_AUDIO_AACObjectLC) {
219// return AOT_AAC_LC;
220// } else if (profile == OMX_AUDIO_AACObjectHE) {
221// return AOT_SBR;
222// } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
223// return AOT_PS;
224// } else if (profile == OMX_AUDIO_AACObjectLD) {
225// return AOT_ER_AAC_LD;
226// } else if (profile == OMX_AUDIO_AACObjectELD) {
227// return AOT_ER_AAC_ELD;
228// } else {
229// ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
230// return AOT_AAC_LC;
231// }
232//}
233
234status_t C2SoftAacEnc::setAudioParams() {
235 // We call this whenever sample rate, number of channels, bitrate or SBR mode change
236 // in reponse to setParameter calls.
237
238 ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
239 mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(), mSBRMode, mSBRRatio);
240
241 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
242 ALOGE("Failed to set AAC encoder parameters");
243 return UNKNOWN_ERROR;
244 }
245
246 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mIntf->getSampleRate())) {
247 ALOGE("Failed to set AAC encoder parameters");
248 return UNKNOWN_ERROR;
249 }
250 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mIntf->getBitrate())) {
251 ALOGE("Failed to set AAC encoder parameters");
252 return UNKNOWN_ERROR;
253 }
254 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
255 getChannelMode(mIntf->getChannelCount()))) {
256 ALOGE("Failed to set AAC encoder parameters");
257 return UNKNOWN_ERROR;
258 }
259 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
260 ALOGE("Failed to set AAC encoder parameters");
261 return UNKNOWN_ERROR;
262 }
263
264 if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
265 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
266 ALOGE("Failed to set AAC encoder parameters");
267 return UNKNOWN_ERROR;
268 }
269 }
270
271 /* SBR ratio parameter configurations:
272 0: Default configuration wherein SBR ratio is configured depending on audio object type by
273 the FDK.
274 1: Downsampled SBR (default for ELD)
275 2: Dualrate SBR (default for HE-AAC)
276 */
277 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
278 ALOGE("Failed to set AAC encoder parameters");
279 return UNKNOWN_ERROR;
280 }
281
282 return OK;
283}
284
285void C2SoftAacEnc::process(
286 const std::unique_ptr<C2Work> &work,
287 const std::shared_ptr<C2BlockPool> &pool) {
288 // Initialize output work
289 work->result = C2_OK;
290 work->workletsProcessed = 1u;
291 work->worklets.front()->output.flags = work->input.flags;
292
293 if (mSignalledError) {
294 return;
295 }
296 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
297
298 uint32_t sampleRate = mIntf->getSampleRate();
299 uint32_t channelCount = mIntf->getChannelCount();
300
301 if (!mSentCodecSpecificData) {
302 // The very first thing we want to output is the codec specific
303 // data.
304
305 if (AACENC_OK != aacEncEncode(mAACEncoder, nullptr, nullptr, nullptr, nullptr)) {
306 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
307 mSignalledError = true;
308 work->result = C2_CORRUPTED;
309 return;
310 }
311
312 uint32_t bitrate = mIntf->getBitrate();
313 uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
314 if (bitrate != actualBitRate) {
315 ALOGW("Requested bitrate %u unsupported, using %u", bitrate, actualBitRate);
316 }
317
318 AACENC_InfoStruct encInfo;
319 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
320 ALOGE("Failed to get AAC encoder info");
321 mSignalledError = true;
322 work->result = C2_CORRUPTED;
323 return;
324 }
325
326 std::unique_ptr<C2StreamCsdInfo::output> csd =
327 C2StreamCsdInfo::output::AllocUnique(encInfo.confSize, 0u);
328 if (!csd) {
329 ALOGE("CSD allocation failed");
330 mSignalledError = true;
331 work->result = C2_NO_MEMORY;
332 return;
333 }
334 memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
335 ALOGV("put csd");
336#if defined(LOG_NDEBUG) && !LOG_NDEBUG
337 hexdump(csd->m.value, csd->flexCount());
338#endif
339 work->worklets.front()->output.configUpdate.push_back(std::move(csd));
340
341 mOutBufferSize = encInfo.maxOutBufBytes;
342 mNumBytesPerInputFrame = encInfo.frameLength * channelCount * sizeof(int16_t);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800343
344 mSentCodecSpecificData = true;
345 }
346
347 uint8_t temp[1];
348 C2ReadView view = mDummyReadView;
349 const uint8_t *data = temp;
350 size_t capacity = 0u;
351 if (!work->input.buffers.empty()) {
352 view = work->input.buffers[0]->data().linearBlocks().front().map().get();
353 data = view.data();
354 capacity = view.capacity();
355 }
Wonsik Kim353e1672019-01-07 16:31:29 -0800356 if (!mInputTimeSet && capacity > 0) {
357 mInputTimeUs = work->input.ordinal.timestamp;
358 mInputTimeSet = true;
359 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800360
361 size_t numFrames = (capacity + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
362 / mNumBytesPerInputFrame;
363 ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu mNumBytesPerInputFrame = %u",
364 capacity, mInputSize, numFrames, mNumBytesPerInputFrame);
365
366 std::shared_ptr<C2LinearBlock> block;
367 std::shared_ptr<C2Buffer> buffer;
368 std::unique_ptr<C2WriteView> wView;
369 uint8_t *outPtr = temp;
370 size_t outAvailable = 0u;
371 uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
372
373 AACENC_InArgs inargs;
374 AACENC_OutArgs outargs;
375 memset(&inargs, 0, sizeof(inargs));
376 memset(&outargs, 0, sizeof(outargs));
377 inargs.numInSamples = capacity / sizeof(int16_t);
378
379 void* inBuffer[] = { (unsigned char *)data };
380 INT inBufferIds[] = { IN_AUDIO_DATA };
381 INT inBufferSize[] = { (INT)capacity };
382 INT inBufferElSize[] = { sizeof(int16_t) };
383
384 AACENC_BufDesc inBufDesc;
385 inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*);
386 inBufDesc.bufs = (void**)&inBuffer;
387 inBufDesc.bufferIdentifiers = inBufferIds;
388 inBufDesc.bufSizes = inBufferSize;
389 inBufDesc.bufElSizes = inBufferElSize;
390
391 void* outBuffer[] = { outPtr };
392 INT outBufferIds[] = { OUT_BITSTREAM_DATA };
393 INT outBufferSize[] = { 0 };
394 INT outBufferElSize[] = { sizeof(UCHAR) };
395
396 AACENC_BufDesc outBufDesc;
397 outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*);
398 outBufDesc.bufs = (void**)&outBuffer;
399 outBufDesc.bufferIdentifiers = outBufferIds;
400 outBufDesc.bufSizes = outBufferSize;
401 outBufDesc.bufElSizes = outBufferElSize;
402
403 AACENC_ERROR encoderErr = AACENC_OK;
404
405 class FillWork {
406 public:
407 FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
408 const std::shared_ptr<C2Buffer> &buffer)
409 : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {
410 }
411 ~FillWork() = default;
412
413 void operator()(const std::unique_ptr<C2Work> &work) {
414 work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
415 work->worklets.front()->output.buffers.clear();
416 work->worklets.front()->output.ordinal = mOrdinal;
417 work->workletsProcessed = 1u;
418 work->result = C2_OK;
419 if (mBuffer) {
420 work->worklets.front()->output.buffers.push_back(mBuffer);
421 }
422 ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
423 mOrdinal.timestamp.peekll(),
424 mOrdinal.frameIndex.peekll(),
425 mBuffer ? "" : "o");
426 }
427
428 private:
429 const uint32_t mFlags;
430 const C2WorkOrdinalStruct mOrdinal;
431 const std::shared_ptr<C2Buffer> mBuffer;
432 };
433
434 C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
435
436 while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
437 if (numFrames && !block) {
438 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
439 // TODO: error handling, proper usage, etc.
440 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
441 if (err != C2_OK) {
442 ALOGE("fetchLinearBlock failed : err = %d", err);
443 work->result = C2_NO_MEMORY;
444 return;
445 }
446
447 wView.reset(new C2WriteView(block->map().get()));
448 outPtr = wView->data();
449 outAvailable = wView->size();
450 --numFrames;
451 }
452
453 memset(&outargs, 0, sizeof(outargs));
454
455 outBuffer[0] = outPtr;
456 outBufferSize[0] = outAvailable;
457
458 encoderErr = aacEncEncode(mAACEncoder,
459 &inBufDesc,
460 &outBufDesc,
461 &inargs,
462 &outargs);
463
464 if (encoderErr == AACENC_OK) {
465 if (buffer) {
466 outOrdinal.frameIndex = mOutIndex++;
467 outOrdinal.timestamp = mInputTimeUs;
468 cloneAndSend(
469 inputIndex,
470 work,
471 FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
472 buffer.reset();
473 }
474
475 if (outargs.numOutBytes > 0) {
476 mInputSize = 0;
Wonsik Kim84889cb2019-01-03 17:07:54 -0800477 int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
478 + outargs.numInSamples;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800479 mInputTimeUs = work->input.ordinal.timestamp
480 + (consumed * 1000000ll / channelCount / sampleRate);
481 buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
482#if defined(LOG_NDEBUG) && !LOG_NDEBUG
483 hexdump(outPtr, std::min(outargs.numOutBytes, 256));
484#endif
485 outPtr = temp;
486 outAvailable = 0;
487 block.reset();
488 } else {
489 mInputSize += outargs.numInSamples * sizeof(int16_t);
490 }
491
492 if (outargs.numInSamples > 0) {
493 inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples;
494 inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
495 inargs.numInSamples -= outargs.numInSamples;
496 }
497 }
498 ALOGV("encoderErr = %d mInputSize = %zu inargs.numInSamples = %d, mInputTimeUs = %lld",
499 encoderErr, mInputSize, inargs.numInSamples, mInputTimeUs.peekll());
500 }
501
502 if (eos && inBufferSize[0] > 0) {
503 if (numFrames && !block) {
504 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
505 // TODO: error handling, proper usage, etc.
506 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
507 if (err != C2_OK) {
508 ALOGE("fetchLinearBlock failed : err = %d", err);
509 work->result = C2_NO_MEMORY;
510 return;
511 }
512
513 wView.reset(new C2WriteView(block->map().get()));
514 outPtr = wView->data();
515 outAvailable = wView->size();
516 --numFrames;
517 }
518
519 memset(&outargs, 0, sizeof(outargs));
520
521 outBuffer[0] = outPtr;
522 outBufferSize[0] = outAvailable;
523
524 // Flush
525 inargs.numInSamples = -1;
526
527 (void)aacEncEncode(mAACEncoder,
528 &inBufDesc,
529 &outBufDesc,
530 &inargs,
531 &outargs);
532 }
533
534 outOrdinal.frameIndex = mOutIndex++;
535 outOrdinal.timestamp = mInputTimeUs;
536 FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
537 outOrdinal, buffer)(work);
538}
539
540c2_status_t C2SoftAacEnc::drain(
541 uint32_t drainMode,
542 const std::shared_ptr<C2BlockPool> &pool) {
543 switch (drainMode) {
544 case DRAIN_COMPONENT_NO_EOS:
545 [[fallthrough]];
546 case NO_DRAIN:
547 // no-op
548 return C2_OK;
549 case DRAIN_CHAIN:
550 return C2_OMITTED;
551 case DRAIN_COMPONENT_WITH_EOS:
552 break;
553 default:
554 return C2_BAD_VALUE;
555 }
556
557 (void)pool;
558 mSentCodecSpecificData = false;
Wonsik Kim353e1672019-01-07 16:31:29 -0800559 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800560 mInputSize = 0u;
561
562 // TODO: we don't have any pending work at this time to drain.
563 return C2_OK;
564}
565
566class C2SoftAacEncFactory : public C2ComponentFactory {
567public:
568 C2SoftAacEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
569 GetCodec2PlatformComponentStore()->getParamReflector())) {
570 }
571
572 virtual c2_status_t createComponent(
573 c2_node_id_t id,
574 std::shared_ptr<C2Component>* const component,
575 std::function<void(C2Component*)> deleter) override {
576 *component = std::shared_ptr<C2Component>(
577 new C2SoftAacEnc(COMPONENT_NAME,
578 id,
579 std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
580 deleter);
581 return C2_OK;
582 }
583
584 virtual c2_status_t createInterface(
585 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
586 std::function<void(C2ComponentInterface*)> deleter) override {
587 *interface = std::shared_ptr<C2ComponentInterface>(
588 new SimpleInterface<C2SoftAacEnc::IntfImpl>(
589 COMPONENT_NAME, id, std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
590 deleter);
591 return C2_OK;
592 }
593
594 virtual ~C2SoftAacEncFactory() override = default;
595
596private:
597 std::shared_ptr<C2ReflectorHelper> mHelper;
598};
599
600} // namespace android
601
602extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
603 ALOGV("in %s", __func__);
604 return new ::android::C2SoftAacEncFactory();
605}
606
607extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
608 ALOGV("in %s", __func__);
609 delete factory;
610}