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_PATH, "output path"),
40 PARAM_TYPE_NAME_ITEM(OUT_FD, "out file descripter"),
41 PARAM_TYPE_NAME_ITEM(NEXT_OUT_FD, "next out file descripter"),
42 PARAM_TYPE_NAME_ITEM(OUTPUT_FORMAT, "output file format"),
43 };
44 }
45
46 namespace OHOS {
47 namespace Media {
RegisterElement(const std::string & key,const ElementCreator creator)48 int32_t RecorderElementFactory::RegisterElement(const std::string &key, const ElementCreator creator)
49 {
50 std::unique_lock<std::mutex> lock(tblMutex_);
51 if (creatorTbl_.find(key) != creatorTbl_.end()) {
52 MEDIA_LOGE("key %{public}s already registered !", key.c_str());
53 return MSERR_INVALID_OPERATION;
54 }
55
56 (void)creatorTbl_.emplace(key, creator);
57 return MSERR_OK;
58 }
59
CreateElement(const std::string key,const RecorderElement::CreateParam & param)60 std::shared_ptr<RecorderElement> RecorderElementFactory::CreateElement(
61 const std::string key, const RecorderElement::CreateParam ¶m)
62 {
63 std::shared_ptr<RecorderElement> elem;
64 {
65 std::unique_lock<std::mutex> lock(tblMutex_);
66 if (creatorTbl_.find(key) == creatorTbl_.end()) {
67 MEDIA_LOGE("key %{public}s not registered !", key.c_str());
68 return nullptr;
69 }
70
71 elem = creatorTbl_[key](param);
72 if (elem == nullptr) {
73 MEDIA_LOGE("create element for key(%{public}s) failed !", key.c_str());
74 return nullptr;
75 }
76 }
77
78 int32_t ret = elem->Init();
79 if (ret != MSERR_OK) {
80 MEDIA_LOGE("init element for key(%{public}s) failed !", key.c_str());
81 return nullptr;
82 }
83
84 return elem;
85 }
86
RecorderElement(const CreateParam & createParam)87 RecorderElement::RecorderElement(const CreateParam &createParam)
88 : desc_(createParam.srcDesc), name_(createParam.name)
89 {
90 MEDIA_LOGD("enter %{public}s ctor", name_.c_str());
91 }
92
~RecorderElement()93 RecorderElement::~RecorderElement()
94 {
95 if (gstElem_ != nullptr) {
96 gst_object_unref(gstElem_);
97 }
98
99 MEDIA_LOGD("enter %{public}s dtor", name_.c_str());
100 }
101
DrainAll(bool isDrain)102 int32_t RecorderElement::DrainAll(bool isDrain)
103 {
104 MEDIA_LOGI("perform drainAll for %{public}s", name_.c_str());
105
106 if (!isDrain) {
107 auto block = [] (GstPad *pad, GstPadProbeInfo *info, gpointer userdata) {
108 (void)userdata;
109 if (pad == nullptr || info == nullptr) {
110 return GST_PAD_PROBE_PASS;
111 }
112 MEDIA_LOGI("During flushing, pad %{public}s's probe is processing the probeInfo", GST_PAD_NAME(pad));
113 if ((static_cast<unsigned int>(info->type) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) == 0) {
114 return GST_PAD_PROBE_DROP;
115 }
116 return GST_PAD_PROBE_PASS;
117 };
118
119 GList *allSrcPads = gstElem_->srcpads;
120 for (GList *padNode = g_list_first(allSrcPads); padNode != nullptr; padNode = padNode->next) {
121 if (padNode->data == nullptr) {
122 continue;
123 }
124 MEDIA_LOGI("add probe for %{public}s...", name_.c_str());
125 (void)gst_pad_add_probe((GstPad *)padNode->data, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
126 (GstPadProbeCallback)block, nullptr, nullptr);
127 }
128 }
129
130 GstEvent *event = gst_event_new_eos();
131 CHECK_AND_RETURN_RET(event != nullptr, MSERR_NO_MEMORY);
132 (void)gst_element_send_event(gstElem_, event);
133
134 return MSERR_OK;
135 }
136
OnMessageReceived(GstMessage & rawMsg,RecorderMessage & prettyMsg)137 RecorderMsgProcResult RecorderElement::OnMessageReceived(GstMessage &rawMsg, RecorderMessage &prettyMsg)
138 {
139 if (rawMsg.src != GST_OBJECT_CAST(gstElem_)) {
140 return RecorderMsgProcResult::REC_MSG_PROC_IGNORE;
141 }
142
143 if (GST_MESSAGE_TYPE(&rawMsg) == GST_MESSAGE_ERROR) { // error msg is fatal, elements can not handle.
144 return RecorderMsgProcResult::REC_MSG_PROC_IGNORE;
145 }
146
147 // if the message is extended format, translate it at here and return OK.
148
149 RecorderMsgProcResult ret = DoProcessMessage(rawMsg, prettyMsg);
150 prettyMsg.sourceId = GetSourceId();
151
152 return ret;
153 }
154
CheckAllParamsConfiged(const std::set<int32_t> & expectedParams) const155 bool RecorderElement::CheckAllParamsConfiged(const std::set<int32_t> &expectedParams) const
156 {
157 std::set<int32_t> intersection;
158 (void)std::set_intersection(expectedParams.begin(), expectedParams.end(),
159 configedParams_.begin(), configedParams_.end(),
160 std::inserter(intersection, intersection.end()));
161 if (intersection == expectedParams) {
162 return true;
163 }
164
165 std::string errStr = "Fail ! Not all expected parameters are configured: ";
166 for (auto ¶m : expectedParams) {
167 auto iter = PARAM_TYPE_NAME_MAP.find(param);
168 if (iter == PARAM_TYPE_NAME_MAP.end()) {
169 errStr += "unknown param type:" + std::to_string(param);
170 } else {
171 errStr += iter->second;
172 }
173 errStr += ", ";
174 }
175 MEDIA_LOGE("%{public}s, %{public}s", name_.c_str(), errStr.c_str());
176
177 return false;
178 }
179
CheckAnyParamConfiged(const std::set<int32_t> & expectedParams) const180 bool RecorderElement::CheckAnyParamConfiged(const std::set<int32_t> &expectedParams) const
181 {
182 std::set<int32_t> intersection;
183 (void)std::set_intersection(expectedParams.begin(), expectedParams.end(),
184 configedParams_.begin(), configedParams_.end(),
185 std::inserter(intersection, intersection.end()));
186 if (!intersection.empty()) {
187 return true;
188 }
189
190 std::string errStr = "Fail ! No any one of expected parameters are configured: ";
191 for (auto ¶m : expectedParams) {
192 auto iter = PARAM_TYPE_NAME_MAP.find(param);
193 if (iter == PARAM_TYPE_NAME_MAP.end()) {
194 errStr += "unknown param type:" + std::to_string(param);
195 } else {
196 errStr += iter->second;
197 }
198 errStr += ", ";
199 }
200 MEDIA_LOGE("%{public}s, %{public}s", name_.c_str(), errStr.c_str());
201
202 return false;
203 }
204 } // namespace Media
205 } // namespace OHOS
206