• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }