• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param);
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 &param) {
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