* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FRAMEWORKS_INNERKITSIMPL_RECEIVER_INCLUDE_IMAGE_RECEIVER_H
#define FRAMEWORKS_INNERKITSIMPL_RECEIVER_INCLUDE_IMAGE_RECEIVER_H
#include <cstdint>
#include <mutex>
#include <securec.h>
#include <string>
#include <surface.h>
#include "image_format.h"
#include "image_type.h"
#include "media_errors.h"
#include "pixel_map.h"
#include "image_receiver_context.h"
#include "image/image_receiver_native.h"
#include "native_image.h"
#include "surface_utils.h"
namespace OHOS {
namespace Media {
class IBufferProcessor;
class NativeImage;
class SurfaceBufferAvaliableListener {
public:
SurfaceBufferAvaliableListener()= default;
virtual ~SurfaceBufferAvaliableListener()= default;
virtual void OnSurfaceBufferAvaliable() = 0;
};
class ImageReceiverArriveListener : public SurfaceBufferAvaliableListener {
public:
explicit ImageReceiverArriveListener(OH_ImageReceiverNative* receiver) : receiver_(receiver) {}
~ImageReceiverArriveListener() override
{
std::lock_guard<std::mutex> lock(mutex_);
callbacks_.clear();
}
bool HasCallback(OH_ImageReceiver_ImageArriveCallback callback)
{
std::lock_guard<std::mutex> lock(mutex_);
return std::any_of(callbacks_.begin(), callbacks_.end(),
[callback](const CallbackData &cbData) { return cbData.callback == callback; });
}
bool RegisterCallback(OH_ImageReceiver_ImageArriveCallback callback, void* userdata)
{
if (callback == nullptr) {
return false;
}
if (HasCallback(callback)) {
return false;
}
std::lock_guard<std::mutex> lock(mutex_);
callbacks_.emplace_back(callback, userdata);
return true;
}
bool UnregisterCallback(OH_ImageReceiver_ImageArriveCallback callback)
{
if (callback == nullptr) {
return false;
}
std::lock_guard<std::mutex> lock(mutex_);
auto it = std::remove_if(callbacks_.begin(), callbacks_.end(),
[callback](const CallbackData &cbData) { return cbData.callback == callback; });
if (it != callbacks_.end()) {
callbacks_.erase(it, callbacks_.end());
return true;
}
return false;
}
void OnSurfaceBufferAvaliable() __attribute__((no_sanitize("cfi"))) override
{
std::lock_guard<std::mutex> lock(mutex_);
for (const auto& cbData : callbacks_) {
if (cbData.callback != nullptr) {
cbData.callback(receiver_, cbData.data);
}
}
}
private:
struct CallbackData {
OH_ImageReceiver_ImageArriveCallback callback;
void* data;
CallbackData(OH_ImageReceiver_ImageArriveCallback cb, void* d) : callback(cb), data(d) {}
};
OH_ImageReceiverNative* receiver_ = nullptr;
std::vector<CallbackData> callbacks_;
mutable std::mutex mutex_;
};
struct ImageReceiverOptions {
int32_t width = 0;
int32_t height = 0;
int32_t capacity = 0;
int32_t format = 0;
};
class ImageReceiver {
public:
std::shared_ptr<ImageReceiverContext> iraContext_ = nullptr;
sptr<IConsumerSurface> receiverConsumerSurface_ = nullptr;
sptr<Surface> receiverProducerSurface_ = nullptr;
std::mutex imageReceiverMutex_;
std::shared_ptr<SurfaceBufferAvaliableListener> surfaceBufferAvaliableListener_ = nullptr;
std::shared_ptr<ImageReceiverArriveListener> surfaceBufferAvaliableArriveListener_ = nullptr;
ImageReceiver() {}
~ImageReceiver();
static inline int32_t pipeFd[2] = {};
static inline std::string OPTION_FORMAT = "image/jpeg";
static inline std::int32_t OPTION_QUALITY = 100;
static inline std::int32_t OPTION_NUMBERHINT = 1;
static std::shared_ptr<ImageReceiver> CreateImageReceiver(int32_t width,
int32_t height,
int32_t format,
int32_t capacity);
static std::shared_ptr<ImageReceiver> CreateImageReceiver(ImageReceiverOptions &options);
sptr<Surface> GetReceiverSurface();
OHOS::sptr<OHOS::SurfaceBuffer> ReadNextImage();
OHOS::sptr<OHOS::SurfaceBuffer> ReadLastImage();
OHOS::sptr<OHOS::SurfaceBuffer> ReadNextImage(int64_t ×tamp);
OHOS::sptr<OHOS::SurfaceBuffer> ReadLastImage(int64_t ×tamp);
int32_t SaveBufferAsImage(int &fd,
OHOS::sptr<OHOS::SurfaceBuffer> buffer,
InitializationOptions initializationOpts);
int32_t SaveBufferAsImage(int &fd, InitializationOptions initializationOpts);
void ReleaseBuffer(OHOS::sptr<OHOS::SurfaceBuffer> &buffer);
std::unique_ptr<PixelMap> getSurfacePixelMap(InitializationOptions initializationOpts);
void RegisterBufferAvaliableListener(
std::shared_ptr<SurfaceBufferAvaliableListener> surfaceBufferAvaliableListener)
{
surfaceBufferAvaliableListener_ = surfaceBufferAvaliableListener;
}
void UnRegisterBufferAvaliableListener()
{
surfaceBufferAvaliableListener_.reset();
}
static sptr<Surface> getSurfaceById(std::string id);
std::shared_ptr<IBufferProcessor> GetBufferProcessor();
std::shared_ptr<NativeImage> NextNativeImage();
std::shared_ptr<NativeImage> LastNativeImage();
private:
std::shared_ptr<IBufferProcessor> bufferProcessor_;
int32_t SaveBufferAsImageInner(int &fd, OHOS::sptr<OHOS::SurfaceBuffer> buffer,
InitializationOptions initializationOpts);
};
class ImageReceiverSurfaceListener : public IBufferConsumerListener {
public:
std::weak_ptr<ImageReceiver> ir_;
void OnBufferAvailable() override;
};
}
}
#endif