Blog

  • BBB Subtitle Fixes, On/Off and Remoting

    I’ve been continuing to work on the BBB player and from the list and I decided to tackle two of the items from the list that were quick-fix oversights from past releases. I’m talking about the promised features of toggling subtitles on/off and hooking dummy server calls up for the chapter addition/deletion demo. Also included is Bookmark object and API refactoring.

    Hooking up dummy server calls on chapter addition/deletion

    The purpose for this change was to emulate the final deployed environment from within the library.  I had already hooked up a call using XmlHttpRequest to retrieve chapter data, so this one should’ve been fairly simple. Just modify the two library calls to include XHR and it would be done. Not quite. The strategy was to make the remote call, and then to add/delete it locally only if the remote call succeeded. We want to keep everything in sync, don’t we?

    Turns out syncing that up highlighted an existing synchronization-related bug in the library. The printTOC() function, which prints the Table of Contents, had some weird funny business going on which resulted in the outputted rows being deleted and occasionally not repopulated. A quick fix to moving the deletion code inside the check for if the Table of Contents had been modified fixed this. Not sure why it was placed before it, but it’s fixed now.

    For this to work, I had to add an optional second parameter to the addChapter() function named “updateServer”. Give it true to update the server remotely (required for saving persistent data). See the DEMO!

    Toggle Subtitles On/Off

    This one was really fun, what should’ve been a simple fix had me debugging a bug deep within the VideoJS library. VideoJS has recently launched version 2.0.1, but for our development purposes it isn’t stable enough for us to use. The bug may very well’ve been fixed; the engine has really received a large overhaul.

    The bug itself is that when subtitles are playing, scrolling forwards through the video will update the subtitles appropriately. Scrolling backwards however, does not. The subtitles do not update at all, but rather freeze in place. The issue was that in the OnTimeUpdate function, a loop for finding the newly scrolled to position was only checking forwards. A quick change and it was working. From here the changes were simple. To enable subtitle toggling on the version of VideoJS in the BBB project:

    1. Setup a video.js page as before
    2. Make a checkbox, give it an id (lets say you give it the id chkCC)
    3. Add this attribute to the video element: data-subToggle=”chkCC”
    4. VideoJS automatically hooks into the click event for the checkbox and will toggle subtitle display

    I’ve also submitted a patch to the VideoJS team. Watch for it in new releases of VideoJS or help them build a stable 2.0. You can see the fix in action here.

    Bookmark/API changes

    To stick to conventions a bit better, we’ve renamed our global object from “Mgr” to “bbb”. This way it’s indicative of the project and is lowercase so as not to be confused with Constructor conventions.

    The Bookmark object has also been refactored for convention and memory usage reasons. The equals and getJSON functions have been moved to the prototype, and instantiated Bookmark objects now requires using the “new” keyword. Before, it was simply bbb.Bookmark(params). These were completed as part of Kevin’s and my effort at merging our 0.2 releases together. You can download the unified 0.2 here.

    Looking Forward

    The easy stuff is off the list, which now stands at:

    • Hooking up dummy server calls on chapter addition/deletion
    • Toggle subtitles on/off
    • Refactor Bookmark object to optimize for memory consumption
    • Time In/Out Buttons for setting chapters rather than manual typing
    • Popcorn-formatted metadata generation (will be sent to same dummy server)
  • BBB 0.3 Preview Change

    In my last BBB-related blogging, I mentioned some upcoming features I’ll be focusing on implementing for this next release. After meeting and discussion, we’re switching focus a bit to further fleshing out the chaptering functionality introduced in BBB 0.1. We’ll still be keeping with some of the simpler oversight fixes, but the new list of “to-be-implemented” for me now stands at:

    • Hooking up dummy server calls on chapter addition/deletion
    • Toggle subtitles on/off
    • Refactor Bookmark object to optimize for memory consumption
    • Time In/Out Buttons for setting chapters rather than manual typing
    • Popcorn-formatted metadata generation (will be sent to same dummy server)

    Time permitting, I would love to be able to continue working on the old list as well. As before, the release date for these and Kevin’s features is December 7, 2010.

  • Assembling a Lower Level understanding

    Time for something different from my usual bloggings about JavaScript and the BBB project. Alongside it, I’m on a team of five working to produce a 3D game using C/C++ and DirectX. Luckily, we’ve been granted a custom framework by our professor but it’s still a lot of tough work. Where as many developers take a “get it working and make it look nice”, it has become habit to me to incorporate one other maxim: “get it working blindly fast”. And it’s being put to the test.

    Enter real-time 3D systems, where you have 1/60 of a second to do every calculation required for your application to run. Sure, you can go a little further, most people won’t notice a difference between 30 fps and 60 fps, but with 60 fps being the norm… well it’s tough. And in perf-grinding fashion, I decided I’d take a shot at collision detection where there’s iterations upon iterations of computations.

    THE REHEARSAL

    First shot went alright. It worked in theory but when implementing it… 1 fpm. No, not 1 frame per second, 1 frame per minute. Turns out I’d underestimated the effect of a nested loop on a data set of size 10,000. So I had to start thinking deeper. And lower. It crossed my mind that to make this work, I may have to cross that hallowed C/Assembler boundary and to do it on my own. So I did some research. Basically all I wanted was an absolute value of some arithmetic to operate inside a nested loop. First shot looked something like this (note comments in assembly start with a semicolon):

    register int diff = collidable[j]->getPartition();
    
    __asm {
    mov edx,[part1] ;Move part1 to register edx
    cmp eax,edx ;Compare the accumulator (eax) which should still hold the value of diff (which is also stored in another register) to edx
    jge lblSubtract ;Jump to lblSubtract label if edx is greater than or equal to eax
    xchg eax,edx ;Exchange register values
    lblSubtract: sub eax,edx ;Subtract edx from eax and store result in eax
    mov , eax
    }

    A few things I learned about assembly (ASM) first: Intel processors are optimized for operation to occur on the eax (accumulator) register, with data for operations coming from the edx (data) register. Other convention registers exist (ecx for count variables, for example) but I wanted to get my feet wet, not drown. For the interested, some have it down to an art.

    Also, ASM is very different from C. C does all the memory movement for you, but in ASM you must indicate that you want memory moved to the registers to work with. You can issue instructions to work with it in memory, but these tend to be much more expensive in terms of clock cycles and bytes. Exactly the repercussions of these I’m still learning, I know it’s like saturated fats: keep ’em low. For each desired action too, you must issue the instruction. I’ve commented a few above, but a complete list of Intel instructions (up until 80486) can be found here. I found manuals on the rest of the Intel lineup too.

    I kept digging.

    THE TESTS

    The first approach seems like it’s a pretty good way, huh? Turns out it isn’t. I did some more exploring and learned a few more things. I had three test cases to find the absolute value of a subtraction:

    1. Ternary operations

    register int diff collidable[j]->getPartition() > part1 ? collidable[j]->getPartition() - part1 : part1 - collidable[j]->getPartition();

    2. Negative multiplication

    register int diff collidable[j]->getPartition()-part1;
    if (diff < 0)
    diff *= -1;

    3. Inline Assembly (repeated from above)

    register int diff = collidable[j]->getPartition();
    
    __asm {
    mov edx,[part1] ;Move part1 to register edx
    cmp eax,edx ;Compare the accumulator (eax) which should still hold the value of diff (which is also stored in another register) to edx
    jge lblSubtract ;Jump to lblSubtract label if edx is greater than or equal to eax
    xchg eax,edx ;Exchange register values
    lblSubtract: sub eax,edx ;Subtract edx from eax and store result in eax
    mov , eax
    }

    I tested each both with and without compiler optimizations. The results surprised me.

    Option 1, the ternary operator, was incredibly slow unoptimized. Checking the disassembly, that one line of C code compiled down to an astonishing 41 instructions. Optimized fared significantly better at 17 instructions. Looking good so far. Not really, actually. The inline assembly approach yielded 17 instructions unoptimized and a blitzing 11 optimized. So with inline assembly I could debug with the performance of an optimized build. Of course I lock it into Intel and AMD processors and leave the PowerPC out but who needs anything but Windows? We’re using DirectX, surely there’s no possibility of porting the framework to OpenGL? Actually, there may be. Oops.

    But there was still approach 2. That couldn’t be any good though, it is 3x the number of lines of C than approach 1, and doesn’t have the touch of custom assembly. The results really opened my eyes. Unoptimized, it yields 17 instructions, same as unoptimized inline assembly. Optimized, it gets quashed down to an unbelievable 8 instructions. That’s 5 times fewer than the single line of C tertiary operator and 3 quicker than optimized inline assembly. How was this possible?

    THE ANALYSIS

    Remember the slave compiler who optimizes everything for us? Turns out he’s not such a bad guy after all, just gets a little confused sometimes. The inline assembly to “improve” the calculation of an absolute value between an intermediate calculation and it’s use just below interfered with the compiler’s optimization heuristic. Comparing disassemblies between optimized approaches 2 (3-line C) and 3 (inline assembly) showed that the three extra operations were from moving the value of diff to and from eax. Without the inline assembly mucking things up, the compiler could see that that was all it needed to work with and just kept it in eax. It even kept it in after calculating the absolute value for use in computations just below. My two hours of careful work and research had actually just gummed up the works. And while 3 or even 30 operations don’t seem like much, it matters inside a block of code which needs to operate 100,000,000 times in 1/60 of a second.

    Speaking of those iterations, turns out even those tweaks didn’t do much. It still ground along until I took a look at the bigger picture. Compared to the 2 hours optimizing the inner loop, the 30 minutes I spent changing the algorithm not only made the game playable, but it’s now humming along at 58 fps. So what did I learn?

    • Work with the compiler, not against it. It makes a great development tool.
    • If you have performance-critical code and can’t figure out which approach to take, take them all and investigate how they turn out.
    • Use the new kid on the block: C. The end result will probably be more elegant, quick and portable than if ASM gets involved.
    • Favour global optimizations over local optimizations EVERY TIME.

    Four lessons in two and a half hours, and I feel like I’ve only just scratched the surface.

  • BBB Player – 0.2 Release

    Here we are, deliverable day. Kevin and I have been gearing up for today’s release by fleshing out the feature set on our player project and iterating/fine tuning what was already there. If you’ve been following my series of blog posts you may have an idea of my portion, but I’m only half the team! Watch out for the second half of the release notes on Kevin’s blog. We’ve been working on entirely different feature sets, so we decided to split release notes up.

    Kevin’s own work has been on local data storage, statistics and user interactivity. Looking forward to December 7th’s 0.3 Release, I’ll be focusing on inclusive and accessible design, a few bug fixes, and data display. These come in the form of:

    • A multilingual (French and English) interface
    • Keyboard-driven player control
    • Ratings display
    • Captions distinct by movie
    • Captions on/off

    Time permitting, I’ll also try to integrate captioning with the Google Translate API. Stay tuned for further project updates! You can view the current status at version 0.2 here.

  • BBB Remote Bookmark Querying

    In preparing for tomorrow’s 0.2 release of the BBB Player, I’ve taken the first step to moving towards remote data retrieval. While right now we’re still using that terrific stub data, it’s at least now not hard-coded into the JavaScript. Instead, it has been hard-coded into a server script which is queried to return the same stub data in JSON format. Compare this to our original interface which treated the library more like a collection that a catalog. Stub data was populated into the library right in the HTML page something like this:

    Mgr.addBookmark(/* code to create stub bookmark 1 */);
    Mgr.addBookmark(/* code to create stub bookmark 2 */);
    ...
    Mgr.addBookmark(/* code to create stub bookmark 6 */);

    While now it’s a little more like this:

    Mgr.fetchBookmarks();

    There have been a lot of little change like this that have tried to separate the HTML and JS code to minimize the library interface and make it more of a simple “include this library and watch it work”. Many functions now take a single object as an argument rather than a list of parameters, which gives a much simpler and flexible library interface. Another benefit is that less JS code in the HTML page means more bandwidth saved as more JS is cached in the form of an external JS file. And less bandwidth means better! 🙂

    Secondly, this change means that we can separate the code and the data to better test the library. But how does this work when we need to absolutely resolve a URI to XmlHttpRequest for both local development, deployed testing and final deployment? The Same Origin Policy is in place for security reasons, but poses difficulties when moving an application across domains: we can’t always use the same remote location for all environments but we don’t want to have to keep changing the hard-coded URI from localhost to our remote testing environment. We get around this by adopting conventions:

    var baseUri = params.remoteServer || location.href.substring(0, location.href.lastIndexOf("/BBB/")+5);

    The above line resolves where to query for data. If no remote server is specified (default) and assuming that the project is located in directory “BBB” (and no URL rewriting), the above line will just look in the root of the project folder for data. This is exactly how our GitHub project has been structured. Just append the name of the data source script to the end of baseUri and you have a dynamic way to use the above remote querying anywhere.

    We’re also working on other data storage techniques, but I’ll let Kevin divulge those as it is his domain.

  • HTML5 Video Mashup: Green Screen Travel Agency

    Last week, Humph traveled partway across the world to attend the Mozilla Drumbeat Festival in Barcelona, Spain. Turns out, he had a great time. Before going though, he gave us a mini-assignment to be creative and come up with video mash-ups using HTML5 Video, jQuery, and web APIs like Flickr and Google.

    Inspired by world travel, I remembered the internet sensation “Where the Hell is Matt” that swept the world in 2006, and then again in 2008. It’s just a simple video of a guy dancing, but those two combined have been been seen by north of 50 million eyes. In late 2008, he gave a demonstration announcing it as a “hoax”, but then followed that up on MacWorld less than a month later denouncing the hoax. This got me thinking… why not do something similar for this mini assignment?

    So I got to work. MDC has a great article on how to manipulate video using canvas, with their example being chroma-keying (aka green screening) where a colour in the video is replaced by an image. With this skeleton, I went to work. Using the Flickr API Public Feed it is possible to get the urls of a series of images. I did this by a jQuery call to return a JSON formatted string.

    var tempId = document.getElementById('flickrUser').value;
     if (tempId !== currId) {
     $.getJSON('http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?',
     {
     id: currId = tempId,
     format: "json"
     },
     function(data) {
     var items = [];
     var img = document.getElementById('img');
     
     $.each(data.items, function(i,item) {
     items.push(item.media.m);
     });
     
     img.src = items[0];
     processor.doLoad(img, items);
     
     });
     }

    This code was more or less adapted from the jQuery example on ajax calls. This already gave the “slide show” illusion of various locations, but there was no way to know where I was making the Man in the Mozilla Video go. Luckily, Flickr photos contain GeoTags and an entire subsection of their API for Geo information.

    Here’s where I ran into an issue: not realizing two distinct APIs. While I didn’t need an API key for feeds, retrieving the latitude, longitude city and more for an image requires using the private API with a registered API key. After getting my API key, I was able to call the getLocation() method to retrieve location information. Another issue came up of not wanting to hardcode the API key into the JavaScript, but that was worked around by creating a PHP script to serve as a proxy, substituting my API key in for any requests I wished.

    With that done, I had all the information I needed to be rolling. With the video playing, I included two buttons: one to view the original picture source and one to find out “Where the Hell is Mozilla Guy?” The picture source was easy, all I did was another Flickr API call (this time to getInfo) to retrieve the user id and to then formulate a url. Flickr urls for a particular image follow the format:

    http://www.flickr.com/photos/{userID}/{photoID}/

    Displaying the location was a bit trickier but still quite doable. It took a call to the aforementioned Flickr getLocation() function to get the latitude and longitude, as well as information about the neighbourhood, county, city and country of the photo. Turns out, I got a lot of crashes on this part: even if a photo is geotagged, not all of this information is publicly shared.

    Once that was all hooked up, it was time to embellish a bit. Feature-wise, I mean. The final version looks a little rough, but encompasses everything mentioned here. Although it requires HTML 5 to work, those without see the action shot below

    A video superimposed on a night at Nuit Blanche 2010 in Toronto
    Where is He?

    So that’s that. What’s missing from this and how could it be taken further? Well, we’re dealing with public photo streams, some of which have all rights reserved. While the combo box eliminates this issue, the public feed still has potential to bring in photos with All Rights Reserved. Unfortunately, I didn’t have the time to investigate how to check for and eliminate this pictures from the stream. So please, stick to the pre-selected photographers 🙂

    Also, it may’ve been nice to slow down the image rotation rate and super-impose the locations right onto the video like they are in “Where the Hell is Matt” but there were two issues:

    1. I couldn’t find a video long enough that had green screen potential
    2. Geo-tagging has its own set of permissions on Flickr and most of the GeoTagged images that were retrieved had the given information limited to latitude and longitude.

    Be those as they may, this was a great experiment and I had a great time with it.

  • BBB Video Player Test Framework Skeleton

    Early on in the prototyping stage when I was first getting used to HTML5 and JSON, I’d written a very rough and primitive suite of tests to test what I was trying to do. In fact, if you look back to the earliest commits into my github repo, you’ll see it floating around here or there.

    While it may still be a little rough, I’ve spent a bit of time pushing it together into a structure to allow some level of testing automation with the BBB Video Player. It’s pretty much an array of functions, each running a test case and returning true/false but it does the job pretty well. In addition to return value, each test case may also alert from within to display specific messages. UI on the page still allows for manual testing. The test page can be found here.

    Interestingly the process of testing the framework already helped identify a bug in the BBB Player. The proof is in the pudding?

  • TTXT Subtitling for BBB Video Player

    In my last blogging I discussed the research I’d made into forcing XML-formatted plain text to being DOM-parsed. This became an essential task for the BBB Video Player as TTXT subtitle files are just that: XML-structured documents which were coming across as plain text. This could be fixed server-side by associating extension “ttxt” with “text/xml”, but given our work with Video.js I went for the client-side approach to ensure TTXT subtitling would always be possible and extended Video.js to ensure the data will be structured into an XML DOM tree client-side. I’ve posted a demo and my implementation code below:

    function XHRFormatter(request, type) {
      var canForce = request.overrideMimeType;
      var forceToXML = canForce && type === 'ttxt';
      var isXml = forceToXML || type === 'xml';
    
      if (forceToXML) {
        request.overrideMimeType('text/xml');
      }
    
      return {
        // Select elements from aRef element tree based on expression aExpr
        // aExpr is a query string (delimiter to split on for text, XPath for xml)
        select: function(aRef, aExpr) {
          if (isXml) {
            var xpe = aRef.ownerDocument || aRef;
     
            if (xpe.createNSResolver && xpe.evaluate) {
              // Thanks to https://developer.mozilla.org/en/Using_XPath
              var nsResolver = xpe.createNSResolver(xpe.documentElement);
              var result = xpe.evaluate(aExpr, aRef, nsResolver, 0, null);  
              var found = [];  
              var res;  
              while (res = result.iterateNext())  
                found.push(res);  
              return found;  
            } else if (xpe.selectNodes) { // IE
              return xpe.selectNodes(aExpr);
            }
          } else if (isText) {
            return aRef.split(aExpr);
          }
        },
     
        getType: function() { return type; },
     
        format: function(str) {
          if (isXml) { // Return str as xml
            // Mime type has been overridden as XML or is XML by default
            if (canForce || !forceToXML) {
              return request.responseXML;
            // IE, mime type not overridden, must parse into XML
            } else if (typeof ActiveXObject !== 'undefined') { 
              var doc = new ActiveXObject("MSXML.DomDocument");
              doc.loadXML(str);
              return doc;
            } else {
              throw new Error("Can not process as XML!");
            }
          } else if (isText) {
            return request.responseText;
          }
        }
      }
    }
    

    My goal was to decouple the (potentially browser-specific) code that formats and selects data from xml from the code that works with that data. In use, it could work like this:

    var request = new XmlHttpRequest();
    var formatter = XHRFormatter(request, 'ttxt');
    ...
    // Further work here
    ..
    request.send();
    var nodeTree = formatter.format(request.responseText);
    var wantedNodes = formatter.select(nodeTree, "//My/XPath/Query/");
    ...
    

    I’ve recently submitted a patch back to the Video.js team integrating this code into their player. Keep an eye out for their future releases, it may have official support for multiple subtitling formats 😉

  • Cross-browser XML Parsing with XmlHttpRequest

    Ah yes, cross-browser coding. Easier now than it was when I first dabbled in JS, but I still get a major sense of satisfaction out of getting something working and working well. For my work on TTXT subtitling, I had to dig deep into the XmlHttpRequest class, edge cases on return types and ended up trying to figure out a way to handle everything on every browser known to man (well, at least the six I can test on). And I think I did it. How did I get here?

    Working with an existing codebase I had some infrastructure to work with (and keep backwards-compatible so as not to break existing apps too) so it wasn’t remaking an entire wheel. Breaking wasn’t much of an issue though, their library has a great modular design so it’s fairly easy to add stuff in, I just wanted to do it as elegantly as possible.

    As TTXT is an XML document, I had to use the XmlHttpRequest.responseXML property. But right away this was an issue: TTXT doesn’t have a MIME type of XML, but the W3C spec says that responseXML returns null if this is the case. What to do… other than use the overrideMimeType function! This handy function will force the request to be parsed as valid XML so that the responseXML property will return a DOM object.

    But I was far from out of the woods yet. IE7 held Microsoft’s initial movement towards W3C-standard XmlHttpRequest, but the overrideMimeType function we need for this solution wasn’t implemented. So how to handle that? For that I had to look at the big picture.

    Assuming we get our data back as an XML document, how do we want to handle and manipulate it? Traditional DOM traversal could be used thanks to DOM Level 2’s document.getElementByTagName function, though this is a bit typing to code and can be a little slow on the execution. John Resig does point out that “Native XPath is blazingly fast” and while there is potential for browser misimplementations of CSS selectors, something as trivial as getting elements by tag name seems like a good choice to use XPath for. This though… this means getting into more mucky browser-specific (or should I say, object-specific) coding. While Firefox 3.5, Firefox 4 beta 8, Chrome 6, Chrome 7 beta, Safari 5 and Opera 10 all can be handled using document.evaluate the same way, IE (at least IE8 and below) requires the loading and calling of ActiveX Code.

    So in the end, the only hang up is the Mime type, but being able to only override it in some browsers means having to resort to parsing it into a DOM tree in others (all the while being sure that both ways are done in an XPath-compatible way). Everything works up to this point except for retrieving an XML response as an XML DOM tree in some IE browsers. Turns out, as far as I can tell, that it just can’t happen. Luckily there’s a way in IE to parse a string as XML.

    With all of these pieces together, it seems we have a bit of a mess of edge cases, what-if’s and work arounds. But not so:

    XML Parse Flowchart
    XML Parse Flowchart

    And just like that, a high-level shot at a cross-browser way to integrate XML parsing with XmlHttpRequest. In implementation this came together for me through a series of closures and one class variable to allow for backwards compatibility, but for other applications this could be done with a single function.

  • JavaScript: the nitty gritty

    This week, reviewing JavaScript was the idea and learning it inside and out was the intention. After watching Douglas Crockford’s video lectures on The JavaScript Programming Language (parts 1, 2, 3, and 4) and Advanced JavaScript (parts 1, 2, and 3) I felt like I’d been reacquainted with an old friend after years of falling out of touch. After watching them I kept asking myself: “Did I learn a lot?“.

    I found that while before I knew JavaScript like I knew a car seeing it drive around a parking lot, I knew it now like I’d been the one driving it. Iterating over object properties? Check. How that factors in with inheritance and using hasOwnProperty to eliminate super classes? Woah, never thought about that!

    Similarly, a lot of other things I held dear about good ol’ JS were blown out of the water. Expressions in switch statements, that ambiguously implemented VB-style “with” statement, and breaking to labels were all new to me.

    Some of the most interesting things I’d found were the traps and best practices of the language. I always knew parseInt would supply a radix if it wasn’t given one, but HOW it would was scary. Rather than default to 10 like I’d assumed, it tries to guess based on the string (“05” has radix 8, “0x05” has radix 16, “5” has radix 10). Good thing I never had supplied a string with a leading 0 or I’d’ve been in trouble.

    Variable declaration and scope was another great thing to learn. I knew of implied global and that there was only function scope, but I never realized the ramifications and power of this. Want to declare a variable or group of logic in a function but then use it outside the function? No problem. Want to do it without cluttering the global namespace? Easy still, just return a closure or anonymous function using that variable. Even though the called function has returned control, the location of returned closure/function declaration ties to the variable itself and it can be used.

    Closure usage and private function emulation has found its way into my code in the past, but I suspect it’ll be more and more prominent (especially when dealing with wrapper functions/objects for cross browser code!) in future projects. 🙂