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 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 <sys/mman.h>
17 #include <securec.h>
18 #include "ashmem.h"
19 #include "encode_buffer_helper.h"
20
21 namespace OHOS::VDI::HEIF {
22 using namespace OHOS::HDI::Codec::Image::V2_0;
23 using namespace OHOS::HDI::Display::Buffer::V1_2;
24 using namespace OHOS::HDI::Display::Composer::V1_2;
25 using namespace std;
26
ToUint32(const uint8_t * ptr)27 uint32_t ToUint32(const uint8_t* ptr)
28 {
29 if (ptr == nullptr) {
30 return 0;
31 }
32 return (ptr[0] << 24) | (ptr[1] << 16) | // 24:bit offset, 16: bit offset, 1:byte offset
33 (ptr[2] << 8) | (ptr[3]); // 8:bit offset, 2: byte offset, 3:byte offset
34 }
35
EncodeBufferHelper()36 EncodeBufferHelper::EncodeBufferHelper()
37 {
38 bufferMgr_ = OHOS::HDI::Display::Buffer::V1_2::IDisplayBuffer::Get();
39 }
40
~EncodeBufferHelper()41 EncodeBufferHelper::~EncodeBufferHelper()
42 {
43 bufferMgr_ = nullptr;
44 for (auto iter = allocatedFd_.begin(); iter != allocatedFd_.end(); ++iter) {
45 close(*iter);
46 }
47 allocatedFd_.clear();
48 }
49
50
InitialRgbaData(BufferHandle * handle,PixelFileInfo & pixelInfo,uint8_t * data,size_t size)51 bool EncodeBufferHelper::InitialRgbaData(BufferHandle* handle, PixelFileInfo& pixelInfo, uint8_t* data, size_t size)
52 {
53 char* dst = reinterpret_cast<char*>(handle->virAddr);
54 static constexpr uint32_t BYTES_PER_PIXEL_RBGA = 4;
55 errno_t ret = EOK;
56 uint8_t* dataEnd = data + size -1;
57 if (dataEnd < data + pixelInfo.alignedWidth * BYTES_PER_PIXEL_RBGA * pixelInfo.displayHeight) {
58 return false;
59 HDF_LOGI("Input Data length Not Enough");
60 }
61 for (uint32_t i = 0; i < pixelInfo.displayHeight; i++) {
62 ret = memcpy_s(dst, pixelInfo.alignedWidth * BYTES_PER_PIXEL_RBGA, data,
63 pixelInfo.alignedWidth * BYTES_PER_PIXEL_RBGA);
64 dst += handle->stride;
65 }
66 data += pixelInfo.alignedWidth * BYTES_PER_PIXEL_RBGA * pixelInfo.displayHeight;
67 return (ret == EOK);
68 }
69
CreateImgBuffer(uint8_t * data,size_t size)70 sptr<NativeBuffer> EncodeBufferHelper::CreateImgBuffer(uint8_t* data, size_t size)
71 {
72 PixelFileInfo pixelInfo;
73 uint8_t* dataEnd = data + size -1;
74 if (dataEnd < data + sizeof(pixelInfo.displayWidth)) {
75 return nullptr;
76 }
77 static constexpr int SHIFT_CNT = 22;
78 pixelInfo.displayWidth = (ToUint32(data) >> SHIFT_CNT); //Max 1024
79 pixelInfo.alignedWidth = pixelInfo.displayWidth;
80 data += sizeof(pixelInfo.displayWidth);
81
82 if (dataEnd < data + sizeof(pixelInfo.displayHeight)) {
83 return nullptr;
84 }
85 pixelInfo.displayHeight = (ToUint32(data) >> SHIFT_CNT);
86 pixelInfo.alignedHeight = pixelInfo.displayHeight;
87 data += sizeof(pixelInfo.displayHeight);
88
89 pixelInfo.pixFmt = OHOS::HDI::Display::Composer::V1_2::PIXEL_FMT_RGBA_8888;
90 uint64_t usage = OHOS::HDI::Display::Composer::V1_2::HBM_USE_CPU_READ |
91 OHOS::HDI::Display::Composer::V1_2::HBM_USE_CPU_WRITE |
92 OHOS::HDI::Display::Composer::V1_2::HBM_USE_MEM_DMA;
93 AllocInfo alloc = {
94 .width = pixelInfo.displayWidth,
95 .height = pixelInfo.displayHeight,
96 .usage = usage,
97 .format = pixelInfo.pixFmt
98 };
99
100 BufferHandle *handle = nullptr;
101 int32_t ret = bufferMgr_->AllocMem(alloc, handle);
102 IF_TRUE_RETURN_VAL_WITH_MSG(ret != HDF_SUCCESS, nullptr,
103 "failed to alloc output buffer, err [%{public}d] !", ret);
104 bufferMgr_->Mmap(*handle);
105
106 HDF_LOGI("Fill Image RGB Data");
107 bool flag = InitialRgbaData(handle, pixelInfo, data, size);
108
109 (void)bufferMgr_->Unmap(*handle);
110 if (!flag) {
111 bufferMgr_->FreeMem(*handle);
112 return nullptr;
113 }
114 HDF_LOGI("Fill Image RGB Data Succesfully");
115 sptr<NativeBuffer> imgBuffer = new NativeBuffer(handle);
116 return imgBuffer;
117 }
118
CreateSharedBuffer(uint8_t * data,size_t size)119 SharedBuffer EncodeBufferHelper::CreateSharedBuffer(uint8_t* data, size_t size)
120 {
121 SharedBuffer buffer = {
122 .fd = -1,
123 .filledLen = 0,
124 .capacity = 0
125 };
126
127 uint8_t* dataEnd = data + size - 1;
128 if (dataEnd < data + sizeof(uint8_t)) {
129 return buffer;
130 }
131 uint8_t totalSize = *data;
132 data += sizeof(totalSize);
133 int fd = AshmemCreate("ForMetaData", (size_t)totalSize);
134 IF_TRUE_RETURN_VAL_WITH_MSG(fd < 0, buffer, "cannot create ashmem for meta data");
135 void *addr = mmap(nullptr, (size_t)totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
136 if (addr == nullptr) {
137 HDF_LOGE("failed to map addr for meta buffer");
138 close(fd);
139 return buffer;
140 }
141 if (dataEnd < data + totalSize) {
142 return buffer;
143 }
144 errno_t ret = EOK;
145 ret = memcpy_s(reinterpret_cast<char*>(addr), totalSize, data, totalSize);
146 if (ret != EOK) {
147 return buffer;
148 }
149 data += totalSize;
150 if (munmap(addr, totalSize) != 0) {
151 HDF_LOGW("failed to unmap addr for meta buffer");
152 }
153 buffer.fd = fd;
154 buffer.filledLen = static_cast<uint32_t>(totalSize);
155 buffer.capacity = static_cast<uint32_t>(AshmemGetSize(fd));
156 allocatedFd_.insert(fd);
157 return buffer;
158 }
159 }