• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 <cinttypes>
17 #include "image_log.h"
18 #include "image_utils.h"
19 #include "media_errors.h"
20 #include "native_image.h"
21 
22 #undef LOG_DOMAIN
23 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
24 
25 #undef LOG_TAG
26 #define LOG_TAG "NativeImage"
27 
28 namespace {
29     constexpr int32_t NUMI_0 = 0;
30     constexpr uint32_t NUM_0 = 0;
31     constexpr uint32_t NUM_1 = 1;
32     constexpr uint32_t NUM_2 = 2;
33     const std::string DATA_SIZE_TAG = "dataSize";
34 }
35 
36 namespace OHOS {
37 namespace Media {
NativeImage(sptr<SurfaceBuffer> buffer,std::shared_ptr<IBufferProcessor> releaser)38 NativeImage::NativeImage(sptr<SurfaceBuffer> buffer,
39     std::shared_ptr<IBufferProcessor> releaser) : buffer_(buffer), releaser_(releaser), timestamp_(0)
40 {}
41 
NativeImage(sptr<SurfaceBuffer> buffer,std::shared_ptr<IBufferProcessor> releaser,int64_t timestamp)42 NativeImage::NativeImage(sptr<SurfaceBuffer> buffer, std::shared_ptr<IBufferProcessor> releaser,
43     int64_t timestamp) : buffer_(buffer), releaser_(releaser), timestamp_(timestamp)
44 {}
45 
46 struct YUVData {
47     std::vector<uint8_t> y;
48     std::vector<uint8_t> u;
49     std::vector<uint8_t> v;
50     uint64_t ySize;
51     uint64_t uvSize;
52 };
53 
DataSwap(uint8_t * a,uint8_t * b,bool flip)54 static inline void DataSwap(uint8_t* a, uint8_t* b, bool flip)
55 {
56     if (flip) {
57         *a = *b;
58     } else {
59         *b = *a;
60     }
61 }
62 
IsYUV422SPFormat(int32_t format)63 static inline bool IsYUV422SPFormat(int32_t format)
64 {
65     if (format == int32_t(ImageFormat::YCBCR_422_SP) ||
66         format == int32_t(GRAPHIC_PIXEL_FMT_YCBCR_422_SP)) {
67         return true;
68     }
69     return false;
70 }
71 
YUV422SPDataCopy(uint8_t * buffer,uint64_t size,YUVData & data,bool flip)72 static void YUV422SPDataCopy(uint8_t* buffer, uint64_t size, YUVData &data, bool flip)
73 {
74     uint64_t ui = NUM_0;
75     uint64_t vi = NUM_0;
76     for (uint64_t i = NUM_0; i < size; i++) {
77         if (i < data.ySize) {
78             DataSwap(&(buffer[i]), &(data.y[i]), flip);
79             continue;
80         }
81         if (vi >= data.uvSize || ui >= data.uvSize) {
82             // Over write buffer size.
83             continue;
84         }
85         if (i % NUM_2 == NUM_1) {
86             DataSwap(&(buffer[i]), &(data.v[vi]), flip);
87             vi++;
88         } else {
89             DataSwap(&(buffer[i]), &(data.u[ui]), flip);
90             ui++;
91         }
92     }
93 }
GetSurfaceBufferAddr()94 uint8_t* NativeImage::GetSurfaceBufferAddr()
95 {
96     if (buffer_ != nullptr) {
97         return static_cast<uint8_t*>(buffer_->GetVirAddr());
98     }
99     return nullptr;
100 }
SplitYUV422SPComponent()101 int32_t NativeImage::SplitYUV422SPComponent()
102 {
103     auto rawBuffer = GetSurfaceBufferAddr();
104     if (rawBuffer == nullptr) {
105         IMAGE_LOGE("SurfaceBuffer viraddr is nullptr");
106         return ERR_MEDIA_NULL_POINTER;
107     }
108 
109     uint64_t surfaceSize = NUM_0;
110     auto res = GetDataSize(surfaceSize);
111     if (res != SUCCESS || surfaceSize == NUM_0) {
112         IMAGE_LOGE("S size is 0");
113         return ERR_MEDIA_DATA_UNSUPPORT;
114     }
115 
116     int32_t width = NUM_0;
117     int32_t height = NUM_0;
118     res = GetSize(width, height);
119     if (res != SUCCESS || width <= NUMI_0 || height <= NUMI_0) {
120         IMAGE_LOGE("Invaild width %{public}" PRId32 " height %{public}" PRId32, width, height);
121         return ERR_MEDIA_DATA_UNSUPPORT;
122     }
123 
124     struct YUVData yuv;
125     uint64_t uvStride = static_cast<uint64_t>((width + NUM_1) / NUM_2);
126     if (ImageUtils::CheckMulOverflow(width, height)) {
127         IMAGE_LOGE("Invalid width %{public}" PRId32 " height %{public}" PRId32, width, height);
128         return ERR_MEDIA_DATA_UNSUPPORT;
129     }
130     yuv.ySize = static_cast<uint64_t>(width) * static_cast<uint64_t>(height);
131     yuv.uvSize = static_cast<uint64_t>(height) * uvStride;
132     if (surfaceSize < (yuv.ySize + yuv.uvSize * NUM_2)) {
133         IMAGE_LOGE("S size %{public}" PRIu64 " < y plane %{public}" PRIu64
134             " + uv plane %{public}" PRIu64, surfaceSize, yuv.ySize, yuv.uvSize * NUM_2);
135         return ERR_MEDIA_DATA_UNSUPPORT;
136     }
137 
138     NativeComponent* y = CreateComponent(int32_t(ComponentType::YUV_Y), yuv.ySize, width, NUM_1, nullptr);
139     NativeComponent* u = CreateComponent(int32_t(ComponentType::YUV_U), yuv.uvSize, uvStride, NUM_2, nullptr);
140     NativeComponent* v = CreateComponent(int32_t(ComponentType::YUV_V), yuv.uvSize, uvStride, NUM_2, nullptr);
141     if ((y == nullptr) || (u == nullptr) || (v == nullptr)) {
142         IMAGE_LOGE("Create Component failed");
143         return ERR_MEDIA_DATA_UNSUPPORT;
144     }
145     yuv.y = y->raw;
146     yuv.u = u->raw;
147     yuv.v = v->raw;
148     YUV422SPDataCopy(rawBuffer, surfaceSize, yuv, false);
149     return SUCCESS;
150 }
151 
SplitSurfaceToComponent()152 int32_t NativeImage::SplitSurfaceToComponent()
153 {
154     int32_t format = NUM_0;
155     auto res = GetFormat(format);
156     if (res != SUCCESS) {
157         return res;
158     }
159     switch (format) {
160         case int32_t(ImageFormat::YCBCR_422_SP):
161         case int32_t(GRAPHIC_PIXEL_FMT_YCBCR_422_SP):
162             return SplitYUV422SPComponent();
163         case int32_t(ImageFormat::JPEG):
164             bool cond = CreateCombineComponent(int32_t(ComponentType::JPEG)) != nullptr;
165             CHECK_ERROR_RETURN_RET(cond, SUCCESS);
166     }
167     // Unsupport split component
168     return ERR_MEDIA_DATA_UNSUPPORT;
169 }
170 
CombineYUVComponents()171 int32_t NativeImage::CombineYUVComponents()
172 {
173     int32_t format = NUM_0;
174     auto res = GetFormat(format);
175     if (res != SUCCESS) {
176         return res;
177     }
178     if (!IsYUV422SPFormat(format)) {
179         IMAGE_LOGI("No need to combine components for NO YUV format now");
180         return SUCCESS;
181     }
182 
183     uint8_t* buffer = GetSurfaceBufferAddr();
184     if (buffer == nullptr) {
185         IMAGE_LOGE("SurfaceBuffer viraddr is nullptr");
186         return ERR_MEDIA_DATA_UNSUPPORT;
187     }
188 
189     uint64_t bufferSize = NUM_0;
190     res = GetDataSize(bufferSize);
191     if (res != SUCCESS || bufferSize == NUM_0) {
192         IMAGE_LOGE("bufferSize is 0");
193         return ERR_MEDIA_DATA_UNSUPPORT;
194     }
195 
196     auto y = GetComponent(int32_t(ComponentType::YUV_Y));
197     auto u = GetComponent(int32_t(ComponentType::YUV_U));
198     auto v = GetComponent(int32_t(ComponentType::YUV_V));
199     bool cond = (y == nullptr) || (u == nullptr) || (v == nullptr);
200     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_MEDIA_DATA_UNSUPPORT, "No component need to combine");
201     YUVData data;
202     data.ySize = y->raw.size();
203     data.uvSize = u->raw.size();
204     data.y = y->raw;
205     data.u = u->raw;
206     data.v = v->raw;
207 
208     YUV422SPDataCopy(buffer, bufferSize, data, true);
209     return SUCCESS;
210 }
211 
BuildComponent(size_t size,int32_t row,int32_t pixel,uint8_t * vir)212 static std::unique_ptr<NativeComponent> BuildComponent(size_t size, int32_t row, int32_t pixel, uint8_t* vir)
213 {
214     if (size == NUM_0 && vir == nullptr) {
215         IMAGE_LOGE("Could't create 0 size component data");
216         return nullptr;
217     }
218     std::unique_ptr<NativeComponent> component = std::make_unique<NativeComponent>();
219     component->pixelStride = pixel;
220     component->rowStride = row;
221     component->size = size;
222     if (vir != nullptr) {
223         component->virAddr = vir;
224     } else {
225         component->raw.resize(size);
226     }
227     return component;
228 }
229 
GetCachedComponent(int32_t type)230 NativeComponent* NativeImage::GetCachedComponent(int32_t type)
231 {
232     auto iter = components_.find(type);
233     if (iter != components_.end()) {
234         return iter->second.get();
235     }
236     return nullptr;
237 }
238 
CreateComponent(int32_t type,size_t size,int32_t row,int32_t pixel,uint8_t * vir)239 NativeComponent* NativeImage::CreateComponent(int32_t type, size_t size, int32_t row,
240     int32_t pixel, uint8_t* vir)
241 {
242     NativeComponent* res = GetCachedComponent(type);
243     if (res != nullptr) {
244         IMAGE_LOGD("Component %{public}d already exist. No need create", type);
245         return res;
246     }
247 
248     std::unique_ptr<NativeComponent> component = BuildComponent(size, row, pixel, vir);
249     if (component == nullptr) {
250         return nullptr;
251     }
252     components_.insert(std::map<int32_t, std::unique_ptr<NativeComponent>>::value_type(type,
253         std::move(component)));
254 
255     return GetCachedComponent(type);
256 }
257 
CreateCombineComponent(int32_t type)258 NativeComponent* NativeImage::CreateCombineComponent(int32_t type)
259 {
260     uint64_t size = NUM_0;
261     GetDataSize(size);
262     return CreateComponent(type, static_cast<size_t>(size), buffer_->GetStride(), NUM_1, GetSurfaceBufferAddr());
263 }
GetSize(int32_t & width,int32_t & height)264 int32_t NativeImage::GetSize(int32_t &width, int32_t &height)
265 {
266     if (buffer_ == nullptr) {
267         return ERR_MEDIA_DEAD_OBJECT;
268     }
269     width = buffer_->GetWidth();
270     height = buffer_->GetHeight();
271     return SUCCESS;
272 }
273 
GetDataSize(uint64_t & size)274 int32_t NativeImage::GetDataSize(uint64_t &size)
275 {
276     if (buffer_ == nullptr) {
277         return ERR_MEDIA_DEAD_OBJECT;
278     }
279 
280     size = static_cast<uint64_t>(buffer_->GetSize());
281     auto extraData = buffer_->GetExtraData();
282     if (extraData == nullptr) {
283         IMAGE_LOGI("Nullptr s extra data. return buffer size %{public}" PRIu64, size);
284         return SUCCESS;
285     }
286 
287     int32_t extraDataSize = NUMI_0;
288     auto res = extraData->ExtraGet(DATA_SIZE_TAG, extraDataSize);
289     if (res != NUM_0) {
290         IMAGE_LOGI("S ExtraGet dataSize error %{public}d", res);
291     } else if (extraDataSize <= NUMI_0) {
292         IMAGE_LOGI("S ExtraGet dataSize Ok, but size <= 0");
293     } else if (static_cast<uint64_t>(extraDataSize) > size) {
294         IMAGE_LOGI("S ExtraGet dataSize Ok,but dataSize %{public}d is bigger than bufferSize %{public}" PRIu64,
295             extraDataSize, size);
296     } else {
297         IMAGE_LOGD("S ExtraGet dataSize %{public}d", extraDataSize);
298         size = extraDataSize;
299     }
300     return SUCCESS;
301 }
302 
GetFormat(int32_t & format)303 int32_t NativeImage::GetFormat(int32_t &format)
304 {
305     if (buffer_ == nullptr) {
306         return ERR_MEDIA_DEAD_OBJECT;
307     }
308     format = buffer_->GetFormat();
309     return SUCCESS;
310 }
311 
GetTimestamp(int64_t & timestamp)312 int32_t NativeImage::GetTimestamp(int64_t &timestamp)
313 {
314     if (buffer_ == nullptr) {
315         return ERR_MEDIA_DEAD_OBJECT;
316     }
317     timestamp = timestamp_;
318     return SUCCESS;
319 }
320 
GetComponent(int32_t type)321 NativeComponent* NativeImage::GetComponent(int32_t type)
322 {
323     if (buffer_ == nullptr) {
324         return nullptr;
325     }
326 
327     // Find type if it has exist.
328     auto component = GetCachedComponent(type);
329     if (component != nullptr) {
330         return component;
331     }
332 
333     int32_t format = NUM_0;
334     if (GetFormat(format) == SUCCESS && type == format) {
335         return CreateCombineComponent(type);
336     }
337     SplitSurfaceToComponent();
338     // Try again
339     component = GetCachedComponent(type);
340 
341 #ifdef COMPONENT_STRICT_CHECK
342     return component;
343 #else // We don't check the input type anymore, return raw format component!!
344     if (component == nullptr && GetFormat(format) == SUCCESS) {
345         return CreateCombineComponent(format);
346     }
347     return nullptr;
348 #endif
349 }
350 
release()351 void NativeImage::release()
352 {
353     if (buffer_ == nullptr) {
354         return;
355     }
356     IMAGE_LOGD("NativeImage release");
357     if (components_.size() > 0) {
358         components_.clear();
359     }
360     if (releaser_ != nullptr && buffer_ != nullptr) {
361         releaser_->BufferRelease(buffer_);
362     }
363     releaser_ = nullptr;
364     buffer_ = nullptr;
365 }
366 } // namespace Media
367 } // namespace OHOS
368