• 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 "player_track_parse.h"
17 #include "media_log.h"
18 #include "media_errors.h"
19 #include "av_common.h"
20 #include "gst_utils.h"
21 #include "gst_meta_parser.h"
22 #include "player.h"
23 
24 namespace {
25     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerTrackParse"};
26 }
27 
28 namespace OHOS {
29 namespace Media {
30 static const std::unordered_map<std::string_view, std::string_view> INNER_KEY_TO_PLAYER_KEY = {
31     { INNER_META_KEY_BITRATE, PlayerKeys::PLAYER_BITRATE },
32     { INNER_META_KEY_CHANNEL_COUNT, PlayerKeys::PLAYER_CHANNELS },
33     { INNER_META_KEY_FRAMERATE, PlayerKeys::PLAYER_FRAMERATE },
34     { INNER_META_KEY_VIDEO_HEIGHT, PlayerKeys::PLAYER_HEIGHT },
35     { INNER_META_KEY_LANGUAGE, PlayerKeys::PLAYER_LANGUGAE },
36     { INNER_META_KEY_MIME_TYPE, PlayerKeys::PLAYER_MIME },
37     { INNER_META_KEY_SAMPLE_RATE, PlayerKeys::PLAYER_SAMPLE_RATE },
38     { INNER_META_KEY_TRACK_INDEX, PlayerKeys::PLAYER_TRACK_INDEX },
39     { INNER_META_KEY_TRACK_TYPE, PlayerKeys::PLAYER_TRACK_TYPE },
40     { INNER_META_KEY_VIDEO_WIDTH, PlayerKeys::PLAYER_WIDTH },
41 };
42 
Create()43 std::shared_ptr<PlayerTrackParse> PlayerTrackParse::Create()
44 {
45     std::shared_ptr<PlayerTrackParse> trackInfo = std::make_shared<PlayerTrackParse>();
46     return trackInfo;
47 }
48 
PlayerTrackParse()49 PlayerTrackParse::PlayerTrackParse()
50 {
51     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
52 }
53 
~PlayerTrackParse()54 PlayerTrackParse::~PlayerTrackParse()
55 {
56     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
57 }
58 
GetVideoTrackInfo(std::vector<Format> & videoTrack)59 int32_t PlayerTrackParse::GetVideoTrackInfo(std::vector<Format> &videoTrack)
60 {
61     std::unique_lock<std::mutex> lock(trackInfoMutex_);
62     int32_t trackType;
63     for (auto &[pad, innerMeta] : trackInfos_) {
64         if (innerMeta.GetIntValue(INNER_META_KEY_TRACK_TYPE, trackType) && trackType == MediaType::MEDIA_TYPE_VID) {
65             Format outMeta;
66             ConvertToPlayerKeys(innerMeta, outMeta);
67             videoTrack.emplace_back(outMeta);
68         }
69     }
70     return MSERR_OK;
71 }
72 
GetAudioTrackInfo(std::vector<Format> & audioTrack)73 int32_t PlayerTrackParse::GetAudioTrackInfo(std::vector<Format> &audioTrack)
74 {
75     std::unique_lock<std::mutex> lock(trackInfoMutex_);
76     int32_t trackType;
77     for (auto &[pad, innerMeta] : trackInfos_) {
78         if (innerMeta.GetIntValue(INNER_META_KEY_TRACK_TYPE, trackType) && trackType == MediaType::MEDIA_TYPE_AUD) {
79             Format outMeta;
80             ConvertToPlayerKeys(innerMeta, outMeta);
81             audioTrack.emplace_back(outMeta);
82         }
83     }
84     return MSERR_OK;
85 }
86 
ConvertToPlayerKeys(const Format & innerMeta,Format & outMeta) const87 void PlayerTrackParse::ConvertToPlayerKeys(const Format &innerMeta, Format &outMeta) const
88 {
89     for (const auto &[innerKey, playerKey] : INNER_KEY_TO_PLAYER_KEY) {
90         if (!innerMeta.ContainKey(innerKey)) {
91             continue;
92         }
93 
94         std::string strVal;
95         int32_t intVal;
96         FormatDataType type = innerMeta.GetValueType(innerKey);
97         switch (type) {
98             case FORMAT_TYPE_STRING:
99                 innerMeta.GetStringValue(innerKey, strVal);
100                 outMeta.PutStringValue(std::string(playerKey), strVal);
101                 break;
102             case FORMAT_TYPE_INT32:
103                 innerMeta.GetIntValue(innerKey, intVal);
104                 outMeta.PutIntValue(std::string(playerKey), intVal);
105                 break;
106             default:
107                 break;
108         }
109     }
110 }
111 
ProbeCallback(GstPad * pad,GstPadProbeInfo * info,gpointer userData)112 GstPadProbeReturn PlayerTrackParse::ProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer userData)
113 {
114     if (pad == nullptr || info ==  nullptr || userData == nullptr) {
115         MEDIA_LOGE("param is invalid");
116         return GST_PAD_PROBE_OK;
117     }
118 
119     auto playerTrackParse = reinterpret_cast<PlayerTrackParse *>(userData);
120     return playerTrackParse->GetTrackParse(pad, info);
121 }
122 
GetTrackParse(GstPad * pad,GstPadProbeInfo * info)123 GstPadProbeReturn PlayerTrackParse::GetTrackParse(GstPad *pad, GstPadProbeInfo *info)
124 {
125     std::unique_lock<std::mutex> lock(trackInfoMutex_);
126     auto it = trackInfos_.find(pad);
127     CHECK_AND_RETURN_RET_LOG(it != trackInfos_.end(), GST_PAD_PROBE_OK,
128         "unrecognized pad %{public}s", PAD_NAME(pad));
129 
130     if (static_cast<unsigned int>(info->type) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) {
131         GstEvent *event = gst_pad_probe_info_get_event(info);
132         CHECK_AND_RETURN_RET_LOG(event != nullptr, GST_PAD_PROBE_OK, "event is null");
133 
134         if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
135             GstTagList *tagList = nullptr;
136             gst_event_parse_tag(event, &tagList);
137             CHECK_AND_RETURN_RET_LOG(tagList != nullptr, GST_PAD_PROBE_OK, "tags is nullptr")
138             MEDIA_LOGI("catch tags at pad %{public}s", PAD_NAME(pad));
139             GstMetaParser::ParseTagList(*tagList, it->second);
140         } else if (GST_EVENT_TYPE(event) == GST_EVENT_CAPS) {
141             GstCaps *caps = nullptr;
142             gst_event_parse_caps(event, &caps);
143             CHECK_AND_RETURN_RET_LOG(caps != nullptr, GST_PAD_PROBE_OK, "caps is nullptr")
144             MEDIA_LOGI("catch caps at pad %{public}s", PAD_NAME(pad));
145             GstMetaParser::ParseStreamCaps(*caps, it->second);
146             it->second.PutIntValue(INNER_META_KEY_TRACK_INDEX, trackcount_);
147             trackcount_++;
148             MEDIA_LOGD("GetTrackParse tarckcount %{public}d", trackcount_);
149         }
150     }
151 
152     return GST_PAD_PROBE_OK;
153 }
154 
AddProbeToPad(const GstElement * element,GstPad * pad)155 bool PlayerTrackParse::AddProbeToPad(const GstElement *element, GstPad *pad)
156 {
157     MEDIA_LOGD("AddProbeToPad element %{public}s, pad %{public}s", ELEM_NAME(element), PAD_NAME(pad));
158     {
159         std::unique_lock<std::mutex> lock(padProbeMutex_);
160         gulong probeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, ProbeCallback, this, nullptr);
161         if (probeId == 0) {
162             MEDIA_LOGE("add probe for %{public}s's pad %{public}s failed",
163                 GST_ELEMENT_NAME(GST_PAD_PARENT(pad)), PAD_NAME(pad));
164             return false;
165         }
166         (void)padProbes_.emplace(pad, probeId);
167         gst_object_ref(pad);
168     }
169     {
170         std::unique_lock<std::mutex> lock(trackInfoMutex_);
171         Format innerMeta;
172         (void)trackInfos_.emplace(pad, innerMeta);
173     }
174 
175     return true;
176 }
177 
AddProbeToPadList(const GstElement * element,GList & list)178 bool PlayerTrackParse::AddProbeToPadList(const GstElement *element, GList &list)
179 {
180     MEDIA_LOGD("AddProbeToPadList element %{public}s", ELEM_NAME(element));
181     for (GList *padNode = g_list_first(&list); padNode != nullptr; padNode = padNode->next) {
182         if (padNode->data == nullptr) {
183             continue;
184         }
185 
186         GstPad *pad = reinterpret_cast<GstPad *>(padNode->data);
187         if (!AddProbeToPad(element, pad)) {
188             return false;
189         }
190     }
191 
192     return true;
193 }
194 
OnPadAddedCb(const GstElement * element,GstPad * pad,gpointer userData)195 void PlayerTrackParse::OnPadAddedCb(const GstElement *element, GstPad *pad, gpointer userData)
196 {
197     if (element == nullptr || pad ==  nullptr || userData == nullptr) {
198         MEDIA_LOGE("param is nullptr");
199         return;
200     }
201 
202     auto playerTrackParse = reinterpret_cast<PlayerTrackParse *>(userData);
203     (void)playerTrackParse->AddProbeToPad(element, pad);
204 }
205 
SetDemuxerElementFind(bool isFind)206 void PlayerTrackParse::SetDemuxerElementFind(bool isFind)
207 {
208     demuxerElementFind_ = isFind;
209 }
210 
GetDemuxerElementFind() const211 bool PlayerTrackParse::GetDemuxerElementFind() const
212 {
213     return demuxerElementFind_;
214 }
215 
SetUpDemuxerElementCb(GstElement & elem)216 void PlayerTrackParse::SetUpDemuxerElementCb(GstElement &elem)
217 {
218     MEDIA_LOGD("SetUpDemuxerElementCb elem %{public}s", ELEM_NAME(&elem));
219     if (!AddProbeToPadList(&elem, *elem.srcpads)) {
220         return;
221     }
222     {
223         std::unique_lock<std::mutex> lock(signalIdMutex_);
224         gulong signalId = g_signal_connect(&elem, "pad-added", G_CALLBACK(PlayerTrackParse::OnPadAddedCb), this);
225         CHECK_AND_RETURN_LOG(signalId != 0, "listen to pad-added failed");
226         (void)signalIds_.emplace_back(SignalInfo { &elem, signalId });
227     }
228 }
229 
SetUpParseElementCb(GstElement & elem)230 void PlayerTrackParse::SetUpParseElementCb(GstElement &elem)
231 {
232     MEDIA_LOGD("SetUpParseElementCb elem %{public}s", ELEM_NAME(&elem));
233     (void)AddProbeToPadList(&elem, *elem.srcpads);
234 }
235 
Stop()236 void PlayerTrackParse::Stop()
237 {
238     MEDIA_LOGD("Stop");
239     {
240         std::unique_lock<std::mutex> lock(trackInfoMutex_);
241         trackInfos_.clear();
242     }
243     {
244         std::unique_lock<std::mutex> lock(padProbeMutex_);
245         // PlayerTrackParse::ProbeCallback
246         for (auto &[pad, probeId] : padProbes_) {
247             MEDIA_LOGD("remove_probe pad %{public}s", PAD_NAME(pad));
248             gst_pad_remove_probe(pad, probeId);
249             gst_object_unref(pad);
250         }
251         padProbes_.clear();
252     }
253     {
254         std::unique_lock<std::mutex> lock(signalIdMutex_);
255         // PlayerTrackParse::OnPadAddedCb
256         for (auto &item : signalIds_) {
257             g_signal_handler_disconnect(item.element, item.signalId);
258         }
259         signalIds_.clear();
260     }
261 }
262 }
263 }
264