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