• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "hardware/imagecodec/image_codec.h"
17 #include "hardware/imagecodec/image_decoder.h"
18 #include "hardware/imagecodec/image_codec_list.h"
19 #include "hardware/imagecodec/image_codec_log.h"
20 #include "syspara/parameters.h" // base/startup/init/interfaces/innerkits/include/
21 #include "qos.h"
22 
23 namespace OHOS::ImagePlugin {
24 using namespace std;
25 using namespace HdiCodecNamespace;
26 
IsSecureMode(const string & name)27 static bool IsSecureMode(const string &name)
28 {
29     string prefix = ".secure";
30     if (name.length() <= prefix.length()) {
31         return false;
32     }
33     return (name.rfind(prefix) == (name.length() - prefix.length()));
34 }
35 
Create()36 shared_ptr<ImageCodec> ImageCodec::Create()
37 {
38     vector<CodecCompCapability> capList = GetCapList();
39     shared_ptr<ImageCodec> codec;
40     string name;
41     for (const auto& cap : capList) {
42         if (cap.role == MEDIA_ROLETYPE_VIDEO_HEVC && cap.type == VIDEO_DECODER && !IsSecureMode(cap.compName)) {
43             name = cap.compName;
44             codec = make_shared<ImageDecoder>();
45             break;
46         }
47     }
48     if ((codec != nullptr) && (codec->InitWithName(name) == IC_ERR_OK)) {
49         return codec;
50     }
51     return nullptr;
52 }
53 
SetCallback(const shared_ptr<ImageCodecCallback> & callback)54 int32_t ImageCodec::SetCallback(const shared_ptr<ImageCodecCallback> &callback)
55 {
56     HLOGI(">>");
57     function<void(ParamSP)> proc = [&](ParamSP msg) {
58         msg->SetValue("callback", callback);
59     };
60     return DoSyncCall(MsgWhat::SET_CALLBACK, proc);
61 }
62 
Configure(const Format & format)63 int32_t ImageCodec::Configure(const Format &format)
64 {
65     function<void(ParamSP)> proc = [&](ParamSP msg) {
66         msg->SetValue("format", format);
67     };
68     return DoSyncCall(MsgWhat::CONFIGURE, proc);
69 }
70 
QueueInputBuffer(uint32_t index)71 int32_t ImageCodec::QueueInputBuffer(uint32_t index)
72 {
73     function<void(ParamSP)> proc = [&](ParamSP msg) {
74         msg->SetValue(BUFFER_ID, index);
75     };
76     return DoSyncCall(MsgWhat::QUEUE_INPUT_BUFFER, proc);
77 }
78 
ReleaseOutputBuffer(uint32_t index)79 int32_t ImageCodec::ReleaseOutputBuffer(uint32_t index)
80 {
81     function<void(ParamSP)> proc = [&](ParamSP msg) {
82         msg->SetValue(BUFFER_ID, index);
83     };
84     return DoSyncCall(MsgWhat::RELEASE_OUTPUT_BUFFER, proc);
85 }
86 
GetInputFormat(Format & format)87 int32_t ImageCodec::GetInputFormat(Format& format)
88 {
89     HLOGI(">>");
90     ParamSP reply;
91     int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_INPUT_FORMAT, nullptr, reply);
92     if (ret != IC_ERR_OK) {
93         HLOGE("failed to get input format");
94         return ret;
95     }
96     IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format),
97         IC_ERR_UNKNOWN, "input format not replied");
98     return IC_ERR_OK;
99 }
100 
GetOutputFormat(Format & format)101 int32_t ImageCodec::GetOutputFormat(Format& format)
102 {
103     ParamSP reply;
104     int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_OUTPUT_FORMAT, nullptr, reply);
105     if (ret != IC_ERR_OK) {
106         HLOGE("failed to get output format");
107         return ret;
108     }
109     IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format),
110         IC_ERR_UNKNOWN, "output format not replied");
111     return IC_ERR_OK;
112 }
113 
Start()114 int32_t ImageCodec::Start()
115 {
116     HLOGI(">>");
117     return DoSyncCall(MsgWhat::START, nullptr);
118 }
119 
Release()120 int32_t ImageCodec::Release()
121 {
122     HLOGI(">>");
123     return DoSyncCall(MsgWhat::RELEASE, nullptr);
124 }
125 
GetOutputBufferUsage(uint64_t & usage)126 int32_t ImageCodec::GetOutputBufferUsage(uint64_t& usage)
127 {
128     ParamSP reply;
129     int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_OUTPUT_BUFFER_USAGE, nullptr, reply);
130     if (ret != IC_ERR_OK) {
131         HLOGE("failed to get output buffer usage");
132         return ret;
133     }
134     IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("usage", usage),
135         IC_ERR_UNKNOWN, "output buffer usage not replied");
136     return IC_ERR_OK;
137 }
138 
SetOutputBuffer(sptr<SurfaceBuffer> output)139 int32_t ImageCodec::SetOutputBuffer(sptr<SurfaceBuffer> output)
140 {
141     HLOGI(">>");
142     std::function<void(ParamSP)> proc = [&](ParamSP msg) {
143         msg->SetValue("output", output);
144     };
145     return DoSyncCall(MsgWhat::SET_OUTPUT_BUFFER, proc);
146 }
147 
SetPackedInputFlag(bool flag)148 int32_t ImageCodec::SetPackedInputFlag(bool flag)
149 {
150     HLOGI(">>");
151     std::function<void(ParamSP)> proc = [&](ParamSP msg) {
152         msg->SetValue("packedInputFlag", flag);
153     };
154     return DoSyncCall(MsgWhat::SET_PACKED_INPUT_FLAG, proc);
155 }
156 
GetPackedInputCapability(bool & flag)157 int32_t ImageCodec::GetPackedInputCapability(bool& flag)
158 {
159     ParamSP reply;
160     int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_PACKED_CAPABILITY, nullptr, reply);
161     if (ret != IC_ERR_OK) {
162         HLOGE("failed to get packed input flag");
163         return ret;
164     }
165     IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("isPackedInputSupported", flag),
166         IC_ERR_UNKNOWN, "packed input flag not replied");
167     return IC_ERR_OK;
168 }
169 /**************************** public functions end ****************************/
170 
ImageCodec(OMX_VIDEO_CODINGTYPE codingType,bool isEncoder)171 ImageCodec::ImageCodec(OMX_VIDEO_CODINGTYPE codingType, bool isEncoder)
172     : isEncoder_(isEncoder), codingType_(codingType)
173 {
174     debugMode_ = OHOS::system::GetBoolParameter("image.codec.debug", false);
175     dumpMode_ = OHOS::system::GetBoolParameter("image.codec.dump", false);
176     LOGD(">> debug mode = %{public}d, dump mode = %{public}d", debugMode_, dumpMode_);
177 
178     uninitializedState_ = make_shared<UninitializedState>(this);
179     initializedState_ = make_shared<InitializedState>(this);
180     startingState_ = make_shared<StartingState>(this);
181     runningState_ = make_shared<RunningState>(this);
182     outputPortChangedState_ = make_shared<OutputPortChangedState>(this);
183     stoppingState_ = make_shared<StoppingState>(this);
184     StateMachine::ChangeStateTo(uninitializedState_);
185 }
186 
~ImageCodec()187 ImageCodec::~ImageCodec()
188 {
189     HLOGI(">>");
190     MsgHandleLoop::Stop();
191     ReleaseComponent();
192 }
193 
InitWithName(const string & name)194 int32_t ImageCodec::InitWithName(const string &name)
195 {
196     function<void(ParamSP)> proc = [&](ParamSP msg) {
197         msg->SetValue("name", name);
198     };
199     return DoSyncCall(MsgWhat::INIT, proc);
200 }
201 
ToString(BufferOwner owner)202 const char* ImageCodec::ToString(BufferOwner owner)
203 {
204     switch (owner) {
205         case BufferOwner::OWNED_BY_US:
206             return "us";
207         case BufferOwner::OWNED_BY_USER:
208             return "user";
209         case BufferOwner::OWNED_BY_OMX:
210             return "omx";
211         default:
212             return "";
213     }
214 }
215 
ToString(MsgWhat what)216 const char* ImageCodec::ToString(MsgWhat what)
217 {
218     static const map<MsgWhat, const char*> m = {
219         { INIT,                    "INIT"                    },
220         { SET_CALLBACK,            "SET_CALLBACK"            },
221         { CONFIGURE,               "CONFIGURE"               },
222         { START,                   "START"                   },
223         { GET_INPUT_FORMAT,        "GET_INPUT_FORMAT"        },
224         { GET_OUTPUT_FORMAT,       "GET_OUTPUT_FORMAT"       },
225         { QUEUE_INPUT_BUFFER,      "QUEUE_INPUT_BUFFER"      },
226         { RELEASE_OUTPUT_BUFFER,   "RELEASE_OUTPUT_BUFFER"   },
227         { RELEASE,                 "RELEASE"                 },
228         { GET_OUTPUT_BUFFER_USAGE, "GET_OUTPUT_BUFFER_USAGE" },
229         { SET_OUTPUT_BUFFER,       "SET_OUTPUT_BUFFER"       },
230         { GET_PACKED_CAPABILITY,   "GET_PACKED_CAPABILITY"   },
231         { SET_PACKED_INPUT_FLAG,   "SET_PACKED_INPUT_FLAG"   },
232         { CODEC_EVENT,             "CODEC_EVENT"             },
233         { OMX_EMPTY_BUFFER_DONE,   "OMX_EMPTY_BUFFER_DONE"   },
234         { OMX_FILL_BUFFER_DONE,    "OMX_FILL_BUFFER_DONE"    },
235         { CHECK_IF_STUCK,          "CHECK_IF_STUCK"          },
236         { FORCE_SHUTDOWN,          "FORCE_SHUTDOWN"          },
237     };
238     auto it = m.find(what);
239     if (it != m.end()) {
240         return it->second;
241     }
242     return "UNKNOWN";
243 }
244 
ReplyErrorCode(MsgId id,int32_t err)245 void ImageCodec::ReplyErrorCode(MsgId id, int32_t err)
246 {
247     if (id == ASYNC_MSG_ID) {
248         return;
249     }
250     ParamSP reply = make_shared<ParamBundle>();
251     reply->SetValue("err", err);
252     PostReply(id, reply);
253 }
254 
GetPixelFmtFromUser(const Format & format)255 bool ImageCodec::GetPixelFmtFromUser(const Format &format)
256 {
257     is10Bit_ = false;
258     optional<PixelFmt> fmt;
259     int32_t graphicFmt;
260     if (format.GetValue(ImageCodecDescriptionKey::PIXEL_FORMAT, graphicFmt)) {
261         if (!isPackedInputSupported_) {
262             if (graphicFmt == GRAPHIC_PIXEL_FMT_YCBCR_P010) {
263                 is10Bit_ = true;
264                 graphicFmt = GRAPHIC_PIXEL_FMT_YCBCR_420_SP;
265             } else if (graphicFmt == GRAPHIC_PIXEL_FMT_YCRCB_P010) {
266                 is10Bit_ = true;
267                 graphicFmt = GRAPHIC_PIXEL_FMT_YCRCB_420_SP;
268             }
269         }
270         fmt = TypeConverter::GraphicFmtToFmt(static_cast<GraphicPixelFormat>(graphicFmt));
271     } else {
272         HLOGE("pixel format unspecified");
273         return false;
274     }
275     if (!fmt.has_value()) {
276         HLOGE("pixel format unsupported");
277         return false;
278     }
279     configuredFmt_ = fmt.value();
280     HLOGI("configured pixel format is %{public}s", configuredFmt_.strFmt.c_str());
281     return true;
282 }
283 
GetFrameRateFromUser(const Format & format)284 optional<double> ImageCodec::GetFrameRateFromUser(const Format &format)
285 {
286     double frameRate;
287     if (format.GetValue(ImageCodecDescriptionKey::FRAME_RATE, frameRate) && frameRate > 0) {
288         LOGD("user set frame rate %{public}.2f", frameRate);
289         return frameRate;
290     }
291     return nullopt;
292 }
293 
SetFrameRateAdaptiveMode(const Format & format)294 int32_t ImageCodec::SetFrameRateAdaptiveMode(const Format &format)
295 {
296     if (!format.ContainKey(ImageCodecDescriptionKey::VIDEO_FRAME_RATE_ADAPTIVE_MODE)) {
297         return IC_ERR_UNKNOWN;
298     }
299 
300     WorkingFrequencyParam param {};
301     InitOMXParamExt(param);
302     if (!GetParameter(OMX_IndexParamWorkingFrequency, param)) {
303         HLOGW("get working freq param failed");
304         return IC_ERR_UNKNOWN;
305     }
306     HLOGI("level cnt is %{public}d, set level to %{public}d", param.level, param.level - 1);
307     param.level = param.level - 1;
308 
309     if (!SetParameter(OMX_IndexParamWorkingFrequency, param)) {
310         HLOGW("set working freq param failed");
311         return IC_ERR_UNKNOWN;
312     }
313     return IC_ERR_OK;
314 }
315 
SetProcessName(const Format & format)316 int32_t ImageCodec::SetProcessName(const Format &format)
317 {
318     string processName;
319     if (!format.GetValue(ImageCodecDescriptionKey::PROCESS_NAME, processName)) {
320         return IC_ERR_UNKNOWN;
321     }
322     HLOGI("processName name is %{public}s", processName.c_str());
323 
324     ProcessNameParam param {};
325     InitOMXParamExt(param);
326     if (strcpy_s(param.processName, sizeof(param.processName), processName.c_str()) != EOK) {
327         HLOGW("strcpy failed");
328         return IC_ERR_UNKNOWN;
329     }
330     if (!SetParameter(OMX_IndexParamProcessName, param)) {
331         HLOGW("set process name failed");
332         return IC_ERR_UNKNOWN;
333     }
334     return IC_ERR_OK;
335 }
336 
SetVideoPortInfo(OMX_DIRTYPE portIndex,const PortInfo & info)337 int32_t ImageCodec::SetVideoPortInfo(OMX_DIRTYPE portIndex, const PortInfo& info)
338 {
339     if (info.pixelFmt.has_value()) {
340         CodecVideoPortFormatParam param;
341         InitOMXParamExt(param);
342         param.portIndex = portIndex;
343         param.codecCompressFormat = info.codingType;
344         param.codecColorFormat = info.pixelFmt->graphicFmt;
345         param.framerate = info.frameRate * FRAME_RATE_COEFFICIENT;
346         if (!SetParameter(OMX_IndexCodecVideoPortFormat, param)) {
347             HLOGE("set port format failed");
348             return IC_ERR_UNKNOWN;
349         }
350     }
351     {
352         OMX_PARAM_PORTDEFINITIONTYPE def;
353         InitOMXParam(def);
354         def.nPortIndex = portIndex;
355         if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
356             HLOGE("get port definition failed");
357             return IC_ERR_UNKNOWN;
358         }
359         def.format.video.nFrameWidth = info.width;
360         def.format.video.nFrameHeight = info.height;
361         def.format.video.eCompressionFormat = info.codingType;
362         // we dont set eColorFormat here because it has been set by CodecVideoPortFormatParam
363         def.format.video.xFramerate = info.frameRate * FRAME_RATE_COEFFICIENT;
364         if (portIndex == OMX_DirInput && info.inputBufSize.has_value()) {
365             def.nBufferSize = info.inputBufSize.value();
366         }
367         if (info.bufferCnt.has_value()) {
368             def.nBufferCountActual = info.bufferCnt.value();
369         }
370         if (!SetParameter(OMX_IndexParamPortDefinition, def)) {
371             HLOGE("set port definition failed");
372             return IC_ERR_UNKNOWN;
373         }
374         if (portIndex == OMX_DirOutput) {
375             if (outputFormat_ == nullptr) {
376                 outputFormat_ = make_shared<Format>();
377             }
378             outputFormat_->SetValue(ImageCodecDescriptionKey::FRAME_RATE, info.frameRate);
379         }
380     }
381 
382     return (portIndex == OMX_DirInput) ? UpdateInPortFormat() : UpdateOutPortFormat();
383 }
384 
PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE & def)385 void ImageCodec::PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE& def)
386 {
387     const OMX_VIDEO_PORTDEFINITIONTYPE& video = def.format.video;
388     HLOGD("----- %{public}s port definition -----", (def.nPortIndex == OMX_DirInput) ? "INPUT" : "OUTPUT");
389     HLOGD("bEnabled %{public}d, bPopulated %{public}d", def.bEnabled, def.bPopulated);
390     HLOGD("nBufferCountActual %{public}u, nBufferSize %{public}u", def.nBufferCountActual, def.nBufferSize);
391     HLOGD("nFrameWidth x nFrameHeight (%{public}u x %{public}u), framerate %{public}u(%{public}.2f)",
392         video.nFrameWidth, video.nFrameHeight, video.xFramerate, video.xFramerate / FRAME_RATE_COEFFICIENT);
393     HLOGD("    nStride x nSliceHeight (%{public}u x %{public}u)", video.nStride, video.nSliceHeight);
394     HLOGD("eCompressionFormat %{public}d(%{public}#x), eColorFormat %{public}d(%{public}#x)",
395         video.eCompressionFormat, video.eCompressionFormat, video.eColorFormat, video.eColorFormat);
396     HLOGD("----------------------------------");
397 }
398 
GetPortDefinition(OMX_DIRTYPE portIndex,OMX_PARAM_PORTDEFINITIONTYPE & def)399 int32_t ImageCodec::GetPortDefinition(OMX_DIRTYPE portIndex, OMX_PARAM_PORTDEFINITIONTYPE& def)
400 {
401     InitOMXParam(def);
402     def.nPortIndex = portIndex;
403     if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
404         HLOGE("get %{public}s port definition failed", (portIndex == OMX_DirInput ? "input" : "output"));
405         return IC_ERR_INVALID_VAL;
406     }
407     if (def.nBufferSize == 0 || def.nBufferSize > MAX_IMAGE_CODEC_BUFFER_SIZE) {
408         HLOGE("invalid nBufferSize %{public}u", def.nBufferSize);
409         return IC_ERR_INVALID_VAL;
410     }
411     PrintPortDefinition(def);
412     return IC_ERR_OK;
413 }
414 
AllocateHardwareBuffers(OMX_DIRTYPE portIndex)415 int32_t ImageCodec::AllocateHardwareBuffers(OMX_DIRTYPE portIndex)
416 {
417     HeifPerfTracker tracker(__FUNCTION__);
418     OMX_PARAM_PORTDEFINITIONTYPE def;
419     int32_t ret = GetPortDefinition(portIndex, def);
420     IF_TRUE_RETURN_VAL(ret != IC_ERR_OK, ret);
421 
422     vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
423     pool.clear();
424     for (uint32_t i = 0; i < def.nBufferCountActual; ++i) {
425         shared_ptr<OmxCodecBuffer> omxBuffer = make_shared<OmxCodecBuffer>();
426         omxBuffer->size = sizeof(OmxCodecBuffer);
427         omxBuffer->version.version.majorVersion = 1;
428         omxBuffer->bufferType = CODEC_BUFFER_TYPE_DMA_MEM_FD;
429         omxBuffer->fd = -1;
430         omxBuffer->allocLen = def.nBufferSize;
431         omxBuffer->fenceFd = -1;
432         shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
433         ret = compNode_->AllocateBuffer(portIndex, *omxBuffer, *outBuffer);
434         if (ret != HDF_SUCCESS) {
435             HLOGE("Failed to AllocateBuffer on %{public}s port", (portIndex == OMX_DirInput ? "input" : "output"));
436             return IC_ERR_INVALID_VAL;
437         }
438         shared_ptr<ImageCodecBuffer> imgCodecBuffer = ImageCodecBuffer::CreateDmaBuffer(outBuffer->fd,
439             static_cast<int32_t>(def.nBufferSize), static_cast<int32_t>(def.format.video.nStride));
440         if (imgCodecBuffer == nullptr || imgCodecBuffer->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) {
441             HLOGE("AllocateHardwareBuffers failed");
442             return IC_ERR_NO_MEMORY;
443         }
444         BufferInfo bufInfo;
445         bufInfo.isInput        = (portIndex == OMX_DirInput) ? true : false;
446         bufInfo.owner          = BufferOwner::OWNED_BY_US;
447         bufInfo.surfaceBuffer  = nullptr;
448         bufInfo.imgCodecBuffer = imgCodecBuffer;
449         bufInfo.omxBuffer      = outBuffer;
450         bufInfo.bufferId       = outBuffer->bufferId;
451         bufInfo.CleanUpUnusedInfo();
452         pool.push_back(bufInfo);
453     }
454     return IC_ERR_OK;
455 }
456 
AllocateSurfaceBuffers(OMX_DIRTYPE portIndex,bool isOutputPortSettingChanged,sptr<SurfaceBuffer> output)457 int32_t ImageCodec::AllocateSurfaceBuffers(OMX_DIRTYPE portIndex, bool isOutputPortSettingChanged,
458                                            sptr<SurfaceBuffer> output)
459 {
460     HeifPerfTracker tracker(__FUNCTION__);
461     OMX_PARAM_PORTDEFINITIONTYPE def;
462     int32_t ret = GetPortDefinition(portIndex, def);
463     if (ret != IC_ERR_OK) {
464         return ret;
465     }
466     vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
467     pool.clear();
468     bool canReuseOutputBuffer = false;
469     if (isPackedInputSupported_) {
470         canReuseOutputBuffer = (output != nullptr);
471     } else {
472         canReuseOutputBuffer = (output != nullptr) && (!is10Bit_ || isOutputPortSettingChanged);
473     }
474     for (uint32_t i = 0; i < def.nBufferCountActual; ++i) {
475         shared_ptr<ImageCodecBuffer> imgCodecBuffer = canReuseOutputBuffer ?
476             ImageCodecBuffer::CreateSurfaceBuffer(output) : ImageCodecBuffer::CreateSurfaceBuffer(requestCfg_);
477         if (imgCodecBuffer == nullptr) {
478             HLOGE("AllocateSurfaceBuffers failed");
479             return IC_ERR_NO_MEMORY;
480         }
481         sptr<SurfaceBuffer> surfaceBuffer = imgCodecBuffer->GetSurfaceBuffer();
482         IF_TRUE_RETURN_VAL_WITH_MSG(surfaceBuffer == nullptr, IC_ERR_INVALID_VAL, "failed to get surfacebuffer");
483         shared_ptr<OmxCodecBuffer> omxBuffer = isEncoder_ ?
484             DynamicSurfaceBufferToOmxBuffer() : SurfaceBufferToOmxBuffer(surfaceBuffer);
485         IF_TRUE_RETURN_VAL(omxBuffer == nullptr, IC_ERR_INVALID_VAL);
486         shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
487         int32_t hdiRet = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer);
488         if (hdiRet != HDF_SUCCESS) {
489             HLOGE("Failed to UseBuffer on %{public}s port", (portIndex == OMX_DirInput ? "input" : "output"));
490             return IC_ERR_INVALID_VAL;
491         }
492         BufferInfo bufInfo;
493         bufInfo.isInput        = (portIndex == OMX_DirInput) ? true : false;
494         bufInfo.owner          = BufferOwner::OWNED_BY_US;
495         bufInfo.surfaceBuffer  = surfaceBuffer;
496         bufInfo.imgCodecBuffer = imgCodecBuffer;
497         bufInfo.omxBuffer      = outBuffer;
498         bufInfo.bufferId       = outBuffer->bufferId;
499         pool.push_back(bufInfo);
500     }
501 
502     return IC_ERR_OK;
503 }
504 
SurfaceBufferToOmxBuffer(const sptr<SurfaceBuffer> & surfaceBuffer)505 shared_ptr<OmxCodecBuffer> ImageCodec::SurfaceBufferToOmxBuffer(const sptr<SurfaceBuffer>& surfaceBuffer)
506 {
507     BufferHandle* bufferHandle = surfaceBuffer->GetBufferHandle();
508     IF_TRUE_RETURN_VAL_WITH_MSG(bufferHandle == nullptr, nullptr, "surfacebuffer has null bufferhandle");
509     auto omxBuffer = make_shared<OmxCodecBuffer>();
510     omxBuffer->size = sizeof(OmxCodecBuffer);
511     omxBuffer->version.version.majorVersion = 1;
512     omxBuffer->bufferType = CODEC_BUFFER_TYPE_HANDLE;
513     omxBuffer->bufferhandle = new NativeBuffer(bufferHandle);
514     omxBuffer->fd = -1;
515     omxBuffer->allocLen = surfaceBuffer->GetSize();
516     omxBuffer->fenceFd = -1;
517     return omxBuffer;
518 }
519 
DynamicSurfaceBufferToOmxBuffer()520 shared_ptr<OmxCodecBuffer> ImageCodec::DynamicSurfaceBufferToOmxBuffer()
521 {
522     auto omxBuffer = make_shared<OmxCodecBuffer>();
523     omxBuffer->size = sizeof(OmxCodecBuffer);
524     omxBuffer->version.version.majorVersion = 1;
525     omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
526     omxBuffer->fd = -1;
527     omxBuffer->allocLen = 0;
528     omxBuffer->fenceFd = -1;
529     return omxBuffer;
530 }
531 
FindBufferInfoByID(OMX_DIRTYPE portIndex,uint32_t bufferId)532 ImageCodec::BufferInfo* ImageCodec::FindBufferInfoByID(OMX_DIRTYPE portIndex, uint32_t bufferId)
533 {
534     vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
535     for (BufferInfo &info : pool) {
536         if (info.bufferId == bufferId) {
537             return &info;
538         }
539     }
540     HLOGE("unknown buffer id %{public}u", bufferId);
541     return nullptr;
542 }
543 
FindBufferIndexByID(OMX_DIRTYPE portIndex,uint32_t bufferId)544 optional<size_t> ImageCodec::FindBufferIndexByID(OMX_DIRTYPE portIndex, uint32_t bufferId)
545 {
546     const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
547     for (size_t i = 0; i < pool.size(); i++) {
548         if (pool[i].bufferId == bufferId) {
549             return i;
550         }
551     }
552     HLOGE("unknown buffer id %{public}u", bufferId);
553     return nullopt;
554 }
555 
NotifyUserToFillThisInBuffer(BufferInfo & info)556 void ImageCodec::NotifyUserToFillThisInBuffer(BufferInfo &info)
557 {
558     callback_->OnInputBufferAvailable(info.bufferId, info.imgCodecBuffer);
559     ChangeOwner(info, BufferOwner::OWNED_BY_USER);
560 }
561 
OnQueueInputBuffer(const MsgInfo & msg,BufferOperationMode mode)562 void ImageCodec::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode)
563 {
564     uint32_t bufferId;
565     (void)msg.param->GetValue(BUFFER_ID, bufferId);
566     BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId);
567     if (bufferInfo == nullptr) {
568         ReplyErrorCode(msg.id, IC_ERR_INVALID_VAL);
569         return;
570     }
571     if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) {
572         HLOGE("wrong ownership: buffer id=%{public}d, owner=%{public}s", bufferId, ToString(bufferInfo->owner));
573         ReplyErrorCode(msg.id, IC_ERR_INVALID_VAL);
574         return;
575     }
576     bufferInfo->imgCodecBuffer->GetBufferCirculateInfo(bufferInfo->omxBuffer->pts,
577                                                        bufferInfo->omxBuffer->flag,
578                                                        bufferInfo->omxBuffer->filledLen,
579                                                        bufferInfo->omxBuffer->offset);
580     ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US);
581     ReplyErrorCode(msg.id, IC_ERR_OK);
582     OnQueueInputBuffer(mode, bufferInfo);
583 }
584 
OnQueueInputBuffer(BufferOperationMode mode,BufferInfo * info)585 void ImageCodec::OnQueueInputBuffer(BufferOperationMode mode, BufferInfo* info)
586 {
587     switch (mode) {
588         case KEEP_BUFFER: {
589             return;
590         }
591         case RESUBMIT_BUFFER: {
592             if (inputPortEos_) {
593                 HLOGI("input already eos, keep this buffer");
594                 return;
595             }
596             bool eos = (info->omxBuffer->flag & OMX_BUFFERFLAG_EOS);
597             if (!eos && info->omxBuffer->filledLen == 0) {
598                 HLOGI("this is not a eos buffer but not filled, ask user to re-fill it");
599                 NotifyUserToFillThisInBuffer(*info);
600                 return;
601             }
602             if (eos) {
603                 inputPortEos_ = true;
604             }
605             int32_t ret = NotifyOmxToEmptyThisInBuffer(*info);
606             if (ret != IC_ERR_OK) {
607                 SignalError(IC_ERR_UNKNOWN);
608             }
609             return;
610         }
611         default: {
612             HLOGE("SHOULD NEVER BE HERE");
613             return;
614         }
615     }
616 }
617 
NotifyOmxToEmptyThisInBuffer(BufferInfo & info)618 int32_t ImageCodec::NotifyOmxToEmptyThisInBuffer(BufferInfo& info)
619 {
620     info.Dump(compUniqueStr_, dumpMode_);
621     info.EndCpuAccess();
622     int32_t ret = compNode_->EmptyThisBuffer(*(info.omxBuffer));
623     if (ret != HDF_SUCCESS) {
624         HLOGE("EmptyThisBuffer failed");
625         return IC_ERR_UNKNOWN;
626     }
627     ChangeOwner(info, BufferOwner::OWNED_BY_OMX);
628     return IC_ERR_OK;
629 }
630 
NotifyOmxToFillThisOutBuffer(BufferInfo & info)631 int32_t ImageCodec::NotifyOmxToFillThisOutBuffer(BufferInfo& info)
632 {
633     info.omxBuffer->flag = 0;
634     int32_t ret = compNode_->FillThisBuffer(*(info.omxBuffer));
635     if (ret != HDF_SUCCESS) {
636         HLOGE("outBufId = %{public}u failed", info.bufferId);
637         return IC_ERR_UNKNOWN;
638     }
639     ChangeOwner(info, BufferOwner::OWNED_BY_OMX);
640     return IC_ERR_OK;
641 }
642 
OnOMXFillBufferDone(const OmxCodecBuffer & omxBuffer,BufferOperationMode mode)643 void ImageCodec::OnOMXFillBufferDone(const OmxCodecBuffer& omxBuffer, BufferOperationMode mode)
644 {
645     optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, omxBuffer.bufferId);
646     if (!idx.has_value()) {
647         return;
648     }
649     BufferInfo& info = outputBufferPool_[idx.value()];
650     if (info.owner != BufferOwner::OWNED_BY_OMX) {
651         HLOGE("wrong ownership: buffer id=%{public}d, owner=%{public}s", info.bufferId, ToString(info.owner));
652         return;
653     }
654     info.omxBuffer->offset = omxBuffer.offset;
655     info.omxBuffer->filledLen = omxBuffer.filledLen;
656     info.omxBuffer->pts = omxBuffer.pts;
657     info.omxBuffer->flag = omxBuffer.flag;
658     ChangeOwner(info, BufferOwner::OWNED_BY_US);
659     OnOMXFillBufferDone(mode, info, idx.value());
660 }
661 
OnOMXFillBufferDone(BufferOperationMode mode,BufferInfo & info,size_t bufferIdx)662 void ImageCodec::OnOMXFillBufferDone(BufferOperationMode mode, BufferInfo& info, size_t bufferIdx)
663 {
664     switch (mode) {
665         case KEEP_BUFFER:
666             return;
667         case RESUBMIT_BUFFER: {
668             if (outputPortEos_) {
669                 HLOGI("output eos, keep this buffer");
670                 return;
671             }
672             bool eos = (info.omxBuffer->flag & OMX_BUFFERFLAG_EOS);
673             if (!eos && info.omxBuffer->filledLen == 0) {
674                 HLOGD("it's not a eos buffer but not filled, ask omx to re-fill it");
675                 NotifyOmxToFillThisOutBuffer(info);
676                 return;
677             }
678             NotifyUserOutBufferAvaliable(info);
679             if (eos) {
680                 outputPortEos_ = true;
681             }
682             return;
683         }
684         case FREE_BUFFER:
685             EraseBufferFromPool(OMX_DirOutput, bufferIdx);
686             return;
687         default:
688             HLOGE("SHOULD NEVER BE HERE");
689             return;
690     }
691 }
692 
NotifyUserOutBufferAvaliable(BufferInfo & info)693 void ImageCodec::NotifyUserOutBufferAvaliable(BufferInfo &info)
694 {
695     info.BeginCpuAccess();
696     info.Dump(compUniqueStr_, dumpMode_);
697     shared_ptr<OmxCodecBuffer> omxBuffer = info.omxBuffer;
698     info.imgCodecBuffer->SetBufferCirculateInfo(omxBuffer->pts, omxBuffer->flag,
699                                                 omxBuffer->filledLen, omxBuffer->offset);
700     callback_->OnOutputBufferAvailable(info.bufferId, info.imgCodecBuffer);
701     ChangeOwner(info, BufferOwner::OWNED_BY_USER);
702 }
703 
OnReleaseOutputBuffer(const MsgInfo & msg,BufferOperationMode mode)704 void ImageCodec::OnReleaseOutputBuffer(const MsgInfo &msg, BufferOperationMode mode)
705 {
706     uint32_t bufferId;
707     (void)msg.param->GetValue(BUFFER_ID, bufferId);
708     optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId);
709     if (!idx.has_value()) {
710         ReplyErrorCode(msg.id, IC_ERR_INVALID_VAL);
711         return;
712     }
713     BufferInfo& info = outputBufferPool_[idx.value()];
714     if (info.owner != BufferOwner::OWNED_BY_USER) {
715         HLOGE("wrong ownership: buffer id=%{public}d, owner=%{public}s", bufferId, ToString(info.owner));
716         ReplyErrorCode(msg.id, IC_ERR_INVALID_VAL);
717         return;
718     }
719     HLOGD("outBufId = %{public}u", bufferId);
720     ChangeOwner(info, BufferOwner::OWNED_BY_US);
721     ReplyErrorCode(msg.id, IC_ERR_OK);
722 
723     switch (mode) {
724         case KEEP_BUFFER: {
725             return;
726         }
727         case RESUBMIT_BUFFER: {
728             if (outputPortEos_) {
729                 HLOGI("output eos, keep this buffer");
730                 return;
731             }
732             int32_t ret = NotifyOmxToFillThisOutBuffer(info);
733             if (ret != IC_ERR_OK) {
734                 SignalError(IC_ERR_UNKNOWN);
735             }
736             return;
737         }
738         case FREE_BUFFER: {
739             EraseBufferFromPool(OMX_DirOutput, idx.value());
740             return;
741         }
742         default: {
743             HLOGE("SHOULD NEVER BE HERE");
744             return;
745         }
746     }
747 }
748 
ReclaimBuffer(OMX_DIRTYPE portIndex,BufferOwner owner,bool erase)749 void ImageCodec::ReclaimBuffer(OMX_DIRTYPE portIndex, BufferOwner owner, bool erase)
750 {
751     vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
752     for (size_t i = pool.size(); i > 0;) {
753         i--;
754         BufferInfo& info = pool[i];
755         if (info.owner == owner) {
756             ChangeOwner(info, BufferOwner::OWNED_BY_US);
757             if (erase) {
758                 EraseBufferFromPool(portIndex, i);
759             }
760         }
761     }
762 }
763 
IsAllBufferOwnedByUs(OMX_DIRTYPE portIndex)764 bool ImageCodec::IsAllBufferOwnedByUs(OMX_DIRTYPE portIndex)
765 {
766     const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
767     for (const BufferInfo& info : pool) {
768         if (info.owner != BufferOwner::OWNED_BY_US) {
769             return false;
770         }
771     }
772     return true;
773 }
774 
IsAllBufferOwnedByUs()775 bool ImageCodec::IsAllBufferOwnedByUs()
776 {
777     return IsAllBufferOwnedByUs(OMX_DirInput) && IsAllBufferOwnedByUs(OMX_DirOutput);
778 }
779 
EraseOutBuffersOwnedByUs()780 void ImageCodec::EraseOutBuffersOwnedByUs()
781 {
782     // traverse index in reverse order because we need to erase index from vector
783     for (size_t i = outputBufferPool_.size(); i > 0;) {
784         i--;
785         const BufferInfo& info = outputBufferPool_[i];
786         if (info.owner == BufferOwner::OWNED_BY_US) {
787             EraseBufferFromPool(OMX_DirOutput, i);
788         }
789     }
790 }
791 
ClearBufferPool(OMX_DIRTYPE portIndex)792 void ImageCodec::ClearBufferPool(OMX_DIRTYPE portIndex)
793 {
794     const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
795     for (size_t i = pool.size(); i > 0;) {
796         i--;
797         EraseBufferFromPool(portIndex, i);
798     }
799 }
800 
FreeOmxBuffer(OMX_DIRTYPE portIndex,const BufferInfo & info)801 void ImageCodec::FreeOmxBuffer(OMX_DIRTYPE portIndex, const BufferInfo& info)
802 {
803     if (compNode_ && info.omxBuffer) {
804         int32_t omxRet = compNode_->FreeBuffer(portIndex, *(info.omxBuffer));
805         if (omxRet != HDF_SUCCESS) {
806             HLOGW("notify omx to free buffer failed");
807         }
808     }
809 }
810 
DoSyncCall(MsgWhat msgType,function<void (ParamSP)> oper)811 int32_t ImageCodec::DoSyncCall(MsgWhat msgType, function<void(ParamSP)> oper)
812 {
813     ParamSP reply;
814     return DoSyncCallAndGetReply(msgType, oper, reply);
815 }
816 
DoSyncCallAndGetReply(MsgWhat msgType,function<void (ParamSP)> oper,ParamSP & reply)817 int32_t ImageCodec::DoSyncCallAndGetReply(MsgWhat msgType, function<void(ParamSP)> oper, ParamSP &reply)
818 {
819     ParamSP msg = make_shared<ParamBundle>();
820     IF_TRUE_RETURN_VAL_WITH_MSG(msg == nullptr, IC_ERR_NO_MEMORY, "out of memory");
821     if (oper) {
822         oper(msg);
823     }
824     bool ret = MsgHandleLoop::SendSyncMsg(msgType, msg, reply);
825     IF_TRUE_RETURN_VAL_WITH_MSG(!ret, IC_ERR_UNKNOWN, "wait msg %{public}d time out", msgType);
826     int32_t err;
827     IF_TRUE_RETURN_VAL_WITH_MSG(reply == nullptr || !reply->GetValue("err", err),
828         IC_ERR_UNKNOWN, "error code of msg %{public}d not replied", msgType);
829     return err;
830 }
831 
ChangeOmxToTargetState(CodecStateType & state,CodecStateType targetState)832 void ImageCodec::ChangeOmxToTargetState(CodecStateType &state, CodecStateType targetState)
833 {
834     int32_t ret = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, targetState, {});
835     if (ret != HDF_SUCCESS) {
836         HLOGE("failed to change omx state, ret=%{public}d", ret);
837         return;
838     }
839 
840     int tryCnt = 0;
841     do {
842         if (tryCnt++ > 10) { // try up to 10 times
843             HLOGE("failed to change to state(%{public}d), abort", targetState);
844             state = CODEC_STATE_INVALID;
845             break;
846         }
847         this_thread::sleep_for(10ms); // wait 10ms
848         ret = compNode_->GetState(state);
849         if (ret != HDF_SUCCESS) {
850             HLOGE("failed to get omx state, ret=%{public}d", ret);
851         }
852     } while (ret == HDF_SUCCESS && state != targetState && state != CODEC_STATE_INVALID);
853 }
854 
RollOmxBackToLoaded()855 bool ImageCodec::RollOmxBackToLoaded()
856 {
857     CodecStateType state;
858     int32_t ret = compNode_->GetState(state);
859     if (ret != HDF_SUCCESS) {
860         HLOGE("failed to get omx node status(ret=%{public}d), can not perform state rollback", ret);
861         return false;
862     }
863     HLOGI("current omx state (%{public}d)", state);
864     switch (state) {
865         case CODEC_STATE_EXECUTING: {
866             ChangeOmxToTargetState(state, CODEC_STATE_IDLE);
867             [[fallthrough]];
868         }
869         case CODEC_STATE_IDLE: {
870             ChangeOmxToTargetState(state, CODEC_STATE_LOADED);
871             [[fallthrough]];
872         }
873         case CODEC_STATE_LOADED:
874         case CODEC_STATE_INVALID: {
875             return true;
876         }
877         default: {
878             HLOGE("invalid omx state: %{public}d", state);
879             return false;
880         }
881     }
882 }
883 
CleanUpOmxNode()884 void ImageCodec::CleanUpOmxNode()
885 {
886     if (compNode_ == nullptr) {
887         return;
888     }
889 
890     if (RollOmxBackToLoaded()) {
891         for (const BufferInfo& info : inputBufferPool_) {
892             FreeOmxBuffer(OMX_DirInput, info);
893         }
894         for (const BufferInfo& info : outputBufferPool_) {
895             FreeOmxBuffer(OMX_DirOutput, info);
896         }
897     }
898 }
899 
ReleaseComponent()900 void ImageCodec::ReleaseComponent()
901 {
902     CleanUpOmxNode();
903     if (compMgr_ != nullptr) {
904         compMgr_->DestroyComponent(componentId_);
905     }
906     compNode_ = nullptr;
907     compCb_ = nullptr;
908     compMgr_ = nullptr;
909     componentId_ = 0;
910     componentName_.clear();
911 }
912 
ForceShutdown(int32_t generation)913 int32_t ImageCodec::ForceShutdown(int32_t generation)
914 {
915     if (generation != stateGeneration_) {
916         HLOGE("ignoring stale force shutdown message: #%{public}d (now #%{public}d)",
917             generation, stateGeneration_);
918         return IC_ERR_OK;
919     }
920     HLOGI("force to shutdown");
921     isShutDownFromRunning_ = true;
922     notifyCallerAfterShutdownComplete_ = false;
923     auto err = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
924     if (err == HDF_SUCCESS) {
925         ChangeStateTo(stoppingState_);
926     }
927     return IC_ERR_OK;
928 }
929 
SignalError(ImageCodecError err)930 void ImageCodec::SignalError(ImageCodecError err)
931 {
932     HLOGE("fatal error happened: errCode=%{public}d", err);
933     hasFatalError_ = true;
934     callback_->OnError(err);
935 }
936 
DeferMessage(const MsgInfo & info)937 void ImageCodec::DeferMessage(const MsgInfo &info)
938 {
939     deferredQueue_.push_back(info);
940 }
941 
ProcessDeferredMessages()942 void ImageCodec::ProcessDeferredMessages()
943 {
944     for (const MsgInfo &info : deferredQueue_) {
945         StateMachine::OnMsgReceived(info);
946     }
947     deferredQueue_.clear();
948 }
949 
ReplyToSyncMsgLater(const MsgInfo & msg)950 void ImageCodec::ReplyToSyncMsgLater(const MsgInfo& msg)
951 {
952     syncMsgToReply_[msg.type].push(make_pair(msg.id, msg.param));
953 }
954 
GetFirstSyncMsgToReply(MsgInfo & msg)955 bool ImageCodec::GetFirstSyncMsgToReply(MsgInfo& msg)
956 {
957     auto iter = syncMsgToReply_.find(msg.type);
958     if (iter == syncMsgToReply_.end()) {
959         return false;
960     }
961     tie(msg.id, msg.param) = iter->second.front();
962     iter->second.pop();
963     return true;
964 }
965 
966 /**************************** HdiCallback functions begin ****************************/
EventHandler(CodecEventType event,const EventInfo & info)967 int32_t ImageCodec::HdiCallback::EventHandler(CodecEventType event, const EventInfo &info)
968 {
969     LOGD("event = %{public}d, data1 = %{public}u, data2 = %{public}u", event, info.data1, info.data2);
970     ParamSP msg = make_shared<ParamBundle>();
971     msg->SetValue("event", event);
972     msg->SetValue("data1", info.data1);
973     msg->SetValue("data2", info.data2);
974     codec_->SendAsyncMsg(MsgWhat::CODEC_EVENT, msg);
975     return HDF_SUCCESS;
976 }
977 
EmptyBufferDone(int64_t appData,const OmxCodecBuffer & buffer)978 int32_t ImageCodec::HdiCallback::EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer)
979 {
980     ParamSP msg = make_shared<ParamBundle>();
981     msg->SetValue(BUFFER_ID, buffer.bufferId);
982     codec_->SendAsyncMsg(MsgWhat::OMX_EMPTY_BUFFER_DONE, msg);
983     return HDF_SUCCESS;
984 }
985 
FillBufferDone(int64_t appData,const OmxCodecBuffer & buffer)986 int32_t ImageCodec::HdiCallback::FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer)
987 {
988     ParamSP msg = make_shared<ParamBundle>();
989     msg->SetValue("omxBuffer", buffer);
990     codec_->SendAsyncMsg(MsgWhat::OMX_FILL_BUFFER_DONE, msg);
991     return HDF_SUCCESS;
992 }
993 /**************************** HdiCallback functions begin ****************************/
994 
995 /**************************** BufferInfo functions begin ****************************/
CleanUpUnusedInfo()996 void ImageCodec::BufferInfo::CleanUpUnusedInfo()
997 {
998     if (omxBuffer == nullptr || omxBuffer->fd < 0) {
999         return;
1000     }
1001     if (omxBuffer->fd == 0) {
1002         LOGW("fd of omxbuffer should never be 0");
1003     }
1004     close(omxBuffer->fd);
1005     omxBuffer->fd = -1;
1006 }
1007 
BeginCpuAccess()1008 void ImageCodec::BufferInfo::BeginCpuAccess()
1009 {
1010     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
1011         GSError err = surfaceBuffer->InvalidateCache();
1012         if (err != GSERROR_OK) {
1013             LOGW("InvalidateCache failed, GSError=%{public}d", err);
1014         }
1015     }
1016 }
1017 
EndCpuAccess()1018 void ImageCodec::BufferInfo::EndCpuAccess()
1019 {
1020     if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
1021         GSError err = surfaceBuffer->Map();
1022         if (err != GSERROR_OK) {
1023             LOGW("Map failed, GSError=%{public}d", err);
1024             return;
1025         }
1026         err = surfaceBuffer->FlushCache();
1027         if (err != GSERROR_OK) {
1028             LOGW("FlushCache failed, GSError=%{public}d", err);
1029         }
1030     }
1031 }
1032 /**************************** BufferInfo functions end ****************************/
1033 } // namespace OHOS::ImagePlugin