blob: 71eb1ac0cc845b2d74ef343c1289357c2c08bfe6 [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(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080040 DefineParam(mInputFormat, C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE)
41 .withConstValue(new C2StreamBufferTypeSetting::input(0u, C2BufferData::LINEAR))
Pawin Vongmasa36653902018-11-15 00:10:25 -080042 .build());
43
44 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080045 DefineParam(mOutputFormat, C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE)
46 .withConstValue(new C2StreamBufferTypeSetting::output(0u, C2BufferData::LINEAR))
Pawin Vongmasa36653902018-11-15 00:10:25 -080047 .build());
48
49 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080050 DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE)
51 .withConstValue(AllocSharedString<C2PortMediaTypeSetting::input>(
Pawin Vongmasa36653902018-11-15 00:10:25 -080052 MEDIA_MIMETYPE_AUDIO_RAW))
53 .build());
54
55 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080056 DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE)
57 .withConstValue(AllocSharedString<C2PortMediaTypeSetting::output>(
Pawin Vongmasa36653902018-11-15 00:10:25 -080058 MEDIA_MIMETYPE_AUDIO_AAC))
59 .build());
60
61 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080062 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
Pawin Vongmasa36653902018-11-15 00:10:25 -080063 .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(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080071 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
Pawin Vongmasa36653902018-11-15 00:10:25 -080072 .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(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080078 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
79 .withDefault(new C2StreamBitrateInfo::output(0u, 64000))
Pawin Vongmasa36653902018-11-15 00:10:25 -080080 .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:
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800128 std::shared_ptr<C2StreamBufferTypeSetting::input> mInputFormat;
129 std::shared_ptr<C2StreamBufferTypeSetting::output> mOutputFormat;
130 std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType;
131 std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800132 std::shared_ptr<C2StreamSampleRateInfo::input> mSampleRate;
133 std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800134 std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800135 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),
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700156 mInputTimeUs(0),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800157 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;
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700182 mInputTimeUs = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800183 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;
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700200 mInputTimeUs = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800201 return C2_OK;
202}
203
204static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
205 CHANNEL_MODE chMode = MODE_INVALID;
206 switch (nChannels) {
207 case 1: chMode = MODE_1; break;
208 case 2: chMode = MODE_2; break;
209 case 3: chMode = MODE_1_2; break;
210 case 4: chMode = MODE_1_2_1; break;
211 case 5: chMode = MODE_1_2_2; break;
212 case 6: chMode = MODE_1_2_2_1; break;
213 default: chMode = MODE_INVALID;
214 }
215 return chMode;
216}
217
218//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
219// if (profile == OMX_AUDIO_AACObjectLC) {
220// return AOT_AAC_LC;
221// } else if (profile == OMX_AUDIO_AACObjectHE) {
222// return AOT_SBR;
223// } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
224// return AOT_PS;
225// } else if (profile == OMX_AUDIO_AACObjectLD) {
226// return AOT_ER_AAC_LD;
227// } else if (profile == OMX_AUDIO_AACObjectELD) {
228// return AOT_ER_AAC_ELD;
229// } else {
230// ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
231// return AOT_AAC_LC;
232// }
233//}
234
235status_t C2SoftAacEnc::setAudioParams() {
236 // We call this whenever sample rate, number of channels, bitrate or SBR mode change
237 // in reponse to setParameter calls.
238
239 ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
240 mIntf->getSampleRate(), mIntf->getChannelCount(), mIntf->getBitrate(), mSBRMode, mSBRRatio);
241
242 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
243 ALOGE("Failed to set AAC encoder parameters");
244 return UNKNOWN_ERROR;
245 }
246
247 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mIntf->getSampleRate())) {
248 ALOGE("Failed to set AAC encoder parameters");
249 return UNKNOWN_ERROR;
250 }
251 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mIntf->getBitrate())) {
252 ALOGE("Failed to set AAC encoder parameters");
253 return UNKNOWN_ERROR;
254 }
255 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
256 getChannelMode(mIntf->getChannelCount()))) {
257 ALOGE("Failed to set AAC encoder parameters");
258 return UNKNOWN_ERROR;
259 }
260 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
261 ALOGE("Failed to set AAC encoder parameters");
262 return UNKNOWN_ERROR;
263 }
264
265 if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
266 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
267 ALOGE("Failed to set AAC encoder parameters");
268 return UNKNOWN_ERROR;
269 }
270 }
271
272 /* SBR ratio parameter configurations:
273 0: Default configuration wherein SBR ratio is configured depending on audio object type by
274 the FDK.
275 1: Downsampled SBR (default for ELD)
276 2: Dualrate SBR (default for HE-AAC)
277 */
278 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
279 ALOGE("Failed to set AAC encoder parameters");
280 return UNKNOWN_ERROR;
281 }
282
283 return OK;
284}
285
286void C2SoftAacEnc::process(
287 const std::unique_ptr<C2Work> &work,
288 const std::shared_ptr<C2BlockPool> &pool) {
289 // Initialize output work
290 work->result = C2_OK;
291 work->workletsProcessed = 1u;
292 work->worklets.front()->output.flags = work->input.flags;
293
294 if (mSignalledError) {
295 return;
296 }
297 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
298
299 uint32_t sampleRate = mIntf->getSampleRate();
300 uint32_t channelCount = mIntf->getChannelCount();
301
302 if (!mSentCodecSpecificData) {
303 // The very first thing we want to output is the codec specific
304 // data.
305
306 if (AACENC_OK != aacEncEncode(mAACEncoder, nullptr, nullptr, nullptr, nullptr)) {
307 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
308 mSignalledError = true;
309 work->result = C2_CORRUPTED;
310 return;
311 }
312
313 uint32_t bitrate = mIntf->getBitrate();
314 uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
315 if (bitrate != actualBitRate) {
316 ALOGW("Requested bitrate %u unsupported, using %u", bitrate, actualBitRate);
317 }
318
319 AACENC_InfoStruct encInfo;
320 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
321 ALOGE("Failed to get AAC encoder info");
322 mSignalledError = true;
323 work->result = C2_CORRUPTED;
324 return;
325 }
326
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800327 std::unique_ptr<C2StreamInitDataInfo::output> csd =
328 C2StreamInitDataInfo::output::AllocUnique(encInfo.confSize, 0u);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800329 if (!csd) {
330 ALOGE("CSD allocation failed");
331 mSignalledError = true;
332 work->result = C2_NO_MEMORY;
333 return;
334 }
335 memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
336 ALOGV("put csd");
337#if defined(LOG_NDEBUG) && !LOG_NDEBUG
338 hexdump(csd->m.value, csd->flexCount());
339#endif
340 work->worklets.front()->output.configUpdate.push_back(std::move(csd));
341
342 mOutBufferSize = encInfo.maxOutBufBytes;
343 mNumBytesPerInputFrame = encInfo.frameLength * channelCount * sizeof(int16_t);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800344
345 mSentCodecSpecificData = true;
346 }
347
348 uint8_t temp[1];
349 C2ReadView view = mDummyReadView;
350 const uint8_t *data = temp;
351 size_t capacity = 0u;
352 if (!work->input.buffers.empty()) {
353 view = work->input.buffers[0]->data().linearBlocks().front().map().get();
354 data = view.data();
355 capacity = view.capacity();
356 }
Wonsik Kim353e1672019-01-07 16:31:29 -0800357 if (!mInputTimeSet && capacity > 0) {
358 mInputTimeUs = work->input.ordinal.timestamp;
359 mInputTimeSet = true;
360 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800361
362 size_t numFrames = (capacity + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
363 / mNumBytesPerInputFrame;
364 ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu mNumBytesPerInputFrame = %u",
365 capacity, mInputSize, numFrames, mNumBytesPerInputFrame);
366
367 std::shared_ptr<C2LinearBlock> block;
368 std::shared_ptr<C2Buffer> buffer;
369 std::unique_ptr<C2WriteView> wView;
370 uint8_t *outPtr = temp;
371 size_t outAvailable = 0u;
372 uint64_t inputIndex = work->input.ordinal.frameIndex.peeku();
373
374 AACENC_InArgs inargs;
375 AACENC_OutArgs outargs;
376 memset(&inargs, 0, sizeof(inargs));
377 memset(&outargs, 0, sizeof(outargs));
378 inargs.numInSamples = capacity / sizeof(int16_t);
379
380 void* inBuffer[] = { (unsigned char *)data };
381 INT inBufferIds[] = { IN_AUDIO_DATA };
382 INT inBufferSize[] = { (INT)capacity };
383 INT inBufferElSize[] = { sizeof(int16_t) };
384
385 AACENC_BufDesc inBufDesc;
386 inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*);
387 inBufDesc.bufs = (void**)&inBuffer;
388 inBufDesc.bufferIdentifiers = inBufferIds;
389 inBufDesc.bufSizes = inBufferSize;
390 inBufDesc.bufElSizes = inBufferElSize;
391
392 void* outBuffer[] = { outPtr };
393 INT outBufferIds[] = { OUT_BITSTREAM_DATA };
394 INT outBufferSize[] = { 0 };
395 INT outBufferElSize[] = { sizeof(UCHAR) };
396
397 AACENC_BufDesc outBufDesc;
398 outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*);
399 outBufDesc.bufs = (void**)&outBuffer;
400 outBufDesc.bufferIdentifiers = outBufferIds;
401 outBufDesc.bufSizes = outBufferSize;
402 outBufDesc.bufElSizes = outBufferElSize;
403
404 AACENC_ERROR encoderErr = AACENC_OK;
405
406 class FillWork {
407 public:
408 FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
409 const std::shared_ptr<C2Buffer> &buffer)
410 : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {
411 }
412 ~FillWork() = default;
413
414 void operator()(const std::unique_ptr<C2Work> &work) {
415 work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
416 work->worklets.front()->output.buffers.clear();
417 work->worklets.front()->output.ordinal = mOrdinal;
418 work->workletsProcessed = 1u;
419 work->result = C2_OK;
420 if (mBuffer) {
421 work->worklets.front()->output.buffers.push_back(mBuffer);
422 }
423 ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
424 mOrdinal.timestamp.peekll(),
425 mOrdinal.frameIndex.peekll(),
426 mBuffer ? "" : "o");
427 }
428
429 private:
430 const uint32_t mFlags;
431 const C2WorkOrdinalStruct mOrdinal;
432 const std::shared_ptr<C2Buffer> mBuffer;
433 };
434
435 C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
436
437 while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
438 if (numFrames && !block) {
439 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
440 // TODO: error handling, proper usage, etc.
441 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
442 if (err != C2_OK) {
443 ALOGE("fetchLinearBlock failed : err = %d", err);
444 work->result = C2_NO_MEMORY;
445 return;
446 }
447
448 wView.reset(new C2WriteView(block->map().get()));
449 outPtr = wView->data();
450 outAvailable = wView->size();
451 --numFrames;
452 }
453
454 memset(&outargs, 0, sizeof(outargs));
455
456 outBuffer[0] = outPtr;
457 outBufferSize[0] = outAvailable;
458
459 encoderErr = aacEncEncode(mAACEncoder,
460 &inBufDesc,
461 &outBufDesc,
462 &inargs,
463 &outargs);
464
465 if (encoderErr == AACENC_OK) {
466 if (buffer) {
467 outOrdinal.frameIndex = mOutIndex++;
468 outOrdinal.timestamp = mInputTimeUs;
469 cloneAndSend(
470 inputIndex,
471 work,
472 FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
473 buffer.reset();
474 }
475
476 if (outargs.numOutBytes > 0) {
477 mInputSize = 0;
Wonsik Kim84889cb2019-01-03 17:07:54 -0800478 int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
479 + outargs.numInSamples;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800480 mInputTimeUs = work->input.ordinal.timestamp
481 + (consumed * 1000000ll / channelCount / sampleRate);
482 buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
483#if defined(LOG_NDEBUG) && !LOG_NDEBUG
484 hexdump(outPtr, std::min(outargs.numOutBytes, 256));
485#endif
486 outPtr = temp;
487 outAvailable = 0;
488 block.reset();
489 } else {
490 mInputSize += outargs.numInSamples * sizeof(int16_t);
491 }
492
493 if (outargs.numInSamples > 0) {
494 inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples;
495 inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
496 inargs.numInSamples -= outargs.numInSamples;
497 }
498 }
499 ALOGV("encoderErr = %d mInputSize = %zu inargs.numInSamples = %d, mInputTimeUs = %lld",
500 encoderErr, mInputSize, inargs.numInSamples, mInputTimeUs.peekll());
501 }
502
503 if (eos && inBufferSize[0] > 0) {
504 if (numFrames && !block) {
505 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
506 // TODO: error handling, proper usage, etc.
507 c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
508 if (err != C2_OK) {
509 ALOGE("fetchLinearBlock failed : err = %d", err);
510 work->result = C2_NO_MEMORY;
511 return;
512 }
513
514 wView.reset(new C2WriteView(block->map().get()));
515 outPtr = wView->data();
516 outAvailable = wView->size();
517 --numFrames;
518 }
519
520 memset(&outargs, 0, sizeof(outargs));
521
522 outBuffer[0] = outPtr;
523 outBufferSize[0] = outAvailable;
524
525 // Flush
526 inargs.numInSamples = -1;
527
528 (void)aacEncEncode(mAACEncoder,
529 &inBufDesc,
530 &outBufDesc,
531 &inargs,
532 &outargs);
533 }
534
535 outOrdinal.frameIndex = mOutIndex++;
536 outOrdinal.timestamp = mInputTimeUs;
537 FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
538 outOrdinal, buffer)(work);
539}
540
541c2_status_t C2SoftAacEnc::drain(
542 uint32_t drainMode,
543 const std::shared_ptr<C2BlockPool> &pool) {
544 switch (drainMode) {
545 case DRAIN_COMPONENT_NO_EOS:
546 [[fallthrough]];
547 case NO_DRAIN:
548 // no-op
549 return C2_OK;
550 case DRAIN_CHAIN:
551 return C2_OMITTED;
552 case DRAIN_COMPONENT_WITH_EOS:
553 break;
554 default:
555 return C2_BAD_VALUE;
556 }
557
558 (void)pool;
559 mSentCodecSpecificData = false;
Wonsik Kim353e1672019-01-07 16:31:29 -0800560 mInputTimeSet = false;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800561 mInputSize = 0u;
Wonsik Kim8ead39d2019-04-01 13:56:12 -0700562 mInputTimeUs = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800563
564 // TODO: we don't have any pending work at this time to drain.
565 return C2_OK;
566}
567
568class C2SoftAacEncFactory : public C2ComponentFactory {
569public:
570 C2SoftAacEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
571 GetCodec2PlatformComponentStore()->getParamReflector())) {
572 }
573
574 virtual c2_status_t createComponent(
575 c2_node_id_t id,
576 std::shared_ptr<C2Component>* const component,
577 std::function<void(C2Component*)> deleter) override {
578 *component = std::shared_ptr<C2Component>(
579 new C2SoftAacEnc(COMPONENT_NAME,
580 id,
581 std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
582 deleter);
583 return C2_OK;
584 }
585
586 virtual c2_status_t createInterface(
587 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
588 std::function<void(C2ComponentInterface*)> deleter) override {
589 *interface = std::shared_ptr<C2ComponentInterface>(
590 new SimpleInterface<C2SoftAacEnc::IntfImpl>(
591 COMPONENT_NAME, id, std::make_shared<C2SoftAacEnc::IntfImpl>(mHelper)),
592 deleter);
593 return C2_OK;
594 }
595
596 virtual ~C2SoftAacEncFactory() override = default;
597
598private:
599 std::shared_ptr<C2ReflectorHelper> mHelper;
600};
601
602} // namespace android
603
604extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
605 ALOGV("in %s", __func__);
606 return new ::android::C2SoftAacEncFactory();
607}
608
609extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
610 ALOGV("in %s", __func__);
611 delete factory;
612}