diff --git a/framework/algorithm/aihdr_enhancer_video/aihdr_enhancer_video_impl.cpp b/framework/algorithm/aihdr_enhancer_video/aihdr_enhancer_video_impl.cpp index 6f565bf..1f8c895 100644 --- a/framework/algorithm/aihdr_enhancer_video/aihdr_enhancer_video_impl.cpp +++ b/framework/algorithm/aihdr_enhancer_video/aihdr_enhancer_video_impl.cpp @@ -396,9 +396,9 @@ void AihdrEnhancerVideoImpl::Process(std::shared_ptr input VPETrace cscTrace("AihdrEnhancerVideoImpl::csc_->Process"); ret = csc_->Process(surfaceOutputBuffer); } - if (ret != 0 && cb_) { - cb_->OnError(ret); - } + if (ret != 0 && cb_) { + cb_->OnError(ret); + } inputSurface_->ReleaseBuffer(surfaceInputBuffer, -1); if (!ret) { std::unique_lock lockOnBq(renderQueMutex_); diff --git a/framework/algorithm/common/algorithm_video.cpp b/framework/algorithm/common/algorithm_video.cpp index de4d16b..c55c3bb 100644 --- a/framework/algorithm/common/algorithm_video.cpp +++ b/framework/algorithm/common/algorithm_video.cpp @@ -82,6 +82,11 @@ VPEAlgoErrCode VpeVideo::Stop() return VPE_ALGO_ERR_OK; } +VPEAlgoErrCode VpeVideo::Release() +{ + return VPE_ALGO_ERR_OK; +} + VPEAlgoErrCode VpeVideo::Flush() { return VPE_ALGO_ERR_OK; diff --git a/framework/algorithm/common/algorithm_video_impl.cpp b/framework/algorithm/common/algorithm_video_impl.cpp index 9574901..86179de 100644 --- a/framework/algorithm/common/algorithm_video_impl.cpp +++ b/framework/algorithm/common/algorithm_video_impl.cpp @@ -74,12 +74,30 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr& surface) "Invalid input: surface is invalid!"); std::lock_guard lock(lock_); + if (producer_ == surface) { + VPE_LOGD("Oops! The same surface!"); + return VPE_ALGO_ERR_OK; + } + if (producer_ != nullptr) { + producer_->UnRegisterReleaseListener(); + producer_->CleanCache(true); + } + surface->UnRegisterReleaseListener(); + surface->CleanCache(true); GSError err = surface->RegisterReleaseListener([this](sptr&) { return OnProducerBufferReleased(); }); CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN, "RegisterReleaseListener failed!"); - surface->SetQueueSize(BUFFER_QUEUE_SIZE); VPE_LOGI("Set output buffer queue size to %{public}u", BUFFER_QUEUE_SIZE); + surface->SetQueueSize(BUFFER_QUEUE_SIZE); + surface->Connect(); + AttachBuffers(surface); + if (state_.load() != VPEState::IDLE) { + cvTrigger_.notify_one(); + } producer_ = surface; - auto ret = UpdateRequestCfg(surface, requestCfg_); + VPEAlgoErrCode ret = VPE_ALGO_ERR_OK; + if (isEnable_.load()) { + ret = UpdateRequestCfg(surface, requestCfg_); + } VPE_LOGD("requestCfg_({ %{public}s })", ToString(requestCfg_).c_str()); return ret; } @@ -114,32 +132,36 @@ VPEAlgoErrCode VpeVideoImpl::Stop() { auto err = ExecuteWhenRunning([this]() { state_ = VPEState::STOPPING; - cv_.notify_one(); + cvTrigger_.notify_one(); return VPE_ALGO_ERR_OK; }, "Already stop!"); return err; } +VPEAlgoErrCode VpeVideoImpl::Release() +{ + return Deinitialize(); +} + VPEAlgoErrCode VpeVideoImpl::Flush() { - return ExecuteWhenNotIdle( - [this]() { - std::queue tempQueue1; - std::queue tempQueue2; - { - std::lock_guard bufferLock(bufferLock_); - consumerBufferQueue_.swap(tempQueue1); - while (!renderBufferQueue_.empty()) { - producerBufferQueue_.push(renderBufferQueue_.front()); - renderBufferQueue_.pop(); - } - attachBufferQueue_.swap(tempQueue2); - attachBufferIDs_.clear(); - } - ClearConsumerLocked(tempQueue1); - ClearConsumerLocked(tempQueue2); - return VPE_ALGO_ERR_OK; - }, "Flush must be called during running!"); + std::unique_lock lock(lock_); + cvDone_.wait(lock, [this]() { return !isProcessing_.load(); }); + std::queue tempQueue1; + std::queue tempQueue2; + { + std::lock_guard bufferLock(bufferLock_); + consumerBufferQueue_.swap(tempQueue1); + while (!renderBufferQueue_.empty()) { + producerBufferQueue_.push(renderBufferQueue_.front()); + renderBufferQueue_.pop(); + } + attachBufferQueue_.swap(tempQueue2); + attachBufferIDs_.clear(); + } + ClearConsumerLocked(tempQueue1); + ClearConsumerLocked(tempQueue2); + return VPE_ALGO_ERR_OK; } VPEAlgoErrCode VpeVideoImpl::Enable() @@ -155,6 +177,13 @@ VPEAlgoErrCode VpeVideoImpl::Enable() auto ret = UpdateRequestCfg(producer_, requestCfg_); VPE_LOGD("requestCfg_({ %{public}s })", ToString(requestCfg_).c_str()); + if (requestCfg_.usage == orgRequestCfg_.usage && + requestCfg_.format == orgRequestCfg_.format && + requestCfg_.width == orgRequestCfg_.width && + requestCfg_.height == orgRequestCfg_.height) { + producer_->CleanCache(false); + ClearBufferQueues(); + } return ret; } @@ -179,7 +208,7 @@ VPEAlgoErrCode VpeVideoImpl::NotifyEos() bufferInfo.bufferFlag = VPE_BUFFER_FLAG_EOS; consumerBufferQueue_.push(bufferInfo); } - cv_.notify_one(); + cvTrigger_.notify_one(); return VPE_ALGO_ERR_OK; }, "Notify EOS must be called during running!"); } @@ -216,7 +245,12 @@ VPEAlgoErrCode VpeVideoImpl::Initialize() while (isRunning_.load()) { { std::unique_lock bufferLock(bufferLock_); - if (!cv_.wait_for(bufferLock, 200s, [this] { + if (!cvTrigger_.wait_for(bufferLock, 200s, [this] { + VPE_LOGD("run:%d stopping:%d consumerBQ:%{public}zu producerBQ:%{public}zu " + "renderBQ:%{public}zu flushBQ:%{public}zu attachBQ:%{public}zu", + isRunning_.load(), state_.load() == VPEState::STOPPING, + consumerBufferQueue_.size(), producerBufferQueue_.size(), + renderBufferQueue_.size(), flushBufferQueue_.size(), attachBufferQueue_.size()); return !isRunning_.load() || state_.load() == VPEState::STOPPING || (!producerBufferQueue_.empty() && !consumerBufferQueue_.empty()); })) { @@ -230,23 +264,27 @@ VPEAlgoErrCode VpeVideoImpl::Initialize() } if (producerBufferQueue_.empty() || consumerBufferQueue_.empty()) { CheckSpuriousWakeup(); + VPE_LOGD("Empty! consumerBQ:%{public}zu producerBQ:%{public}zu", consumerBufferQueue_.size(), + producerBufferQueue_.size()); continue; } } + VPE_LOGD("ProcessBuffers"); ProcessBuffers(); CheckStopping(); }; }); auto errorCode = OnInitialize(); isInitialized_ = true; - VPE_LOGD("OnInitialize() return %{public}d.", errorCode); + VPE_LOGD("OnInitialize() return %{public}d. this:%{public}p", errorCode, this); return errorCode; } VPEAlgoErrCode VpeVideoImpl::Deinitialize() { - std::lock_guard lock(lock_); - VPE_LOGD("Start to deinitializing..."); + std::unique_lock lock(lock_); + VPE_LOGD("Start to deinitializing... this:%{public}p", this); + cvDone_.wait(lock, [this]() { return !isProcessing_.load(); }); if (!isInitialized_.load()) { VPE_LOGD("Already deinitialize!"); return VPE_ALGO_ERR_OK; @@ -257,7 +295,7 @@ VPEAlgoErrCode VpeVideoImpl::Deinitialize() state_ = VPEState::STOPPING; } isRunning_ = false; - cv_.notify_one(); + cvTrigger_.notify_one(); if (worker_.joinable()) { worker_.join(); } @@ -273,7 +311,7 @@ VPEAlgoErrCode VpeVideoImpl::Deinitialize() producer_->CleanCache(true); producer_ = nullptr; } - VPE_LOGD("OnDeinitialize() return %{public}d.", errorCode); + VPE_LOGD("OnDeinitialize() return %{public}d. this:%{public}p", errorCode, this); return errorCode; } @@ -402,24 +440,37 @@ GSError VpeVideoImpl::OnConsumerBufferAvailable() } consumerBufferQueue_.push(bufferInfo); } - cv_.notify_one(); + cvTrigger_.notify_one(); return GSERROR_OK; } GSError VpeVideoImpl::OnProducerBufferReleased() { + VPE_LOGD("step in"); std::lock_guard lock(lock_); CHECK_AND_RETURN_RET_LOG(consumer_ != nullptr || producer_ != nullptr, GSERROR_OK, "Input or output surface is null!"); { std::lock_guard bufferLock(bufferLock_); + if (flushBufferQueue_.empty()) { + VPE_LOGD("NO flush buffer!"); + return GSERROR_OK; + } GSError err = GSERROR_OK; - CHECK_AND_RETURN_RET_LOG(RequestBuffer(err), err, "Failed to request buffer!"); + SurfaceBufferInfo bufferInfo{}; + CHECK_AND_RETURN_RET_LOG(RequestBuffer(bufferInfo, err), err, "Failed to request buffer!"); + PopBuffer(flushBufferQueue_, bufferInfo.buffer->GetSeqNum(), bufferInfo, + [this](sptr& buffer) { + CHECK_AND_RETURN_LOG(buffer != nullptr, "OnProducerBufferReleased: Flush buffer is null!"); + VPE_LOGD("OnProducerBufferReleased: Pop flush buffer { %{public}s } flushBQ=%{public}zu", + ToString(buffer).c_str(), flushBufferQueue_.size()); + }); } if (state_.load() != VPEState::IDLE) { - cv_.notify_one(); + cvTrigger_.notify_one(); } + VPE_LOGD("step out"); return GSERROR_OK; } @@ -437,10 +488,19 @@ VPEAlgoErrCode VpeVideoImpl::RenderOutputBufferLocked(uint32_t index, int64_t re flushcfg.damage.h = bufferInfo.buffer->GetHeight(); flushcfg.timestamp = (renderTimestamp == -1) ? bufferInfo.timestamp : renderTimestamp; auto ret = producer_->FlushBuffer(bufferInfo.buffer, -1, flushcfg); - VPE_LOGD("producer_->FlushBuffer({ %{public}s })=%{public}d", ToString(bufferInfo.buffer).c_str(), ret); + VPE_LOGD("producer_->FlushBuffer({ %{public}s })=%{public}d flushBQ=%{public}zu", + ToString(bufferInfo.buffer).c_str(), ret, flushBufferQueue_.size() + 1); + bufferLock.lock(); + flushBufferQueue_.push(bufferInfo); } else { + VPE_LOGD("reback { %{public}s } producerBQ=%{public}zu", + ToString(bufferInfo.buffer).c_str(), producerBufferQueue_.size() + 1); bufferLock.lock(); producerBufferQueue_.push(bufferInfo); + bufferLock.unlock(); + if (state_.load() != VPEState::IDLE) { + cvTrigger_.notify_one(); + } } return VPE_ALGO_ERR_OK; } @@ -467,9 +527,8 @@ sptr VpeVideoImpl::CreateConsumerSurfaceLocked() return producerSurface; } -bool VpeVideoImpl::RequestBuffer(GSError& errorCode) +bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode) { - SurfaceBufferInfo bufferInfo{}; int releaseFence = -1; errorCode = producer_->RequestBuffer(bufferInfo.buffer, releaseFence, requestCfg_); if (errorCode != GSERROR_OK || bufferInfo.buffer == nullptr) { @@ -511,11 +570,39 @@ void VpeVideoImpl::PrepareBuffers() { for (uint32_t i = 0; i < producer_->GetQueueSize(); i++) { GSError errorCode; - RequestBuffer(errorCode); + SurfaceBufferInfo bufferInfo{}; + RequestBuffer(bufferInfo, errorCode); VPE_LOGD("<%{public}u> RequestBuffer({ %{public}s })=%{public}d", i, ToString(requestCfg_).c_str(), errorCode); } } +void VpeVideoImpl::AttachBuffers(const sptr& producer) +{ + std::lock_guard bufferLock(bufferLock_); + std::queue tempQueue; + producerBufferQueue_.swap(tempQueue); + AttachBuffers(producer, tempQueue); + AttachBuffers(producer, flushBufferQueue_); +} + +void VpeVideoImpl::AttachBuffers(const sptr& producer, std::queue& bufferQueue) +{ + for (; !bufferQueue.empty(); bufferQueue.pop()) { + auto bufferInfo = bufferQueue.front(); + if (bufferInfo.buffer == nullptr) { + VPE_LOGW("buffer is null!"); + continue; + } + auto errorCode = producer->AttachBufferToQueue(bufferInfo.buffer); + if (errorCode != GSERROR_OK) { + VPE_LOGW("Failed to producer->AttachBufferToQueue({ %{public}s })=%{public}d", + ToString(bufferInfo.buffer).c_str(), errorCode); + continue; + } + producerBufferQueue_.push(bufferInfo); + } +} + void VpeVideoImpl::ProcessBuffers() { sptr consumer; @@ -525,8 +612,9 @@ void VpeVideoImpl::ProcessBuffers() return; } consumer = consumer_; + isProcessing_ = true; } - while (state_.load() != VPEState::IDLE) { + while (isRunning_.load()) { SurfaceBufferInfo srcBufferInfo; SurfaceBufferInfo dstBufferInfo; { @@ -555,6 +643,14 @@ void VpeVideoImpl::ProcessBuffers() BypassBuffer(srcBufferInfo, dstBufferInfo); } } + VPE_LOGD("consumerBQ:%{public}zu producerBQ:%{public}zu renderBQ:%{public}zu flushBQ:%{public}zu " + "attachBQ:%{public}zu", consumerBufferQueue_.size(), producerBufferQueue_.size(), renderBufferQueue_.size(), + flushBufferQueue_.size(), attachBufferQueue_.size()); + { + std::lock_guard lock(lock_); + isProcessing_ = false; + } + cvDone_.notify_all(); } bool VpeVideoImpl::ProcessBuffer(sptr& consumer, SurfaceBufferInfo& srcBufferInfo, @@ -647,6 +743,7 @@ void VpeVideoImpl::SetRequestCfgLocked(const sptr& buffer) requestCfg_.format = buffer->GetFormat(); requestCfg_.width = buffer->GetWidth(); requestCfg_.height = buffer->GetHeight(); + orgRequestCfg_ = requestCfg_; } void VpeVideoImpl::CheckSpuriousWakeup() @@ -683,7 +780,8 @@ void VpeVideoImpl::ClearQueue(std::queue& bufferQueue) void VpeVideoImpl::ClearConsumerLocked(std::queue& bufferQueue) { while (!bufferQueue.empty()) { - consumer_->ReleaseBuffer(bufferQueue.front().buffer, -1); + auto bufferInfo = bufferQueue.front(); + consumer_->ReleaseBuffer(bufferInfo.buffer, -1); bufferQueue.pop(); } } @@ -736,9 +834,10 @@ VPEAlgoErrCode VpeVideoImpl::ExecuteWithCheck(std::function&& checke void VpeVideoImpl::ConsumerListener::OnBufferAvailable() { - if (owner_ == nullptr) { + std::shared_ptr owner = owner_.lock(); + if (owner == nullptr) { VPE_LOGE("Video processing is null!"); return; } - owner_->OnConsumerBufferAvailable(); + owner->OnConsumerBufferAvailable(); } diff --git a/framework/algorithm/common/include/algorithm_video_impl.h b/framework/algorithm/common/include/algorithm_video_impl.h index 1800be6..fccfa1b 100644 --- a/framework/algorithm/common/include/algorithm_video_impl.h +++ b/framework/algorithm/common/include/algorithm_video_impl.h @@ -43,6 +43,7 @@ public: sptr GetInputSurface() override; VPEAlgoErrCode Start() override; VPEAlgoErrCode Stop() override; + VPEAlgoErrCode Release() override; VPEAlgoErrCode Flush() override; VPEAlgoErrCode Enable() override; VPEAlgoErrCode Disable() override; @@ -96,7 +97,7 @@ private: void OnBufferAvailable() final; private: - std::shared_ptr owner_; + std::weak_ptr owner_; }; void OnErrorLocked(VPEAlgoErrCode errorCode); @@ -109,8 +110,10 @@ private: VPEAlgoErrCode RenderOutputBufferLocked(uint32_t index, int64_t renderTimestamp, bool render); sptr CreateConsumerSurfaceLocked(); - bool RequestBuffer(GSError& errorCode); + bool RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode); void PrepareBuffers(); + void AttachBuffers(const sptr& producer); + void AttachBuffers(const sptr& producer, std::queue& bufferQueue); void ProcessBuffers(); bool ProcessBuffer(sptr& consumer, SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo); void BypassBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo); @@ -136,12 +139,14 @@ private: uint32_t type_{}; // For thread control - std::condition_variable cv_{}; + std::condition_variable cvTrigger_{}; + std::condition_variable cvDone_{}; mutable std::mutex lock_{}; // Guarded by lock_ begin std::atomic isInitialized_{false}; std::atomic isRunning_{false}; + std::atomic isProcessing_{false}; std::atomic isEnable_{true}; std::atomic isEnableChange_{true}; std::atomic state_{VPEState::IDLE}; @@ -150,6 +155,7 @@ private: sptr consumer_{}; sptr producer_{}; BufferRequestConfig requestCfg_{}; + BufferRequestConfig orgRequestCfg_{}; // Guarded by lock_ end mutable std::mutex bufferLock_{}; @@ -158,6 +164,7 @@ private: std::queue consumerBufferQueue_{}; std::queue producerBufferQueue_{}; std::queue renderBufferQueue_{}; + std::queue flushBufferQueue_{}; std::queue attachBufferQueue_{}; std::set attachBufferIDs_{}; // Guarded by bufferLock_ end diff --git a/framework/algorithm/detail_enhancer_video/include/detail_enhancer_video_fwk.h b/framework/algorithm/detail_enhancer_video/include/detail_enhancer_video_fwk.h index 85e3274..ee76b39 100644 --- a/framework/algorithm/detail_enhancer_video/include/detail_enhancer_video_fwk.h +++ b/framework/algorithm/detail_enhancer_video/include/detail_enhancer_video_fwk.h @@ -30,7 +30,7 @@ public: static std::shared_ptr Create(); explicit DetailEnhancerVideoFwk(uint32_t type) : VpeVideoImpl(type) {} - virtual ~DetailEnhancerVideoFwk() = default; + ~DetailEnhancerVideoFwk() = default; DetailEnhancerVideoFwk(const DetailEnhancerVideoFwk&) = delete; DetailEnhancerVideoFwk& operator=(const DetailEnhancerVideoFwk&) = delete; DetailEnhancerVideoFwk(DetailEnhancerVideoFwk&&) = delete; diff --git a/framework/algorithm/metadata_generator_video/metadata_generator_video_impl.cpp b/framework/algorithm/metadata_generator_video/metadata_generator_video_impl.cpp index a773334..848072e 100644 --- a/framework/algorithm/metadata_generator_video/metadata_generator_video_impl.cpp +++ b/framework/algorithm/metadata_generator_video/metadata_generator_video_impl.cpp @@ -111,7 +111,7 @@ int32_t MetadataGeneratorVideoImpl::SetCallback(const std::shared_ptr newSurface) { std::lock_guard lockrender(renderQueMutex_); - for (auto it = outputBufferAvilQueBak_.begin(); it != outputBufferAvilQueBak_.end(); ++it) { + for (auto it = outputBufferAvilQueBak_.begin(); it != outputBufferAvilQueBak_.end(); ++it) { auto buffer = it->second; GSError err = newSurface->AttachBufferToQueue(buffer->memory); CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN, "outputbuffer AttachToNewSurface fail"); @@ -406,9 +406,9 @@ void MetadataGeneratorVideoImpl::Process(std::shared_ptr i VPETrace cscTrace("MetadataGeneratorVideoImpl::csc_->Process"); ret = csc_->Process(surfaceOutputBuffer); } - if (ret != 0 && cb_) { - cb_->OnError(ret); - } + if (ret != 0 && cb_) { + cb_->OnError(ret); + } inputSurface_->ReleaseBuffer(surfaceInputBuffer, -1); if (!ret) { std::unique_lock lockOnBq(renderQueMutex_); diff --git a/interfaces/inner_api/algorithm_video.h b/interfaces/inner_api/algorithm_video.h index 6c68085..2a50c1c 100644 --- a/interfaces/inner_api/algorithm_video.h +++ b/interfaces/inner_api/algorithm_video.h @@ -94,12 +94,23 @@ public: /** * @brief Stop video processing. + * + * This method must be called during running. + * * @return If successful, returns {@link VPE_ALGO_ERR_OK}. On error, retuns an error code. * @since 5.1 * @version 5.1 */ virtual VPEAlgoErrCode Stop(); + /** + * @brief Releases all resources before destructor. All methods are unavailable after calling this. + * @return If successful, returns {@link VPE_ALGO_ERR_OK}. On error, retuns an error code. + * @since 5.1 + * @version 5.1 + */ + virtual VPEAlgoErrCode Release(); + /** * @brief Flush both input and output buffers for video processing. * diff --git a/test/utils/ColorSpaceConverter/sample/csc_sample.cpp b/test/utils/ColorSpaceConverter/sample/csc_sample.cpp index 2c5c07a..e9bedfe 100644 --- a/test/utils/ColorSpaceConverter/sample/csc_sample.cpp +++ b/test/utils/ColorSpaceConverter/sample/csc_sample.cpp @@ -60,7 +60,11 @@ void SetMeatadata(sptr &buffer, uint32_t value) { std::vector metadata; metadata.resize(sizeof(value)); - (void)memcpy_s(metadata.data(), metadata.size(), &value, sizeof(value)); + errno_t ret = memcpy_s(metadata.data(), metadata.size(), &value, sizeof(value)); + if (ret != EOK) { + printf("memcpy_s failed, err = %d\n", ret); + return; + } GSError err = buffer->SetMetadata(ATTRKEY_HDR_METADATA_TYPE, metadata); if (err != 0) { printf("Buffer set metadata type, ret: %d\n", static_cast(err)); @@ -71,7 +75,11 @@ void SetMeatadata(sptr &buffer, const CM_ColorSpaceInfo &colorspa { std::vector metadata; metadata.resize(sizeof(CM_ColorSpaceInfo)); - (void)memcpy_s(metadata.data(), metadata.size(), &colorspaceInfo, sizeof(CM_ColorSpaceInfo)); + errno_t ret = memcpy_s(metadata.data(), metadata.size(), &colorspaceInfo, sizeof(CM_ColorSpaceInfo)); + if (ret != EOK) { + printf("memcpy_s failed, err = %d\n", ret); + return; + } GSError err = buffer->SetMetadata(ATTRKEY_COLORSPACE_INFO, metadata); if (err != 0) { printf("Buffer set colorspace info, ret: %d\n", static_cast(err)); @@ -111,8 +119,11 @@ void PrintMetadataType(sptr &buffer, int32_t bufferHandleAttrKey) return; } int32_t value; - (void)memcpy_s(&value, sizeof(value), metadata.data(), metadata.size()); - + errno_t ret = memcpy_s(&value, sizeof(value), metadata.data(), metadata.size()); + if (ret != EOK) { + printf("memcpy_s failed, err = %d\n", ret); + return; + } std::string bufferHandleStr = bufferHandleAttrKey == ATTRKEY_COLORSPACE_TYPE ? "colorspace" : "metadata"; printf("Buffer %s type %d\n", bufferHandleStr.c_str(), value); }