1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hardware/imagecodec/image_codec_buffer.h"
17 #include "hardware/imagecodec/image_codec_log.h"
18 #include "sys/mman.h"
19 #include "ashmem.h" // commonlibrary/c_utils/base/include/ashmem.h
20
21 namespace OHOS::ImagePlugin {
22 using namespace std;
23
24 /*============================ ImageCodecBuffer ====================================*/
CreateDmaBuffer(int fd,int32_t capacity,int32_t stride)25 std::shared_ptr<ImageCodecBuffer> ImageCodecBuffer::CreateDmaBuffer(int fd, int32_t capacity, int32_t stride)
26 {
27 if (fd < 0 || capacity <= 0) {
28 LOGE("invalid input param: fd=%{public}d, capacity=%{public}d", fd, capacity);
29 return nullptr;
30 }
31 return make_shared<ImageDmaBuffer>(dup(fd), capacity, stride);
32 }
33
CreateSurfaceBuffer(const BufferRequestConfig & config)34 std::shared_ptr<ImageCodecBuffer> ImageCodecBuffer::CreateSurfaceBuffer(const BufferRequestConfig &config)
35 {
36 std::shared_ptr<ImageCodecBuffer> buf = make_shared<ImageSurfaceBuffer>(config);
37 if (buf != nullptr && buf->Init()) {
38 return buf;
39 }
40 return nullptr;
41 }
42
CreateSurfaceBuffer(sptr<SurfaceBuffer> surface)43 std::shared_ptr<ImageCodecBuffer> ImageCodecBuffer::CreateSurfaceBuffer(sptr<SurfaceBuffer> surface)
44 {
45 std::shared_ptr<ImageCodecBuffer> buf = make_shared<ImageSurfaceBuffer>(surface);
46 return buf;
47 }
48
49 /*============================ ImageDmaBuffer ====================================*/
ImageDmaBuffer(int fd,int32_t capacity,int32_t stride)50 ImageDmaBuffer::ImageDmaBuffer(int fd, int32_t capacity, int32_t stride): fd_(fd)
51 {
52 capacity_ = capacity;
53 stride_ = stride;
54 }
55
~ImageDmaBuffer()56 ImageDmaBuffer::~ImageDmaBuffer()
57 {
58 if (addr_ != nullptr) {
59 (void)::munmap(addr_, static_cast<size_t>(capacity_));
60 addr_ = nullptr;
61 }
62
63 if (fd_ >= 0) {
64 close(fd_);
65 fd_ = -1;
66 }
67 }
68
GetAddr()69 uint8_t* ImageDmaBuffer::GetAddr()
70 {
71 if (addr_ == nullptr) {
72 IF_TRUE_RETURN_VAL_WITH_MSG(fd_ < 0, nullptr, "invalid fd=%{public}d", fd_);
73 unsigned int prot = PROT_READ | PROT_WRITE;
74 void *addr = ::mmap(nullptr, static_cast<size_t>(capacity_), static_cast<int>(prot), MAP_SHARED, fd_, 0);
75 IF_TRUE_RETURN_VAL_WITH_MSG(addr == MAP_FAILED, nullptr, "mmap failed for fd=%{public}d", fd_);
76 addr_ = reinterpret_cast<uint8_t*>(addr);
77 }
78 return addr_;
79 }
80
81 /*============================ ImageSurfaceBuffer ====================================*/
ImageSurfaceBuffer(const BufferRequestConfig & config)82 ImageSurfaceBuffer::ImageSurfaceBuffer(const BufferRequestConfig &config): config_(config)
83 {}
84
ImageSurfaceBuffer(sptr<SurfaceBuffer> surface)85 ImageSurfaceBuffer::ImageSurfaceBuffer(sptr<SurfaceBuffer> surface)
86 {
87 surfaceBuffer_ = surface;
88 stride_ = surfaceBuffer_->GetStride();
89 }
90
~ImageSurfaceBuffer()91 ImageSurfaceBuffer::~ImageSurfaceBuffer()
92 {
93 if (addr_ != nullptr) {
94 GSError ret = surfaceBuffer_->Unmap();
95 if (ret != GSERROR_OK) {
96 LOGE("failed to unmap surface buffer");
97 }
98 addr_ = nullptr;
99 }
100 }
101
Init()102 bool ImageSurfaceBuffer::Init()
103 {
104 surfaceBuffer_ = SurfaceBuffer::Create();
105 IF_TRUE_RETURN_VAL_WITH_MSG(surfaceBuffer_ == nullptr, false, "failed to create surface buffer");
106 GSError ret = surfaceBuffer_->Alloc(config_);
107 IF_TRUE_RETURN_VAL_WITH_MSG(ret != GSERROR_OK, false, "failed to alloc surface buffer");
108 capacity_ = static_cast<int32_t>(surfaceBuffer_->GetSize());
109 stride_ = surfaceBuffer_->GetStride();
110 return true;
111 }
112
GetFileDescriptor()113 int32_t ImageSurfaceBuffer::GetFileDescriptor()
114 {
115 return surfaceBuffer_->GetFileDescriptor();
116 }
117
GetAddr()118 uint8_t* ImageSurfaceBuffer::GetAddr()
119 {
120 if (addr_ == nullptr) {
121 GSError ret = surfaceBuffer_->Map();
122 IF_TRUE_RETURN_VAL_WITH_MSG(ret != GSERROR_OK, nullptr,
123 "mmap failed, err=%{public}s", GSErrorStr(ret).c_str());
124 addr_ = reinterpret_cast<uint8_t*>(surfaceBuffer_->GetVirAddr());
125 if (surfaceBuffer_->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE) {
126 ret = surfaceBuffer_->InvalidateCache();
127 if (ret != GSERROR_OK) {
128 LOGW("InvalidateCache failed, GSError=%{public}d", ret);
129 }
130 }
131 }
132 return addr_;
133 }
134
GetSurfaceBuffer()135 sptr<SurfaceBuffer> ImageSurfaceBuffer::GetSurfaceBuffer()
136 {
137 return surfaceBuffer_;
138 }
139 } // namespace OHOS::ImagePlugin