• 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 #include "recorder_element.h"
17 #include <algorithm>
18 #include <iterator>
19 #include "media_errors.h"
20 #include "media_log.h"
21 #include "recorder_private_param.h"
22 
23 namespace {
24 using namespace OHOS::Media;
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "RecorderElement"};
26 #define PARAM_TYPE_NAME_ITEM(paramType, captionString) { paramType, captionString }
27 static const std::unordered_map<uint32_t, std::string> PARAM_TYPE_NAME_MAP = {
28     PARAM_TYPE_NAME_ITEM(VID_ENC_FMT, "video encode format"),
29     PARAM_TYPE_NAME_ITEM(VID_RECTANGLE, "video size"),
30     PARAM_TYPE_NAME_ITEM(VID_BITRATE, "video bitrate"),
31     PARAM_TYPE_NAME_ITEM(VID_FRAMERATE, "video framerate"),
32     PARAM_TYPE_NAME_ITEM(VID_CAPTURERATE, "video capture rate"),
33     PARAM_TYPE_NAME_ITEM(AUD_ENC_FMT, "audio encode format"),
34     PARAM_TYPE_NAME_ITEM(AUD_SAMPLERATE, "audio samplerate"),
35     PARAM_TYPE_NAME_ITEM(AUD_CHANNEL, "audio channels"),
36     PARAM_TYPE_NAME_ITEM(AUD_BITRATE, "audio bitrate"),
37     PARAM_TYPE_NAME_ITEM(MAX_DURATION, "max record duration"),
38     PARAM_TYPE_NAME_ITEM(MAX_SIZE, "max record size"),
39     PARAM_TYPE_NAME_ITEM(OUT_FD, "out file descripter"),
40     PARAM_TYPE_NAME_ITEM(NEXT_OUT_FD, "next out file descripter"),
41     PARAM_TYPE_NAME_ITEM(OUTPUT_FORMAT, "output file format"),
42 };
43 }
44 
45 namespace OHOS {
46 namespace Media {
RegisterElement(const std::string & key,const ElementCreator creator)47 int32_t RecorderElementFactory::RegisterElement(const std::string &key, const ElementCreator creator)
48 {
49     std::unique_lock<std::mutex> lock(tblMutex_);
50     if (creatorTbl_.find(key) != creatorTbl_.end()) {
51         MEDIA_LOGE("key %{public}s already registered !", key.c_str());
52         return MSERR_INVALID_OPERATION;
53     }
54 
55     (void)creatorTbl_.emplace(key, creator);
56     return MSERR_OK;
57 }
58 
CreateElement(const std::string & key,const RecorderElement::CreateParam & param)59 std::shared_ptr<RecorderElement> RecorderElementFactory::CreateElement(
60     const std::string &key, const RecorderElement::CreateParam &param)
61 {
62     std::shared_ptr<RecorderElement> elem;
63     {
64         std::unique_lock<std::mutex> lock(tblMutex_);
65         if (creatorTbl_.find(key) == creatorTbl_.end()) {
66             MEDIA_LOGE("key %{public}s not registered !", key.c_str());
67             return nullptr;
68         }
69 
70         elem = creatorTbl_[key](param);
71         if (elem == nullptr) {
72             MEDIA_LOGE("create element for key(%{public}s) failed !", key.c_str());
73             return nullptr;
74         }
75     }
76 
77     int32_t ret = elem->Init();
78     if (ret != MSERR_OK) {
79         MEDIA_LOGE("init element for key(%{public}s) failed !", key.c_str());
80         return nullptr;
81     }
82 
83     return elem;
84 }
85 
RecorderElement(const CreateParam & createParam)86 RecorderElement::RecorderElement(const CreateParam &createParam)
87     : desc_(createParam.srcDesc), name_(createParam.name)
88 {
89     MEDIA_LOGD("enter %{public}s ctor", name_.c_str());
90 }
91 
~RecorderElement()92 RecorderElement::~RecorderElement()
93 {
94     if (gstElem_ != nullptr) {
95         gst_object_unref(gstElem_);
96     }
97 
98     MEDIA_LOGD("enter %{public}s dtor", name_.c_str());
99 }
100 
DrainAll(bool isDrain)101 int32_t RecorderElement::DrainAll(bool isDrain)
102 {
103     MEDIA_LOGI("perform drainAll for %{public}s", name_.c_str());
104 
105     if (!isDrain) {
106         auto block = [] (GstPad *pad, GstPadProbeInfo *info, gpointer userData) {
107             (void)userData;
108             if (pad == nullptr || info == nullptr) {
109                 return GST_PAD_PROBE_PASS;
110             }
111             MEDIA_LOGI("During flushing, pad %{public}s's probe is processing the probeInfo", GST_PAD_NAME(pad));
112             if ((static_cast<unsigned int>(info->type) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) == 0) {
113                 return GST_PAD_PROBE_DROP;
114             }
115             return GST_PAD_PROBE_PASS;
116         };
117 
118         GList *allSrcPads = gstElem_->srcpads;
119         for (GList *padNode = g_list_first(allSrcPads); padNode != nullptr; padNode = padNode->next) {
120             if (padNode->data == nullptr)  {
121                 continue;
122             }
123             MEDIA_LOGI("add probe for %{public}s...", name_.c_str());
124             (void)gst_pad_add_probe((GstPad *)padNode->data, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
125                                     (GstPadProbeCallback)block, nullptr, nullptr);
126         }
127     }
128 
129     GstEvent *event = gst_event_new_eos();
130     CHECK_AND_RETURN_RET(event != nullptr, MSERR_NO_MEMORY);
131     (void)gst_element_send_event(gstElem_, event);
132 
133     return MSERR_OK;
134 }
135 
OnMessageReceived(GstMessage & rawMsg,RecorderMessage & prettyMsg)136 RecorderMsgProcResult RecorderElement::OnMessageReceived(GstMessage &rawMsg, RecorderMessage &prettyMsg)
137 {
138     if (rawMsg.src != GST_OBJECT_CAST(gstElem_)) {
139         return RecorderMsgProcResult::REC_MSG_PROC_IGNORE;
140     }
141 
142     if (GST_MESSAGE_TYPE(&rawMsg) == GST_MESSAGE_ERROR) { // error msg is fatal, elements can not handle.
143         return RecorderMsgProcResult::REC_MSG_PROC_IGNORE;
144     }
145 
146     // if the message is extended format, translate it at here and return OK.
147     RecorderMsgProcResult ret = DoProcessMessage(rawMsg, prettyMsg);
148     prettyMsg.sourceId = GetSourceId();
149 
150     return ret;
151 }
152 
CheckAllParamsConfigured(const std::set<int32_t> & expectedParams) const153 bool RecorderElement::CheckAllParamsConfigured(const std::set<int32_t> &expectedParams) const
154 {
155     std::set<int32_t> intersection;
156     (void)std::set_intersection(expectedParams.begin(), expectedParams.end(),
157                                 configuredParams_.begin(), configuredParams_.end(),
158                                 std::inserter(intersection, intersection.end()));
159     if (intersection == expectedParams) {
160         return true;
161     }
162 
163     std::string errStr = "Fail ! Not all expected parameters are configured: ";
164     for (auto &param : expectedParams) {
165         auto iter = PARAM_TYPE_NAME_MAP.find(param);
166         if (iter == PARAM_TYPE_NAME_MAP.end()) {
167             errStr += "unknown param type:" + std::to_string(param);
168         } else {
169             errStr += iter->second;
170         }
171         errStr += ", ";
172     }
173     MEDIA_LOGE("%{public}s, %{public}s", name_.c_str(), errStr.c_str());
174 
175     return false;
176 }
177 
CheckAnyParamConfiged(const std::set<int32_t> & expectedParams) const178 bool RecorderElement::CheckAnyParamConfiged(const std::set<int32_t> &expectedParams) const
179 {
180     std::set<int32_t> intersection;
181     (void)std::set_intersection(expectedParams.begin(), expectedParams.end(),
182                                 configuredParams_.begin(), configuredParams_.end(),
183                                 std::inserter(intersection, intersection.end()));
184     if (!intersection.empty()) {
185         return true;
186     }
187 
188     std::string errStr = "Fail ! No any one of expected parameters are configured: ";
189     for (auto &param : expectedParams) {
190         auto iter = PARAM_TYPE_NAME_MAP.find(param);
191         if (iter == PARAM_TYPE_NAME_MAP.end()) {
192             errStr += "unknown param type:" + std::to_string(param);
193         } else {
194             errStr += iter->second;
195         }
196         errStr += ", ";
197     }
198     MEDIA_LOGE("%{public}s, %{public}s", name_.c_str(), errStr.c_str());
199 
200     return false;
201 }
202 
CheckRangeValid(Range & range,int32_t value)203 bool RecorderElement::CheckRangeValid(Range &range, int32_t value)
204 {
205     if ((range.minVal != 0 || range.maxVal != 0) &&
206         (value < range.minVal || value > range.maxVal)) {
207         return false;
208     }
209 
210     return true;
211 }
212 } // namespace Media
213 } // namespace OHOS
214