Jump to content
Search Community

VideoLoader + H.264 Memory Problems

famicomboy test
Moderator Tag

Recommended Posts

I've got an application that currently loads 30 or so small .flv files at the beginning of the application. They all average 215k each. The video files are interactivity transitions, rather than a video in a player with controls. This is why I want to load them all at runtime, in order to preserve the user experience and not break continuity by having to wait for videos to start buffering when you click on a button that would activate a video.

 

I previously used Bulkloader to manage my loading in the application, but decided to move the project over to loadermax. Using Bulkloader, I would load all the videos, which probably took a total of 25mb of memory in the player. That part was fine. However, I noticed that when I actually pulled the netstream out of the bulkloader instance and attached it to the Video instance, that is when it would decode it, which in turn would extract all that video data into the memory, and probably added 4mb to the total memory used, and would compound on every single playthrough of any single video until I called Netstream.close(). So what I had to do was play the video once, and close the netstream when it was done playing, and when it needed the video again, I would have to tell bulkloader to load it again. This wasn't a huge deal but obviously not ideal. So this all relates to LoaderMax in that loadermax seems to automatically do Video.attachNetStream() automatically in the onComplete handler, or sometime soon after. So what's happening is that I compile my application, it loads all the initial xml, css, etc. ok, but then it starts the video load and the memory used skyrockets until it hits around 1.5 gb and crashes the player.

 

tl:dr : Is there a way to disallow the netstream to be attached to a video object to avoid these memory issues? If not, is there any other fix or issue regarding the NetStream class that I'm not understanding correctly that would help me achieve the user experience?

Link to comment
Share on other sites

Fair point. Thanks for bringing that up. Would you mind testing the attached [revised] version of VideoLoader? It only attaches the NetStream to the Video object if/when it is placed into the display list. It should be pretty transparent to you - everything is handled internally but your memory usage should be positively affected.

Link to comment
Share on other sites

So I've done some pretty rigorous testing, and I realize that I'm still having a crash issue. I can't get Loadermax to truly release the netstream from memory after it's been played. Before, all I had to do was Video.clear() and NetStream.close() and it went away just fine, but it's not working here. Memory just compounds until I play too many videos until it crashes. GC is running, however it does run a lot less frequently than I expect. It also does not clear the netstream from memory as well so that means there is some reference not being nulled out or reset.

 

So when I go to play the video, this is the code I use:

 

clipLayer.addChild(model.loader.getLoader(data.id).content);
clipLayer.x = -clipLayer.width / 2;
clipLayer.y = -clipLayer.height / 2;
model.loader.getLoader(data.id).gotoVideoTime(0);
model.loader.getLoader(data.id).playVideo();
VideoLoader(model.loader.getLoader(data.id)).netStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus, false, 0, true);

 

I do model.loader.getLoader().content to avoid making unnecessary references to the ContentDisplay.

Then, when the clip is finished playing: (unrelated code removed)

 

private function onNetStatus(e:NetStatusEvent):void {
switch (e.info.code) {
	case "NetStream.Play.Stop":
		trace('VideoClip.NetStream.Play.Stop');
		clipCleanup();
		break;		
}
}

private function clipCleanup():void {
VideoLoader(model.loader.getLoader(currentVideoData.id)).netStream.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);	
VideoLoader(model.loader.getLoader(currentVideoData.id)).rawContent.clear(); //clear the Video object as this was what I did before
VideoLoader(model.loader.getLoader(currentVideoData.id)).netStream.close(); //close the netstream

model.reloadNetStream(currentVideoData);
removeAllChildren(clipLayer);
clipLayer = new Sprite();
addChild(clipLayer);
}

 

And then this is in my data model, where the loader instance is stored:

 

public function reloadNetStream(d:VideoData):void { 
//VideoData is a custom object that is used to contain basic video properties like url, id, and netstream. 
//Netstream isn't being defined anymore in VideoData to remove unnecessary references
if (loader.getLoader(d.id)) {
	VideoLoader(loader.getLoader(d.id)).unload();
	VideoLoader(loader.getLoader(d.id)).load(true);
} else {
	trace("Video ID: '" + d.id + "' doesn't exist!");
}
}

 

