diff --git a/frameworks/native/soundpool/BUILD.gn b/frameworks/native/soundpool/BUILD.gn index 0ce200e1c5b745d7a83e5f554cbf7ef365bb4bbf..b6a22a4460b3df615d76d6cd0632bc459672a3db 100644 --- a/frameworks/native/soundpool/BUILD.gn +++ b/frameworks/native/soundpool/BUILD.gn @@ -61,7 +61,7 @@ ohos_shared_library("soundpool_client") { defines = [] #Soundpool low latency playback switch - #defines += [ "SOUNDPOOL_SUPPORT_LOW_LATENCY" ] + defines += [ "SOUNDPOOL_SUPPORT_LOW_LATENCY" ] defines += player_framework_defines subsystem_name = "multimedia" diff --git a/frameworks/native/soundpool/cache_buffer.cpp b/frameworks/native/soundpool/cache_buffer.cpp index 24e6cafe4054416d0da8d224e82846da68834d48..01db8d5db9a81a7b216f4c05f6f6c63799a74ab6 100644 --- a/frameworks/native/soundpool/cache_buffer.cpp +++ b/frameworks/native/soundpool/cache_buffer.cpp @@ -22,8 +22,8 @@ namespace OHOS { namespace Media { CacheBuffer::CacheBuffer(const MediaAVCodec::Format trackFormat, const std::deque> cacheData, - const int32_t soundID, const int32_t streamID) : trackFormat_(trackFormat), - cacheData_(cacheData), soundID_(soundID), streamID_(streamID) + const size_t cacheDataTotalSize, const int32_t soundID, const int32_t streamID) : trackFormat_(trackFormat), + cacheData_(cacheData), cacheDataTotalSize_(cacheDataTotalSize), soundID_(soundID), streamID_(streamID) { MEDIA_INFO_LOG("Construction CacheBuffer"); } @@ -37,7 +37,6 @@ CacheBuffer::~CacheBuffer() std::unique_ptr CacheBuffer::CreateAudioRenderer(const int32_t streamID, const AudioStandard::AudioRendererInfo audioRendererInfo, const PlayParams playParams) { - MEDIA_INFO_LOG("CacheBuffer"); CHECK_AND_RETURN_RET_LOG(streamID == streamID_, nullptr, "Invalid streamID, failed to create normal audioRenderer."); int32_t sampleRate; @@ -66,20 +65,35 @@ std::unique_ptr CacheBuffer::CreateAudioRenderer(c } // low-latency:1, non low-latency:0 - rendererOptions.rendererInfo.rendererFlags = audioRendererInfo.rendererFlags; + if ((rendererOptions.streamInfo.samplingRate == AudioStandard::AudioSamplingRate::SAMPLE_RATE_48000) && + (rendererOptions.streamInfo.channels == AudioStandard::AudioChannel::MONO || + rendererOptions.streamInfo.channels == AudioStandard::AudioChannel::STEREO)) { + // samplingRate 48KHz, channelCount 1/2 + MEDIA_INFO_LOG("low latency support this rendererOptions."); + rendererFlags_ = audioRendererInfo.rendererFlags; + } else { + MEDIA_INFO_LOG("low latency didn't support this rendererOptions, force normal play."); + rendererFlags_ = NORMAL_PLAY_RENDERER_FLAGS; + } + rendererOptions.rendererInfo.rendererFlags = rendererFlags_; std::unique_ptr audioRenderer = AudioStandard::AudioRenderer::Create(cacheDir, rendererOptions); - MEDIA_INFO_LOG("CacheBuffer rendererFlags:%{public}d", audioRendererInfo.rendererFlags); + CHECK_AND_RETURN_RET_LOG(audioRenderer != nullptr, nullptr, "Invalid audioRenderer."); + audioRenderer->SetRenderMode(AudioStandard::AudioRenderMode::RENDER_MODE_CALLBACK); + int32_t ret = audioRenderer->SetRendererWriteCallback(shared_from_this()); + if (ret != MSERR_OK) { + MEDIA_ERR_LOG("audio renderer write callback fail, ret %{public}d.", ret); + } return audioRenderer; } int32_t CacheBuffer::PreparePlay(const int32_t streamID, const AudioStandard::AudioRendererInfo audioRendererInfo, const PlayParams playParams) { - MEDIA_INFO_LOG("CacheBuffer should prepare before play"); // create audioRenderer if (audioRenderer_ == nullptr) { audioRenderer_ = CreateAudioRenderer(streamID, audioRendererInfo, playParams); + ReCombineCacheData(); } else { MEDIA_INFO_LOG("audio render inited."); } @@ -91,34 +105,70 @@ int32_t CacheBuffer::PreparePlay(const int32_t streamID, const AudioStandard::Au int32_t CacheBuffer::DoPlay(const int32_t streamID) { CHECK_AND_RETURN_RET_LOG(streamID == streamID_, MSERR_INVALID_VAL, "Invalid streamID, failed to DoPlay."); - if (isRunning_.load()) { - Stop(streamID); - } - std::unique_lock lock(cacheBufferLock_); + std::lock_guard lock(cacheBufferLock_); if (audioRenderer_ != nullptr) { + isRunning_.store(true); + cacheDataFrameNum_ = 0; + havePlayedCount_ = 0; if (!audioRenderer_->Start()) { MEDIA_ERR_LOG("audioRenderer Start failed"); if (callback_ != nullptr) callback_->OnError(MSERR_INVALID_VAL); if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnError(MSERR_INVALID_VAL); return MSERR_INVALID_VAL; } - audioRendererRunningThread_ = std::make_unique(&CacheBuffer::AudioRendererRunning, this); - isRunning_.store(true); - runningValid_.notify_all(); return MSERR_OK; } MEDIA_ERR_LOG("Invalid audioRenderer."); return MSERR_INVALID_VAL; } +int32_t CacheBuffer::ReCombineCacheData() +{ + std::lock_guard lock(cacheBufferLock_); + CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer."); + CHECK_AND_RETURN_RET_LOG(!cacheData_.empty(), MSERR_INVALID_VAL, "empty cache data."); + size_t bufferSize; + audioRenderer_->GetBufferSize(bufferSize); + // Prevent data from crossing boundaries, ensure recombine data largest. + size_t reCombineCacheDataSize = (cacheDataTotalSize_ + bufferSize - 1) / bufferSize; + std::shared_ptr preAudioBuffer = cacheData_.front(); + size_t preAudioBufferIndex = 0; + for (size_t reCombineCacheDataNum = 0; reCombineCacheDataNum < reCombineCacheDataSize; reCombineCacheDataNum++) { + uint8_t *reCombineBuf = new(std::nothrow) uint8_t[bufferSize]; + for (size_t bufferNum = 0; bufferNum < bufferSize; bufferNum++) { + if (cacheData_.size() > 1 && (preAudioBufferIndex == static_cast(preAudioBuffer->size))) { + cacheData_.pop_front(); + preAudioBuffer = cacheData_.front(); + preAudioBufferIndex = 0; + } + if (cacheData_.size() == 1 && (preAudioBufferIndex == static_cast(preAudioBuffer->size))) { + preAudioBuffer = cacheData_.front(); + cacheData_.pop_front(); + preAudioBufferIndex = 0; + } + if (cacheData_.empty()) { + reCombineBuf[bufferNum] = 0; + } else { + reCombineBuf[bufferNum] = preAudioBuffer->buffer[preAudioBufferIndex]; + } + preAudioBufferIndex++; + } + reCombineCacheData_.push_back(std::make_shared(reCombineBuf, bufferSize)); + } + if (!cacheData_.empty()) { + cacheData_.clear(); + } + return MSERR_OK; +} + int32_t CacheBuffer::DealPlayParamsBeforePlay(const int32_t streamID, const PlayParams playParams) { + std::lock_guard lock(cacheBufferLock_); CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer."); loop_ = playParams.loop; audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(playParams.rate)); audioRenderer_->SetVolume(playParams.leftVolume); priority_ = playParams.priority; - MEDIA_INFO_LOG("CacheBuffer parallelPlayFlag:%{public}d.", playParams.parallelPlayFlag); audioRenderer_->SetParallelPlayFlag(playParams.parallelPlayFlag); return MSERR_OK; } @@ -143,69 +193,56 @@ AudioStandard::AudioRendererRate CacheBuffer::CheckAndAlignRendererRate(const in return renderRate; } -void CacheBuffer::AudioRendererRunning() +void CacheBuffer::OnWriteData(size_t length) { - MEDIA_INFO_LOG("CacheBuffer audion render running."); - int ret = MSERR_OK; - int32_t runningCount = 0; - do { - for (auto data : cacheData_) { - if (audioRenderer_ == nullptr) { - MEDIA_ERR_LOG("audioRenderer_ is nullptr, failed to write audiobuffer"); - ret = MSERR_INVALID_VAL; - break; - } - if (!(isRunning_.load())) { - MEDIA_ERR_LOG("stop by user."); - break; - } - if (data == nullptr) { - continue; - } - std::unique_lock lock(amutex_); - int32_t bytesWritten = audioRenderer_->Write(data->buffer, data->size); - if (bytesWritten <= 0) { - MEDIA_ERR_LOG("write audiobuffer failed"); - } - } - if (loop_ == runningCount) { - MEDIA_ERR_LOG("CacheBuffer loop done, loop_:%{public}d, runningCount:%{public}d", loop_, runningCount); - break; - } - if (!(isRunning_.load())) { - MEDIA_ERR_LOG("stop by user."); - break; - } - if (loop_ >= 0) { - runningCount++; + AudioStandard::BufferDesc bufDesc; + if (audioRenderer_ == nullptr) { + MEDIA_ERR_LOG("audioRenderer is nullptr."); + return; + } + if (!isRunning_.load()) { + MEDIA_ERR_LOG("audioRenderer is stop."); + return; + } + if (cacheDataFrameNum_ == reCombineCacheData_.size()) { + if (havePlayedCount_ == loop_) { + MEDIA_INFO_LOG("CacheBuffer stream write finish, cacheDataFrameNum_:%{public}zu," + " havePlayedCount_:%{public}d, loop:%{public}d, try to stop.", cacheDataFrameNum_, + havePlayedCount_, loop_); + Stop(streamID_); + return; } - } while (true); - - if (ret == MSERR_OK) { - if (callback_ != nullptr) callback_->OnPlayFinished(); - if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnPlayFinished(); - } else { - if (callback_ != nullptr) callback_->OnError(MSERR_INVALID_VAL); + cacheDataFrameNum_ = 0; + havePlayedCount_++; } + audioRenderer_->GetBufferDesc(bufDesc); + std::shared_ptr audioBuffer = reCombineCacheData_[cacheDataFrameNum_]; + + bufDesc.buffer = audioBuffer->buffer; + bufDesc.bufLength = static_cast(audioBuffer->size); + bufDesc.dataLength = static_cast(audioBuffer->size); + + audioRenderer_->Enqueue(bufDesc); + cacheDataFrameNum_++; } int32_t CacheBuffer::Stop(const int32_t streamID) { + std::lock_guard lock(cacheBufferLock_); if (streamID == streamID_) { - std::unique_lock lock(cacheBufferLock_); - if (!isRunning_.load()) { - MEDIA_INFO_LOG("CacheBuffer streamID:%{public}d the stream has not been played, wait it.", streamID); - runningValid_.wait_for(lock, std::chrono::duration(WAIT_TIME_BEFORE_RUNNING_CONFIG)); - } - if (audioRenderer_ != nullptr) { + if (audioRenderer_ != nullptr && isRunning_.load()) { isRunning_.store(false); - audioRenderer_->Stop(); - } - if (audioRendererRunningThread_ != nullptr && audioRendererRunningThread_->joinable()) { - audioRendererRunningThread_ ->join(); - audioRendererRunningThread_.reset(); + if (rendererFlags_ == LOW_LATENCY_PLAY_RENDERER_FLAGS) { + audioRenderer_->Pause(); + audioRenderer_->Flush(); + } else { + audioRenderer_->Stop(); + } + cacheDataFrameNum_ = 0; + havePlayedCount_ = 0; + if (callback_ != nullptr) callback_->OnPlayFinished(); + if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnPlayFinished(); } - runningValid_.notify_all(); return MSERR_OK; } return MSERR_INVALID_VAL; @@ -213,18 +250,13 @@ int32_t CacheBuffer::Stop(const int32_t streamID) int32_t CacheBuffer::SetVolume(const int32_t streamID, const float leftVolume, const float rightVolume) { + std::lock_guard lock(cacheBufferLock_); int32_t ret = MSERR_OK; if (streamID == streamID_) { - std::unique_lock lock(cacheBufferLock_); - if (!isRunning_.load()) { - MEDIA_INFO_LOG("CacheBuffer streamID:%{public}d the stream has not been played, wait it.", streamID); - runningValid_.wait_for(lock, std::chrono::duration(WAIT_TIME_BEFORE_RUNNING_CONFIG)); - } if (audioRenderer_ != nullptr) { // audio cannot support left & right volume, all use left volume. (void) rightVolume; ret = audioRenderer_->SetVolume(leftVolume); - runningValid_.notify_all(); } } return ret; @@ -232,16 +264,11 @@ int32_t CacheBuffer::SetVolume(const int32_t streamID, const float leftVolume, c int32_t CacheBuffer::SetRate(const int32_t streamID, const AudioStandard::AudioRendererRate renderRate) { + std::lock_guard lock(cacheBufferLock_); int32_t ret = MSERR_INVALID_VAL; if (streamID == streamID_) { - std::unique_lock lock(cacheBufferLock_); - if (!isRunning_.load()) { - MEDIA_INFO_LOG("CacheBuffer streamID:%{public}d the stream has not been played, wait it.", streamID); - runningValid_.wait_for(lock, std::chrono::duration(WAIT_TIME_BEFORE_RUNNING_CONFIG)); - } if (audioRenderer_ != nullptr) { ret = audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(renderRate)); - runningValid_.notify_all(); } } return ret; @@ -249,52 +276,37 @@ int32_t CacheBuffer::SetRate(const int32_t streamID, const AudioStandard::AudioR int32_t CacheBuffer::SetPriority(const int32_t streamID, const int32_t priority) { + std::lock_guard lock(cacheBufferLock_); if (streamID == streamID_) { - std::unique_lock lock(cacheBufferLock_); - if (!isRunning_.load()) { - MEDIA_INFO_LOG("CacheBuffer streamID:%{public}d the stream has not been played, wait it.", streamID); - runningValid_.wait_for(lock, std::chrono::duration(WAIT_TIME_BEFORE_RUNNING_CONFIG)); - } priority_ = priority; - runningValid_.notify_all(); } return MSERR_OK; } int32_t CacheBuffer::SetLoop(const int32_t streamID, const int32_t loop) { + std::lock_guard lock(cacheBufferLock_); if (streamID == streamID_) { - std::unique_lock lock(cacheBufferLock_); - if (!isRunning_.load()) { - MEDIA_INFO_LOG("CacheBuffer streamID:%{public}d the stream has not been played, wait it.", streamID); - runningValid_.wait_for(lock, std::chrono::duration(WAIT_TIME_BEFORE_RUNNING_CONFIG)); - } loop_ = loop; - runningValid_.notify_all(); } return MSERR_OK; } int32_t CacheBuffer::SetParallelPlayFlag(const int32_t streamID, const bool parallelPlayFlag) { + std::lock_guard lock(cacheBufferLock_); if (streamID == streamID_) { - std::unique_lock lock(cacheBufferLock_); - if (!isRunning_.load()) { - MEDIA_INFO_LOG("CacheBuffer streamID:%{public}d the stream has not been played, wait it.", streamID); - runningValid_.wait_for(lock, std::chrono::duration(WAIT_TIME_BEFORE_RUNNING_CONFIG)); - } - MEDIA_INFO_LOG("CacheBuffer parallelPlayFlag:%{public}d.", parallelPlayFlag); if (audioRenderer_ != nullptr) { audioRenderer_->SetParallelPlayFlag(parallelPlayFlag); } - runningValid_.notify_all(); } return MSERR_OK; } int32_t CacheBuffer::Release() { + std::lock_guard lock(cacheBufferLock_); MEDIA_INFO_LOG("CacheBuffer release, streamID:%{public}d", streamID_); isRunning_.store(false); if (audioRenderer_ != nullptr) { @@ -302,11 +314,10 @@ int32_t CacheBuffer::Release() audioRenderer_->Release(); audioRenderer_ = nullptr; } - if (audioRendererRunningThread_ != nullptr && audioRendererRunningThread_->joinable()) { - audioRendererRunningThread_ ->join(); - audioRendererRunningThread_.reset(); - } - runningValid_.notify_all(); + if (!cacheData_.empty()) cacheData_.clear(); + if (!reCombineCacheData_.empty()) reCombineCacheData_.clear(); + if (callback_ != nullptr) callback_.reset(); + if (cacheBufferCallback_ != nullptr) cacheBufferCallback_.reset(); return MSERR_OK; } diff --git a/frameworks/native/soundpool/cache_buffer.h b/frameworks/native/soundpool/cache_buffer.h index 1bec668568bf6b0c916b8f228d060a17c5458a33..936c8ab1c7e2bb040411661709308716806cd18c 100644 --- a/frameworks/native/soundpool/cache_buffer.h +++ b/frameworks/native/soundpool/cache_buffer.h @@ -16,11 +16,10 @@ #ifndef CACHE_BUFFER_H #define CACHE_BUFFER_H -#include #include -#include #include "audio_renderer.h" #include "audio_info.h" +#include "audio_stream_info.h" #include "isoundpool.h" #include "media_description.h" @@ -41,12 +40,16 @@ struct AudioBufferEntry { int32_t size; }; -class CacheBuffer { +class CacheBuffer : + public AudioStandard::AudioRendererWriteCallback, + public std::enable_shared_from_this { public: CacheBuffer(const MediaAVCodec::Format trackFormat, - const std::deque> cacheData, - const int32_t soundID, const int32_t streamID); + const std::deque> cacheData, + const size_t cacheDataTotalSize, + const int32_t soundID, const int32_t streamID); ~CacheBuffer(); + void OnWriteData(size_t length) override; int32_t PreparePlay(const int32_t streamID, const AudioStandard::AudioRendererInfo audioRendererInfo, const PlayParams playParams); int32_t DoPlay(const int32_t streamID); @@ -78,32 +81,35 @@ public: } private: + static constexpr int32_t NORMAL_PLAY_RENDERER_FLAGS = 0; + static constexpr int32_t LOW_LATENCY_PLAY_RENDERER_FLAGS = 1; + std::unique_ptr CreateAudioRenderer(const int32_t streamID, const AudioStandard::AudioRendererInfo audioRendererInfo, const PlayParams playParams); - void AudioRendererRunning(); + int32_t ReCombineCacheData(); int32_t DealPlayParamsBeforePlay(const int32_t streamID, const PlayParams playParams); AudioStandard::AudioRendererRate CheckAndAlignRendererRate(const int32_t renderRate) const; MediaAVCodec::Format trackFormat_; std::deque> cacheData_; + std::deque> reCombineCacheData_; + size_t cacheDataTotalSize_; int32_t soundID_; int32_t streamID_; - std::mutex cacheBufferLock_; // use for save audiobuffer std::unique_ptr audioRenderer_; - std::condition_variable bufferCond_; - std::mutex amutex_; - std::unique_ptr audioRendererRunningThread_; std::atomic isRunning_ = false; std::shared_ptr callback_ = nullptr; std::shared_ptr cacheBufferCallback_ = nullptr; - std::condition_variable runningValid_; - - static constexpr int32_t WAIT_TIME_BEFORE_RUNNING_CONFIG = 400; + std::mutex cacheBufferLock_; int32_t loop_ = 0; int32_t priority_ = 0; + int32_t rendererFlags_ = NORMAL_PLAY_RENDERER_FLAGS; + + size_t cacheDataFrameNum_; + int32_t havePlayedCount_; }; } // namespace Media } // namespace OHOS diff --git a/frameworks/native/soundpool/sound_parser.cpp b/frameworks/native/soundpool/sound_parser.cpp index 1a5be7af196e2cfe9f926070565a54af5950dece..3d0960c2e40fee76e17ec357366c5dfaf498a10d 100644 --- a/frameworks/native/soundpool/sound_parser.cpp +++ b/frameworks/native/soundpool/sound_parser.cpp @@ -20,6 +20,7 @@ namespace { static constexpr int32_t MAX_SOUND_BUFFER_SIZE = 1 * 1024 * 1024; + static const std::string AUDIO_RAW_MIMETYPE_INFO = "audio/raw"; } namespace OHOS { @@ -103,11 +104,17 @@ int32_t SoundParser::DoDecode(MediaAVCodec::Format trackFormat) std::string trackMimeTypeInfo; trackFormat.GetStringValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_MIME, trackMimeTypeInfo); MEDIA_INFO_LOG("SoundParser mime type:%{public}s", trackMimeTypeInfo.c_str()); - audioDec_ = MediaAVCodec::AudioDecoderFactory::CreateByMime(trackMimeTypeInfo); + if (AUDIO_RAW_MIMETYPE_INFO.compare(trackMimeTypeInfo) == 0) { + MEDIA_INFO_LOG("SoundParser pcm file, read it directly."); + audioDec_ = + MediaAVCodec::AudioDecoderFactory::CreateByName((AVCodecCodecName::AUDIO_DECODER_AAC_NAME).data()); + } else { + audioDec_ = MediaAVCodec::AudioDecoderFactory::CreateByMime(trackMimeTypeInfo); + } CHECK_AND_RETURN_RET_LOG(audioDec_ != nullptr, MSERR_INVALID_VAL, "Failed to obtain audioDecorder."); int32_t ret = audioDec_->Configure(trackFormat); CHECK_AND_RETURN_RET_LOG(ret == 0, MSERR_INVALID_VAL, "Failed to configure audioDecorder."); - audioDecCb_ = std::make_shared(soundID_, audioDec_, demuxer_); + audioDecCb_ = std::make_shared(soundID_, audioDec_, demuxer_, trackMimeTypeInfo); CHECK_AND_RETURN_RET_LOG(audioDecCb_ != nullptr, MSERR_INVALID_VAL, "Failed to obtain decode callback."); ret = audioDec_->SetCallback(audioDecCb_); CHECK_AND_RETURN_RET_LOG(ret == 0, MSERR_INVALID_VAL, "Failed to setCallback audioDecorder"); @@ -127,6 +134,12 @@ int32_t SoundParser::GetSoundData(std::deque> return soundParserListener_->GetSoundData(soundData); } +size_t SoundParser::GetSoundDataTotalSize() const +{ + CHECK_AND_RETURN_RET_LOG(soundParserListener_ != nullptr, MSERR_INVALID_VAL, "Invalid sound parser listener"); + return soundParserListener_->GetSoundDataTotalSize(); +} + bool SoundParser::IsSoundParserCompleted() const { CHECK_AND_RETURN_RET_LOG(soundParserListener_ != nullptr, MSERR_INVALID_VAL, "Invalid sound parser listener"); @@ -160,8 +173,9 @@ int32_t SoundParser::Release() SoundDecoderCallback::SoundDecoderCallback(const int32_t soundID, const std::shared_ptr &audioDec, - const std::shared_ptr &demuxer) : soundID_(soundID), - audioDec_(audioDec), demuxer_(demuxer), eosFlag_(false), + const std::shared_ptr &demuxer, + const std::string trackMimeTypeInfo) : soundID_(soundID), audioDec_(audioDec), + demuxer_(demuxer), trackMimeTypeInfo_(trackMimeTypeInfo), eosFlag_(false), decodeShouldCompleted_(false), currentSoundBufferSize_(0) { MEDIA_INFO_LOG("Construction SoundDecoderCallback"); @@ -174,7 +188,9 @@ SoundDecoderCallback::~SoundDecoderCallback() } void SoundDecoderCallback::OnError(AVCodecErrorType errorType, int32_t errorCode) { - MEDIA_INFO_LOG("Recive error, errorType:%{public}d,errorCode:%{public}d", errorType, errorCode); + if (AUDIO_RAW_MIMETYPE_INFO.compare(trackMimeTypeInfo_) != 0) { + MEDIA_INFO_LOG("Recive error, errorType:%{public}d,errorCode:%{public}d", errorType, errorCode); + } } void SoundDecoderCallback::OnOutputFormatChanged(const Format &format) @@ -189,16 +205,45 @@ void SoundDecoderCallback::OnInputBufferAvailable(uint32_t index, std::shared_pt MediaAVCodec::AVCodecBufferInfo sampleInfo; CHECK_AND_RETURN_LOG(demuxer_ != nullptr, "Failed to obtain demuxer"); CHECK_AND_RETURN_LOG(audioDec_ != nullptr, "Failed to obtain audio decode."); - if (!eosFlag_ && !decodeShouldCompleted_) { - int ret = demuxer_->ReadSample(0, buffer, sampleInfo, bufferFlag); - if (ret == 0) { - if (bufferFlag == AVCODEC_BUFFER_FLAG_EOS) { - eosFlag_ = true; + + if (AUDIO_RAW_MIMETYPE_INFO.compare(trackMimeTypeInfo_) == 0) { + if (demuxer_->ReadSample(0, buffer, sampleInfo, bufferFlag) != AVCS_ERR_OK) { + MEDIA_ERR_LOG("SoundDecoderCallback demuxer error."); + return; + } + int32_t size = sampleInfo.size; + uint8_t *buf = new(std::nothrow) uint8_t[size]; + if (currentSoundBufferSize_ > MAX_SOUND_BUFFER_SIZE || bufferFlag == AVCODEC_BUFFER_FLAG_EOS) { + decodeShouldCompleted_ = true; + CHECK_AND_RETURN_LOG(listener_ != nullptr, "sound decode listener invalid."); + listener_->OnSoundDecodeCompleted(availableAudioBuffers_); + listener_->SetSoundBufferTotalSize(static_cast(currentSoundBufferSize_)); + CHECK_AND_RETURN_LOG(callback_ != nullptr, "sound decode:soundpool callback invalid."); + callback_->OnLoadCompleted(soundID_); + return; + } + if (buf != nullptr) { + if (memcpy_s(buf, size, buffer->GetBase(), size) != EOK) { + MEDIA_INFO_LOG("audio buffer copy failed:%{public}s", strerror(errno)); + } else { + availableAudioBuffers_.push_back(std::make_shared(buf, size)); + bufferCond_.notify_all(); } - audioDec_->QueueInputBuffer(index, sampleInfo, bufferFlag); - } else if (ret != 0) { - MEDIA_ERR_LOG("error parser:%{public}d", ret); } + currentSoundBufferSize_ += size; + audioDec_->QueueInputBuffer(index, sampleInfo, bufferFlag); + return; + } + + if (!eosFlag_ && !decodeShouldCompleted_) { + if (demuxer_->ReadSample(0, buffer, sampleInfo, bufferFlag) != AVCS_ERR_OK) { + MEDIA_ERR_LOG("SoundDecoderCallback demuxer error."); + return; + } + if (bufferFlag == AVCODEC_BUFFER_FLAG_EOS) { + eosFlag_ = true; + } + audioDec_->QueueInputBuffer(index, sampleInfo, bufferFlag); } } @@ -206,11 +251,18 @@ void SoundDecoderCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBuffer std::shared_ptr buffer) { std::unique_lock lock(amutex_); + if (AUDIO_RAW_MIMETYPE_INFO.compare(trackMimeTypeInfo_) == 0) { + MEDIA_INFO_LOG("audio raw data, return."); + CHECK_AND_RETURN_LOG(audioDec_ != nullptr, "Failed to obtain audio decode."); + audioDec_->ReleaseOutputBuffer(index); + return; + } if (buffer != nullptr && !decodeShouldCompleted_) { if (currentSoundBufferSize_ > MAX_SOUND_BUFFER_SIZE || flag == AVCODEC_BUFFER_FLAG_EOS) { decodeShouldCompleted_ = true; CHECK_AND_RETURN_LOG(listener_ != nullptr, "sound decode listener invalid."); listener_->OnSoundDecodeCompleted(availableAudioBuffers_); + listener_->SetSoundBufferTotalSize(static_cast(currentSoundBufferSize_)); CHECK_AND_RETURN_LOG(callback_ != nullptr, "sound decode:soundpool callback invalid."); callback_->OnLoadCompleted(soundID_); return; diff --git a/frameworks/native/soundpool/sound_parser.h b/frameworks/native/soundpool/sound_parser.h index 1a1fece5fe782e02e6513fbf546a2683f1a11724..436f31d8df731656f8eb3bc3fab8e81026adf319 100644 --- a/frameworks/native/soundpool/sound_parser.h +++ b/frameworks/native/soundpool/sound_parser.h @@ -22,9 +22,11 @@ #include #include "ashmem.h" #include "avcodec_audio_decoder.h" +#include "avcodec_errors.h" #include "avdemuxer.h" #include "avsource.h" #include "avsharedmemory.h" +#include "avcodec_codec_name.h" #include "cache_buffer.h" #include "isoundpool.h" #include "media_description.h" @@ -50,10 +52,11 @@ public: } virtual void OnSoundDecodeCompleted(const std::deque> availableAudioBuffers) = 0; + virtual void SetSoundBufferTotalSize(const size_t soundBufferTotalSize) = 0; }; SoundDecoderCallback(const int32_t soundID, const std::shared_ptr &audioDec, - const std::shared_ptr &demuxer); + const std::shared_ptr &demuxer, const std::string trackMimeTypeInfo); ~SoundDecoderCallback(); int32_t SetDecodeCallback(const std::shared_ptr &listener) { @@ -76,6 +79,7 @@ private: std::shared_ptr audioDec_; std::shared_ptr demuxer_; std::shared_ptr listener_; + std::string trackMimeTypeInfo_; bool eosFlag_; std::deque> availableAudioBuffers_; bool decodeShouldCompleted_; @@ -96,6 +100,7 @@ public: return soundID_; } int32_t GetSoundData(std::deque> &soundData) const; + size_t GetSoundDataTotalSize() const; MediaAVCodec::Format GetSoundTrackFormat() const { return trackFormat_; @@ -118,20 +123,35 @@ private: isSoundParserCompleted_.store(true); } } + void SetSoundBufferTotalSize(const size_t soundBufferTotalSize) override + { + std::unique_lock lock(soundParserInner_.lock()->soundParserLock_); + if (!soundParserInner_.expired()) { + soundBufferTotalSize_ = soundBufferTotalSize; + } + } int32_t GetSoundData(std::deque> &soundData) const { std::unique_lock lock(soundParserInner_.lock()->soundParserLock_); soundData = soundData_; return MSERR_OK; } + + size_t GetSoundDataTotalSize() const + { + std::unique_lock lock(soundParserInner_.lock()->soundParserLock_); + return soundBufferTotalSize_; + } bool IsSoundParserCompleted() const { + std::unique_lock lock(soundParserInner_.lock()->soundParserLock_); return isSoundParserCompleted_.load(); } private: std::weak_ptr soundParserInner_; std::deque> soundData_; + size_t soundBufferTotalSize_; std::atomic isSoundParserCompleted_ = false; }; diff --git a/frameworks/native/soundpool/stream_id_manager.cpp b/frameworks/native/soundpool/stream_id_manager.cpp index d80ce837c741bffb7b0b9d5aafff3f4654e64960..98e6f8802cca0acb7bce0eac0ef99c5a00665ef6 100644 --- a/frameworks/native/soundpool/stream_id_manager.cpp +++ b/frameworks/native/soundpool/stream_id_manager.cpp @@ -107,8 +107,10 @@ int32_t StreamIDManager::Play(std::shared_ptr soundParser, PlayPara streamID = nextStreamID_; std::deque> cacheData; soundParser->GetSoundData(cacheData); + size_t cacheDataTotalSize = soundParser->GetSoundDataTotalSize(); auto cacheBuffer = - std::make_shared(soundParser->GetSoundTrackFormat(), cacheData, soundID, streamID); + std::make_shared(soundParser->GetSoundTrackFormat(), cacheData, cacheDataTotalSize, + soundID, streamID); CHECK_AND_RETURN_RET_LOG(cacheBuffer != nullptr, -1, "failed to create cache buffer"); CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, MSERR_INVALID_VAL, "Invalid callback."); cacheBuffer->SetCallback(callback_);