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