• 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 #include "scope_guard.h"
24 
25 namespace {
26     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerTrackParse"};
27 }
28 
29 namespace OHOS {
30 namespace Media {
31 inline constexpr std::string_view INNER_META_KEY_TRACK_INNER_INDEX = "track_inner_index";
32 
33 static const std::unordered_map<std::string_view, std::string_view> INNER_KEY_TO_PLAYER_KEY = {
34     { INNER_META_KEY_BITRATE, PlayerKeys::PLAYER_BITRATE },
35     { INNER_META_KEY_CHANNEL_COUNT, PlayerKeys::PLAYER_CHANNELS },
36     { INNER_META_KEY_FRAMERATE, PlayerKeys::PLAYER_FRAMERATE },
37     { INNER_META_KEY_VIDEO_HEIGHT, PlayerKeys::PLAYER_HEIGHT },
38     { INNER_META_KEY_LANGUAGE, PlayerKeys::PLAYER_LANGUGAE },
39     { INNER_META_KEY_MIME_TYPE, PlayerKeys::PLAYER_MIME },
40     { INNER_META_KEY_SAMPLE_RATE, PlayerKeys::PLAYER_SAMPLE_RATE },
41     { INNER_META_KEY_TRACK_INDEX, PlayerKeys::PLAYER_TRACK_INDEX },
42     { INNER_META_KEY_TRACK_TYPE, PlayerKeys::PLAYER_TRACK_TYPE },
43     { INNER_META_KEY_VIDEO_WIDTH, PlayerKeys::PLAYER_WIDTH },
44     { INNER_META_KEY_TRACK_INNER_INDEX, INNER_META_KEY_TRACK_INNER_INDEX },
45 };
46 
Create()47 std::shared_ptr<PlayerTrackParse> PlayerTrackParse::Create()
48 {
49     std::shared_ptr<PlayerTrackParse> trackInfo = std::make_shared<PlayerTrackParse>();
50     return trackInfo;
51 }
52 
PlayerTrackParse()53 PlayerTrackParse::PlayerTrackParse()
54 {
55     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
56 }
57 
~PlayerTrackParse()58 PlayerTrackParse::~PlayerTrackParse()
59 {
60     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
61 }
62 
OnElementSetup(GstElement & elem)63 void PlayerTrackParse::OnElementSetup(GstElement &elem)
64 {
65     CHECK_AND_RETURN_LOG(isStopping_.load() == false, "playbin is stopping");
66     const gchar *metadata = gst_element_get_metadata(&elem, GST_ELEMENT_METADATA_KLASS);
67     CHECK_AND_RETURN_LOG(metadata != nullptr, "gst_element_get_metadata return nullptr");
68     std::string elementName(GST_ELEMENT_NAME(&elem));
69 
70     std::string metaStr(metadata);
71     if (metaStr.find("Codec/Demuxer") != std::string::npos && elementName.find("hlsdemux") == std::string::npos) {
72         // Collect trackinfo information
73         std::unique_lock<std::mutex> lock(trackInfoMutex_);
74         DemuxInfo demux(&elem);
75         trackVec_.push_back(demux);
76         lock.unlock();
77         SetUpDemuxerElementCb(elem);
78     }
79 
80     if (metaStr.find("Codec/Parser") != std::string::npos) {
81         // HLS stream demux has no width and height data, and requires prase as a supplement
82         SetUpDemuxerElementCb(elem);
83     }
84 
85     if (elementName.find("inputselector") != std::string::npos) {
86         // Detect resolution switching events
87         std::unique_lock<std::mutex> lock(trackInfoMutex_);
88         InputSelectInfo info;
89         inputSelectMap_.insert(std::pair<GstElement *, InputSelectInfo>(&elem, info));
90         lock.unlock();
91         SetUpInputSelectElementCb(elem);
92     }
93 }
94 
OnElementUnSetup(GstElement & elem)95 void PlayerTrackParse::OnElementUnSetup(GstElement &elem)
96 {
97     const gchar *metadata = gst_element_get_metadata(&elem, GST_ELEMENT_METADATA_KLASS);
98     CHECK_AND_RETURN_LOG(metadata != nullptr, "gst_element_get_metadata return nullptr");
99     std::string elementName(GST_ELEMENT_NAME(&elem));
100     std::string metaStr(metadata);
101 
102     std::unique_lock<std::mutex> lock(trackInfoMutex_);
103     if (metaStr.find("Codec/Demuxer") != std::string::npos) {
104         MEDIA_LOGI("UnSetUp Demuxer elem %{public}s", ELEM_NAME(&elem));
105         for (auto it = trackVec_.begin(); it != trackVec_.end(); it++) {
106             if (it->demux == &elem) {
107                 trackVec_.erase(it);
108                 MEDIA_LOGI("remove demux from trackVec 0x%{public}06" PRIXPTR, FAKE_POINTER(&elem));
109                 break;
110             }
111         }
112     }
113 
114     if (elementName.find("inputselector") != std::string::npos) {
115         MEDIA_LOGI("UnSetUp inputselector elem %{public}s", ELEM_NAME(&elem));
116 
117         auto it = inputSelectMap_.find(&elem);
118         if (it != inputSelectMap_.end()) {
119             inputSelectMap_.erase(it);
120         }
121 
122         if (inputSelectMap_.empty()) {
123             findTrackInfo_ = false;
124             MEDIA_LOGI("Remove all inputselect plugins");
125         }
126     }
127 
128     RemoveSignalIds(&elem);
129 }
130 
SetUpInputSelectElementCb(GstElement & elem)131 void PlayerTrackParse::SetUpInputSelectElementCb(GstElement &elem)
132 {
133     MEDIA_LOGD("SetUpInputSelectElementCb elem %{public}s", ELEM_NAME(&elem));
134     {
135         std::unique_lock<std::mutex> lock(signalIdMutex_);
136         gulong signalId = g_signal_connect(&elem, "pad-added",
137             G_CALLBACK(PlayerTrackParse::OnInputSelectPadAddedCb), this);
138         CHECK_AND_RETURN_LOG(signalId != 0, "listen to pad-added failed");
139         AddSignalIds(&elem, signalId);
140     }
141 }
142 
OnInputSelectPadAddedCb(const GstElement * element,GstPad * pad,gpointer userData)143 void PlayerTrackParse::OnInputSelectPadAddedCb(const GstElement *element, GstPad *pad, gpointer userData)
144 {
145     CHECK_AND_RETURN_LOG(element != nullptr && pad != nullptr && userData != nullptr, "param is nullptr");
146 
147     auto playerTrackParse = reinterpret_cast<PlayerTrackParse *>(userData);
148     (void)playerTrackParse->InputSelectAddProbeToPad(element, pad);
149 }
150 
InputSelectAddProbeToPad(const GstElement * element,GstPad * pad)151 bool PlayerTrackParse::InputSelectAddProbeToPad(const GstElement *element, GstPad *pad)
152 {
153     {
154         std::unique_lock<std::mutex> lock(trackInfoMutex_);
155         auto it = inputSelectMap_.find(const_cast<GstElement *>(element));
156         CHECK_AND_RETURN_RET_LOG(it != inputSelectMap_.end(), false, "Unregistered elements");
157         it->second.padIndexMap[pad] = it->second.padCount;
158         it->second.padCount++;
159         MEDIA_LOGD("AddProbeToPad element %{public}s, pad %{public}s, count %{public}d",
160             ELEM_NAME(element), PAD_NAME(pad), it->second.padCount);
161     }
162 
163     std::unique_lock<std::mutex> lock(padProbeMutex_);
164     gulong probeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
165         InputSelectProbeCallback, this, nullptr);
166     CHECK_AND_RETURN_RET_LOG(probeId != 0, false, "add probe for %{public}s's pad %{public}s failed",
167         GST_ELEMENT_NAME(GST_PAD_PARENT(pad)), PAD_NAME(pad));
168     (void)padProbes_.emplace(pad, probeId);
169     gst_object_ref(pad);
170     return true;
171 }
172 
InputSelectProbeCallback(GstPad * pad,GstPadProbeInfo * info,gpointer userData)173 GstPadProbeReturn PlayerTrackParse::InputSelectProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer userData)
174 {
175     CHECK_AND_RETURN_RET_LOG(pad != nullptr && info != nullptr && userData != nullptr,
176         GST_PAD_PROBE_OK, "param is nullptr");
177 
178     auto playerTrackParse = reinterpret_cast<PlayerTrackParse *>(userData);
179     return playerTrackParse->GetUsedDemux(pad, info);
180 }
181 
GetUsedDemux(GstPad * pad,GstPadProbeInfo * info)182 GstPadProbeReturn PlayerTrackParse::GetUsedDemux(GstPad *pad, GstPadProbeInfo *info)
183 {
184     (void)pad;
185     CHECK_AND_RETURN_RET((static_cast<unsigned int>(info->type) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) != 0,
186         GST_PAD_PROBE_OK);
187 
188     GstEvent *event = gst_pad_probe_info_get_event(info);
189     CHECK_AND_RETURN_RET_LOG(event != nullptr, GST_PAD_PROBE_OK, "event is null");
190     if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START) {
191         return GST_PAD_PROBE_OK;
192     }
193 
194     const gchar *current_stream_id;
195     gst_event_parse_stream_start (event, &current_stream_id);
196     CHECK_AND_RETURN_RET_LOG(current_stream_id != nullptr, GST_PAD_PROBE_OK, "current_stream_id is nullptr");
197 
198     std::unique_lock<std::mutex> lock(trackInfoMutex_);
199     for (int32_t i = 0; i < static_cast<int32_t>(trackVec_.size()); i++) {
200         for (auto padIt = trackVec_[i].trackInfos.begin(); padIt != trackVec_[i].trackInfos.end(); padIt++) {
201             gchar *stream_id = gst_pad_get_stream_id(padIt->first);
202             CHECK_AND_CONTINUE(stream_id != nullptr && current_stream_id != nullptr);
203             if (strcmp(current_stream_id, stream_id) == 0) {
204                 findTrackInfo_ = true;
205                 trackVec_[i].inUse = true;
206                 int32_t index = GetInputSelectPadIndex(pad);
207                 padIt->second.PutIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), index);
208                 MEDIA_LOGD("Matched to pad:0x%{public}06" PRIXPTR ", index:%{public}d, streamid:%{public}s",
209                     FAKE_POINTER(padIt->first), index, stream_id);
210                 UpdateTrackInfo();
211                 g_free (stream_id);
212                 return GST_PAD_PROBE_OK;
213             }
214             g_free (stream_id);
215         }
216     }
217 
218     return GST_PAD_PROBE_OK;
219 }
220 
GetInputSelectPadIndex(GstPad * pad)221 int32_t PlayerTrackParse::GetInputSelectPadIndex(GstPad *pad)
222 {
223     CHECK_AND_RETURN_RET(pad != nullptr, -1);
224     int32_t index = -1;
225     for (auto inputIt = inputSelectMap_.begin(); inputIt != inputSelectMap_.end(); inputIt++) {
226         auto inputPadIt = inputIt ->second.padIndexMap.find(pad);
227         if (inputPadIt != inputIt ->second.padIndexMap.end()) {
228             index = inputPadIt->second;
229             break;
230         }
231     }
232     return index;
233 }
234 
IsSameStreamId(GstPad * padA,GstPad * padB)235 bool PlayerTrackParse::IsSameStreamId(GstPad *padA, GstPad *padB)
236 {
237     gchar *streamIdA = gst_pad_get_stream_id(padA);
238     CHECK_AND_RETURN_RET_LOG(streamIdA != nullptr, false, "streamIdA is nullptr");
239     ON_SCOPE_EXIT(0) { g_free(streamIdA); };
240     gchar *streamIdB = gst_pad_get_stream_id(padB);
241     CHECK_AND_RETURN_RET_LOG(streamIdB != nullptr, false, "streamIdB is nullptr");
242     CANCEL_SCOPE_EXIT_GUARD(0);
243 
244     bool ret = (strcmp(streamIdA, streamIdB) == 0);
245     g_free(streamIdA);
246     g_free(streamIdB);
247     return ret;
248 }
249 
HasSameStreamIdInDemux(GstPad * pad)250 bool PlayerTrackParse::HasSameStreamIdInDemux(GstPad *pad)
251 {
252     for (int32_t i = 0; i < static_cast<int32_t>(trackVec_.size()); i++) {
253         for (auto padIt = trackVec_[i].trackInfos.begin(); padIt != trackVec_[i].trackInfos.end(); padIt++) {
254             CHECK_AND_RETURN_RET(!IsSameStreamId(pad, padIt->first), true);
255         }
256     }
257 
258     return false;
259 }
260 
GetTrackInfo(int32_t index,int32_t & innerIndex,int32_t & trackType)261 int32_t PlayerTrackParse::GetTrackInfo(int32_t index, int32_t &innerIndex, int32_t &trackType)
262 {
263     std::unique_lock<std::mutex> lock(trackInfoMutex_);
264     CHECK_AND_RETURN_RET_LOG(findTrackInfo_, MSERR_INVALID_OPERATION, "trackinfo not found");
265     CHECK_AND_RETURN_RET_LOG(index >= 0, MSERR_INVALID_VAL, "Invalid index %{public}d", index);
266 
267     StartUpdateTrackInfo();
268 
269     for (int32_t i = 0; i < static_cast<int32_t>(videoTracks_.size()); i++) {
270         int32_t trackIndex = -1;
271         videoTracks_[i].GetIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), trackIndex);
272         if (trackIndex == index) {
273             trackType = MediaType::MEDIA_TYPE_VID;
274             videoTracks_[i].GetIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), innerIndex);
275             MEDIA_LOGI("index:0x%{public}d inner:0x%{public}d Type:0x%{public}d", index, innerIndex, trackType);
276             return MSERR_OK;
277         }
278     }
279 
280     for (int32_t i = 0; i < static_cast<int32_t>(audioTracks_.size()); i++) {
281         int32_t trackIndex = -1;
282         audioTracks_[i].GetIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), trackIndex);
283         if (trackIndex == index) {
284             trackType = MediaType::MEDIA_TYPE_AUD;
285             audioTracks_[i].GetIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), innerIndex);
286             MEDIA_LOGI("index:0x%{public}d inner:0x%{public}d Type:0x%{public}d", index, innerIndex, trackType);
287             return MSERR_OK;
288         }
289     }
290 
291     for (int32_t i = 0; i < static_cast<int32_t>(subtitleTracks_.size()); i++) {
292         int32_t trackIndex = -1;
293         subtitleTracks_[i].GetIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), trackIndex);
294         if (trackIndex == index) {
295             trackType = MediaType::MEDIA_TYPE_SUBTITLE;
296             subtitleTracks_[i].GetIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), innerIndex);
297             MEDIA_LOGI("index:0x%{public}d inner:0x%{public}d Type:0x%{public}d", index, innerIndex, trackType);
298             return MSERR_OK;
299         }
300     }
301 
302     return MSERR_INVALID_VAL;
303 }
304 
GetTrackIndex(int32_t innerIndex,int32_t trackType,int32_t & index)305 int32_t PlayerTrackParse::GetTrackIndex(int32_t innerIndex, int32_t trackType, int32_t &index)
306 {
307     std::unique_lock<std::mutex> lock(trackInfoMutex_);
308     CHECK_AND_RETURN_RET_LOG(findTrackInfo_, MSERR_INVALID_OPERATION, "trackinfo not found");
309     CHECK_AND_RETURN_RET_LOG(trackType >= MediaType::MEDIA_TYPE_AUD && trackType <= MediaType::MEDIA_TYPE_SUBTITLE,
310         MSERR_INVALID_VAL, "Invalid trackType %{public}d", trackType);
311     CHECK_AND_RETURN_RET_LOG(innerIndex >= 0, MSERR_INVALID_VAL, "Invalid innerIndex %{public}d", innerIndex);
312 
313     StartUpdateTrackInfo();
314 
315     if (trackType == MediaType::MEDIA_TYPE_AUD) {
316         for (int32_t i = 0; i < static_cast<int32_t>(audioTracks_.size()); i++) {
317             int32_t trackInnerIndex = -1;
318             audioTracks_[i].GetIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), trackInnerIndex);
319             if (trackInnerIndex == innerIndex) {
320                 audioTracks_[i].GetIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), index);
321                 MEDIA_LOGI("inner:0x%{public}d Type:0x%{public}d index:0x%{public}d", innerIndex, trackType, index);
322                 return MSERR_OK;
323             }
324         }
325     } else if (trackType == MediaType::MEDIA_TYPE_VID) {
326         for (int32_t i = 0; i < static_cast<int32_t>(videoTracks_.size()); i++) {
327             int32_t trackInnerIndex = -1;
328             videoTracks_[i].GetIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), trackInnerIndex);
329             if (trackInnerIndex == innerIndex) {
330                 videoTracks_[i].GetIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), index);
331                 MEDIA_LOGI("inner:0x%{public}d Type:0x%{public}d index:0x%{public}d", innerIndex, trackType, index);
332                 return MSERR_OK;
333             }
334         }
335     } else {
336         index = static_cast<size_t>(innerIndex) + videoTracks_.size() + audioTracks_.size();
337         MEDIA_LOGI("inner:0x%{public}d Type:0x%{public}d index:0x%{public}d", innerIndex, trackType, index);
338         return MSERR_OK;
339     }
340 
341     return MSERR_INVALID_VAL;
342 }
343 
StartUpdateTrackInfo()344 void PlayerTrackParse::StartUpdateTrackInfo()
345 {
346     if (!updateTrackInfo_) {
347         updateTrackInfo_ = true;
348         UpdateTrackInfo();
349     }
350 }
351 
UpdateTrackInfo()352 void PlayerTrackParse::UpdateTrackInfo()
353 {
354     if (!updateTrackInfo_) {
355         return;
356     }
357     CHECK_AND_RETURN(findTrackInfo_);
358     videoTracks_.clear();
359     audioTracks_.clear();
360     subtitleTracks_.clear();
361 
362     int32_t index;
363     int32_t baseIndex = 0;
364     std::map<int32_t, Format> tracks;
365     for (int32_t i = 0; i < static_cast<int32_t>(trackVec_.size()); i++) {
366         if (!trackVec_[i].inUse) {
367             continue;
368         }
369         for (auto &[pad, innerMeta] : trackVec_[i].trackInfos) {
370             // Sort trackinfo by index
371             innerMeta.GetIntValue(std::string(INNER_META_KEY_TRACK_INDEX), index);
372             (void)tracks.emplace(index + baseIndex, innerMeta);
373         }
374         baseIndex += trackVec_[i].trackcount;
375     }
376 
377     int32_t trackType = MediaType::MEDIA_TYPE_AUD;
378     for (auto &[ind, innerMeta] : tracks) {
379         Format outMeta;
380         innerMeta.GetIntValue(INNER_META_KEY_TRACK_TYPE, trackType);
381         ConvertToPlayerKeys(innerMeta, outMeta);
382         outMeta.PutIntValue(std::string(PlayerKeys::PLAYER_TRACK_INDEX), ind);
383         if (trackType == MediaType::MEDIA_TYPE_VID) {
384             videoTracks_.emplace_back(outMeta);
385         } else if (trackType == MediaType::MEDIA_TYPE_AUD) {
386             audioTracks_.emplace_back(outMeta);
387         } else if (trackType == MediaType::MEDIA_TYPE_SUBTITLE) {
388             subtitleTracks_.emplace_back(outMeta);
389         }
390     }
391     return;
392 }
393 
GetVideoTrackInfo(std::vector<Format> & videoTrack)394 int32_t PlayerTrackParse::GetVideoTrackInfo(std::vector<Format> &videoTrack)
395 {
396     std::unique_lock<std::mutex> lock(trackInfoMutex_);
397     CHECK_AND_RETURN_RET_LOG(findTrackInfo_, MSERR_INVALID_OPERATION, "trackinfo not found");
398     StartUpdateTrackInfo();
399     videoTrack.assign(videoTracks_.begin(), videoTracks_.end());
400     for (int32_t i = 0; i < static_cast<int32_t>(videoTracks_.size()); i++) {
401         videoTrack[i].RemoveKey(std::string(INNER_META_KEY_TRACK_INNER_INDEX));
402     }
403     return MSERR_OK;
404 }
405 
GetAudioTrackInfo(std::vector<Format> & audioTrack)406 int32_t PlayerTrackParse::GetAudioTrackInfo(std::vector<Format> &audioTrack)
407 {
408     std::unique_lock<std::mutex> lock(trackInfoMutex_);
409     CHECK_AND_RETURN_RET_LOG(findTrackInfo_, MSERR_INVALID_OPERATION, "trackinfo not found");
410     StartUpdateTrackInfo();
411     audioTrack.assign(audioTracks_.begin(), audioTracks_.end());
412     for (int32_t i = 0; i < static_cast<int32_t>(audioTrack.size()); i++) {
413         audioTrack[i].RemoveKey(std::string(INNER_META_KEY_TRACK_INNER_INDEX));
414     }
415     return MSERR_OK;
416 }
417 
GetSubtitleTrackInfo(std::vector<Format> & subtitleTrack)418 int32_t PlayerTrackParse::GetSubtitleTrackInfo(std::vector<Format> &subtitleTrack)
419 {
420     std::unique_lock<std::mutex> lock(trackInfoMutex_);
421     CHECK_AND_RETURN_RET_LOG(findTrackInfo_, MSERR_INVALID_OPERATION, "trackinfo not found");
422     StartUpdateTrackInfo();
423     subtitleTrack.assign(subtitleTracks_.begin(), subtitleTracks_.end());
424     for (int32_t i = 0; i < static_cast<int32_t>(subtitleTrack.size()); i++) {
425         subtitleTrack[i].RemoveKey(std::string(INNER_META_KEY_TRACK_INNER_INDEX));
426     }
427     return MSERR_OK;
428 }
429 
ConvertToPlayerKeys(const Format & innerMeta,Format & outMeta) const430 void PlayerTrackParse::ConvertToPlayerKeys(const Format &innerMeta, Format &outMeta) const
431 {
432     for (const auto &[innerKey, playerKey] : INNER_KEY_TO_PLAYER_KEY) {
433         if (!innerMeta.ContainKey(innerKey)) {
434             continue;
435         }
436 
437         std::string strVal;
438         int32_t intVal;
439         double douVal;
440         FormatDataType type = innerMeta.GetValueType(innerKey);
441         switch (type) {
442             case FORMAT_TYPE_STRING:
443                 innerMeta.GetStringValue(innerKey, strVal);
444                 outMeta.PutStringValue(std::string(playerKey), strVal);
445                 break;
446             case FORMAT_TYPE_INT32:
447                 innerMeta.GetIntValue(innerKey, intVal);
448                 outMeta.PutIntValue(std::string(playerKey), intVal);
449                 break;
450             case FORMAT_TYPE_DOUBLE:
451                 innerMeta.GetDoubleValue(innerKey, douVal);
452                 outMeta.PutDoubleValue(std::string(playerKey), douVal);
453                 break;
454             default:
455                 break;
456         }
457     }
458 }
459 
ProbeCallback(GstPad * pad,GstPadProbeInfo * info,gpointer userData)460 GstPadProbeReturn PlayerTrackParse::ProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer userData)
461 {
462     CHECK_AND_RETURN_RET_LOG(pad != nullptr && info != nullptr && userData != nullptr,
463         GST_PAD_PROBE_OK, "param is invalid");
464 
465     auto playerTrackParse = reinterpret_cast<PlayerTrackParse *>(userData);
466     return playerTrackParse->GetTrackParse(pad, info);
467 }
468 
GetTrackParse(GstPad * pad,GstPadProbeInfo * info)469 GstPadProbeReturn PlayerTrackParse::GetTrackParse(GstPad *pad, GstPadProbeInfo *info)
470 {
471     std::unique_lock<std::mutex> lock(trackInfoMutex_);
472     bool isDemuxPad = (parsePadSet_.count(pad) == 0);
473     for (int32_t i = 0; i < static_cast<int32_t>(trackVec_.size()); i++) {
474         if (isDemuxPad) {
475             auto padIt = trackVec_[i].trackInfos.find(pad);
476             if (padIt != trackVec_[i].trackInfos.end()) {
477                 return ParseTrackInfo(pad, info, padIt->second);
478             }
479             continue;
480         }
481 
482         for (auto padIt = trackVec_[i].trackInfos.begin(); padIt != trackVec_[i].trackInfos.end(); padIt++) {
483             if (IsSameStreamId(pad, padIt->first)) {
484                 return ParseTrackInfo(pad, info, padIt->second);
485             }
486         }
487     }
488     return GST_PAD_PROBE_OK;
489 }
490 
ParseTrackInfo(GstPad * pad,GstPadProbeInfo * info,Format & format)491 GstPadProbeReturn PlayerTrackParse::ParseTrackInfo(GstPad *pad, GstPadProbeInfo *info, Format &format)
492 {
493     if (static_cast<unsigned int>(info->type) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) {
494         GstEvent *event = gst_pad_probe_info_get_event(info);
495         CHECK_AND_RETURN_RET_LOG(event != nullptr, GST_PAD_PROBE_OK, "event is null");
496 
497         if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
498             GstTagList *tagList = nullptr;
499             gst_event_parse_tag(event, &tagList);
500             CHECK_AND_RETURN_RET_LOG(tagList != nullptr, GST_PAD_PROBE_OK, "tags is nullptr");
501             GstMetaParser::ParseTagList(*tagList, format);
502             MEDIA_LOGI("catch tags at pad %{public}s:0x%{public}06" PRIXPTR, PAD_NAME(pad), FAKE_POINTER(pad));
503             (void)UpdateTrackInfo();
504         } else if (GST_EVENT_TYPE(event) == GST_EVENT_CAPS) {
505             GstCaps *caps = nullptr;
506             gst_event_parse_caps(event, &caps);
507             CHECK_AND_RETURN_RET_LOG(caps != nullptr, GST_PAD_PROBE_OK, "caps is nullptr");
508             GstMetaParser::ParseStreamCaps(*caps, format);
509             MEDIA_LOGI("catch caps at pad %{public}s:0x%{public}06" PRIXPTR, PAD_NAME(pad), FAKE_POINTER(pad));
510             (void)UpdateTrackInfo();
511         }
512     }
513     return GST_PAD_PROBE_OK;
514 }
515 
ParseSubtitlePadCaps(const GstElement * element,GstPad * pad,int32_t index,Format & innerMeta)516 void PlayerTrackParse::ParseSubtitlePadCaps(const GstElement *element, GstPad *pad, int32_t index, Format &innerMeta)
517 {
518     GstCaps *caps = gst_pad_query_caps(pad, nullptr);
519     GstMetaParser::ParseStreamCaps(*caps, innerMeta);
520     trackVec_[index].inUse = true;
521     (void)trackVec_[index].trackInfos.emplace(pad, innerMeta);
522     UpdateTrackInfo();
523     MEDIA_LOGI("subtitle parse:0x%{public}06" PRIXPTR " trackcount:0x%{public}d pad:0x%{public}06" PRIXPTR,
524         FAKE_POINTER(element), trackVec_[index].trackcount, FAKE_POINTER(pad));
525 }
526 
AddProbeToPad(const GstElement * element,GstPad * pad)527 bool PlayerTrackParse::AddProbeToPad(const GstElement *element, GstPad *pad)
528 {
529     MEDIA_LOGD("AddProbeToPad element %{public}s, pad %{public}s", ELEM_NAME(element), PAD_NAME(pad));
530     {
531         std::unique_lock<std::mutex> lock(padProbeMutex_);
532         gulong probeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, ProbeCallback, this, nullptr);
533         CHECK_AND_RETURN_RET_LOG(probeId != 0, false,
534             "add probe for %{public}s's pad %{public}s failed", GST_ELEMENT_NAME(GST_PAD_PARENT(pad)), PAD_NAME(pad));
535         (void)padProbes_.emplace(pad, probeId);
536         gst_object_ref(pad);
537     }
538     {
539         std::unique_lock<std::mutex> lock(trackInfoMutex_);
540 
541         const gchar *metadata = gst_element_get_metadata(const_cast<GstElement *>(element),
542             GST_ELEMENT_METADATA_KLASS);
543         CHECK_AND_RETURN_RET_LOG(metadata != nullptr, true, "gst_element_get_metadata return nullptr");
544         std::string metaStr(metadata);
545         if (metaStr.find("Codec/Parser/Subtitle") != std::string::npos && !HasSameStreamIdInDemux(pad)) {
546             MEDIA_LOGD("external subtitle parser, handle it as demux");
547             DemuxInfo demux(const_cast<GstElement *>(element));
548             trackVec_.push_back(demux);
549         } else if (metaStr.find("Codec/Parser") != std::string::npos) {
550             parsePadSet_.insert(pad);
551             MEDIA_LOGI("Parser pad:0x%{public}06" PRIXPTR, FAKE_POINTER(pad));
552             return true;
553         }
554 
555         for (int32_t i = 0; i < static_cast<int32_t>(trackVec_.size()); i++) {
556             if (trackVec_[i].demux != element) {
557                 continue;
558             }
559 
560             Format innerMeta;
561             innerMeta.PutIntValue(std::string(INNER_META_KEY_TRACK_INNER_INDEX), -1);
562             innerMeta.PutIntValue(std::string(INNER_META_KEY_TRACK_INDEX), trackVec_[i].trackcount);
563             trackVec_[i].trackcount++;
564             if (metaStr.find("Codec/Parser/Subtitle") != std::string::npos && !HasSameStreamIdInDemux(pad)) {
565                 ParseSubtitlePadCaps(element, pad, i, innerMeta);
566                 continue;
567             }
568             (void)trackVec_[i].trackInfos.emplace(pad, innerMeta);
569             MEDIA_LOGI("demux:0x%{public}06" PRIXPTR " trackcount:0x%{public}d pad:0x%{public}06" PRIXPTR,
570                 FAKE_POINTER(element), trackVec_[i].trackcount, FAKE_POINTER(pad));
571         }
572     }
573 
574     return true;
575 }
576 
AddProbeToPadList(GstElement * element,GList & list)577 bool PlayerTrackParse::AddProbeToPadList(GstElement *element, GList &list)
578 {
579     MEDIA_LOGD("AddProbeToPadList element %{public}s", ELEM_NAME(element));
580     for (GList *padNode = g_list_first(&list); padNode != nullptr; padNode = padNode->next) {
581         CHECK_AND_CONTINUE(padNode->data != nullptr);
582 
583         GstPad *pad = reinterpret_cast<GstPad *>(padNode->data);
584         CHECK_AND_RETURN_RET(AddProbeToPad(element, pad), false);
585     }
586 
587     return true;
588 }
589 
OnPadAddedCb(const GstElement * element,GstPad * pad,gpointer userData)590 void PlayerTrackParse::OnPadAddedCb(const GstElement *element, GstPad *pad, gpointer userData)
591 {
592     CHECK_AND_RETURN_LOG(element != nullptr && pad != nullptr && userData != nullptr, "param is nullptr");
593 
594     auto playerTrackParse = reinterpret_cast<PlayerTrackParse *>(userData);
595     (void)playerTrackParse->AddProbeToPad(element, pad);
596 }
597 
FindTrackInfo()598 bool PlayerTrackParse::FindTrackInfo()
599 {
600     std::unique_lock<std::mutex> lock(trackInfoMutex_);
601     return findTrackInfo_;
602 }
603 
SetUpDemuxerElementCb(GstElement & elem)604 void PlayerTrackParse::SetUpDemuxerElementCb(GstElement &elem)
605 {
606     MEDIA_LOGD("SetUpDemuxerElementCb elem %{public}s", ELEM_NAME(&elem));
607     CHECK_AND_RETURN(AddProbeToPadList(&elem, *elem.srcpads));
608     {
609         std::unique_lock<std::mutex> lock(signalIdMutex_);
610         gulong signalId = g_signal_connect(&elem, "pad-added", G_CALLBACK(PlayerTrackParse::OnPadAddedCb), this);
611         CHECK_AND_RETURN_LOG(signalId != 0, "listen to pad-added failed");
612         AddSignalIds(&elem, signalId);
613     }
614 }
615 
Stop()616 void PlayerTrackParse::Stop()
617 {
618     MEDIA_LOGD("Stop");
619     isStopping_ = true;
620     {
621         std::unique_lock<std::mutex> lock(trackInfoMutex_);
622         videoTracks_.clear();
623         audioTracks_.clear();
624         updateTrackInfo_ = false;
625         findTrackInfo_ = false;
626         inputSelectMap_.clear();
627         parsePadSet_.clear();
628         trackVec_.clear();
629     }
630     {
631         std::unique_lock<std::mutex> lock(padProbeMutex_);
632         // PlayerTrackParse::ProbeCallback
633         for (auto &[pad, probeId] : padProbes_) {
634             MEDIA_LOGD("remove_probe pad %{public}s", PAD_NAME(pad));
635             gst_pad_remove_probe(pad, probeId);
636             gst_object_unref(pad);
637         }
638         padProbes_.clear();
639     }
640     {
641         std::unique_lock<std::mutex> lock(signalIdMutex_);
642         // PlayerTrackParse::OnPadAddedCb
643         for (auto &item : signalIds_) {
644             for (auto id : item.second) {
645                 g_signal_handler_disconnect(item.first, id);
646             }
647         }
648         signalIds_.clear();
649     }
650 }
651 }
652 }
653