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 }