diff --git a/frameworks/native/avcodeclist/avcodeclist_impl.cpp b/frameworks/native/avcodeclist/avcodeclist_impl.cpp index 525d1fb93fbebbb839c558c13ce7c99ba72f1550..dd13461b7ed6700f57d1bc4b59c56b2b5326a415 100644 --- a/frameworks/native/avcodeclist/avcodeclist_impl.cpp +++ b/frameworks/native/avcodeclist/avcodeclist_impl.cpp @@ -41,6 +41,7 @@ const std::vector AUDIO_MIME_VEC = { std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_FLAC), std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_RAW), std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_G711MU), + std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_G711A), std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_COOK), std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AC3), std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AVS3DA), diff --git a/frameworks/native/capi/avcodec/native_avcodec_base.cpp b/frameworks/native/capi/avcodec/native_avcodec_base.cpp index 73930cf5e686e4ae8ce7b273013edffd7541b2b1..49af3a3391944b7cbbfc835f46df3613ecdff064 100644 --- a/frameworks/native/capi/avcodec/native_avcodec_base.cpp +++ b/frameworks/native/capi/avcodec/native_avcodec_base.cpp @@ -43,6 +43,7 @@ const char *OH_AVCODEC_MIMETYPE_SUBTITLE_SRT = "application/x-subrip"; const char *OH_AVCODEC_MIMETYPE_AUDIO_LBVC = "audio/lbvc"; const char *OH_AVCODEC_MIMETYPE_SUBTITLE_WEBVTT = "text/vtt"; const char *OH_AVCODEC_MIMETYPE_AUDIO_RAW = "audio/raw"; +const char *OH_AVCODEC_MIMETYPE_AUDIO_G711A = "audio/g711a"; const char *OH_ED_KEY_TIME_STAMP = "timeStamp"; const char *OH_ED_KEY_EOS = "endOfStream"; diff --git a/interfaces/inner_api/native/avcodec_codec_name.h b/interfaces/inner_api/native/avcodec_codec_name.h index d6a1d8c2152ed64cc98a903be3e85f39359b45e7..f7567e816a7748afd34d0bbb0b904e454381f69b 100644 --- a/interfaces/inner_api/native/avcodec_codec_name.h +++ b/interfaces/inner_api/native/avcodec_codec_name.h @@ -31,6 +31,7 @@ public: static constexpr std::string_view AUDIO_DECODER_AMRWB_NAME = "OH.Media.Codec.Decoder.Audio.Amrwb"; static constexpr std::string_view AUDIO_DECODER_VIVID_NAME = "OH.Media.Codec.Decoder.Audio.Vivid"; static constexpr std::string_view AUDIO_DECODER_G711MU_NAME = "OH.Media.Codec.Decoder.Audio.G711mu"; + static constexpr std::string_view AUDIO_DECODER_G711A_NAME = "OH.Media.Codec.Decoder.Audio.G711a"; static constexpr std::string_view AUDIO_DECODER_APE_NAME = "OH.Media.Codec.Decoder.Audio.Ape"; static constexpr std::string_view AUDIO_DECODER_L2HC_NAME = "OH.Media.Codec.Decoder.Audio.L2HC"; static constexpr std::string_view AUDIO_DECODER_LBVC_NAME = "OH.Media.Codec.Decoder.Audio.LBVC"; diff --git a/interfaces/inner_api/native/avcodec_info.h b/interfaces/inner_api/native/avcodec_info.h index 28a0c7c75210a8103265a9951ef5b9812dc2f299..8db029994cc53186b68cac63f6db3612f94a05b7 100644 --- a/interfaces/inner_api/native/avcodec_info.h +++ b/interfaces/inner_api/native/avcodec_info.h @@ -613,6 +613,7 @@ public: static constexpr std::string_view AUDIO_FLAC = "audio/flac"; static constexpr std::string_view AUDIO_RAW = "audio/raw"; static constexpr std::string_view AUDIO_G711MU = "audio/g711mu"; + static constexpr std::string_view AUDIO_G711A = "audio/g711a"; static constexpr std::string_view AUDIO_COOK = "audio/cook"; static constexpr std::string_view AUDIO_AC3 = "audio/ac3"; static constexpr std::string_view AUDIO_VIVID = "audio/av3a"; diff --git a/interfaces/inner_api/native/avcodec_mime_type.h b/interfaces/inner_api/native/avcodec_mime_type.h index 03d58852925630e24fc83cef6d49be4af0819517..b927f2b991396a8d06c026599301cacbca2de66d 100644 --- a/interfaces/inner_api/native/avcodec_mime_type.h +++ b/interfaces/inner_api/native/avcodec_mime_type.h @@ -35,6 +35,7 @@ public: static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_AMRWB = "audio/amr-wb"; static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_VIVID = "audio/av3a"; static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_G711MU = "audio/g711mu"; + static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_G711A = "audio/g711a"; static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_L2HC = "audio/l2hc"; static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_LBVC = "audio/lbvc"; static constexpr std::string_view MEDIA_MIMETYPE_AUDIO_APE = "audio/x-ape"; diff --git a/interfaces/kits/c/native_avcodec_base.h b/interfaces/kits/c/native_avcodec_base.h index ef28fedff421ef8a26a28f14eeb091675e404550..2baf1ef0ca75e41b19c3d159617bc5f996cccde8 100644 --- a/interfaces/kits/c/native_avcodec_base.h +++ b/interfaces/kits/c/native_avcodec_base.h @@ -329,6 +329,14 @@ extern const char *OH_AVCODEC_MIMETYPE_SUBTITLE_WEBVTT; */ extern const char *OH_AVCODEC_MIMETYPE_AUDIO_RAW; +/** + * @brief Enumerates the mime types of audio G711 A-law codec. + * + * @syscap SystemCapability.Multimedia.Media.CodecBase + * @since 20 + */ +extern const char *OH_AVCODEC_MIMETYPE_AUDIO_G711A; + /** * @brief Key for timeStamp in surfacebuffer, value type is int64_t. * @syscap SystemCapability.Multimedia.Media.CodecBase diff --git a/services/engine/codeclist/audio_codeclist_info.cpp b/services/engine/codeclist/audio_codeclist_info.cpp index 4ccd175e7b88b5cabe932d9cb6adae792b9ce91e..f174ac073cfed577e5049e2d4f34795179c6a51e 100644 --- a/services/engine/codeclist/audio_codeclist_info.cpp +++ b/services/engine/codeclist/audio_codeclist_info.cpp @@ -37,6 +37,7 @@ constexpr int MAX_CHANNEL_COUNT_MP3 = 2; constexpr int MAX_CHANNEL_COUNT_APE = 2; constexpr int MAX_CHANNEL_COUNT_OPUS = 2; constexpr int MAX_CHANNEL_COUNT_RAW = 16; +constexpr int MAX_CHANNEL_COUNT_G711A = 6; constexpr int MIN_BIT_RATE_AAC = 8000; constexpr int MAX_BIT_RATE_AAC = 960000; @@ -48,6 +49,9 @@ const std::vector AUDIO_AMRWB_SAMPLE_RATE = {16000}; const std::vector AUDIO_G711MU_SAMPLE_RATE = {8000}; +const std::vector AUDIO_G711A_SAMPLE_RATE = {8000, 11025, 12000, 16000, 22050, 24000, 32000, + 44100, 48000}; + const std::vector AUDIO_FLAC_SAMPLE_RATE = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000}; @@ -102,6 +106,7 @@ const std::vector AUDIO_AC3_SAMPLE_RATE = {32000, 44100, 48000}; #endif constexpr int MAX_BIT_RATE_G711MU_DECODER = 64000; constexpr int MAX_BIT_RATE_G711MU_ENCODER = 64000; +constexpr int MAX_BIT_RATE_G711A_DECODER = 64000; const std::string VENDOR_AAC_LIB_PATH = std::string(AV_CODEC_PATH) + "/libaac_enc.z.so"; @@ -470,6 +475,20 @@ CapabilityData AudioCodeclistInfo::GetG711muEncoderCapability() return audioG711muEncoderCapability; } +CapabilityData AudioCodeclistInfo::GetG711aDecoderCapability() +{ + CapabilityData audioG711aDecoderCapability; + audioG711aDecoderCapability.codecName = AVCodecCodecName::AUDIO_DECODER_G711A_NAME; + audioG711aDecoderCapability.codecType = AVCODEC_TYPE_AUDIO_DECODER; + audioG711aDecoderCapability.mimeType = AVCodecMimeType::MEDIA_MIMETYPE_AUDIO_G711A; + audioG711aDecoderCapability.isVendor = false; + audioG711aDecoderCapability.bitrate = Range(1, MAX_BIT_RATE_G711A_DECODER); + audioG711aDecoderCapability.channels = Range(1, MAX_CHANNEL_COUNT_G711A); + audioG711aDecoderCapability.sampleRate = AUDIO_G711A_SAMPLE_RATE; + audioG711aDecoderCapability.maxInstance = MAX_SUPPORT_AUDIO_INSTANCE; + return audioG711aDecoderCapability; +} + #ifdef SUPPORT_CODEC_COOK CapabilityData AudioCodeclistInfo::GetCookDecoderCapability() { @@ -513,6 +532,7 @@ AudioCodeclistInfo::AudioCodeclistInfo() GetAmrwbDecoderCapability(), GetG711muDecoderCapability(), GetRawDecoderCapability(), GetAacEncoderCapability(), GetFlacEncoderCapability(), GetOpusEncoderCapability(), GetG711muEncoderCapability(), GetAPEDecoderCapability(), GetMP3EncoderCapability(), + GetG711aDecoderCapability(), #ifdef AV_CODEC_AUDIO_VIVID_CAPACITY GetVividDecoderCapability(), GetAmrnbEncoderCapability(), GetAmrwbEncoderCapability(), GetLbvcDecoderCapability(), GetLbvcEncoderCapability(), GetL2hcEncoderCapability(), diff --git a/services/engine/codeclist/audio_codeclist_info.h b/services/engine/codeclist/audio_codeclist_info.h index 6e1aea0a54f2d7a85f7d444822be315de1c59314..d2554d66e106e884bf2600aa83bb4d3a90e9105f 100644 --- a/services/engine/codeclist/audio_codeclist_info.h +++ b/services/engine/codeclist/audio_codeclist_info.h @@ -36,6 +36,7 @@ public: CapabilityData GetFlacEncoderCapability(); CapabilityData GetG711muEncoderCapability(); CapabilityData GetG711muDecoderCapability(); + CapabilityData GetG711aDecoderCapability(); CapabilityData GetAPEDecoderCapability(); CapabilityData GetMP3EncoderCapability(); CapabilityData GetLbvcDecoderCapability(); diff --git a/services/media_engine/plugins/BUILD.gn b/services/media_engine/plugins/BUILD.gn index a304aeae3d10f58a4fec40303c968ecb4696ff0f..30f663a81d5b7d3d254ab13f825965c6fd5f5e84 100644 --- a/services/media_engine/plugins/BUILD.gn +++ b/services/media_engine/plugins/BUILD.gn @@ -20,6 +20,7 @@ group("av_codec_media_engine_plugins") { "ffmpeg_adapter:media_plugin_FFmpegMuxer", "ffmpeg_adapter/audio_decoder:media_plugin_FFmpegAudioDecoders", "ffmpeg_adapter/audio_decoder/g711mu:media_plugin_G711muAudioDecoder", + "ffmpeg_adapter/audio_decoder/g711a:media_plugin_G711aAudioDecoder", "ffmpeg_adapter/audio_decoder/lbvc:media_plugin_LbvcAudioDecoder", "ffmpeg_adapter/audio_decoder/raw:media_plugin_RawAudioDecoder", "ffmpeg_adapter/audio_encoder:media_plugin_FFmpegAudioEncoders", diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/BUILD.gn b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c11266b6310dee57b88cdaa8a9593d9272dc38d7 --- /dev/null +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (C) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/multimedia/av_codec/config.gni") + +config("ffmpeg_adapter_config") { + defines = [ + "HST_ANY_WITH_NO_RTTI", + "MEDIA_OHOS", + ] + + cflags = [ + "-fno-exceptions", + "-Wall", + "-fno-common", + "-fstack-protector-all", + "-Wshadow", + "-FPIC", + "-FS", + "-O2", + "-D_FORTIFY_SOURCE=2", + "-Wformat=2", + "-Wdate-time", + ] + + cflags_cc = [ + "-std=c++17", + "-fno-rtti", + ] + + include_dirs = [ + "$av_codec_root_dir/interfaces", + "$av_codec_root_dir/interfaces/inner_api/native", + "$av_codec_root_dir/services/dfx/include", + "$av_codec_root_dir/services/media_engine/plugins/ffmpeg_adapter", + "$av_codec_root_dir/services/media_engine/plugins/ffmpeg_adapter/common", + "$av_codec_root_dir/services/media_engine/plugins/ffmpeg_adapter/audio_decoder", + "$av_codec_root_dir/services/media_engine/plugins/ffmpeg_adapter/demuxer", + ] +} + +ohos_shared_library("media_plugin_G711aAudioDecoder") { + branch_protector_ret = "pac_ret" + sanitize = av_codec_sanitize + install_enable = true + configs = [ + ":ffmpeg_adapter_config", + "$av_codec_root_dir/services/dfx:av_codec_service_log_dfx_public_config", + ] + + sources = [ "audio_g711a_decoder_plugin.cpp" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "media_foundation:media_foundation", + ] + + relative_install_dir = "media/media_plugins" + subsystem_name = "multimedia" + part_name = "av_codec" +} diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/audio_g711a_decoder_plugin.cpp b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/audio_g711a_decoder_plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a9d1bd3a220977d5a8f3eabd713fb799e479752 --- /dev/null +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/audio_g711a_decoder_plugin.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "audio_g711a_decoder_plugin.h" +#include "avcodec_audio_common.h" +#include "avcodec_codec_name.h" +#include "avcodec_log.h" +#include "avcodec_mime_type.h" +#include "plugin/codec_plugin.h" +#include "plugin/plugin_definition.h" + + +namespace { +using namespace OHOS::Media; +using namespace OHOS::Media::Plugins; +using namespace G711a; + +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO, "AvCodec-AudioG711aDecoderPlugin"}; +constexpr int MIN_CHANNELS = 1; +constexpr int MIN_SAMPLE_RATE = 8000; +constexpr int INPUT_BUFFER_SIZE_DEFAULT = 8192; // 20ms:160 +constexpr int OUTPUT_BUFFER_SIZE_DEFAULT = 16384; // 20ms:320 +constexpr float TIME_ONE_SECOND = 1000000.f; +constexpr int AVCODEC_G711A_SHIFT = 3; +constexpr int AVCODEC_G711A_SHIFT_BASE = 2; +constexpr int AVCODEC_G711A_SEG_SHIFT = 4; +constexpr int AVCODEC_G711A_SEG_MASK = 0x70; +constexpr int AVCODEC_G711A_SIGN_BIT = 0x80; +constexpr int AVCODEC_G711A_MAX_INT32 = 0x7fffffff; + +Status RegisterAudioDecoderPlugins(const std::shared_ptr& reg) +{ + CodecPluginDef definition; + definition.name = std::string(OHOS::MediaAVCodec::AVCodecCodecName::AUDIO_DECODER_G711A_NAME); + definition.pluginType = PluginType::AUDIO_DECODER; + definition.rank = 100; // 100 + definition.SetCreator([](const std::string& name) -> std::shared_ptr { + return std::make_shared(name); + }); + + Capability cap; + cap.SetMime(MimeType::AUDIO_G711A); + cap.AppendFixedKey(Tag::MEDIA_CODEC_MODE, CodecMode::SOFTWARE); + + definition.AddInCaps(cap); + // do not delete the codec in the deleter + if (reg->AddPlugin(definition) != Status::OK) { + AVCODEC_LOGE("AudioG711aDecoderPlugin Register Failure"); + return Status::ERROR_UNKNOWN; + } + + return Status::OK; +} + +void UnRegisterAudioDecoderPlugin() {} + +PLUGIN_DEFINITION(G711aAudioDecoder, LicenseType::APACHE_V2, RegisterAudioDecoderPlugins, + UnRegisterAudioDecoderPlugin); +} // namespace + +namespace OHOS { +namespace Media { +namespace Plugins { +namespace G711a { +AudioG711aDecoderPlugin::AudioG711aDecoderPlugin(const std::string& name) + : CodecPlugin(std::move(name)), + decodeBytes_(0), + channels_(MIN_CHANNELS), + sampleRate_(MIN_SAMPLE_RATE), + pts_(0), + maxInputSize_(INPUT_BUFFER_SIZE_DEFAULT), + maxOutputSize_(OUTPUT_BUFFER_SIZE_DEFAULT), + sampleFormat_(AudioSampleFormat::INVALID_WIDTH) +{ +} + +AudioG711aDecoderPlugin::~AudioG711aDecoderPlugin() +{ +} + +Status AudioG711aDecoderPlugin::Init() +{ + std::lock_guard lock(avMutex_); + decodeInput_.reserve(maxInputSize_); + return Status::OK; +} + +Status AudioG711aDecoderPlugin::Start() +{ + return Status::OK; +} + +int16_t AudioG711aDecoderPlugin::G711aLawDecode(uint8_t aLawValue) +{ + uint16_t tmp = 0; + // sabc wxyz + aLawValue ^= 0x55; + uint8_t offsetNum = (aLawValue & AVCODEC_G711A_SEG_MASK) >> AVCODEC_G711A_SEG_SHIFT; // 4 -> 0x0000 0abc + uint16_t offsetValue = offsetNum > 0 ? 0x21 : 1; // 0x21 -> 0010 0001 + offsetNum = offsetNum > 1 ? offsetNum + AVCODEC_G711A_SHIFT_BASE : AVCODEC_G711A_SHIFT; + offsetValue |= ((aLawValue & 0xf) << 1); // 000w xyz0 | 0010 0001 + tmp |= offsetValue << offsetNum; + return ((aLawValue & AVCODEC_G711A_SIGN_BIT) ? static_cast(tmp) : -static_cast(tmp)); +} + +Status AudioG711aDecoderPlugin::QueueInputBuffer(const std::shared_ptr& inputBuffer) +{ + auto memory = inputBuffer->memory_; + int32_t size = memory->GetSize(); + CHECK_AND_RETURN_RET_LOG(memory != nullptr && size >= 0, Status::ERROR_UNKNOWN, + "SendBuffer buffer size < 0. size : %{public}d", size); + if (size > memory->GetCapacity()) { + AVCODEC_LOGE("send input buffer > allocate size. size : %{public}d, allocate size : %{public}d", + size, memory->GetCapacity()); + return Status::ERROR_UNKNOWN; + } + if ((size_t)size > decodeInput_.capacity()) { + AVCODEC_LOGI("g711a size change form %{public}zu to %{public}d", decodeInput_.capacity(), size); + decodeInput_.reserve(size); + maxInputSize_ = size; + } + { + std::lock_guard lock(avMutex_); + decodeBytes_ = size; + memory->Read(reinterpret_cast(decodeInput_.data()), decodeBytes_, 0); + pts_ = inputBuffer->pts_; + dataCallback_->OnInputBufferDone(inputBuffer); + } + return Status::OK; +} + +Status AudioG711aDecoderPlugin::QueueOutputBuffer(std::shared_ptr& outputBuffer) +{ + if (!outputBuffer) { + AVCODEC_LOGE("AudioG711aDecoderPlugin Queue out buffer is null."); + return Status::ERROR_INVALID_PARAMETER; + } + if (decodeBytes_ <= 0) { + return Status::ERROR_NOT_ENOUGH_DATA; + } + { + std::lock_guard lock(avMutex_); + auto memory = outputBuffer->memory_; + int32_t outSize = static_cast(sizeof(int16_t)) * decodeBytes_; + CHECK_AND_RETURN_RET_LOG(memory != nullptr && memory->GetCapacity() >= outSize, Status::ERROR_UNKNOWN, + "memory not enough, capacity:%{public}d, outSize:%{public}d", memory->GetCapacity(), outSize); + int16_t *decOutputData = reinterpret_cast(memory->GetAddr()); + uint8_t *decInputData = reinterpret_cast(decodeInput_.data()); + for (int32_t i = 0; i < decodeBytes_ ; ++i) { + decOutputData[i] = G711aLawDecode(decInputData[i]); + } + memory->SetSize(outSize); + outputBuffer->pts_ = pts_; + if (sampleFormat_ == SAMPLE_S16LE && sampleRate_ > 0 && channels_ > 0) { + float usPerSample = TIME_ONE_SECOND / sampleRate_; + outputBuffer->duration_ = static_cast((outSize / 2.0f / channels_) * usPerSample); // 2 bytes + } + dataCallback_->OnOutputBufferDone(outputBuffer); + decodeBytes_ = 0; + } + return Status::OK; +} + +Status AudioG711aDecoderPlugin::Reset() +{ + std::lock_guard lock(avMutex_); + audioParameter_.Clear(); + return Status::OK; +} + +Status AudioG711aDecoderPlugin::Release() +{ + std::lock_guard lock(avMutex_); + return Status::OK; +} + +Status AudioG711aDecoderPlugin::Flush() +{ + std::lock_guard lock(avMutex_); + return Status::OK; +} + +Status AudioG711aDecoderPlugin::SetParameter(const std::shared_ptr ¶meter) +{ + std::lock_guard lock(avMutex_); + Status ret = Status::OK; + + if (parameter->Find(Tag::AUDIO_CHANNEL_COUNT) != parameter->end()) { + parameter->Get(channels_); + } else { + AVCODEC_LOGE("AudioG711aDecoderPlugin no AUDIO_CHANNEL_COUNT"); + ret = Status::ERROR_INVALID_PARAMETER; + } + + if (parameter->Find(Tag::AUDIO_SAMPLE_RATE) != parameter->end()) { + parameter->Get(sampleRate_); + } else { + AVCODEC_LOGE("AudioG711aDecoderPlugin no AUDIO_SAMPLE_RATE"); + ret = Status::ERROR_INVALID_PARAMETER; + } + + if (channels_ <= 0 || sampleRate_ <= 0) { + AVCODEC_LOGE("AudioG711aDecoderPlugin not supported channles:%{public}d or sampleRate:%{public}d", + channels_, sampleRate_); + ret = Status::ERROR_INVALID_PARAMETER; + } + + if (parameter->Find(Tag::AUDIO_MAX_INPUT_SIZE) != parameter->end()) { + parameter->Get(maxInputSize_); + AVCODEC_LOGI("AudioG711aDecoderPlugin SetParameter maxInputSize_: %{public}d", maxInputSize_); + if (maxInputSize_ < 0 || maxInputSize_ > AVCODEC_G711A_MAX_INT32 / sizeof(int16_t)) { + maxInputSize_ = INPUT_BUFFER_SIZE_DEFAULT; + } + maxOutputSize_ = maxInputSize_ * static_cast(sizeof(int16_t)); + decodeInput_.reserve(maxInputSize_); + } + + if (parameter->Find(Tag::AUDIO_SAMPLE_FORMAT) != parameter->end()) { + parameter->Get(sampleFormat_); + } else { + AVCODEC_LOGW("AudioG711aDecoderPlugin no AUDIO_SAMPLE_FORMAT"); + } + + audioParameter_ = *parameter; + return ret; +} + +Status AudioG711aDecoderPlugin::GetParameter(std::shared_ptr ¶meter) +{ + std::lock_guard lock(avMutex_); + AVCODEC_LOGD("AudioG711aDecoderPlugin GetParameter maxInputSize_: %{public}d", maxInputSize_); + audioParameter_.Set(maxInputSize_); + audioParameter_.Set(maxOutputSize_); + *parameter = audioParameter_; + return Status::OK; +} + +Status AudioG711aDecoderPlugin::Prepare() +{ + return Status::OK; +} + +Status AudioG711aDecoderPlugin::Stop() +{ + std::lock_guard lock(avMutex_); + return Status::OK; +} + +Status AudioG711aDecoderPlugin::GetInputBuffers(std::vector>& inputBuffers) +{ + return Status::OK; +} + +Status AudioG711aDecoderPlugin::GetOutputBuffers(std::vector>& outputBuffers) +{ + return Status::OK; +} + +} // namespace G711mu +} // namespace Plugins +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/audio_g711a_decoder_plugin.h b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/audio_g711a_decoder_plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..7beec59103f4605caa474da0e11f0300eb3666ee --- /dev/null +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/g711a/audio_g711a_decoder_plugin.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HISTREAMER_AUDIO_G711A_DECODER_PLUGIN_H +#define HISTREAMER_AUDIO_G711A_DECODER_PLUGIN_H + +#include +#include +#include +#include "buffer/avbuffer.h" +#include "meta/meta.h" +#include "nocopyable.h" +#include "plugin/codec_plugin.h" +#include "plugin/plugin_definition.h" + +namespace OHOS { +namespace Media { +namespace Plugins { +namespace G711a { +class AudioG711aDecoderPlugin : public CodecPlugin { +public: + explicit AudioG711aDecoderPlugin(const std::string& name); + + ~AudioG711aDecoderPlugin(); + + Status Init() override; + + Status Prepare() override; + + Status Reset() override; + + Status Start() override; + + Status Stop() override; + + Status SetParameter(const std::shared_ptr ¶meter) override; + + Status GetParameter(std::shared_ptr ¶meter) override; + + Status QueueInputBuffer(const std::shared_ptr &inputBuffer) override; + + Status QueueOutputBuffer(std::shared_ptr &outputBuffer) override; + + Status GetInputBuffers(std::vector> &inputBuffers) override; + + Status GetOutputBuffers(std::vector> &outputBuffers) override; + + Status Flush() override; + + Status Release() override; + + Status SetDataCallback(DataCallback* dataCallback) override + { + dataCallback_ = dataCallback; + return Status::OK; + } + +private: + Meta audioParameter_ ; + mutable std::mutex avMutex_ {}; + DataCallback* dataCallback_ {nullptr}; + + int16_t G711aLawDecode(uint8_t aLawValue); + + std::vector decodeInput_; + int32_t decodeBytes_; + int32_t channels_; + int32_t sampleRate_; + int64_t pts_; + int32_t maxInputSize_; + int32_t maxOutputSize_; + AudioSampleFormat sampleFormat_; +}; +} // namespace G711a +} // namespace Plugins +} // namespace Media +} // namespace OHOS + +#endif // HISTREAMER_AUDIO_G711A_DECODER_PLUGIN_H \ No newline at end of file diff --git a/test/BUILD.gn b/test/BUILD.gn index f5a0a5bd810156c3d6113a1d2724ee331b276b27..1cec9cb128bd5c4f218c46e538ba04975f4243b0 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -37,6 +37,7 @@ group("av_codec_unit_test") { "unittest/audio_test:audio_encoder_plugin_unit_test", "unittest/audio_test:audio_ffmpeg_base_codec_unit_test", "unittest/audio_test:audio_g711mu_encoder_plugin_unit_test", + "unittest/audio_test:audio_g711a_decoder_unit_test", "unittest/audio_test:audio_hdi_codec_inner_unit_test", "unittest/audio_test:audio_lbvc_plugin_unit_test", "unittest/audio_test:audio_resample_unit_test", diff --git a/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.cpp b/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.cpp index f4140b296b52e71136e067091c44888801810862..e1a320e27ccf0c0e31634e72d4f04013eca158c9 100644 --- a/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.cpp +++ b/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.cpp @@ -59,6 +59,8 @@ constexpr string_view INPUT_G711MU_FILE_PATH = "/data/test/media/g711mu_8kHz.dat constexpr string_view OUTPUT_G711MU_PCM_FILE_PATH = "/data/test/media/g711mu_8kHz_decode.pcm"; constexpr string_view INPUT_APE_FILE_PATH = "/data/test/media/ape.dat"; constexpr string_view OUTPUT_APE_PCM_FILE_PATH = "/data/test/media/ape_decode.pcm"; +constexpr string_view INPUT_G711A_FILE_PATH = "/data/test/media/g711a_1c_8000.dat"; +constexpr string_view OUTPUT_G711A_PCM_FILE_PATH = "/data/test/media/g711a_1c_8000_decode.pcm"; } // namespace static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) @@ -123,6 +125,9 @@ bool ADecBufferDemo::InitFile(AudioBufferFormatType audioType) } else if (audioType == AudioBufferFormatType::TYPE_APE) { inputFile_.open(INPUT_APE_FILE_PATH, std::ios::binary); pcmOutputFile_.open(OUTPUT_APE_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary); + } else if (audioType == AudioBufferFormatType::TYPE_G711A) { + inputFile_.open(INPUT_G711A_FILE_PATH, std::ios::binary); + pcmOutputFile_.open(OUTPUT_G711A_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary); } else { std::cout << "audio format type not support\n"; return false; @@ -144,7 +149,8 @@ void ADecBufferDemo::RunCase(AudioBufferFormatType audioType) OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AAC_IS_ADTS.data(), DEFAULT_AAC_TYPE); OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), OH_BitsPerSample::SAMPLE_S16LE); - } else if (audioType == AudioBufferFormatType::TYPE_AMRNB || audioType == AudioBufferFormatType::TYPE_G711MU) { + } else if (audioType == AudioBufferFormatType::TYPE_AMRNB || audioType == AudioBufferFormatType::TYPE_G711MU || + audioType == AudioBufferFormatType::TYPE_G711A) { channelCount = 1; sampleRate = AMRNB_SAMPLE_RATE; } else if (audioType == AudioBufferFormatType::TYPE_AMRWB || audioType == AudioBufferFormatType::TYPE_APE) { @@ -245,6 +251,8 @@ int32_t ADecBufferDemo::CreateDec() audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_G711MU_NAME).data()); } else if (audioType_ == AudioBufferFormatType::TYPE_APE) { audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_APE_NAME).data()); + } else if (audioType_ == AudioBufferFormatType::TYPE_G711A) { + audioDec_ = OH_AudioCodec_CreateByName((AVCodecCodecName::AUDIO_DECODER_G711A_NAME).data()); } else { return AVCS_ERR_INVALID_VAL; } @@ -400,7 +408,7 @@ void ADecBufferDemo::InputFunc() buffer->buffer_->memory_->SetSize(size); DEMO_CHECK_AND_BREAK_LOG(inputFile_.gcount() == size, "Fatal: read buffer fail"); - cout << "SetSize" << size << endl; + cout << "SetSize: " << size << endl; int32_t ret; if (isFirstFrame_) { buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_CODEC_DATA; diff --git a/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.h b/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.h index 83f4d2f0197cadb2b21fc815a39f8ed74db1aa64..78896cee970311331da7d46e85678b45118f6d9a 100644 --- a/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.h +++ b/test/nativedemo/audio_demo/avcodec_audio_avbuffer_decoder_demo.h @@ -38,7 +38,8 @@ enum class AudioBufferFormatType : int32_t { TYPE_AMRWB = 5, TYPE_G711MU = 6, TYPE_APE = 7, - TYPE_MAX = 8, + TYPE_G711A = 8, + TYPE_MAX = 9, }; class ADecBufferSignal { diff --git a/test/nativedemo/av_codec_demo.cpp b/test/nativedemo/av_codec_demo.cpp index 47e8a7fb057c901a7700fa70482623f0f5d2abec..9ab2a5261ad6875247eb582b2a4b68cc5e6e7c73 100644 --- a/test/nativedemo/av_codec_demo.cpp +++ b/test/nativedemo/av_codec_demo.cpp @@ -114,6 +114,7 @@ static int RunAudioAVBufferDecoder() cout << "5: AMR-WB" << endl; cout << "6: G711MU" << endl; cout << "7: APE" << endl; + cout << "8: G711A" << endl; string mode; AudioBufferFormatType audioFormatType = AudioBufferFormatType::TYPE_AAC; @@ -134,6 +135,8 @@ static int RunAudioAVBufferDecoder() audioFormatType = AudioBufferFormatType::TYPE_G711MU; } else if (mode == "7") { audioFormatType = AudioBufferFormatType::TYPE_APE; + } else if (mode == "8") { + audioFormatType = AudioBufferFormatType::TYPE_G711A; } else { cout << "no that selection" << endl; return 0; diff --git a/test/unittest/audio_test/BUILD.gn b/test/unittest/audio_test/BUILD.gn index 1d6a06668a3c0d3eaaf1275797bdaaffa407e153..fe6e5dae29b3fb8739b0f804e85f4e5a6da42e06 100644 --- a/test/unittest/audio_test/BUILD.gn +++ b/test/unittest/audio_test/BUILD.gn @@ -933,4 +933,54 @@ ohos_unittest("audio_ffmpeg_base_codec_unit_test") { resource_config_file = "$av_codec_root_dir/test/unittest/resources/ohos_test.xml" +} + +################################################################################################################## +ohos_unittest("audio_g711a_decoder_unit_test") { + sanitize = av_codec_test_sanitize + module_out_path = module_output_path + include_dirs = av_codec_unittest_include_dirs + include_dirs += [ + "./", + "$av_codec_root_dir/interfaces/kits/c", + "$av_codec_root_dir/services/engine/common/include", + "$av_codec_root_dir/services/engine/base/include", + "$av_codec_root_dir/services/engine/codec/include/audio/decoder", + "$av_codec_root_dir/services/utils/include", + "$av_codec_root_dir/services/engine/codec/include/audio", + ] + + cflags = [ + "-fno-exceptions", + "-Wall", + "-fno-common", + "-fstack-protector-strong", + "-Wshadow", + "-FPIC", + "-FS", + "-O2", + "-D_FORTIFY_SOURCE=2", + "-Wformat=2", + "-Wdate-time", +] + + cflags_cc = cflags + + public_configs = [] + + if (av_codec_support_test) { + sources = [ "./audio_g711a_decoder_unit_test.cpp" ] + } + + deps = [ + "$av_codec_root_dir/interfaces/inner_api/native:av_codec_client", + "$av_codec_root_dir/interfaces/kits/c:capi_packages", + "$av_codec_root_dir/services/services:av_codec_service", + "$av_codec_root_dir/services/utils:av_codec_service_utils", + ] + + external_deps = [ + "c_utils:utils", + "media_foundation:media_foundation", + ] } \ No newline at end of file diff --git a/test/unittest/audio_test/audio_g711a_decoder_unit_test.cpp b/test/unittest/audio_test/audio_g711a_decoder_unit_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4269494c40e7680e808132c6837e44325248ad1f --- /dev/null +++ b/test/unittest/audio_test/audio_g711a_decoder_unit_test.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "plugin/plugin_manager_v2.h" +#include "plugin/codec_plugin.h" +#include "avcodec_codec_name.h" + +using namespace std; +using namespace testing::ext; +using namespace OHOS::Media; +using namespace OHOS::Media::Plugins; + +namespace OHOS { +namespace Media { +namespace Plugins { + +const string CODEC_G711A_DEC_NAME = std::string(MediaAVCodec::AVCodecCodecName::AUDIO_DECODER_G711A_NAME); +constexpr int32_t G711A_SAMPLE_RATE = 16000; +constexpr int64_t G711A_BIT_RATE = 6000; +constexpr int32_t G711A_SIZE = 640; // 40ms +constexpr int32_t G711A_MAX_INPUT_SIZE = 8192; +constexpr int32_t G711A_MAX_OUTPUT_SIZE = G711A_MAX_INPUT_SIZE * 2; +static constexpr int32_t TEST_INPUT_SIZE = 8; +static const uint8_t TEST_INPUT_ARR[TEST_INPUT_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; +static const uint8_t TEST_OUTPUT_ARR[TEST_INPUT_SIZE * 2] = {0x80, 0xeb, 0x00, 0xa6, 0xf8, 0xfe, 0x60, 0xfb, 0x80, 0x1c, + 0x00, 0x7a, 0x88, 0x01, 0xa0, 0x06}; + +class G711aUnitTest : public testing::Test, public DataCallback { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; + void OnInputBufferDone(const shared_ptr &inputBuffer) override + { + (void)inputBuffer; + } + void OnOutputBufferDone(const shared_ptr &outputBuffer) override + { + (void)outputBuffer; + } + void OnEvent(const shared_ptr event) override + { + (void)event; + } +protected: + // std::unique_ptr soFile_; + shared_ptr meta_ = nullptr; + shared_ptr plugin_ = nullptr; + shared_ptr avBuffer_ = nullptr; +}; + +void G711aUnitTest::SetUpTestCase(void) +{ +} + +void G711aUnitTest::TearDownTestCase(void) +{ +} + +void G711aUnitTest::SetUp(void) +{ + auto tmp = PluginManagerV2::Instance().CreatePluginByName(CODEC_G711A_DEC_NAME); + plugin_ = reinterpret_pointer_cast(tmp); + meta_ = make_shared(); + meta_->Set(1); + meta_->Set(G711A_SAMPLE_RATE); + meta_->Set(AudioSampleFormat::SAMPLE_S16LE); + meta_->Set(G711A_BIT_RATE); + auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE); + avBuffer_ = AVBuffer::CreateAVBuffer(avAllocator, (G711A_SIZE << 1)); + avBuffer_->memory_->SetSize(G711A_SIZE); +} + +void G711aUnitTest::TearDown(void) +{ + if (plugin_) { + plugin_->Release(); + plugin_ = nullptr; + meta_ = nullptr; + } +} + +HWTEST_F(G711aUnitTest, SetParamter_001, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->Init(); + plugin_->SetDataCallback(this); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + meta_->Remove(Tag::AUDIO_CHANNEL_COUNT); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + meta_->Set(1); + meta_->Remove(Tag::AUDIO_SAMPLE_RATE); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + meta_->Set(G711A_SAMPLE_RATE); + meta_->Remove(Tag::AUDIO_SAMPLE_FORMAT); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + meta_->Set(AudioSampleFormat::SAMPLE_S16LE); + meta_->Set(G711A_MAX_INPUT_SIZE); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + plugin_->Start(); + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer_), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer_), Status::OK); + avBuffer_->memory_->SetSize(0); + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer_), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer_), Status::ERROR_NOT_ENOUGH_DATA); + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, SetParamter_002, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->Init(); + plugin_->SetDataCallback(this); + meta_->Set(0); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + meta_->Set(-1); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + meta_->Set(1); + + meta_->Set(0); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + meta_->Set(-1); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, GetParamter_001, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + shared_ptr tmpMeta = make_shared(); + int32_t maxInputSize = 0; + int32_t maxOutputSize = 0; + plugin_->Init(); + plugin_->Reset(); + plugin_->SetDataCallback(this); + int32_t testMaxInput = G711A_MAX_INPUT_SIZE + 1; + meta_->Set(testMaxInput); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + EXPECT_EQ(plugin_->GetParameter(tmpMeta), Status::OK); + tmpMeta->Get(maxInputSize); + EXPECT_EQ(maxInputSize, testMaxInput); + tmpMeta->Get(maxOutputSize); + EXPECT_EQ(maxOutputSize, testMaxInput * sizeof(int16_t)); + + testMaxInput = -1; + meta_->Set(testMaxInput); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + EXPECT_EQ(plugin_->GetParameter(tmpMeta), Status::OK); + tmpMeta->Get(maxInputSize); + EXPECT_EQ(maxInputSize, G711A_MAX_INPUT_SIZE); + tmpMeta->Get(maxOutputSize); + EXPECT_EQ(maxOutputSize, G711A_MAX_OUTPUT_SIZE); + + testMaxInput = 0xf7777777 / 2 + 1; + meta_->Set(testMaxInput); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + EXPECT_EQ(plugin_->GetParameter(tmpMeta), Status::OK); + tmpMeta->Get(maxInputSize); + EXPECT_EQ(maxInputSize, G711A_MAX_INPUT_SIZE); + tmpMeta->Get(maxOutputSize); + EXPECT_EQ(maxOutputSize, G711A_MAX_OUTPUT_SIZE); + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, Decode_001, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->Init(); + plugin_->SetDataCallback(this); + meta_->Set(AudioSampleFormat::SAMPLE_S16LE); + meta_->Set(G711A_MAX_INPUT_SIZE + 1); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + plugin_->Start(); + uint8_t *buffer = avBuffer_->memory_->GetAddr(); + for (int i = 0; i < TEST_INPUT_SIZE; i++) { + buffer[i] = TEST_INPUT_ARR[i]; + } + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer_), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer_), Status::OK); + buffer = avBuffer_->memory_->GetAddr(); + EXPECT_EQ(avBuffer_->memory_->GetSize(), G711A_SIZE * 2); + EXPECT_EQ(avBuffer_->duration_, 40000); // 40000us -> 40ms + for (int i = 0; i < TEST_INPUT_SIZE * 2; i++) { + EXPECT_EQ(buffer[i], TEST_OUTPUT_ARR[i]); + } + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, Decode_002, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->Init(); + plugin_->SetDataCallback(this); + meta_->Set(AudioSampleFormat::SAMPLE_S32LE); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + plugin_->Start(); + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer_), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer_), Status::OK); + EXPECT_NE(avBuffer_->duration_, 40000); // 40000us -> 40ms + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, Decode_003, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->SetDataCallback(this); + meta_->Set(AudioSampleFormat::SAMPLE_S32LE); + EXPECT_EQ(plugin_->SetParameter(meta_), Status::OK); + plugin_->Init(); + plugin_->Start(); + auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE); + shared_ptr avBuffer = AVBuffer::CreateAVBuffer(avAllocator, (G711A_MAX_OUTPUT_SIZE << 1)); + avBuffer->memory_->SetSize(G711A_MAX_OUTPUT_SIZE); + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer), Status::OK); + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, Decode_004, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->Init(); + plugin_->SetDataCallback(this); + meta_->Set(0); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + plugin_->Start(); + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer_), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer_), Status::OK); + EXPECT_NE(avBuffer_->duration_, 40000); // 40000us -> 40ms + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +HWTEST_F(G711aUnitTest, Decode_005, TestSize.Level1) +{ + if (plugin_ == nullptr) { + cout << "g711a plugin is nullptr!" << endl; + return; + } + plugin_->Init(); + plugin_->SetDataCallback(this); + meta_->Set(0); + EXPECT_NE(plugin_->SetParameter(meta_), Status::OK); + plugin_->Start(); + EXPECT_EQ(plugin_->QueueInputBuffer(avBuffer_), Status::OK); + EXPECT_EQ(plugin_->QueueOutputBuffer(avBuffer_), Status::OK); + EXPECT_NE(avBuffer_->duration_, 40000); // 40000us -> 40ms + plugin_->Flush(); + plugin_->Stop(); + EXPECT_EQ(plugin_->Reset(), Status::OK); +} + +} // namespace Plugins +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/resources/audio_res/g711a_1c_8000.dat b/test/unittest/resources/audio_res/g711a_1c_8000.dat new file mode 100644 index 0000000000000000000000000000000000000000..f87f51dfd6457c377ed47c6958a9b1bdb7c99c5a Binary files /dev/null and b/test/unittest/resources/audio_res/g711a_1c_8000.dat differ