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