1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ffmpeg_aac_encoder_plugin.h"
17 #include <cstring>
18 #include <iostream>
19 #include <map>
20 #include <set>
21 #include <string>
22 #include "avcodec_codec_name.h"
23 #include "common/log.h"
24 #include "avcodec_log.h"
25 #include "osal/utils/util.h"
26
27 namespace {
28 using namespace OHOS::Media;
29 using namespace OHOS::Media::Plugins;
30 using namespace Ffmpeg;
31
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_AUDIO, "HiStreamer" };
34 constexpr int32_t INPUT_BUFFER_SIZE_DEFAULT = 4 * 1024 * 8;
35 constexpr int32_t OUTPUT_BUFFER_SIZE_DEFAULT = 8192;
36 constexpr int32_t ADTS_HEADER_SIZE = 7;
37 constexpr uint8_t SAMPLE_FREQUENCY_INDEX_DEFAULT = 4;
38 constexpr int32_t MIN_CHANNELS = 1;
39 constexpr int32_t MAX_CHANNELS = 8;
40 constexpr int32_t INVALID_CHANNELS = 7;
41 constexpr int32_t AAC_MIN_BIT_RATE = 1;
42 constexpr int32_t AAC_DEFAULT_BIT_RATE = 128000;
43 constexpr int32_t AAC_MAX_BIT_RATE = 500000;
44 constexpr int64_t FRAMES_PER_SECOND = 1000 / 20;
45 constexpr int32_t BUFFER_FLAG_EOS = 0x00000001;
46 constexpr int32_t NS_PER_US = 1000;
47 constexpr int32_t AAC_FRAME_SIZE = 1024;
48 constexpr int32_t CORRECTION_SAMPLE_RATE = 8000;
49 constexpr int32_t CORRECTION_BIT_RATE = 70000;
50 constexpr int32_t CORRECTION_CHANNEL_COUNT = 2;
51 constexpr float Q_SCALE = 1.2f;
52 static std::map<int32_t, uint8_t> sampleFreqMap = {{96000, 0}, {88200, 1}, {64000, 2}, {48000, 3}, {44100, 4},
53 {32000, 5}, {24000, 6}, {22050, 7}, {16000, 8}, {12000, 9},
54 {11025, 10}, {8000, 11}, {7350, 12}};
55
56 static std::set<AudioSampleFormat> supportedSampleFormats = {
57 AudioSampleFormat::SAMPLE_S16LE,
58 AudioSampleFormat::SAMPLE_S32LE,
59 AudioSampleFormat::SAMPLE_F32LE,
60 };
61 static std::map<int32_t, int64_t> channelLayoutMap = {{1, AV_CH_LAYOUT_MONO}, {2, AV_CH_LAYOUT_STEREO},
62 {3, AV_CH_LAYOUT_SURROUND}, {4, AV_CH_LAYOUT_4POINT0},
63 {5, AV_CH_LAYOUT_5POINT0_BACK}, {6, AV_CH_LAYOUT_5POINT1_BACK},
64 {7, AV_CH_LAYOUT_7POINT0}, {8, AV_CH_LAYOUT_7POINT1}};
65 } // namespace
66 } // namespace
67
68 namespace OHOS {
69 namespace Media {
70 namespace Plugins {
71 namespace Ffmpeg {
FFmpegAACEncoderPlugin(const std::string & name)72 FFmpegAACEncoderPlugin::FFmpegAACEncoderPlugin(const std::string& name)
73 : CodecPlugin(std::move(name)),
74 needResample_(false),
75 codecContextValid_(false),
76 avCodec_(nullptr),
77 avCodecContext_(nullptr),
78 fifo_(nullptr),
79 cachedFrame_(nullptr),
80 avPacket_(nullptr),
81 prevPts_(0),
82 resample_(nullptr),
83 srcFmt_(AVSampleFormat::AV_SAMPLE_FMT_NONE),
84 audioSampleFormat_(AudioSampleFormat::INVALID_WIDTH),
85 srcLayout_(AudioChannelLayout::UNKNOWN),
86 channels_(MIN_CHANNELS),
87 sampleRate_(0),
88 bitRate_(0),
89 maxInputSize_(-1),
90 maxOutputSize_(-1),
91 outfile(nullptr)
92 {
93 }
94
~FFmpegAACEncoderPlugin()95 FFmpegAACEncoderPlugin::~FFmpegAACEncoderPlugin()
96 {
97 CloseCtxLocked();
98 }
99
GetAdtsHeader(std::string & adtsHeader,int32_t & headerSize,std::shared_ptr<AVCodecContext> ctx,int aacLength)100 Status FFmpegAACEncoderPlugin::GetAdtsHeader(std::string &adtsHeader, int32_t &headerSize,
101 std::shared_ptr<AVCodecContext> ctx, int aacLength)
102 {
103 uint8_t freqIdx = SAMPLE_FREQUENCY_INDEX_DEFAULT; // 0: 96000 Hz 3: 48000 Hz 4: 44100 Hz
104 auto iter = sampleFreqMap.find(ctx->sample_rate);
105 if (iter != sampleFreqMap.end()) {
106 freqIdx = iter->second;
107 }
108 uint8_t chanCfg = static_cast<uint8_t>(ctx->channels);
109 uint32_t frameLength = static_cast<uint32_t>(aacLength + ADTS_HEADER_SIZE);
110 uint8_t profile = static_cast<uint8_t>(ctx->profile);
111 adtsHeader += 0xFF;
112 adtsHeader += 0xF1;
113 adtsHeader += ((profile) << 0x6) + (freqIdx << 0x2) + (chanCfg >> 0x2);
114 adtsHeader += (((chanCfg & 0x3) << 0x6) + (frameLength >> 0xB));
115 adtsHeader += ((frameLength & 0x7FF) >> 0x3);
116 adtsHeader += (((frameLength & 0x7) << 0x5) + 0x1F);
117 adtsHeader += 0xFC;
118 headerSize = ADTS_HEADER_SIZE;
119
120 return Status::OK;
121 }
122
CheckSampleRate(const int sampleRate)123 bool FFmpegAACEncoderPlugin::CheckSampleRate(const int sampleRate)
124 {
125 return sampleFreqMap.find(sampleRate) != sampleFreqMap.end() ? true : false;
126 }
127
CheckSampleFormat()128 bool FFmpegAACEncoderPlugin::CheckSampleFormat()
129 {
130 if (supportedSampleFormats.find(audioSampleFormat_) == supportedSampleFormats.end()) {
131 MEDIA_LOG_E("input sample format not supported,srcFmt_=%{public}d", (int32_t)srcFmt_);
132 return false;
133 }
134 AudioSampleFormat2AVSampleFormat(audioSampleFormat_, srcFmt_);
135 MEDIA_LOG_E("AUDIO_SAMPLE_FORMAT found,srcFmt:%{public}d to "
136 "ffmpeg-srcFmt_:%{public}d ",
137 (int32_t)audioSampleFormat_, (int32_t)srcFmt_);
138 needResample_ = CheckResample();
139 return true;
140 }
141
CheckChannelLayout()142 bool FFmpegAACEncoderPlugin::CheckChannelLayout()
143 {
144 uint64_t ffmpegChlayout = FFMpegConverter::ConvertOHAudioChannelLayoutToFFMpeg(
145 static_cast<AudioChannelLayout>(srcLayout_));
146 // channel layout not available
147 CHECK_AND_RETURN_RET_LOG(av_get_channel_layout_nb_channels(ffmpegChlayout) == channels_, false,
148 "channel layout channels mismatch");
149 return true;
150 }
151
CheckBitRate() const152 bool FFmpegAACEncoderPlugin::CheckBitRate() const
153 {
154 if (bitRate_ < AAC_MIN_BIT_RATE || bitRate_ > AAC_MAX_BIT_RATE) {
155 MEDIA_LOG_E("parameter bit_rate illegal");
156 return false;
157 }
158 return true;
159 }
160
CheckFormat()161 bool FFmpegAACEncoderPlugin::CheckFormat()
162 {
163 if (!CheckSampleFormat()) {
164 MEDIA_LOG_E("sampleFormat not supported");
165 return false;
166 }
167
168 if (!CheckBitRate()) {
169 MEDIA_LOG_E("bitRate not supported");
170 return false;
171 }
172
173 if (!CheckSampleRate(sampleRate_)) {
174 MEDIA_LOG_E("sample rate not supported");
175 return false;
176 }
177
178 if (channels_ < MIN_CHANNELS || channels_ > MAX_CHANNELS || channels_ == INVALID_CHANNELS) {
179 MEDIA_LOG_E("channels not supported");
180 return false;
181 }
182
183 if (!CheckChannelLayout()) {
184 MEDIA_LOG_E("channelLayout not supported");
185 return false;
186 }
187
188 return true;
189 }
190
AudioSampleFormat2AVSampleFormat(const AudioSampleFormat & audioFmt,AVSampleFormat & fmt)191 bool FFmpegAACEncoderPlugin::AudioSampleFormat2AVSampleFormat(const AudioSampleFormat &audioFmt, AVSampleFormat &fmt)
192 {
193 /* AudioSampleFormat to AVSampleFormat */
194 static const std::unordered_map<AudioSampleFormat, AVSampleFormat> formatTable = {
195 {AudioSampleFormat::SAMPLE_U8, AVSampleFormat::AV_SAMPLE_FMT_U8},
196 {AudioSampleFormat::SAMPLE_S16LE, AVSampleFormat::AV_SAMPLE_FMT_S16},
197 {AudioSampleFormat::SAMPLE_S32LE, AVSampleFormat::AV_SAMPLE_FMT_S32},
198 {AudioSampleFormat::SAMPLE_F32LE, AVSampleFormat::AV_SAMPLE_FMT_FLT},
199 {AudioSampleFormat::SAMPLE_U8P, AVSampleFormat::AV_SAMPLE_FMT_U8P},
200 {AudioSampleFormat::SAMPLE_S16P, AVSampleFormat::AV_SAMPLE_FMT_S16P},
201 {AudioSampleFormat::SAMPLE_F32P, AVSampleFormat::AV_SAMPLE_FMT_FLTP},
202 };
203
204 fmt = formatTable.at(audioFmt);
205 return true;
206 }
207
Init()208 Status FFmpegAACEncoderPlugin::Init()
209 {
210 MEDIA_LOG_I("Init enter");
211 return Status::OK;
212 }
213
Start()214 Status FFmpegAACEncoderPlugin::Start()
215 {
216 MEDIA_LOG_I("Start enter");
217 Status status = AllocateContext("aac");
218 CHECK_AND_RETURN_RET_LOG(status == Status::OK, status, "Allocat aac context failed, status = %{public}d", status);
219
220 CHECK_AND_RETURN_RET_LOG(CheckFormat(), Status::ERROR_INVALID_PARAMETER, "Format check failed.");
221 (void)InitContext();
222
223 status = OpenContext();
224 CHECK_AND_RETURN_RET_LOG(status == Status::OK, status, "Open context failed, status = %{public}d", status);
225
226 status = InitFrame();
227 CHECK_AND_RETURN_RET_LOG(status == Status::OK, status, "Init frame failed, status = %{public}d", status);
228
229 return Status::OK;
230 }
231
QueueInputBuffer(const std::shared_ptr<AVBuffer> & inputBuffer)232 Status FFmpegAACEncoderPlugin::QueueInputBuffer(const std::shared_ptr<AVBuffer> &inputBuffer)
233 {
234 auto memory = inputBuffer->memory_;
235 if (memory == nullptr) {
236 return Status::ERROR_INVALID_DATA;
237 }
238 if (memory->GetSize() == 0 && !(inputBuffer->flag_ & BUFFER_FLAG_EOS)) {
239 MEDIA_LOG_E("size is 0, but flag is not 1");
240 return Status::ERROR_INVALID_DATA;
241 }
242 Status ret;
243 {
244 std::lock_guard<std::mutex> lock(avMutex_);
245 if (avCodecContext_ == nullptr) {
246 return Status::ERROR_WRONG_STATE;
247 }
248 ret = PushInFifo(inputBuffer);
249 if (ret == Status::OK) {
250 std::lock_guard<std::mutex> l(bufferMetaMutex_);
251 if (inputBuffer->meta_ == nullptr) {
252 MEDIA_LOG_E("encoder input buffer or meta is nullptr");
253 return Status::ERROR_INVALID_DATA;
254 }
255 bufferMeta_ = inputBuffer->meta_;
256 dataCallback_->OnInputBufferDone(inputBuffer);
257 ret = Status::OK;
258 }
259 }
260 return ret;
261 }
262
QueueOutputBuffer(std::shared_ptr<AVBuffer> & outputBuffer)263 Status FFmpegAACEncoderPlugin::QueueOutputBuffer(std::shared_ptr<AVBuffer> &outputBuffer)
264 {
265 if (!outputBuffer) {
266 MEDIA_LOG_E("queue out buffer is nullptr.");
267 return Status::ERROR_INVALID_PARAMETER;
268 }
269 std::lock_guard<std::mutex> lock(avMutex_);
270 if (avCodecContext_ == nullptr) {
271 return Status::ERROR_WRONG_STATE;
272 }
273 outBuffer_ = outputBuffer;
274 Status ret = SendOutputBuffer(outputBuffer);
275 return ret;
276 }
277
ReceivePacketSucc(std::shared_ptr<AVBuffer> & outBuffer)278 Status FFmpegAACEncoderPlugin::ReceivePacketSucc(std::shared_ptr<AVBuffer> &outBuffer)
279 {
280 int32_t headerSize = 0;
281 auto memory = outBuffer->memory_;
282 std::string header;
283 GetAdtsHeader(header, headerSize, avCodecContext_, avPacket_->size);
284 if (headerSize == 0) {
285 MEDIA_LOG_E("Get header failed.");
286 return Status::ERROR_UNKNOWN;
287 }
288 int32_t writeBytes = memory->Write(
289 reinterpret_cast<uint8_t *>(const_cast<char *>(header.c_str())), headerSize, 0);
290 if (writeBytes < headerSize) {
291 MEDIA_LOG_E("Write header failed");
292 return Status::ERROR_UNKNOWN;
293 }
294
295 int32_t outputSize = avPacket_->size + headerSize;
296 CHECK_AND_RETURN_RET_LOG(memory->GetCapacity() >= outputSize, Status::ERROR_NO_MEMORY,
297 "Output buffer capacity is not enough");
298
299 auto len = memory->Write(avPacket_->data, avPacket_->size, headerSize);
300 if (len < avPacket_->size) {
301 MEDIA_LOG_E("write packet data failed, len = %{public}d", len);
302 return Status::ERROR_UNKNOWN;
303 }
304
305 // how get perfect pts with upstream pts(us)
306 outBuffer->duration_ = ConvertTimeFromFFmpeg(avPacket_->duration, avCodecContext_->time_base) / NS_PER_US;
307 // adjust ffmpeg duration with sample rate
308 outBuffer->pts_ = ((INT64_MAX - prevPts_) < avPacket_->duration)
309 ? (outBuffer->duration_ - (INT64_MAX - prevPts_))
310 : (prevPts_ + outBuffer->duration_);
311 prevPts_ = outBuffer->pts_;
312 return Status::OK;
313 }
314
ReceiveBuffer(std::shared_ptr<AVBuffer> & outBuffer)315 Status FFmpegAACEncoderPlugin::ReceiveBuffer(std::shared_ptr<AVBuffer> &outBuffer)
316 {
317 MEDIA_LOG_D("ReceiveBuffer enter");
318 (void)memset_s(avPacket_.get(), sizeof(AVPacket), 0, sizeof(AVPacket));
319 auto ret = avcodec_receive_packet(avCodecContext_.get(), avPacket_.get());
320 Status status;
321 if (ret >= 0) {
322 MEDIA_LOG_D("receive one packet");
323 status = ReceivePacketSucc(outBuffer);
324 } else if (ret == AVERROR_EOF) {
325 outBuffer->flag_ = BUFFER_FLAG_EOS;
326 avcodec_flush_buffers(avCodecContext_.get());
327 status = Status::END_OF_STREAM;
328 MEDIA_LOG_E("ReceiveBuffer EOF");
329 } else if (ret == AVERROR(EAGAIN)) {
330 status = Status::ERROR_NOT_ENOUGH_DATA;
331 MEDIA_LOG_E("ReceiveBuffer EAGAIN");
332 } else {
333 MEDIA_LOG_E("audio encoder receive unknow error: %{public}s", OSAL::AVStrError(ret).c_str());
334 status = Status::ERROR_UNKNOWN;
335 }
336 av_packet_unref(avPacket_.get());
337 return status;
338 }
339
SendOutputBuffer(std::shared_ptr<AVBuffer> & outputBuffer)340 Status FFmpegAACEncoderPlugin::SendOutputBuffer(std::shared_ptr<AVBuffer> &outputBuffer)
341 {
342 Status status = SendFrameToFfmpeg();
343 if (status == Status::ERROR_NOT_ENOUGH_DATA) {
344 MEDIA_LOG_D("SendFrameToFfmpeg no one frame data");
345 // last frame mark eos
346 if (outputBuffer->flag_ & BUFFER_FLAG_EOS) {
347 dataCallback_->OnOutputBufferDone(outBuffer_);
348 return Status::OK;
349 }
350 return status;
351 }
352 status = ReceiveBuffer(outputBuffer);
353 if (status == Status::OK || status == Status::END_OF_STREAM) {
354 {
355 std::lock_guard<std::mutex> l(bufferMetaMutex_);
356 if (outBuffer_ == nullptr) {
357 MEDIA_LOG_E("SendOutputBuffer ERROR_NULL_POINTER");
358 return Status::ERROR_NULL_POINTER;
359 }
360 outBuffer_->meta_ = bufferMeta_;
361 }
362 int32_t fifoSize = av_audio_fifo_size(fifo_);
363 if (fifoSize >= avCodecContext_->frame_size) {
364 outputBuffer->flag_ = 0; // not eos
365 MEDIA_LOG_D("fifoSize:%{public}d need another encoder", fifoSize);
366 dataCallback_->OnOutputBufferDone(outBuffer_);
367 return Status::ERROR_AGAIN;
368 }
369 dataCallback_->OnOutputBufferDone(outBuffer_);
370 return Status::OK;
371 } else {
372 MEDIA_LOG_E("SendOutputBuffer-ReceiveBuffer error");
373 }
374 return status;
375 }
376
Reset()377 Status FFmpegAACEncoderPlugin::Reset()
378 {
379 MEDIA_LOG_I("Reset enter");
380 std::lock_guard<std::mutex> lock(avMutex_);
381 auto ret = CloseCtxLocked();
382 prevPts_ = 0;
383 return ret;
384 }
385
Release()386 Status FFmpegAACEncoderPlugin::Release()
387 {
388 MEDIA_LOG_I("Release enter");
389 std::lock_guard<std::mutex> lock(avMutex_);
390 auto ret = CloseCtxLocked();
391 return ret;
392 }
393
Flush()394 Status FFmpegAACEncoderPlugin::Flush()
395 {
396 MEDIA_LOG_I("Flush enter");
397 std::lock_guard<std::mutex> lock(avMutex_);
398 if (avCodecContext_ != nullptr) {
399 avcodec_flush_buffers(avCodecContext_.get());
400 }
401 prevPts_ = 0;
402 if (fifo_) {
403 av_audio_fifo_reset(fifo_);
404 }
405 return ReAllocateContext();
406 }
407
ReAllocateContext()408 Status FFmpegAACEncoderPlugin::ReAllocateContext()
409 {
410 if (!codecContextValid_) {
411 MEDIA_LOG_D("Old avcodec context not valid, no need to reallocate");
412 return Status::OK;
413 }
414
415 AVCodecContext *context = avcodec_alloc_context3(avCodec_.get());
416 auto tmpContext = std::shared_ptr<AVCodecContext>(context, [](AVCodecContext *ptr) {
417 if (ptr) {
418 avcodec_free_context(&ptr);
419 ptr = nullptr;
420 }
421 });
422 CHECK_AND_RETURN_RET_LOG(tmpContext != nullptr, Status::ERROR_NO_MEMORY,
423 "Allocate tmpContext failed.");
424
425 tmpContext->channels = avCodecContext_->channels;
426 tmpContext->sample_rate = avCodecContext_->sample_rate;
427 tmpContext->bit_rate = avCodecContext_->bit_rate;
428 tmpContext->channel_layout = avCodecContext_->channel_layout;
429 tmpContext->sample_fmt = avCodecContext_->sample_fmt;
430 tmpContext->flags = avCodecContext_->flags;
431 tmpContext->global_quality = avCodecContext_->global_quality;
432 MEDIA_LOG_I("flags:%{public}d global_quality:%{public}d", tmpContext->flags, tmpContext->global_quality);
433
434 auto res = avcodec_open2(tmpContext.get(), avCodec_.get(), nullptr);
435 CHECK_AND_RETURN_RET_LOG(res == 0, Status::ERROR_UNKNOWN,
436 "avcodec reopen error %{public}s", OSAL::AVStrError(res).c_str());
437 avCodecContext_ = tmpContext;
438
439 return Status::OK;
440 }
441
AllocateContext(const std::string & name)442 Status FFmpegAACEncoderPlugin::AllocateContext(const std::string &name)
443 {
444 std::lock_guard<std::mutex> lock(avMutex_);
445 avCodec_ = std::shared_ptr<AVCodec>(const_cast<AVCodec *>(avcodec_find_encoder_by_name(name.c_str())),
446 [](AVCodec *ptr) {});
447 cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame *fp) { av_frame_free(&fp); });
448 CHECK_AND_RETURN_RET_LOG(cachedFrame_ != nullptr, Status::ERROR_NO_MEMORY,
449 "Allocate cachedFrame_ failed.");
450
451 avPacket_ = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket *ptr) { av_packet_free(&ptr); });
452
453 if (avCodec_ == nullptr) {
454 return Status::ERROR_UNSUPPORTED_FORMAT;
455 }
456
457 AVCodecContext *context = nullptr;
458 context = avcodec_alloc_context3(avCodec_.get());
459 avCodecContext_ = std::shared_ptr<AVCodecContext>(context, [](AVCodecContext *ptr) {
460 if (ptr) {
461 avcodec_free_context(&ptr);
462 ptr = nullptr;
463 }
464 });
465 CHECK_AND_RETURN_RET_LOG(avCodecContext_ != nullptr, Status::ERROR_NO_MEMORY,
466 "Allocate avCodecContext_ failed.");
467
468 return Status::OK;
469 }
470
InitContext()471 Status FFmpegAACEncoderPlugin::InitContext()
472 {
473 avCodecContext_->channels = channels_;
474 avCodecContext_->sample_rate = sampleRate_;
475 avCodecContext_->bit_rate = bitRate_;
476 avCodecContext_->channel_layout = srcLayout_;
477 avCodecContext_->sample_fmt = srcFmt_;
478 // 8khz 2声道编码码率校正
479 if (sampleRate_ == CORRECTION_SAMPLE_RATE && channels_ == CORRECTION_CHANNEL_COUNT &&
480 bitRate_ < CORRECTION_BIT_RATE) {
481 // 设置 AV_CODEC_FLAG_QSCALE 标志
482 avCodecContext_->flags |= AV_CODEC_FLAG_QSCALE;
483 // Q_SCALE质量参数,对应FFmpeg 命令行工具的-q:a参数,范围通常是0.1~2。
484 // 此处Q_SCALE:1.2 global_quality:141比较合适
485 avCodecContext_->global_quality = static_cast<int32_t>(FF_QP2LAMBDA * Q_SCALE);
486 MEDIA_LOG_I("flags:%{public}d global_quality:%{public}d", avCodecContext_->flags,
487 avCodecContext_->global_quality);
488 }
489
490 if (needResample_) {
491 avCodecContext_->sample_fmt = avCodec_->sample_fmts[0];
492 }
493 return Status::OK;
494 }
495
OpenContext()496 Status FFmpegAACEncoderPlugin::OpenContext()
497 {
498 {
499 std::unique_lock lock(avMutex_);
500 MEDIA_LOG_I("avCodecContext_->channels " PUBLIC_LOG_D32, avCodecContext_->channels);
501 MEDIA_LOG_I("avCodecContext_->sample_rate " PUBLIC_LOG_D32, avCodecContext_->sample_rate);
502 MEDIA_LOG_I("avCodecContext_->bit_rate " PUBLIC_LOG_D64, avCodecContext_->bit_rate);
503 MEDIA_LOG_I("avCodecContext_->channel_layout " PUBLIC_LOG_D64, avCodecContext_->channel_layout);
504 MEDIA_LOG_I("avCodecContext_->sample_fmt " PUBLIC_LOG_D32,
505 static_cast<int32_t>(*(avCodec_.get()->sample_fmts)));
506 MEDIA_LOG_I("avCodecContext_ old srcFmt_ " PUBLIC_LOG_D32, static_cast<int32_t>(srcFmt_));
507 MEDIA_LOG_I("avCodecContext_->codec_id " PUBLIC_LOG_D32, static_cast<int32_t>(avCodec_.get()->id));
508 auto res = avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr);
509 if (res != 0) {
510 MEDIA_LOG_E("avcodec open error %{public}s", OSAL::AVStrError(res).c_str());
511 return Status::ERROR_UNKNOWN;
512 }
513 av_log_set_level(AV_LOG_DEBUG);
514
515 codecContextValid_ = true;
516 }
517 MEDIA_LOG_I("frame size: %{public}d", avCodecContext_->frame_size);
518
519 int32_t destSamplesPerFrame = (avCodecContext_->frame_size > (avCodecContext_->sample_rate / FRAMES_PER_SECOND)) ?
520 avCodecContext_->frame_size : (avCodecContext_->sample_rate / FRAMES_PER_SECOND);
521 if (needResample_) {
522 ResamplePara resamplePara = {
523 .channels = static_cast<uint32_t>(avCodecContext_->channels),
524 .sampleRate = static_cast<uint32_t>(avCodecContext_->sample_rate),
525 .bitsPerSample = 0,
526 .channelLayout = avCodecContext_->ch_layout,
527 .srcFfFmt = srcFmt_,
528 .destSamplesPerFrame = static_cast<uint32_t>(destSamplesPerFrame),
529 .destFmt = avCodecContext_->sample_fmt,
530 };
531 resample_ = std::make_shared<Ffmpeg::Resample>();
532 if (resample_->Init(resamplePara) != Status::OK) {
533 MEDIA_LOG_E("Resmaple init failed.");
534 return Status::ERROR_UNKNOWN;
535 }
536 }
537 return Status::OK;
538 }
539
CheckResample() const540 bool FFmpegAACEncoderPlugin::CheckResample() const
541 {
542 if (avCodec_ == nullptr || avCodecContext_ == nullptr) {
543 return false;
544 }
545 for (size_t index = 0; avCodec_->sample_fmts[index] != AV_SAMPLE_FMT_NONE; ++index) {
546 if (avCodec_->sample_fmts[index] == srcFmt_) {
547 return false;
548 }
549 }
550 MEDIA_LOG_I("CheckResample need resample");
551 return true;
552 }
553
GetMetaData(const std::shared_ptr<Meta> & meta)554 Status FFmpegAACEncoderPlugin::GetMetaData(const std::shared_ptr<Meta> &meta)
555 {
556 int32_t type;
557 int32_t aacProfile;
558 MEDIA_LOG_I("GetMetaData enter");
559 if (meta->Get<Tag::MEDIA_PROFILE>(aacProfile)) {
560 if (aacProfile != AAC_PROFILE_LC) {
561 MEDIA_LOG_E("this plugin only support LC-AAC, input profile:%{public}d", aacProfile);
562 return Status::ERROR_INVALID_PARAMETER;
563 }
564 }
565
566 if (meta->Get<Tag::AUDIO_AAC_IS_ADTS>(type)) {
567 aacName_ = (type == 1 ? "aac" : "aac_latm");
568 }
569 if (meta->Get<Tag::AUDIO_CHANNEL_COUNT>(channels_)) {
570 if (channels_ < MIN_CHANNELS || channels_ > MAX_CHANNELS) {
571 MEDIA_LOG_E("AUDIO_CHANNEL_COUNT error");
572 return Status::ERROR_INVALID_PARAMETER;
573 }
574 } else {
575 MEDIA_LOG_E("no AUDIO_CHANNEL_COUNT");
576 return Status::ERROR_INVALID_PARAMETER;
577 }
578 if (!meta->Get<Tag::AUDIO_SAMPLE_RATE>(sampleRate_)) {
579 MEDIA_LOG_E("no AUDIO_SAMPLE_RATE");
580 return Status::ERROR_INVALID_PARAMETER;
581 }
582 if (!meta->Get<Tag::MEDIA_BITRATE>(bitRate_)) {
583 MEDIA_LOG_E("no MEDIA_BITRATE, set to 32k");
584 bitRate_ = AAC_DEFAULT_BIT_RATE;
585 }
586 if (meta->Get<Tag::AUDIO_SAMPLE_FORMAT>(audioSampleFormat_)) {
587 MEDIA_LOG_D("AUDIO_SAMPLE_FORMAT found, srcFmt:%{public}d", audioSampleFormat_);
588 } else {
589 MEDIA_LOG_E("no AUDIO_SAMPLE_FORMAT");
590 return Status::ERROR_INVALID_PARAMETER;
591 }
592 if (meta->Get<Tag::AUDIO_MAX_INPUT_SIZE>(maxInputSize_)) {
593 MEDIA_LOG_I("maxInputSize: %{public}d", maxInputSize_);
594 }
595 if (meta->Get<Tag::AUDIO_CHANNEL_LAYOUT>(srcLayout_)) {
596 MEDIA_LOG_I("srcLayout_: " PUBLIC_LOG_U64, srcLayout_);
597 } else {
598 srcLayout_ = static_cast<AudioChannelLayout>(channelLayoutMap.at(channels_));
599 }
600 return Status::OK;
601 }
602
SetParameter(const std::shared_ptr<Meta> & meta)603 Status FFmpegAACEncoderPlugin::SetParameter(const std::shared_ptr<Meta> &meta)
604 {
605 MEDIA_LOG_I("SetParameter enter");
606 std::lock_guard<std::mutex> lock(parameterMutex_);
607 Status ret = GetMetaData(meta);
608 if (!CheckFormat()) {
609 MEDIA_LOG_E("CheckFormat fail");
610 return Status::ERROR_INVALID_PARAMETER;
611 }
612 audioParameter_ = *meta;
613 audioParameter_.Set<Tag::AUDIO_SAMPLE_PER_FRAME>(AAC_FRAME_SIZE);
614 return ret;
615 }
616
GetParameter(std::shared_ptr<Meta> & meta)617 Status FFmpegAACEncoderPlugin::GetParameter(std::shared_ptr<Meta> &meta)
618 {
619 std::lock_guard<std::mutex> lock(parameterMutex_);
620 if (maxInputSize_ <= 0 || maxInputSize_ > INPUT_BUFFER_SIZE_DEFAULT) {
621 maxInputSize_ = INPUT_BUFFER_SIZE_DEFAULT;
622 }
623 maxOutputSize_ = OUTPUT_BUFFER_SIZE_DEFAULT;
624 MEDIA_LOG_I("GetParameter maxInputSize_: %{public}d", maxInputSize_);
625 // add codec meta
626 audioParameter_.Set<Tag::AUDIO_MAX_INPUT_SIZE>(maxInputSize_);
627 audioParameter_.Set<Tag::AUDIO_MAX_OUTPUT_SIZE>(maxOutputSize_);
628 *meta = audioParameter_;
629 return Status::OK;
630 }
631
InitFrame()632 Status FFmpegAACEncoderPlugin::InitFrame()
633 {
634 MEDIA_LOG_I("InitFrame enter");
635 cachedFrame_->nb_samples = avCodecContext_->frame_size;
636 cachedFrame_->format = avCodecContext_->sample_fmt;
637 cachedFrame_->channel_layout = avCodecContext_->channel_layout;
638 cachedFrame_->channels = avCodecContext_->channels;
639 int ret = av_frame_get_buffer(cachedFrame_.get(), 0);
640 CHECK_AND_RETURN_RET_LOG(ret >= 0, Status::ERROR_NO_MEMORY,
641 "Get frame buffer failed: %{public}s", OSAL::AVStrError(ret).c_str());
642 if (!(fifo_ =
643 av_audio_fifo_alloc(avCodecContext_->sample_fmt, avCodecContext_->channels, cachedFrame_->nb_samples))) {
644 MEDIA_LOG_E("Could not allocate FIFO");
645 }
646 return Status::OK;
647 }
648
SendEncoder(const std::shared_ptr<AVBuffer> & inputBuffer)649 Status FFmpegAACEncoderPlugin::SendEncoder(const std::shared_ptr<AVBuffer> &inputBuffer)
650 {
651 auto memory = inputBuffer->memory_;
652 CHECK_AND_RETURN_RET_LOG(memory->GetSize() >= 0, Status::ERROR_UNKNOWN,
653 "SendEncoder buffer size is less than 0. size : %{public}d", memory->GetSize());
654 if (memory->GetSize() > memory->GetCapacity()) {
655 MEDIA_LOG_E("send input buffer is > allocate size. size : "
656 "%{public}d, allocate size : %{public}d",
657 memory->GetSize(), memory->GetCapacity());
658 return Status::ERROR_UNKNOWN;
659 }
660 auto errCode = PcmFillFrame(inputBuffer);
661 if (errCode != Status::OK) {
662 MEDIA_LOG_E("SendEncoder PcmFillFrame error");
663 return errCode;
664 }
665 return Status::OK;
666 }
667
PushInFifo(const std::shared_ptr<AVBuffer> & inputBuffer)668 Status FFmpegAACEncoderPlugin::PushInFifo(const std::shared_ptr<AVBuffer> &inputBuffer)
669 {
670 if (!inputBuffer) {
671 MEDIA_LOG_D("inputBuffer is nullptr");
672 return Status::ERROR_INVALID_PARAMETER;
673 }
674 int ret = av_frame_make_writable(cachedFrame_.get());
675 if (ret != 0) {
676 MEDIA_LOG_D("Frame make writable failed: %{public}s", OSAL::AVStrError(ret).c_str());
677 return Status::ERROR_UNKNOWN;
678 }
679 bool isEos = inputBuffer->flag_ & BUFFER_FLAG_EOS;
680 if (!isEos) {
681 auto status = SendEncoder(inputBuffer);
682 if (status != Status::OK) {
683 MEDIA_LOG_E("input push in fifo fail");
684 return status;
685 }
686 } else {
687 MEDIA_LOG_I("input eos");
688 }
689 return Status::OK;
690 }
691
SendFrameToFfmpeg()692 Status FFmpegAACEncoderPlugin::SendFrameToFfmpeg()
693 {
694 MEDIA_LOG_D("SendFrameToFfmpeg enter");
695 int32_t fifoSize = av_audio_fifo_size(fifo_);
696 if (fifoSize < avCodecContext_->frame_size) {
697 MEDIA_LOG_D("fifoSize:%{public}d not enough", fifoSize);
698 return Status::ERROR_NOT_ENOUGH_DATA;
699 }
700 cachedFrame_->nb_samples = avCodecContext_->frame_size;
701 int32_t bytesPerSample = av_get_bytes_per_sample(avCodecContext_->sample_fmt);
702 // adjest data addr
703 for (int i = 1; i < avCodecContext_->channels; i++) {
704 cachedFrame_->extended_data[i] =
705 cachedFrame_->extended_data[i - 1] + cachedFrame_->nb_samples * bytesPerSample;
706 }
707 int readRet =
708 av_audio_fifo_read(fifo_, reinterpret_cast<void **>(cachedFrame_->data), avCodecContext_->frame_size);
709 if (readRet < 0) {
710 MEDIA_LOG_E("fifo read error");
711 return Status::ERROR_UNKNOWN;
712 }
713 cachedFrame_->linesize[0] = readRet * av_get_bytes_per_sample(avCodecContext_->sample_fmt);
714 int32_t ret = avcodec_send_frame(avCodecContext_.get(), cachedFrame_.get());
715 if (ret == 0) {
716 return Status::OK;
717 } else if (ret == AVERROR(EAGAIN)) {
718 MEDIA_LOG_E("skip this frame because data not enough, msg:%{public}s", OSAL::AVStrError(ret).data());
719 return Status::ERROR_NOT_ENOUGH_DATA;
720 } else if (ret == AVERROR_EOF) {
721 MEDIA_LOG_D("eos send frame, msg:%{public}s", OSAL::AVStrError(ret).data());
722 return Status::END_OF_STREAM;
723 } else {
724 MEDIA_LOG_D("Send frame unknown error: %{public}s", OSAL::AVStrError(ret).c_str());
725 return Status::ERROR_UNKNOWN;
726 }
727 }
728
PcmFillFrame(const std::shared_ptr<AVBuffer> & inputBuffer)729 Status FFmpegAACEncoderPlugin::PcmFillFrame(const std::shared_ptr<AVBuffer> &inputBuffer)
730 {
731 MEDIA_LOG_D("PcmFillFrame enter, buffer->pts" PUBLIC_LOG_D64, inputBuffer->pts_);
732 auto memory = inputBuffer->memory_;
733 auto bytesPerSample = av_get_bytes_per_sample(avCodecContext_->sample_fmt);
734 const uint8_t *srcBuffer = memory->GetAddr();
735 uint8_t *destBuffer = const_cast<uint8_t *>(srcBuffer);
736 size_t srcBufferSize = static_cast<size_t>(memory->GetSize());
737 size_t destBufferSize = srcBufferSize;
738 if (needResample_ && resample_ != nullptr) {
739 if (resample_->Convert(srcBuffer, srcBufferSize, destBuffer, destBufferSize) != Status::OK) {
740 MEDIA_LOG_E("Convert sample format failed");
741 }
742 }
743
744 cachedFrame_->nb_samples = static_cast<int>(destBufferSize) / (bytesPerSample * avCodecContext_->channels);
745 if (!(inputBuffer->flag_ & BUFFER_FLAG_EOS) && cachedFrame_->nb_samples != avCodecContext_->frame_size) {
746 MEDIA_LOG_D("Input frame size not match, input samples: %{public}d, "
747 "frame_size: %{public}d",
748 cachedFrame_->nb_samples, avCodecContext_->frame_size);
749 }
750 int32_t destSamplesPerFrame = (avCodecContext_->frame_size > (avCodecContext_->sample_rate / FRAMES_PER_SECOND)) ?
751 avCodecContext_->frame_size : (avCodecContext_->sample_rate / FRAMES_PER_SECOND);
752 cachedFrame_->extended_data = cachedFrame_->data;
753 cachedFrame_->extended_data[0] = destBuffer;
754 cachedFrame_->linesize[0] = cachedFrame_->nb_samples * bytesPerSample;
755 for (int i = 1; i < avCodecContext_->channels; i++) {
756 // after convert, the length of line is destSamplesPerFrame
757 cachedFrame_->extended_data[i] =
758 cachedFrame_->extended_data[i - 1] + static_cast<uint32_t>(destSamplesPerFrame * bytesPerSample);
759 }
760 int32_t cacheSize = av_audio_fifo_size(fifo_);
761 int32_t ret = av_audio_fifo_realloc(fifo_, cacheSize + cachedFrame_->nb_samples);
762 if (ret < 0) {
763 MEDIA_LOG_E("realloc ret: %{public}d, cacheSize: %{public}d", ret, cacheSize);
764 }
765 MEDIA_LOG_D("realloc nb_samples:%{public}d cacheSize:%{public}d channels:%{public}d",
766 cachedFrame_->nb_samples, cacheSize, avCodecContext_->channels);
767 int32_t writeSamples =
768 av_audio_fifo_write(fifo_, reinterpret_cast<void **>(cachedFrame_->data), cachedFrame_->nb_samples);
769 if (writeSamples < cachedFrame_->nb_samples) {
770 MEDIA_LOG_E("write smaples: %{public}d, nb_samples: %{public}d", writeSamples, cachedFrame_->nb_samples);
771 }
772 return Status::OK;
773 }
774
Prepare()775 Status FFmpegAACEncoderPlugin::Prepare()
776 {
777 return Status::OK;
778 }
779
Stop()780 Status FFmpegAACEncoderPlugin::Stop()
781 {
782 std::lock_guard<std::mutex> lock(avMutex_);
783 auto ret = CloseCtxLocked();
784 if (outBuffer_) {
785 outBuffer_.reset();
786 outBuffer_ = nullptr;
787 }
788 MEDIA_LOG_I("Stop");
789 return ret;
790 }
791
GetInputBuffers(std::vector<std::shared_ptr<AVBuffer>> & inputBuffers)792 Status FFmpegAACEncoderPlugin::GetInputBuffers(std::vector<std::shared_ptr<AVBuffer>> &inputBuffers)
793 {
794 return Status::OK;
795 }
796
GetOutputBuffers(std::vector<std::shared_ptr<AVBuffer>> & outputBuffers)797 Status FFmpegAACEncoderPlugin::GetOutputBuffers(std::vector<std::shared_ptr<AVBuffer>> &outputBuffers)
798 {
799 return Status::OK;
800 }
801
CloseCtxLocked()802 Status FFmpegAACEncoderPlugin::CloseCtxLocked()
803 {
804 if (avCodecContext_ != nullptr) {
805 avCodecContext_.reset();
806 avCodecContext_ = nullptr;
807 }
808 if (fifo_) {
809 av_audio_fifo_free(fifo_);
810 fifo_ = nullptr;
811 }
812 return Status::OK;
813 }
814 } // namespace Ffmpeg
815 } // namespace Plugins
816 } // namespace Media
817 } // namespace OHOS
818
819 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
820 #define FFMPEG_AAC_ENCODER_EXPORT extern "C" __declspec(dllexport)
821 #else
822 #if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
823 #define FFMPEG_AAC_ENCODER_EXPORT extern "C" __attribute__((visibility("default")))
824 #else
825 #define FFMPEG_AAC_ENCODER_EXPORT
826 #endif
827 #endif
828
829 namespace {
830 using namespace Ffmpeg;
CreateFFmpegAacEncoderPluginObject()831 FFMPEG_AAC_ENCODER_EXPORT CodecPlugin *CreateFFmpegAacEncoderPluginObject()
832 {
833 const std::string name = std::string(OHOS::MediaAVCodec::AVCodecCodecName::AUDIO_ENCODER_AAC_NAME);
834 CodecPlugin *obj = new FFmpegAACEncoderPlugin(name);
835 return obj;
836 }
837
DestroyFFmpegAacEncoderPluginObject(CodecPlugin * obj)838 FFMPEG_AAC_ENCODER_EXPORT void DestroyFFmpegAacEncoderPluginObject(CodecPlugin *obj)
839 {
840 if (obj != nullptr) {
841 delete obj;
842 }
843 }
844 }