1 /* 2 * Copyright (C) 2021 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 #ifndef RECORDER_ELEMENT_H 17 #define RECORDER_ELEMENT_H 18 19 #include <memory> 20 #include <unordered_map> 21 #include <type_traits> 22 #include <mutex> 23 #include <set> 24 #include <gst/gstelement.h> 25 #include "nocopyable.h" 26 #include "recorder_param.h" 27 #include "recorder_inner_defines.h" 28 #include "recorder_message_handler.h" 29 #include "avcodec_ability_singleton.h" 30 31 namespace OHOS { 32 namespace Media { 33 class RecorderElement : public RecorderMsgHandler { 34 public: 35 struct CreateParam { 36 // The source element's description that this element uniquely dependents to. 37 // For multiplexer, the description is invalid. 38 RecorderSourceDesc srcDesc; 39 std::string name; 40 }; 41 42 explicit RecorderElement(const CreateParam &createParam); 43 virtual ~RecorderElement(); 44 45 /** 46 * @brief Get this element's sourceId 47 * @return sourceId. 48 */ GetSourceId()49 inline int32_t GetSourceId() const 50 { 51 return desc_.handle_; 52 } 53 54 /** 55 * @brief Get this element's name 56 * @return sourceId. 57 */ GetName()58 inline std::string GetName() const 59 { 60 return name_; 61 } 62 63 /** 64 * @brief Initialize the element after it created. 65 * @return MSERR_OK if success, or failed. 66 */ 67 virtual int32_t Init() = 0; 68 69 /** 70 * @brief Configure the element. This will be called before CheckConfigReady. 71 * @param recParam: RecorderParam, this is the base type of specific type's recorder parameter. 72 * @return MSERR_OK if success, or failed. 73 */ Configure(const RecorderParam & recParam)74 virtual int32_t Configure(const RecorderParam &recParam) 75 { 76 (void)recParam; 77 return MSERR_OK; 78 } 79 80 /** 81 * @brief This interface will be called before Prepare to ensure that all static recorder parameters required 82 * by this element are configured completely. 83 * @return MSERR_OK if success, or failed. 84 */ CheckConfigReady()85 virtual int32_t CheckConfigReady() 86 { 87 return MSERR_OK; 88 } 89 90 /** 91 * @brief This interface is invoked before the corresponding gstreamer element's state changed from NULL to 92 * PAUSED, and during the process when the RecorderPipeline's Prepare invoked. 93 * @return MSERR_OK if success, or failed. 94 */ Prepare()95 virtual int32_t Prepare() 96 { 97 return MSERR_OK; 98 } 99 100 /** 101 * @brief This interface is invoked before the corresponding gstreamer element's state changed from PAUSED to 102 * PLAYING. and during the process when the RecorderPipeline's Start invoked. 103 * @return MSERR_OK if success, or failed. 104 */ Start()105 virtual int32_t Start() 106 { 107 return MSERR_OK; 108 } 109 110 /** 111 * @brief This interface is invoked before the corresponding gstreamer element's state changed from PLAYING to 112 * PAUSED. and during the process when the RecorderPipeline's Pause invoked. 113 * @return MSERR_OK if success, or failed. 114 */ Pause()115 virtual int32_t Pause() 116 { 117 return MSERR_OK; 118 } 119 120 /** 121 * @brief This interface is invoked before the corresponding gstreamer element's state changed from PAUSED to 122 * PLAYING. and during the process when the RecorderPipeline's Resume invoked. 123 * @return MSERR_OK if success, or failed. 124 */ Resume()125 virtual int32_t Resume() 126 { 127 return MSERR_OK; 128 } 129 130 /** 131 * @brief This interface is invoked before the Stop interface called. The components could send EOS event to 132 * relevant gstreamer element through this interface to only drain out all itself cached buffer before changing 133 * state to NULL. It is designed to speed up the whole pipeline's stopping process. If the user requires a fast 134 * stop, the components could firstly send FLUSH event to relevant gstreamer element. The upper layer will decide 135 * to whether need to wait the GST_MESSAGE_EOS according to this interface's return value. 136 * @return MSERR_OK if success, or failed. 137 */ 138 int32_t DrainAll(bool isDrain); 139 140 /** 141 * @brief This interface is invoked before the corresponding gstreamer element's state changed from PLAYING or 142 * PAUSED to NULL. and during the process when the RecorderPipeline's Stop invoked. 143 * @return MSERR_OK if success, or failed. 144 */ Stop()145 virtual int32_t Stop() 146 { 147 return MSERR_OK; 148 } 149 150 /** 151 * @brief This interface is invoked during the process when the RecorderPipeline's Reset invoked. 152 * @return MSERR_OK if success, or failed. 153 */ Reset()154 virtual int32_t Reset() 155 { 156 return MSERR_OK; 157 } 158 159 /** 160 * @brief Set dynamic parameter to this element, this will be called after Prepare and before Stop 161 * @param recParam: RecorderParam, this is the base type of specific type's recorder parameter. 162 * @return MSERR_OK if success, or failed. 163 */ SetParameter(const RecorderParam & recParam)164 virtual int32_t SetParameter(const RecorderParam &recParam) 165 { 166 (void)recParam; 167 return MSERR_OK; 168 } 169 170 /** 171 * @brief Get Parameter of this elements 172 * @param recParam: RecorderParam, this is the base type of specific type's recorder parameter. 173 * @return MSERR_OK if success, or failed. 174 */ GetParameter(RecorderParam & recParam)175 virtual int32_t GetParameter(RecorderParam &recParam) 176 { 177 (void)recParam; 178 return MSERR_OK; 179 } 180 181 /** 182 * @brief Process raw message from gstreamer's element to inner message format. 183 * @param msg: GstMessage, this is the raw message from gstreamer 184 * @param prettyMsg: RecorderMessage, this is the processed result 185 * @return see @RecorderMsgProcResult 186 */ 187 RecorderMsgProcResult OnMessageReceived(GstMessage &rawMsg, RecorderMessage &prettyMsg) final; 188 189 /** 190 * @brief Dump all dynamic or static configuration info. 191 */ Dump()192 virtual void Dump() {} 193 194 protected: 195 /** 196 * @brief Mark one parameter successfully configured to this element. 197 * @param paramType: the enum value of RecorderParamType 198 * @return None. 199 */ MarkParameter(int32_t paramType)200 void MarkParameter(int32_t paramType) 201 { 202 (void)configuredParams_.insert(paramType); 203 } 204 205 /** 206 * @brief Check whether the specified type's parameter is configured. 207 * @param paramType: the enum value of RecorderParamType 208 * @return true if configured, false if not configured. 209 */ CheckParameter(int32_t paramType)210 bool CheckParameter(int32_t paramType) const 211 { 212 return configuredParams_.find(paramType) != configuredParams_.end(); 213 } 214 215 /** 216 * @brief Check whether the all specified type's parameters is configured. 217 * @param expectedParams: the enum value set of RecorderParamType 218 * @return true if all specified type's parameters configured, false if not all. 219 */ 220 bool CheckAllParamsConfigured(const std::set<int32_t> &expectedParams) const; 221 222 /** 223 * @brief Check whether the any one specified type's parameters is configured. 224 * @param expectedParams: the enum value set of RecorderParamType 225 * @return true if any one specified type's parameters configured, false if no one. 226 */ 227 bool CheckAnyParamConfiged(const std::set<int32_t> &expectedParams) const; 228 229 /** 230 * @brief Subclass implement to process the raw message from gstreamer's element 231 * @param msg: GstMessage, this is the raw message from gstreamer 232 * @param prettyMsg: RecorderMessage, this is the processed result 233 * @return see @RecorderMsgProcResult 234 */ DoProcessMessage(GstMessage & msg,RecorderMessage & prettyMsg)235 virtual RecorderMsgProcResult DoProcessMessage(GstMessage &msg, RecorderMessage &prettyMsg) 236 { 237 (void)msg; 238 (void)prettyMsg; 239 return RecorderMsgProcResult::REC_MSG_PROC_IGNORE; 240 } 241 242 /** 243 * @brief Judge whether value is within the valid range 244 * @param range: Reasonable value range 245 * @param value: Value to be judged 246 * @return If the value is valid, return true, otherwise return false 247 */ 248 bool CheckRangeValid(Range &range, int32_t value); 249 250 friend class RecorderPipelineLinkHelper; 251 252 RecorderSourceDesc desc_; 253 std::string name_; 254 GstElement *gstElem_ = nullptr; 255 256 private: 257 std::set<int32_t> configuredParams_; 258 }; 259 260 /** 261 * @brief Provides the factory to register the derived class instantiation method and 262 * create the RecorderElement instance. 263 */ 264 class RecorderElementFactory { 265 public: GetInstance()266 static RecorderElementFactory &GetInstance() 267 { 268 static RecorderElementFactory inst; 269 return inst; 270 } 271 272 using ElementCreator = std::function<std::shared_ptr<RecorderElement>(const RecorderElement::CreateParam&)>; 273 274 int32_t RegisterElement(const std::string &key, const ElementCreator creator); 275 std::shared_ptr<RecorderElement> CreateElement(const std::string &key, const RecorderElement::CreateParam ¶m); 276 277 private: 278 RecorderElementFactory() = default; 279 ~RecorderElementFactory() = default; 280 281 std::unordered_map<std::string, ElementCreator> creatorTbl_; 282 std::mutex tblMutex_; 283 }; 284 285 template<typename T, 286 typename = std::enable_if_t<std::is_base_of_v<RecorderElement, std::decay_t<T>>>> 287 class RecorderElementRegister : public NoCopyable { 288 public: RecorderElementRegister(const std::string & key)289 explicit RecorderElementRegister(const std::string &key) 290 { 291 (void)RecorderElementFactory::GetInstance().RegisterElement( 292 key, [](const RecorderElement::CreateParam ¶m) { 293 return std::make_shared<std::decay_t<T>>(param); 294 } 295 ); 296 } 297 298 ~RecorderElementRegister() = default; 299 }; 300 301 /** 302 * @brief Provides the RecorderElement register macro to simplify the registration. 303 */ 304 #define REGISTER_RECORDER_ELEMENT(__classname__) \ 305 static std::shared_ptr<RecorderElementRegister<__classname__>> g_##__classname__##register = \ 306 std::make_shared<RecorderElementRegister<__classname__>>(#__classname__) 307 } // namespace Media 308 } // namespace OHOS 309 #endif 310