• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = 40 * 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 + sizeof(Media::ImageInfo)), nullptr,
53         "innerPixelMap has no imageInfo");
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 
69     memset_s(&imageInfo, sizeof(Media::ImageInfo), 0, sizeof(Media::ImageInfo));
70     CHECK_AND_RETURN_RET_LOG(imgByteSizeInner == imgByteSizeExist, nullptr, "imageInfo size error!");
71 
72     uint32_t dataSize = 0;
73     for (uint8_t i = 0; i < DATA_BYTE_SIZE; i++) {
74         uint32_t tmpValue = innerImgBuffer[IMAGE_BYTE_SIZE + imgBufferSize + i];
75         dataSize += (tmpValue << (OFFSET_BYTE * (DATA_BYTE_SIZE - i - 1)));
76     }
77     CHECK_AND_RETURN_RET_LOG(dataSize == imgByteSizeExist, nullptr, "dataSize error");
78     void* dataAddr = static_cast<void*>(innerImgBuffer.data() + IMAGE_BYTE_SIZE + imgBufferSize + DATA_BYTE_SIZE);
79     pixelMap->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
80     uint8_t imgTopicNumber = innerImgBuffer[innerImgSize / 2] + innerImgBuffer[innerImgSize / 2 + 1];
81     SLOGI("ConvertFromInner:%{public}u srcSize=[%{public}d, %{public}d}], dstSize=[%{public}d, %{public}d}].",
82         imgTopicNumber, pixelMap->GetWidth(), pixelMap->GetHeight(), originalWidth_, originalHeight_);
83     Media::InitializationOptions options;
84     options.alphaType = imageInfo.alphaType;
85     options.pixelFormat = imageInfo.pixelFormat;
86     options.size.width = originalWidth_;
87     options.size.height = originalHeight_;
88     options.editable = true;
89     auto result = Media::PixelMap::Create(*pixelMap, options);
90     return std::move(result);
91 }
92 
CopyPixMapToDst(Media::PixelMap & source,void * dstPixels,uint32_t bufferSize)93 bool AVSessionPixelMapAdapter::CopyPixMapToDst(Media::PixelMap &source, void* dstPixels, uint32_t bufferSize)
94 {
95     if (source.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
96         SLOGD("CopyPixMapToDst in dma");
97         ImageInfo imageInfo;
98         source.GetImageInfo(imageInfo);
99         for (int i = 0; i < imageInfo.size.height; ++i) {
100             if (memcpy_s(dstPixels, source.GetRowBytes(),
101                 source.GetPixels() + i * source.GetRowStride(), source.GetRowBytes()) != 0) {
102                 SLOGE("copy source memory size %{public}u fail", bufferSize);
103                 return false;
104             }
105             // Move the destination buffer pointer to the next row
106             dstPixels = reinterpret_cast<uint8_t *>(dstPixels) + source.GetRowBytes();
107         }
108     } else  {
109         SLOGI("CopyPixMapToDst in normal way with bufferSize %{public}u", bufferSize);
110         if (memcpy_s(dstPixels, bufferSize, source.GetPixels(), bufferSize) != 0) {
111             SLOGE("copy source memory size %{public}u fail", bufferSize);
112             return false;
113         }
114     }
115     return true;
116 }
117 
ConvertAndSetInnerImgBuffer(const std::shared_ptr<Media::PixelMap> & pixelMapTemp)118 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertAndSetInnerImgBuffer(
119     const std::shared_ptr<Media::PixelMap>& pixelMapTemp)
120 {
121     std::shared_ptr<AVSessionPixelMap> innerPixelMap = std::make_shared<AVSessionPixelMap>();
122     std::vector<uint8_t> imgBuffer;
123     Media::ImageInfo imageInfo;
124     pixelMapTemp->GetImageInfo(imageInfo);
125     const auto* buffer = reinterpret_cast<uint8_t*>(&imageInfo);
126     uint16_t imageInfoSize = static_cast<uint16_t>(sizeof(Media::ImageInfo));
127     uint32_t pixelDataSize = static_cast<uint32_t>(pixelMapTemp->GetByteCount());
128     size_t bufferSize = static_cast<size_t>(IMAGE_BYTE_SIZE + imageInfoSize + DATA_BYTE_SIZE + pixelDataSize);
129     imgBuffer.reserve(bufferSize);
130     imgBuffer.insert(imgBuffer.begin(), (imageInfoSize & 0xFF00) >> OFFSET_BYTE);
131     imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), (imageInfoSize & 0x00FF));
132     imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), buffer, buffer + imageInfoSize);
133     uint32_t computedValue = 0xFF000000;
134     for (uint8_t i = 0; i < DATA_BYTE_SIZE; i++) {
135         uint8_t tmpValue = ((pixelDataSize & computedValue) >> (OFFSET_BYTE * (DATA_BYTE_SIZE - i - 1)));
136         imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), tmpValue);
137         computedValue = computedValue >> OFFSET_BYTE;
138     }
139     SLOGI("insert with size: %{public}hu, %{public}u, %{public}d",
140         imageInfoSize, pixelDataSize, static_cast<int>(imgBuffer.size()));
141     imgBuffer.insert(imgBuffer.begin() + imgBuffer.size(), pixelMapTemp->GetPixels(),
142         pixelMapTemp->GetPixels() + pixelDataSize);
143     innerPixelMap->SetInnerImgBuffer(imgBuffer);
144     imgBuffer.clear();
145     return innerPixelMap;
146 }
147 
ConvertToInner(const std::shared_ptr<Media::PixelMap> & pixelMap)148 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertToInner(
149     const std::shared_ptr<Media::PixelMap>& pixelMap)
150 {
151     std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
152     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "invalid parameter");
153     originalPixelMapBytes_ = pixelMap->GetByteCount();
154     originalWidth_ = pixelMap->GetWidth();
155     originalHeight_ = pixelMap->GetHeight();
156     Media::ImageInfo imageInfoTemp;
157     pixelMap->GetImageInfo(imageInfoTemp);
158     const std::shared_ptr<Media::PixelMap>& pixelMapTemp = std::make_shared<Media::PixelMap>();
159     pixelMapTemp->SetImageInfo(imageInfoTemp);
160     uint32_t dataSize = static_cast<uint32_t>(originalPixelMapBytes_);
161     void* dataAddr = malloc(dataSize);
162     CHECK_AND_RETURN_RET_LOG(dataAddr != nullptr, nullptr, "create dataSize with null, return");
163 
164     if (!CopyPixMapToDst(*pixelMap, dataAddr, dataSize)) {
165         SLOGE("CopyPixMapToDst failed");
166         free(dataAddr);
167         return nullptr;
168     }
169     pixelMapTemp->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
170     if (originalPixelMapBytes_ > MAX_PIXEL_BUFFER_SIZE) {
171         int32_t originSize = originalPixelMapBytes_;
172         float scaleRatio = sqrt(static_cast<float>(MAX_PIXEL_BUFFER_SIZE) / static_cast<float>(originalPixelMapBytes_));
173         pixelMapTemp->scale(scaleRatio, scaleRatio);
174         originalPixelMapBytes_ = pixelMapTemp->GetByteCount();
175         SLOGI("imgBufferSize exceeds limited: %{public}d scaled to %{public}d", originSize, originalPixelMapBytes_);
176     }
177     std::shared_ptr<AVSessionPixelMap> innerPixelMap = ConvertAndSetInnerImgBuffer(pixelMapTemp);
178     free(dataAddr);
179     return innerPixelMap;
180 }
181 
ConvertToInnerWithLimitedSize(const std::shared_ptr<Media::PixelMap> & pixelMap)182 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertToInnerWithLimitedSize(
183     const std::shared_ptr<Media::PixelMap>& pixelMap)
184 {
185     std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
186     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "invalid parameter");
187     originalPixelMapBytes_ = pixelMap->GetByteCount();
188     originalWidth_ = pixelMap->GetWidth();
189     originalHeight_ = pixelMap->GetHeight();
190     Media::ImageInfo imageInfoTemp;
191     pixelMap->GetImageInfo(imageInfoTemp);
192     const std::shared_ptr<Media::PixelMap>& pixelMapTemp = std::make_shared<Media::PixelMap>();
193     pixelMapTemp->SetImageInfo(imageInfoTemp);
194     uint32_t dataSize = static_cast<uint32_t>(originalPixelMapBytes_);
195     void* dataAddr = malloc(dataSize);
196     CHECK_AND_RETURN_RET_LOG(dataAddr != nullptr, nullptr, "create dataSize with null, return");
197 
198     if (!CopyPixMapToDst(*pixelMap, dataAddr, dataSize)) {
199         SLOGE("CopyPixMapToDst failed");
200         free(dataAddr);
201         return nullptr;
202     }
203     pixelMapTemp->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
204     if (originalPixelMapBytes_ > LIMITED_PIXEL_BUFFER_SIZE) {
205         int32_t originSize = originalPixelMapBytes_;
206         float scaleRatio =
207             sqrt(static_cast<float>(LIMITED_PIXEL_BUFFER_SIZE) / static_cast<float>(originalPixelMapBytes_));
208         pixelMapTemp->scale(scaleRatio, scaleRatio);
209         originalPixelMapBytes_ = pixelMapTemp->GetByteCount();
210         SLOGI("imgBufferSize exceeds limited: %{public}d scaled to %{public}d", originSize, originalPixelMapBytes_);
211     }
212     std::shared_ptr<AVSessionPixelMap> innerPixelMap = ConvertAndSetInnerImgBuffer(pixelMapTemp);
213     free(dataAddr);
214     return innerPixelMap;
215 }
216 
ConvertToInnerWithMinSize(const std::shared_ptr<Media::PixelMap> & pixelMap)217 std::shared_ptr<AVSessionPixelMap> AVSessionPixelMapAdapter::ConvertToInnerWithMinSize(
218     const std::shared_ptr<Media::PixelMap>& pixelMap)
219 {
220     std::lock_guard<std::mutex> lockGuard(pixelMapLock_);
221     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "invalid parameter");
222     originalPixelMapBytes_ = pixelMap->GetByteCount();
223     originalWidth_ = pixelMap->GetWidth();
224     originalHeight_ = pixelMap->GetHeight();
225     Media::ImageInfo imageInfoTemp;
226     pixelMap->GetImageInfo(imageInfoTemp);
227     const std::shared_ptr<Media::PixelMap>& pixelMapTemp = std::make_shared<Media::PixelMap>();
228     pixelMapTemp->SetImageInfo(imageInfoTemp);
229     uint32_t dataSize = static_cast<uint32_t>(originalPixelMapBytes_);
230     void* dataAddr = malloc(dataSize);
231     CHECK_AND_RETURN_RET_LOG(dataAddr != nullptr, nullptr, "create dataSize with null, return");
232 
233     if (!CopyPixMapToDst(*pixelMap, dataAddr, dataSize)) {
234         SLOGE("CopyPixMapToDst failed");
235         free(dataAddr);
236         return nullptr;
237     }
238     pixelMapTemp->SetPixelsAddr(dataAddr, nullptr, dataSize, Media::AllocatorType::CUSTOM_ALLOC, nullptr);
239     if (originalPixelMapBytes_ > MIN_PIXEL_BUFFER_SIZE) {
240         int32_t originSize = originalPixelMapBytes_;
241         float scaleRatio =
242             sqrt(static_cast<float>(MIN_PIXEL_BUFFER_SIZE) / static_cast<float>(originalPixelMapBytes_));
243         pixelMapTemp->scale(scaleRatio, scaleRatio);
244         originalPixelMapBytes_ = pixelMapTemp->GetByteCount();
245         SLOGI("imgBufferSize exceeds limited: %{public}d scaled to %{public}d", originSize, originalPixelMapBytes_);
246     }
247     std::shared_ptr<AVSessionPixelMap> innerPixelMap = ConvertAndSetInnerImgBuffer(pixelMapTemp);
248     free(dataAddr);
249     return innerPixelMap;
250 }
251 } // namespace OHOS::AVSession