diff --git a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h index 78ea1b596cc37d32f34306dae0f8e9a480a29a09..997439e025c509a81812dce1b7ee0207c57cf60e 100644 --- a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h +++ b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h @@ -32,7 +32,9 @@ public: RendererState GetStatus() const override; bool GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const override; bool Drain() const override; + bool Pause() const override; bool Stop() const override; + bool Flush() const override; bool Release() const override; int32_t GetBufferSize(size_t &bufferSize) const override; diff --git a/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp index 87c8fdc3395c8bb6c84057b79b2bc90238cf48e3..df37e8ca5352bc0455014b3b94c9787ef9786bc5 100644 --- a/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp +++ b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp @@ -95,6 +95,16 @@ bool AudioRendererPrivate::Drain() const return audioRenderer->DrainAudioStream(); } +bool AudioRendererPrivate::Flush() const +{ + return audioRenderer->FlushAudioStream(); +} + +bool AudioRendererPrivate::Pause() const +{ + return audioRenderer->PauseAudioStream(); +} + bool AudioRendererPrivate::Stop() const { return audioRenderer->StopAudioStream(); diff --git a/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h b/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h index ce6d9e8de627417ec6570f2844f348b5a322d501..649f795212d17e2412d98ebb5bd5bd862e0fc110 100644 --- a/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h +++ b/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h @@ -53,7 +53,9 @@ enum RendererState { /** Renderer Released state */ RENDERER_RELEASED, /** INVALID state */ - RENDERER_INVALID + RENDERER_INVALID, + /** Renderer Paused state */ + RENDERER_PAUSED }; /** @@ -154,6 +156,20 @@ public: */ virtual bool Drain() const = 0; + /** + * @brief flush renderer stream. + * + * @return Returns true if the object is successfully flushed; returns false otherwise. + */ + virtual bool Flush() const = 0; + + /** + * @brief Pauses audio rendering. + * + * @return Returns true if the rendering is successfully Paused; returns false otherwise. + */ + virtual bool Pause() const = 0; + /** * @brief Stops audio rendering. * diff --git a/interfaces/innerkits/native/audiostream/include/audio_stream.h b/interfaces/innerkits/native/audiostream/include/audio_stream.h index d24838e832adab38adf42e23fb3446321b8b7af8..66694d6f6ea7cda09d9f350f30f6da529583c996 100644 --- a/interfaces/innerkits/native/audiostream/include/audio_stream.h +++ b/interfaces/innerkits/native/audiostream/include/audio_stream.h @@ -43,7 +43,9 @@ enum State { /** Released */ RELEASED, /** INVALID */ - INVALID + INVALID, + /** Paused */ + PAUSED }; class AudioStream : public AudioSession { @@ -68,6 +70,7 @@ public: // Common APIs bool StartAudioStream(); + bool PauseAudioStream(); bool StopAudioStream(); bool ReleaseAudioStream(); bool FlushAudioStream(); diff --git a/services/include/client/audio_service_client.h b/services/include/client/audio_service_client.h index d8b39f746380943c3b046b98f3c8e8e15a9639c5..a9374d1df27e6b0c15e1a584a165f72e1d7297f6 100644 --- a/services/include/client/audio_service_client.h +++ b/services/include/client/audio_service_client.h @@ -132,12 +132,11 @@ public: int32_t DrainStream(); /** - * Pauses the stream using the session ID + * Pauses the stream * - * @param sessionID indicates the ID for the active stream to be controlled * @return Returns {@code 0} if success; returns {@code -1} otherwise. */ - int32_t PauseStream(uint32_t sessionID); + int32_t PauseStream(); /** * Sets the volume of the stream associated with session ID diff --git a/services/src/client/audio_service_client.cpp b/services/src/client/audio_service_client.cpp index cc63a15612c42369325581998fc493e47a0b9f21..a14230a1281962d5d4522315cc763a5b21b09fe5 100644 --- a/services/src/client/audio_service_client.cpp +++ b/services/src/client/audio_service_client.cpp @@ -560,10 +560,9 @@ int32_t AudioServiceClient::StartStream() } } -int32_t AudioServiceClient::PauseStream(uint32_t sessionID) +int32_t AudioServiceClient::PauseStream() { - CHECK_PA_STATUS_RET_IF_FAIL(mainLoop, context, paStream, AUDIO_CLIENT_PA_ERR); - return AUDIO_CLIENT_SUCCESS; + return StopStream(); } int32_t AudioServiceClient::StopStream() @@ -628,6 +627,9 @@ int32_t AudioServiceClient::FlushStream() return AUDIO_CLIENT_ERR; } else { MEDIA_INFO_LOG("Stream Flushed Successfully"); + acache.readIndex = 0; + acache.writeIndex = 0; + acache.isFull = false; return AUDIO_CLIENT_SUCCESS; } } diff --git a/services/src/client/audio_stream.cpp b/services/src/client/audio_stream.cpp index 22f6c473b3f662396f2197f811bad7b7fd04dc1e..7eb856689e3c105688f581b432e44e240b757227 100644 --- a/services/src/client/audio_stream.cpp +++ b/services/src/client/audio_stream.cpp @@ -207,7 +207,7 @@ int32_t AudioStream::SetAudioStreamInfo(const AudioStreamParams info) bool AudioStream::StartAudioStream() { - if ((state_ != PREPARED) && (state_ != STOPPED)) { + if ((state_ != PREPARED) && (state_ != STOPPED) && (state_ != PAUSED)) { MEDIA_ERR_LOG("StartAudioStream Illegal state:%{public}u", state_); return false; } @@ -279,6 +279,28 @@ size_t AudioStream::Write(uint8_t *buffer, size_t buffer_size) return bytesWritten; } +bool AudioStream::PauseAudioStream() +{ + if (state_ != RUNNING) { + MEDIA_ERR_LOG("PauseAudioStream: State is not RUNNING. Illegal state:%{public}u", state_); + return false; + } + State oldState = state_; + state_ = PAUSED; // Set it before stopping as Read/Write and Stop can be called from different threads + while (isReadInProgress_ || isWriteInProgress_) { + } + + int32_t ret = PauseStream(); + if (ret != SUCCESS) { + MEDIA_DEBUG_LOG("StreamPause fail,ret:0x%{public}x", ret); + state_ = oldState; + return false; + } + MEDIA_INFO_LOG("PauseAudioStream SUCCESS"); + + return true; +} + bool AudioStream::StopAudioStream() { if (state_ != RUNNING) { @@ -303,7 +325,7 @@ bool AudioStream::StopAudioStream() bool AudioStream::FlushAudioStream() { - if (state_ != RUNNING) { + if ((state_ != RUNNING) && (state_ != PAUSED)) { MEDIA_ERR_LOG("FlushAudioStream: State is not RUNNING. Illegal state:%{public}u", state_); return false; } diff --git a/services/test/audio_renderer_test.cpp b/services/test/audio_renderer_test.cpp index 7e8418e7703a57899b17912c2d5f19d96cdd8967..9deecb7c9cb7cd36371bcfe92902b0ec073e23d4 100644 --- a/services/test/audio_renderer_test.cpp +++ b/services/test/audio_renderer_test.cpp @@ -26,6 +26,10 @@ namespace AudioTestConstants { constexpr int32_t ARGS_INDEX_TWO = 2; constexpr int32_t ARGS_COUNT_TWO = 2; constexpr int32_t SUCCESS = 0; + constexpr int32_t STOP_BUFFER_POSITION = 700000; + constexpr int32_t PAUSE_BUFFER_POSITION = 1400000; + constexpr int32_t PAUSE_RENDER_TIME_SECONDS = 1; + constexpr int32_t STOP_RENDER_TIME_SECONDS = 1; } class AudioRendererTest { @@ -115,12 +119,41 @@ public: size_t bytesWritten = 0; size_t minBytes = 4; uint64_t latency; + bool stopTested = false; + bool pauseTested = false; while (!feof(wavFile)) { bytesToWrite = fread(buffer, 1, bufferLen, wavFile); bytesWritten = 0; MEDIA_INFO_LOG("AudioRendererTest: Bytes to write: %{public}d", bytesToWrite); + uint64_t currFilePos = ftell(wavFile); + MEDIA_INFO_LOG("AudioRendererTest: Current file position: %{public}llu", currFilePos); + if (!stopTested && (currFilePos > AudioTestConstants::STOP_BUFFER_POSITION) && audioRenderer->Stop()) { + MEDIA_INFO_LOG("Audio render stopping for 1 second"); + stopTested = true; + sleep(AudioTestConstants::STOP_RENDER_TIME_SECONDS); + MEDIA_INFO_LOG("Audio render resume"); + if (!audioRenderer->Start()) { + MEDIA_ERR_LOG("resume stream failed"); + break; + } + } else if (!pauseTested && (currFilePos > AudioTestConstants::PAUSE_BUFFER_POSITION) + && audioRenderer->Pause()) { + MEDIA_INFO_LOG("Audio render pausing for 1 second"); + pauseTested = true; + sleep(AudioTestConstants::PAUSE_RENDER_TIME_SECONDS); + MEDIA_INFO_LOG("Audio render resume"); + if (!audioRenderer->Flush()) { + MEDIA_ERR_LOG("AudioRendererTest: flush failed"); + break; + } + if (!audioRenderer->Start()) { + MEDIA_ERR_LOG("resume stream failed"); + break; + } + } + if (audioRenderer->GetLatency(latency)) { MEDIA_ERR_LOG("AudioRendererTest: GetLatency failed"); break; @@ -183,7 +216,7 @@ public: return false; } - if (StartRender(audioRenderer, wavFile)) { + if (!StartRender(audioRenderer, wavFile)) { MEDIA_ERR_LOG("AudioRendererTest: Start render failed"); return false; }