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