• 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 = 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