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 ¶m)
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 ¶m : 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 ¶m : 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