• 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 "gst_loader.h"
17 #include <string>
18 #include <map>
19 #include <queue>
20 #include <glib.h>
21 #include <gst/gst.h>
22 #include "string_ex.h"
23 #include "param_wrapper.h"
24 #include "media_errors.h"
25 #include "media_log.h"
26 #include "engine_dump_manager.h"
27 
28 namespace {
29     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "GstLoader"};
30     const std::map<char, GstDebugLevel> LOG_LEVEL_TO_GST_LEVEL = {
31         {'E', GST_LEVEL_ERROR},
32         {'W', GST_LEVEL_WARNING},
33         {'I', GST_LEVEL_INFO},
34         {'D', GST_LEVEL_DEBUG},
35         {'L', GST_LEVEL_LOG},
36         {'T', GST_LEVEL_TRACE},
37     };
38     const std::string g_gstDftTag = "*";
39     const std::string g_gstVdecTag = "vdecbase";
40     const std::string g_gstVencTag = "vencbase";
41     const std::vector<const gchar *> GST_ARGS = {
42         "ohos_media_service",
43         "--gst-disable-registry-fork",
44 #ifdef __aarch64__
45         "--gst-plugin-path=/system/lib64/media/plugins"
46 #else
47         "--gst-plugin-path=/system/lib/media/plugins"
48 #endif
49     };
50 }
51 
52 namespace OHOS {
53 namespace Media {
54 struct GstLogPrintInfo {
55     GstDebugLevel level;
56     const gchar *file;
57     const gchar *function;
58     gint line;
59     GObject *object;
60     const char *logMsg;
61     const char *modeName;
62 };
63 
64 #ifdef OHOS_MEDIA_LOG_DFX
GstLogPrint(const GstLogPrintInfo & info)65 static void GstLogPrint(const GstLogPrintInfo &info)
66 {
67     const gchar *objName = GST_IS_OBJECT(info.object) ? GST_OBJECT_NAME(info.object) : " ";
68     objName = objName ? objName : " ";
69     OHOS::HiviewDFX::HiLogLabel gstLable = {LOG_CORE, LOG_DOMAIN, info.modeName};
70 
71     switch (info.level) {
72         case GST_LEVEL_TRACE: // no break
73         case GST_LEVEL_LOG:   // no break
74         case GST_LEVEL_DEBUG:
75             DfxLogDump::GetInstance().SaveLog("LOGD", gstLable, "{%s():%d} [gst::%s:%" PRIXPTR "] %s",
76                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
77             (void)::OHOS::HiviewDFX::HiLog::Debug(gstLable,
78                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
79                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
80             break;
81         case GST_LEVEL_INFO:
82             DfxLogDump::GetInstance().SaveLog("LOGI", gstLable, "{%s():%d} [gst::%s:%" PRIXPTR "] %s",
83                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
84             (void)::OHOS::HiviewDFX::HiLog::Info(gstLable,
85                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
86                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
87             break;
88         case GST_LEVEL_WARNING:
89             DfxLogDump::GetInstance().SaveLog("LOGW", gstLable, "{%s():%d} [gst::%s:%" PRIXPTR "] %s",
90                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
91             (void)::OHOS::HiviewDFX::HiLog::Warn(gstLable,
92                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
93                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
94             break;
95         case GST_LEVEL_ERROR:
96             DfxLogDump::GetInstance().SaveLog("LOGE", gstLable, "{%s():%d} [gst::%s:%" PRIXPTR "] %s",
97                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
98             (void)::OHOS::HiviewDFX::HiLog::Error(gstLable,
99                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
100                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
101             break;
102         default:
103             break;
104     }
105 }
106 #else
GstLogPrint(const GstLogPrintInfo & info)107 static void GstLogPrint(const GstLogPrintInfo &info)
108 {
109     const gchar *objName = GST_IS_OBJECT(info.object) ? GST_OBJECT_NAME(info.object) : " ";
110     objName = objName ? objName : " ";
111     OHOS::HiviewDFX::HiLogLabel gstLable = {LOG_CORE, LOG_DOMAIN, info.modeName};
112 
113     switch (info.level) {
114         case GST_LEVEL_TRACE: // no break
115         case GST_LEVEL_LOG:   // no break
116         case GST_LEVEL_DEBUG:
117             (void)::OHOS::HiviewDFX::HiLog::Debug(gstLable,
118                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
119                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
120             break;
121         case GST_LEVEL_INFO:
122             (void)::OHOS::HiviewDFX::HiLog::Info(gstLable,
123                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
124                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
125             break;
126         case GST_LEVEL_WARNING:
127             (void)::OHOS::HiviewDFX::HiLog::Warn(gstLable,
128                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
129                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
130             break;
131         case GST_LEVEL_ERROR:
132             (void)::OHOS::HiviewDFX::HiLog::Error(gstLable,
133                 "{%{public}s():%{public}d} [gst::%{public}s:%{public}" PRIXPTR "] %{public}s",
134                 info.function, info.line, objName, FAKE_POINTER(info.object), info.logMsg);
135             break;
136         default:
137             break;
138     }
139 }
140 #endif
141 
GstLogCallbackFunc(GstDebugCategory * category,GstDebugLevel level,const gchar * file,const gchar * function,gint line,GObject * object,GstDebugMessage * message,gpointer userData)142 static void GstLogCallbackFunc(GstDebugCategory *category, GstDebugLevel level, const gchar *file,
143     const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer userData)
144 {
145     const gchar *modeName = nullptr;
146     (void)userData;
147 
148     if (message == nullptr) {
149         return;
150     }
151     if (category != nullptr) {
152         if (level > gst_debug_category_get_threshold(category)) {
153             return;
154         }
155         modeName = gst_debug_category_get_name(category);
156     } else {
157         if (level > gst_debug_get_default_threshold()) {
158             return;
159         }
160     }
161 
162     if (modeName == nullptr) {
163         modeName = LABEL.tag;
164     }
165 
166     const gchar *logMsg = gst_debug_message_get(message);
167     if (logMsg == nullptr) {
168         return;
169     }
170     GstLogPrintInfo printInfo = {level, file ? file : " ", function ? function : " ", line, object, logMsg, modeName};
171     GstLogPrint(printInfo);
172 }
173 
GLogCallbackFunc(const gchar * logDomain,GLogLevelFlags level,const gchar * message,gpointer userData)174 static void GLogCallbackFunc(const gchar *logDomain, GLogLevelFlags level, const gchar *message, gpointer userData)
175 {
176     const gchar *modeName = logDomain;
177     (void)userData;
178 
179     if (message == nullptr || level > G_LOG_LEVEL_WARNING) {
180         return;
181     }
182 
183     if (modeName == nullptr) {
184         modeName = LABEL.tag;
185     }
186     OHOS::HiviewDFX::HiLogLabel glibLable = {LOG_CORE, LOG_DOMAIN, modeName};
187 
188     switch (level) {
189         case G_LOG_LEVEL_WARNING:
190             (void)::OHOS::HiviewDFX::HiLog::Warn(glibLable, "[glog] %{public}s", message);
191             break;
192         case G_LOG_LEVEL_CRITICAL: // no break
193         case G_LOG_LEVEL_ERROR:    // no break
194         case G_LOG_FLAG_RECURSION:
195             (void)::OHOS::HiviewDFX::HiLog::Error(glibLable, "[glog] %{public}s", message);
196             break;
197         default:
198             break;
199     }
200 }
201 
EnableGLog(GLogFunc func)202 static void EnableGLog(GLogFunc func)
203 {
204     // map glib default log handler, and gstreamer log hander to GLogMap
205     (void)g_log_set_default_handler(func, nullptr);
206     (void)g_log_set_handler("GStreamer", static_cast<GLogLevelFlags>(0xFFFFFFFF), func, nullptr);
207 }
208 
SetGstLogLevelFromSysPara()209 static void SetGstLogLevelFromSysPara()
210 {
211     std::string levelPara;
212     int res = OHOS::system::GetStringParameter("sys.media.log.level", levelPara, "");
213     if (res != 0 || levelPara.empty()) {
214         gst_debug_set_default_threshold(GST_LEVEL_WARNING);
215         MEDIA_LOGD("sys.media.log.level not find");
216     } else {
217         MEDIA_LOGD("sys.media.log.level=%{public}s", levelPara.c_str());
218     }
219 
220     static std::map<std::string, char> logTagLevelMap =
221         { { g_gstDftTag, 'W' }, { g_gstVdecTag, 'D' }, { g_gstVencTag, 'D' } };
222     std::vector<std::string> tagLevelVec;
223     SplitStr(levelPara, ",", tagLevelVec, false, true);
224     for (auto &tagLevel : tagLevelVec) {
225         std::vector<std::string> item;
226         SplitStr(tagLevel, ":", item, false, true); // module format:"tagname:level"
227         if (item.size() < 2) { // module format:"tagname:level"
228             continue;
229         }
230         const std::string &tag = item[0];
231         if (tag.size() >= 128) { // max tag size is 128
232             continue;
233         }
234         if (logTagLevelMap.size() >= 512 && logTagLevelMap.count(tag) == 0) { // 512 is max tag number
235             continue;
236         }
237         const std::string &level = item[1];
238         if (level.empty() || LOG_LEVEL_TO_GST_LEVEL.count(level.c_str()[0]) == 0) {
239             continue;
240         }
241 
242         logTagLevelMap[tag] = level.c_str()[0];
243         MEDIA_LOGI("logPrara:%{public}s:%{public}c", tag.c_str(), level.c_str()[0]);
244     }
245     gst_debug_set_default_threshold(LOG_LEVEL_TO_GST_LEVEL.at(logTagLevelMap[g_gstDftTag]));
246     for (auto &&[tag, levelCode] : logTagLevelMap) {
247         if (tag == g_gstDftTag) {
248             continue;
249         }
250         GstDebugCategory *cat = _gst_debug_get_category(tag.c_str());
251         if (cat == nullptr) {
252             continue;
253         }
254         gst_debug_category_set_threshold(cat, LOG_LEVEL_TO_GST_LEVEL.at(logTagLevelMap[tag]));
255     }
256 }
257 
CreateGstInitArgv()258 static gchar ***CreateGstInitArgv()
259 {
260     gchar ***argv = nullptr;
261     argv = static_cast<gchar ***>(new (std::nothrow) (gchar **));
262     if (argv == nullptr) {
263         MEDIA_LOGI("new argv failed");
264         return nullptr;
265     }
266     *argv = static_cast<gchar **>(new (std::nothrow) gchar *[GST_ARGS.size()]);
267     if (*argv == nullptr) {
268         delete argv;
269         return nullptr;
270     }
271     for (size_t i = 0; i < GST_ARGS.size(); i++) {
272         (*argv)[i] = const_cast<gchar *>(GST_ARGS[i]);
273     }
274 
275     return argv;
276 }
277 
DestroyGstInitArgv(gchar *** argv)278 static void DestroyGstInitArgv(gchar ***argv)
279 {
280     if (argv == nullptr) {
281         return;
282     }
283     if (*argv == nullptr) {
284         delete argv;
285         return;
286     }
287     delete [] *argv;
288     delete argv;
289 }
290 
SetUp()291 int32_t GstLoader::SetUp()
292 {
293     std::lock_guard<std::mutex> lock(mutex_);
294     if (isInit_) {
295         return MSERR_OK;
296     }
297     EngineDumpManager::GetInstance().Init();
298 
299     EnableGLog(GLogCallbackFunc);
300     gst_debug_remove_log_function(gst_debug_log_default);
301     gst_debug_add_log_function(GstLogCallbackFunc, nullptr, nullptr);
302     SetGstLogLevelFromSysPara();
303     int32_t argc = static_cast<int32_t>(GST_ARGS.size());
304     MEDIA_LOGI("SetUp GstLoader argc=%{public}d", argc);
305     gchar ***argv = CreateGstInitArgv();
306     if (argv == nullptr) {
307         return MSERR_NO_MEMORY;
308     }
309     gst_init(&argc, argv);
310     DestroyGstInitArgv(argv);
311     isInit_ = true;
312 
313     MEDIA_LOGI("SetUp GstLoader finished!");
314 
315     return MSERR_OK;
316 }
317 
UpdateLogLevel() const318 void GstLoader::UpdateLogLevel() const
319 {
320     SetGstLogLevelFromSysPara();
321 }
322 } // namespace Media
323 } // namespace OHOS
324