1 /*
2 * Copyright (c) 2022-2023 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 "avsession_pixel_map_adapter.h"
17 #include "avsession_log.h"
18 #include "securec.h"
19
20 using namespace OHOS::Media;
21
22 namespace OHOS::AVSession {
23 namespace {
24 constexpr int32_t MAX_PIXEL_BUFFER_SIZE = 1 * 1024 * 1024;
25 constexpr int32_t LIMITED_PIXEL_BUFFER_SIZE = 500 * 1024; // ipc max 1m at the same time
26 constexpr int32_t MIN_PIXEL_BUFFER_SIZE = 100 * 1024;
27 constexpr uint8_t IMAGE_BYTE_SIZE = 2;
28 constexpr uint8_t DATA_BYTE_SIZE = 4;
29 constexpr uint8_t OFFSET_BYTE = 8;
30 }
31
32 int32_t AVSessionPixelMapAdapter::originalPixelMapBytes_ = 0;
33 int32_t AVSessionPixelMapAdapter::originalWidth_ = 0;
34 int32_t AVSessionPixelMapAdapter::originalHeight_ = 0;
35 std::mutex AVSessionPixelMapAdapter::pixelMapLock_;
36
CleanAVSessionPixelMap(std::shared_ptr<AVSessionPixelMap> & innerPixelMap)37 void AVSessionPixelMapAdapter::CleanAVSessionPixelMap(std::shared_ptr<AVSessionPixelMap>& innerPixelMap)
38 {
39 std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
40 if (innerPixelMap != nullptr) {
41 innerPixelMap->Clear();
42 }
43 }
44
ConvertFromInner(const std::shared_ptr<AVSessionPixelMap> & innerPixelMap)45 std::shared_ptr<Media::PixelMap> AVSessionPixelMapAdapter::ConvertFromInner(
46 const std::shared_ptr<AVSessionPixelMap>& innerPixelMap)
47 {
48 std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
49 CHECK_AND_RETURN_RET_LOG(innerPixelMap != nullptr, nullptr, "invalid parameter");
50 std::vector<uint8_t> innerImgBuffer = innerPixelMap->GetInnerImgBuffer();
51 int32_t innerImgSize = static_cast<int>(innerImgBuffer.size());
52 CHECK_AND_RETURN_RET_LOG(innerImgSize > IMAGE_BYTE_SIZE, nullptr,
53 "innerPixelMap innerImgBuffer size less than 2");
54 uint16_t imgBufferSize = static_cast<uint16_t>(innerImgBuffer[0]);
55 imgBufferSize = (imgBufferSize << OFFSET_BYTE) + innerImgBuffer[1];
56 CHECK_AND_RETURN_RET_LOG(imgBufferSize == sizeof(Media::ImageInfo), nullptr,
57 "imgBufferSize not equal to %{public}zu", sizeof(Media::ImageInfo));
58
59 Media::ImageInfo imageInfo;
60 std::copy(innerImgBuffer.data() + IMAGE_BYTE_SIZE,
61 innerImgBuffer.data() + IMAGE_BYTE_SIZE + imgBufferSize, reinterpret_cast<uint8_t*>(&imageInfo));
62
63 const std::shared_ptr<Media::PixelMap>& pixelMap = std::make_shared<Media::PixelMap>();
64 pixelMap->SetImageInfo(imageInfo);
65
66 uint32_t imgByteSizeExist = innerImgBuffer.size() - IMAGE_BYTE_SIZE - imgBufferSize - DATA_BYTE_SIZE;
67 uint32_t imgByteSizeInner = static_cast<uint32_t>(pixelMap->GetByteCount());
68 CHECK_AND_RETURN_RET_LOG(imgByteSizeInner == imgByteSizeExist, nullptr, "imageInfo size error");
69
70 uint32_t dataSize = 0;
71 for (uint8_t i = 0; i < DATA_BYTE_SIZE; i++) {
72 uint32_t tmpValue = innerImgBuffer[IMAGE_BYTE_SIZE + imgBufferSize + i];
73 dataSize += (tmpValue << (OFFSET_BYTE * (DATA_BYTE_SIZE - i - 1)));
74 }
75 CHECK_AND_RETURN_RET_LOG(dataSize == imgByteSizeExist, nullptr, "dataSize error");
76 void* dataAddr = static_cast<void*>(innerImgBuffer.data() + IMAGE_BYTE_SIZE + imgBufferSize + DATA_BYTE_SIZE);
77 pixelMap->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
78 uint8_t imgTopicNumber = innerImgBuffer[innerImgSize / 2] + innerImgBuffer[innerImgSize / 2 + 1];
79 SLOGI("ConvertFromInner:%{public}u srcSize=[%{public}d, %{public}d}], dstSize=[%{public}d, %{public}d}]",
80 imgTopicNumber, pixelMap->GetWidth(), pixelMap->GetHeight(), originalWidth_, originalHeight_);
81 Media::InitializationOptions options;
82 options.alphaType = imageInfo.alphaType;
83 options.pixelFormat = imageInfo.pixelFormat;
84 options.size.width = originalWidth_;
85 options.size.height = originalHeight_;
86 options.editable = true;
87 auto result = Media::PixelMap::Create(*pixelMap, options);
88 return std::move(result);
89 }
90
CopyPixMapToDst(Media::PixelMap & source,void * dstPixels,uint32_t bufferSize)91 bool AVSessionPixelMapAdapter::CopyPixMapToDst(Media::PixelMap &source, void* dstPixels, uint32_t bufferSize)
92 {
93 if (source.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
94 SLOGD("CopyPixMapToDst in dma");
95 ImageInfo imageInfo;
96 source.GetImageInfo(imageInfo);
97 for (int i = 0; i < imageInfo.size.height; ++i) {
98 if (memcpy_s(dstPixels, source.GetRowBytes(),
99 source.GetPixels() + i * source.GetRowStride(), source.GetRowBytes()) != 0) {
100 SLOGE("copy source memory size %{public}u fail", bufferSize);
101 return false;
102 }
103 // Move the destination buffer pointer to the next row
104 dstPixels = reinterpret_cast<uint8_t *>(dstPixels) + source.GetRowBytes();
105 }
106 } else {
107 SLOGI("CopyPixMapToDst in normal way with bufferSize %{public}u", bufferSize);
108 if (memcpy_s(dstPixels, bufferSize, source.GetPixels(), bufferSize) != 0) {
109 SLOGE("copy source memory size %{public}u fail", bufferSize);
110 return false;
111 }
112 }
113 return true;
114 }
115
ConvertAndSetInnerImgBuffer(const std::shared_ptr<Media::PixelMap> & pixelMapTemp)116 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertAndSetInnerImgBuffer(
117 const std::shared_ptr<Media::PixelMap>& pixelMapTemp)
118 {
119 std::shared_ptr<AVSessionPixelMap> innerPixelMap = std::make_shared<AVSessionPixelMap>();
120 std::vector<uint8_t> imgBuffer;
121 Media::ImageInfo imageInfo;
122 pixelMapTemp->GetImageInfo(imageInfo);
123 const auto* buffer = reinterpret_cast<uint8_t*>(&imageInfo);
124 uint16_t imageInfoSize = static_cast<uint16_t>(sizeof(Media::ImageInfo));
125 uint32_t pixelDataSize = static_cast<uint32_t>(pixelMapTemp->GetByteCount());
126 size_t bufferSize = static_cast<size_t>(IMAGE_BYTE_SIZE + imageInfoSize + DATA_BYTE_SIZE + pixelDataSize);
127 imgBuffer.reserve(bufferSize);
128 imgBuffer.insert(imgBuffer.begin(), (imageInfoSize & 0xFF00) >> OFFSET_BYTE);
129 imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), (imageInfoSize & 0x00FF));
130 imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), buffer, buffer + imageInfoSize);
131 uint32_t computedValue = 0xFF000000;
132 for (uint8_t i = 0; i < DATA_BYTE_SIZE; i++) {
133 uint8_t tmpValue = ((pixelDataSize & computedValue) >> (OFFSET_BYTE * (DATA_BYTE_SIZE - i - 1)));
134 imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), tmpValue);
135 computedValue = computedValue >> OFFSET_BYTE;
136 }
137 SLOGI("insert with size: %{public}hu, %{public}u, %{public}d",
138 imageInfoSize, pixelDataSize, static_cast<int>(imgBuffer.size()));
139 imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), pixelMapTemp->GetPixels(),
140 pixelMapTemp->GetPixels() + pixelDataSize);
141 innerPixelMap->SetInnerImgBuffer(imgBuffer);
142 imgBuffer.clear();
143 return innerPixelMap;
144 }
145
ConvertToInner(const std::shared_ptr<Media::PixelMap> & pixelMap)146 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertToInner(
147 const std::shared_ptr<Media::PixelMap>& pixelMap)
148 {
149 std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
150 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "invalid parameter");
151 originalPixelMapBytes_ = pixelMap->GetByteCount();
152 originalWidth_ = pixelMap->GetWidth();
153 originalHeight_ = pixelMap->GetHeight();
154 Media::ImageInfo imageInfoTemp;
155 pixelMap->GetImageInfo(imageInfoTemp);
156 const std::shared_ptr<Media::PixelMap>& pixelMapTemp = std::make_shared<Media::PixelMap>();
157 pixelMapTemp->SetImageInfo(imageInfoTemp);
158 uint32_t dataSize = static_cast<uint32_t>(originalPixelMapBytes_);
159 void* dataAddr = malloc(dataSize);
160 CHECK_AND_RETURN_RET_LOG(dataAddr != nullptr, nullptr, "create dataSize with null, return");
161
162 if (!CopyPixMapToDst(*pixelMap, dataAddr, dataSize)) {
163 SLOGE("CopyPixMapToDst failed");
164 free(dataAddr);
165 return nullptr;
166 }
167 pixelMapTemp->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
168 if (originalPixelMapBytes_ > MAX_PIXEL_BUFFER_SIZE) {
169 int32_t originSize = originalPixelMapBytes_;
170 float scaleRatio = sqrt(static_cast<float>(MAX_PIXEL_BUFFER_SIZE) / static_cast<float>(originalPixelMapBytes_));
171 pixelMapTemp->scale(scaleRatio, scaleRatio);
172 originalPixelMapBytes_ = pixelMapTemp->GetByteCount();
173 SLOGI("imgBufferSize exceeds limited: %{public}d scaled to %{public}d", originSize, originalPixelMapBytes_);
174 }
175 std::shared_ptr<AVSessionPixelMap> innerPixelMap = ConvertAndSetInnerImgBuffer(pixelMapTemp);
176 free(dataAddr);
177 return innerPixelMap;
178 }
179
ConvertToInnerWithLimitedSize(const std::shared_ptr<Media::PixelMap> & pixelMap)180 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertToInnerWithLimitedSize(
181 const std::shared_ptr<Media::PixelMap>& pixelMap)
182 {
183 std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
184 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "invalid parameter");
185 originalPixelMapBytes_ = pixelMap->GetByteCount();
186 originalWidth_ = pixelMap->GetWidth();
187 originalHeight_ = pixelMap->GetHeight();
188 Media::ImageInfo imageInfoTemp;
189 pixelMap->GetImageInfo(imageInfoTemp);
190 const std::shared_ptr<Media::PixelMap>& pixelMapTemp = std::make_shared<Media::PixelMap>();
191 pixelMapTemp->SetImageInfo(imageInfoTemp);
192 uint32_t dataSize = static_cast<uint32_t>(originalPixelMapBytes_);
193 void* dataAddr = malloc(dataSize);
194 CHECK_AND_RETURN_RET_LOG(dataAddr != nullptr, nullptr, "create dataSize with null, return");
195
196 if (!CopyPixMapToDst(*pixelMap, dataAddr, dataSize)) {
197 SLOGE("CopyPixMapToDst failed");
198 free(dataAddr);
199 return nullptr;
200 }
201 pixelMapTemp->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
202 if (originalPixelMapBytes_ > LIMITED_PIXEL_BUFFER_SIZE) {
203 int32_t originSize = originalPixelMapBytes_;
204 float scaleRatio =
205 sqrt(static_cast<float>(LIMITED_PIXEL_BUFFER_SIZE) / static_cast<float>(originalPixelMapBytes_));
206 pixelMapTemp->scale(scaleRatio, scaleRatio);
207 originalPixelMapBytes_ = pixelMapTemp->GetByteCount();
208 SLOGI("imgBufferSize exceeds limited: %{public}d scaled to %{public}d", originSize, originalPixelMapBytes_);
209 }
210 std::shared_ptr<AVSessionPixelMap> innerPixelMap = ConvertAndSetInnerImgBuffer(pixelMapTemp);
211 free(dataAddr);
212 return innerPixelMap;
213 }
214
ConvertToInnerWithMinSize(const std::shared_ptr<Media::PixelMap> & pixelMap)215 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertToInnerWithMinSize(
216 const std::shared_ptr<Media::PixelMap>& pixelMap)
217 {
218 std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
219 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "invalid parameter");
220 originalPixelMapBytes_ = pixelMap->GetByteCount();
221 originalWidth_ = pixelMap->GetWidth();
222 originalHeight_ = pixelMap->GetHeight();
223 Media::ImageInfo imageInfoTemp;
224 pixelMap->GetImageInfo(imageInfoTemp);
225 const std::shared_ptr<Media::PixelMap>& pixelMapTemp = std::make_shared<Media::PixelMap>();
226 pixelMapTemp->SetImageInfo(imageInfoTemp);
227 uint32_t dataSize = static_cast<uint32_t>(originalPixelMapBytes_);
228 void* dataAddr = malloc(dataSize);
229 CHECK_AND_RETURN_RET_LOG(dataAddr != nullptr, nullptr, "create dataSize with null, return");
230
231 if (!CopyPixMapToDst(*pixelMap, dataAddr, dataSize)) {
232 SLOGE("CopyPixMapToDst failed");
233 free(dataAddr);
234 return nullptr;
235 }
236 pixelMapTemp->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
237 if (originalPixelMapBytes_ > MIN_PIXEL_BUFFER_SIZE) {
238 int32_t originSize = originalPixelMapBytes_;
239 float scaleRatio =
240 sqrt(static_cast<float>(MIN_PIXEL_BUFFER_SIZE) / static_cast<float>(originalPixelMapBytes_));
241 pixelMapTemp->scale(scaleRatio, scaleRatio);
242 originalPixelMapBytes_ = pixelMapTemp->GetByteCount();
243 SLOGI("imgBufferSize exceeds limited: %{public}d scaled to %{public}d", originSize, originalPixelMapBytes_);
244 }
245 std::shared_ptr<AVSessionPixelMap> innerPixelMap = ConvertAndSetInnerImgBuffer(pixelMapTemp);
246 free(dataAddr);
247 return innerPixelMap;
248 }
249 } // namespace OHOS::AVSession