Search code examples
firebreath

Streaming video from a plugin to the browser


I've been writing a browser plugin that receives a stream of QVGA video. I'd like to stream that video to the browser in a way that can be programmatically interfaced from JavaScript - for example, something that can be fed into a canvas, like an element or Image() object.

NOTE: this means I'm trying to avoid having my plugin draw into a window - I know I can do that, but I want something that interacts nicely with the rest of the page's rendering and also has a well-known object model that I won't have to implement.

The tricky part is how to do it fast - I can do it for example by setting up the src property to have base64 encoded data, but the overhead is pretty high.

My question is whether there's a way to avoid more overhead (e.g. feeding a raw image buffer instead of formatting an image and base64-encoding it only to have the browser decode it) - what I have right now isn't nearly fast enough.

As for environment, I'm using Firebreath to write the plugin (C++ with NPAPI/ActiveX mostly abstracted away) and I want to preserve the Mac and Windows support I have. Delving into using NPAPI directly is acceptable but I'd rather not.

EDIT: I solved the problem by using an element and updating its 'src' property to a base64 encoded bitmap using the data UI scheme - (e.g. imageJSObject->SetProperty('src', 'data:image/bmp;base64,<encoded BMP>'); Performance isn't great, but it's good enough. The main caveat is that at least on Chrome 15, onload is fired only once, not every time I change the src property, so I have to generate my own event after each update.


Solution

  • There are no high performance methods for sending binary data to the page; you could presumably use the html5 video tag to stream, in which case you could possibly provide a web server source in your plugin, but as far as actually sending binary data to javascript base64 is probably your fastest method.

    On the other hand, if you were to use a windowless plugin you'd have to draw when instructed (you can call InvalidateWindow on the PluginWindow to request a redraw) and you'd draw into an hDC but you'd participate in the DOM ordering. This is windows-specific; on Mac you can do the same thing if you draw with CoreGraphics (CoreAnimation on some but not all browsers).

    As to getting the data to javascript, your options are to use sockets (and something in the browser to query them off of localhost such as websockets or xmlhttprequest or something) or to base64 encode it and send it as a string. There are no binary data capabilities in NPAPI yet.