1 /*
2 * Copyright (c) 2023-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 #if defined(VIDEO_SUPPORT)
16
17 #define HST_LOG_TAG "CodecCmdExecutor"
18
19 #include "codec_cmd_executor.h"
20 #include "codec_utils.h"
21 #include "foundation/log.h"
22 #include "hdf_base.h"
23
24 namespace OHOS {
25 namespace Media {
26 namespace Plugin {
27 namespace CodecAdapter {
CodecCmdExecutor(CodecComponentType * component,uint32_t inPortIndex)28 CodecCmdExecutor::CodecCmdExecutor(CodecComponentType* component, uint32_t inPortIndex)
29 : codecComp_(component), inPortIndex_(inPortIndex)
30 {
31 resultMap_[OMX_CommandStateSet] = OMX_StateInvalid;
32 resultMap_[OMX_CommandFlush] = std::pair<Result, Result>{Result::INVALID, Result::INVALID};
33 resultMap_[OMX_CommandPortEnable] = std::pair<Result, Result>{Result::INVALID, Result::INVALID};
34 resultMap_[OMX_CommandPortDisable] = std::pair<Result, Result>{Result::INVALID, Result::INVALID};
35 }
36
OnEvent(OMX_EVENTTYPE event,EventInfo * info)37 Status CodecCmdExecutor::OnEvent(OMX_EVENTTYPE event, EventInfo* info)
38 {
39 MEDIA_LOG_I("OnEvent begin - eEvent: " PUBLIC_LOG_D32 ", nData1: " PUBLIC_LOG_U32 ", nData2: " PUBLIC_LOG_U32,
40 static_cast<int>(event), info->data1, info->data2);
41 switch (event) {
42 case OMX_EventCmdComplete:
43 HandleEventCmdComplete(info->data1, info->data2); // data2 indicates a state
44 break;
45 case OMX_EventPortSettingsChanged:
46 HandleEventPortSettingsChanged(info->data1, info->data2);
47 break;
48 case OMX_EventBufferFlag:
49 HandleEventBufferFlag(info->data1, info->data2);
50 break;
51 case OMX_EventError:
52 HandleEventError(info->data1, info->data2);
53 break;
54 default:
55 break;
56 }
57 MEDIA_LOG_D("OnEvent end");
58 return Status::OK;
59 }
60
SendCmd(OMX_COMMANDTYPE cmd,const Plugin::Any & param)61 Status CodecCmdExecutor::SendCmd(OMX_COMMANDTYPE cmd, const Plugin::Any& param)
62 {
63 MEDIA_LOG_D("SendCmd Start");
64 switch (cmd) {
65 case OMX_CommandStateSet: {
66 resultMap_[cmd] = OMX_StateInvalid;
67 auto ret = HdiSendCommand(codecComp_, cmd, Plugin::AnyCast<OMX_STATETYPE>(param), 0);
68 FALSE_RETURN_V_MSG(ret == HDF_SUCCESS, Status::ERROR_INVALID_OPERATION, "HdiSendCommand failed");
69 break;
70 }
71 case OMX_CommandFlush: {
72 uint32_t portIndex;
73 if (Plugin::Any::IsSameTypeWith<int32_t >(param) && Plugin::AnyCast<int32_t>(param) == -1) {
74 portIndex = static_cast<uint32_t>(-1);
75 } else {
76 portIndex = Plugin::AnyCast<uint32_t>(param);
77 }
78 auto ret = HdiSendCommand(codecComp_, cmd, portIndex, 0);
79 FALSE_RETURN_V_MSG(ret == HDF_SUCCESS, Status::ERROR_INVALID_OPERATION, "HdiSendCommand failed");
80 break;
81 }
82 case OMX_CommandPortEnable:
83 case OMX_CommandPortDisable: {
84 auto ret = HdiSendCommand(codecComp_, cmd, Plugin::AnyCast<uint32_t>(param), 0);
85 FALSE_RETURN_V_MSG(ret == HDF_SUCCESS, Status::ERROR_INVALID_OPERATION, "HdiSendCommand failed");
86 break;
87 }
88 default:
89 break;
90 }
91 return Status::OK;
92 }
93
WaitCmdResult(OMX_COMMANDTYPE cmd,const Plugin::Any & param)94 bool CodecCmdExecutor::WaitCmdResult(OMX_COMMANDTYPE cmd, const Plugin::Any& param)
95 {
96 OSAL::ScopedLock lock(mutex_);
97 MEDIA_LOG_D("WaitCmdResult lastCmd: " PUBLIC_LOG_D32 ", cmd:" PUBLIC_LOG_D32, lastCmd_, static_cast<int32_t>(cmd));
98 bool result {true};
99 static constexpr int32_t timeout = 2000; // ms
100 switch (cmd) {
101 case OMX_CommandStateSet: {
102 cond_.WaitFor(lock, timeout, [&] {
103 if (lastCmd_ == -1) {
104 resultMap_[cmd] = OMX_StateInvalid;
105 result = false;
106 return true;
107 }
108 return Plugin::AnyCast<OMX_STATETYPE>(resultMap_[cmd]) == AnyCast<OMX_STATETYPE>(param);
109 });
110 return result;
111 }
112 case OMX_CommandFlush:
113 case OMX_CommandPortEnable:
114 case OMX_CommandPortDisable: {
115 auto portIndex = AnyCast<uint32_t>(param);
116 cond_.WaitFor(lock, timeout, [&] {
117 auto tempPair = AnyCast<std::pair<Result, Result>>(resultMap_[cmd]);
118 if (lastCmd_ == -1) {
119 if (portIndex == inPortIndex_) {
120 resultMap_[cmd] = std::pair<Result, Result>{Result::FAIL, tempPair.second};
121 } else {
122 resultMap_[cmd] = std::pair<Result, Result>{tempPair.second, Result::FAIL};
123 }
124 result = false;
125 return true;
126 }
127 if (portIndex == inPortIndex_) {
128 if (tempPair.first != Result::INVALID) {
129 resultMap_[cmd] = std::pair<Result, Result>{Result::INVALID, tempPair.second};
130 }
131 return tempPair.first == Result::SUCCESS;
132 } else {
133 if (tempPair.second != Result::INVALID) {
134 resultMap_[cmd] = std::pair<Result, Result>{tempPair.second, Result::INVALID};
135 }
136 return tempPair.second == Result::SUCCESS;
137 }
138 });
139 return result;
140 }
141 default:
142 return true;
143 }
144 }
145
SetCallback(Callback * cb)146 Status CodecCmdExecutor::SetCallback(Callback* cb)
147 {
148 callback_ = cb;
149 return Status::OK;
150 }
151
HandleEventCmdComplete(uint32_t data1,uint32_t data2)152 void CodecCmdExecutor::HandleEventCmdComplete(uint32_t data1, uint32_t data2)
153 {
154 MEDIA_LOG_D("HandleEventCmdComplete begin");
155 OSAL::ScopedLock lock(mutex_);
156 auto cmd = static_cast<OMX_COMMANDTYPE>(data1);
157 switch (data1) {
158 case OMX_CommandStateSet:
159 resultMap_[cmd] = static_cast<OMX_STATETYPE>(data2);
160 break;
161 case OMX_CommandFlush:
162 case OMX_CommandPortEnable:
163 case OMX_CommandPortDisable: {
164 auto tempPair = AnyCast<std::pair<Result, Result>>(resultMap_[cmd]);
165 if (data2 == inPortIndex_) {
166 resultMap_[cmd] = std::pair<Result, Result>{Result::SUCCESS, tempPair.second};
167 } else {
168 resultMap_[cmd] = std::pair<Result, Result>{tempPair.second, Result::SUCCESS};
169 }
170 break;
171 }
172 default:
173 break;
174 }
175 lastCmd_ = static_cast<int32_t>(cmd);
176 cond_.NotifyAll();
177 MEDIA_LOG_D("HandelCmdCompleteEvent end");
178 }
179
HandleEventPortSettingsChanged(OMX_U32 data1,OMX_U32 data2)180 void CodecCmdExecutor::HandleEventPortSettingsChanged(OMX_U32 data1, OMX_U32 data2)
181 {
182 MEDIA_LOG_I("HandleEventPortSettingsChanged begin");
183 OSAL::ScopedLock lock(mutex_);
184 }
185
HandleEventBufferFlag(OMX_U32 data1,OMX_U32 data2)186 void CodecCmdExecutor::HandleEventBufferFlag(OMX_U32 data1, OMX_U32 data2)
187 {
188 MEDIA_LOG_I("HandleEventBufferFlag begin");
189 OSAL::ScopedLock lock(mutex_);
190 if (data1 == 1 && (data2 & OMX_BUFFERFLAG_EOS)) {
191 MEDIA_LOG_D("it is eos, wait buffer eos");
192 }
193 }
194
HandleEventError(OMX_U32 data1,OMX_U32 data2)195 void CodecCmdExecutor::HandleEventError(OMX_U32 data1, OMX_U32 data2)
196 {
197 {
198 OSAL::ScopedLock lock(mutex_);
199 lastCmd_ = -1;
200 cond_.NotifyAll();
201 }
202 // Sometimes, hdi return data1 does not indicate an OMX_ERRORTYPE, call OmxErrorType2String() return OMX_ErrorNone
203 auto errorType = OmxErrorType2String(data1);
204 MEDIA_LOG_E("HandleEventError begin, error msg: " PUBLIC_LOG_S, errorType.c_str());
205 if (errorType == "OMX_ErrorNone" && static_cast<OMX_INDEXTYPE>(data2) == OMX_IndexParamPortDefinition) {
206 if (data1 == inPortIndex_) {
207 MEDIA_LOG_E("Unknown error on input port");
208 } else {
209 MEDIA_LOG_E("Input data does not contain keyframes, unable to obtain output data.");
210 }
211 }
212 }
213 } // namespace CodecAdapter
214 } // namespace Plugin
215 } // namespace Media
216 } // namespace OHOS
217 #endif