• 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 "dumper.h"
17 #include <string>
18 #include <unistd.h>
19 #include <cstdio>
20 #include <mutex>
21 #include <sys/time.h>
22 #include <securec.h>
23 #include <unordered_map>
24 #include "directory_ex.h"
25 #include "media_errors.h"
26 #include "media_log.h"
27 #include "param_wrapper.h"
28 
29 namespace {
30     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "GstDumper"};
31     static std::mutex g_padBufCountMutex;
32     static std::unordered_map<GstPad *, uint64_t> g_padBufCount = {};
33 }
34 
35 namespace OHOS {
36 namespace Media {
DumpDotGraph(GstPipeline & pipeline,int32_t oldState,int32_t newState)37 void Dumper::DumpDotGraph(GstPipeline &pipeline, int32_t oldState, int32_t newState)
38 {
39     bool checkRet = (oldState < GST_STATE_VOID_PENDING) || (oldState > GST_STATE_PLAYING) ||
40         (newState < GST_STATE_VOID_PENDING) || (newState > GST_STATE_PLAYING);
41     CHECK_AND_RETURN_LOG(!checkRet, "invalid state, oldState: %{public}d, newState: %{public}d",
42         oldState, newState);
43 
44     std::string dumpDir;
45     int res = OHOS::system::GetStringParameter("sys.media.dump.dot.path", dumpDir, "");
46     if (res != 0 || dumpDir.empty()) {
47         return;
48     }
49 
50     std::string realPath;
51     CHECK_AND_RETURN_LOG(PathToRealPath(dumpDir, realPath), "invalid dump path: %{public}s", dumpDir.c_str());
52 
53     struct timeval tv;
54     int ret = gettimeofday(&tv, nullptr);
55     CHECK_AND_RETURN_LOG(ret >= 0, "get time of day failed");
56 
57     constexpr int32_t secPerHour = 60 * 60;
58     constexpr int32_t minutePerHour = 60;
59     constexpr int32_t secPerMinute = 60;
60     constexpr int32_t usecPerMSec = 1000;
61 
62     uint64_t hour = static_cast<uint64_t>(tv.tv_sec / secPerHour);
63     uint32_t minute = static_cast<uint32_t>((tv.tv_sec / secPerMinute) % minutePerHour);
64     uint32_t sec = static_cast<uint32_t>(tv.tv_sec % minutePerHour);
65     uint32_t millsec = static_cast<uint32_t>(tv.tv_usec / usecPerMSec);
66 
67     const gchar *oldName = gst_element_state_get_name(static_cast<GstState>(oldState));
68     const gchar *newName = gst_element_state_get_name(static_cast<GstState>(newState));
69 
70     char fullPath[PATH_MAX] = { 0 };
71     const char *format = "%s/%" PRIu64 ".%u.%u.%u-media-pipeline.0x%06" PRIXPTR ".%s_%s.dot";
72     ret = sprintf_s(fullPath, PATH_MAX, format, realPath.c_str(), hour, minute, sec, millsec,
73                     FAKE_POINTER(&pipeline), oldName, newName);
74     CHECK_AND_RETURN_LOG(ret > 0, "dump dot failed for 0x%{public}06" PRIXPTR " %{public}s to %{public}s",
75         FAKE_POINTER(&pipeline), oldName, newName);
76 
77     FILE *fp = fopen(fullPath, "wb");
78     CHECK_AND_RETURN_LOG(fp != nullptr, "open path failed, %{public}s", fullPath);
79 
80     gchar *buf = gst_debug_bin_to_dot_data(GST_BIN(&pipeline), GST_DEBUG_GRAPH_SHOW_ALL);
81     if (buf != nullptr) {
82         (void)fputs(buf, fp);
83         g_free(buf);
84     }
85 
86     (void)fclose(fp);
87     MEDIA_LOGD("wrote pipeline graph to : '%{public}s'", fullPath);
88 }
89 
DumpGstBuffer(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)90 GstPadProbeReturn Dumper::DumpGstBuffer(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
91 {
92     (void)user_data;
93     CHECK_AND_RETURN_RET(pad != nullptr && info != nullptr, GST_PAD_PROBE_OK);
94 
95     if ((GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) == 0) {
96         return GST_PAD_PROBE_OK;
97     }
98 
99     GstBuffer *buf = gst_pad_probe_info_get_buffer(info);
100     CHECK_AND_RETURN_RET(buf != nullptr, GST_PAD_PROBE_OK);
101     GstMapInfo mapInfo = GST_MAP_INFO_INIT;
102     CHECK_AND_RETURN_RET(gst_buffer_map(buf, &mapInfo, GST_MAP_READ), GST_PAD_PROBE_OK);
103 
104     uint64_t bufSeq = 0;
105     {
106         std::lock_guard<std::mutex> lock(g_padBufCountMutex);
107         if (g_padBufCount.count(pad) == 0) {
108             g_padBufCount.emplace(pad, 0);
109         }
110         bufSeq = g_padBufCount[pad]++;
111     }
112 
113     char fullPath[PATH_MAX] = { 0 };
114     const char *format = "/data/media/dump/pad_%s_%s_buf_%" PRIu64 "";
115     if (sprintf_s(fullPath, PATH_MAX, format, GST_DEBUG_PAD_NAME(pad), bufSeq) <= 0) {
116         MEDIA_LOGE("dump buffer failed for 0x%{public}06" PRIXPTR ", pad is %{public}s:%{public}s",
117                    FAKE_POINTER(buf), GST_DEBUG_PAD_NAME(pad));
118         gst_buffer_unmap(buf, &mapInfo);
119         return GST_PAD_PROBE_OK;
120     }
121 
122     FILE *fp = fopen(fullPath, "wb");
123     if (fp != nullptr) {
124         (void)fwrite(mapInfo.data, mapInfo.size, 1, fp);
125         (void)fflush(fp);
126         (void)fclose(fp);
127         fp = nullptr;
128     }
129 
130     gst_buffer_unmap(buf, &mapInfo);
131 
132     MEDIA_LOGD("wrote buffer to %{public}s", fullPath);
133     return GST_PAD_PROBE_OK;
134 }
135 
AddDumpGstBufferProbe(GstElement * element,const gchar * padname)136 void Dumper::AddDumpGstBufferProbe(GstElement *element, const gchar *padname)
137 {
138     GstPad *pad = gst_element_get_static_pad(element, padname);
139     CHECK_AND_RETURN(pad != nullptr);
140 
141     (void)gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, &Dumper::DumpGstBuffer, nullptr, nullptr);
142     gst_object_unref(pad);
143 }
144 
IsEnableDumpGstBuffer()145 bool Dumper::IsEnableDumpGstBuffer()
146 {
147     int value = OHOS::system::GetIntParameter("sys.media.dump.gstbuffer", 0);
148     return value == 0 ? false : true;
149 }
150 } // namespace Media
151 } // namespace OHOS
152