• 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 "image_packer.h"
17 
18 #include "buffer_packer_stream.h"
19 #include "file_packer_stream.h"
20 #include "image/abs_image_encoder.h"
21 #include "image_utils.h"
22 #include "log_tags.h"
23 #include "media_errors.h"
24 #include "ostream_packer_stream.h"
25 #include "plugin_server.h"
26 #if defined(A_PLATFORM) || defined(IOS_PLATFORM)
27 #include "include/jpeg_encoder.h"
28 #endif
29 
30 namespace OHOS {
31 namespace Media {
32 using namespace OHOS::HiviewDFX;
33 using namespace ImagePlugin;
34 using namespace MultimediaPlugin;
35 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "ImagePacker" };
36 static constexpr uint8_t QUALITY_MAX = 100;
37 const static std::string EXTENDED_ENCODER = "image/extended";
38 static constexpr size_t SIZE_ZERO = 0;
39 
40 PluginServer &ImagePacker::pluginServer_ = ImageUtils::GetPluginServer();
41 
GetSupportedFormats(std::set<std::string> & formats)42 uint32_t ImagePacker::GetSupportedFormats(std::set<std::string> &formats)
43 {
44     formats.clear();
45     std::vector<ClassInfo> classInfos;
46     uint32_t ret =
47         pluginServer_.PluginServerGetClassInfo<AbsImageEncoder>(AbsImageEncoder::SERVICE_DEFAULT, classInfos);
48     if (ret != SUCCESS) {
49         HiLog::Error(LABEL, "get class info from plugin server,ret:%{public}u.", ret);
50         return ret;
51     }
52     for (auto &info : classInfos) {
53         std::map<std::string, AttrData> &capbility = info.capabilities;
54         auto iter = capbility.find(IMAGE_ENCODE_FORMAT);
55         if (iter == capbility.end()) {
56             continue;
57         }
58         AttrData &attr = iter->second;
59         std::string format;
60         if (attr.GetValue(format) != SUCCESS) {
61             HiLog::Error(LABEL, "attr data get format failed.");
62             continue;
63         }
64         formats.insert(format);
65     }
66     return SUCCESS;
67 }
68 
StartPackingImpl(const PackOption & option)69 uint32_t ImagePacker::StartPackingImpl(const PackOption &option)
70 {
71     if (packerStream_ == nullptr || packerStream_.get() == nullptr) {
72         HiLog::Error(LABEL, "make buffer packer stream failed.");
73         return ERR_IMAGE_DATA_ABNORMAL;
74     }
75     if (!GetEncoderPlugin(option)) {
76         HiLog::Error(LABEL, "StartPackingImpl get encoder plugin failed.");
77         return ERR_IMAGE_MISMATCHED_FORMAT;
78     }
79     PlEncodeOptions plOpts;
80     CopyOptionsToPlugin(option, plOpts);
81     return DoEncodingFunc([this, &plOpts](ImagePlugin::AbsImageEncoder* encoder) {
82         return encoder->StartEncode(*packerStream_.get(), plOpts);
83     });
84 }
85 
StartPacking(uint8_t * outputData,uint32_t maxSize,const PackOption & option)86 uint32_t ImagePacker::StartPacking(uint8_t *outputData, uint32_t maxSize, const PackOption &option)
87 {
88     if (!IsPackOptionValid(option)) {
89         HiLog::Error(LABEL, "array startPacking option invalid %{public}s, %{public}u.", option.format.c_str(),
90                      option.quality);
91         return ERR_IMAGE_INVALID_PARAMETER;
92     }
93 
94     if (outputData == nullptr) {
95         HiLog::Error(LABEL, "output buffer is null.");
96         return ERR_IMAGE_INVALID_PARAMETER;
97     }
98     BufferPackerStream *stream = new (std::nothrow) BufferPackerStream(outputData, maxSize);
99     if (stream == nullptr) {
100         HiLog::Error(LABEL, "make buffer packer stream failed.");
101         return ERR_IMAGE_DATA_ABNORMAL;
102     }
103     FreeOldPackerStream();
104     packerStream_ = std::unique_ptr<BufferPackerStream>(stream);
105     return StartPackingImpl(option);
106 }
107 
StartPacking(const std::string & filePath,const PackOption & option)108 uint32_t ImagePacker::StartPacking(const std::string &filePath, const PackOption &option)
109 {
110     if (!IsPackOptionValid(option)) {
111         HiLog::Error(LABEL, "filepath startPacking option invalid %{public}s, %{public}u.", option.format.c_str(),
112                      option.quality);
113         return ERR_IMAGE_INVALID_PARAMETER;
114     }
115     FilePackerStream *stream = new (std::nothrow) FilePackerStream(filePath);
116     if (stream == nullptr) {
117         HiLog::Error(LABEL, "make file packer stream failed.");
118         return ERR_IMAGE_DATA_ABNORMAL;
119     }
120     FreeOldPackerStream();
121     packerStream_ = std::unique_ptr<FilePackerStream>(stream);
122     return StartPackingImpl(option);
123 }
124 
StartPacking(const int & fd,const PackOption & option)125 uint32_t ImagePacker::StartPacking(const int &fd, const PackOption &option)
126 {
127     if (!IsPackOptionValid(option)) {
128         HiLog::Error(LABEL, "fd startPacking option invalid %{public}s, %{public}u.", option.format.c_str(),
129                      option.quality);
130         return ERR_IMAGE_INVALID_PARAMETER;
131     }
132     FilePackerStream *stream = new (std::nothrow) FilePackerStream(fd);
133     if (stream == nullptr) {
134         HiLog::Error(LABEL, "make file packer stream failed.");
135         return ERR_IMAGE_DATA_ABNORMAL;
136     }
137     FreeOldPackerStream();
138     packerStream_ = std::unique_ptr<FilePackerStream>(stream);
139     return StartPackingImpl(option);
140 }
141 
StartPacking(std::ostream & outputStream,const PackOption & option)142 uint32_t ImagePacker::StartPacking(std::ostream &outputStream, const PackOption &option)
143 {
144     if (!IsPackOptionValid(option)) {
145         HiLog::Error(LABEL, "outputStream startPacking option invalid %{public}s, %{public}u.", option.format.c_str(),
146                      option.quality);
147         return ERR_IMAGE_INVALID_PARAMETER;
148     }
149     OstreamPackerStream *stream = new (std::nothrow) OstreamPackerStream(outputStream);
150     if (stream == nullptr) {
151         HiLog::Error(LABEL, "make ostream packer stream failed.");
152         return ERR_IMAGE_DATA_ABNORMAL;
153     }
154     FreeOldPackerStream();
155     packerStream_ = std::unique_ptr<OstreamPackerStream>(stream);
156     return StartPackingImpl(option);
157 }
158 
159 // JNI adapter method, this method be called by jni and the outputStream be created by jni, here we manage the lifecycle
160 // of the outputStream
StartPackingAdapter(PackerStream & outputStream,const PackOption & option)161 uint32_t ImagePacker::StartPackingAdapter(PackerStream &outputStream, const PackOption &option)
162 {
163     FreeOldPackerStream();
164     packerStream_ = std::unique_ptr<PackerStream>(&outputStream);
165 
166     if (!IsPackOptionValid(option)) {
167         HiLog::Error(LABEL, "packer stream option invalid %{public}s, %{public}u.", option.format.c_str(),
168                      option.quality);
169         return ERR_IMAGE_INVALID_PARAMETER;
170     }
171     return StartPackingImpl(option);
172 }
173 
AddImage(PixelMap & pixelMap)174 uint32_t ImagePacker::AddImage(PixelMap &pixelMap)
175 {
176     return DoEncodingFunc([this, &pixelMap](ImagePlugin::AbsImageEncoder* encoder) {
177         return encoder->AddImage(pixelMap);
178     });
179 }
180 
AddImage(ImageSource & source)181 uint32_t ImagePacker::AddImage(ImageSource &source)
182 {
183     DecodeOptions opts;
184     uint32_t ret = SUCCESS;
185     if (pixelMap_ != nullptr) {
186         pixelMap_.reset();  // release old inner pixelmap
187     }
188     pixelMap_ = source.CreatePixelMap(opts, ret);
189     if (ret != SUCCESS) {
190         HiLog::Error(LABEL, "image source create pixel map failed.");
191         return ret;
192     }
193     if (pixelMap_ == nullptr || pixelMap_.get() == nullptr) {
194         HiLog::Error(LABEL, "create the pixel map unique_ptr fail.");
195         return ERR_IMAGE_MALLOC_ABNORMAL;
196     }
197     return AddImage(*pixelMap_.get());
198 }
199 
AddImage(ImageSource & source,uint32_t index)200 uint32_t ImagePacker::AddImage(ImageSource &source, uint32_t index)
201 {
202     DecodeOptions opts;
203     uint32_t ret = SUCCESS;
204     if (pixelMap_ != nullptr) {
205         pixelMap_.reset();  // release old inner pixelmap
206     }
207     pixelMap_ = source.CreatePixelMap(index, opts, ret);
208     if (ret != SUCCESS) {
209         HiLog::Error(LABEL, "image source create pixel map failed.");
210         return ret;
211     }
212     if (pixelMap_ == nullptr || pixelMap_.get() == nullptr) {
213         HiLog::Error(LABEL, "create the pixel map unique_ptr fail.");
214         return ERR_IMAGE_MALLOC_ABNORMAL;
215     }
216     return AddImage(*pixelMap_.get());
217 }
218 
FinalizePacking()219 uint32_t ImagePacker::FinalizePacking()
220 {
221     return DoEncodingFunc([](ImagePlugin::AbsImageEncoder* encoder) {
222         auto res = encoder->FinalizeEncode();
223         if (res != SUCCESS) {
224             HiLog::Error(LABEL, "FinalizePacking failed %{public}d.", res);
225         }
226         return res;
227         }, false);
228 }
229 
FinalizePacking(int64_t & packedSize)230 uint32_t ImagePacker::FinalizePacking(int64_t &packedSize)
231 {
232     uint32_t ret = FinalizePacking();
233     packedSize = (packerStream_ != nullptr) ? packerStream_->BytesWritten() : 0;
234     return ret;
235 }
236 
GetEncoder(PluginServer & pluginServer,std::string format)237 static ImagePlugin::AbsImageEncoder* GetEncoder(PluginServer &pluginServer, std::string format)
238 {
239     std::map<std::string, AttrData> capabilities;
240     capabilities.insert(std::map<std::string, AttrData>::value_type(IMAGE_ENCODE_FORMAT, AttrData(format)));
241     return pluginServer.CreateObject<AbsImageEncoder>(AbsImageEncoder::SERVICE_DEFAULT, capabilities);
242 }
243 
GetEncoderPlugin(const PackOption & option)244 bool ImagePacker::GetEncoderPlugin(const PackOption &option)
245 {
246     encoders_.clear();
247     HiLog::Debug(LABEL, "GetEncoderPlugin current encoder plugin size %{public}zu.", encoders_.size());
248     auto encoder = GetEncoder(pluginServer_, EXTENDED_ENCODER);
249     if (encoder != nullptr) {
250         encoders_.emplace_back(std::unique_ptr<ImagePlugin::AbsImageEncoder>(encoder));
251     } else {
252         HiLog::Error(LABEL, "GetEncoderPlugin get exencoder plugin failed.");
253     }
254     encoder = GetEncoder(pluginServer_, option.format);
255     if (encoder != nullptr) {
256         encoders_.emplace_back(std::unique_ptr<ImagePlugin::AbsImageEncoder>(encoder));
257     } else {
258         HiLog::Error(LABEL, "GetEncoderPlugin get %{publci}s plugin failed.", option.format.c_str());
259     }
260     return encoders_.size() != SIZE_ZERO;
261 }
262 
CopyOptionsToPlugin(const PackOption & opts,PlEncodeOptions & plOpts)263 void ImagePacker::CopyOptionsToPlugin(const PackOption &opts, PlEncodeOptions &plOpts)
264 {
265     plOpts.numberHint = opts.numberHint;
266     plOpts.quality = opts.quality;
267     plOpts.format = opts.format;
268 }
269 
FreeOldPackerStream()270 void ImagePacker::FreeOldPackerStream()
271 {
272     if (packerStream_ != nullptr) {
273         packerStream_.reset();
274     }
275 }
276 
IsPackOptionValid(const PackOption & option)277 bool ImagePacker::IsPackOptionValid(const PackOption &option)
278 {
279     return !(option.quality > QUALITY_MAX || option.format.empty());
280 }
281 
DoEncodingFunc(std::function<uint32_t (ImagePlugin::AbsImageEncoder *)> func,bool forAll)282 uint32_t ImagePacker::DoEncodingFunc(std::function<uint32_t(ImagePlugin::AbsImageEncoder*)> func, bool forAll)
283 {
284     if (encoders_.size() == SIZE_ZERO) {
285         HiLog::Error(LABEL, "DoEncodingFunc encoders is empty.");
286         return ERR_IMAGE_DECODE_ABNORMAL;
287     }
288     std::vector<uint32_t> rets;
289     rets.resize(SIZE_ZERO);
290     bool isSuccessOnce = false;
291     for (size_t i = SIZE_ZERO; i < encoders_.size(); i++) {
292         if (!forAll && isSuccessOnce) {
293             HiLog::Debug(LABEL, "DoEncodingFunc encoding successed, reset other encoder.");
294             encoders_.at(i).reset();
295             continue;
296         }
297         auto iterRes = func(encoders_.at(i).get());
298         rets.emplace_back(iterRes);
299         if (iterRes == SUCCESS) {
300             isSuccessOnce = true;
301         }
302         if (!forAll && !isSuccessOnce) {
303             HiLog::Debug(LABEL, "DoEncodingFunc failed.");
304         }
305     }
306     if (isSuccessOnce) {
307         return SUCCESS;
308     }
309     return (rets.size() == SIZE_ZERO)?ERR_IMAGE_DECODE_ABNORMAL:rets.front();
310 }
311 
312 // class reference need explicit constructor and destructor, otherwise unique_ptr<T> use unnormal
ImagePacker()313 ImagePacker::ImagePacker()
314 {}
315 
~ImagePacker()316 ImagePacker::~ImagePacker()
317 {}
318 } // namespace Media
319 } // namespace OHOS
320