Line data Source code
1 : /*
2 : * Copyright (C) 2022 Sky UK
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Lesser General Public
6 : * License as published by the Free Software Foundation;
7 : * version 2.1 of the License.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Lesser General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public
15 : * License along with this library; if not, write to the Free Software
16 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 : */
18 :
19 : #include "MediaPlayerManager.h"
20 : #include "GstreamerCatLog.h"
21 : #include "IMessageQueue.h"
22 : #include "MediaPlayerClientBackend.h"
23 :
24 : std::mutex MediaPlayerManager::m_mediaPlayerClientsMutex;
25 : std::map<const GstObject *, MediaPlayerManager::MediaPlayerClientInfo> MediaPlayerManager::m_mediaPlayerClientsInfo;
26 : #define GST_CAT_DEFAULT rialtoGStreamerCat
27 295 : MediaPlayerManager::MediaPlayerManager() : m_currentGstBinParent(nullptr) {}
28 :
29 295 : MediaPlayerManager::~MediaPlayerManager()
30 : {
31 295 : releaseMediaPlayerClient();
32 : }
33 :
34 167 : bool MediaPlayerManager::attachMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth,
35 : const uint32_t maxVideoHeight, bool isLive)
36 : {
37 : // Read m_client and m_currentGstBinParent under mutex to avoid data race
38 167 : std::weak_ptr<GStreamerMSEMediaPlayerClient> clientCopy;
39 167 : const GstObject *currentParent = nullptr;
40 : {
41 167 : std::lock_guard<std::mutex> guard(m_mediaPlayerClientsMutex);
42 167 : clientCopy = m_client;
43 167 : currentParent = m_currentGstBinParent;
44 : }
45 :
46 167 : if (!clientCopy.lock())
47 : {
48 166 : createMediaPlayerClient(gstBinParent, maxVideoWidth, maxVideoHeight, isLive);
49 : }
50 1 : else if (gstBinParent != currentParent)
51 : {
52 : // New parent gst bin, release old client and create new
53 1 : releaseMediaPlayerClient();
54 1 : createMediaPlayerClient(gstBinParent, maxVideoWidth, maxVideoHeight, isLive);
55 : }
56 :
57 : // Verify attachment succeeded, re-read m_client since createMediaPlayerClient() modified it
58 : {
59 167 : std::lock_guard<std::mutex> guard(m_mediaPlayerClientsMutex);
60 167 : clientCopy = m_client;
61 : }
62 :
63 167 : if (!clientCopy.lock())
64 : {
65 4 : GST_ERROR("Failed to attach the media player client");
66 4 : return false;
67 : }
68 :
69 163 : return true;
70 167 : }
71 :
72 1866 : std::shared_ptr<GStreamerMSEMediaPlayerClient> MediaPlayerManager::getMediaPlayerClient() const
73 : {
74 1866 : return m_client.lock();
75 : }
76 :
77 9 : bool MediaPlayerManager::hasControl()
78 : {
79 9 : if (m_client.lock())
80 : {
81 8 : std::lock_guard<std::mutex> guard(m_mediaPlayerClientsMutex);
82 :
83 8 : auto it = m_mediaPlayerClientsInfo.find(m_currentGstBinParent);
84 8 : if (it != m_mediaPlayerClientsInfo.end())
85 : {
86 8 : if (it->second.controller == this)
87 : {
88 6 : return true;
89 : }
90 : else
91 : { // in case there's no controller anymore
92 2 : return acquireControl(it->second);
93 : }
94 : }
95 : else
96 : {
97 0 : GST_WARNING("Could not find the attached media player client");
98 : }
99 8 : }
100 : else
101 : {
102 1 : GST_WARNING("No media player client attached");
103 : }
104 :
105 1 : return false;
106 : }
107 :
108 587 : void MediaPlayerManager::releaseMediaPlayerClient()
109 : {
110 587 : if (m_client.lock())
111 : {
112 163 : std::lock_guard<std::mutex> guard(m_mediaPlayerClientsMutex);
113 :
114 163 : auto it = m_mediaPlayerClientsInfo.find(m_currentGstBinParent);
115 163 : if (it != m_mediaPlayerClientsInfo.end())
116 : {
117 163 : it->second.refCount--;
118 163 : if (it->second.refCount == 0)
119 : {
120 159 : it->second.client->stop();
121 159 : it->second.client->stopStreaming();
122 159 : it->second.client->destroyClientBackend();
123 159 : m_mediaPlayerClientsInfo.erase(it);
124 : }
125 : else
126 : {
127 4 : if (it->second.controller == this)
128 4 : it->second.controller = nullptr;
129 : }
130 163 : m_client.reset();
131 163 : m_currentGstBinParent = nullptr;
132 : }
133 : else
134 : {
135 0 : GST_ERROR("Could not find the attached media player client");
136 : }
137 163 : }
138 587 : }
139 :
140 2 : bool MediaPlayerManager::acquireControl(MediaPlayerClientInfo &mediaPlayerClientInfo)
141 : {
142 2 : if (mediaPlayerClientInfo.controller == nullptr)
143 : {
144 1 : mediaPlayerClientInfo.controller = this;
145 1 : return true;
146 : }
147 :
148 1 : return false;
149 : }
150 :
151 167 : void MediaPlayerManager::createMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth,
152 : const uint32_t maxVideoHeight, bool isLive)
153 : {
154 167 : std::lock_guard<std::mutex> guard(m_mediaPlayerClientsMutex);
155 :
156 167 : auto it = m_mediaPlayerClientsInfo.find(gstBinParent);
157 167 : if (it != m_mediaPlayerClientsInfo.end())
158 : {
159 4 : it->second.refCount++;
160 4 : m_client = it->second.client;
161 4 : m_currentGstBinParent = gstBinParent;
162 : }
163 : else
164 : {
165 : std::shared_ptr<firebolt::rialto::client::MediaPlayerClientBackendInterface> clientBackend =
166 163 : std::make_shared<firebolt::rialto::client::MediaPlayerClientBackend>();
167 : std::shared_ptr<GStreamerMSEMediaPlayerClient> client =
168 326 : std::make_shared<GStreamerMSEMediaPlayerClient>(IMessageQueueFactory::createFactory(), clientBackend,
169 163 : maxVideoWidth, maxVideoHeight, isLive);
170 :
171 163 : if (client->createBackend())
172 : {
173 : // Store the new client in global map
174 159 : MediaPlayerClientInfo newClientInfo;
175 159 : newClientInfo.client = client;
176 159 : newClientInfo.controller = this;
177 159 : newClientInfo.refCount = 1;
178 159 : m_mediaPlayerClientsInfo.insert(
179 318 : std::pair<const GstObject *, MediaPlayerClientInfo>(gstBinParent, newClientInfo));
180 :
181 : // Store client info in object
182 159 : m_client = client;
183 159 : m_currentGstBinParent = gstBinParent;
184 : }
185 : else
186 : {
187 4 : GST_ERROR("Failed to create the media player client backend");
188 4 : return;
189 : }
190 167 : }
191 : }
|