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