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 HDF_LOGI("Input Data length Not Enough");
59 return false;
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 size -= pixelInfo.alignedWidth * BYTES_PER_PIXEL_RBGA * pixelInfo.displayHeight;
68 return (ret == EOK);
69 }
70
CreateImgBuffer(uint8_t * data,size_t & size)71 sptr<NativeBuffer> EncodeBufferHelper::CreateImgBuffer(uint8_t* data, size_t &size)
72 {
73 PixelFileInfo pixelInfo;
74 uint8_t* dataEnd = data + size -1;
75 if (dataEnd < data + sizeof(pixelInfo.displayWidth)) {
76 return nullptr;
77 }
78 static constexpr int SHIFT_CNT = 22;
79 pixelInfo.displayWidth = (ToUint32(data) >> SHIFT_CNT); //Max 1024
80 pixelInfo.alignedWidth = pixelInfo.displayWidth;
81 data += sizeof(pixelInfo.displayWidth);
82 size -= sizeof(pixelInfo.displayWidth);
83
84 if (dataEnd < data + sizeof(pixelInfo.displayHeight)) {
85 return nullptr;
86 }
87 pixelInfo.displayHeight = (ToUint32(data) >> SHIFT_CNT);
88 pixelInfo.alignedHeight = pixelInfo.displayHeight;
89 data += sizeof(pixelInfo.displayHeight);
90 size -= sizeof(pixelInfo.displayHeight);
91
92 pixelInfo.pixFmt = OHOS::HDI::Display::Composer::V1_2::PIXEL_FMT_RGBA_8888;
93 uint64_t usage = OHOS::HDI::Display::Composer::V1_2::HBM_USE_CPU_READ |
94 OHOS::HDI::Display::Composer::V1_2::HBM_USE_CPU_WRITE |
95 OHOS::HDI::Display::Composer::V1_2::HBM_USE_MEM_DMA;
96 AllocInfo alloc = {
97 .width = pixelInfo.displayWidth,
98 .height = pixelInfo.displayHeight,
99 .usage = usage,
100 .format = pixelInfo.pixFmt
101 };
102
103 BufferHandle *handle = nullptr;
104 int32_t ret = bufferMgr_->AllocMem(alloc, handle);
105 IF_TRUE_RETURN_VAL_WITH_MSG(ret != HDF_SUCCESS, nullptr,
106 "failed to alloc output buffer, err [%{public}d] !", ret);
107 sptr<NativeBuffer> imgBuffer = new NativeBuffer();
108 imgBuffer->SetBufferHandle(handle, true);
109 bufferMgr_->Mmap(*handle);
110
111 HDF_LOGI("Fill Image RGB Data");
112 bool flag = InitialRgbaData(handle, pixelInfo, data, size);
113
114 (void)bufferMgr_->Unmap(*handle);
115 if (!flag) {
116 return nullptr;
117 }
118 HDF_LOGI("Fill Image RGB Data Succesfully");
119 return imgBuffer;
120 }
121
CreateSharedBuffer(uint8_t * data,size_t & size)122 SharedBuffer EncodeBufferHelper::CreateSharedBuffer(uint8_t* data, size_t &size)
123 {
124 SharedBuffer buffer = {
125 .fd = -1,
126 .filledLen = 0,
127 .capacity = 0
128 };
129
130 uint8_t* dataEnd = data + size - 1;
131 if (dataEnd < data + sizeof(uint8_t)) {
132 return buffer;
133 }
134 uint8_t totalSize = *data;
135 data += sizeof(totalSize);
136 size -= sizeof(totalSize);
137 int fd = AshmemCreate("ForMetaData", (size_t)totalSize);
138 IF_TRUE_RETURN_VAL_WITH_MSG(fd < 0, buffer, "cannot create ashmem for meta data");
139 void *addr = mmap(nullptr, (size_t)totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
140 if (addr == nullptr) {
141 HDF_LOGE("failed to map addr for meta buffer");
142 close(fd);
143 return buffer;
144 }
145 if (dataEnd < data + totalSize) {
146 close(fd);
147 return buffer;
148 }
149 errno_t ret = EOK;
150 ret = memcpy_s(reinterpret_cast<char*>(addr), totalSize, data, totalSize);
151 if (ret != EOK) {
152 close(fd);
153 return buffer;
154 }
155 data += totalSize;
156 size -= totalSize;
157 if (munmap(addr, totalSize) != 0) {
158 HDF_LOGW("failed to unmap addr for meta buffer");
159 }
160 buffer.fd = fd;
161 buffer.filledLen = static_cast<uint32_t>(totalSize);
162 buffer.capacity = static_cast<uint32_t>(AshmemGetSize(fd));
163 allocatedFd_.insert(fd);
164 return buffer;
165 }
166 }