• 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_player_track_parse.h"
17 #include "media_log.h"
18 #include "media_errors.h"
19 
20 namespace {
21     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "GstPlayerTrackParse"};
22 }
23 
24 namespace OHOS {
25 namespace Media {
26 static constexpr uint32_t MEDIA_TYPE_AUD = 0;
27 static constexpr uint32_t MEDIA_TYPE_VID = 1;
28 static const std::unordered_map<std::string_view, std::string> TRACK_FORMAT_STRING_CHANGE = {
29     {PlayerKeys::PLAYER_WIDTH, "width"}, {PlayerKeys::PLAYER_HEIGHT, "height"}, {PlayerKeys::PLAYER_MIME, "codec_mime"},
30     {PlayerKeys::PLAYER_BITRATE, "bitrate"}, {PlayerKeys::PLAYER_FRAMERATE, "framerate"},
31     {PlayerKeys::PLAYER_LANGUGAE, "language-code"}, {PlayerKeys::PLAYER_SAMPLE_RATE, "rate"},
32     {PlayerKeys::PLAYER_CHANNELS, "channels"},
33 };
Create()34 std::shared_ptr<GstPlayerTrackParse> GstPlayerTrackParse::Create()
35 {
36     std::shared_ptr<GstPlayerTrackParse> trackInfo = std::make_shared<GstPlayerTrackParse>();
37     return trackInfo;
38 }
39 
GetVideoTrackInfo(std::vector<Format> & videoTrack)40 int32_t GstPlayerTrackParse::GetVideoTrackInfo(std::vector<Format> &videoTrack)
41 {
42     int32_t value;
43     for (auto iter = videoTrackInfo_.begin(); iter != videoTrackInfo_.end(); iter++) {
44         Format trackInfo;
45         auto trackInfoMap = iter->begin()->second;
46         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_MIME)) > 0) {
47             std::string strValue = trackInfoMap.at(std::string(PlayerKeys::PLAYER_MIME));
48             (void)trackInfo.PutStringValue(std::string(PlayerKeys::PLAYER_MIME), strValue);
49         }
50         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_BITRATE)) > 0) {
51             value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_BITRATE)));
52             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_BITRATE), value);
53         }
54         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_WIDTH)) > 0) {
55             value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_WIDTH)));
56             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_WIDTH), value);
57         }
58         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_HEIGHT)) > 0) {
59             value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_HEIGHT)));
60             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_HEIGHT), value);
61         }
62         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_FRAMERATE)) > 0) {
63             std::string framerate = trackInfoMap.at(std::string(PlayerKeys::PLAYER_FRAMERATE));
64             std::string::size_type delimPos = framerate.find('/');
65             if (delimPos == std::string::npos) {
66                 MEDIA_LOGE("unrecognizable framerate, %{public}s", framerate.c_str());
67                 return MSERR_UNKNOWN;
68             }
69             int32_t num = std::stoi(framerate.substr(0, delimPos));
70             int32_t den = std::stoi(framerate.substr(delimPos + 1, framerate.length()));
71             if (den != 0) {
72                 /* 100: float to int ratio */
73                 value = (static_cast<float>(num) / den) * 100;
74             } else {
75                 value = num;
76             }
77 
78             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_FRAMERATE), value);
79         }
80         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_TRACK_INDEX)) > 0) {
81             value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_TRACK_INDEX)));
82             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), value);
83         }
84         (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_TRACK_TYPE), MEDIA_TYPE_VID);
85         videoTrack.push_back(trackInfo);
86     }
87     return MSERR_OK;
88 }
89 
GetAudioTrackInfo(std::vector<Format> & audioTrack)90 int32_t GstPlayerTrackParse::GetAudioTrackInfo(std::vector<Format> &audioTrack)
91 {
92     for (auto iter = audioTrackInfo_.begin(); iter != audioTrackInfo_.end(); iter++) {
93         Format trackInfo;
94         auto trackInfoMap = iter->begin()->second;
95         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_MIME)) > 0) {
96             std::string value = trackInfoMap.at(std::string(PlayerKeys::PLAYER_MIME));
97             (void)trackInfo.PutStringValue(std::string(PlayerKeys::PLAYER_MIME), value);
98         }
99         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_BITRATE)) > 0) {
100             int32_t value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_BITRATE)));
101             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_BITRATE), value);
102         }
103         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_SAMPLE_RATE)) > 0) {
104             int32_t value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_SAMPLE_RATE)));
105             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_SAMPLE_RATE), value);
106         }
107         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_CHANNELS)) > 0) {
108             int32_t value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_CHANNELS)));
109             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_CHANNELS), value);
110         }
111         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_LANGUGAE)) > 0) {
112             std::string value = trackInfoMap.at(std::string(PlayerKeys::PLAYER_LANGUGAE));
113             (void)trackInfo.PutStringValue(std::string(PlayerKeys::PLAYER_LANGUGAE), value);
114         }
115         if (trackInfoMap.count(std::string(PlayerKeys::PLAYER_TRACK_INDEX)) > 0) {
116             int32_t value = std::stoi(trackInfoMap.at(std::string(PlayerKeys::PLAYER_TRACK_INDEX)));
117             (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), value);
118         }
119         (void)trackInfo.PutIntValue(std::string(PlayerKeys::PLAYER_TRACK_TYPE), MEDIA_TYPE_AUD);
120         audioTrack.push_back(trackInfo);
121     }
122     return MSERR_OK;
123 }
124 
GetSerializedValue(const GValue * value)125 std::string GstPlayerTrackParse::GetSerializedValue(const GValue *value)
126 {
127     if (G_VALUE_HOLDS_STRING(value)) {
128         const gchar *str = g_value_get_string(value);
129         CHECK_AND_RETURN_RET_LOG(str != nullptr, "", "gvalue has no null value");
130         MEDIA_LOGI("value: %{public}s", str);
131         return std::string(str);
132     }
133 
134     gchar *str = gst_value_serialize(value);
135     CHECK_AND_RETURN_RET_LOG(str != nullptr, "", "serialize value failed");
136     std::string serializedValue = str;
137     g_free(str);
138 
139     return serializedValue;
140 }
141 
ParseSingleCapsStructure(const GstStructure * struc,const GstPad * pad,std::vector<std::unordered_map<GstPad *,std::unordered_map<std::string,std::string>>> & trackInfoVec,std::vector<std::string_view> expectedCapsFields,int32_t index)142 void GstPlayerTrackParse::ParseSingleCapsStructure(const GstStructure *struc, const GstPad *pad,
143     std::vector<std::unordered_map<GstPad *, std::unordered_map<std::string, std::string>>> &trackInfoVec,
144     std::vector<std::string_view> expectedCapsFields, int32_t index)
145 {
146     std::unordered_map<std::string, std::string> trackMap;
147     std::string mime = gst_structure_get_name(struc);
148 
149     (void)trackMap.insert(
150         std::pair<std::string, std::string>(std::string(PlayerKeys::PLAYER_TRACK_INDEX), std::to_string(index)));
151     (void)trackMap.insert(std::pair<std::string, std::string>(std::string(PlayerKeys::PLAYER_MIME), mime));
152     for (auto &field : expectedCapsFields) {
153         auto iterStr = TRACK_FORMAT_STRING_CHANGE.find(field);
154         if (iterStr == TRACK_FORMAT_STRING_CHANGE.end()) {
155             MEDIA_LOGE("not match expected cap, %{public}s", field.data());
156             continue;
157         }
158         const GValue *val = gst_structure_get_value(struc, iterStr->second.c_str());
159         if (val == nullptr) {
160             MEDIA_LOGE("get %{public}s filed data value error", iterStr->second.c_str());
161             continue;
162         }
163 
164         std::string serializedValue = GetSerializedValue(val);
165         MEDIA_LOGD("field %{public}s val %{public}s", iterStr->second.c_str(), serializedValue.c_str());
166         trackMap.insert(std::pair<std::string, std::string>(std::string(field), serializedValue));
167     }
168     std::unordered_map<GstPad *, std::unordered_map<std::string, std::string>> padMap;
169     (void)padMap.insert(std::pair<GstPad *, std::unordered_map<std::string, std::string>>((GstPad *)pad, trackMap));
170     trackInfoVec.push_back(padMap);
171 }
172 
GetMimeFromStruc(const GstStructure * struc,std::string & mime)173 int32_t GstPlayerTrackParse::GetMimeFromStruc(const GstStructure *struc, std::string &mime)
174 {
175     const gchar *name = gst_structure_get_name(struc);
176     if (name == nullptr) {
177         MEDIA_LOGE("gst_structure_get_name fail");
178         return MSERR_UNKNOWN;
179     }
180     std::string mimeType = name;
181     std::string::size_type delimPos = mimeType.find('/');
182     if (delimPos == std::string::npos) {
183         MEDIA_LOGE("unrecognizable mimetype, %{public}s", mimeType.c_str());
184         return MSERR_UNKNOWN;
185     }
186     MEDIA_LOGI("parse mimetype %{public}s's caps", mimeType.c_str());
187     mime = mimeType.substr(0, delimPos);
188     return MSERR_OK;
189 }
190 
ParseStreamStruc(const GstPad * pad,GstPlayerTrackParse * playerTrackInfo)191 void GstPlayerTrackParse::ParseStreamStruc(const GstPad *pad, GstPlayerTrackParse *playerTrackInfo)
192 {
193     std::string mime;
194     GstStructure *structure;
195 
196     int32_t retVal = GetStrucFromPad(pad, &structure);
197     if (retVal != MSERR_OK) {
198         return;
199     }
200     retVal = GetMimeFromStruc(structure, mime);
201     if (retVal != MSERR_OK) {
202         return;
203     }
204     if (mime.compare("video") == 0) {
205         std::vector<std::string_view> expectedCapsFields = {
206             PlayerKeys::PLAYER_WIDTH, PlayerKeys::PLAYER_HEIGHT, PlayerKeys::PLAYER_FRAMERATE
207         };
208         ParseSingleCapsStructure(structure, pad, playerTrackInfo->videoTrackInfo_,
209             expectedCapsFields, playerTrackInfo->trackIndex_);
210         playerTrackInfo->trackIndex_++;
211     } else if (mime.compare("audio") == 0) {
212         std::vector<std::string_view> expectedCapsFields = {
213             PlayerKeys::PLAYER_SAMPLE_RATE, PlayerKeys::PLAYER_CHANNELS
214         };
215         ParseSingleCapsStructure(structure, pad, playerTrackInfo->audioTrackInfo_,
216             expectedCapsFields, playerTrackInfo->trackIndex_);
217         playerTrackInfo->trackIndex_++;
218     } else {
219         MEDIA_LOGE("parse streamType %{public}s's not match", mime.c_str());
220         return;
221     }
222 }
223 
GetStrucFromPad(const GstPad * pad,GstStructure ** struc)224 int32_t GstPlayerTrackParse::GetStrucFromPad(const GstPad *pad, GstStructure **struc)
225 {
226     GstCaps *caps = gst_pad_get_current_caps(const_cast<GstPad *>(pad));
227     if (caps == nullptr) {
228         MEDIA_LOGE("gst_pad_get_current_caps return nullptr");
229         return MSERR_UNKNOWN;
230     }
231 
232     MEDIA_LOGD("add probe for %{public}s's pad %{public}s",
233         GST_ELEMENT_NAME(GST_PAD_PARENT(pad)), GST_PAD_NAME(pad));
234 
235     *struc = gst_caps_get_structure(caps, 0);
236     if (*struc == nullptr) {
237         MEDIA_LOGE("gst_caps_get_structure return nullptr");
238         return MSERR_UNKNOWN;
239     }
240     return MSERR_OK;
241 }
242 
FindTrackInfoMap(const GstPad * pad,std::vector<std::unordered_map<GstPad *,std::unordered_map<std::string,std::string>>> & trackInfoVec)243 std::unordered_map<std::string, std::string> *GstPlayerTrackParse::FindTrackInfoMap(const GstPad *pad,
244     std::vector<std::unordered_map<GstPad *, std::unordered_map<std::string, std::string>>> &trackInfoVec)
245 {
246     for (auto iter = trackInfoVec.begin(); iter != trackInfoVec.end(); iter++) {
247         auto padToMapIt = iter->find(const_cast<GstPad *>(pad));
248         if (padToMapIt == iter->end()) {
249             return nullptr;
250         }
251         return &(padToMapIt->second);
252     }
253 
254     return nullptr;
255 }
256 
ParseTag(const GstTagList * tagList,guint tagIndex,std::vector<std::string_view> expectedTagFields,std::unordered_map<std::string,std::string> * trackInfoMap)257 void GstPlayerTrackParse::ParseTag(const GstTagList *tagList, guint tagIndex,
258     std::vector<std::string_view> expectedTagFields,
259     std::unordered_map<std::string, std::string> *trackInfoMap)
260 {
261     const gchar *tag = gst_tag_list_nth_tag_name(tagList, tagIndex);
262     if (tag == nullptr) {
263         return;
264     }
265 
266     MEDIA_LOGD("visit tag: %{public}s", tag);
267     for (auto iter = expectedTagFields.begin(); iter != expectedTagFields.end(); iter++) {
268         auto iterStr = TRACK_FORMAT_STRING_CHANGE.find(*iter);
269         if (iterStr == TRACK_FORMAT_STRING_CHANGE.end()) {
270             MEDIA_LOGE("not match expected tag, %{public}s", iter->data());
271             continue;
272         }
273         if (iterStr->second.compare(tag) == 0) {
274             const GValue *value = gst_tag_list_get_value_index(tagList, tag, 0);
275             if (value == nullptr) {
276                 MEDIA_LOGE("gst_tag_list_get_value_index get tag %{public}s fail", tag);
277                 return;
278             }
279             std::string serializedValue = GetSerializedValue(value);
280             trackInfoMap->insert(std::pair<std::string, std::string>(std::string(*iter), serializedValue));
281             MEDIA_LOGD("trackInfoMap: %{public}s, %{public}s", iter->data(), serializedValue.c_str());
282             break;
283         }
284     }
285 }
286 
ParseTagAndSaveTrackInfo(const GstPad * pad,const GstTagList * tagList,const std::vector<std::string_view> & expectedTagFields,std::vector<std::unordered_map<GstPad *,std::unordered_map<std::string,std::string>>> & trackInfoVec)287 void GstPlayerTrackParse::ParseTagAndSaveTrackInfo(const GstPad *pad, const GstTagList *tagList,
288     const std::vector<std::string_view> &expectedTagFields,
289     std::vector<std::unordered_map<GstPad *, std::unordered_map<std::string, std::string>>> &trackInfoVec)
290 {
291     std::unordered_map<std::string, std::string> *trackInfoMap;
292     gint tagCnt = gst_tag_list_n_tags(tagList);
293     if (tagCnt < 0) {
294         return;
295     }
296 
297     trackInfoMap = FindTrackInfoMap(pad, trackInfoVec);
298     if (trackInfoMap == nullptr) {
299         MEDIA_LOGE("not find trackInfoMap at pad %{public}s", GST_PAD_NAME(pad));
300         return;
301     }
302 
303     for (guint tagIndex = 0; tagIndex < static_cast<guint>(tagCnt); tagIndex++) {
304         ParseTag(tagList, tagIndex, expectedTagFields, trackInfoMap);
305     }
306 }
307 
ParseTagList(const GstPad * pad,const GstTagList * tagList,GstPlayerTrackParse * playerTrackInfo)308 void GstPlayerTrackParse::ParseTagList(const GstPad *pad, const GstTagList *tagList,
309                                        GstPlayerTrackParse *playerTrackInfo)
310 {
311     std::vector<std::string_view> expectedTagFields;
312     GstStructure *structure;
313     std::string mime;
314 
315     int32_t retVal = GetStrucFromPad(pad, &structure);
316     if (retVal != MSERR_OK) {
317         return;
318     }
319     retVal = GetMimeFromStruc(structure, mime);
320     if (retVal != MSERR_OK) {
321         return;
322     }
323     if (mime.compare("video") == 0) {
324         expectedTagFields = {PlayerKeys::PLAYER_BITRATE};
325         ParseTagAndSaveTrackInfo(pad, tagList, expectedTagFields, playerTrackInfo->videoTrackInfo_);
326     } else if (mime.compare("audio") == 0) {
327         expectedTagFields = {PlayerKeys::PLAYER_BITRATE, PlayerKeys::PLAYER_LANGUGAE};
328         ParseTagAndSaveTrackInfo(pad, tagList, expectedTagFields, playerTrackInfo->audioTrackInfo_);
329     } else {
330         MEDIA_LOGE("parse streamType %{public}s's not match", mime.c_str());
331         return;
332     }
333 }
334 
ProbeCallback(GstPad * pad,GstPadProbeInfo * info,gpointer usrdata)335 GstPadProbeReturn GstPlayerTrackParse::ProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer usrdata)
336 {
337     if (pad == nullptr || info ==  nullptr || usrdata == nullptr) {
338         MEDIA_LOGE("param is invalid");
339         return GST_PAD_PROBE_OK;
340     }
341 
342     if (static_cast<unsigned int>(info->type) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) {
343         GstEvent *event = gst_pad_probe_info_get_event(info);
344         CHECK_AND_RETURN_RET_LOG(event != nullptr, GST_PAD_PROBE_OK, "event is null");
345         if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
346             GstTagList *tagList = nullptr;
347             gst_event_parse_tag(event, &tagList);
348             if (tagList == nullptr) {
349                 MEDIA_LOGE("taglist is invalid");
350                 return GST_PAD_PROBE_OK;
351             }
352             MEDIA_LOGI("catch tags at pad %{public}s", GST_PAD_NAME(pad));
353             ParseTagList(pad, tagList, reinterpret_cast<GstPlayerTrackParse *>(usrdata));
354         }
355     }
356 
357     return GST_PAD_PROBE_OK;
358 }
359 
AddProbeToPad(const GstPad * pad,GstPlayerTrackParse * playerTrackInfo)360 void GstPlayerTrackParse::AddProbeToPad(const GstPad *pad, GstPlayerTrackParse *playerTrackInfo)
361 {
362     gulong probeId = gst_pad_add_probe(const_cast<GstPad *>(pad), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
363                                        ProbeCallback, playerTrackInfo, nullptr);
364     if (probeId == 0) {
365         MEDIA_LOGE("add probe for %{public}s's pad %{public}s failed",
366             GST_ELEMENT_NAME(GST_PAD_PARENT(pad)), GST_PAD_NAME(pad));
367         return;
368     }
369     (void)playerTrackInfo->padProbes_.insert(std::pair<GstPad *, gulong>((GstPad *)pad, probeId));
370 }
371 
OnPadAddedCb(const GstElement * element,const GstPad * pad,GstPlayerTrackParse * playerTrackInfo)372 void GstPlayerTrackParse::OnPadAddedCb(const GstElement *element,
373     const GstPad *pad, GstPlayerTrackParse *playerTrackInfo)
374 {
375     CHECK_AND_RETURN_LOG(element != nullptr, "element is null");
376     CHECK_AND_RETURN_LOG(playerTrackInfo != nullptr, "playerTrackInfo is null");
377     CHECK_AND_RETURN_LOG(pad != nullptr, "pad is null");
378 
379     ParseStreamStruc(pad, playerTrackInfo);
380     AddProbeToPad(pad, playerTrackInfo);
381 }
382 
SetDemuxerElementFind(bool isFind)383 void GstPlayerTrackParse::SetDemuxerElementFind(bool isFind)
384 {
385     demuxerElementFind_ = isFind;
386 }
387 
GetDemuxerElementFind()388 bool GstPlayerTrackParse::GetDemuxerElementFind()
389 {
390     return demuxerElementFind_;
391 }
392 } // namespace Media
393 } // namespace OHOS
394