• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "colorspace_processor.h"
17 
18 #include <v1_0/cm_color_space.h>
19 #include <v1_0/buffer_handle_meta_key_type.h>
20 #include <hdr_type.h>
21 #include "effect_log.h"
22 #include "v1_0/cm_color_space.h"
23 #include "colorspace_helper.h"
24 #include "format_helper.h"
25 #include "common_utils.h"
26 #include "pixel_map.h"
27 #include "metadata_helper.h"
28 #ifdef VPE_ENABLE
29 #include "colorspace_converter.h"
30 #endif
31 
32 namespace OHOS {
33 namespace Media {
34 namespace Effect {
35 using namespace OHOS::ColorManager;
36 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
37 using namespace OHOS::Media::VideoProcessingEngine;
38 
ColorSpaceProcessor()39 ColorSpaceProcessor::ColorSpaceProcessor()
40 {
41 #ifdef VPE_ENABLE
42     converter = ColorSpaceConverter::Create();
43 #endif
44 }
45 
~ColorSpaceProcessor()46 ColorSpaceProcessor::~ColorSpaceProcessor()
47 {
48 }
49 
AllocSurfaceBuffer(std::vector<std::shared_ptr<MemoryData>> & memoryDataArray,MemoryInfo & allocMemInfo,CM_HDR_Metadata_Type type,CM_ColorSpaceType colorSpace)50 SurfaceBuffer *AllocSurfaceBuffer(std::vector<std::shared_ptr<MemoryData>> &memoryDataArray, MemoryInfo &allocMemInfo,
51     CM_HDR_Metadata_Type type, CM_ColorSpaceType colorSpace)
52 {
53     BufferInfo &bufferInfo = allocMemInfo.bufferInfo;
54     EFFECT_LOGD("AllocSurfaceBuffer: Alloc surface buffer memory! w=%{public}d, h=%{public}d, format=%{public}d",
55         bufferInfo.width_, bufferInfo.height_, bufferInfo.formatType_);
56 
57     std::unique_ptr<AbsMemory> absMemory = EffectMemory::CreateMemory(BufferType::DMA_BUFFER);
58     CHECK_AND_RETURN_RET_LOG(absMemory != nullptr, nullptr, "AllocSurfaceBuffer: absMemory is null!");
59     std::shared_ptr<MemoryData> memoryData = absMemory->Alloc(allocMemInfo);
60     CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, nullptr, "AllocSurfaceBuffer: memoryData is null!");
61 
62     void *surfaceBuffer = memoryData->memoryInfo.extra;
63     CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, nullptr, "AllocSurfaceBuffer: extra info is null!");
64 
65     auto *sb = static_cast<SurfaceBuffer *>(surfaceBuffer);
66     ColorSpaceHelper::SetSurfaceBufferMetadataType(sb, type);
67     ColorSpaceHelper::SetSurfaceBufferColorSpaceType(sb, colorSpace);
68     memoryDataArray.emplace_back(memoryData);
69     return sb;
70 }
71 
AllocSdrSurfaceBuffer(std::vector<std::shared_ptr<MemoryData>> & memoryDataArray,const EffectBuffer * inputHdr,CM_HDR_Metadata_Type type,CM_ColorSpaceType colorSpaceType,EffectColorSpace effectColorSpace)72 sptr<SurfaceBuffer> AllocSdrSurfaceBuffer(std::vector<std::shared_ptr<MemoryData>> &memoryDataArray,
73     const EffectBuffer *inputHdr, CM_HDR_Metadata_Type type, CM_ColorSpaceType colorSpaceType,
74     EffectColorSpace effectColorSpace)
75 {
76     MemoryInfo allocMemInfo;
77     BufferInfo &bufferInfo = allocMemInfo.bufferInfo;
78     bufferInfo = *inputHdr->bufferInfo_;
79     bufferInfo.formatType_ = IEffectFormat::RGBA8888;
80     bufferInfo.colorSpace_ = effectColorSpace;
81     SurfaceBuffer *sb = AllocSurfaceBuffer(memoryDataArray, allocMemInfo, type, colorSpaceType);
82     CHECK_AND_RETURN_RET_LOG(sb != nullptr, nullptr,
83         "AllocSdrSurfaceBuffer: alloc fail! w=%{public}d, h=%{public}d, format=%{public}d",
84         bufferInfo.width_, bufferInfo.height_, bufferInfo.formatType_);
85 
86     return sb;
87 }
88 
AllocGainmapSurfaceBuffer(std::vector<std::shared_ptr<MemoryData>> & memoryDataArray,const EffectBuffer * inputHdr,CM_HDR_Metadata_Type type,CM_ColorSpaceType colorSpaceType,EffectColorSpace effectColorSpace)89 sptr<SurfaceBuffer> AllocGainmapSurfaceBuffer(std::vector<std::shared_ptr<MemoryData>> &memoryDataArray,
90     const EffectBuffer *inputHdr, CM_HDR_Metadata_Type type, CM_ColorSpaceType colorSpaceType,
91     EffectColorSpace effectColorSpace)
92 {
93     MemoryInfo allocMemInfo;
94     BufferInfo &bufferInfo = allocMemInfo.bufferInfo;
95     bufferInfo = *inputHdr->bufferInfo_;
96     uint32_t half = 2;
97     bufferInfo.width_ = bufferInfo.width_ / half;
98     bufferInfo.height_ = bufferInfo.height_ / half;
99     bufferInfo.formatType_ = IEffectFormat::RGBA8888;
100     bufferInfo.colorSpace_ = effectColorSpace;
101     SurfaceBuffer *sb = AllocSurfaceBuffer(memoryDataArray, allocMemInfo, type, colorSpaceType);
102     CHECK_AND_RETURN_RET_LOG(sb != nullptr, nullptr,
103         "AllocGainmapSurfaceBuffer: alloc fail! w=%{public}d, h=%{public}d, format=%{public}d",
104         bufferInfo.width_, bufferInfo.height_, bufferInfo.formatType_);
105 
106     return sb;
107 }
108 
PrintColorSpaceInfo(const sptr<SurfaceBuffer> & surfaceBuffer,const std::string & tag)109 void PrintColorSpaceInfo(const sptr<SurfaceBuffer> &surfaceBuffer, const std::string &tag)
110 {
111     if (surfaceBuffer == nullptr) {
112         return;
113     }
114 
115     CM_HDR_Metadata_Type metadataType = CM_HDR_Metadata_Type::CM_METADATA_NONE;
116     ColorSpaceHelper::GetSurfaceBufferMetadataType(surfaceBuffer, metadataType);
117     CM_ColorSpaceType colorSpaceType = CM_ColorSpaceType::CM_COLORSPACE_NONE;
118     ColorSpaceHelper::GetSurfaceBufferColorSpaceType(surfaceBuffer, colorSpaceType);
119 
120     EFFECT_LOGD("%{public}s: metadataType=%{public}d, colorSpaceType=%{public}d, format=%{public}d",
121         tag.c_str(), metadataType, colorSpaceType, surfaceBuffer->GetFormat());
122 }
123 
ComposeHdrImage(const EffectBuffer * inputSdr,const SurfaceBuffer * inputGainmap,EffectBuffer * outputHdr)124 ErrorCode ColorSpaceProcessor::ComposeHdrImage(const EffectBuffer *inputSdr, const SurfaceBuffer *inputGainmap,
125     EffectBuffer *outputHdr)
126 {
127 #ifdef VPE_ENABLE
128     CHECK_AND_RETURN_RET_LOG(converter != nullptr, ErrorCode::ERR_INVALID_VPE_INSTANCE,
129         "DecomposeHdrImageInner: invalid vpe instance!");
130     CHECK_AND_RETURN_RET_LOG(inputSdr != nullptr && inputGainmap != nullptr && outputHdr != nullptr,
131         ErrorCode::ERR_INPUT_NULL, "ComposeHdrImageInner: inputSdr or inputGainmap or outputHdr is null!");
132 
133     sptr<SurfaceBuffer> sdrSb = inputSdr->bufferInfo_->surfaceBuffer_;
134     sptr<SurfaceBuffer> gainmapSb = const_cast<SurfaceBuffer *>(inputGainmap);
135     sptr<SurfaceBuffer> hdrSb = outputHdr->bufferInfo_->surfaceBuffer_;
136     CHECK_AND_RETURN_RET_LOG(sdrSb != nullptr && gainmapSb != nullptr && hdrSb != nullptr,
137         ErrorCode::ERR_INVALID_SURFACE_BUFFER, "ComposeHdrImageInner: invalid surface buffer! sdrSb=%{public}d,"
138         "gainmapSb=%{public}d, hdrSb=%{public}d", sdrSb == nullptr, gainmapSb == nullptr, hdrSb == nullptr);
139 
140     PrintColorSpaceInfo(sdrSb, "ComposeHdrImageInner:SdrSurfaceBuffer");
141     PrintColorSpaceInfo(gainmapSb, "ComposeHdrImageInner:GainmapSurfaceBuffer");
142     PrintColorSpaceInfo(hdrSb, "ComposeHdrImageInner:HdrSurfaceBuffer");
143 
144     ColorSpaceConverterParameter parameter;
145     parameter.renderIntent = RenderIntent::RENDER_INTENT_ABSOLUTE_COLORIMETRIC;
146     converter->SetParameter(parameter);
147 
148     int32_t res = converter->ComposeImage(sdrSb, gainmapSb, hdrSb, false);
149     CHECK_AND_RETURN_RET_LOG(res == 0, ErrorCode::ERR_VPE_COMPOSE_IMAGE_FAIL,
150         "ComposeHdrImageInner: ColorSpaceConverterComposeImage fail! res=%{public}d", res);
151 #endif
152     return ErrorCode::SUCCESS;
153 }
154 
DecomposeHdrImage(const EffectBuffer * inputHdr,std::shared_ptr<EffectBuffer> & outputSdr,SurfaceBuffer ** outputGainmap)155 ErrorCode ColorSpaceProcessor::DecomposeHdrImage(const EffectBuffer *inputHdr, std::shared_ptr<EffectBuffer> &outputSdr,
156     SurfaceBuffer **outputGainmap)
157 {
158 #ifdef VPE_ENABLE
159     CHECK_AND_RETURN_RET_LOG(converter != nullptr, ErrorCode::ERR_INVALID_VPE_INSTANCE,
160         "DecomposeHdrImageInner: invalid vpe instance!");
161     CHECK_AND_RETURN_RET_LOG(inputHdr != nullptr && outputGainmap != nullptr,
162         ErrorCode::ERR_INPUT_NULL, "DecomposeHdrImageInner: inputHdr or outputGainmap is null!");
163 
164     sptr<SurfaceBuffer> hdrSb = inputHdr->bufferInfo_->surfaceBuffer_;
165     sptr<SurfaceBuffer> sdrSb = AllocSdrSurfaceBuffer(memoryDataArray_, inputHdr, CM_IMAGE_HDR_VIVID_DUAL, CM_P3_FULL,
166         EffectColorSpace::DISPLAY_P3);
167     sptr<SurfaceBuffer> gainmapSb = AllocGainmapSurfaceBuffer(memoryDataArray_, inputHdr, CM_METADATA_NONE, CM_P3_FULL,
168         EffectColorSpace::DISPLAY_P3);
169     CHECK_AND_RETURN_RET_LOG(hdrSb != nullptr && sdrSb != nullptr && gainmapSb != nullptr,
170         ErrorCode::ERR_INVALID_SURFACE_BUFFER, "DecomposeHdrImageInner: invalid surface buffer! hdrSb=%{public}d,"
171         "sdrSb=%{public}d, gainmapSb=%{public}d", hdrSb == nullptr, sdrSb == nullptr, gainmapSb == nullptr);
172 
173     ColorSpaceHelper::SetHDRDynamicMetadata(hdrSb, std::vector<uint8_t>(0));
174     ColorSpaceHelper::SetHDRStaticMetadata(hdrSb, std::vector<uint8_t>(0));
175 
176     PrintColorSpaceInfo(hdrSb, "DecomposeHdrImageInner:HdrSurfaceBuffer");
177     PrintColorSpaceInfo(sdrSb, "DecomposeHdrImageInner:SdrSurfaceBuffer");
178     PrintColorSpaceInfo(gainmapSb, "DecomposeHdrImageInner:GainmapSurfaceBuffer");
179 
180     ColorSpaceConverterParameter parameter;
181     parameter.renderIntent = RenderIntent::RENDER_INTENT_ABSOLUTE_COLORIMETRIC;
182     converter->SetParameter(parameter);
183 
184     int32_t res = converter->DecomposeImage(hdrSb, sdrSb, gainmapSb);
185     CHECK_AND_RETURN_RET_LOG(res == 0, ErrorCode::ERR_VPE_DECOMPOSE_IMAGE_FAIL,
186         "DecomposeHdrImageInner: ColorSpaceConverterDecomposeImage fail! res=%{public}d", res);
187 
188     // update effectBuffer
189     std::shared_ptr<EffectBuffer> buffer = nullptr;
190     ErrorCode errorCode = CommonUtils::ParseSurfaceData(sdrSb, buffer, inputHdr->extraInfo_->dataType);
191     CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode,
192         "DecomposeHdrImageInner: ParseSurfaceData fail! errorCode=%{public}d", errorCode);
193     CHECK_AND_RETURN_RET_LOG(buffer != nullptr && buffer->extraInfo_ != nullptr, ErrorCode::ERR_INPUT_NULL,
194         "DecomposeHdrImageInner: buffer is null or extraInfo of buffer is null!"
195         "buffer=%{public}d, buffer->extraInfo_=%{public}d", buffer == nullptr, buffer->extraInfo_ == nullptr);
196     *buffer->extraInfo_ = *inputHdr->extraInfo_;
197     buffer->bufferInfo_->surfaceBuffer_ = sdrSb;
198     buffer->extraInfo_->bufferType = BufferType::DMA_BUFFER;
199 
200     outputSdr = buffer;
201     *outputGainmap = gainmapSb;
202 #endif
203     return ErrorCode::SUCCESS;
204 }
205 
ProcessHdrImage(const EffectBuffer * inputHdr,std::shared_ptr<EffectBuffer> & outputSdr)206 ErrorCode ColorSpaceProcessor::ProcessHdrImage(const EffectBuffer *inputHdr, std::shared_ptr<EffectBuffer> &outputSdr)
207 {
208 #ifdef VPE_ENABLE
209     CHECK_AND_RETURN_RET_LOG(converter != nullptr, ErrorCode::ERR_INVALID_VPE_INSTANCE,
210         "DecomposeHdrImageInner: invalid vpe instance!");
211     CHECK_AND_RETURN_RET_LOG(inputHdr != nullptr, ErrorCode::ERR_INPUT_NULL,
212         "ProcessHdrImageInner: inputHdr is null!");
213 
214     sptr<SurfaceBuffer> sdrSb = AllocSdrSurfaceBuffer(memoryDataArray_, inputHdr, CM_IMAGE_HDR_VIVID_DUAL, CM_P3_FULL,
215         EffectColorSpace::DISPLAY_P3);
216     sptr<SurfaceBuffer> hdrSb = inputHdr->bufferInfo_->surfaceBuffer_;
217     CHECK_AND_RETURN_RET_LOG(sdrSb != nullptr && hdrSb != nullptr, ErrorCode::ERR_INVALID_SURFACE_BUFFER,
218         "ProcessHdrImageInner: invalid surface buffer! sdrSb=%{public}d, hdrSb=%{public}d",
219         sdrSb == nullptr, hdrSb == nullptr);
220 
221     PrintColorSpaceInfo(hdrSb, "ProcessHdrImageInner:HdrSurfaceBuffer");
222     PrintColorSpaceInfo(sdrSb, "ProcessHdrImageInner:SdrSurfaceBuffer");
223 
224     ColorSpaceHelper::SetHDRDynamicMetadata(hdrSb, std::vector<uint8_t>(0));
225     ColorSpaceHelper::SetHDRStaticMetadata(hdrSb, std::vector<uint8_t>(0));
226 
227     ColorSpaceConverterParameter parameter;
228     parameter.renderIntent = RenderIntent::RENDER_INTENT_ABSOLUTE_COLORIMETRIC;
229     converter->SetParameter(parameter);
230 
231     int32_t res = converter->Process(hdrSb, sdrSb);
232     CHECK_AND_RETURN_RET_LOG(res == 0, ErrorCode::ERR_VPE_PROCESS_IMAGE_FAIL,
233         "ProcessHdrImageInner: ColorSpaceConverterProcessImage fail! res=%{public}d", res);
234 
235     // update effectBuffer
236     std::shared_ptr<EffectBuffer> buffer;
237     ErrorCode errorCode = CommonUtils::ParseSurfaceData(sdrSb, buffer, inputHdr->extraInfo_->dataType);
238     CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode,
239         "ProcessHdrImageInner: ParseSurfaceData fail! errorCode=%{public}d", errorCode);
240     *buffer->extraInfo_ = *inputHdr->extraInfo_;
241     buffer->bufferInfo_->surfaceBuffer_ = sdrSb;
242     buffer->extraInfo_->bufferType = BufferType::DMA_BUFFER;
243 
244     outputSdr = buffer;
245 #endif
246     return ErrorCode::SUCCESS;
247 }
248 
GetMemoryData(SurfaceBuffer * sb)249 std::shared_ptr<MemoryData> ColorSpaceProcessor::GetMemoryData(SurfaceBuffer *sb)
250 {
251     CHECK_AND_RETURN_RET_LOG(sb != nullptr, nullptr, "GetMemoryData: sb is null!");
252 
253     void *pSurfaceBuffer = static_cast<void *>(sb);
254     for (const auto &memoryData : memoryDataArray_) {
255         if (memoryData->memoryInfo.extra == pSurfaceBuffer) {
256             return memoryData;
257         }
258     }
259 
260     return nullptr;
261 }
262 
CreatePixelMap(EffectBuffer * effectBuffer)263 PixelMap *CreatePixelMap(EffectBuffer *effectBuffer)
264 {
265     std::shared_ptr<BufferInfo> &bufferInfo = effectBuffer->bufferInfo_;
266     InitializationOptions options = {
267         .size = {
268             .width = static_cast<int32_t>(bufferInfo->width_),
269             .height = static_cast<int32_t>(bufferInfo->height_),
270         },
271         .srcPixelFormat = CommonUtils::SwitchToPixelFormat(bufferInfo->formatType_),
272         .pixelFormat = CommonUtils::SwitchToPixelFormat(bufferInfo->formatType_),
273     };
274     std::unique_ptr<PixelMap> pixelMap = PixelMap::Create(static_cast<uint32_t *>(effectBuffer->buffer_),
275         bufferInfo->len_, 0, static_cast<int32_t>(bufferInfo->rowStride_), options, true);
276     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "CreatePixelMap: create fail!");
277     CHECK_AND_RETURN_RET_LOG(pixelMap->GetPixelFormat() == options.pixelFormat, nullptr,
278         "CreatePixelMap: pixelFormat error! pixelFormat=%{public}d, optionPixelFormat=%{public}d",
279         pixelMap->GetPixelFormat(), options.pixelFormat);
280 
281     const std::shared_ptr<ExtraInfo> &extraInfo = effectBuffer->extraInfo_;
282     extraInfo->innerPixelMap = std::move(pixelMap);
283     return extraInfo->innerPixelMap.get();
284 }
285 
GetPixelMap(EffectBuffer * effectBuffer)286 PixelMap *GetPixelMap(EffectBuffer *effectBuffer)
287 {
288     std::shared_ptr<ExtraInfo> &extraInfo = effectBuffer->extraInfo_;
289     std::shared_ptr<BufferInfo> &bufferInfo = effectBuffer->bufferInfo_;
290     switch (extraInfo->dataType) {
291         case DataType::PIXEL_MAP:
292             return bufferInfo->pixelMap_;
293         case DataType::URI:
294         case DataType::PATH:
295         case DataType::PICTURE:
296             return extraInfo->picture == nullptr ? nullptr : extraInfo->picture->GetMainPixel().get();
297         case DataType::SURFACE:
298         case DataType::SURFACE_BUFFER:
299             return CreatePixelMap(effectBuffer);
300         default:
301             EFFECT_LOGE("Data type not support! dataType=%{public}d", extraInfo->dataType);
302             return nullptr;
303     }
304 }
305 
ApplyColorSpace(EffectBuffer * effectBuffer,EffectColorSpace targetColorSpace)306 ErrorCode ColorSpaceProcessor::ApplyColorSpace(EffectBuffer *effectBuffer, EffectColorSpace targetColorSpace)
307 {
308     CHECK_AND_RETURN_RET_LOG(effectBuffer != nullptr && effectBuffer->bufferInfo_ != nullptr &&
309         effectBuffer->buffer_ != nullptr && effectBuffer->extraInfo_ != nullptr,
310         ErrorCode::ERR_INPUT_NULL, "ApplyColorSpace: effectBuffer is null!");
311 
312     ColorSpaceName colorSpaceName = ColorSpaceHelper::ConvertToColorSpaceName(targetColorSpace);
313     CHECK_AND_RETURN_RET_LOG(colorSpaceName != ColorSpaceName::NONE, ErrorCode::ERR_INVALID_COLORSPACE,
314         "ApplyColorSpace: invalid color space! targetColorSpace=%{public}d", targetColorSpace);
315 
316     PixelMap *pixelMap = GetPixelMap(effectBuffer);
317     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_CREATE_PIXELMAP_FAIL,
318         "ApplyColorSpace create pixelmap fail!");
319 
320     OHOS::ColorManager::ColorSpace grColorSpace(colorSpaceName);
321     uint32_t res = pixelMap->ApplyColorSpace(grColorSpace);
322     CHECK_AND_RETURN_RET_LOG(res == 0, ErrorCode::ERR_APPLYCOLORSPACE_FAIL, "ApplyColorSpace: pixelMap "
323         "ApplyColorSpace fail! res=%{public}d, colorSpaceName=%{public}d", res, colorSpaceName);
324 
325     // update effectBuffer
326     std::shared_ptr<EffectBuffer> buffer;
327     ErrorCode errorCode = CommonUtils::LockPixelMap(pixelMap, buffer);
328     CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode, "ApplyColorSpace: pixelMap parse fail!"
329         "res=%{public}d, colorSpaceName=%{public}d", res, colorSpaceName);
330 
331     effectBuffer->bufferInfo_ = buffer->bufferInfo_;
332     effectBuffer->buffer_ = buffer->buffer_;
333     effectBuffer->bufferInfo_->surfaceBuffer_ = buffer->bufferInfo_->surfaceBuffer_;
334 
335     return ErrorCode::SUCCESS;
336 }
337 } // namespace Effect
338 } // namespace Media
339 } // namespace OHOS