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