• 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_msg_converter.h"
17 #include <functional>
18 #include <unordered_map>
19 #include "media_errors.h"
20 #include "media_log.h"
21 #include "gst_utils.h"
22 
23 namespace {
24     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "GstMsgConvDefault"};
25 }
26 
27 namespace OHOS {
28 namespace Media {
StreamDecErrorParse(const gchar * name)29 static int32_t StreamDecErrorParse(const gchar *name)
30 {
31     if (strstr(name, "aac") != nullptr) {
32         MEDIA_LOGE("tag: MSERR_AUD_DEC_FAILED");
33         return MSERR_AUD_DEC_FAILED;
34     } else if (strstr(name, "h264") != nullptr || strstr(name, "h265") != nullptr) {
35         MEDIA_LOGE("tag: MSERR_VID_DEC_FAILED");
36         return MSERR_VID_DEC_FAILED;
37     } else {
38         MEDIA_LOGE("tag: MSERR_UNKNOWN");
39         return MSERR_UNKNOWN;
40     }
41 }
42 
43 using StreamToServiceErrFunc = std::function<int32_t(const gchar*)>;
44 static const std::unordered_map<int32_t, StreamToServiceErrFunc> STREAM_TO_SERVICE_ERR_FUNC_TABLE = {
45     { GST_STREAM_ERROR_DECODE, StreamDecErrorParse },
46 };
47 static const std::unordered_map<int32_t, MediaServiceErrCode> STREAM_TO_SERVICE_ERR_TABLE = {
48     { GST_STREAM_ERROR_FORMAT, MSERR_UNSUPPORT_CONTAINER_TYPE },
49     { GST_STREAM_ERROR_TYPE_NOT_FOUND, MSERR_NOT_FIND_CONTAINER },
50     /* Currently, audio decoding and video decoding cannot be distinguished which is not supported by msg.
51     * By default, we set video decoding is not supported.
52     * The identification method must be added when the new demux pulgin in is use.
53     */
54     { GST_STREAM_ERROR_CODEC_NOT_FOUND, MSERR_UNSUPPORT_VID_DEC_TYPE },
55     { GST_STREAM_ERROR_DEMUX, MSERR_DEMUXER_FAILED },
56     { GST_STREAM_ERROR_WRONG_TYPE, MSERR_UNSUPPORT_FILE },
57     { GST_STREAM_ERROR_FAILED, MSERR_UNSUPPORT_STREAM },
58 };
59 static const std::unordered_map<int32_t, MediaServiceErrCode> RESOURCE_TO_SERVICE_ERR_TABLE = {
60     { GST_RESOURCE_ERROR_NOT_FOUND, MSERR_OPEN_FILE_FAILED },
61     { GST_RESOURCE_ERROR_OPEN_READ, MSERR_OPEN_FILE_FAILED },
62     { GST_RESOURCE_ERROR_READ, MSERR_FILE_ACCESS_FAILED },
63     { GST_RESOURCE_ERROR_NOT_AUTHORIZED, MSERR_FILE_ACCESS_FAILED },
64     { GST_RESOURCE_ERROR_TIME_OUT, MSERR_NETWORK_TIMEOUT },
65 };
66 
StreamErrorParse(const gchar * name,const GError * error)67 static int32_t StreamErrorParse(const gchar *name, const GError *error)
68 {
69     CHECK_AND_RETURN_RET_LOG(name != nullptr, MSERR_UNSUPPORT_STREAM, "name is nullptr");
70     MEDIA_LOGE("domain: GST_STREAM_ERROR(%{public}d)", error->code);
71     auto streamIter = STREAM_TO_SERVICE_ERR_TABLE.find(error->code);
72     if (streamIter != STREAM_TO_SERVICE_ERR_TABLE.end()) {
73         return streamIter->second;
74     }
75     auto streamFuncIter = STREAM_TO_SERVICE_ERR_FUNC_TABLE.find(error->code);
76     if (streamFuncIter != STREAM_TO_SERVICE_ERR_FUNC_TABLE.end()) {
77         return streamFuncIter->second(name);
78     }
79 
80     return MSERR_UNSUPPORT_STREAM;
81 }
82 
ResourceErrorParse(const GError * error)83 static int32_t ResourceErrorParse(const GError *error)
84 {
85     MEDIA_LOGE("domain: GST_RESOURCE_ERROR");
86     auto resIter = RESOURCE_TO_SERVICE_ERR_TABLE.find(error->code);
87     if (resIter == RESOURCE_TO_SERVICE_ERR_TABLE.end()) {
88         return MSERR_UNSUPPORT_SOURCE;
89     }
90     return resIter->second;
91 }
92 
ConvertErrorMessage(GstMessage & gstMsg,InnerMessage & innerMsg)93 static int32_t ConvertErrorMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
94 {
95     GError *error = nullptr;
96     gchar *debug  = nullptr;
97     gst_message_parse_error(&gstMsg, &error, &debug);
98     if (error == nullptr || debug == nullptr) {
99         return MSERR_UNKNOWN;
100     }
101     MEDIA_LOGE("[ERROR] %{public}s, %{public}s", error->message, debug);
102 
103     gchar *name = gst_object_get_path_string(gstMsg.src);
104     innerMsg.type = INNER_MSG_ERROR;
105     if (error->domain == GST_STREAM_ERROR) {
106         innerMsg.detail1 = StreamErrorParse(name, error);
107     } else if (error->domain == GST_RESOURCE_ERROR) {
108         innerMsg.detail1 = ResourceErrorParse(error);
109     } else {
110         innerMsg.detail1 = MSERR_UNSUPPORT_STREAM;
111     }
112     innerMsg.extend = std::string(error->message);
113 
114     g_error_free(error);
115     g_free(debug);
116     g_free(name);
117     return MSERR_OK;
118 }
119 
ConvertWarningMessage(GstMessage & gstMsg,InnerMessage & innerMsg)120 static int32_t ConvertWarningMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
121 {
122     GError *error = nullptr;
123     gchar *debug  = nullptr;
124     gst_message_parse_warning(&gstMsg, &error, &debug);
125     if (error == nullptr || debug == nullptr) {
126         return MSERR_UNKNOWN;
127     }
128     MEDIA_LOGW("[WARNING] %{public}s, %{public}s", error->message, debug);
129 
130     innerMsg.type = INNER_MSG_WARNING;
131     innerMsg.detail1 = MSERR_UNKNOWN;
132 
133     g_error_free(error);
134     g_free(debug);
135     return MSERR_OK;
136 }
137 
ConvertInfoMessage(GstMessage & gstMsg,InnerMessage & innerMsg)138 static int32_t ConvertInfoMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
139 {
140     GError *error = nullptr;
141     gchar *debug  = nullptr;
142     gst_message_parse_info(&gstMsg, &error, &debug);
143     if (error == nullptr || debug == nullptr) {
144         return MSERR_UNKNOWN;
145     }
146     MEDIA_LOGI("[INFO] %{public}s, %{public}s", error->message, debug);
147 
148     innerMsg.type = INNER_MSG_INFO;
149     innerMsg.detail1 = MSERR_UNKNOWN;
150 
151     g_error_free(error);
152     g_free(debug);
153     return MSERR_OK;
154 }
155 
ConvertStateChangedMessage(GstMessage & gstMsg,InnerMessage & innerMsg)156 static int32_t ConvertStateChangedMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
157 {
158     GstState oldState = GST_STATE_VOID_PENDING;
159     GstState newState = GST_STATE_VOID_PENDING;
160     GstState pendingState = GST_STATE_VOID_PENDING;
161     gst_message_parse_state_changed(&gstMsg, &oldState, &newState, &pendingState);
162     MEDIA_LOGI("%{public}s change state from %{public}s to %{public}s", ELEM_NAME(GST_MESSAGE_SRC(&gstMsg)),
163         gst_element_state_get_name(oldState), gst_element_state_get_name(newState));
164 
165     innerMsg.type = INNER_MSG_STATE_CHANGED;
166     innerMsg.detail1 = static_cast<int32_t>(oldState);
167     innerMsg.detail2 = static_cast<int32_t>(newState);
168     if (GST_IS_PIPELINE(gstMsg.src)) {
169         GstPipeline *pipeline = GST_PIPELINE(GST_MESSAGE_SRC(&gstMsg));
170         innerMsg.extend = pipeline;
171     }
172 
173     return MSERR_OK;
174 }
175 
ConvertAsyncDoneMessage(GstMessage & gstMsg,InnerMessage & innerMsg)176 static int32_t ConvertAsyncDoneMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
177 {
178     innerMsg.type = INNER_MSG_ASYNC_DONE;
179     if (GST_IS_PIPELINE(gstMsg.src)) {
180         GstPipeline *pipeline = GST_PIPELINE(GST_MESSAGE_SRC(&gstMsg));
181         innerMsg.extend = pipeline;
182     }
183 
184     return MSERR_OK;
185 }
186 
ConvertResolutionChangedMessage(GstMessage & gstMsg,InnerMessage & innerMsg)187 static int32_t ConvertResolutionChangedMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
188 {
189     gint width = 0;
190     gint height = 0;
191     gst_message_parse_resulution_changed(&gstMsg, &width, &height);
192     MEDIA_LOGI("resolution changed to width:%{public}d height:%{public}d", width, height);
193 
194     innerMsg.type = INNER_MSG_RESOLUTION_CHANGED;
195     innerMsg.detail1 = width;
196     innerMsg.detail2 = height;
197     return MSERR_OK;
198 }
199 
ConvertBufferingTimeMessage(GstMessage & gstMsg,InnerMessage & innerMsg)200 static int32_t ConvertBufferingTimeMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
201 {
202     gint64 bufferingTime;
203     guint mqNumId;
204     gst_message_parse_buffering_time(&gstMsg, &bufferingTime, &mqNumId);
205     MEDIA_LOGI("mqNumId = %{public}u, bufferingTime = %{public}" PRIi64 "", mqNumId, bufferingTime);
206 
207     innerMsg.type = INNER_MSG_BUFFERING_TIME;
208     innerMsg.detail1 = static_cast<int32_t>(mqNumId);
209     innerMsg.extend = bufferingTime;
210     return MSERR_OK;
211 }
212 
ConvertUsedMqNumMessage(GstMessage & gstMsg,InnerMessage & innerMsg)213 static int32_t ConvertUsedMqNumMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
214 {
215     guint usedMqNum;
216     gst_message_parse_mq_num_use_buffering(&gstMsg, &usedMqNum);
217     MEDIA_LOGI("used multiqueue num for buffering is %{public}u", usedMqNum);
218 
219     innerMsg.type = INNER_MSG_BUFFERING_USED_MQ_NUM;
220     innerMsg.detail1 = static_cast<int32_t>(usedMqNum);
221     return MSERR_OK;
222 }
223 
ConvertVideoRotationMessage(GstMessage & gstMsg,InnerMessage & innerMsg)224 static int32_t ConvertVideoRotationMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
225 {
226     gchar *rotation = NULL;
227     gst_message_parse_video_rotation(&gstMsg, &rotation);
228     MEDIA_LOGI("Rotation is %{public}s", rotation);
229 
230     std::string str(rotation);
231     std::string::size_type pos = std::string::npos;
232     if ((pos = str.find("-")) == std::string::npos) {
233         return MSERR_INVALID_VAL;
234     }
235     std::string subStr = str.substr(pos + 1);
236     int32_t rotate = std::stol(subStr, nullptr, 10);  // 10, decimalism
237     MEDIA_LOGI("Get rotate is %{public}d", rotate);
238 
239     innerMsg.type = INNER_MSG_VIDEO_ROTATION;
240     innerMsg.detail1 = rotate;
241     return MSERR_OK;
242 }
243 
ConvertElementMessage(GstMessage & gstMsg,InnerMessage & innerMsg)244 static int32_t ConvertElementMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
245 {
246     const GstStructure *s = gst_message_get_structure(&gstMsg);
247     if (gst_structure_has_name(s, "resolution-changed")) {
248         return ConvertResolutionChangedMessage(gstMsg, innerMsg);
249     } else if (gst_structure_has_name(s, "message-buffering-time")) {
250         return ConvertBufferingTimeMessage(gstMsg, innerMsg);
251     } else if (gst_structure_has_name(s, "message-mq-num-use-buffering")) {
252         return ConvertUsedMqNumMessage(gstMsg, innerMsg);
253     } else if (gst_structure_has_name(s, "video-rotation")) {
254         return ConvertVideoRotationMessage(gstMsg, innerMsg);
255     }
256 
257     return MSERR_OK;
258 }
259 
ConvertBufferingMessage(GstMessage & gstMsg,InnerMessage & innerMsg)260 static int32_t ConvertBufferingMessage(GstMessage &gstMsg, InnerMessage &innerMsg)
261 {
262     gchar *eleName = gst_element_get_name(GST_MESSAGE_SRC(&gstMsg));
263     if ((GST_MESSAGE_SRC(&gstMsg) != nullptr) && (strncmp(eleName, "queue2", strlen("queue2")) == 0)) {
264         MEDIA_LOGD("buffering msg comes from queue2, do not handle it");
265         g_free(eleName);
266         return MSERR_OK;
267     }
268 
269     gint percent;
270     gst_message_parse_buffering (&gstMsg, &percent);
271     MEDIA_LOGI("multiqueue percent is %{public}d", percent);
272 
273     innerMsg.type = INNER_MSG_BUFFERING;
274     innerMsg.detail1 = percent;
275     g_free(eleName);
276     return MSERR_OK;
277 }
278 
279 static const std::unordered_map<GstMessageType, InnerMsgType> SIMPLE_MSG_TYPE_MAPPING = {
280     { GST_MESSAGE_DURATION_CHANGED, INNER_MSG_DURATION_CHANGED },
281     { GST_MESSAGE_EOS, INNER_MSG_EOS },
282 };
283 
284 using MsgConvFunc = std::function<int32_t(GstMessage&, InnerMessage&)>;
285 static const std::unordered_map<GstMessageType, MsgConvFunc> MSG_CONV_FUNC_TABLE = {
286     { GST_MESSAGE_ERROR, ConvertErrorMessage },
287     { GST_MESSAGE_WARNING, ConvertWarningMessage },
288     { GST_MESSAGE_INFO, ConvertInfoMessage },
289     { GST_MESSAGE_STATE_CHANGED, ConvertStateChangedMessage },
290     { GST_MESSAGE_ASYNC_DONE, ConvertAsyncDoneMessage },
291     { GST_MESSAGE_ELEMENT, ConvertElementMessage },
292     { GST_MESSAGE_BUFFERING, ConvertBufferingMessage },
293 };
294 
ConvertToInnerMsg(GstMessage & gstMsg,InnerMessage & innerMsg) const295 int32_t GstMsgConverterDefault::ConvertToInnerMsg(GstMessage &gstMsg, InnerMessage &innerMsg) const
296 {
297     innerMsg.type = INNER_MSG_UNKNOWN;
298 
299     if (SIMPLE_MSG_TYPE_MAPPING.count(gstMsg.type) != 0) {
300         innerMsg.type = SIMPLE_MSG_TYPE_MAPPING.at(gstMsg.type);
301         MEDIA_LOGI("convert gst msg type: %{public}s", GST_MESSAGE_TYPE_NAME(&gstMsg));
302         return MSERR_OK;
303     }
304 
305     if (MSG_CONV_FUNC_TABLE.count(gstMsg.type) == 0) {
306         return MSERR_OK;
307     }
308 
309     return MSG_CONV_FUNC_TABLE.at(gstMsg.type)(gstMsg, innerMsg);
310 }
311 } // namespace Media
312 } // namespace OHOS