• 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_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 &param)
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 &param : 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 &param : 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