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_Decoder"
17
18 #include "audio_ffmpeg_decoder_plugin.h"
19 #include <cstring>
20 #include <map>
21 #include <set>
22 #include "foundation/utils/constants.h"
23 #include "plugin/common/plugin_audio_tags.h"
24 #include "plugin/common/plugin_caps_builder.h"
25 #include "plugins/ffmpeg_adapter/utils/ffmpeg_utils.h"
26
27 namespace {
28 using namespace OHOS::Media::Plugin;
29 using namespace Ffmpeg;
30 void UpdatePluginDefinition(const AVCodec* codec, CodecPluginDef& definition);
31 void SetCapMime(const AVCodec* codec, CapabilityBuilder& capBuilder);
32
33 std::map<std::string, std::shared_ptr<const AVCodec>> codecMap;
34
35 const size_t BUFFER_QUEUE_SIZE = 6;
36
37 const std::set<AVCodecID> g_supportedCodec = {
38 AV_CODEC_ID_MP3,
39 AV_CODEC_ID_FLAC,
40 AV_CODEC_ID_AAC,
41 AV_CODEC_ID_AAC_LATM,
42 AV_CODEC_ID_VORBIS,
43 AV_CODEC_ID_APE,
44 AV_CODEC_ID_AMR_NB,
45 AV_CODEC_ID_AMR_WB,
46 };
47
48 std::map<AVCodecID, uint32_t> samplesPerFrameMap = {
49 {AV_CODEC_ID_MP3, 1152}, // 1152
50 {AV_CODEC_ID_FLAC, 8192}, // 8192
51 {AV_CODEC_ID_AAC, 2048}, // 2048
52 {AV_CODEC_ID_AAC_LATM, 2048}, // 2048
53 {AV_CODEC_ID_VORBIS, 8192}, // 8192
54 {AV_CODEC_ID_APE, 4608}, // 4608
55 {AV_CODEC_ID_AMR_NB, 160}, // 160
56 {AV_CODEC_ID_AMR_WB, 160}, // 160
57 };
58
RegisterAudioDecoderPlugins(const std::shared_ptr<Register> & reg)59 Status RegisterAudioDecoderPlugins(const std::shared_ptr<Register>& reg)
60 {
61 const AVCodec* codec = nullptr;
62 void* ite = nullptr;
63 MEDIA_LOG_I("registering audio decoders");
64 while ((codec = av_codec_iterate(&ite))) {
65 if (!av_codec_is_decoder(codec) || codec->type != AVMEDIA_TYPE_AUDIO) {
66 continue;
67 }
68 if (g_supportedCodec.find(codec->id) == g_supportedCodec.end()) {
69 MEDIA_LOG_DD("codec " PUBLIC_LOG_S "(" PUBLIC_LOG_S ") is not supported right now",
70 codec->name, codec->long_name);
71 continue;
72 }
73 CodecPluginDef definition;
74 definition.name = "ffmpegAuDec_" + std::string(codec->name);
75 definition.pluginType = PluginType::AUDIO_DECODER;
76 definition.rank = 100; // 100
77 definition.creator = [] (const std::string& name) -> std::shared_ptr<CodecPlugin> {
78 return std::make_shared<AudioFfmpegDecoderPlugin>(name);
79 };
80 UpdatePluginDefinition(codec, definition);
81 // do not delete the codec in the deleter
82 codecMap[definition.name] = std::shared_ptr<AVCodec>(const_cast<AVCodec*>(codec), [](void* ptr) {});
83 if (reg->AddPlugin(definition) != Status::OK) {
84 MEDIA_LOG_W("register plugin " PUBLIC_LOG_S " failed", definition.name.c_str());
85 }
86 }
87 return Status::OK;
88 }
89
UnRegisterAudioDecoderPlugin()90 void UnRegisterAudioDecoderPlugin()
91 {
92 codecMap.clear();
93 }
94
UpdateInCaps(const AVCodec * codec,CodecPluginDef & definition)95 void UpdateInCaps(const AVCodec* codec, CodecPluginDef& definition)
96 {
97 CapabilityBuilder capBuilder;
98 SetCapMime(codec, capBuilder);
99
100 if (codec->supported_samplerates != nullptr) {
101 DiscreteCapability<uint32_t> values;
102 size_t index {0};
103 for (; codec->supported_samplerates[index] != 0; ++index) {
104 values.push_back(codec->supported_samplerates[index]);
105 }
106 if (index) {
107 capBuilder.SetAudioSampleRateList(values);
108 }
109 }
110
111 if (codec->channel_layouts != nullptr) {
112 DiscreteCapability<AudioChannelLayout> values;
113 size_t index {0};
114 for (; codec->channel_layouts[index] != 0; ++index) {
115 values.push_back(AudioChannelLayout(codec->channel_layouts[index]));
116 }
117 if (index) {
118 capBuilder.SetAudioChannelLayoutList(values);
119 }
120 }
121 definition.inCaps.push_back(capBuilder.Build());
122 }
123
SetCapMime(const AVCodec * codec,CapabilityBuilder & capBuilder)124 void SetCapMime(const AVCodec* codec, CapabilityBuilder& capBuilder)
125 {
126 switch (codec->id) {
127 case AV_CODEC_ID_MP3:
128 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_MPEG)
129 .SetAudioMpegVersion(1)
130 .SetAudioMpegLayerRange(1, 3); // 3
131 break;
132 case AV_CODEC_ID_FLAC:
133 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_FLAC);
134 break;
135 case AV_CODEC_ID_AAC:
136 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AAC);
137 break;
138 case AV_CODEC_ID_AAC_LATM:
139 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AAC_LATM);
140 break;
141 case AV_CODEC_ID_VORBIS:
142 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_VORBIS);
143 break;
144 case AV_CODEC_ID_APE:
145 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_APE);
146 break;
147 case AV_CODEC_ID_AMR_NB:
148 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AMR_NB);
149 break;
150 case AV_CODEC_ID_AMR_WB:
151 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AMR_WB);
152 break;
153 default:
154 MEDIA_LOG_I("codec is not supported right now");
155 }
156 }
157
UpdateOutCaps(const AVCodec * codec,CodecPluginDef & definition)158 void UpdateOutCaps(const AVCodec* codec, CodecPluginDef& definition)
159 {
160 CapabilityBuilder capBuilder;
161 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
162 if (codec->sample_fmts != nullptr) {
163 DiscreteCapability<AudioSampleFormat> values;
164 size_t index {0};
165 for (; codec->sample_fmts[index] != AV_SAMPLE_FMT_NONE; ++index) {
166 values.push_back(ConvFf2PSampleFmt(codec->sample_fmts[index]));
167 }
168 if (index) {
169 capBuilder.SetAudioSampleFormatList(values);
170 }
171 }
172 definition.outCaps.push_back(capBuilder.Build());
173 }
174
UpdatePluginDefinition(const AVCodec * codec,CodecPluginDef & definition)175 void UpdatePluginDefinition(const AVCodec* codec, CodecPluginDef& definition)
176 {
177 UpdateInCaps(codec, definition);
178 UpdateOutCaps(codec, definition);
179 }
180 } // namespace
181 PLUGIN_DEFINITION(FFmpegAudioDecoders, LicenseType::LGPL, RegisterAudioDecoderPlugins, UnRegisterAudioDecoderPlugin);
182
183 namespace OHOS {
184 namespace Media {
185 namespace Plugin {
186 namespace Ffmpeg {
AudioFfmpegDecoderPlugin(std::string name)187 AudioFfmpegDecoderPlugin::AudioFfmpegDecoderPlugin(std::string name) : CodecPlugin(std::move(name)) {}
188
~AudioFfmpegDecoderPlugin()189 AudioFfmpegDecoderPlugin::~AudioFfmpegDecoderPlugin()
190 {
191 DeInitLocked();
192 }
193
Init()194 Status AudioFfmpegDecoderPlugin::Init()
195 {
196 auto ite = codecMap.find(pluginName_);
197 if (ite == codecMap.end()) {
198 MEDIA_LOG_W("cannot find codec with name " PUBLIC_LOG_S, pluginName_.c_str());
199 return Status::ERROR_UNSUPPORTED_FORMAT;
200 }
201 {
202 OSAL::ScopedLock lock(avMutex_);
203 avCodec_ = ite->second;
204 cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame *fp) { av_frame_free(&fp); });
205 }
206
207 {
208 OSAL::ScopedLock lock1(parameterMutex_);
209 audioParameter_[Tag::REQUIRED_OUT_BUFFER_CNT] = (uint32_t) BUFFER_QUEUE_SIZE;
210 if (samplesPerFrameMap.count(avCodec_->id)) {
211 audioParameter_[Tag::AUDIO_SAMPLE_PER_FRAME] = samplesPerFrameMap[avCodec_->id];
212 } else {
213 return Status::ERROR_UNSUPPORTED_FORMAT;
214 }
215 }
216 return Status::OK;
217 }
218
Deinit()219 Status AudioFfmpegDecoderPlugin::Deinit()
220 {
221 MEDIA_LOG_I("Deinit enter.");
222 OSAL::ScopedLock lock(avMutex_);
223 OSAL::ScopedLock lock1(parameterMutex_);
224 return DeInitLocked();
225 }
226
DeInitLocked()227 Status AudioFfmpegDecoderPlugin::DeInitLocked()
228 {
229 MEDIA_LOG_I("DeInitLocked enter.");
230 ResetLocked();
231 avCodec_.reset();
232 cachedFrame_.reset();
233 return Status::OK;
234 }
235
SetParameter(Tag tag,const ValueType & value)236 Status AudioFfmpegDecoderPlugin::SetParameter(Tag tag, const ValueType& value)
237 {
238 OSAL::ScopedLock lock(parameterMutex_);
239 audioParameter_.insert(std::make_pair(tag, value));
240 return Status::OK;
241 }
242
GetParameter(Tag tag,ValueType & value)243 Status AudioFfmpegDecoderPlugin::GetParameter(Tag tag, ValueType& value)
244 {
245 OSAL::ScopedLock lock(parameterMutex_);
246 auto res = audioParameter_.find(tag);
247 if (res != audioParameter_.end()) {
248 value = res->second;
249 return Status::OK;
250 }
251 return Status::ERROR_INVALID_PARAMETER;
252 }
253
254 template <typename T>
FindInParameterMapThenAssignLocked(Tag tag,T & assign)255 Status AudioFfmpegDecoderPlugin::FindInParameterMapThenAssignLocked(Tag tag, T& assign)
256 {
257 if (audioParameter_.count(tag) == 0) {
258 MEDIA_LOG_I("tag " PUBLIC_LOG_D32 "is not set", static_cast<int32_t>(tag));
259 return Status::ERROR_NOT_EXISTED;
260 }
261 const auto& item = audioParameter_.at(tag);
262 if (Any::IsSameTypeWith<T>(item)) {
263 assign = Plugin::AnyCast<T>(item);
264 return Status::OK;
265 }
266 MEDIA_LOG_E("type of tag " PUBLIC_LOG_D32 "not matched", static_cast<int32_t>(tag));
267 return Status::ERROR_MISMATCHED_TYPE;
268 }
269
Prepare()270 Status AudioFfmpegDecoderPlugin::Prepare()
271 {
272 #define FAIL_RET_WHEN_ASSIGN_LOCKED(tag, type, assign) \
273 do { \
274 type tmpVal; \
275 auto ret = FindInParameterMapThenAssignLocked(tag, tmpVal); \
276 if (ret != Status::OK) { \
277 return ret; \
278 } \
279 (assign) = tmpVal; \
280 } while (0)
281 AVCodecContext* context = nullptr;
282 {
283 OSAL::ScopedLock lock(avMutex_);
284 FALSE_RETURN_V(avCodec_ != nullptr, Status::ERROR_WRONG_STATE);
285 context = avcodec_alloc_context3(avCodec_.get());
286 }
287 FALSE_RETURN_V_MSG_E(context != nullptr, Status::ERROR_NO_MEMORY, "can't allocate codec context");
288 auto tmpCtx = std::shared_ptr<AVCodecContext>(context, [](AVCodecContext* ptr) {
289 avcodec_free_context(&ptr);
290 });
291 {
292 OSAL::ScopedLock lock1(parameterMutex_);
293 FAIL_RET_WHEN_ASSIGN_LOCKED(Tag::AUDIO_CHANNELS, int32_t, tmpCtx->channels);
294 FAIL_RET_WHEN_ASSIGN_LOCKED(Tag::AUDIO_SAMPLE_RATE, int32_t, tmpCtx->sample_rate);
295 FAIL_RET_WHEN_ASSIGN_LOCKED(Tag::MEDIA_BITRATE, int64_t, tmpCtx->bit_rate);
296 FAIL_RET_WHEN_ASSIGN_LOCKED(Tag::BITS_PER_CODED_SAMPLE, int32_t, tmpCtx->bits_per_coded_sample);
297 AudioSampleFormat audioSampleFormat = AudioSampleFormat::NONE;
298 auto ret = FindInParameterMapThenAssignLocked(Tag::AUDIO_SAMPLE_FORMAT, audioSampleFormat);
299 FALSE_RETURN_V(ret == Status::OK || ret == Status::ERROR_NOT_EXISTED, ret);
300 auto tmpFmt = ConvP2FfSampleFmt(Plugin::AnyCast<AudioSampleFormat>(audioSampleFormat));
301 FALSE_RETURN_V(tmpFmt != AV_SAMPLE_FMT_NONE, Status::ERROR_INVALID_PARAMETER);
302 tmpCtx->sample_fmt = tmpFmt;
303 tmpCtx->request_sample_fmt = tmpCtx->sample_fmt;
304 ret = AssignExtraDataIfExistsLocked(tmpCtx);
305 FALSE_RETURN_V(ret == Status::OK, ret);
306 }
307 tmpCtx->workaround_bugs = static_cast<uint32_t>(tmpCtx->workaround_bugs) | static_cast<uint32_t>(FF_BUG_AUTODETECT);
308 tmpCtx->err_recognition = 1;
309 {
310 OSAL::ScopedLock lock(avMutex_);
311 avCodecContext_ = tmpCtx;
312 }
313 avPacket_ = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket* ptr) {
314 av_packet_free(&ptr);
315 });
316 return Status::OK;
317 #undef FAIL_RET_WHEN_ASSIGN_LOCKED
318 }
319
AssignExtraDataIfExistsLocked(const std::shared_ptr<AVCodecContext> & ctx)320 Status AudioFfmpegDecoderPlugin::AssignExtraDataIfExistsLocked(const std::shared_ptr<AVCodecContext>& ctx)
321 {
322 if (!ctx) {
323 return Status::ERROR_INVALID_PARAMETER;
324 }
325 if (audioParameter_.count(Tag::MEDIA_CODEC_CONFIG) == 0) {
326 return Status::OK;
327 }
328 const auto& item = audioParameter_.at(Tag::MEDIA_CODEC_CONFIG);
329 if (!Plugin::Any::IsSameTypeWith<CodecConfig>(item)) {
330 return Status::ERROR_MISMATCHED_TYPE;
331 }
332 const auto* codecConfig = Plugin::AnyCast<CodecConfig>(&item);
333 if (codecConfig == nullptr) {
334 return Status::ERROR_UNKNOWN;
335 }
336 if (!codecConfig->empty()) {
337 auto configSize = codecConfig->size();
338 auto allocSize = AlignUp(configSize + AV_INPUT_BUFFER_PADDING_SIZE, 16); // 16
339 ctx->extradata = static_cast<uint8_t*>(av_mallocz(allocSize));
340 if (!ctx->extradata) {
341 return Status::ERROR_NO_MEMORY;
342 }
343 if (memcpy_s(ctx->extradata, allocSize, codecConfig->data(), configSize) != EOK) {
344 MEDIA_LOG_E("init codec context extra data error");
345 av_free(ctx->extradata);
346 ctx->extradata = nullptr;
347 return Status::ERROR_UNKNOWN;
348 }
349 ctx->extradata_size = configSize;
350 }
351 return Status::OK;
352 }
353
ResetLocked()354 Status AudioFfmpegDecoderPlugin::ResetLocked()
355 {
356 MEDIA_LOG_I("ResetLocked enter.");
357 audioParameter_.clear();
358 StopLocked();
359 avCodecContext_.reset();
360 {
361 OSAL::ScopedLock l(bufferMetaMutex_);
362 bufferMeta_.reset();
363 }
364 return Status::OK;
365 }
366
Reset()367 Status AudioFfmpegDecoderPlugin::Reset()
368 {
369 OSAL::ScopedLock lock(avMutex_);
370 OSAL::ScopedLock lock1(parameterMutex_);
371 return ResetLocked();
372 }
373
OpenCtxLocked()374 Status AudioFfmpegDecoderPlugin::OpenCtxLocked()
375 {
376 if (avCodecContext_ == nullptr) {
377 return Status::ERROR_WRONG_STATE;
378 }
379 auto res = avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr);
380 if (res != 0) {
381 MEDIA_LOG_E("avcodec open error " PUBLIC_LOG_S, AVStrError(res).c_str());
382 return Status::ERROR_UNKNOWN;
383 }
384 return Status::OK;
385 }
386
Start()387 Status AudioFfmpegDecoderPlugin::Start()
388 {
389 OSAL::ScopedLock lock(avMutex_);
390 return OpenCtxLocked();
391 }
392
CloseCtxLocked()393 Status AudioFfmpegDecoderPlugin::CloseCtxLocked()
394 {
395 if (avCodecContext_ != nullptr) {
396 auto res = avcodec_close(avCodecContext_.get());
397 if (res != 0) {
398 MEDIA_LOG_E("avcodec close error " PUBLIC_LOG_S, AVStrError(res).c_str());
399 return Status::ERROR_UNKNOWN;
400 }
401 }
402 return Status::OK;
403 }
404
StopLocked()405 Status AudioFfmpegDecoderPlugin::StopLocked()
406 {
407 MEDIA_LOG_I("StopLocked enter.");
408 auto ret = CloseCtxLocked();
409 avCodecContext_.reset();
410 if (outBuffer_) {
411 outBuffer_.reset();
412 }
413 return ret;
414 }
415
Stop()416 Status AudioFfmpegDecoderPlugin::Stop()
417 {
418 MEDIA_LOG_I("Stop enter.");
419 OSAL::ScopedLock lock(avMutex_);
420 return StopLocked();
421 }
422
Flush()423 Status AudioFfmpegDecoderPlugin::Flush()
424 {
425 MEDIA_LOG_I("Flush entered.");
426 OSAL::ScopedLock lock(avMutex_);
427 if (avCodecContext_ != nullptr) {
428 avcodec_flush_buffers(avCodecContext_.get());
429 }
430 MEDIA_LOG_I("Flush exit.");
431 return Status::OK;
432 }
433
QueueInputBuffer(const std::shared_ptr<Buffer> & inputBuffer,int32_t timeoutMs)434 Status AudioFfmpegDecoderPlugin::QueueInputBuffer(const std::shared_ptr<Buffer>& inputBuffer, int32_t timeoutMs)
435 {
436 MEDIA_LOG_DD("queue input buffer");
437 (void)timeoutMs;
438 if (inputBuffer->IsEmpty() && !(inputBuffer->flag & BUFFER_FLAG_EOS)) {
439 MEDIA_LOG_E("Decoder does not support fd buffer.");
440 return Status::ERROR_INVALID_DATA;
441 }
442 Status ret = Status::OK;
443 {
444 OSAL::ScopedLock lock(avMutex_);
445 if (avCodecContext_ == nullptr) {
446 return Status::ERROR_WRONG_STATE;
447 }
448 ret = SendBufferLocked(inputBuffer);
449 if (ret == Status::OK || ret == Status::END_OF_STREAM) {
450 OSAL::ScopedLock l(bufferMetaMutex_);
451 if (inputBuffer == nullptr || inputBuffer->GetBufferMeta() == nullptr) {
452 MEDIA_LOG_E("Decoder input buffer is null or get buffer meta fail.");
453 return Status::ERROR_INVALID_DATA;
454 }
455 bufferMeta_ = inputBuffer->GetBufferMeta()->Clone();
456 }
457 }
458 return ret;
459 }
460
QueueOutputBuffer(const std::shared_ptr<Buffer> & outputBuffer,int32_t timeoutMs)461 Status AudioFfmpegDecoderPlugin::QueueOutputBuffer(const std::shared_ptr<Buffer>& outputBuffer, int32_t timeoutMs)
462 {
463 MEDIA_LOG_DD("queue output buffer");
464 (void)timeoutMs;
465 if (!outputBuffer) {
466 MEDIA_LOG_E("Queue out buffer is null.");
467 return Status::ERROR_INVALID_PARAMETER;
468 }
469 outBuffer_ = outputBuffer;
470 return SendOutputBuffer();
471 }
472
SendOutputBuffer()473 Status AudioFfmpegDecoderPlugin::SendOutputBuffer()
474 {
475 MEDIA_LOG_DD("send output buffer");
476 Status status = ReceiveBuffer();
477 if (status == Status::OK || status == Status::END_OF_STREAM) {
478 {
479 OSAL::ScopedLock l(bufferMetaMutex_);
480 FALSE_RETURN_V_MSG_E(outBuffer_ != nullptr, Status::ERROR_NULL_POINTER, "Send out buffer is null.");
481 outBuffer_->UpdateBufferMeta(*bufferMeta_);
482 }
483 dataCallback_->OnOutputBufferDone(outBuffer_);
484 }
485 outBuffer_.reset();
486 return status;
487 }
488
SendBufferLocked(const std::shared_ptr<Buffer> & inputBuffer)489 Status AudioFfmpegDecoderPlugin::SendBufferLocked(const std::shared_ptr<Buffer>& inputBuffer)
490 {
491 if (inputBuffer && !(inputBuffer->flag & BUFFER_FLAG_EOS)) {
492 auto inputMemory = inputBuffer->GetMemory();
493 if (inputMemory == nullptr) {
494 return Status::ERROR_NULL_POINTER;
495 }
496 const uint8_t* ptr = inputMemory->GetReadOnlyData();
497 auto bufferLength = inputMemory->GetSize();
498 // pad to data if needed
499 if (bufferLength % AV_INPUT_BUFFER_PADDING_SIZE != 0) {
500 if (paddedBufferSize_ < bufferLength + AV_INPUT_BUFFER_PADDING_SIZE) {
501 paddedBufferSize_ = bufferLength + AV_INPUT_BUFFER_PADDING_SIZE;
502 paddedBuffer_.reserve(paddedBufferSize_);
503 MEDIA_LOG_I("increase padded buffer size to " PUBLIC_LOG_ZU, paddedBufferSize_);
504 }
505 paddedBuffer_.assign(ptr, ptr + bufferLength);
506 paddedBuffer_.insert(paddedBuffer_.end(), AV_INPUT_BUFFER_PADDING_SIZE, 0);
507 ptr = paddedBuffer_.data();
508 }
509 avPacket_->data = const_cast<uint8_t*>(ptr);
510 avPacket_->size = bufferLength;
511 avPacket_->pts = inputBuffer->pts;
512 }
513 auto ret = avcodec_send_packet(avCodecContext_.get(), avPacket_.get());
514 av_packet_unref(avPacket_.get());
515 if (ret == 0) {
516 return Status::OK;
517 } else if (ret == AVERROR(EAGAIN)) {
518 return Status::ERROR_AGAIN;
519 } else if (ret == AVERROR_EOF) { // AVStrError(ret).c_str() == "End of file"
520 return Status::END_OF_STREAM;
521 } else {
522 MEDIA_LOG_E("send buffer error " PUBLIC_LOG_S, AVStrError(ret).c_str());
523 return Status::ERROR_UNKNOWN;
524 }
525 }
526
ReceiveFrameSucc(const std::shared_ptr<Buffer> & ioInfo)527 Status AudioFfmpegDecoderPlugin::ReceiveFrameSucc(const std::shared_ptr<Buffer>& ioInfo)
528 {
529 FALSE_RETURN_V_MSG_E(ioInfo != nullptr, Status::ERROR_INVALID_PARAMETER, "ioInfo buffer is null.");
530 int32_t channels = cachedFrame_->channels;
531 int32_t samples = cachedFrame_->nb_samples;
532 auto sampleFormat = static_cast<AVSampleFormat>(cachedFrame_->format);
533 int32_t bytePerSample = av_get_bytes_per_sample(sampleFormat);
534 size_t outputSize = static_cast<size_t>(samples) * static_cast<size_t>(bytePerSample) *
535 static_cast<size_t>(channels);
536 auto ioInfoMem = ioInfo->GetMemory();
537 if (ioInfoMem == nullptr) {
538 MEDIA_LOG_E("ReceiveFrameSucc ioInfo GetMemory nullptr");
539 return Status::ERROR_UNKNOWN;
540 }
541 if (ioInfoMem->GetCapacity() < outputSize) {
542 MEDIA_LOG_W("output buffer size is not enough");
543 return Status::ERROR_NO_MEMORY;
544 }
545 if (av_sample_fmt_is_planar(avCodecContext_->sample_fmt)) {
546 size_t planarSize = outputSize / channels;
547 for (int32_t idx = 0; idx < channels; idx++) {
548 ioInfoMem->Write(cachedFrame_->extended_data[idx], planarSize);
549 }
550 } else {
551 ioInfoMem->Write(cachedFrame_->data[0], outputSize);
552 }
553 ioInfo->pts = static_cast<uint64_t>(cachedFrame_->pts);
554 return Status::OK;
555 }
556 /*
557 Audio/Video Track is composed of multiple BufferGroups,
558 and BufferGroup is composed of multiple Buffers.
559 Each BufferGroup has a pts, it's the pts of the first buffer in group.
560 We should calculate the other buffer's pts.
561 ┌────────────────────────────────────────────┐
562 │ │
563 │ Audio / Video Track │
564 │ │
565 ├─────────────────────┬──────────────────────┤
566 │ │ │
567 │ BufferGroup │ BufferGroup │
568 │ │ │
569 ├──────┬──────┬───────┼──────┬───────┬───────┤
570 │ │ │ │ │ │ │
571 │Buffer│Buffer│Buffer │Buffer│Buffer │Buffer │
572 │ │ │ │ │ │ │
573 └──────┴──────┴───────┴──────┴───────┴───────┘
574 */
ReceiveBufferLocked(const std::shared_ptr<Buffer> & ioInfo)575 Status AudioFfmpegDecoderPlugin::ReceiveBufferLocked(const std::shared_ptr<Buffer>& ioInfo)
576 {
577 FALSE_RETURN_V_MSG_E(ioInfo != nullptr, Status::ERROR_INVALID_PARAMETER, "ioInfo buffer is null.");
578 Status status;
579 auto ret = avcodec_receive_frame(avCodecContext_.get(), cachedFrame_.get());
580 if (ret >= 0) {
581 if (cachedFrame_->pts != AV_NOPTS_VALUE) {
582 preBufferGroupPts_ = curBufferGroupPts_;
583 curBufferGroupPts_ = cachedFrame_->pts;
584 if (bufferGroupPtsDistance == 0) {
585 bufferGroupPtsDistance = abs(curBufferGroupPts_ - preBufferGroupPts_);
586 }
587 if (bufferIndex_ >= bufferNum_) {
588 bufferNum_ = bufferIndex_;
589 }
590 bufferIndex_ = 1;
591 } else {
592 bufferIndex_++;
593 if (abs(curBufferGroupPts_ - preBufferGroupPts_) > bufferGroupPtsDistance) {
594 cachedFrame_->pts = curBufferGroupPts_;
595 preBufferGroupPts_ = curBufferGroupPts_;
596 } else {
597 cachedFrame_->pts = curBufferGroupPts_ + abs(curBufferGroupPts_ - preBufferGroupPts_) *
598 (bufferIndex_ - 1) / bufferNum_;
599 }
600 }
601 MEDIA_LOG_DD("receive one frame");
602 status = ReceiveFrameSucc(ioInfo);
603 } else if (ret == AVERROR_EOF) {
604 MEDIA_LOG_I("eos received");
605 if (ioInfo->GetMemory() == nullptr) {
606 return Status::ERROR_NULL_POINTER;
607 }
608 ioInfo->GetMemory()->Reset();
609 ioInfo->flag = BUFFER_FLAG_EOS;
610 avcodec_flush_buffers(avCodecContext_.get());
611 status = Status::END_OF_STREAM;
612 } else if (ret == AVERROR(EAGAIN)) {
613 status = Status::ERROR_NOT_ENOUGH_DATA;
614 } else {
615 MEDIA_LOG_E("audio decoder receive error: " PUBLIC_LOG_S, AVStrError(ret).c_str());
616 status = Status::ERROR_UNKNOWN;
617 }
618 av_frame_unref(cachedFrame_.get());
619 return status;
620 }
621
ReceiveBuffer()622 Status AudioFfmpegDecoderPlugin::ReceiveBuffer()
623 {
624 std::shared_ptr<Buffer> ioInfo {outBuffer_};
625 if ((ioInfo == nullptr) || ioInfo->IsEmpty() || ioInfo->GetBufferMeta() == nullptr ||
626 (ioInfo->GetBufferMeta()->GetType() != BufferMetaType::AUDIO)) {
627 MEDIA_LOG_W("cannot fetch valid buffer to output");
628 return Status::ERROR_NO_MEMORY;
629 }
630 Status status;
631 {
632 OSAL::ScopedLock l(avMutex_);
633 if (avCodecContext_ == nullptr) {
634 return Status::ERROR_WRONG_STATE;
635 }
636 status = ReceiveBufferLocked(ioInfo);
637 }
638 return status;
639 }
640
GetAllocator()641 std::shared_ptr<Allocator> AudioFfmpegDecoderPlugin::GetAllocator()
642 {
643 return nullptr;
644 }
645 } // Ffmpeg
646 } // namespace Plugin
647 } // namespace Media
648 } // namespace OHOS
649