Since I'm not really understanding how unload() and load(true); works, I can't be sure that it's truly removing all references to the netstream. Any thoughts?

Link to comment
Share on other sites

So I decided to test my claims, and sure enough, there's something about the way VideoLoader handles the netstream that doesn't null it out properly. I went through my code and decided to handle the netstream directly by calling VideoLoader.rawContent.clear() and then passing the netstream directly into my videoclip Sprite class, and handling all the Video and Netstream stuff myself. This fixed the issue for me so it's what I have to use for this project. However, you might do some good to really test out the memory issues in the VideoLoader class.

Link to comment
Share on other sites

You never disposed your VideoLoader, so it will keep a reference of the NetStream so that it can use it again when load() is called. If you want to completely destroy a VideoLoader, just call dispose(true). I ran a bunch of tests and as far as I can tell, gc runs properly and cleans up what it should. However, it cannot be predicted exactly when gc will run - that's totally up to the Flash Player. The System.gc() thing is only for the debugger.

 

I tweaked a few more things to make it even more bullet-proof, so would you mind trying the attached version of VideoLoader and letting me know if it works well for you?

Link to comment
Share on other sites

I see. I thought VideoLoader.unload() would remove the netstream. So basically I have to use dispose() and then just append a new VideoLoader instance to load it again, right? There's no way to just re-use the same VideoLoader instance?

Link to comment
Share on other sites

Yeah, due to bugs/inconsistencies in Adobe's NetStream class, it can cause gc problems to reuse the same NetStream in certain scenarios. So VideoLoader protects you from that hassle by automatically re-generating a new NetStream when necessary (like after canceling or unloading). But I don't see any problem with reusing a VideoLoader instance to load the same URL multiple times.

 

And yes, to answer your question, you could just dispose(true) the VideoLoader and recreate another instance each time you need to load a file again.

Link to comment
Share on other sites

Hi, I do have a problem that might be related.

 

I built an Application which preloads 15 f4v movies (FULL HD, 165MB for all of them) which can be played back over a simple interface.

Works like a dream on MAC (where I initially developed it). Your Framework is really nice work and was good to develop with..

 

Unfortunately, PC is my target platform. When I test it in Flash CS5.5 on PC, the preloader starts and finishes up to 98%, then the app crashes.

I looked further and found that it would crash after exactly 10 movies preloaded, independent from size or specific file (preloading 10 times the same small movie will return similar results). I donwnloaded your updated videoloader and it would crash a tad bit later :-/.

 

When I preload only 10 movies, the application runs, but very unstable and will crash eventually.

 

I'm completely puzzled what the reason for this is.

Shouldn't be RAM as there is plenty and the App isn't going past 450 MB.

 

I'm working on Win 7, Core I7, 24 GB RAM, Adobe Air 2.7 installed. (same result on AIR 2.6 though).

The worst thing is that I have to install this at a trade show on Sunday! HELP! :-/

 

Any Hints?

Thanks,

-martin

Link to comment
Share on other sites

hi klu,

 

I don't have an answer for you, but perhaps more info will help someone diagnos your problem.

 

 

is this app loading the videos off a local drive? if so, is it necessary to preload them all? wouldn't they play virtually instantaneously upon request? in which case you could just load and unload them as needed?

 

have you tested on another pc to rule out hardware issues? it seems that your pc is pretty beefy, but h.264 can be pretty demanding on the cpu/gpu. are you enabling hardware acceleration if available? have you googled about issues relating to your specific video card?

 

have you experimented with different encoding settings/formats?

 

My gut feeling is that LoaderMax isn't doing anything to cause problems or can do much to fix the issue, but hopefully someone can help get you closer to a fix.

Link to comment
Share on other sites

It's not a hardware issue, tested different machines.

It seems that there is an maximum Number of 10 Movies that can be added to the stage on Windows.

I used this many seperate movies as it is easier to manage in case of changes.

They were all instantiated and invisible on the stage to avoid the short flash I get on .addChild().

 

I now rendered all movies together and am working with cue points and it works fine.

 

Thanks again, I guess it all would have been a lot more hassle without videoLoader.

 

Best,

-martin

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...