[WPE][GTK] Bump minimum versions of GLib, GTK, libsoup, ATK, GStreamer, and Cairo
[WebKit-https.git] / Source / WebCore / platform / graphics / gstreamer / TrackPrivateBaseGStreamer.cpp
1 /*
2  * Copyright (C) 2013 Cable Television Laboratories, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK)
29
30 #include "TrackPrivateBaseGStreamer.h"
31
32 #include "GStreamerCommon.h"
33 #include "Logging.h"
34 #include "TrackPrivateBase.h"
35 #include <glib-object.h>
36 #include <gst/gst.h>
37 #include <gst/tag/tag.h>
38 #include <wtf/glib/GUniquePtr.h>
39 #include <wtf/text/CString.h>
40
41 GST_DEBUG_CATEGORY_EXTERN(webkit_media_player_debug);
42 #define GST_CAT_DEFAULT webkit_media_player_debug
43
44 namespace WebCore {
45
46 TrackPrivateBaseGStreamer::TrackPrivateBaseGStreamer(TrackPrivateBase* owner, gint index, GRefPtr<GstPad> pad)
47     : m_notifier(MainThreadNotifier<MainThreadNotification>::create())
48     , m_index(index)
49     , m_pad(pad)
50     , m_owner(owner)
51 {
52     ASSERT(m_pad);
53
54     g_signal_connect_swapped(m_pad.get(), "notify::active", G_CALLBACK(activeChangedCallback), this);
55     g_signal_connect_swapped(m_pad.get(), "notify::tags", G_CALLBACK(tagsChangedCallback), this);
56
57     // We can't call notifyTrackOfTagsChanged() directly, because we need tagsChanged() to setup m_tags.
58     tagsChanged();
59 }
60
61 TrackPrivateBaseGStreamer::TrackPrivateBaseGStreamer(TrackPrivateBase* owner, gint index, GRefPtr<GstStream> stream)
62     : m_notifier(MainThreadNotifier<MainThreadNotification>::create())
63     , m_index(index)
64     , m_stream(stream)
65     , m_owner(owner)
66 {
67     ASSERT(m_stream);
68
69     // We can't call notifyTrackOfTagsChanged() directly, because we need tagsChanged() to setup m_tags.
70     tagsChanged();
71 }
72
73 TrackPrivateBaseGStreamer::~TrackPrivateBaseGStreamer()
74 {
75     disconnect();
76     m_notifier->invalidate();
77 }
78
79 void TrackPrivateBaseGStreamer::disconnect()
80 {
81     m_tags.clear();
82
83     if (m_stream)
84         m_stream.clear();
85
86     m_notifier->cancelPendingNotifications();
87
88     if (!m_pad)
89         return;
90
91     g_signal_handlers_disconnect_matched(m_pad.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
92     m_pad.clear();
93 }
94
95 void TrackPrivateBaseGStreamer::activeChangedCallback(TrackPrivateBaseGStreamer* track)
96 {
97     track->m_notifier->notify(MainThreadNotification::ActiveChanged, [track] { track->notifyTrackOfActiveChanged(); });
98 }
99
100 void TrackPrivateBaseGStreamer::tagsChangedCallback(TrackPrivateBaseGStreamer* track)
101 {
102     track->tagsChanged();
103 }
104
105 void TrackPrivateBaseGStreamer::tagsChanged()
106 {
107     GRefPtr<GstTagList> tags;
108     if (m_pad) {
109         if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_pad.get()), "tags"))
110             g_object_get(m_pad.get(), "tags", &tags.outPtr(), nullptr);
111         else
112             tags = adoptGRef(gst_tag_list_new_empty());
113     }
114     else if (m_stream)
115         tags = adoptGRef(gst_stream_get_tags(m_stream.get()));
116     else
117         tags = adoptGRef(gst_tag_list_new_empty());
118
119     GST_DEBUG("Inspecting track at index %d with tags: %" GST_PTR_FORMAT, m_index, tags.get());
120     {
121         LockHolder lock(m_tagMutex);
122         m_tags.swap(tags);
123     }
124
125     m_notifier->notify(MainThreadNotification::TagsChanged, [this] { notifyTrackOfTagsChanged(); });
126 }
127
128 void TrackPrivateBaseGStreamer::notifyTrackOfActiveChanged()
129 {
130     if (!m_pad)
131         return;
132
133     gboolean active = false;
134     if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_pad.get()), "active"))
135         g_object_get(m_pad.get(), "active", &active, nullptr);
136
137     setActive(active);
138 }
139
140 bool TrackPrivateBaseGStreamer::getLanguageCode(GstTagList* tags, AtomString& value)
141 {
142     String language;
143     if (getTag(tags, GST_TAG_LANGUAGE_CODE, language)) {
144         language = gst_tag_get_language_code_iso_639_1(language.utf8().data());
145         GST_DEBUG("Converted track %d's language code to %s.", m_index, language.utf8().data());
146         if (language != value) {
147             value = language;
148             return true;
149         }
150     }
151     return false;
152 }
153
154 template<class StringType>
155 bool TrackPrivateBaseGStreamer::getTag(GstTagList* tags, const gchar* tagName, StringType& value)
156 {
157     GUniqueOutPtr<gchar> tagValue;
158     if (gst_tag_list_get_string(tags, tagName, &tagValue.outPtr())) {
159         GST_DEBUG("Track %d got %s %s.", m_index, tagName, tagValue.get());
160         value = tagValue.get();
161         return true;
162     }
163     return false;
164 }
165
166 void TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged()
167 {
168     TrackPrivateBaseClient* client = m_owner->client();
169
170     GRefPtr<GstTagList> tags;
171     {
172         LockHolder lock(m_tagMutex);
173         tags.swap(m_tags);
174     }
175
176     if (!tags)
177         return;
178
179     if (getTag(tags.get(), GST_TAG_TITLE, m_label) && client)
180         client->labelChanged(m_label);
181
182     AtomString language;
183     if (!getLanguageCode(tags.get(), language))
184         return;
185
186     if (language == m_language)
187         return;
188
189     m_language = language;
190     if (client)
191         client->languageChanged(m_language);
192 }
193
194 } // namespace WebCore
195
196 #endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK)