blob: 7efc7f1511e5866cd8e440edbfeec92a01c69cf9 [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
Rakesh Kumar66d9d062019-03-12 17:46:17 +053032namespace {
33
34constexpr char COMPONENT_NAME[] = "c2.android.aac.encoder";
35
36} // namespace
37
38class C2SoftAacEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
Pawin Vongmasa36653902018-11-15 00:10:25 -080039public:
40 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
Rakesh Kumar66d9d062019-03-12 17:46:17 +053041 : SimpleInterface<void>::BaseParams(
42 helper,
43 COMPONENT_NAME,
44 C2Component::KIND_ENCODER,
45 C2Component::DOMAIN_AUDIO,
46 MEDIA_MIMETYPE_AUDIO_AAC) {
47 noPrivateBuffers();
48 noInputReferences();
49 noOutputReferences();
50 noInputLatency();
51 noTimeStretch();
Pawin Vongmasa36653902018-11-15 00:10:25 -080052 setDerivedInstance(this);
53
54 addParameter(
Rakesh Kumar66d9d062019-03-12 17:46:17 +053055 DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
56 .withConstValue(new C2ComponentAttributesSetting(
57 C2Component::ATTRIB_IS_TEMPORAL))
Pawin Vongmasa36653902018-11-15 00:10:25 -080058 .build());
59
60 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080061 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
Pawin Vongmasa36653902018-11-15 00:10:25 -080062 .withDefault(new C2StreamSampleRateInfo::input(0u, 44100))
63 .withFields({C2F(mSampleRate, value).oneOf({
64 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
65 })})
66 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
67 .build());
68
69 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080070 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
Pawin Vongmasa36653902018-11-15 00:10:25 -080071 .withDefault(new C2StreamChannelCountInfo::input(0u, 1))
72 .withFields({C2F(mChannelCount, value).inRange(1, 6)})
73 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
74 .build());
75
76 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080077 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
78 .withDefault(new C2StreamBitrateInfo::output(0u, 64000))
Pawin Vongmasa36653902018-11-15 00:10:25 -080079 .withFields({C2F(mBitrate, value).inRange(8000, 960000)})
80 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
81 .build());
82
83 addParameter(
84 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
85 .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 8192))
86 .calculatedAs(MaxBufSizeCalculator, mChannelCount)
87 .build());
88
89 addParameter(
90 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
91 .withDefault(new C2StreamProfileLevelInfo::output(0u,
92 C2Config::PROFILE_AAC_LC, C2Config::LEVEL_UNUSED))
93 .withFields({
94 C2F(mProfileLevel, profile).oneOf({
95 C2Config::PROFILE_AAC_LC,
96 C2Config::PROFILE_AAC_HE,
97 C2Config::PROFILE_AAC_HE_PS,
98 C2Config::PROFILE_AAC_LD,
99 C2Config::PROFILE_AAC_ELD}),
100 C2F(mProfileLevel, level).oneOf({
101 C2Config::LEVEL_UNUSED
102 })
103 })
104 .withSetter(ProfileLevelSetter)
105 .build());
106 }
107
108 uint32_t getSampleRate() const { return mSampleRate->value; }
109 uint32_t getChannelCount() const { return mChannelCount->value; }
110 uint32_t getBitrate() const { return mBitrate->value; }
111 static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output> &me) {
112 (void)mayBlock;
113 (void)me; // TODO: validate
114 return C2R::Ok();
115 }
116
117 static C2R MaxBufSizeCalculator(
118 bool mayBlock,
119 C2P<C2StreamMaxBufferSizeInfo::input> &me,
120 const C2P<C2StreamChannelCountInfo::input> &channelCount) {
121 (void)mayBlock;
122 me.set().value = 1024 * sizeof(short) * channelCount.v.value;
123 return C2R::Ok();
124 }
125
126private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800127 std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate;
128 std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800129 std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800130 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
131 std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
132};
133
Pawin Vongmasa36653902018-11-15 00:10:25 -0800134C2SoftAacEnc::C2SoftAacEnc(
135 const char *name,
136 c2_node_id_t id,
137 const std::shared_ptr<IntfImpl> &intfImpl)
138 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
139 mIntf(intfImpl),
140 mAACEncoder(nullptr),
141 mSBRMode(-1),
142 mSBRRatio(0),
143 mAACProfile(AOT_AAC_LC),
144 mNumBytesPerInputFrame(0u),
145 mOutBufferSize(0u),
146 mSentCodecSpecificData(false),
Wonsik Kim353e1672019-01-07 16:31:29 -0800147 mInputTimeSet(false),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800148 mInputSize(0),
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700149 mInputTimeUs(0),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800150 mSignalledError(false),
151 mOutIndex(0u) {
152}
153
154C2SoftAacEnc::~C2SoftAacEnc() {
155 onReset();
156}
157
158c2_status_t C2SoftAacEnc::onInit() {
159 status_t err = initEncoder();
160 return err == OK ? C2_OK : C2_CORRUPTED;
161}
162
163status_t C2SoftAacEnc::initEncoder() {
164 if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
165 ALOGE("Failed to init AAC encoder");
166 return UNKNOWN_ERROR;
167 }
168 return setAudioParams();
169}
170
171c2_status_t C2SoftAacEnc::onStop() {
172 mSentCodecSpecificData = false;
Wonsik Kim353e1672019-01-07 16:31:29 -0800173 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800174 mInputSize = 0u;
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700175 mInputTimeUs = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800176 mSignalledError = false;
177 return C2_OK;
178}
179
180void C2SoftAacEnc::onReset() {
181 (void)onStop();
182 aacEncClose(&mAACEncoder);
183}
184
185void C2SoftAacEnc::onRelease() {
186 // no-op
187}
188
189c2_status_t C2SoftAacEnc::onFlush_sm() {
190 mSentCodecSpecificData = false;
Wonsik Kim353e1672019-01-07 16:31:29 -0800191 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800192 mInputSize = 0u;
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700193 mInputTimeUs = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800194 return C2_OK;
195}
196
197static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
198 CHANNEL_MODE chMode = MODE_INVALID;
199 switch (nChannels) {
200 case 1: chMode = MODE_1; break;
201 case 2: chMode = MODE_2; break;
202 case 3: chMode = MODE_1_2; break;
203 case 4: chMode = MODE_1_2_1; break;
204 case 5: chMode = MODE_1_2_2; break;
205 case 6: chMode = MODE_1_2_2_1; break;
206 default: chMode = MODE_INVALID;
207 }
208 return chMode;
209}
210
211//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
212// if (profile == OMX_AUDIO_AACObjectLC) {
213// return AOT_AAC_LC;
214// } else if (profile == OMX_AUDIO_AACObjectHE) {
215// return AOT_SBR;
216// } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
217// return AOT_PS;
218// } else if (profile == OMX_AUDIO_AACObjectLD) {
219// return AOT_ER_AAC_LD;
220// } else if (profile == OMX_AUDIO_AACObjectELD) {
221// return AOT_ER_AAC_ELD;
222// } else {
223// ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
224// return AOT_AAC_LC;
225// }
226//}
227
228status_t C2SoftAacEnc::setAudioParams() {
229 // We call this whenever sample rate, number of channels, bitrate or SBR mode change
230 // in reponse to setParameter calls.
231
232 ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
233 mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(), mSBRMode, mSBRRatio);
234
235 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
236 ALOGE("Failed to set AAC encoder parameters");
237 return UNKNOWN_ERROR;
238 }
239
240 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mIntf->getSampleRate())) {
241 ALOGE("Failed to set AAC encoder parameters");
242 return UNKNOWN_ERROR;
243 }
244 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mIntf->getBitrate())) {
245 ALOGE("Failed to set AAC encoder parameters");
246 return UNKNOWN_ERROR;
247 }
248 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
249 getChannelMode(mIntf->getChannelCount()))) {
250 ALOGE("Failed to set AAC encoder parameters");
251 return UNKNOWN_ERROR;
252 }
253 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
254 ALOGE("Failed to set AAC encoder parameters");
255 return UNKNOWN_ERROR;
256 }
257
258 if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
259 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
260 ALOGE("Failed to set AAC encoder parameters");
261 return UNKNOWN_ERROR;
262 }
263 }
264
265 /* SBR ratio parameter configurations:
266 0: Default configuration wherein SBR ratio is configured depending on audio object type by
267 the FDK.
268 1: Downsampled SBR (default for ELD)
269 2: Dualrate SBR (default for HE-AAC)
270 */
271 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
272 ALOGE("Failed to set AAC encoder parameters");
273 return UNKNOWN_ERROR;
274 }
275
276 return OK;
277}
278
279void C2SoftAacEnc::process(
280 const std::unique_ptr<C2Work> &work,
281 const std::shared_ptr<C2BlockPool> &pool) {
282 // Initialize output work
283 work->result = C2_OK;
284 work->workletsProcessed = 1u;
285 work->worklets.front()->output.flags = work->input.flags;
286
287 if (mSignalledError) {
288 return;
289 }
290 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
291
292 uint32_t sampleRate = mIntf->getSampleRate();
293 uint32_t channelCount = mIntf->getChannelCount();
294
295 if (!mSentCodecSpecificData) {
296 // The very first thing we want to output is the codec specific
297 // data.
298
299 if (AACENC_OK != aacEncEncode(mAACEncoder, nullptr, nullptr, nullptr, nullptr)) {
300 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
301 mSignalledError = true;
302 work->result = C2_CORRUPTED;
303 return;
304 }
305
306 uint32_t bitrate = mIntf->getBitrate();
307 uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
308 if (bitrate != actualBitRate) {
309 ALOGW("Requested bitrate %u unsupported, using %u", bitrate, actualBitRate);
310 }
311
312 AACENC_InfoStruct encInfo;
313 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
314 ALOGE("Failed to get AAC encoder info");
315 mSignalledError = true;
316 work->result = C2_CORRUPTED;
317 return;
318 }
319
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800320 std::unique_ptr<C2StreamInitDataInfo::output> csd =
321 C2StreamInitDataInfo::output::AllocUnique(encInfo.confSize, 0u);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800322 if (!csd) {
323 ALOGE("CSD allocation failed");
324 mSignalledError = true;
325 work->result = C2_NO_MEMORY;
326 return;
327 }
328 memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
329 ALOGV("put csd");
330#if defined(LOG_NDEBUG) && !LOG_NDEBUG
331 hexdump(csd->m.value, csd->flexCount());
332#endif
333 work->worklets.front()->output.configUpdate.push_back(std::move(csd));
334
335 mOutBufferSize = encInfo.maxOutBufBytes;
336 mNumBytesPerInputFrame = encInfo.frameLength * channelCount * sizeof(int16_t);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800337
338 mSentCodecSpecificData = true;
339 }
340
341 uint8_t temp[1];
342 C2ReadView view = mDummyReadView;
343 const uint8_t *data = temp;
344 size_t capacity = 0u;
345 if (!work->input.buffers.empty()) {
346 view = work->input.buffers[0]->data().linearBlocks().front().map().get();
347 data = view.data();
348 capacity = view.capacity();
349 }
Wonsik Kim353e1672019-01-07 16:31:29 -0800350 if (!mInputTimeSet && capacity > 0) {
351 mInputTimeUs = work->input.ordinal.timestamp;
352 mInputTimeSet = true;
353 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800354
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;
Wonsik Kim84889cb2019-01-03 17:07:54 -0800471 int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
472 + outargs.numInSamples;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800473 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
534c2_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;
Wonsik Kim353e1672019-01-07 16:31:29 -0800553 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800554 mInputSize = 0u;
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700555 mInputTimeUs = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800556
557 // TODO: we don't have any pending work at this time to drain.
558 return C2_OK;
559}
560
561class C2SoftAacEncFactory : public C2ComponentFactory {
562public:
563 C2SoftAacEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
564 GetCodec2PlatformComponentStore()->getParamReflector())) {
565 }
566
567 virtual c2_status_t createComponent(
568 c2_node_id_t id,
569 std::shared_ptr<C2Component>* const component,
570 std::function<void(C2Component*)> deleter) override {
571 *component = std::shared_ptr<C2Component>(
572 new C2SoftAacEnc(COMPONENT_NAME,
573 id,
574 std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
575 deleter);
576 return C2_OK;
577 }
578
579 virtual c2_status_t createInterface(
580 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
581 std::function<void(C2ComponentInterface*)> deleter) override {
582 *interface = std::shared_ptr<C2ComponentInterface>(
583 new SimpleInterface<C2SoftAacEnc::IntfImpl>(
584 COMPONENT_NAME, id, std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
585 deleter);
586 return C2_OK;
587 }
588
589 virtual ~C2SoftAacEncFactory() override = default;
590
591private:
592 std::shared_ptr<C2ReflectorHelper> mHelper;
593};
594
595} // namespace android
596
597extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
598 ALOGV("in %s", __func__);
599 return new ::android::C2SoftAacEncFactory();
600}
601
602extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
603 ALOGV("in %s", __func__);
604 delete factory;
605}