e411dcc1d807070580e74957fe5ac2c5e44be930
[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 "GStreamerUtilities.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 static void trackPrivateActiveChangedCallback(GObject*, GParamSpec*, TrackPrivateBaseGStreamer* track)
47 {
48     track->activeChanged();
49 }
50
51 static void trackPrivateTagsChangedCallback(GObject*, GParamSpec*, TrackPrivateBaseGStreamer* track)
52 {
53     track->tagsChanged();
54 }
55
56 TrackPrivateBaseGStreamer::TrackPrivateBaseGStreamer(TrackPrivateBase* owner, gint index, GRefPtr<GstPad> pad)
57     : m_index(index)
58     , m_pad(pad)
59     , m_owner(owner)
60 {
61     ASSERT(m_pad);
62
63     g_signal_connect(m_pad.get(), "notify::active", G_CALLBACK(trackPrivateActiveChangedCallback), this);
64     g_signal_connect(m_pad.get(), "notify::tags", G_CALLBACK(trackPrivateTagsChangedCallback), this);
65
66     // We can't call notifyTrackOfTagsChanged() directly, because we need tagsChanged()
67     // to setup m_tags.
68     tagsChanged();
69 }
70
71 TrackPrivateBaseGStreamer::~TrackPrivateBaseGStreamer()
72 {
73     disconnect();
74 }
75
76 void TrackPrivateBaseGStreamer::disconnect()
77 {
78     if (!m_pad)
79         return;
80
81     g_signal_handlers_disconnect_by_func(m_pad.get(),
82         reinterpret_cast<gpointer>(trackPrivateActiveChangedCallback), this);
83     g_signal_handlers_disconnect_by_func(m_pad.get(),
84         reinterpret_cast<gpointer>(trackPrivateTagsChangedCallback), this);
85
86     m_activeTimerHandler.cancel();
87     m_tagTimerHandler.cancel();
88
89     m_pad.clear();
90     m_tags.clear();
91 }
92
93 void TrackPrivateBaseGStreamer::activeChanged()
94 {
95     m_activeTimerHandler.schedule("[WebKit] TrackPrivateBaseGStreamer::notifyTrackOfActiveChanged", std::function<void()>(std::bind(&TrackPrivateBaseGStreamer::notifyTrackOfActiveChanged, this)));
96 }
97
98 void TrackPrivateBaseGStreamer::tagsChanged()
99 {
100     m_tagTimerHandler.cancel();
101
102     GRefPtr<GstTagList> tags;
103     g_object_get(m_pad.get(), "tags", &tags.outPtr(), NULL);
104     {
105         DeprecatedMutexLocker lock(m_tagMutex);
106         m_tags.swap(tags);
107     }
108
109     m_tagTimerHandler.schedule("[WebKit] TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged", std::function<void()>(std::bind(&TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged, this)));
110 }
111
112 void TrackPrivateBaseGStreamer::notifyTrackOfActiveChanged()
113 {
114     if (!m_pad)
115         return;
116
117     gboolean active = false;
118     if (m_pad)
119         g_object_get(m_pad.get(), "active", &active, NULL);
120
121     setActive(active);
122 }
123
124 bool TrackPrivateBaseGStreamer::getLanguageCode(GstTagList* tags, AtomicString& value)
125 {
126     String language;
127     if (getTag(tags, GST_TAG_LANGUAGE_CODE, language)) {
128         language = gst_tag_get_language_code_iso_639_1(language.utf8().data());
129         INFO_MEDIA_MESSAGE("Converted track %d's language code to %s.", m_index, language.utf8().data());
130         if (language != value) {
131             value = language;
132             return true;
133         }
134     }
135     return false;
136 }
137
138 template<class StringType>
139 bool TrackPrivateBaseGStreamer::getTag(GstTagList* tags, const gchar* tagName, StringType& value)
140 {
141     GUniqueOutPtr<gchar> tagValue;
142     if (gst_tag_list_get_string(tags, tagName, &tagValue.outPtr())) {
143         INFO_MEDIA_MESSAGE("Track %d got %s %s.", m_index, tagName, tagValue.get());
144         value = tagValue.get();
145         return true;
146     }
147     return false;
148 }
149
150 void TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged()
151 {
152     if (!m_pad)
153         return;
154
155     TrackPrivateBaseClient* client = m_owner->client();
156     if (!client)
157         return;
158
159     GRefPtr<GstTagList> tags;
160     {
161         DeprecatedMutexLocker lock(m_tagMutex);
162         tags.swap(m_tags);
163     }
164     if (!tags)
165         return;
166
167     if (getTag(tags.get(), GST_TAG_TITLE, m_label))
168         client->labelChanged(m_owner, m_label);
169
170     AtomicString language;
171     if (!getLanguageCode(tags.get(), language))
172         return;
173
174     if (language == m_language)
175         return;
176
177     m_language = language;
178     client->languageChanged(m_owner, m_language);
179 }
180
181 } // namespace WebCore
182
183 #endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK)