59
65
MediaPlayer::NetworkState error;
60
66
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
68
bool issueError = true;
69
bool attemptNextLocation = false;
71
if (message->structure) {
72
const gchar* messageTypeName = gst_structure_get_name(message->structure);
74
// Redirect messages are sent from elements, like qtdemux, to
75
// notify of the new location(s) of the media.
76
if (!g_strcmp0(messageTypeName, "redirect")) {
77
mp->mediaLocationChanged(message);
63
82
switch (GST_MESSAGE_TYPE(message)) {
64
83
case GST_MESSAGE_ERROR:
84
if (mp && mp->pipelineReset())
65
86
gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
66
87
LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
72
93
|| err->code == GST_CORE_ERROR_MISSING_PLUGIN
73
94
|| err->code == GST_RESOURCE_ERROR_NOT_FOUND)
74
95
error = MediaPlayer::FormatError;
75
else if (err->domain == GST_STREAM_ERROR)
96
else if (err->domain == GST_STREAM_ERROR) {
76
97
error = MediaPlayer::DecodeError;
77
else if (err->domain == GST_RESOURCE_ERROR)
98
attemptNextLocation = true;
99
} else if (err->domain == GST_RESOURCE_ERROR)
78
100
error = MediaPlayer::NetworkError;
81
mp->loadingFailed(error);
103
if (attemptNextLocation)
104
issueError = !mp->loadNextLocation();
106
mp->loadingFailed(error);
83
109
case GST_MESSAGE_EOS:
84
110
LOG_VERBOSE(Media, "End of Stream");
132
void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, gpointer data)
134
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
135
GOwnPtr<GstElement> element;
137
g_object_get(mp->m_playBin, "source", &element.outPtr(), NULL);
138
gst_object_replace((GstObject**) &mp->m_source, (GstObject*) element.get());
143
GOwnPtr<char> location;
144
g_object_get(element.get(), "location", &location.outPtr(), NULL);
146
// Do injection only for elements dealing with uris.
147
if (!gst_uri_is_valid(location.get()))
150
GOwnPtr<SoupURI> uri(soup_uri_new(location.get()));
152
// Do injection only for http(s) uris.
153
if (!SOUP_URI_VALID_FOR_HTTP(uri))
156
// Let Apple web servers know we want to access their nice movie trailers.
157
if (g_str_equal(uri->host, "movies.apple.com"))
158
g_object_set(element.get(), "user-agent", "Quicktime/7.2.0", NULL);
160
// Set the HTTP referer.
161
Frame* frame = mp->m_player->frameView() ? mp->m_player->frameView()->frame() : 0;
162
Document* document = frame ? frame->document() : 0;
164
GstStructure* extraHeaders = gst_structure_new("extra-headers",
165
"Referer", G_TYPE_STRING,
166
document->documentURI().utf8().data(), 0);
167
g_object_set(element.get(), "extra-headers", extraHeaders, NULL);
168
gst_structure_free(extraHeaders);
171
// Deal with the cookies from now on.
172
GParamSpec* cookiesParamSpec = g_object_class_find_property(G_OBJECT_GET_CLASS(element.get()), "cookies");
174
// First check if the source element has a cookies property
175
// of the format we expect
176
if (!cookiesParamSpec || cookiesParamSpec->value_type != G_TYPE_STRV)
179
// Then get the cookies for the URI and set them
180
SoupSession* session = webkit_get_default_session();
181
SoupSessionFeature* cookieJarFeature = soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR);
182
if (!cookieJarFeature)
185
SoupCookieJar* cookieJar = SOUP_COOKIE_JAR(cookieJarFeature);
186
GOwnPtr<char> cookies(soup_cookie_jar_get_cookies(cookieJar, uri.get(), FALSE));
187
char* cookiesStrv[] = {cookies.get(), 0};
188
g_object_set(element.get(), "cookies", cookiesStrv, NULL);
106
191
void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
108
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
112
gboolean notifyVolumeIdleCallback(MediaPlayer* mp)
193
// This is called when playbin receives the notify::volume signal.
194
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
198
gboolean notifyVolumeIdleCallback(gpointer data)
200
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
201
mp->volumeChangedCallback();
205
void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
207
// This is called when playbin receives the notify::mute signal.
208
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
212
gboolean notifyMuteIdleCallback(gpointer data)
214
MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
215
mp->muteChangedCallback();
444
563
g_object_set(m_playBin, "volume", static_cast<double>(volume), NULL);
566
void MediaPlayerPrivate::volumeChangedCallback()
569
g_object_get(m_playBin, "volume", &volume, NULL);
570
m_player->volumeChanged(static_cast<float>(volume));
447
573
void MediaPlayerPrivate::volumeChanged()
449
if (m_volumeIdleId) {
450
576
g_source_remove(m_volumeIdleId);
453
m_volumeIdleId = g_idle_add((GSourceFunc) notifyVolumeIdleCallback, m_player);
577
m_volumeIdleId = g_idle_add((GSourceFunc) notifyVolumeIdleCallback, this);
457
580
void MediaPlayerPrivate::setRate(float rate)
459
582
// Avoid useless playback rate update.
819
void MediaPlayerPrivate::mediaLocationChanged(GstMessage* message)
821
if (m_mediaLocations)
822
gst_structure_free(m_mediaLocations);
824
if (message->structure) {
825
// This structure can contain:
826
// - both a new-location string and embedded locations structure
827
// - or only a new-location string.
828
m_mediaLocations = gst_structure_copy(message->structure);
829
const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations");
832
m_mediaLocationCurrentIndex = gst_value_list_get_size(locations) -1;
838
bool MediaPlayerPrivate::loadNextLocation()
840
if (!m_mediaLocations)
843
const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations");
844
const gchar* newLocation = 0;
847
// Fallback on new-location string.
848
newLocation = gst_structure_get_string(m_mediaLocations, "new-location");
854
if (m_mediaLocationCurrentIndex < 0) {
855
m_mediaLocations = 0;
859
const GValue* location = gst_value_list_get_value(locations,
860
m_mediaLocationCurrentIndex);
861
const GstStructure* structure = gst_value_get_structure(location);
864
m_mediaLocationCurrentIndex--;
868
newLocation = gst_structure_get_string(structure, "new-location");
872
// Found a candidate. new-location is not always an absolute url
873
// though. We need to take the base of the current url and
874
// append the value of new-location to it.
876
gchar* currentLocation = 0;
877
g_object_get(m_playBin, "uri", ¤tLocation, NULL);
879
KURL currentUrl(KURL(), currentLocation);
880
g_free(currentLocation);
884
if (gst_uri_is_valid(newLocation))
885
newUrl = KURL(KURL(), newLocation);
887
newUrl = KURL(KURL(), currentUrl.baseAsString() + newLocation);
889
RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(currentUrl);
890
if (securityOrigin->canRequest(newUrl)) {
891
LOG_VERBOSE(Media, "New media url: %s", newUrl.string().utf8().data());
893
// Reset player states.
894
m_networkState = MediaPlayer::Loading;
895
m_player->networkStateChanged();
896
m_readyState = MediaPlayer::HaveNothing;
897
m_player->readyStateChanged();
899
// Reset pipeline state.
900
m_resetPipeline = true;
901
gst_element_set_state(m_playBin, GST_STATE_READY);
904
gst_element_get_state(m_playBin, &state, 0, 0);
905
if (state <= GST_STATE_READY) {
906
// Set the new uri and start playing.
907
g_object_set(m_playBin, "uri", newUrl.string().utf8().data(), NULL);
908
gst_element_set_state(m_playBin, GST_STATE_PLAYING);
913
m_mediaLocationCurrentIndex--;
705
918
void MediaPlayerPrivate::loadStateChanged()
721
934
void MediaPlayerPrivate::didEnd()
936
// EOS was reached but in case of reverse playback the position is
937
// not always 0. So to not confuse the HTMLMediaElement we
938
// synchronize position and duration values.
939
float now = currentTime();
941
m_mediaDuration = now;
942
gst_element_set_state(m_playBin, GST_STATE_PAUSED);
726
947
void MediaPlayerPrivate::durationChanged()
949
// Reset cached media duration
952
// And re-cache it if possible.
953
float newDuration = duration();
954
if (!isinf(newDuration))
955
m_mediaDuration = newDuration;
728
957
m_player->durationChanged();
960
bool MediaPlayerPrivate::supportsMuting() const
965
void MediaPlayerPrivate::setMuted(bool muted)
970
g_object_set(m_playBin, "mute", muted, NULL);
973
void MediaPlayerPrivate::muteChangedCallback()
976
g_object_get(m_playBin, "mute", &muted, NULL);
977
m_player->muteChanged(static_cast<bool>(muted));
980
void MediaPlayerPrivate::muteChanged()
983
g_source_remove(m_muteIdleId);
985
m_muteIdleId = g_idle_add((GSourceFunc) notifyMuteIdleCallback, this);
731
988
void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error)
733
990
m_errorOccured = true;
945
1202
g_object_set(m_playBin, "uri", url.utf8().data(), NULL);
947
1204
g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
1205
g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
1206
g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
949
1208
m_videoSink = webkit_video_sink_new();