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