diff --git a/LayoutTests/platform/gtk/Skipped b/LayoutTests/platform/gtk/Skipped index fc7a7d6..eeae147 100644 --- a/LayoutTests/platform/gtk/Skipped +++ b/LayoutTests/platform/gtk/Skipped @@ -3588,9 +3588,7 @@ media/video-source-error.html # Tests timing out media/controls-drag-timebar.html -media/event-attributes.html media/unsupported-rtsp.html -media/video-played-collapse.html # Tests generating new results media/audio-controls-rendering.html media/video-aspect-ratio.html diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp index 11eb4d4..538b7fd 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp @@ -66,11 +66,11 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message); error = MediaPlayer::Empty; - if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND || - err->code == GST_STREAM_ERROR_WRONG_TYPE || - err->code == GST_STREAM_ERROR_FAILED || - err->code == GST_CORE_ERROR_MISSING_PLUGIN || - err->code == GST_RESOURCE_ERROR_NOT_FOUND) + if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND + || err->code == GST_STREAM_ERROR_WRONG_TYPE + || err->code == GST_STREAM_ERROR_FAILED + || err->code == GST_CORE_ERROR_MISSING_PLUGIN + || err->code == GST_RESOURCE_ERROR_NOT_FOUND) error = MediaPlayer::FormatError; else if (err->domain == GST_STREAM_ERROR) error = MediaPlayer::DecodeError; @@ -137,6 +137,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_videoSink(0) , m_source(0) , m_seekTime(0) + , m_changingRate(false) , m_endTime(numeric_limits::infinity()) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) @@ -186,14 +187,26 @@ void MediaPlayerPrivate::load(const String& url) void MediaPlayerPrivate::play() { - LOG_VERBOSE(Media, "Play"); - gst_element_set_state(m_playBin, GST_STATE_PLAYING); + GstState state; + GstState pending; + + gst_element_get_state(m_playBin, &state, &pending, 250 * GST_NSECOND); + if (state != GST_STATE_PLAYING) { + LOG_VERBOSE(Media, "Play"); + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + } } void MediaPlayerPrivate::pause() { - LOG_VERBOSE(Media, "Pause"); - gst_element_set_state(m_playBin, GST_STATE_PAUSED); + GstState state; + GstState pending; + + gst_element_get_state(m_playBin, &state, &pending, 250 * GST_NSECOND); + if (state != GST_STATE_PAUSED) { + LOG_VERBOSE(Media, "Pause"); + gst_element_set_state(m_playBin, GST_STATE_PAUSED); + } } float MediaPlayerPrivate::duration() const @@ -229,10 +242,17 @@ float MediaPlayerPrivate::currentTime() const if (m_seeking) return m_seekTime; + return playbackPosition(m_playBin); + +} + +float playbackPosition(GstElement* playbin) +{ + float ret = 0.0; GstQuery* query = gst_query_new_position(GST_FORMAT_TIME); - if (!gst_element_query(m_playBin, query)) { + if (!gst_element_query(playbin, query)) { LOG_VERBOSE(Media, "Position query failed..."); gst_query_unref(query); return ret; @@ -269,6 +289,7 @@ void MediaPlayerPrivate::seek(float time) GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) LOG_VERBOSE(Media, "Seek to %f failed", time); else { + gst_element_get_state(m_playBin, 0, 0, 40 * GST_MSECOND); m_seeking = true; m_seekTime = sec; } @@ -320,10 +341,10 @@ IntSize MediaPlayerPrivate::naturalSize() const gfloat pixelAspectRatio; gint pixelAspectRatioNumerator, pixelAspectRatioDenominator; - if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps) || - !gst_video_format_parse_caps(caps, NULL, &width, &height) || - !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, - &pixelAspectRatioDenominator)) { + if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps) + || !gst_video_format_parse_caps(caps, 0, &width, &height) + || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, + &pixelAspectRatioDenominator)) { gst_object_unref(GST_OBJECT(pad)); return IntSize(); } @@ -363,16 +384,36 @@ void MediaPlayerPrivate::setVolume(float volume) void MediaPlayerPrivate::setRate(float rate) { - if (rate == 0.0) { - gst_element_set_state(m_playBin, GST_STATE_PAUSED); + GstState state; + GstState pending; + + gst_element_get_state(m_playBin, + &state, &pending, 250 * GST_NSECOND); + if (state != GST_STATE_PLAYING) return; - } if (m_isStreaming) return; + m_changingRate = true; + float currentPosition = playbackPosition(m_playBin); + GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE); + gint64 start, end; + LOG_VERBOSE(Media, "Set Rate to %f", rate); - seek(currentTime()); + if (rate >= 0) { + start = currentPosition; + end = GST_CLOCK_TIME_NONE; + } else { + start = 0; + end = currentPosition; + } + if (!gst_element_seek(m_playBin, rate, GST_FORMAT_TIME, flags, + GST_SEEK_TYPE_SET, start, + GST_SEEK_TYPE_SET, end)) + LOG_VERBOSE(Media, "Set rate to %f failed", rate); + else + gst_element_get_state(m_playBin, 0, 0, 40 * GST_MSECOND); } int MediaPlayerPrivate::dataRate() const @@ -507,6 +548,11 @@ void MediaPlayerPrivate::updateStates() } else m_paused = true; + if (m_changingRate) { + m_player->rateChanged(); + m_changingRate = false; + } + if (m_seeking) { shouldUpdateAfterSeek = true; m_seeking = false; @@ -643,10 +689,10 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) double scale, gapHeight, gapWidth; GstVideoFormat format; - GstCaps *caps = gst_buffer_get_caps(m_buffer); + GstCaps* caps = gst_buffer_get_caps(m_buffer); - if (G_UNLIKELY(!gst_video_format_parse_caps(caps, &format, &width, &height) || - !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator))) { + if (G_UNLIKELY(!gst_video_format_parse_caps(caps, &format, &width, &height) + || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator))) { gst_caps_unref(caps); return; } @@ -676,7 +722,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) displayHeight *= doublePixelAspectRatioDenominator / doublePixelAspectRatioNumerator; // Calculate the largest scale factor that would fill the target surface - scale = MIN(rect.width() / displayWidth, rect.height() / displayHeight); + scale = std::min(rect.width() / displayWidth, rect.height() / displayHeight); // And calculate the new display width/height displayWidth *= scale; displayHeight *= scale; @@ -743,15 +789,15 @@ static HashSet mimeTypeCache() // by default. In that case, we should not consider these types supportable by GStreamer. // Examples of what GStreamer can support but should not be added: // text/plain, text/html, image/jpeg, application/xml - if (g_str_equal(mimetype[0], "audio") || - g_str_equal(mimetype[0], "video") || - (g_str_equal(mimetype[0], "application") && - !ignoredApplicationSubtypes.contains(String(mimetype[1])))) { + if (g_str_equal(mimetype[0], "audio") + || g_str_equal(mimetype[0], "video") + || (g_str_equal(mimetype[0], "application") + && !ignoredApplicationSubtypes.contains(String(mimetype[1])))) { cache.add(String(capability[0])); // These formats are supported by GStreamer, but not correctly advertised - if (g_str_equal(capability[0], "video/x-h264") || - g_str_equal(capability[0], "audio/x-m4a")) { + if (g_str_equal(capability[0], "video/x-h264") + || g_str_equal(capability[0], "audio/x-m4a")) { cache.add(String("video/mp4")); cache.add(String("audio/aac")); } @@ -766,7 +812,7 @@ static HashSet mimeTypeCache() // This is what we are handling: mpegversion=(int)1, layer=(int)[ 1, 3 ] gchar** versionAndLayer = g_strsplit(capability[1], ",", 2); - if (g_str_has_suffix (versionAndLayer[0], "(int)1")) { + if (g_str_has_suffix(versionAndLayer[0], "(int)1")) { for (int i = 0; versionAndLayer[1][i] != '\0'; i++) { if (versionAndLayer[1][i] == '1') cache.add(String("audio/mp1")); diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h index 3f0f29a..299e6cf 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h @@ -39,14 +39,15 @@ typedef struct _GstBus GstBus; namespace WebCore { - class GraphicsContext; - class IntSize; - class IntRect; - class String; +class GraphicsContext; +class IntSize; +class IntRect; +class String; - gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); +gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); +float playbackPosition(GstElement* playbin); - class MediaPlayerPrivate : public MediaPlayerPrivateInterface { +class MediaPlayerPrivate : public MediaPlayerPrivateInterface { friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate); @@ -126,6 +127,7 @@ namespace WebCore { GstElement* m_videoSink; GstElement* m_source; GstClockTime m_seekTime; + bool m_changingRate; float m_endTime; bool m_isEndReached; MediaPlayer::NetworkState m_networkState;