|
Lines 26-38
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec1
|
| 26 |
|
26 |
|
| 27 |
#if ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(GSTREAMER) |
27 |
#if ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(GSTREAMER) |
| 28 |
|
28 |
|
| 29 |
#include "AudioTrackPrivate.h" |
29 |
#include "AudioTrackPrivateMediaStream.h" |
| 30 |
#include "GStreamerAudioData.h" |
30 |
#include "GStreamerAudioData.h" |
| 31 |
#include "GStreamerCommon.h" |
31 |
#include "GStreamerCommon.h" |
| 32 |
#include "MediaSampleGStreamer.h" |
32 |
#include "MediaSampleGStreamer.h" |
| 33 |
#include "MediaStreamPrivate.h" |
33 |
#include "MediaStreamPrivate.h" |
| 34 |
#include "MediaStreamTrackPrivate.h" |
34 |
#include "VideoTrackPrivateMediaStream.h" |
| 35 |
#include "VideoTrackPrivate.h" |
|
|
| 36 |
|
35 |
|
| 37 |
#include <gst/app/gstappsrc.h> |
36 |
#include <gst/app/gstappsrc.h> |
| 38 |
#include <wtf/UUID.h> |
37 |
#include <wtf/UUID.h> |
|
Lines 40-63
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec2
|
| 40 |
|
39 |
|
| 41 |
using namespace WebCore; |
40 |
using namespace WebCore; |
| 42 |
|
41 |
|
| 43 |
static void webkitMediaStreamSrcPushVideoSample(WebKitMediaStreamSrc*, GstSample*); |
42 |
static GstStaticPadTemplate videoSrcTemplate = GST_STATIC_PAD_TEMPLATE("video_src%u", GST_PAD_SRC, GST_PAD_SOMETIMES, |
| 44 |
static void webkitMediaStreamSrcPushAudioSample(WebKitMediaStreamSrc*, const GRefPtr<GstSample>&); |
|
|
| 45 |
static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc*, MediaStreamTrackPrivate&); |
| 46 |
static void webkitMediaStreamSrcRemoveTrackByType(WebKitMediaStreamSrc*, RealtimeMediaSource::Type); |
| 47 |
static void webkitMediaStreamSrcRemoveTrackObserver(WebKitMediaStreamSrc*, MediaStreamTrackPrivate&); |
| 48 |
static void webkitMediaStreamSrcPostStreamCollection(WebKitMediaStreamSrc*); |
| 49 |
static void webkitMediaStreamSrcRemovePad(WebKitMediaStreamSrc*, const char* padName); |
| 50 |
|
| 51 |
static GstStaticPadTemplate videoSrcTemplate = GST_STATIC_PAD_TEMPLATE("video_src", GST_PAD_SRC, GST_PAD_SOMETIMES, |
| 52 |
GST_STATIC_CAPS("video/x-raw;video/x-h264;video/x-vp8")); |
43 |
GST_STATIC_CAPS("video/x-raw;video/x-h264;video/x-vp8")); |
| 53 |
|
44 |
|
| 54 |
static GstStaticPadTemplate audioSrcTemplate = GST_STATIC_PAD_TEMPLATE("audio_src", GST_PAD_SRC, GST_PAD_SOMETIMES, |
45 |
static GstStaticPadTemplate audioSrcTemplate = GST_STATIC_PAD_TEMPLATE("audio_src%u", GST_PAD_SRC, GST_PAD_SOMETIMES, |
| 55 |
GST_STATIC_CAPS("audio/x-raw(ANY);")); |
46 |
GST_STATIC_CAPS("audio/x-raw(ANY);")); |
| 56 |
|
47 |
|
| 57 |
GST_DEBUG_CATEGORY_STATIC(webkitMediaStreamSrcDebug); |
48 |
GST_DEBUG_CATEGORY_STATIC(webkitMediaStreamSrcDebug); |
| 58 |
#define GST_CAT_DEFAULT webkitMediaStreamSrcDebug |
49 |
#define GST_CAT_DEFAULT webkitMediaStreamSrcDebug |
| 59 |
|
50 |
|
| 60 |
GRefPtr<GstTagList> mediaStreamTrackPrivateGetTags(MediaStreamTrackPrivate* track) |
51 |
GRefPtr<GstTagList> mediaStreamTrackPrivateGetTags(const MediaStreamTrackPrivate* track) |
| 61 |
{ |
52 |
{ |
| 62 |
auto tagList = adoptGRef(gst_tag_list_new_empty()); |
53 |
auto tagList = adoptGRef(gst_tag_list_new_empty()); |
| 63 |
|
54 |
|
|
Lines 100-154
GstStream* webkitMediaStreamNew(MediaStreamTrackPrivate* track)
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec3
|
| 100 |
return stream; |
91 |
return stream; |
| 101 |
} |
92 |
} |
| 102 |
|
93 |
|
| 103 |
class WebKitMediaStreamTrackObserver |
|
|
| 104 |
: public MediaStreamTrackPrivate::Observer |
| 105 |
, public RealtimeMediaSource::AudioSampleObserver |
| 106 |
, public RealtimeMediaSource::VideoSampleObserver { |
| 107 |
WTF_MAKE_FAST_ALLOCATED; |
| 108 |
public: |
| 109 |
virtual ~WebKitMediaStreamTrackObserver() { }; |
| 110 |
WebKitMediaStreamTrackObserver(GstElement* src) |
| 111 |
: m_src(src) { } |
| 112 |
void trackStarted(MediaStreamTrackPrivate&) final { }; |
| 113 |
|
| 114 |
void trackEnded(MediaStreamTrackPrivate& track) final |
| 115 |
{ |
| 116 |
if (m_src) |
| 117 |
webkitMediaStreamSrcTrackEnded(WEBKIT_MEDIA_STREAM_SRC(m_src), track); |
| 118 |
} |
| 119 |
|
| 120 |
void trackEnabledChanged(MediaStreamTrackPrivate& track) final |
| 121 |
{ |
| 122 |
m_enabled = track.enabled(); |
| 123 |
} |
| 124 |
|
| 125 |
void trackMutedChanged(MediaStreamTrackPrivate&) final { }; |
| 126 |
void trackSettingsChanged(MediaStreamTrackPrivate&) final { }; |
| 127 |
void readyStateChanged(MediaStreamTrackPrivate&) final { }; |
| 128 |
|
| 129 |
void videoSampleAvailable(MediaSample& sample) final |
| 130 |
{ |
| 131 |
if (!m_enabled || !m_src) |
| 132 |
return; |
| 133 |
|
| 134 |
auto* gstSample = static_cast<MediaSampleGStreamer*>(&sample)->platformSample().sample.gstSample; |
| 135 |
webkitMediaStreamSrcPushVideoSample(WEBKIT_MEDIA_STREAM_SRC(m_src), gstSample); |
| 136 |
} |
| 137 |
|
| 138 |
void audioSamplesAvailable(const MediaTime&, const PlatformAudioData& audioData, const AudioStreamDescription&, size_t) final |
| 139 |
{ |
| 140 |
if (!m_enabled || !m_src) |
| 141 |
return; |
| 142 |
|
| 143 |
auto data = static_cast<const GStreamerAudioData&>(audioData); |
| 144 |
webkitMediaStreamSrcPushAudioSample(WEBKIT_MEDIA_STREAM_SRC(m_src), data.getSample()); |
| 145 |
} |
| 146 |
|
| 147 |
private: |
| 148 |
GstElement* m_src { nullptr }; |
| 149 |
bool m_enabled { true }; |
| 150 |
}; |
| 151 |
|
| 152 |
class WebKitMediaStreamObserver : public MediaStreamPrivate::Observer { |
94 |
class WebKitMediaStreamObserver : public MediaStreamPrivate::Observer { |
| 153 |
WTF_MAKE_FAST_ALLOCATED; |
95 |
WTF_MAKE_FAST_ALLOCATED; |
| 154 |
public: |
96 |
public: |
|
Lines 166-193
public:
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec4
|
| 166 |
void didAddTrack(MediaStreamTrackPrivate& track) final |
108 |
void didAddTrack(MediaStreamTrackPrivate& track) final |
| 167 |
{ |
109 |
{ |
| 168 |
if (m_src) |
110 |
if (m_src) |
| 169 |
webkitMediaStreamSrcAddTrack(WEBKIT_MEDIA_STREAM_SRC(m_src), &track, false); |
111 |
webkitMediaStreamSrcAddTrack(WEBKIT_MEDIA_STREAM_SRC_CAST(m_src), &track, false); |
| 170 |
} |
112 |
} |
| 171 |
|
113 |
|
| 172 |
void didRemoveTrack(MediaStreamTrackPrivate& track) final |
114 |
void didRemoveTrack(MediaStreamTrackPrivate&) final; |
| 173 |
{ |
|
|
| 174 |
if (!m_src) |
| 175 |
return; |
| 176 |
|
| 177 |
webkitMediaStreamSrcRemoveTrackObserver(WEBKIT_MEDIA_STREAM_SRC(m_src), track); |
| 178 |
webkitMediaStreamSrcRemoveTrackByType(WEBKIT_MEDIA_STREAM_SRC(m_src), track.type()); |
| 179 |
} |
| 180 |
|
115 |
|
| 181 |
private: |
116 |
private: |
| 182 |
GstElement* m_src; |
117 |
GstElement* m_src; |
| 183 |
}; |
118 |
}; |
| 184 |
|
119 |
|
| 185 |
class InternalSource { |
120 |
class InternalSource final : public MediaStreamTrackPrivate::Observer, |
|
|
121 |
public RealtimeMediaSource::AudioSampleObserver, |
| 122 |
public RealtimeMediaSource::VideoSampleObserver { |
| 186 |
WTF_MAKE_FAST_ALLOCATED; |
123 |
WTF_MAKE_FAST_ALLOCATED; |
| 187 |
public: |
124 |
public: |
| 188 |
InternalSource(bool isCaptureTrack, RealtimeMediaSource::Type type) |
125 |
InternalSource(GstElement* parent, MediaStreamTrackPrivate& track, const String& padName) |
| 189 |
: m_type(type) |
126 |
: m_parent(parent) |
|
|
127 |
, m_track(track) |
| 128 |
, m_padName(padName) |
| 190 |
{ |
129 |
{ |
|
|
130 |
if (track.type() == RealtimeMediaSource::Type::Audio) |
| 131 |
m_audioTrack = AudioTrackPrivateMediaStream::create(track); |
| 132 |
else if (track.type() == RealtimeMediaSource::Type::Video) |
| 133 |
m_videoTrack = VideoTrackPrivateMediaStream::create(track); |
| 134 |
|
| 135 |
bool isCaptureTrack = track.isCaptureTrack(); |
| 191 |
m_src = gst_element_factory_make("appsrc", nullptr); |
136 |
m_src = gst_element_factory_make("appsrc", nullptr); |
| 192 |
RELEASE_ASSERT_WITH_MESSAGE(GST_IS_APP_SRC(m_src.get()), "GStreamer appsrc element not found. Please make sure to install gst-plugins-base"); |
137 |
RELEASE_ASSERT_WITH_MESSAGE(GST_IS_APP_SRC(m_src.get()), "GStreamer appsrc element not found. Please make sure to install gst-plugins-base"); |
| 193 |
|
138 |
|
|
Lines 201-225
public:
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec5
|
| 201 |
}), this); |
146 |
}), this); |
| 202 |
} |
147 |
} |
| 203 |
|
148 |
|
| 204 |
~InternalSource() |
149 |
virtual ~InternalSource() |
| 205 |
{ |
150 |
{ |
| 206 |
g_signal_handlers_disconnect_matched(m_src.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); |
151 |
stopObserving(); |
| 207 |
|
152 |
|
| 208 |
if (auto parent = adoptGRef(gst_object_get_parent(GST_OBJECT_CAST(m_src.get())))) { |
153 |
if (m_src) |
| 209 |
GST_STATE_LOCK(GST_ELEMENT_CAST(parent.get())); |
154 |
g_signal_handlers_disconnect_matched(m_src.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); |
| 210 |
gst_element_set_locked_state(m_src.get(), true); |
|
|
| 211 |
gst_element_set_state(m_src.get(), GST_STATE_NULL); |
| 212 |
gst_bin_remove(GST_BIN_CAST(parent.get()), m_src.get()); |
| 213 |
gst_element_set_locked_state(m_src.get(), false); |
| 214 |
GST_STATE_UNLOCK(GST_ELEMENT_CAST(parent.get())); |
| 215 |
|
| 216 |
const char* padName = m_type == RealtimeMediaSource::Type::Video ? "video_src" : "audio_src"; |
| 217 |
webkitMediaStreamSrcRemovePad(WEBKIT_MEDIA_STREAM_SRC(parent.get()), padName); |
| 218 |
} |
| 219 |
} |
155 |
} |
| 220 |
|
156 |
|
|
|
157 |
const MediaStreamTrackPrivate& track() const { return m_track; } |
| 158 |
const String& padName() const { return m_padName; } |
| 221 |
GstElement* get() const { return m_src.get(); } |
159 |
GstElement* get() const { return m_src.get(); } |
| 222 |
|
160 |
|
|
|
161 |
void startObserving() |
| 162 |
{ |
| 163 |
if (m_isObserving) |
| 164 |
return; |
| 165 |
|
| 166 |
m_track.addObserver(*this); |
| 167 |
switch (m_track.type()) { |
| 168 |
case RealtimeMediaSource::Type::Audio: |
| 169 |
m_track.source().addAudioSampleObserver(*this); |
| 170 |
break; |
| 171 |
case RealtimeMediaSource::Type::Video: |
| 172 |
m_track.source().addVideoSampleObserver(*this); |
| 173 |
break; |
| 174 |
case RealtimeMediaSource::Type::None: |
| 175 |
ASSERT_NOT_REACHED(); |
| 176 |
} |
| 177 |
m_isObserving = true; |
| 178 |
} |
| 179 |
|
| 180 |
void stopObserving() |
| 181 |
{ |
| 182 |
if (!m_isObserving) |
| 183 |
return; |
| 184 |
|
| 185 |
m_isObserving = false; |
| 186 |
switch (m_track.type()) { |
| 187 |
case RealtimeMediaSource::Type::Audio: |
| 188 |
m_track.source().removeAudioSampleObserver(*this); |
| 189 |
break; |
| 190 |
case RealtimeMediaSource::Type::Video: |
| 191 |
m_track.source().removeVideoSampleObserver(*this); |
| 192 |
break; |
| 193 |
case RealtimeMediaSource::Type::None: |
| 194 |
ASSERT_NOT_REACHED(); |
| 195 |
} |
| 196 |
m_track.removeObserver(*this); |
| 197 |
} |
| 198 |
|
| 199 |
void configureAudioTrack(float volume, bool isMuted, bool isPlaying) |
| 200 |
{ |
| 201 |
ASSERT(m_track.type() == RealtimeMediaSource::Type::Audio); |
| 202 |
m_audioTrack->setVolume(volume); |
| 203 |
m_audioTrack->setMuted(isMuted); |
| 204 |
m_audioTrack->setEnabled(m_audioTrack->streamTrack().enabled() && !m_audioTrack->streamTrack().muted()); |
| 205 |
if (isPlaying) |
| 206 |
m_audioTrack->play(); |
| 207 |
} |
| 208 |
|
| 223 |
void pushSample(GstSample* sample) |
209 |
void pushSample(GstSample* sample) |
| 224 |
{ |
210 |
{ |
| 225 |
ASSERT(m_src); |
211 |
ASSERT(m_src); |
|
Lines 235-246
public:
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec6
|
| 235 |
gst_pad_set_offset(pad.get(), -m_firstBufferPts); |
221 |
gst_pad_set_offset(pad.get(), -m_firstBufferPts); |
| 236 |
} |
222 |
} |
| 237 |
|
223 |
|
| 238 |
if (m_type == RealtimeMediaSource::Type::Video && drop) |
224 |
if (m_track.type() == RealtimeMediaSource::Type::Video && drop) |
| 239 |
drop = doCapsHaveType(caps, "video/x-raw") || GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT); |
225 |
drop = doCapsHaveType(caps, "video/x-raw") || GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT); |
| 240 |
|
226 |
|
| 241 |
if (drop) { |
227 |
if (drop) { |
| 242 |
m_needsDiscont = true; |
228 |
m_needsDiscont = true; |
| 243 |
GST_INFO_OBJECT(m_src.get(), "%s queue full already... not pushing", m_type == RealtimeMediaSource::Type::Video ? "Video" : "Audio"); |
229 |
GST_INFO_OBJECT(m_src.get(), "%s queue full already... not pushing", m_track.type() == RealtimeMediaSource::Type::Video ? "Video" : "Audio"); |
| 244 |
return; |
230 |
return; |
| 245 |
} |
231 |
} |
| 246 |
|
232 |
|
|
Lines 252-275
public:
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec7
|
| 252 |
gst_app_src_push_sample(GST_APP_SRC(m_src.get()), sample); |
238 |
gst_app_src_push_sample(GST_APP_SRC(m_src.get()), sample); |
| 253 |
} |
239 |
} |
| 254 |
|
240 |
|
|
|
241 |
void trackStarted(MediaStreamTrackPrivate&) final { }; |
| 242 |
void trackEnded(MediaStreamTrackPrivate&) final; |
| 243 |
|
| 244 |
void trackEnabledChanged(MediaStreamTrackPrivate& track) final |
| 245 |
{ |
| 246 |
m_enabled = track.enabled(); |
| 247 |
} |
| 248 |
|
| 249 |
void trackMutedChanged(MediaStreamTrackPrivate&) final { }; |
| 250 |
void trackSettingsChanged(MediaStreamTrackPrivate&) final { }; |
| 251 |
void readyStateChanged(MediaStreamTrackPrivate&) final { }; |
| 252 |
|
| 253 |
void videoSampleAvailable(MediaSample& sample) final |
| 254 |
{ |
| 255 |
if (!m_enabled || !m_parent) |
| 256 |
return; |
| 257 |
|
| 258 |
auto* gstSample = static_cast<MediaSampleGStreamer*>(&sample)->platformSample().sample.gstSample; |
| 259 |
pushSample(gstSample); |
| 260 |
} |
| 261 |
|
| 262 |
void audioSamplesAvailable(const MediaTime&, const PlatformAudioData& audioData, const AudioStreamDescription&, size_t) final |
| 263 |
{ |
| 264 |
if (!m_enabled || !m_parent) |
| 265 |
return; |
| 266 |
|
| 267 |
const auto& data = static_cast<const GStreamerAudioData&>(audioData); |
| 268 |
auto sample = data.getSample(); |
| 269 |
pushSample(sample.get()); |
| 270 |
} |
| 271 |
|
| 255 |
private: |
272 |
private: |
| 256 |
RealtimeMediaSource::Type m_type { RealtimeMediaSource::Type::None }; |
273 |
GstElement* m_parent { nullptr }; |
|
|
274 |
MediaStreamTrackPrivate& m_track; |
| 257 |
GRefPtr<GstElement> m_src; |
275 |
GRefPtr<GstElement> m_src; |
|
|
276 |
bool m_enabled { true }; |
| 258 |
GstClockTime m_firstBufferPts { GST_CLOCK_TIME_NONE }; |
277 |
GstClockTime m_firstBufferPts { GST_CLOCK_TIME_NONE }; |
| 259 |
bool m_enoughData { false }; |
278 |
bool m_enoughData { false }; |
| 260 |
bool m_needsDiscont { false }; |
279 |
bool m_needsDiscont { false }; |
|
|
280 |
String m_padName; |
| 281 |
bool m_isObserving { false }; |
| 282 |
RefPtr<AudioTrackPrivateMediaStream> m_audioTrack; |
| 283 |
RefPtr<VideoTrackPrivateMediaStream> m_videoTrack; |
| 261 |
}; |
284 |
}; |
| 262 |
|
285 |
|
| 263 |
struct _WebKitMediaStreamSrcPrivate { |
286 |
struct _WebKitMediaStreamSrcPrivate { |
| 264 |
CString uri; |
287 |
CString uri; |
| 265 |
Optional<InternalSource> audioSrc; |
288 |
Vector<std::unique_ptr<InternalSource>> sources; |
| 266 |
Optional<InternalSource> videoSrc; |
|
|
| 267 |
std::unique_ptr<WebKitMediaStreamTrackObserver> mediaStreamTrackObserver; |
| 268 |
std::unique_ptr<WebKitMediaStreamObserver> mediaStreamObserver; |
289 |
std::unique_ptr<WebKitMediaStreamObserver> mediaStreamObserver; |
| 269 |
RefPtr<MediaStreamPrivate> stream; |
290 |
RefPtr<MediaStreamPrivate> stream; |
| 270 |
Vector<RefPtr<MediaStreamTrackPrivate>> tracks; |
291 |
Vector<RefPtr<MediaStreamTrackPrivate>> tracks; |
| 271 |
GUniquePtr<GstFlowCombiner> flowCombiner; |
292 |
GUniquePtr<GstFlowCombiner> flowCombiner; |
| 272 |
GRefPtr<GstStreamCollection> streamCollection; |
293 |
GRefPtr<GstStreamCollection> streamCollection; |
|
|
294 |
Atomic<unsigned> audioPadCounter; |
| 295 |
Atomic<unsigned> videoPadCounter; |
| 273 |
}; |
296 |
}; |
| 274 |
|
297 |
|
| 275 |
enum { |
298 |
enum { |
|
Lines 278-283
enum {
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec8
|
| 278 |
PROP_LAST |
301 |
PROP_LAST |
| 279 |
}; |
302 |
}; |
| 280 |
|
303 |
|
|
|
304 |
void WebKitMediaStreamObserver::didRemoveTrack(MediaStreamTrackPrivate& track) |
| 305 |
{ |
| 306 |
if (!m_src) |
| 307 |
return; |
| 308 |
|
| 309 |
auto* element = WEBKIT_MEDIA_STREAM_SRC_CAST(m_src); |
| 310 |
element->priv->sources.removeFirstMatching([&](auto& item) { |
| 311 |
return item->track().id() == track.id(); |
| 312 |
}); |
| 313 |
} |
| 314 |
|
| 281 |
static GstURIType webkitMediaStreamSrcUriGetType(GType) |
315 |
static GstURIType webkitMediaStreamSrcUriGetType(GType) |
| 282 |
{ |
316 |
{ |
| 283 |
return GST_URI_SRC; |
317 |
return GST_URI_SRC; |
|
Lines 291-303
static const char* const* webkitMediaStreamSrcUriGetProtocols(GType)
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec9
|
| 291 |
|
325 |
|
| 292 |
static char* webkitMediaStreamSrcUriGetUri(GstURIHandler* handler) |
326 |
static char* webkitMediaStreamSrcUriGetUri(GstURIHandler* handler) |
| 293 |
{ |
327 |
{ |
| 294 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(handler); |
328 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC_CAST(handler); |
| 295 |
return g_strdup(self->priv->uri.data()); |
329 |
return g_strdup(self->priv->uri.data()); |
| 296 |
} |
330 |
} |
| 297 |
|
331 |
|
| 298 |
static gboolean webkitMediaStreamSrcUriSetUri(GstURIHandler* handler, const char* uri, GError**) |
332 |
static gboolean webkitMediaStreamSrcUriSetUri(GstURIHandler* handler, const char* uri, GError**) |
| 299 |
{ |
333 |
{ |
| 300 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(handler); |
334 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC_CAST(handler); |
| 301 |
self->priv->uri = CString(uri); |
335 |
self->priv->uri = CString(uri); |
| 302 |
return TRUE; |
336 |
return TRUE; |
| 303 |
} |
337 |
} |
|
Lines 345-354
static void webkitMediaStreamSrcGetProperty(GObject* object, guint propertyId, G
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec10
|
| 345 |
static void webkitMediaStreamSrcConstructed(GObject* object) |
379 |
static void webkitMediaStreamSrcConstructed(GObject* object) |
| 346 |
{ |
380 |
{ |
| 347 |
GST_CALL_PARENT(G_OBJECT_CLASS, constructed, (object)); |
381 |
GST_CALL_PARENT(G_OBJECT_CLASS, constructed, (object)); |
| 348 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(object); |
382 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC_CAST(object); |
| 349 |
auto* priv = self->priv; |
383 |
auto* priv = self->priv; |
| 350 |
|
384 |
|
| 351 |
priv->mediaStreamTrackObserver = makeUnique<WebKitMediaStreamTrackObserver>(GST_ELEMENT_CAST(self)); |
|
|
| 352 |
priv->mediaStreamObserver = makeUnique<WebKitMediaStreamObserver>(GST_ELEMENT_CAST(self)); |
385 |
priv->mediaStreamObserver = makeUnique<WebKitMediaStreamObserver>(GST_ELEMENT_CAST(self)); |
| 353 |
priv->flowCombiner = GUniquePtr<GstFlowCombiner>(gst_flow_combiner_new()); |
386 |
priv->flowCombiner = GUniquePtr<GstFlowCombiner>(gst_flow_combiner_new()); |
| 354 |
|
387 |
|
|
Lines 357-392
static void webkitMediaStreamSrcConstructed(GObject* object)
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec11
|
| 357 |
ASSERT(g_object_is_floating(self)); |
390 |
ASSERT(g_object_is_floating(self)); |
| 358 |
} |
391 |
} |
| 359 |
|
392 |
|
| 360 |
static void webkitMediaStreamSrcRemoveTrackObserver(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate& track) |
|
|
| 361 |
{ |
| 362 |
auto* priv = self->priv; |
| 363 |
switch (track.type()) { |
| 364 |
case RealtimeMediaSource::Type::Video: |
| 365 |
track.source().removeVideoSampleObserver(*priv->mediaStreamTrackObserver); |
| 366 |
break; |
| 367 |
case RealtimeMediaSource::Type::Audio: |
| 368 |
track.source().removeAudioSampleObserver(*priv->mediaStreamTrackObserver); |
| 369 |
break; |
| 370 |
case RealtimeMediaSource::Type::None: |
| 371 |
ASSERT_NOT_REACHED(); |
| 372 |
} |
| 373 |
track.removeObserver(*priv->mediaStreamTrackObserver); |
| 374 |
} |
| 375 |
|
| 376 |
static void stopObservingTracks(WebKitMediaStreamSrc* self) |
| 377 |
{ |
| 378 |
GST_OBJECT_LOCK(self); |
| 379 |
auto* priv = self->priv; |
| 380 |
for (auto& track : priv->tracks) |
| 381 |
webkitMediaStreamSrcRemoveTrackObserver(self, *track); |
| 382 |
GST_OBJECT_UNLOCK(self); |
| 383 |
} |
| 384 |
|
| 385 |
static void webkitMediaStreamSrcDispose(GObject* object) |
393 |
static void webkitMediaStreamSrcDispose(GObject* object) |
| 386 |
{ |
394 |
{ |
| 387 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(object); |
395 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC_CAST(object); |
| 388 |
|
|
|
| 389 |
stopObservingTracks(self); |
| 390 |
|
396 |
|
| 391 |
GST_OBJECT_LOCK(self); |
397 |
GST_OBJECT_LOCK(self); |
| 392 |
auto* priv = self->priv; |
398 |
auto* priv = self->priv; |
|
Lines 402-415
static void webkitMediaStreamSrcDispose(GObject* object)
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec12
|
| 402 |
static GstStateChangeReturn webkitMediaStreamSrcChangeState(GstElement* element, GstStateChange transition) |
408 |
static GstStateChangeReturn webkitMediaStreamSrcChangeState(GstElement* element, GstStateChange transition) |
| 403 |
{ |
409 |
{ |
| 404 |
GST_DEBUG_OBJECT(element, "%s", gst_state_change_get_name(transition)); |
410 |
GST_DEBUG_OBJECT(element, "%s", gst_state_change_get_name(transition)); |
|
|
411 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC_CAST(element); |
| 405 |
|
412 |
|
| 406 |
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) |
413 |
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) { |
| 407 |
stopObservingTracks(WEBKIT_MEDIA_STREAM_SRC(element)); |
414 |
GST_OBJECT_LOCK(self); |
|
|
415 |
for (auto& item : self->priv->sources) |
| 416 |
item->stopObserving(); |
| 417 |
GST_OBJECT_UNLOCK(self); |
| 418 |
} |
| 408 |
|
419 |
|
| 409 |
GstStateChangeReturn result = GST_ELEMENT_CLASS(webkit_media_stream_src_parent_class)->change_state(element, transition); |
420 |
GstStateChangeReturn result = GST_ELEMENT_CLASS(webkit_media_stream_src_parent_class)->change_state(element, transition); |
| 410 |
|
421 |
|
| 411 |
if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) |
422 |
if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) { |
|
|
423 |
GST_OBJECT_LOCK(self); |
| 424 |
for (auto& item : self->priv->sources) |
| 425 |
item->startObserving(); |
| 426 |
GST_OBJECT_UNLOCK(self); |
| 412 |
result = GST_STATE_CHANGE_NO_PREROLL; |
427 |
result = GST_STATE_CHANGE_NO_PREROLL; |
|
|
428 |
} |
| 413 |
|
429 |
|
| 414 |
return result; |
430 |
return result; |
| 415 |
} |
431 |
} |
|
Lines 436-442
static GstFlowReturn webkitMediaStreamSrcChain(GstPad* pad, GstObject* parent, G
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec13
|
| 436 |
{ |
452 |
{ |
| 437 |
GRefPtr<GstElement> element = adoptGRef(GST_ELEMENT_CAST(gst_object_get_parent(parent))); |
453 |
GRefPtr<GstElement> element = adoptGRef(GST_ELEMENT_CAST(gst_object_get_parent(parent))); |
| 438 |
GstFlowReturn chainResult = gst_proxy_pad_chain_default(pad, GST_OBJECT_CAST(element.get()), buffer); |
454 |
GstFlowReturn chainResult = gst_proxy_pad_chain_default(pad, GST_OBJECT_CAST(element.get()), buffer); |
| 439 |
auto* self = WEBKIT_MEDIA_STREAM_SRC(element.get()); |
455 |
auto* self = WEBKIT_MEDIA_STREAM_SRC_CAST(element.get()); |
| 440 |
GstFlowReturn result = gst_flow_combiner_update_pad_flow(self->priv->flowCombiner.get(), pad, chainResult); |
456 |
GstFlowReturn result = gst_flow_combiner_update_pad_flow(self->priv->flowCombiner.get(), pad, chainResult); |
| 441 |
|
457 |
|
| 442 |
if (result == GST_FLOW_FLUSHING) |
458 |
if (result == GST_FLOW_FLUSHING) |
|
Lines 445-456
static GstFlowReturn webkitMediaStreamSrcChain(GstPad* pad, GstObject* parent, G
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec14
|
| 445 |
return result; |
461 |
return result; |
| 446 |
} |
462 |
} |
| 447 |
|
463 |
|
| 448 |
static void webkitMediaStreamSrcAddPad(WebKitMediaStreamSrc* self, GstPad* target, GstStaticPadTemplate* padTemplate, GRefPtr<GstTagList>&& tags, RealtimeMediaSource::Type sourceType) |
464 |
static void webkitMediaStreamSrcPostStreamCollection(WebKitMediaStreamSrc* self) |
| 449 |
{ |
465 |
{ |
|
|
466 |
auto* priv = self->priv; |
| 467 |
|
| 468 |
GST_OBJECT_LOCK(self); |
| 469 |
if (priv->stream && (!priv->stream->active() || !priv->stream->hasTracks())) { |
| 470 |
GST_OBJECT_UNLOCK(self); |
| 471 |
return; |
| 472 |
} |
| 473 |
|
| 474 |
auto upstreamId = priv->stream ? priv->stream->id() : createCanonicalUUIDString(); |
| 475 |
priv->streamCollection = adoptGRef(gst_stream_collection_new(upstreamId.ascii().data())); |
| 476 |
for (auto& track : priv->tracks) { |
| 477 |
if (!track->isActive()) |
| 478 |
continue; |
| 479 |
gst_stream_collection_add_stream(priv->streamCollection.get(), webkitMediaStreamNew(track.get())); |
| 480 |
} |
| 481 |
|
| 482 |
GST_OBJECT_UNLOCK(self); |
| 483 |
|
| 484 |
GST_DEBUG_OBJECT(self, "Posting stream collection"); |
| 485 |
gst_element_post_message(GST_ELEMENT_CAST(self), gst_message_new_stream_collection(GST_OBJECT_CAST(self), priv->streamCollection.get())); |
| 486 |
} |
| 487 |
|
| 488 |
static void webkitMediaStreamSrcAddPad(WebKitMediaStreamSrc* self, GstPad* target, GstStaticPadTemplate* padTemplate, GRefPtr<GstTagList>&& tags, RealtimeMediaSource::Type sourceType, const String& padName) |
| 489 |
{ |
| 490 |
ASSERT(sourceType != RealtimeMediaSource::Type::None); |
| 491 |
if (sourceType == RealtimeMediaSource::Type::None) |
| 492 |
return; |
| 493 |
|
| 450 |
GST_DEBUG_OBJECT(self, "%s Ghosting %" GST_PTR_FORMAT, gst_object_get_path_string(GST_OBJECT_CAST(self)), target); |
494 |
GST_DEBUG_OBJECT(self, "%s Ghosting %" GST_PTR_FORMAT, gst_object_get_path_string(GST_OBJECT_CAST(self)), target); |
| 451 |
|
495 |
|
| 452 |
const char* padName = sourceType == RealtimeMediaSource::Type::Audio ? "audio_src" : "video_src"; |
496 |
auto* ghostPad = webkitGstGhostPadFromStaticTemplate(padTemplate, padName.ascii().data(), target); |
| 453 |
auto* ghostPad = webkitGstGhostPadFromStaticTemplate(padTemplate, padName, target); |
|
|
| 454 |
gst_pad_set_active(ghostPad, TRUE); |
497 |
gst_pad_set_active(ghostPad, TRUE); |
| 455 |
gst_element_add_pad(GST_ELEMENT_CAST(self), ghostPad); |
498 |
gst_element_add_pad(GST_ELEMENT_CAST(self), ghostPad); |
| 456 |
|
499 |
|
|
Lines 461-487
static void webkitMediaStreamSrcAddPad(WebKitMediaStreamSrc* self, GstPad* targe
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec15
|
| 461 |
gst_pad_push_event(target, gst_event_new_tag(tags.leakRef())); |
504 |
gst_pad_push_event(target, gst_event_new_tag(tags.leakRef())); |
| 462 |
} |
505 |
} |
| 463 |
|
506 |
|
| 464 |
static void webkitMediaStreamSrcRemovePad(WebKitMediaStreamSrc* self, const char* padName) |
|
|
| 465 |
{ |
| 466 |
auto pad = adoptGRef(gst_element_get_static_pad(GST_ELEMENT_CAST(self), padName)); |
| 467 |
if (!pad) |
| 468 |
return; |
| 469 |
|
| 470 |
auto proxyPad = adoptGRef(GST_PAD_CAST(gst_proxy_pad_get_internal(GST_PROXY_PAD(pad.get())))); |
| 471 |
if (proxyPad) |
| 472 |
gst_flow_combiner_remove_pad(self->priv->flowCombiner.get(), proxyPad.get()); |
| 473 |
|
| 474 |
gst_pad_set_active(pad.get(), FALSE); |
| 475 |
gst_element_remove_pad(GST_ELEMENT_CAST(self), pad.get()); |
| 476 |
} |
| 477 |
|
| 478 |
struct ProbeData { |
507 |
struct ProbeData { |
| 479 |
ProbeData(GstElement* element, GstStaticPadTemplate* padTemplate, GRefPtr<GstTagList>&& tags, const char* trackId, RealtimeMediaSource::Type sourceType) |
508 |
ProbeData(GstElement* element, GstStaticPadTemplate* padTemplate, GRefPtr<GstTagList>&& tags, const char* trackId, RealtimeMediaSource::Type sourceType, const String& padName) |
| 480 |
: element(element) |
509 |
: element(element) |
| 481 |
, padTemplate(padTemplate) |
510 |
, padTemplate(padTemplate) |
| 482 |
, tags(WTFMove(tags)) |
511 |
, tags(WTFMove(tags)) |
| 483 |
, trackId(g_strdup(trackId)) |
512 |
, trackId(g_strdup(trackId)) |
| 484 |
, sourceType(sourceType) |
513 |
, sourceType(sourceType) |
|
|
514 |
, padName(padName) |
| 485 |
{ |
515 |
{ |
| 486 |
} |
516 |
} |
| 487 |
|
517 |
|
|
Lines 490-501
struct ProbeData {
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec16
|
| 490 |
GRefPtr<GstTagList> tags; |
520 |
GRefPtr<GstTagList> tags; |
| 491 |
GUniquePtr<char> trackId; |
521 |
GUniquePtr<char> trackId; |
| 492 |
RealtimeMediaSource::Type sourceType; |
522 |
RealtimeMediaSource::Type sourceType; |
|
|
523 |
String padName; |
| 493 |
}; |
524 |
}; |
| 494 |
|
525 |
|
| 495 |
static GstPadProbeReturn webkitMediaStreamSrcPadProbeCb(GstPad* pad, GstPadProbeInfo* info, ProbeData* data) |
526 |
static GstPadProbeReturn webkitMediaStreamSrcPadProbeCb(GstPad* pad, GstPadProbeInfo* info, ProbeData* data) |
| 496 |
{ |
527 |
{ |
| 497 |
GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); |
528 |
GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); |
| 498 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(data->element.get()); |
529 |
WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC_CAST(data->element.get()); |
| 499 |
|
530 |
|
| 500 |
GST_DEBUG_OBJECT(self, "Event %" GST_PTR_FORMAT, event); |
531 |
GST_DEBUG_OBJECT(self, "Event %" GST_PTR_FORMAT, event); |
| 501 |
switch (GST_EVENT_TYPE(event)) { |
532 |
switch (GST_EVENT_TYPE(event)) { |
|
Lines 511-519
static GstPadProbeReturn webkitMediaStreamSrcPadProbeCb(GstPad* pad, GstPadProbe
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec17
|
| 511 |
gst_event_set_group_id(streamStart, 1); |
542 |
gst_event_set_group_id(streamStart, 1); |
| 512 |
gst_pad_push_event(pad, streamStart); |
543 |
gst_pad_push_event(pad, streamStart); |
| 513 |
|
544 |
|
| 514 |
webkitMediaStreamSrcAddPad(self, pad, data->padTemplate, WTFMove(data->tags), data->sourceType); |
545 |
webkitMediaStreamSrcAddPad(self, pad, data->padTemplate, WTFMove(data->tags), data->sourceType, data->padName); |
| 515 |
callOnMainThreadAndWait([element = data->element] { |
546 |
callOnMainThreadAndWait([element = data->element] { |
| 516 |
webkitMediaStreamSrcPostStreamCollection(WEBKIT_MEDIA_STREAM_SRC(element.get())); |
547 |
webkitMediaStreamSrcPostStreamCollection(WEBKIT_MEDIA_STREAM_SRC_CAST(element.get())); |
| 517 |
}); |
548 |
}); |
| 518 |
return GST_PAD_PROBE_REMOVE; |
549 |
return GST_PAD_PROBE_REMOVE; |
| 519 |
} |
550 |
} |
|
Lines 524-623
static GstPadProbeReturn webkitMediaStreamSrcPadProbeCb(GstPad* pad, GstPadProbe
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec18
|
| 524 |
return GST_PAD_PROBE_OK; |
555 |
return GST_PAD_PROBE_OK; |
| 525 |
} |
556 |
} |
| 526 |
|
557 |
|
| 527 |
static void webkitMediaStreamSrcSetupSrc(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate* track, GstElement* element, GstStaticPadTemplate* padTemplate, bool onlyTrack) |
558 |
void webkitMediaStreamSrcAddTrack(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate* track, bool onlyTrack) |
| 528 |
{ |
559 |
{ |
| 529 |
const char* sourceType = "unknown"; |
560 |
const char* sourceType = "unknown"; |
| 530 |
switch (track->source().type()) { |
561 |
unsigned counter = 0; |
| 531 |
case RealtimeMediaSource::Type::Audio: |
562 |
GstStaticPadTemplate* padTemplate = nullptr; |
|
|
563 |
if (track->type() == RealtimeMediaSource::Type::Audio) { |
| 564 |
padTemplate = &audioSrcTemplate; |
| 532 |
sourceType = "audio"; |
565 |
sourceType = "audio"; |
| 533 |
break; |
566 |
counter = self->priv->audioPadCounter.exchangeAdd(1); |
| 534 |
case RealtimeMediaSource::Type::Video: |
567 |
} else if (track->type() == RealtimeMediaSource::Type::Video) { |
|
|
568 |
padTemplate = &videoSrcTemplate; |
| 535 |
sourceType = "video"; |
569 |
sourceType = "video"; |
| 536 |
break; |
570 |
counter = self->priv->videoPadCounter.exchangeAdd(1); |
| 537 |
case RealtimeMediaSource::Type::None: |
571 |
} else { |
| 538 |
ASSERT_NOT_REACHED(); |
572 |
GST_WARNING_OBJECT(self, "Unsupported track type: %d", static_cast<int>(track->type())); |
|
|
573 |
return; |
| 539 |
} |
574 |
} |
| 540 |
|
575 |
|
|
|
576 |
StringBuilder padName; |
| 577 |
padName.append(sourceType); |
| 578 |
padName.append("_src"); |
| 579 |
padName.append(counter); |
| 580 |
|
| 541 |
GST_DEBUG_OBJECT(self, "Setup %s source for track %s, only track: %s", sourceType, track->id().utf8().data(), boolForPrinting(onlyTrack)); |
581 |
GST_DEBUG_OBJECT(self, "Setup %s source for track %s, only track: %s", sourceType, track->id().utf8().data(), boolForPrinting(onlyTrack)); |
|
|
582 |
|
| 583 |
auto source = makeUnique<InternalSource>(GST_ELEMENT_CAST(self), *track, padName.toString()); |
| 584 |
auto* element = source->get(); |
| 542 |
gst_bin_add(GST_BIN_CAST(self), element); |
585 |
gst_bin_add(GST_BIN_CAST(self), element); |
| 543 |
|
586 |
|
| 544 |
auto pad = adoptGRef(gst_element_get_static_pad(element, "src")); |
587 |
auto pad = adoptGRef(gst_element_get_static_pad(element, "src")); |
| 545 |
auto tags = mediaStreamTrackPrivateGetTags(track); |
588 |
auto tags = mediaStreamTrackPrivateGetTags(track); |
| 546 |
if (!onlyTrack) { |
589 |
if (!onlyTrack) { |
| 547 |
auto* data = new ProbeData(GST_ELEMENT_CAST(self), padTemplate, WTFMove(tags), track->id().utf8().data(), track->source().type()); |
590 |
auto* data = new ProbeData(GST_ELEMENT_CAST(self), padTemplate, WTFMove(tags), track->id().utf8().data(), track->source().type(), source->padName()); |
| 548 |
gst_pad_add_probe(pad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast<GstPadProbeCallback>(webkitMediaStreamSrcPadProbeCb), data, [](gpointer data) { |
591 |
gst_pad_add_probe(pad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast<GstPadProbeCallback>(webkitMediaStreamSrcPadProbeCb), data, [](gpointer data) { |
| 549 |
delete reinterpret_cast<ProbeData*>(data); |
592 |
delete reinterpret_cast<ProbeData*>(data); |
| 550 |
}); |
593 |
}); |
| 551 |
} else { |
594 |
} else { |
| 552 |
gst_pad_set_active(pad.get(), TRUE); |
595 |
gst_pad_set_active(pad.get(), TRUE); |
| 553 |
webkitMediaStreamSrcAddPad(self, pad.get(), padTemplate, WTFMove(tags), track->source().type()); |
596 |
webkitMediaStreamSrcAddPad(self, pad.get(), padTemplate, WTFMove(tags), track->source().type(), source->padName()); |
| 554 |
} |
597 |
} |
| 555 |
|
|
|
| 556 |
auto* priv = self->priv; |
| 557 |
track->addObserver(*priv->mediaStreamTrackObserver); |
| 558 |
switch (track->type()) { |
| 559 |
case RealtimeMediaSource::Type::Audio: |
| 560 |
track->source().addAudioSampleObserver(*priv->mediaStreamTrackObserver); |
| 561 |
break; |
| 562 |
case RealtimeMediaSource::Type::Video: |
| 563 |
track->source().addVideoSampleObserver(*priv->mediaStreamTrackObserver); |
| 564 |
break; |
| 565 |
case RealtimeMediaSource::Type::None: |
| 566 |
ASSERT_NOT_REACHED(); |
| 567 |
} |
| 568 |
|
| 569 |
gst_element_sync_state_with_parent(element); |
598 |
gst_element_sync_state_with_parent(element); |
| 570 |
} |
|
|
| 571 |
|
| 572 |
static void webkitMediaStreamSrcPostStreamCollection(WebKitMediaStreamSrc* self) |
| 573 |
{ |
| 574 |
auto* priv = self->priv; |
| 575 |
|
| 576 |
GST_OBJECT_LOCK(self); |
| 577 |
if (priv->stream && (!priv->stream->active() || !priv->stream->hasTracks())) { |
| 578 |
GST_OBJECT_UNLOCK(self); |
| 579 |
return; |
| 580 |
} |
| 581 |
|
| 582 |
auto upstreamId = priv->stream ? priv->stream->id() : createCanonicalUUIDString(); |
| 583 |
priv->streamCollection = adoptGRef(gst_stream_collection_new(upstreamId.ascii().data())); |
| 584 |
for (auto& track : priv->tracks) { |
| 585 |
if (!track->isActive()) |
| 586 |
continue; |
| 587 |
gst_stream_collection_add_stream(priv->streamCollection.get(), webkitMediaStreamNew(track.get())); |
| 588 |
} |
| 589 |
|
| 590 |
GST_OBJECT_UNLOCK(self); |
| 591 |
|
| 592 |
GST_DEBUG_OBJECT(self, "Posting stream collection"); |
| 593 |
gst_element_post_message(GST_ELEMENT_CAST(self), gst_message_new_stream_collection(GST_OBJECT_CAST(self), priv->streamCollection.get())); |
| 594 |
} |
| 595 |
|
| 596 |
void webkitMediaStreamSrcAddTrack(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate* track, bool onlyTrack) |
| 597 |
{ |
| 598 |
auto* priv = self->priv; |
| 599 |
if (track->type() == RealtimeMediaSource::Type::Audio) { |
| 600 |
priv->audioSrc.emplace(track->isCaptureTrack(), track->type()); |
| 601 |
webkitMediaStreamSrcSetupSrc(self, track, priv->audioSrc->get(), &audioSrcTemplate, onlyTrack); |
| 602 |
} else if (track->type() == RealtimeMediaSource::Type::Video) { |
| 603 |
priv->videoSrc.emplace(track->isCaptureTrack(), track->type()); |
| 604 |
webkitMediaStreamSrcSetupSrc(self, track, priv->videoSrc->get(), &videoSrcTemplate, onlyTrack); |
| 605 |
} else |
| 606 |
GST_INFO_OBJECT(self, "Unsupported track type: %d", static_cast<int>(track->type())); |
| 607 |
|
599 |
|
|
|
600 |
source->startObserving(); |
| 601 |
self->priv->sources.append(WTFMove(source)); |
| 608 |
self->priv->tracks.append(track); |
602 |
self->priv->tracks.append(track); |
| 609 |
} |
603 |
} |
| 610 |
|
604 |
|
| 611 |
static void webkitMediaStreamSrcRemoveTrackByType(WebKitMediaStreamSrc* self, RealtimeMediaSource::Type trackType) |
|
|
| 612 |
{ |
| 613 |
if (trackType == RealtimeMediaSource::Type::Audio) |
| 614 |
self->priv->audioSrc.reset(); |
| 615 |
else if (trackType == RealtimeMediaSource::Type::Video) |
| 616 |
self->priv->videoSrc.reset(); |
| 617 |
else |
| 618 |
GST_INFO_OBJECT(self, "Unsupported track type: %d", static_cast<int>(trackType)); |
| 619 |
} |
| 620 |
|
| 621 |
void webkitMediaStreamSrcSetStream(WebKitMediaStreamSrc* self, MediaStreamPrivate* stream, bool isVideoPlayer) |
605 |
void webkitMediaStreamSrcSetStream(WebKitMediaStreamSrc* self, MediaStreamPrivate* stream, bool isVideoPlayer) |
| 622 |
{ |
606 |
{ |
| 623 |
ASSERT(WEBKIT_IS_MEDIA_STREAM_SRC(self)); |
607 |
ASSERT(WEBKIT_IS_MEDIA_STREAM_SRC(self)); |
|
Lines 633-657
void webkitMediaStreamSrcSetStream(WebKitMediaStreamSrc* self, MediaStreamPrivat
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec19
|
| 633 |
webkitMediaStreamSrcAddTrack(self, track.get(), onlyTrack); |
617 |
webkitMediaStreamSrcAddTrack(self, track.get(), onlyTrack); |
| 634 |
} |
618 |
} |
| 635 |
webkitMediaStreamSrcPostStreamCollection(self); |
619 |
webkitMediaStreamSrcPostStreamCollection(self); |
| 636 |
gst_element_no_more_pads(GST_ELEMENT_CAST(self)); |
|
|
| 637 |
} |
| 638 |
|
| 639 |
static void webkitMediaStreamSrcPushVideoSample(WebKitMediaStreamSrc* self, GstSample* sample) |
| 640 |
{ |
| 641 |
if (self->priv->videoSrc) |
| 642 |
self->priv->videoSrc->pushSample(sample); |
| 643 |
} |
| 644 |
|
| 645 |
static void webkitMediaStreamSrcPushAudioSample(WebKitMediaStreamSrc* self, const GRefPtr<GstSample>& sample) |
| 646 |
{ |
| 647 |
if (self->priv->audioSrc) |
| 648 |
self->priv->audioSrc->pushSample(sample.get()); |
| 649 |
} |
620 |
} |
| 650 |
|
621 |
|
| 651 |
static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc* self, MediaStreamTrackPrivate& track) |
622 |
static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc* self, InternalSource& source) |
| 652 |
{ |
623 |
{ |
| 653 |
GRefPtr<GstPad> pad; |
624 |
GRefPtr<GstPad> pad; |
| 654 |
|
625 |
|
|
|
626 |
auto& track = source.track(); |
| 655 |
GST_DEBUG_OBJECT(self, "Track %s ended", track.label().utf8().data()); |
627 |
GST_DEBUG_OBJECT(self, "Track %s ended", track.label().utf8().data()); |
| 656 |
GST_OBJECT_LOCK(self); |
628 |
GST_OBJECT_LOCK(self); |
| 657 |
GstElement* element = GST_ELEMENT_CAST(self); |
629 |
GstElement* element = GST_ELEMENT_CAST(self); |
|
Lines 684-689
static void webkitMediaStreamSrcTrackEnded(WebKitMediaStreamSrc* self, MediaStre
a/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp_sec20
|
| 684 |
auto tags = mediaStreamTrackPrivateGetTags(&track); |
656 |
auto tags = mediaStreamTrackPrivateGetTags(&track); |
| 685 |
gst_pad_push_event(pad.get(), gst_event_new_tag(tags.leakRef())); |
657 |
gst_pad_push_event(pad.get(), gst_event_new_tag(tags.leakRef())); |
| 686 |
gst_pad_push_event(pad.get(), gst_event_new_eos()); |
658 |
gst_pad_push_event(pad.get(), gst_event_new_eos()); |
|
|
659 |
|
| 660 |
GST_STATE_LOCK(GST_ELEMENT_CAST(self)); |
| 661 |
gst_element_set_locked_state(source.get(), true); |
| 662 |
gst_element_set_state(source.get(), GST_STATE_NULL); |
| 663 |
gst_bin_remove(GST_BIN_CAST(self), source.get()); |
| 664 |
gst_element_set_locked_state(source.get(), false); |
| 665 |
GST_STATE_UNLOCK(GST_ELEMENT_CAST(self)); |
| 666 |
|
| 667 |
auto proxyPad = adoptGRef(GST_PAD_CAST(gst_proxy_pad_get_internal(GST_PROXY_PAD(pad.get())))); |
| 668 |
if (proxyPad) |
| 669 |
gst_flow_combiner_remove_pad(self->priv->flowCombiner.get(), proxyPad.get()); |
| 670 |
|
| 671 |
gst_pad_set_active(pad.get(), FALSE); |
| 672 |
gst_element_remove_pad(GST_ELEMENT_CAST(self), pad.get()); |
| 673 |
} |
| 674 |
|
| 675 |
void InternalSource::trackEnded(MediaStreamTrackPrivate&) |
| 676 |
{ |
| 677 |
if (m_parent) |
| 678 |
webkitMediaStreamSrcTrackEnded(WEBKIT_MEDIA_STREAM_SRC_CAST(m_parent), *this); |
| 679 |
|
| 680 |
stopObserving(); |
| 681 |
} |
| 682 |
|
| 683 |
void webkitMediaStreamSrcConfigureAudioTracks(WebKitMediaStreamSrc* self, float volume, bool isMuted, bool isPlaying) |
| 684 |
{ |
| 685 |
for (auto& source : self->priv->sources) { |
| 686 |
if (source->track().type() == RealtimeMediaSource::Type::Audio) |
| 687 |
source->configureAudioTrack(volume, isMuted, isPlaying); |
| 688 |
} |
| 687 |
} |
689 |
} |
| 688 |
|
690 |
|
| 689 |
GstElement* webkitMediaStreamSrcNew() |
691 |
GstElement* webkitMediaStreamSrcNew() |