Flex VideoDisplay just flat leaks

1k Views Asked by At

And actually I found the solution myself, but as I searched Adobe forums and here previously and found the problem presented repeatedly but never resolved, thought I'd answer my own question here for the benefit of future google searches of someone.

But anyway it leaks, and judging from previous commentors, in a whole myriad of scenarios. In my case its in SWFLoader within another SWFLoader, and when the parent SWFLoader goes away, the video stays in memory, and no combination of removeEventListeners or gc.collect or what have you in a RemovedFromStage handler will fix the problem. You can stop the video there, so it doesn't keep playing, but it still stays in memory, and another 10Mb or so added each time you run it.

And parenthetically, I'm just mystified how Adobe could let something like this stay unfixed incessantly like they have. There is obviously some eventlistener buried somewhere in their own code which is never released, but clearly they could care less. I'm assuming this sort of thing has to be at least one of the reasons that flash is being increasingly marginalized. Its also strange to me the number of flash developers that don't seem to appreciate the problem either, that think its not a problem until literally all the system memory is consumed and the browser crashes. Well,coming from conventional application development myself, its not acceptable to see in task manager the memory continuously bumped up every time the user hits a button and never released .

So originally I started looking for 3rd party flex video players and immediately ran across the Open Source Media Framework . And in their package they actually have numerous different methods and classes by which a video can be invoked. And I tried several of these (MediaPlayerSprite, MediaContainer, VideoElement, LightweightVideoElement, etc) but all of these leaked as well, and in in the same way as Flex's VideoDisplay! Evidently though, Flex VideoDisplay uses the OSMF code behind the scenes I think (maybe). So anyway, a whole other company that doesn't care about leaks - incredible, inexplicable.

2

There are 2 best solutions below

0
On

Just use the original flash.media.Video. You'll have to also create a NetStream seperately, a NetConnection,and also run your own timer if you want to have functionality like in VideoDisplay that automatically updates the play head time while running. (You need to do that and track load progress yourself with your own timer.) You also need to do some things in a removedFromStage handler to avoid leaks. That's really the crucial part, but to initialize everything, something like the following:

var uic:UIComponent = new UIComponent();          
var ns:NetStream;         
var v:Video = new Video();        
var nc:NetConnection = new NetConnection();      
var timer:Timer = new Timer(250);         

...

uic.addChild(v);    
this.addChild(uic);     
v.width=Number(parameters.w);   
v.height=Number(parameters.h);  

nc.connect(null);        
ns  = new NetStream(nc);        
ns.addEventListener("netStatus",play_end);  
uic.addEventListener("removedFromStage",v_remove);  

v.attachNetStream(ns);        

ns.play(session.source);        
ns.pause();         

timer.addEventListener("timer",load_handlr);        
timer.start();          

And in the removedFromStage handler:

private function v_remove(e:Event) {      

  ns.close();      
  nc.close();   

  v.attachNetStream(null);  

  timer.stop()      
}

That's it. So, interestingly, none of the eventlisteners I created had to be removed, just that one timer had to be stopped. And also the call to nc.close, etc. (Not sure actually if the v.attachNetStream(null); is strictly necessary). VideoDisplay has its own close() method, but I had tried it and no effect on the leak in VideoDisplay.

So the above stops the video and prevents the leak. In my case I want the video to keep playing until the end though, and for that I did have to remove the other event listeners, so it wouldn't keep restarting in a loop (and the memory not released for that reason), and then take out the call to ns.close so it will play to the end:

private function v_remove(e:Event) {

  nc.close();

  v.attachNetStream(null);

  timer.stop()
  timer.removeEventListener("timer",timer_handlr);
  ns.removeEventListener("netStatus",play_end);
  uic.removeEventListener("removedFromStage",v_remove);

}

So just some useful arcane alchemy for anyone still doing flash development I guess. Why Adobe could not provide some general purpose method to completely nuke an arbitrary object at your own risk I guess we'll never know.

1
On

Not sure if this will help you but I've had success unloading the video (in Flash, not Flex) when using the video component. It doesn't empty out the video (and leaks) unless you do this this (videoPlayer is my Component instance)...

         try{

            for each(var v: VideoPlayer in videoPlayer.flvplayback_internal::videoPlayers){
                log("Cleaning up VideoPlayer:" + v);
                v.close();
                v.clear();
            }


        }catch(e:Error){
            log("EndVideo Failed: " + e);
        }