1 /*
2 * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "Ffmpeg_Au_Encoder"
17
18 #include "audio_ffmpeg_encoder_plugin.h"
19 #include <cstring>
20 #include <map>
21 #include <set>
22 #include "ffmpeg_au_enc_config.h"
23 #include "plugin/common/plugin_caps_builder.h"
24 #include "plugins/ffmpeg_adapter/utils/ffmpeg_utils.h"
25
26 namespace {
27 // register plugins
28 using namespace OHOS::Media::Plugin;
29 using namespace Ffmpeg;
30 void UpdatePluginDefinition(const AVCodec* codec, CodecPluginDef& definition);
31
32 std::map<std::string, std::shared_ptr<const AVCodec>> codecMap;
33 const size_t BUFFER_QUEUE_SIZE = 6;
34 std::set<AVCodecID> g_supportedCodec = {AV_CODEC_ID_AAC, AV_CODEC_ID_AAC_LATM};
35
AuFfmpegEncoderCreator(const std::string & name)36 std::shared_ptr<CodecPlugin> AuFfmpegEncoderCreator(const std::string& name)
37 {
38 return std::make_shared<AudioFfmpegEncoderPlugin>(name);
39 }
40
RegisterAudioEncoderPlugins(const std::shared_ptr<Register> & reg)41 Status RegisterAudioEncoderPlugins(const std::shared_ptr<Register>& reg)
42 {
43 const AVCodec* codec = nullptr;
44 void* ite = nullptr;
45 MEDIA_LOG_I("registering audio encoders");
46 while ((codec = av_codec_iterate(&ite))) {
47 if (!av_codec_is_encoder(codec) || codec->type != AVMEDIA_TYPE_AUDIO) {
48 continue;
49 }
50 if (g_supportedCodec.find(codec->id) == g_supportedCodec.end()) {
51 MEDIA_LOG_DD("codec " PUBLIC_LOG_S "(" PUBLIC_LOG_S ") is not supported right now",
52 codec->name, codec->long_name);
53 continue;
54 }
55 CodecPluginDef definition;
56 definition.name = "ffmpegAuEnc_" + std::string(codec->name);
57 definition.codecType = CodecType::AUDIO_ENCODER;
58 definition.rank = 100; // 100
59 definition.creator = AuFfmpegEncoderCreator;
60 UpdatePluginDefinition(codec, definition);
61 // do not delete the codec in the deleter
62 codecMap[definition.name] = std::shared_ptr<AVCodec>(const_cast<AVCodec*>(codec), [](void* ptr) {});
63 if (reg->AddPlugin(definition) != Status::OK) {
64 MEDIA_LOG_W("register plugin " PUBLIC_LOG_S "(" PUBLIC_LOG_S ") failed", codec->name, codec->long_name);
65 }
66 }
67 return Status::OK;
68 }
69
UnRegisterAudioEncoderPlugin()70 void UnRegisterAudioEncoderPlugin()
71 {
72 codecMap.clear();
73 }
74
UpdateInCaps(const AVCodec * codec,CodecPluginDef & definition)75 void UpdateInCaps(const AVCodec* codec, CodecPluginDef& definition)
76 {
77 CapabilityBuilder capBuilder;
78 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
79 if (codec->supported_samplerates != nullptr) {
80 DiscreteCapability<uint32_t> values;
81 size_t index = 0;
82 for (; codec->supported_samplerates[index] != 0; ++index) {
83 values.push_back(codec->supported_samplerates[index]);
84 }
85 if (index) {
86 capBuilder.SetAudioSampleRateList(values);
87 }
88 }
89 definition.inCaps.push_back(capBuilder.Build());
90 }
91
UpdateOutCaps(const AVCodec * codec,CodecPluginDef & definition)92 void UpdateOutCaps(const AVCodec* codec, CodecPluginDef& definition)
93 {
94 CapabilityBuilder capBuilder;
95 switch (codec->id) {
96 case AV_CODEC_ID_AAC:
97 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AAC)
98 .SetAudioMpegVersion(4) // 4
99 .SetAudioAacProfile(AudioAacProfile::LC)
100 .SetAudioAacStreamFormat(AudioAacStreamFormat::MP4ADTS);
101 break;
102 case AV_CODEC_ID_AAC_LATM:
103 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AAC_LATM)
104 .SetAudioMpegVersion(4) // 4
105 .SetAudioAacStreamFormat(AudioAacStreamFormat::MP4LOAS);
106 break;
107 default:
108 MEDIA_LOG_I("codec is not supported right now");
109 }
110 definition.outCaps.push_back(capBuilder.Build());
111 }
112
UpdatePluginDefinition(const AVCodec * codec,CodecPluginDef & definition)113 void UpdatePluginDefinition(const AVCodec* codec, CodecPluginDef& definition)
114 {
115 UpdateInCaps(codec, definition);
116 UpdateOutCaps(codec, definition);
117 }
118 } // namespace
119 PLUGIN_DEFINITION(FFmpegAudioEncoders, LicenseType::LGPL, RegisterAudioEncoderPlugins, UnRegisterAudioEncoderPlugin);
120
121 namespace OHOS {
122 namespace Media {
123 namespace Plugin {
124 namespace Ffmpeg {
AudioFfmpegEncoderPlugin(std::string name)125 AudioFfmpegEncoderPlugin::AudioFfmpegEncoderPlugin(std::string name) : CodecPlugin(std::move(name)), prev_pts_(0)
126 {
127 }
128
~AudioFfmpegEncoderPlugin()129 AudioFfmpegEncoderPlugin::~AudioFfmpegEncoderPlugin()
130 {
131 OSAL::ScopedLock lock(avMutex_);
132 OSAL::ScopedLock lock1(parameterMutex_);
133 DeInitLocked();
134 }
135
Init()136 Status AudioFfmpegEncoderPlugin::Init()
137 {
138 auto ite = codecMap.find(pluginName_);
139 if (ite == codecMap.end()) {
140 MEDIA_LOG_W("cannot find codec with name " PUBLIC_LOG_S, pluginName_.c_str());
141 return Status::ERROR_UNSUPPORTED_FORMAT;
142 }
143 OSAL::ScopedLock lock(avMutex_);
144 avCodec_ = ite->second;
145 cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* frame) { av_frame_free(&frame);});
146 return Status::OK;
147 }
148
Deinit()149 Status AudioFfmpegEncoderPlugin::Deinit()
150 {
151 OSAL::ScopedLock lock(avMutex_);
152 OSAL::ScopedLock lock1(parameterMutex_);
153 return DeInitLocked();
154 }
155
DeInitLocked()156 Status AudioFfmpegEncoderPlugin::DeInitLocked()
157 {
158 ResetLocked();
159 avCodec_.reset();
160 cachedFrame_.reset();
161 return Status::OK;
162 }
163
SetParameter(Tag tag,const ValueType & value)164 Status AudioFfmpegEncoderPlugin::SetParameter(Tag tag, const ValueType& value)
165 {
166 OSAL::ScopedLock lock(parameterMutex_);
167 audioParameter_.insert(std::make_pair(tag, value));
168 return Status::OK;
169 }
170
GetParameter(Tag tag,ValueType & value)171 Status AudioFfmpegEncoderPlugin::GetParameter(Tag tag, ValueType& value)
172 {
173 if (tag == Tag::REQUIRED_OUT_BUFFER_CNT) {
174 value = static_cast<uint32_t>(BUFFER_QUEUE_SIZE);
175 return Status::OK;
176 }
177 OSAL::ScopedLock lock(avMutex_);
178 if (avCodecContext_ == nullptr) {
179 return Status::ERROR_WRONG_STATE;
180 }
181 return GetAudioEncoderParameters(*avCodecContext_, tag, value);
182 }
183
Prepare()184 Status AudioFfmpegEncoderPlugin::Prepare()
185 {
186 {
187 OSAL::ScopedLock lock(avMutex_);
188 if (avCodec_ == nullptr) {
189 return Status::ERROR_WRONG_STATE;
190 }
191 auto context = avcodec_alloc_context3(avCodec_.get());
192 FALSE_RETURN_V_MSG_E(context != nullptr, Status::ERROR_UNKNOWN, "cannot allocate codec context");
193 avCodecContext_ = std::shared_ptr<AVCodecContext>(context, [](AVCodecContext* ptr) {
194 if (ptr != nullptr) {
195 if (ptr->extradata) {
196 av_free(ptr->extradata);
197 ptr->extradata = nullptr;
198 }
199 avcodec_free_context(&ptr);
200 }
201 });
202 {
203 OSAL::ScopedLock lock1(parameterMutex_);
204 ConfigAudioEncoder(*avCodecContext_, audioParameter_);
205 }
206
207 if (!avCodecContext_->time_base.den) {
208 avCodecContext_->time_base.den = avCodecContext_->sample_rate;
209 avCodecContext_->time_base.num = 1;
210 avCodecContext_->ticks_per_frame = 1;
211 }
212
213 avCodecContext_->workaround_bugs =
214 static_cast<uint32_t>(avCodecContext_->workaround_bugs) | static_cast<uint32_t>(FF_BUG_AUTODETECT);
215 }
216 return Status::OK;
217 }
218
ResetLocked()219 Status AudioFfmpegEncoderPlugin::ResetLocked()
220 {
221 audioParameter_.clear();
222 avCodecContext_.reset();
223 return Status::OK;
224 }
225
Reset()226 Status AudioFfmpegEncoderPlugin::Reset()
227 {
228 OSAL::ScopedLock lock(avMutex_);
229 OSAL::ScopedLock lock1(parameterMutex_);
230 return ResetLocked();
231 }
232
CheckReformat()233 bool AudioFfmpegEncoderPlugin::CheckReformat()
234 {
235 if (avCodec_ == nullptr || avCodecContext_ == nullptr) {
236 return false;
237 }
238 for (size_t index = 0; avCodec_->sample_fmts[index] != AV_SAMPLE_FMT_NONE; ++index) {
239 if (avCodec_->sample_fmts[index] == avCodecContext_->sample_fmt) {
240 return false;
241 }
242 }
243 return true;
244 }
245
Start()246 Status AudioFfmpegEncoderPlugin::Start()
247 {
248 OSAL::ScopedLock lock(avMutex_);
249 if (avCodecContext_ == nullptr) {
250 return Status::ERROR_WRONG_STATE;
251 }
252 needReformat_ = CheckReformat();
253 if (needReformat_) {
254 srcFmt_ = avCodecContext_->sample_fmt;
255 // always use the first fmt
256 avCodecContext_->sample_fmt = avCodec_->sample_fmts[0];
257 }
258 auto res = avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr);
259 FALSE_RETURN_V_MSG_E(res == 0, Status::ERROR_UNKNOWN, "avcodec open error " PUBLIC_LOG_S " when start encoder",
260 AVStrError(res).c_str());
261 FALSE_RETURN_V_MSG_E(avCodecContext_->frame_size > 0, Status::ERROR_UNKNOWN, "frame_size unknown");
262 fullInputFrameSize_ = (uint32_t)av_samples_get_buffer_size(nullptr, avCodecContext_->channels,
263 avCodecContext_->frame_size, srcFmt_, 1);
264 srcBytesPerSample_ = av_get_bytes_per_sample(srcFmt_) * avCodecContext_->channels;
265 if (needReformat_) {
266 Ffmpeg::ResamplePara resamplePara = {
267 static_cast<uint32_t>(avCodecContext_->channels),
268 static_cast<uint32_t>(avCodecContext_->sample_rate),
269 0,
270 static_cast<int64_t>(avCodecContext_->channel_layout),
271 srcFmt_,
272 static_cast<uint32_t>(avCodecContext_->frame_size),
273 avCodecContext_->sample_fmt,
274 };
275 resample_ = std::make_shared<Ffmpeg::Resample>();
276 FALSE_RETURN_V_MSG(resample_->Init(resamplePara) == Status::OK, Status::ERROR_UNKNOWN, "Resample init error");
277 }
278 SetParameter(Tag::AUDIO_SAMPLE_PER_FRAME, static_cast<uint32_t>(avCodecContext_->frame_size));
279 return Status::OK;
280 }
281
Stop()282 Status AudioFfmpegEncoderPlugin::Stop()
283 {
284 Status ret = Status::OK;
285 {
286 OSAL::ScopedLock lock(avMutex_);
287 if (avCodecContext_ != nullptr) {
288 auto res = avcodec_close(avCodecContext_.get());
289 FALSE_RETURN_V_MSG_E(res == 0, Status::ERROR_UNKNOWN,
290 "avcodec close error " PUBLIC_LOG_S " when stop encoder", AVStrError(res).c_str());
291 avCodecContext_.reset();
292 }
293 if (outBuffer_) {
294 outBuffer_.reset();
295 }
296 }
297 return ret;
298 }
299
Flush()300 Status AudioFfmpegEncoderPlugin::Flush()
301 {
302 MEDIA_LOG_I("Flush entered.");
303 OSAL::ScopedLock lock(avMutex_);
304 if (avCodecContext_ != nullptr) {
305 avcodec_flush_buffers(avCodecContext_.get());
306 }
307 MEDIA_LOG_I("Flush exit.");
308 return Status::OK;
309 }
310
QueueInputBuffer(const std::shared_ptr<Buffer> & inputBuffer,int32_t timeoutMs)311 Status AudioFfmpegEncoderPlugin::QueueInputBuffer(const std::shared_ptr<Buffer>& inputBuffer, int32_t timeoutMs)
312 {
313 MEDIA_LOG_DD("queue input buffer");
314 (void)timeoutMs;
315 if (inputBuffer->IsEmpty() && !(inputBuffer->flag & BUFFER_FLAG_EOS)) {
316 MEDIA_LOG_E("encoder does not support fd buffer");
317 return Status::ERROR_INVALID_DATA;
318 }
319 Status ret = Status::OK;
320 {
321 OSAL::ScopedLock lock(avMutex_);
322 if (avCodecContext_ == nullptr) {
323 return Status::ERROR_WRONG_STATE;
324 }
325 ret = SendBufferLocked(inputBuffer);
326 }
327 return ret;
328 }
329
QueueOutputBuffer(const std::shared_ptr<Buffer> & outputBuffer,int32_t timeoutMs)330 Status AudioFfmpegEncoderPlugin::QueueOutputBuffer(const std::shared_ptr<Buffer>& outputBuffer, int32_t timeoutMs)
331 {
332 MEDIA_LOG_DD("queue output buffer");
333 (void)timeoutMs;
334 if (!outputBuffer) {
335 return Status::ERROR_INVALID_PARAMETER;
336 }
337 outBuffer_ = outputBuffer;
338 return SendOutputBuffer();
339 }
340
SendOutputBuffer()341 Status AudioFfmpegEncoderPlugin::SendOutputBuffer()
342 {
343 MEDIA_LOG_DD("send output buffer");
344 Status status = ReceiveBuffer();
345 if (status == Status::OK || status == Status::END_OF_STREAM) {
346 dataCallback_->OnOutputBufferDone(outBuffer_);
347 }
348 outBuffer_.reset();
349 return status;
350 }
351
FillInFrameCache(const std::shared_ptr<Memory> & mem)352 void AudioFfmpegEncoderPlugin::FillInFrameCache(const std::shared_ptr<Memory>& mem)
353 {
354 uint8_t* sampleData = nullptr;
355 int32_t nbSamples = 0;
356 auto srcBuffer = mem->GetReadOnlyData();
357 auto destBuffer = const_cast<uint8_t*>(srcBuffer);
358 auto srcLength = mem->GetSize();
359 auto destLength = srcLength;
360 if (needReformat_ && resample_) {
361 FALSE_LOG(resample_->Convert(srcBuffer, srcLength, destBuffer, destLength) == Status::OK);
362 if (destLength) {
363 sampleData = destBuffer;
364 nbSamples = destLength / av_get_bytes_per_sample(avCodecContext_->sample_fmt) / avCodecContext_->channels;
365 }
366 } else {
367 sampleData = destBuffer;
368 nbSamples = destLength / srcBytesPerSample_;
369 }
370 cachedFrame_->format = avCodecContext_->sample_fmt;
371 cachedFrame_->sample_rate = avCodecContext_->sample_rate;
372 cachedFrame_->channels = avCodecContext_->channels;
373 cachedFrame_->channel_layout = avCodecContext_->channel_layout;
374 cachedFrame_->nb_samples = nbSamples;
375 if (av_sample_fmt_is_planar(avCodecContext_->sample_fmt) && avCodecContext_->channels > 1) {
376 if (avCodecContext_->channels > AV_NUM_DATA_POINTERS) {
377 av_freep(cachedFrame_->extended_data);
378 cachedFrame_->extended_data = static_cast<uint8_t**>(av_malloc_array(avCodecContext_->channels,
379 sizeof(uint8_t *)));
380 } else {
381 cachedFrame_->extended_data = cachedFrame_->data;
382 }
383 cachedFrame_->extended_data[0] = sampleData;
384 cachedFrame_->linesize[0] = nbSamples * av_get_bytes_per_sample(avCodecContext_->sample_fmt);
385 for (int i = 1; i < avCodecContext_->channels; i++) {
386 cachedFrame_->extended_data[i] = cachedFrame_->extended_data[i-1] + cachedFrame_->linesize[0];
387 }
388 } else {
389 cachedFrame_->data[0] = sampleData;
390 cachedFrame_->extended_data = cachedFrame_->data;
391 cachedFrame_->linesize[0] = nbSamples * av_get_bytes_per_sample(avCodecContext_->sample_fmt) *
392 avCodecContext_->channels;
393 }
394 }
395
SendBufferLocked(const std::shared_ptr<Buffer> & inputBuffer)396 Status AudioFfmpegEncoderPlugin::SendBufferLocked(const std::shared_ptr<Buffer>& inputBuffer)
397 {
398 bool eos = false;
399 if (inputBuffer == nullptr || (inputBuffer->flag & BUFFER_FLAG_EOS) != 0) {
400 // eos buffer
401 eos = true;
402 } else {
403 auto inputMemory = inputBuffer->GetMemory();
404 FALSE_RETURN_V_MSG_W(inputMemory->GetSize() == fullInputFrameSize_, Status::ERROR_NOT_ENOUGH_DATA,
405 "Not enough data, input: " PUBLIC_LOG_ZU ", fullInputFrameSize: " PUBLIC_LOG_U32,
406 inputMemory->GetSize(), fullInputFrameSize_);
407 FillInFrameCache(inputMemory);
408 }
409 AVFrame* inputFrame = nullptr;
410 if (!eos) {
411 inputFrame = cachedFrame_.get();
412 }
413 auto ret = avcodec_send_frame(avCodecContext_.get(), inputFrame);
414 if (!eos && inputFrame) {
415 av_frame_unref(inputFrame);
416 }
417 if (ret == 0) {
418 return Status::OK;
419 } else if (ret == AVERROR_EOF) {
420 return Status::END_OF_STREAM;
421 } else if (ret == AVERROR(EAGAIN)) {
422 return Status::ERROR_AGAIN;
423 } else {
424 MEDIA_LOG_E("send buffer error " PUBLIC_LOG_S, AVStrError(ret).c_str());
425 return Status::ERROR_UNKNOWN;
426 }
427 }
428
ReceiveFrameSucc(const std::shared_ptr<Buffer> & ioInfo,const std::shared_ptr<AVPacket> & packet)429 Status AudioFfmpegEncoderPlugin::ReceiveFrameSucc(const std::shared_ptr<Buffer>& ioInfo,
430 const std::shared_ptr<AVPacket>& packet)
431 {
432 auto ioInfoMem = ioInfo->GetMemory();
433 FALSE_RETURN_V_MSG_W(ioInfoMem->GetCapacity() >= static_cast<size_t>(packet->size),
434 Status::ERROR_NO_MEMORY, "buffer size is not enough");
435 ioInfoMem->Write(packet->data, packet->size);
436 // how get perfect pts with upstream pts ?
437 ioInfo->duration = ConvertTimeFromFFmpeg(packet->duration, avCodecContext_->time_base);
438 ioInfo->pts = (UINT64_MAX - prev_pts_ < packet->duration) ?
439 (ioInfo->duration - (UINT64_MAX - prev_pts_)) :
440 (prev_pts_ + ioInfo->duration);
441 prev_pts_ = ioInfo->pts;
442 return Status::OK;
443 }
444
ReceiveBufferLocked(const std::shared_ptr<Buffer> & ioInfo)445 Status AudioFfmpegEncoderPlugin::ReceiveBufferLocked(const std::shared_ptr<Buffer>& ioInfo)
446 {
447 Status status;
448 std::shared_ptr<AVPacket> packet = std::make_shared<AVPacket>();
449 auto ret = avcodec_receive_packet(avCodecContext_.get(), packet.get());
450 if (ret >= 0) {
451 MEDIA_LOG_DD("receive one frame");
452 status = ReceiveFrameSucc(ioInfo, packet);
453 } else if (ret == AVERROR_EOF) {
454 MEDIA_LOG_I("eos received");
455 ioInfo->GetMemory()->Reset();
456 ioInfo->flag = BUFFER_FLAG_EOS;
457 status = Status::END_OF_STREAM;
458 } else if (ret == AVERROR(EAGAIN)) {
459 status = Status::ERROR_NOT_ENOUGH_DATA;
460 } else {
461 MEDIA_LOG_E("audio encoder receive error: " PUBLIC_LOG_S, AVStrError(ret).c_str());
462 status = Status::ERROR_UNKNOWN;
463 }
464 av_frame_unref(cachedFrame_.get());
465 return status;
466 }
467
ReceiveBuffer()468 Status AudioFfmpegEncoderPlugin::ReceiveBuffer()
469 {
470 std::shared_ptr<Buffer> ioInfo = outBuffer_;
471 if ((ioInfo == nullptr) || ioInfo->IsEmpty() ||
472 (ioInfo->GetBufferMeta()->GetType() != BufferMetaType::AUDIO)) {
473 MEDIA_LOG_W("cannot fetch valid buffer to output");
474 return Status::ERROR_NO_MEMORY;
475 }
476 Status status = Status::OK;
477 {
478 OSAL::ScopedLock l(avMutex_);
479 if (avCodecContext_ == nullptr) {
480 return Status::ERROR_WRONG_STATE;
481 }
482 status = ReceiveBufferLocked(ioInfo);
483 }
484 return status;
485 }
486
GetAllocator()487 std::shared_ptr<Allocator> AudioFfmpegEncoderPlugin::GetAllocator()
488 {
489 return nullptr;
490 }
491 } // namespace Ffmpeg
492 } // namespace Plugin
493 } // namespace Media
494 } // namespace OHOS