diff --git a/bundle.json b/bundle.json index cd77d72b006052c48cd6ad7da3ea594c41780fc9..bbb19c9b7bcf2da4934123c0aa3c175168585a75 100644 --- a/bundle.json +++ b/bundle.json @@ -71,7 +71,8 @@ "libxml2", "video_processing_engine", "curl", - "openssl" + "openssl", + "bundle_framework" ], "third_party": [ "bounds_checking_function" diff --git a/frameworks/native/avcodec/avcodec_audio_codec_impl.cpp b/frameworks/native/avcodec/avcodec_audio_codec_impl.cpp index fed505d4498d0f0a80a2f088d4e4476d6bf3b82b..9277477f7bbc720d16836b4b66fc399a38a748c4 100644 --- a/frameworks/native/avcodec/avcodec_audio_codec_impl.cpp +++ b/frameworks/native/avcodec/avcodec_audio_codec_impl.cpp @@ -505,6 +505,8 @@ void AVCodecAudioCodecImpl::AVCodecInnerCallback::OnOutputFormatChanged(const Fo { if (impl_->callback_) { impl_->callback_->OnOutputFormatChanged(format); + } else { + AVCODEC_LOGE("receive format changed, but impl callback is nullptr"); } } diff --git a/frameworks/native/capi/avcodec/native_audio_codec.cpp b/frameworks/native/capi/avcodec/native_audio_codec.cpp index 67f6bf30779c58110299638417e5341e081fe1a5..a89755d6e3d4a49400334a416a30048143faa7a2 100644 --- a/frameworks/native/capi/avcodec/native_audio_codec.cpp +++ b/frameworks/native/capi/avcodec/native_audio_codec.cpp @@ -80,6 +80,8 @@ public: OHOS::sptr object = new (std::nothrow) OH_AVFormat(format); // The object lifecycle is controlled by the current function stack callback_.onStreamChanged(codec_, reinterpret_cast(object.GetRefPtr()), userData_); + } else { + AVCODEC_LOGE("receive format changed but callback is nullptr"); } } diff --git a/interfaces/inner_api/native/audio_decoder_filter.h b/interfaces/inner_api/native/audio_decoder_filter.h index 658e6b408217eafc225ee34f12199f71fd79a638..d64fa2159d37bbfa613666b7cce5bbe719c06e9d 100644 --- a/interfaces/inner_api/native/audio_decoder_filter.h +++ b/interfaces/inner_api/native/audio_decoder_filter.h @@ -109,6 +109,7 @@ private: std::shared_ptr onLinkedResultCallback_; std::shared_ptr mediaCodec_; + std::shared_ptr mediaCodecCallback_; sptr inputBufferQueueProducer_; bool isDrmProtected_ = false; @@ -132,6 +133,8 @@ public: void OnOutputBufferDone(const std::shared_ptr &outputBuffer) override; + void OnOutputFormatChanged(const std::shared_ptr &format) override; + private: std::weak_ptr audioDecoderFilter_; }; diff --git a/services/engine/codec/include/audio/audio_codec.h b/services/engine/codec/include/audio/audio_codec.h index 711646969ad233fdc3e2b4ad0eaa3fc909204e43..041353d6514dd0e38e621c54548add69cd806e63 100644 --- a/services/engine/codec/include/audio/audio_codec.h +++ b/services/engine/codec/include/audio/audio_codec.h @@ -37,9 +37,12 @@ public: void OnOutputBufferDone(const std::shared_ptr &outputBuffer) override; + void OnOutputFormatChanged(const std::shared_ptr &format) override; + private: std::shared_ptr codec_; }; + class AudioCodec : public std::enable_shared_from_this, public CodecBase { public: explicit AudioCodec() @@ -174,6 +177,16 @@ public: } } + void OnOutputFormatChanged(const std::shared_ptr &format) + { + auto realPtr = callback_.lock(); + if (realPtr != nullptr) { + Media::Format outputFormat; + outputFormat.SetMeta(format); + realPtr->OnOutputFormatChanged(outputFormat); + } + } + #ifdef SUPPORT_DRM int32_t SetAudioDecryptionConfig(const sptr &keySession, const bool svpFlag) override @@ -204,6 +217,14 @@ void AudioCodecCallback::OnOutputBufferDone(const std::shared_ptr &out codec_->OnOutputBufferDone(outputBuffer); } } + +void AudioCodecCallback::OnOutputFormatChanged(const std::shared_ptr &format) +{ + if (codec_) { + codec_->OnOutputFormatChanged(format); + } +} + } // namespace MediaAVCodec } // namespace OHOS #endif \ No newline at end of file diff --git a/services/media_engine/filters/audio_decoder_filter.cpp b/services/media_engine/filters/audio_decoder_filter.cpp index 9415d7a33b1a8e6dde5de0b2264e907d27442ff0..4c1540cd9a4a5cd44dd0bb5d9d83ed2bee40466d 100644 --- a/services/media_engine/filters/audio_decoder_filter.cpp +++ b/services/media_engine/filters/audio_decoder_filter.cpp @@ -106,6 +106,7 @@ AudioDecoderFilter::AudioDecoderFilter(std::string name, FilterType type): Filte AudioDecoderFilter::~AudioDecoderFilter() { + mediaCodecCallback_ = nullptr; mediaCodec_->Release(); MEDIA_LOG_I("audio decoder filter destroy"); } @@ -201,6 +202,7 @@ Status AudioDecoderFilter::DoFlush() Status AudioDecoderFilter::DoRelease() { MEDIA_LOG_E("AudioDecoderFilter::Release."); + mediaCodecCallback_ = nullptr; return (Status)mediaCodec_->Release(); } @@ -272,9 +274,8 @@ Status AudioDecoderFilter::OnLinked(StreamType inType, const std::shared_ptrInit(mime, false); - std::shared_ptr mediaCodecCallback - = std::make_shared(shared_from_this()); - mediaCodec_->SetCodecCallback(mediaCodecCallback); + mediaCodecCallback_ = std::make_shared(shared_from_this()); + mediaCodec_->SetCodecCallback(mediaCodecCallback_); auto ret = mediaCodec_->Configure(meta); if (ret != (int32_t)Status::OK && ret != (int32_t)Status::ERROR_INVALID_STATE) { @@ -464,6 +465,12 @@ void AudioDecoderCallback::OnOutputBufferDone(const std::shared_ptr &o { (void)outputBuffer; } + +void AudioDecoderCallback::OnOutputFormatChanged(const std::shared_ptr &format) +{ + (void)format; +} + } // namespace Pipeline } // namespace MEDIA } // namespace OHOS diff --git a/services/media_engine/modules/BUILD.gn b/services/media_engine/modules/BUILD.gn index 91a5eaf49e178db7c5b95bd1035b97700b4655d4..76d8efcf8a68e00fc2bd65a9ab581beae80ecaf8 100644 --- a/services/media_engine/modules/BUILD.gn +++ b/services/media_engine/modules/BUILD.gn @@ -95,6 +95,8 @@ ohos_shared_library("av_codec_media_engine_modules") { external_deps = [ "audio_framework:audio_capturer", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "c_utils:utils", "ffmpeg:libohosffmpeg", "graphic_surface:surface", @@ -105,6 +107,7 @@ ohos_shared_library("av_codec_media_engine_modules") { "ipc:ipc_single", "media_foundation:media_foundation", "safwk:system_ability_fwk", + "samgr:samgr_proxy", ] if (av_codec_support_drm) { diff --git a/services/media_engine/modules/media_codec/media_codec.cpp b/services/media_engine/modules/media_codec/media_codec.cpp index 50ea14e1597831da5269276cda551f8662ea797f..26a79f7e9c92caef5f567211c9248acf837ee807 100644 --- a/services/media_engine/modules/media_codec/media_codec.cpp +++ b/services/media_engine/modules/media_codec/media_codec.cpp @@ -19,13 +19,18 @@ #include "plugin/plugin_manager_v2.h" #include "osal/utils/dump_buffer.h" #include "avcodec_trace.h" -#include "plugin/plugin_manager_v2.h" +#include "bundle_mgr_interface.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" namespace { constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_AUDIO, "MediaCodec" }; const std::string INPUT_BUFFER_QUEUE_NAME = "MediaCodecInputBufferQueue"; constexpr int32_t DEFAULT_BUFFER_NUM = 8; constexpr int32_t TIME_OUT_MS = 50; +constexpr uint32_t API_SUPPORT_AUDIO_FORMAT_CHANGED = 15; +constexpr uint32_t INVALID_API_VERSION = 0; +constexpr uint32_t API_VERSION_MOD = 1000; const std::string DUMP_PARAM = "a"; const std::string DUMP_FILE_NAME = "player_audio_decoder_output.pcm"; } // namespace @@ -188,6 +193,9 @@ int32_t MediaCodec::SetCodecCallback(const std::shared_ptr= API_SUPPORT_AUDIO_FORMAT_CHANGED)); return (int32_t)Status::OK; } @@ -802,7 +810,25 @@ void MediaCodec::ClearInputBuffer() } } -void MediaCodec::OnEvent(const std::shared_ptr event) {} +void MediaCodec::OnEvent(const std::shared_ptr event) +{ + if (event->type != Plugins::PluginEventType::AUDIO_OUTPUT_FORMAT_CHANGED) { + return; + } + + if (!isSupportAudioFormatChanged_) { + MEDIA_LOG_W("receive audio format changed but api version is low"); + return; + } + + auto realPtr = mediaCodecCallback_.lock(); + if (realPtr != nullptr) { + std::shared_ptr format = std::make_shared(AnyCast(event->param)); + realPtr->OnOutputFormatChanged(format); + } else { + MEDIA_LOG_E("receive AUDIO_OUTPUT_FORMAT_CHANGED, but lock callback fail"); + } +} std::string MediaCodec::StateToString(CodecState state) { @@ -837,5 +863,28 @@ void MediaCodec::OnDumpInfo(int32_t fd) return; } } + +uint32_t MediaCodec::GetApiVersion() +{ + uint32_t apiVersion = INVALID_API_VERSION; + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr remoteObject = + systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + sptr iBundleMgr = OHOS::iface_cast(remoteObject); + if (iBundleMgr == nullptr) { + MEDIA_LOG_W("GetApiVersion IBundleMgr is nullptr"); + return apiVersion; + } + AppExecFwk::BundleInfo bundleInfo; + if (iBundleMgr->GetBundleInfoForSelf(0, bundleInfo) == ERR_OK) { + apiVersion = bundleInfo.targetVersion % API_VERSION_MOD; + MEDIA_LOG_I("GetApiVersion targetVersion: %{public}u", bundleInfo.targetVersion); + } else { + MEDIA_LOG_W("GetApiVersion failed, call by SA or test maybe"); + } + return apiVersion; +} + } // namespace Media } // namespace OHOS diff --git a/services/media_engine/modules/media_codec/media_codec.h b/services/media_engine/modules/media_codec/media_codec.h index fe5c230d601d83ed2b46e7364062e52d7415a861..c87188c22ec8956c40a2743ef49d55eef0997502 100644 --- a/services/media_engine/modules/media_codec/media_codec.h +++ b/services/media_engine/modules/media_codec/media_codec.h @@ -74,6 +74,8 @@ public: virtual void OnError(CodecErrorType errorType, int32_t errorCode) = 0; virtual void OnOutputBufferDone(const std::shared_ptr &outputBuffer) = 0; + + virtual void OnOutputFormatChanged(const std::shared_ptr &format) = 0; }; class MediaCodec : public Plugins::DataCallback { @@ -156,6 +158,8 @@ private: void HandleAudioCencDecryptError(); + uint32_t GetApiVersion(); + private: std::shared_ptr codecPlugin_; std::shared_ptr inputBufferQueue_; @@ -170,6 +174,7 @@ private: bool isSurfaceMode_; bool isBufferMode_; bool isDump_ = false; + bool isSupportAudioFormatChanged_ = true; std::string dumpPrefix_ = ""; int32_t outputBufferCapacity_; std::string codecPluginName_; diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp index 9813141ba04cff50e90ba2ed9817d65a91dd9566..ea0d39349f2701c6d371e9ed524c83e33ec2b136 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.cpp @@ -38,6 +38,7 @@ namespace Ffmpeg { FfmpegBaseDecoder::FfmpegBaseDecoder() : isFirst(true), hasExtra_(false), + currentFrameFormatChanged_(false), maxInputSize_(-1), nextPts_(0), durationTime_(0.f), @@ -152,6 +153,7 @@ Status FfmpegBaseDecoder::ReceiveBuffer(std::shared_ptr &outBuffer) if (cachedFrame_->pts == AV_NOPTS_VALUE) { cachedFrame_->pts = nextPts_; } + CheckFormatChange(); status = ReceiveFrameSucc(outBuffer); dataCallback_->OnOutputBufferDone(outBuffer); } else if (ret == AVERROR_EOF) { @@ -181,12 +183,36 @@ Status FfmpegBaseDecoder::ConvertPlanarFrame(std::shared_ptr &outBuffe return Status::OK; } +void FfmpegBaseDecoder::CheckFormatChange() +{ + int32_t preSampleRate = 0; + int32_t preChannels = 0; + AudioSampleFormat preFormat = INVALID_WIDTH; + AudioSampleFormat currentFormat = FFMpegConverter::ConvertFFMpegToOHAudioFormat(destFmt_); + format_->GetData(Tag::AUDIO_SAMPLE_RATE, preSampleRate); + format_->GetData(Tag::AUDIO_CHANNEL_COUNT, preChannels); + format_->GetData(Tag::AUDIO_SAMPLE_FORMAT, preFormat); + if (preSampleRate != avCodecContext_->sample_rate || preChannels != avCodecContext_->channels || + preFormat != currentFormat) { + AVCODEC_LOGI("decode format changed, sample rate:%{public}d->%{public}d, channel:%{public}d->%{public}d, " + "sample format:%{public}d->%{public}d", preSampleRate, avCodecContext_->sample_rate, + preChannels, avCodecContext_->channels, preFormat, currentFormat); + currentFrameFormatChanged_ = true; + format_->SetData(Tag::AUDIO_SAMPLE_RATE, avCodecContext_->sample_rate); + format_->SetData(Tag::AUDIO_CHANNEL_COUNT, avCodecContext_->channels); + format_->SetData(Tag::AUDIO_SAMPLE_FORMAT, currentFormat); + std::shared_ptr changeEvent = std::make_shared(); + changeEvent->type = PluginEventType::AUDIO_OUTPUT_FORMAT_CHANGED; + changeEvent->param = *(format_.get()); + changeEvent->description = "audio_output_format_changed"; + dataCallback_->OnEvent(changeEvent); + } +} + Status FfmpegBaseDecoder::ReceiveFrameSucc(std::shared_ptr &outBuffer) { - if (isFirst) { + if (isFirst || currentFrameFormatChanged_) { isFirst = false; - format_->SetData(Tag::AUDIO_SAMPLE_FORMAT, - FFMpegConverter::ConvertFFMpegToOHAudioFormat(avCodecContext_->sample_fmt)); auto layout = FFMpegConverter::ConvertFFToOHAudioChannelLayoutV2(avCodecContext_->channel_layout, avCodecContext_->channels); if (avCodecContext_->channel_layout == 0) { @@ -198,10 +224,12 @@ Status FfmpegBaseDecoder::ReceiveFrameSucc(std::shared_ptr &outBuffer) avCodecContext_->channels, avCodecContext_->ch_layout.nb_channels); format_->SetData(Tag::AUDIO_CHANNEL_LAYOUT, layout); if (InitResample() != Status::OK) { + currentFrameFormatChanged_ = false; return Status::ERROR_UNKNOWN; } int32_t sampleRate = avCodecContext_->sample_rate; durationTime_ = TIME_BASE_FFMPEG / sampleRate; + currentFrameFormatChanged_ = false; } nextPts_ = cachedFrame_->pts + static_cast(cachedFrame_->nb_samples * durationTime_); auto outFrame = cachedFrame_; @@ -346,7 +374,8 @@ Status FfmpegBaseDecoder::InitResample() AVCODEC_LOGI("ffmpeg default sample_fmt :%{public}" PRId32, avCodecContext_->sample_fmt); AVCODEC_LOGI("need sample_fmt :%{public}" PRId32, destFmt_); AVCODEC_LOGI("frameSize :%{public}" PRId32, avCodecContext_->frame_size); - if (avCodecContext_->sample_fmt != destFmt_) { + if ((!needResample_ && avCodecContext_->sample_fmt != destFmt_) + || (needResample_ && currentFrameFormatChanged_)) { ResamplePara resamplePara; resamplePara.channels = static_cast(avCodecContext_->channels); resamplePara.sampleRate = static_cast(avCodecContext_->sample_rate); diff --git a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.h b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.h index 708da9b28a72e42134e436fbc909733cca8e6abc..abe3fde6ac52a14e5cde1f1ba629b56008e85300 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.h +++ b/services/media_engine/plugins/ffmpeg_adapter/audio_decoder/ffmpeg_base_decoder.h @@ -79,6 +79,7 @@ public: private: bool isFirst; bool hasExtra_; + bool currentFrameFormatChanged_; int32_t maxInputSize_; int64_t nextPts_; float durationTime_; @@ -108,6 +109,7 @@ private: Status ConvertPlanarFrame(std::shared_ptr &outBuffer); void EnableResample(AVSampleFormat destFmt); Status SetCodecExtradata(const std::shared_ptr &format); + void CheckFormatChange(); }; } // namespace Ffmpeg } // namespace Plugins diff --git a/services/services/codec/server/codec_server.cpp b/services/services/codec/server/codec_server.cpp index 0c5a27fabc3a1d1fa6bfd121c12b2ffb500e105b..dda846a695eaea99c2561be843517d964ac01b85 100644 --- a/services/services/codec/server/codec_server.cpp +++ b/services/services/codec/server/codec_server.cpp @@ -980,6 +980,8 @@ void CodecBaseCallback::OnOutputFormatChanged(const Format &format) { if (codec_ != nullptr) { codec_->OnOutputFormatChanged(format); + } else { + AVCODEC_LOGI("CodecBaseCallback receive output format changed but codec is nullptr"); } } @@ -1020,6 +1022,8 @@ void VCodecBaseCallback::OnOutputFormatChanged(const Format &format) { if (codec_ != nullptr) { codec_->OnOutputFormatChanged(format); + } else { + AVCODEC_LOGE("receive output format changed, but codec is nullptr"); } } diff --git a/test/unittest/audio_encoder_filter_test/BUILD.gn b/test/unittest/audio_encoder_filter_test/BUILD.gn index 8c2ff321e3b245eff3284a9608877ec2102386df..3bf6c25851b2e0dec33d56399c34bf9b88324029 100644 --- a/test/unittest/audio_encoder_filter_test/BUILD.gn +++ b/test/unittest/audio_encoder_filter_test/BUILD.gn @@ -89,6 +89,8 @@ ohos_unittest("audio_encoder_filter_unitest") { external_deps = [ "audio_framework:audio_capturer", "audio_framework:audio_client", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "c_utils:utils", "ffmpeg:libohosffmpeg", "graphic_surface:surface", @@ -100,6 +102,7 @@ ohos_unittest("audio_encoder_filter_unitest") { "media_foundation:media_foundation", "media_foundation:native_media_core", "safwk:system_ability_fwk", + "samgr:samgr_proxy", ] resource_config_file = diff --git a/test/unittest/audio_test/audio_decoder_avbuffer_capi_unit_test.cpp b/test/unittest/audio_test/audio_decoder_avbuffer_capi_unit_test.cpp index 493b9999431cac421c389610e5d3998c6940b0b4..f2d6a69406002828bc60cedf9af6dab436eb3fa3 100644 --- a/test/unittest/audio_test/audio_decoder_avbuffer_capi_unit_test.cpp +++ b/test/unittest/audio_test/audio_decoder_avbuffer_capi_unit_test.cpp @@ -55,7 +55,7 @@ constexpr int32_t ABNORMAL_SAMPLE_FORMAT = AudioSampleFormat::INVALID_WIDTH; constexpr int32_t FLAC_S24_SAMPLE_FORMAT = AudioSampleFormat::SAMPLE_S24LE; constexpr int64_t BITS_RATE[7] = {199000, 261000, 60000, 320000}; constexpr uint32_t AMRWB_SAMPLE_RATE = 16000; -constexpr uint32_t AMRNB_SAMPLE_RATE = 8000; +constexpr uint32_t SAMPLE_RATE_8K = 8000; constexpr uint32_t ONE_CHANNEL_COUNT = 1; constexpr uint32_t ABNORMAL_MAX_CHANNEL_COUNT = 999999; constexpr uint32_t ABNORMAL_MIN_CHANNEL_COUNT = 0; @@ -66,6 +66,8 @@ constexpr string_view INPUT_AAC_FILE_PATH = "/data/test/media/aac_2c_44100hz_199 constexpr string_view OUTPUT_AAC_PCM_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k.pcm"; constexpr string_view INPUT_FLAC_FILE_PATH = "/data/test/media/flac_2c_44100hz_261k.dat"; constexpr string_view OUTPUT_FLAC_PCM_FILE_PATH = "/data/test/media/flac_2c_44100hz_261k.pcm"; +constexpr string_view INPUT_FLAC_192K_FILE_PATH = "/data/test/media/FLAC_192k_2c_xxkb.dat"; +constexpr string_view OUTPUT_FLAC_192K_PCM_FILE_PATH = "/data/test/media/FLAC_192k_2c_xxkb.pcm"; constexpr string_view INPUT_MP3_FILE_PATH = "/data/test/media/mp3_2c_44100hz_60k.dat"; constexpr string_view OUTPUT_MP3_PCM_FILE_PATH = "/data/test/media/mp3_2c_44100hz_60k.pcm"; constexpr string_view INPUT_VORBIS_FILE_PATH = "/data/test/media/vorbis_2c_44100hz_320k.dat"; @@ -80,6 +82,12 @@ constexpr string_view INPUT_OPUS_FILE_PATH = "/data/test/media/voice_opus.dat"; constexpr string_view OUTPUT_OPUS_PCM_FILE_PATH = "/data/test/media/opus_decode.pcm"; constexpr string_view INPUT_APE_FILE_PATH = "/data/test/media/voice_ape.dat"; constexpr string_view OUTPUT_APE_PCM_FILE_PATH = "/data/test/media/ape_decode.pcm"; +constexpr string_view INPUT_AAC_LC_ADTS_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_lc.dat"; +constexpr string_view OUTPUT_AAC_LC_ADTS_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_lc.pcm"; +constexpr string_view INPUT_AAC_HE_ADTS_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_he.dat"; +constexpr string_view OUTPUT_AAC_HE_ADTS_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_he.pcm"; +constexpr string_view INPUT_AAC_HEV2_ADTS_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_hev2.dat"; +constexpr string_view OUTPUT_AAC_HEV2_ADTS_FILE_PATH = "/data/test/media/aac_2c_44100hz_199k_hev2.pcm"; const string OPUS_SO_FILE_PATH = std::string(AV_CODEC_PATH) + "/libav_codec_ext_base.z.so"; } // namespace @@ -112,6 +120,10 @@ public: std::queue outBufferQueue_; }; +static uint32_t g_outputFormatChangedTimes = 0; +static int32_t g_outputSampleRate = 0; +static int32_t g_outputChannels = 0; + static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) { (void)codec; @@ -123,9 +135,11 @@ static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) { (void)codec; - (void)format; (void)userData; - cout << "OnOutputFormatChanged received" << endl; + g_outputFormatChangedTimes++; + OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, &g_outputChannels); + OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, &g_outputSampleRate); + cout << "OnOutputFormatChanged received, rate:" << g_outputSampleRate << ",channel:" << g_outputChannels << endl; } static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData) @@ -156,12 +170,14 @@ public: void TearDown(); bool ReadBuffer(OH_AVBuffer *buffer, uint32_t index); int32_t InitFile(AudioBufferFormatType audioType); + int32_t InitFile(string_view input, string_view output); void InputFunc(); void OutputFunc(); int32_t CreateCodecFunc(AudioBufferFormatType audioType); int32_t CheckSoFunc(); void HandleInputEOS(const uint32_t index); int32_t Configure(AudioBufferFormatType audioType); + void SetTestingFormat(AudioBufferFormatType audioType); int32_t Start(); int32_t Stop(); void Release(); @@ -174,6 +190,7 @@ protected: AudioCodecBufferSignal *signal_ = nullptr; OH_AVCodec *audioDec_ = nullptr; OH_AVFormat *format_ = nullptr; + bool isTestingFormat_ = false; bool isFirstFrame_ = true; uint32_t frameCount_ = 0; std::ifstream inputFile_; @@ -193,11 +210,19 @@ void AudioDecoderBufferCapiUnitTest::TearDownTestCase(void) void AudioDecoderBufferCapiUnitTest::SetUp(void) { + g_outputFormatChangedTimes = 0; + g_outputSampleRate = 0; + g_outputChannels = 0; cout << "[SetUp]: SetUp!!!" << endl; } void AudioDecoderBufferCapiUnitTest::TearDown(void) { + if (isTestingFormat_) { + EXPECT_EQ(g_outputFormatChangedTimes, 1); + } else { + EXPECT_EQ(g_outputFormatChangedTimes, 0); + } cout << "[TearDown]: over!!!" << endl; if (signal_) { @@ -210,6 +235,11 @@ void AudioDecoderBufferCapiUnitTest::TearDown(void) if (pcmOutputFile_.is_open()) { pcmOutputFile_.close(); } + + if (format_ != nullptr) { + OH_AVFormat_Destroy(format_); + format_ = nullptr; + } } void AudioDecoderBufferCapiUnitTest::Release() @@ -446,6 +476,22 @@ int32_t AudioDecoderBufferCapiUnitTest::InitFile(AudioBufferFormatType audioType return OH_AVErrCode::AV_ERR_OK; } +int32_t AudioDecoderBufferCapiUnitTest::InitFile(string_view inputFilename, string_view outputFilename) +{ + inputFile_.open(inputFilename, std::ios::binary); + if (!inputFile_.is_open()) { + cout << "Fatal: open input file failed:" << inputFilename << endl; + return OH_AVErrCode::AV_ERR_UNKNOWN; + } + pcmOutputFile_.open(outputFilename, std::ios::out | std::ios::binary); + if (!pcmOutputFile_.is_open()) { + cout << "Fatal: open output file failed" << outputFilename << endl; + inputFile_.close(); + return OH_AVErrCode::AV_ERR_UNKNOWN; + } + return OH_AVErrCode::AV_ERR_OK; +} + int32_t AudioDecoderBufferCapiUnitTest::CreateCodecFunc(AudioBufferFormatType audioType) { if (audioType == AudioBufferFormatType::TYPE_MP3) { @@ -491,6 +537,20 @@ int32_t AudioDecoderBufferCapiUnitTest::CreateCodecFunc(AudioBufferFormatType au return OH_AVErrCode::AV_ERR_OK; } +void AudioDecoderBufferCapiUnitTest::SetTestingFormat(AudioBufferFormatType audioType) +{ + if (!isTestingFormat_) { + OH_AVFormat_SetIntValue(format_, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, DEFAULT_SAMPLE_FORMAT); + return; + } + int32_t notMatchRate = 48000; // 48000 is valid for most codec but not match default + if (audioType == AudioBufferFormatType::TYPE_OPUS) { + OH_AVFormat_SetIntValue(format_, OH_MD_KEY_AUD_CHANNEL_COUNT, 1); + } else { + OH_AVFormat_SetIntValue(format_, OH_MD_KEY_AUD_SAMPLE_RATE, notMatchRate); + } +} + int32_t AudioDecoderBufferCapiUnitTest::Configure(AudioBufferFormatType audioType) { format_ = OH_AVFormat_Create(); @@ -501,25 +561,22 @@ int32_t AudioDecoderBufferCapiUnitTest::Configure(AudioBufferFormatType audioTyp int32_t channelCount = DEFAULT_CHANNEL_COUNT; int32_t sampleRate = DEFAULT_SAMPLE_RATE; if (audioType == AudioBufferFormatType::TYPE_AAC) { - 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(), - DEFAULT_SAMPLE_FORMAT); + OH_AVFormat_SetIntValue(format_, OH_MD_KEY_AAC_IS_ADTS, DEFAULT_AAC_TYPE); } else if (audioType == AudioBufferFormatType::TYPE_AMRNB || audioType == AudioBufferFormatType::TYPE_G711MU || - audioType == AudioBufferFormatType::TYPE_OPUS || audioType == AudioBufferFormatType::TYPE_APE) { + audioType == AudioBufferFormatType::TYPE_APE) { channelCount = 1; - sampleRate = AMRNB_SAMPLE_RATE; + sampleRate = SAMPLE_RATE_8K; } else if (audioType == AudioBufferFormatType::TYPE_AMRWB) { channelCount = 1; sampleRate = AMRWB_SAMPLE_RATE; - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), - DEFAULT_SAMPLE_FORMAT); + } else if (audioType == AudioBufferFormatType::TYPE_OPUS) { + channelCount = DEFAULT_CHANNEL_COUNT; + sampleRate = SAMPLE_RATE_8K; } - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), channelCount); - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), sampleRate); - OH_AVFormat_SetLongValue(format_, MediaDescriptionKey::MD_KEY_BITRATE.data(), BITS_RATE[(uint32_t)audioType]); + OH_AVFormat_SetIntValue(format_, OH_MD_KEY_AUD_CHANNEL_COUNT, channelCount); + OH_AVFormat_SetIntValue(format_, OH_MD_KEY_AUD_SAMPLE_RATE, sampleRate); + OH_AVFormat_SetLongValue(format_, OH_MD_KEY_BITRATE, BITS_RATE[(uint32_t)audioType]); if (audioType == AudioBufferFormatType::TYPE_VORBIS) { - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), - DEFAULT_SAMPLE_FORMAT); int64_t extradataSize; if (!inputFile_.is_open()) { cout << "Fatal: file is not open" << endl; @@ -536,9 +593,9 @@ int32_t AudioDecoderBufferCapiUnitTest::Configure(AudioBufferFormatType audioTyp cout << "Fatal: read extradata bytes error" << endl; return OH_AVErrCode::AV_ERR_UNKNOWN; } - OH_AVFormat_SetBuffer(format_, MediaDescriptionKey::MD_KEY_CODEC_CONFIG.data(), (uint8_t *)buffer, - extradataSize); + OH_AVFormat_SetBuffer(format_, OH_MD_KEY_CODEC_CONFIG, (uint8_t *)buffer, extradataSize); } + SetTestingFormat(audioType); return OH_AudioCodec_Configure(audioDec_, format_); } @@ -1152,12 +1209,16 @@ HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_Flac_ReleaseOutputBuffer_0 HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_Flac_192k_01, TestSize.Level1) { - ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(AudioBufferFormatType::TYPE_FLAC)); + inputFile_.open(INPUT_FLAC_192K_FILE_PATH, std::ios::binary); + ASSERT_EQ(true, inputFile_.is_open()); + pcmOutputFile_.open(OUTPUT_FLAC_192K_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary); + ASSERT_EQ(true, pcmOutputFile_.is_open()); ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_FLAC)); format_ = OH_AVFormat_Create(); EXPECT_NE(nullptr, format_); OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), DEFAULT_CHANNEL_COUNT); OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), FLAC_192K_SAMPLE_RATE); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), DEFAULT_SAMPLE_FORMAT); OH_AVFormat_SetLongValue(format_, MediaDescriptionKey::MD_KEY_BITRATE.data(), BITS_RATE[(uint32_t)AudioBufferFormatType::TYPE_FLAC]); EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); @@ -2125,7 +2186,7 @@ HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_Amrnb_Configure_02, TestSi EXPECT_NE(nullptr, format_); OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), DEFAULT_SAMPLE_FORMAT); - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), AMRNB_SAMPLE_RATE); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), SAMPLE_RATE_8K); EXPECT_NE(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); // missing channel count EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); @@ -2154,7 +2215,7 @@ HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_Amrnb_Configure_03, TestSi EXPECT_NE(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); // abnormal sample rate EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), AMRNB_SAMPLE_RATE); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), SAMPLE_RATE_8K); EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); // normal sample rate Release(); @@ -2564,7 +2625,7 @@ HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_g711muCheckChannelCount, T CreateCodecFunc(AudioBufferFormatType::TYPE_G711MU); format_ = OH_AVFormat_Create(); EXPECT_NE(nullptr, format_); - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), AMRNB_SAMPLE_RATE); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), SAMPLE_RATE_8K); EXPECT_NE(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); // missing channel count EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); @@ -2591,7 +2652,7 @@ HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_g711muCheckSampleRate, Tes EXPECT_NE(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); // illegal sample rate EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), AMRNB_SAMPLE_RATE); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), SAMPLE_RATE_8K); EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); // normal sample rate EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Destroy(audioDec_)); @@ -2912,5 +2973,191 @@ HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_Aac_SetDecryptionConfig_01 #endif } +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_AacLcFormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(INPUT_AAC_LC_ADTS_FILE_PATH, OUTPUT_AAC_LC_ADTS_FILE_PATH)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_AAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure(AudioBufferFormatType::TYPE_AAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(g_outputSampleRate, DEFAULT_SAMPLE_RATE); + EXPECT_EQ(g_outputChannels, DEFAULT_CHANNEL_COUNT); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_AacHeFormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(INPUT_AAC_HE_ADTS_FILE_PATH, OUTPUT_AAC_HE_ADTS_FILE_PATH)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_AAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure(AudioBufferFormatType::TYPE_AAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(g_outputSampleRate, DEFAULT_SAMPLE_RATE); + EXPECT_EQ(g_outputChannels, DEFAULT_CHANNEL_COUNT); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_AacHev2FormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(INPUT_AAC_HEV2_ADTS_FILE_PATH, OUTPUT_AAC_HEV2_ADTS_FILE_PATH)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_AAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure(AudioBufferFormatType::TYPE_AAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(g_outputSampleRate, DEFAULT_SAMPLE_RATE); + EXPECT_EQ(g_outputChannels, DEFAULT_CHANNEL_COUNT); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_FlacFormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(INPUT_FLAC_FILE_PATH, OUTPUT_FLAC_PCM_FILE_PATH)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_FLAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure(AudioBufferFormatType::TYPE_FLAC)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(g_outputSampleRate, DEFAULT_SAMPLE_RATE); + EXPECT_EQ(g_outputChannels, DEFAULT_CHANNEL_COUNT); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_FlacSampleFormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + inputFile_.open(INPUT_FLAC_192K_FILE_PATH, std::ios::binary); + ASSERT_EQ(true, inputFile_.is_open()); + pcmOutputFile_.open(OUTPUT_FLAC_192K_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary); + ASSERT_EQ(true, pcmOutputFile_.is_open()); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_FLAC)); + format_ = OH_AVFormat_Create(); + EXPECT_NE(nullptr, format_); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), DEFAULT_CHANNEL_COUNT); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), FLAC_192K_SAMPLE_RATE); + // set abnormal trigger on changed callback + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), ABNORMAL_SAMPLE_FORMAT); + OH_AVFormat_SetLongValue(format_, MediaDescriptionKey::MD_KEY_BITRATE.data(), + BITS_RATE[(uint32_t)AudioBufferFormatType::TYPE_FLAC]); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_FlacSampleFormatChanged_02, TestSize.Level1) +{ + isTestingFormat_ = true; + inputFile_.open(INPUT_FLAC_192K_FILE_PATH, std::ios::binary); + ASSERT_EQ(true, inputFile_.is_open()); + pcmOutputFile_.open(OUTPUT_FLAC_192K_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary); + ASSERT_EQ(true, pcmOutputFile_.is_open()); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_FLAC)); + format_ = OH_AVFormat_Create(); + EXPECT_NE(nullptr, format_); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), DEFAULT_CHANNEL_COUNT); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), FLAC_192K_SAMPLE_RATE); + // set invalid sample format trigger on changed callback + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), + AudioSampleFormat::SAMPLE_S16P); + OH_AVFormat_SetLongValue(format_, MediaDescriptionKey::MD_KEY_BITRATE.data(), + BITS_RATE[(uint32_t)AudioBufferFormatType::TYPE_FLAC]); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_FlacSampleFormatChanged_03, TestSize.Level1) +{ + isTestingFormat_ = true; + inputFile_.open(INPUT_FLAC_192K_FILE_PATH, std::ios::binary); + ASSERT_EQ(true, inputFile_.is_open()); + pcmOutputFile_.open(OUTPUT_FLAC_192K_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary); + ASSERT_EQ(true, pcmOutputFile_.is_open()); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_FLAC)); + format_ = OH_AVFormat_Create(); + EXPECT_NE(nullptr, format_); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), DEFAULT_CHANNEL_COUNT); + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), FLAC_192K_SAMPLE_RATE); + // not set sample format trigger on changed callback + OH_AVFormat_SetLongValue(format_, MediaDescriptionKey::MD_KEY_BITRATE.data(), + BITS_RATE[(uint32_t)AudioBufferFormatType::TYPE_FLAC]); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_Mp3FormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(INPUT_MP3_FILE_PATH, OUTPUT_MP3_PCM_FILE_PATH)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_MP3)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure(AudioBufferFormatType::TYPE_MP3)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(g_outputSampleRate, DEFAULT_SAMPLE_RATE); + EXPECT_EQ(g_outputChannels, DEFAULT_CHANNEL_COUNT); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); + Release(); +} + +HWTEST_F(AudioDecoderBufferCapiUnitTest, audioDecoder_VorbisFormatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(INPUT_VORBIS_FILE_PATH, OUTPUT_VORBIS_PCM_FILE_PATH)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(AudioBufferFormatType::TYPE_VORBIS)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure(AudioBufferFormatType::TYPE_VORBIS)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(g_outputSampleRate, DEFAULT_SAMPLE_RATE); + EXPECT_EQ(g_outputChannels, DEFAULT_CHANNEL_COUNT); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Reset(audioDec_)); + Release(); +} + } } \ No newline at end of file diff --git a/test/unittest/audio_test/audio_media_codec_unit_test.cpp b/test/unittest/audio_test/audio_media_codec_unit_test.cpp index 7373137d5d4b4ab5eb4c0fde549abb55ec2e10b2..7d1250a0b671794a4e0a3ca95c62ad58a5dbb62e 100644 --- a/test/unittest/audio_test/audio_media_codec_unit_test.cpp +++ b/test/unittest/audio_test/audio_media_codec_unit_test.cpp @@ -54,6 +54,8 @@ public: void OnError(Media::CodecErrorType errorType, int32_t errorCode) override; void OnOutputBufferDone(const std::shared_ptr &outputBuffer) override; + + void OnOutputFormatChanged(const std::shared_ptr &format) override; }; void AudioCodecCallback::OnError(Media::CodecErrorType errorType, int32_t errorCode) @@ -67,6 +69,11 @@ void AudioCodecCallback::OnOutputBufferDone(const std::shared_ptr &out (void)outputBuffer; } +void AudioCodecCallback::OnOutputFormatChanged(const std::shared_ptr &format) +{ + (void)format; +} + class TestCodecCallback : public Media::CodecCallback { public: TestCodecCallback() diff --git a/test/unittest/audio_vivid_test/audio_decoder_capi_avbuffer_vivid_unit_test.cpp b/test/unittest/audio_vivid_test/audio_decoder_capi_avbuffer_vivid_unit_test.cpp index 2325a1c48407d68d06c8868e6fc3671df77a0b23..1cce67b99d4435b57c45873653b6031f75bd5cbd 100644 --- a/test/unittest/audio_vivid_test/audio_decoder_capi_avbuffer_vivid_unit_test.cpp +++ b/test/unittest/audio_vivid_test/audio_decoder_capi_avbuffer_vivid_unit_test.cpp @@ -38,6 +38,7 @@ constexpr uint32_t VIVID_MIN_CHANNEL_COUNT = 0; constexpr uint32_t VIVID_MAX_CHANNEL_COUNT = 17; constexpr uint32_t MAX_CHANNEL_COUNT = 2; constexpr uint32_t DEFAULT_SAMPLE_RATE = 48000; +constexpr uint32_t TEST_SAMPLE_RATE = 32000; constexpr uint32_t VIVID_MAX_INPUT_SIZE = 99999999; constexpr string_view INPUT_VIVID_FILE_PATH = "/data/test/media/vivid_2c_44100hz_320k.dat"; constexpr string_view OUTPUT_VIVID_PCM_FILE_PATH = "/data/test/media/vivid_2c_44100hz_320k.pcm"; @@ -45,6 +46,11 @@ constexpr string_view OUTPUT_VIVID_PCM_FILE_PATH = "/data/test/media/vivid_2c_44 namespace OHOS { namespace MediaAVCodec { + +static uint32_t g_outputFormatChangedTimes = 0; +static int32_t g_outputSampleRate = 0; +static int32_t g_outputChannels = 0; + class ADecBufferSignal { public: std::mutex inMutex_; @@ -70,9 +76,11 @@ static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) { (void)codec; - (void)format; (void)userData; - cout << "OnOutputFormatChanged received" << endl; + g_outputFormatChangedTimes++; + OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, &g_outputChannels); + OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, &g_outputSampleRate); + cout << "OnOutputFormatChanged received, rate:" << g_outputSampleRate << ", channel:" << g_outputChannels << endl; } static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData) @@ -121,6 +129,7 @@ protected: OH_AVCodec *audioDec_ = nullptr; OH_AVFormat *format_ = nullptr; bool isFirstFrame_ = true; + bool isTestingFormat_ = false; std::ifstream inputFile_; std::ofstream pcmOutputFile_; }; @@ -137,11 +146,19 @@ void AudioVividCodeCapiDecoderUnitTest::TearDownTestCase(void) void AudioVividCodeCapiDecoderUnitTest::SetUp(void) { + g_outputFormatChangedTimes = 0; + g_outputSampleRate = 0; + g_outputChannels = 0; cout << "[SetUp]: SetUp!!!" << endl; } void AudioVividCodeCapiDecoderUnitTest::TearDown(void) { + if (isTestingFormat_) { + EXPECT_EQ(g_outputFormatChangedTimes, 1); + } else { + EXPECT_EQ(g_outputFormatChangedTimes, 0); + } cout << "[TearDown]: over!!!" << endl; if (signal_) { @@ -357,8 +374,12 @@ int32_t AudioVividCodeCapiDecoderUnitTest::Configure() return OH_AVErrCode::AV_ERR_UNKNOWN; } - OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(), MAX_CHANNEL_COUNT); OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), DEFAULT_SAMPLE_RATE); + if (isTestingFormat_) { + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), TEST_SAMPLE_RATE); + } else { + OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(), DEFAULT_SAMPLE_RATE); + } OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), OH_BitsPerSample::SAMPLE_S16LE); @@ -822,5 +843,21 @@ HWTEST_F(AudioVividCodeCapiDecoderUnitTest, audioDecoder_Vivid_ReleaseOutputBuff EXPECT_NE(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_FreeOutputBuffer(audioDec_, index)); Release(); } + +HWTEST_F(AudioVividCodeCapiDecoderUnitTest, audioDecoder_Vivid_formatChanged, TestSize.Level1) +{ + isTestingFormat_ = true; + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, InitFile(CODEC_VIVID_NAME)); + ASSERT_EQ(OH_AVErrCode::AV_ERR_OK, CreateCodecFunc(CODEC_VIVID_NAME)); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Configure()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Start()); + { + unique_lock lock(signal_->startMutex_); + signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); }); + } + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop()); + EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Destroy(audioDec_)); +} + } // namespace MediaAVCodec } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/resources/audio_res/FLAC_192k_2c_xxkb.dat b/test/unittest/resources/audio_res/FLAC_192k_2c_xxkb.dat new file mode 100644 index 0000000000000000000000000000000000000000..ee84c6081f0f3d6cab0af2672067758e44e3b8b5 Binary files /dev/null and b/test/unittest/resources/audio_res/FLAC_192k_2c_xxkb.dat differ diff --git a/test/unittest/resources/audio_res/aac_2c_44100hz_199k_he.dat b/test/unittest/resources/audio_res/aac_2c_44100hz_199k_he.dat new file mode 100644 index 0000000000000000000000000000000000000000..360b840d005be1914e92603850c201660afd1fee Binary files /dev/null and b/test/unittest/resources/audio_res/aac_2c_44100hz_199k_he.dat differ diff --git a/test/unittest/resources/audio_res/aac_2c_44100hz_199k_hev2.dat b/test/unittest/resources/audio_res/aac_2c_44100hz_199k_hev2.dat new file mode 100644 index 0000000000000000000000000000000000000000..375313de2095cbe3c0afdf6b657ca25d2807332a Binary files /dev/null and b/test/unittest/resources/audio_res/aac_2c_44100hz_199k_hev2.dat differ diff --git a/test/unittest/resources/audio_res/aac_2c_44100hz_199k_lc.dat b/test/unittest/resources/audio_res/aac_2c_44100hz_199k_lc.dat new file mode 100644 index 0000000000000000000000000000000000000000..862c7ec4225cdbda13e56847652adc91003c0259 Binary files /dev/null and b/test/unittest/resources/audio_res/aac_2c_44100hz_199k_lc.dat differ diff --git a/test/unittest/resources/ohos_test.xml b/test/unittest/resources/ohos_test.xml index f83f02188f495925d6c5ab3837c893583ee09a3b..8b681c153246d4d1e28b5499390ae1cf77ea3e93 100644 --- a/test/unittest/resources/ohos_test.xml +++ b/test/unittest/resources/ohos_test.xml @@ -179,6 +179,10 @@