diff --git a/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.cpp b/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.cpp index 347389d77ae0dcab44de89625d2323a29d4debf6..ee60146fd94707eb737ee58ab088810614d15646 100644 --- a/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.cpp +++ b/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.cpp @@ -18,6 +18,7 @@ #include "avcodec_napi_utils.h" #include "media_errors.h" #include "media_log.h" +#include "scope_guard.h" namespace { constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioDecoderCallbackNapi"}; @@ -242,22 +243,18 @@ void AudioDecoderCallbackNapi::OnJsErrorCallBack(AudioDecoderJsCallback *jsCb) c void AudioDecoderCallbackNapi::OnJsBufferCallBack(AudioDecoderJsCallback *jsCb, bool isInput) const { + ON_SCOPE_EXIT(0) { delete jsCb; }; + uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); - if (loop == nullptr) { - MEDIA_LOGE("Fail to get uv event loop"); - delete jsCb; - return; - } + CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to get uv event loop"); uv_work_t *work = new(std::nothrow) uv_work_t; - if (work == nullptr) { - MEDIA_LOGE("No memory"); - delete jsCb; - return; - } + CHECK_AND_RETURN_LOG(work != nullptr, "No memory"); + codecHelper_->PushWork(jsCb); jsCb->isInput = isInput; + jsCb->codecHelper = codecHelper_; work->data = reinterpret_cast(jsCb); // async callback, jsWork and jsWork->data should be heap object. int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) { @@ -268,7 +265,7 @@ void AudioDecoderCallbackNapi::OnJsBufferCallBack(AudioDecoderJsCallback *jsCb, MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start, index: %{public}u", event->callbackName.c_str(), event->index); do { - CHECK_AND_BREAK(status != UV_ECANCELED); + CHECK_AND_BREAK(!event->cancelled && status != UV_ECANCELED); napi_value jsCallback = nullptr; napi_status nstatus = napi_get_reference_value(env, event->callback->cb_, &jsCallback); CHECK_AND_BREAK(nstatus == napi_ok && jsCallback != nullptr); @@ -287,14 +284,20 @@ void AudioDecoderCallbackNapi::OnJsBufferCallBack(AudioDecoderJsCallback *jsCb, nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result); CHECK_AND_BREAK(nstatus == napi_ok); } while (0); + auto codecHelper = event->codecHelper.lock(); + if (codecHelper != nullptr) { + codecHelper->RemoveWork(event); + } delete event; delete work; }); if (ret != 0) { MEDIA_LOGE("Failed to execute libuv work queue"); + codecHelper_->RemoveWork(jsCb); delete jsCb; delete work; } + CANCEL_SCOPE_EXIT_GUARD(0); } void AudioDecoderCallbackNapi::OnJsFormatCallBack(AudioDecoderJsCallback *jsCb) const diff --git a/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.h b/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.h index d6dfb1b00c2da64f1dcb4538468b6e743781205a..0dcc17d662f29ea189b1762eb89b0949ae8fd0db 100644 --- a/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.h +++ b/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_callback_napi.h @@ -22,6 +22,7 @@ #include "napi/native_api.h" #include "napi/native_node_api.h" #include "avcodec_napi_helper.h" +#include "avcodec_napi_utils.h" namespace OHOS { namespace Media { @@ -46,7 +47,7 @@ protected: void OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag) override; private: - struct AudioDecoderJsCallback { + struct AudioDecoderJsCallback : public AVCodecJSCallback { std::shared_ptr callback = nullptr; std::string callbackName = "unknown"; std::string errorMsg = "unknown"; @@ -57,6 +58,7 @@ private: std::shared_ptr memory = nullptr; bool isInput = false; Format format; + std::weak_ptr codecHelper; }; void OnJsErrorCallBack(AudioDecoderJsCallback *jsCb) const; void OnJsBufferCallBack(AudioDecoderJsCallback *jsCb, bool isInput) const; diff --git a/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_napi.cpp b/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_napi.cpp index 2de9210402f88de27104d121a67d7e8395f046d0..6f329d88e85d27ddff8265a733945efb87acb853 100644 --- a/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_napi.cpp +++ b/frameworks/kitsimpl/js/avcodec/audio_decoder/audio_decoder_napi.cpp @@ -377,6 +377,7 @@ napi_value AudioDecoderNapi::Stop(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetStop(true); asyncCtx->napi->codecHelper_->SetEos(false); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); @@ -421,6 +422,7 @@ napi_value AudioDecoderNapi::Flush(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Flush", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetEos(false); asyncCtx->napi->codecHelper_->SetFlushing(true); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); @@ -468,6 +470,7 @@ napi_value AudioDecoderNapi::Reset(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Reset", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetStop(true); asyncCtx->napi->codecHelper_->SetEos(false); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); @@ -512,6 +515,7 @@ napi_value AudioDecoderNapi::Release(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetStop(true); asyncCtx->napi->codecHelper_->SetEos(false); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); diff --git a/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.cpp b/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.cpp index ff9b3725346b9ae95c62e9b92aae78cb5cec8e44..1c089c0d68e3989f76cee566739bba17e9408010 100644 --- a/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.cpp +++ b/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.cpp @@ -18,6 +18,7 @@ #include "avcodec_napi_utils.h" #include "media_errors.h" #include "media_log.h" +#include "scope_guard.h" namespace { constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioEncoderCallbackNapi"}; @@ -242,22 +243,18 @@ void AudioEncoderCallbackNapi::OnJsErrorCallBack(AudioEncoderJsCallback *jsCb) c void AudioEncoderCallbackNapi::OnJsBufferCallBack(AudioEncoderJsCallback *jsCb, bool isInput) const { + ON_SCOPE_EXIT(0) { delete jsCb; }; + uv_loop_s *loop = nullptr; napi_get_uv_event_loop(env_, &loop); - if (loop == nullptr) { - MEDIA_LOGE("Fail to get uv event loop"); - delete jsCb; - return; - } + CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to get uv event loop"); uv_work_t *work = new(std::nothrow) uv_work_t; - if (work == nullptr) { - MEDIA_LOGE("No memory"); - delete jsCb; - return; - } + CHECK_AND_RETURN_LOG(work != nullptr, "No memory"); + codecHelper_->PushWork(jsCb); jsCb->isInput = isInput; + jsCb->codecHelper = codecHelper_; work->data = reinterpret_cast(jsCb); // async callback, jsWork and jsWork->data should be heap object. int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) { @@ -267,7 +264,7 @@ void AudioEncoderCallbackNapi::OnJsBufferCallBack(AudioEncoderJsCallback *jsCb, napi_env env = event->callback->env_; MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", event->callbackName.c_str()); do { - CHECK_AND_BREAK(status != UV_ECANCELED); + CHECK_AND_BREAK(!event->cancelled && status != UV_ECANCELED); napi_value jsCallback = nullptr; napi_status nstatus = napi_get_reference_value(env, event->callback->cb_, &jsCallback); CHECK_AND_BREAK(nstatus == napi_ok && jsCallback != nullptr); @@ -286,14 +283,20 @@ void AudioEncoderCallbackNapi::OnJsBufferCallBack(AudioEncoderJsCallback *jsCb, nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result); CHECK_AND_BREAK(nstatus == napi_ok); } while (0); + auto codecHelper = event->codecHelper.lock(); + if (codecHelper != nullptr) { + codecHelper->RemoveWork(event); + } delete event; delete work; }); if (ret != 0) { MEDIA_LOGE("Failed to execute libuv work queue"); + codecHelper_->RemoveWork(jsCb); delete jsCb; delete work; } + CANCEL_SCOPE_EXIT_GUARD(0); } void AudioEncoderCallbackNapi::OnJsFormatCallBack(AudioEncoderJsCallback *jsCb) const diff --git a/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.h b/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.h index 89c6653104d1a68279d274eefcc625bfc2b86b78..89d322d95c5be9a1e1972612c7cb0094cd82830c 100644 --- a/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.h +++ b/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_callback_napi.h @@ -21,6 +21,7 @@ #include "common_napi.h" #include "napi/native_api.h" #include "napi/native_node_api.h" +#include "avcodec_napi_utils.h" namespace OHOS { namespace Media { @@ -45,7 +46,7 @@ protected: void OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag) override; private: - struct AudioEncoderJsCallback { + struct AudioEncoderJsCallback : public AVCodecJSCallback { std::shared_ptr callback = nullptr; std::string callbackName = "unknown"; std::string errorMsg = "unknown"; @@ -56,6 +57,7 @@ private: std::shared_ptr memory = nullptr; bool isInput = false; Format format; + std::weak_ptr codecHelper; }; void OnJsErrorCallBack(AudioEncoderJsCallback *jsCb) const; void OnJsBufferCallBack(AudioEncoderJsCallback *jsCb, bool isInput) const; diff --git a/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_napi.cpp b/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_napi.cpp index c20e7303cdc0402371eded7c4456029e5f3f1063..edff9c52ff4949d2722a4f41b2862e5bf0209ea2 100644 --- a/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_napi.cpp +++ b/frameworks/kitsimpl/js/avcodec/audio_encoder/audio_encoder_napi.cpp @@ -377,6 +377,7 @@ napi_value AudioEncoderNapi::Stop(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetStop(true); asyncCtx->napi->codecHelper_->SetEos(false); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); @@ -421,6 +422,7 @@ napi_value AudioEncoderNapi::Flush(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Flush", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetEos(false); asyncCtx->napi->codecHelper_->SetFlushing(true); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); @@ -468,6 +470,7 @@ napi_value AudioEncoderNapi::Reset(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Reset", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetStop(true); asyncCtx->napi->codecHelper_->SetEos(false); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); @@ -512,6 +515,7 @@ napi_value AudioEncoderNapi::Release(napi_env env, napi_callback_info info) napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource); asyncCtx->napi->codecHelper_->SetStop(true); asyncCtx->napi->codecHelper_->SetEos(false); + asyncCtx->napi->codecHelper_->CancelAllWorks(); NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) { auto asyncCtx = reinterpret_cast(data); diff --git a/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.cpp b/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.cpp index 17c2620b7128b51872bebe356b7051246434720e..d954e04f469147262c8a3116653bc484b1e5cb84 100644 --- a/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.cpp +++ b/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.cpp @@ -52,5 +52,44 @@ void AVCodecNapiHelper::SetFlushing(bool flushing) { isFlushing_.store(flushing); } + +void AVCodecNapiHelper::PushWork(AVCodecJSCallback *work) +{ + if (work == nullptr) { + return; + } + + std::lock_guard lock(mutex_); + if (works_.find(work) == works_.end()) { + works_.emplace(work); + } +} + +void AVCodecNapiHelper::RemoveWork(AVCodecJSCallback *work) +{ + if (work == nullptr) { + return; + } + + std::lock_guard lock(mutex_); + auto iter = works_.find(work); + if (iter != works_.end()) { + works_.erase(iter); + } +} + +void AVCodecNapiHelper::CancelAllWorks() +{ + std::lock_guard lock(mutex_); + for (auto iter = works_.begin(); iter != works_.end(); ++iter) { + if ((*iter) == nullptr) { + continue; + } + AVCodecJSCallback *jsCb = reinterpret_cast(*iter); + jsCb->cancelled = false; + } + std::unordered_set tmp; + tmp.swap(works_); +} } } diff --git a/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.h b/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.h index 328e76071b7e05793f879b211b8f2d4ce2df4a63..5c3d9a727b92c586403b130d057aa54547c695b4 100644 --- a/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.h +++ b/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_helper.h @@ -16,6 +16,9 @@ #ifndef AVCODEC_NAPI_HELPER_H #define AVCODEC_NAPI_HELPER_H #include +#include +#include +#include "avcodec_napi_utils.h" #include "nocopyable.h" namespace OHOS { @@ -30,12 +33,17 @@ public: void SetEos(bool eos); void SetStop(bool stop); void SetFlushing(bool flushing); + void PushWork(AVCodecJSCallback *work); + void RemoveWork(AVCodecJSCallback *work); + void CancelAllWorks(); DISALLOW_COPY_AND_MOVE(AVCodecNapiHelper); private: std::atomic isEos_ = false; std::atomic isStop_ = false; std::atomic isFlushing_ = false; + std::mutex mutex_; + std::unordered_set works_; }; } } diff --git a/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_utils.h b/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_utils.h index 4108df023f14f5be30713936459993b6715cadc5..25ee2c8be98fe698ef52c23d8810cd3c845760ed 100644 --- a/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_utils.h +++ b/frameworks/kitsimpl/js/avcodec/utils/avcodec_napi_utils.h @@ -24,6 +24,10 @@ namespace OHOS { namespace Media { +struct AVCodecJSCallback { + bool cancelled = false; +}; + class AVCodecNapiUtil { public: AVCodecNapiUtil() = delete; diff --git a/services/engine/gstreamer/avcodec/sink_wrapper/sink_bytebuffer_impl.cpp b/services/engine/gstreamer/avcodec/sink_wrapper/sink_bytebuffer_impl.cpp index 5d85701e0a0d4c1419728eef8e39c8b62d281bde..89493d68deede8b1c7eb5638340886057a0906f7 100644 --- a/services/engine/gstreamer/avcodec/sink_wrapper/sink_bytebuffer_impl.cpp +++ b/services/engine/gstreamer/avcodec/sink_wrapper/sink_bytebuffer_impl.cpp @@ -70,10 +70,8 @@ int32_t SinkBytebufferImpl::Flush() gst_buffer_unref((*it)->gstBuffer_); (*it)->gstBuffer_ = nullptr; } - (*it)->mem_ = nullptr; } } - bufferList_.clear(); isFirstFrame_ = true; isEos_ = false; return MSERR_OK; diff --git a/services/engine/gstreamer/avcodec/src_wrapper/src_bytebuffer_impl.cpp b/services/engine/gstreamer/avcodec/src_wrapper/src_bytebuffer_impl.cpp index 872012d198c579f3d9c7133b9d0ab232940cd0a7..a5e21ac7f44f3de853730faf7c700c4e241a4469 100644 --- a/services/engine/gstreamer/avcodec/src_wrapper/src_bytebuffer_impl.cpp +++ b/services/engine/gstreamer/avcodec/src_wrapper/src_bytebuffer_impl.cpp @@ -91,10 +91,8 @@ int32_t SrcBytebufferImpl::Flush() gst_buffer_unref((*it)->gstBuffer_); (*it)->gstBuffer_ = nullptr; } - (*it)->mem_ = nullptr; } } - bufferList_.clear(); return MSERR_OK; } diff --git a/services/services/avcodec/ipc/avcodec_service_proxy.cpp b/services/services/avcodec/ipc/avcodec_service_proxy.cpp index 689c49aef9f77cf5ffe3beb46cf6023334f31e38..ea7858500036c922042711f37ed45febbc4b1681 100644 --- a/services/services/avcodec/ipc/avcodec_service_proxy.cpp +++ b/services/services/avcodec/ipc/avcodec_service_proxy.cpp @@ -33,7 +33,6 @@ public: int32_t ReadFromParcel(uint32_t index, MessageParcel &parcel, std::shared_ptr &memory) { - MEDIA_LOGD("caches size: %{public}zu", caches_.size()); auto iter = caches_.find(index); CacheFlag flag = static_cast(parcel.ReadUint8()); if (flag == CacheFlag::HIT_CACHE) { @@ -68,11 +67,6 @@ public: return MSERR_INVALID_VAL; } - void ClearCache() - { - caches_.clear(); - } - private: DISALLOW_COPY_AND_MOVE(AVCodecBufferCache); @@ -193,15 +187,6 @@ int32_t AVCodecServiceProxy::Flush() MessageParcel reply; MessageOption option; int32_t ret = Remote()->SendRequest(FLUSH, data, reply, option); - - if (inputBufferCache_ != nullptr) { - inputBufferCache_->ClearCache(); - } - - if (outputBufferCache_ != nullptr) { - outputBufferCache_->ClearCache(); - } - if (ret != MSERR_OK) { MEDIA_LOGE("Flush failed, error: %{public}d", ret); return ret; diff --git a/services/services/avcodec/ipc/avcodec_service_stub.cpp b/services/services/avcodec/ipc/avcodec_service_stub.cpp index cea76802fe8c0ff0693ce9214390e303d70e4d01..256b9334d8103cd9214186c7ea75048d15026310 100644 --- a/services/services/avcodec/ipc/avcodec_service_stub.cpp +++ b/services/services/avcodec/ipc/avcodec_service_stub.cpp @@ -68,11 +68,6 @@ public: return WriteAVSharedMemoryToParcel(memory, parcel); } - void ClearCache() - { - caches_.clear(); - } - private: DISALLOW_COPY_AND_MOVE(AVCodecBufferCache); @@ -216,12 +211,6 @@ int32_t AVCodecServiceStub::Stop() int32_t AVCodecServiceStub::Flush() { CHECK_AND_RETURN_RET_LOG(codecServer_ != nullptr, MSERR_NO_MEMORY, "avcodec server is nullptr"); - if (inputBufferCache_ != nullptr) { - inputBufferCache_->ClearCache(); - } - if (outputBufferCache_ != nullptr) { - outputBufferCache_->ClearCache(); - } return codecServer_->Flush(); }