Nasty FLV preloading issue

Came across a nasty bug with NetConnection and NetStream. 3 full hours wasted.. damn...

Flash is, by far, the best way to deliver video on the web. The wide availability of the plugin makes it a no brainer.

I always used progressive download video, meaning video that's read from a vanilla http connection, no special streaming server on the backend. I'd love to hear the stats, but my guess is that the majority of flash video is delivered this way. The huge video sites, youtube, google video and yahoo videos all use flash with progressive download. But the API for showing video content is highly skewed towards using Flash Media Server. Sure Adobe(then macromedia) expects to make a buck on that, but still it's pretty odd that the most common use case is so cumbersome to code.

With the great architectural changes I was really chocked to learn the the NetStream remained mostly unchanged. It's awkward to use. It's full of small confusing details and the documentation could be so much better. I sure am not the only one to feel this way. Traces from the youtube player, from the nytimes player make that clear.

So we hacked a sane VideoStream class for AS2 and I wanted to port it to AS3. The idea was to have a class that could do something like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var vs : VideoStream = new VideoStream(url, buffertime);
// video loops once the end of the stream is reached
vs.loops = true ; 
// listen to complete loading events
vs.addEventListener(Event.COMPLETE, onVideoLoaded); 
// listen to loading progres events
vs.addEventListener(Event.PROGRESS, onLoadingProgress);
vs.addEventListener("playComplete", onPlayFinished);
  
// and then later:
// the video duration:
trace(vs.duration)
// and so on
In order to start a NetStream, you must instantiate it with a NetConnection object. it's ugly. You have to say:
1
2
3
nc = new NetConnection();
nc.connect(null);
stream = new NetStream(nc);

Why on earth you can't say simply stream = new NetStream(); and, with no parameters for the NetConnection, it would do it for you? Since the NetConnection object doesn't do anything, I coded this class differently. Instead of keeping the NetConnection as a class property, I simply created a local variable and used that to instantiate the NetStream. But then something funny would happen. For a while the NetStream.bytesLoaded and NetStream.bytesTotal would behave as expected, at first it would be zero, until the the response would return the content length and then it would show the right bytes total and bytes loaded for a few executions, and THEN it would read 0 for both. That's right, after a few milliseconds the bytesTotal would go from 28428 to 0. That combined with a miss configured apache omitting the content length, and it took us hours to chase this bug. Worse it wasn't very predictable: sometimes loading information would read correctly all the way trough.

Googling around, I came across this thread. The post is 3 years old, for flash MX , but it's the same issue. They found the workaround but didn't understand why. Here's what I think happens. When you create a new NetConnection and the NetStream object everything is fine. But if the NetConnection is a local variable inside a function it will be marked for garbage collection by the VM. At some point the gc kicks in and clears the NetConnection object, since it is a local variable. When that happens, the NetStream goes cuckoo and reads dummy values for bytesLoaded. Because you don't know when the gc will do it's thing, it is unpredictable, intermittent. If the gc is idle until you finished your preloading code, it works. The strangest part is that even if the gc clears the NetConnection object and the loading information goes berseck, you can still use the NetStream. It's there. It's readable and all, but the loading information becomes useless. The fix is easy. Just make sure you keep a reference to the NetConnection object, as a class property, anywhere the gc won't clean it up.

getting a third opinion

posted by
Arthur Debert

on

Tagged with:

3 comments so far.
Say something

Other months availabe in 2007

The complete blog archive

The latest entries

Subscribe to comments on this entry: rss feed

Cloud me:
  • Saurabh in Loading Reloaded on

    Brilliant brilliant class. Takes the preloader pain away. Thanks Arthur.

    For anyone else struggling with the infamous null Object errors when loading swfs via Bulkloader, here's something basic you could ...

  • Fernando in Loading Reloaded on

    Hi, Arthur!

    I just want to let you know that I added Bulk Loader to my site called AS3GameGears (http://www.as3gamegears.com/).

    I am using it on one of our projects. ...

  • Nitin Sharma in Loading Reloaded on

    Hi Junio Vitorino, I am facing the same problem. Can you please tell me, how did you solve this.

    1046: Type was not found or was not a compile-time constant: ...

  • slopps in AS3 Sad bits #1: Deep copying or cloning on

    Wow...good info. I cannot fathom how this was left out of AS3...so frustrating.

    To be clear, if a custom class extends MovieClip (or any DisplayObject) and you attempt to clone ...

  • Elmar Nieser in Maxhaus on

    Thanks for all the information!

    I wanted to show my Isometric Engine wich works pretty ok now thanks to all this info :)

    www.uber.nl <-- its just the engine so ...

Feeds: Entries rss feed Linksrss feed Worksrss feed

A Django joint. hosted on Slicehost