Bug 140808 - [GTK] .ogv videos over http cannot seek using video controls
Summary: [GTK] .ogv videos over http cannot seek using video controls
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKitGTK (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Linux
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-01-22 18:41 PST by Philip Chimento
Modified: 2018-02-09 09:21 PST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Philip Chimento 2015-01-22 18:41:02 PST
The following Python script using WebKitGTK 2.4.6 exhibits some odd behaviour with the video progress control while playing an .ogv file over HTTP:

    from gi.repository import WebKit2, Gtk

    win = Gtk.Window(default_width=800, default_height=600)
    view = WebKit2.WebView()

    view.load_html('''
    <html>
    <body>
        <video src="http://upload.wikimedia.org/wikipedia/commons/1/13/2012_Team_USA_basketball_practice.ogv"
               height="580" width="780" controls/>
    </body>
    </html>
    ''', 'file:///')

    win.add(view)
    win.show_all()
    win.connect('destroy', Gtk.main_quit)
    Gtk.main()

If you try to seek to a later position in the video using the progress control, the progress bar and the clock update, but the video freezes at the new frame, and cannot be made to play again.

If you download the file and play it from a file:// URI, seeking works properly. If you play a .webm file over HTTP, seeking works properly.

For comparison, I tried the same thing on a Fedora 21 VM with 2.6.4, and 2.7.4 from Rawhide. (Sorry, I don't have actual hardware running an appropriate environment at the moment.)

On 2.6.4, when you try to seek, the video plays on as if nothing happened, the progress bar updates to the new position, but the clock freezes. (This happens with .webm videos as well.)

On 2.7.4, the WebProcess crashes when you try to play the video in the first place. Stack trace below:

Program received signal SIGSEGV, Segmentation fault.
0x00007f94dc766029 in llint_entry () from /lib64/libjavascriptcoregtk-4.0.so.18
(gdb) bt
#0  0x00007f94dc766029 in llint_entry ()
    at /lib64/libjavascriptcoregtk-4.0.so.18
#1  0x00007f94dc761e76 in vmEntryToJavaScript ()
    at /lib64/libjavascriptcoregtk-4.0.so.18
#2  0x00007f94dc4f2684 in JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) () at /lib64/libjavascriptcoregtk-4.0.so.18
#3  0x00007f94dc4d290c in JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) () at /lib64/libjavascriptcoregtk-4.0.so.18
#4  0x00007f94dc61cc35 in JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) ()
    at /lib64/libjavascriptcoregtk-4.0.so.18
#5  0x00007f94dc61cc51 in JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&, JSC::JSValue*) ()
    at /lib64/libjavascriptcoregtk-4.0.so.18
#6  0x00007f94dd2e693d in WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) () at /lib64/libwebkit2gtk-4.0.so.37
#7  0x00007f94dd48bd5f in WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*, WTF::Vector<WebCore::RegisteredEventListener, 1ul, WTF::CrashOnOverflow>&) () at /lib64/libwebkit2gtk-4.0.so.37
#8  0x00007f94dd48c180 in WebCore::EventTarget::fireEventListeners(WebCore::Event*) () at /lib64/libwebkit2gtk-4.0.so.37
#9  0x00007f94dd4854c8 in WebCore::EventContext::handleLocalEvents(WebCore::Event&) const () at /lib64/libwebkit2gtk-4.0.so.37
#10 0x00007f94dd487836 in WebCore::EventDispatcher::dispatchEvent(WebCore::Node*, WTF::PassRefPtr<WebCore::Event>) () at /lib64/libwebkit2gtk-4.0.so.37
#11 0x00007f94dd4a2555 in WebCore::Node::dispatchEvent(WTF::PassRefPtr<WebCore::Event>) () at /lib64/libwebkit2gtk-4.0.so.37
#12 0x00007f94dd48ddb6 in WebCore::GenericEventQueue::dispatchOneEvent() ()
    at /lib64/libwebkit2gtk-4.0.so.37
#13 0x00007f94dd48dee5 in WebCore::GenericEventQueue::sharedTimerFired() ()
    at /lib64/libwebkit2gtk-4.0.so.37
#14 0x00007f94dd8e58d9 in WebCore::ThreadTimers::sharedTimerFiredInternal() ()
    at /lib64/libwebkit2gtk-4.0.so.37
#15 0x00007f94dc7dcb51 in WTF::GMainLoopSource::voidCallback() ()
    at /lib64/libjavascriptcoregtk-4.0.so.18
#16 0x00007f94dc7d7cda in WTF::GMainLoopSource::voidSourceCallback(WTF::GMainLoopSource*) () at /lib64/libjavascriptcoregtk-4.0.so.18
#17 0x00007f94dc7d7d3f in WTF::{lambda(_GSource*, int (*)(void*), void*)#1}::_FUN(_GSource*, int (*)(void*), void*) () at /lib64/libjavascriptcoregtk-4.0.so.18
#18 0x00007f94d96ebaeb in g_main_context_dispatch (context=0x7f94dff20780)
    at gmain.c:3111
#19 0x00007f94d96ebaeb in g_main_context_dispatch (context=context@entry=0x7f94dff20780) at gmain.c:3710
#20 0x00007f94d96ebe88 in g_main_context_iterate (context=0x7f94dff20780, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3781
#21 0x00007f94d96ec1b2 in g_main_loop_run (loop=0x7f94e00b2300) at gmain.c:3975
#22 0x00007f94dd1e5319 in int WebKit::ChildProcessMain<WebKit::WebProcess, WebKit::WebProcessMain>(int, char**) () at /lib64/libwebkit2gtk-4.0.so.37
#23 0x00007f94d3fe3fe0 in __libc_start_main () at /lib64/libc.so.6
#24 0x00007f94deec4c59 in _start ()
Comment 1 Mario Sanchez Prada 2015-08-06 03:48:24 PDT
I could not get the crash myself with newer versions of WebKitGTK+, but I could reproduce the rest of the issue in the following environments:

  * epiphany 3.16.2 + webkitgtk4-2.8.4 (Fedora 22 64bit)
  * MiniBrowser built from a fairly recent checkout of the sources: r186277
    http://trac.webkit.org/changeset/186277

In both cases, I could start play and seek positions inside the .ogv video without problems from a local URI, but seeking would not work over HTTP. As I said, I could not reproduce the crash in any case, though.

Also, in contrast, webM and H264 videos played and seeked just fine, as I could check by simply loading http://www.quirksmode.org/html5/tests/video.html in epiphany and MiniBrowser.

I'm adding Calvaris, Victor and Philippe to CC, perhaps they have some insight on why this might be happening, as it could be an issue present in SVN trunk.
Comment 2 Philippe Normand 2015-08-06 04:06:50 PDT
Which GStreamer version?

Seeking over HTTP for OGG is unfortunately known to not work very well.
Comment 3 Mario Sanchez Prada 2015-08-06 05:47:41 PDT
(In reply to comment #2)
> Which GStreamer version?
> 
1.4.4 for the case with MiniBrowser (the version inside the internal jhbuild, really) and 1.4.5 for the case with epiphany 3.16.2, in my Fedora 22 box.

> Seeking over HTTP for OGG is unfortunately known to not work very well.

Any pointer to specific issues we could check for a better understanding? Thanks!
Comment 4 Philippe Normand 2015-08-06 08:02:23 PDT
You can get some debug infos with the GST_DEBUG env var:

GST_DEBUG=webkitwebsrc:5

Seek support is implemented in WebKitWebSourceGStreamer.cpp, you can see there that it relies on HTTP range requests support, so if the server doesn't support that, there's not much we can do :(

Additionally the demuxer (in this case, oggdemux) needs to handle this properly.
Comment 5 Mario Sanchez Prada 2015-08-06 09:44:37 PDT
(In reply to comment #4)
> You can get some debug infos with the GST_DEBUG env var:
> 
> GST_DEBUG=webkitwebsrc:5
> 
I'll do that tomorrow morning, see what it comes up with. Thanks for the hint!

> Seek support is implemented in WebKitWebSourceGStreamer.cpp, you can see
> there that it relies on HTTP range requests support, so if the server
> doesn't support that, there's not much we can do :(
> 
I don't think that's the case here, since all the videos from http://www.quirksmode.org/html5/tests/video.html are hosted in the same server, and the WebM and H264 ones work fine, while the OGV does not.

> Additionally the demuxer (in this case, oggdemux) needs to handle this
> properly.

We are using the demuxer from gstreamer-plugins-base, perhaps it does not support this then? Although it still strikes me the fact that it works when played from a local source but not from a remote one...
Comment 6 Philippe Normand 2015-08-06 10:35:11 PDT
(In reply to comment #5)
> (In reply to comment #4)
> > You can get some debug infos with the GST_DEBUG env var:
> > 
> > GST_DEBUG=webkitwebsrc:5
> > 
> I'll do that tomorrow morning, see what it comes up with. Thanks for the
> hint!
> 
> > Seek support is implemented in WebKitWebSourceGStreamer.cpp, you can see
> > there that it relies on HTTP range requests support, so if the server
> > doesn't support that, there's not much we can do :(
> > 
> I don't think that's the case here, since all the videos from
> http://www.quirksmode.org/html5/tests/video.html are hosted in the same
> server, and the WebM and H264 ones work fine, while the OGV does not.
> 
> > Additionally the demuxer (in this case, oggdemux) needs to handle this
> > properly.
> 
> We are using the demuxer from gstreamer-plugins-base, perhaps it does not
> support this then? Although it still strikes me the fact that it works when
> played from a local source but not from a remote one...

Well it depends how the pipeline retrieves data from the source, there are 2 modes, push and pull. By local source you mean file:///? In that configuration push mode is selected (I think) and filesrc has a complete access to the data, and then seeking is easy. But for an http:// source, where we can't randomly access data easily, we work in pull mode and that's a bit more complicated.
Comment 7 Xabier Rodríguez Calvar 2015-08-06 10:38:59 PDT
It is also interesting that the crash happens in JS without any trace of going into GStreamer, or am I missing anything?
Comment 8 Philip Chimento 2015-08-06 11:36:57 PDT
(In reply to comment #7)
> It is also interesting that the crash happens in JS without any trace of
> going into GStreamer, or am I missing anything?

I think the crash may only have been in that particular development snapshot.

(In reply to comment #6)
> Well it depends how the pipeline retrieves data from the source, there are 2
> modes, push and pull. By local source you mean file:///? In that
> configuration push mode is selected (I think) and filesrc has a complete
> access to the data, and then seeking is easy. But for an http:// source,
> where we can't randomly access data easily, we work in pull mode and that's
> a bit more complicated.

How about blob URIs? I also have a sample program that loads a local file using XHR and sets the <video>'s src attribute to a blob URI. This also doesn't seek when playing OGV.

import gi
gi.require_version('WebKit2', '4.0')

from gi.repository import GLib, Gio, Gtk, WebKit2


def _handle_local_uri(request, data=None):
    path = request.get_path()
    f = Gio.File.new_for_path(path)
    try:
        stream = f.read(None)
        request.finish(stream, -1, 'text/html')
    except GLib.Error as e:
        request.finish_error(e)

context = WebKit2.WebContext.get_default()
security = context.get_security_manager()

context.register_uri_scheme('local', _handle_local_uri, None)
security.register_uri_scheme_as_cors_enabled('local')

w = Gtk.Window(default_width=700, default_height=500)
v = WebKit2.WebView()
w.add(v)

w.connect('destroy', Gtk.main_quit)
v.get_settings().props.enable_developer_extras = True
# Comment the following line out to break playing the video at all!
v.get_inspector().show()

v.load_html('''
<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
window.onload = function() {
    var elem = document.getElementById("video-player");
    var req = new XMLHttpRequest();
    req.onload = function () {
        var blob_uri = URL.createObjectURL(this.response);
        var source = document.createElement("source");
        elem.appendChild(source);
        source.src = blob_uri;
    };
    req.responseType = "blob";
    req.open("GET", "video.ogv");
    req.send(null);
};
    </script>
</head>
<body>
    <video autoplay controls width="400" height="300" id="video-player"></video>
</body>
</html>
''', 'local:///home/philip/checkout/scratch/')

w.show_all()
Gtk.main()
Comment 9 Xabier Rodríguez Calvar 2015-08-07 00:32:00 PDT
(In reply to comment #8)
> How about blob URIs? I also have a sample program that loads a local file
> using XHR and sets the <video>'s src attribute to a blob URI. This also
> doesn't seek when playing OGV.

Does this work when playing anything else?
Comment 10 Philippe Normand 2015-08-07 00:39:12 PDT
blob URIs are also loaded with the webkitwebsrc element which will use the ResourceLoader underneath, but I don't know how blob loading works there.
Comment 11 Mario Sanchez Prada 2015-08-07 03:11:35 PDT
(In reply to comment #5)
> (In reply to comment #4)
> > You can get some debug infos with the GST_DEBUG env var:
> > 
> > GST_DEBUG=webkitwebsrc:5
> > 
> I'll do that tomorrow morning, see what it comes up with. Thanks for the
> hint!
> 
As a follow-up on this, I run MiniBrowser today with this envvar set and this is what I got when trying to seek a WebM or an OGV from the link mentioned before (same output in both cases):

  0:00:25.454755142 28295      0x24d64c0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:864:webKitWebSrcSeekDataCb:<source> Seeking to offset: 1495502
  0:00:25.454781350 28295      0x24d64c0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:872:webKitWebSrcSeekDataCb:<source> Doing range-request seek
  0:00:25.455223500 28295      0x316a0a0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:808:webKitWebSrcNeedDataCb:<source> Need more data: 4096
  0:00:25.455281497 28295      0x24d64c0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:471:webKitWebSrcStop:<source> Stopped request
  0:00:25.455336743 28295      0x24d64c0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:582:webKitWebSrcStart:<source> Persistent connection support disabled
  0:00:25.455538976 28295      0x24d64c0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:617:webKitWebSrcStart:<source> Started request
  0:00:25.567535912 28295      0x24d64c0 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:927:handleResponseReceived:<source> Received response: 206

Additionally, I can see a whole lot of lines like the following ones in both cases too:

0:02:39.882248677 28295      0x3196d40 DEBUG           webkitwebsrc ../../Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:808:webKitWebSrcNeedDataCb:<source> Need more data: 4096
 
Yet I could not spot any difference between the two scenarios. Maybe am I missing something else?

(In reply to comment #7)
> It is also interesting that the crash happens in JS without any trace of
> going into GStreamer, or am I missing anything?

As Philip said, I think this might be unrelated. At least I'm not getting any crash either with 2.8.4 or SVN trunk either
Comment 12 Philip Chimento 2015-08-07 10:21:58 PDT
(In reply to comment #9)
> (In reply to comment #8)
> > How about blob URIs? I also have a sample program that loads a local file
> > using XHR and sets the <video>'s src attribute to a blob URI. This also
> > doesn't seek when playing OGV.
> 
> Does this work when playing anything else?

Yes, a WebM video (e.g. Big Buck Bunny trailer) played in this manner is able to seek.
Comment 13 Philippe Normand 2015-08-15 06:31:35 PDT
Seems like this has been fixed between gst 1.4.x and current git master (1.5.2). I can seek just fine in that video here.
Comment 14 Mario Sanchez Prada 2015-08-15 08:33:16 PDT
(In reply to comment #13)
> Seems like this has been fixed between gst 1.4.x and current git master
> (1.5.2). I can seek just fine in that video here.
This is very interesting. I've just double-checked and the version of gstreamer packages we have now is the latest one from the stable series (1.4.5), which explains why we are seeing this problem in our platform.

Thanks a lot Philippe for mentioning this, very useful information indeed.
Comment 15 Philippe Normand 2018-02-09 09:21:28 PST
If there's anything left to fix regarding this bug please reopen it :)