mp4parser
mp4parser copied to clipboard
OutOfMemoryError when building Movie
After upgrading from 1.1.7 to later versions, OutOfMemoryError happens on MovieCreator.build() I think it's related with removing deferred mapping.
Log from 1.1.14
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 788249407 byte allocation with 16769200 free bytes and 477MB until OOM
at java.nio.ByteBuffer.allocate(ByteBuffer.java:56)
at com.googlecode.mp4parser.AbstractBox.parse(AbstractBox.java:110)
at com.coremedia.iso.AbstractBoxParser.parseBox(AbstractBoxParser.java:107)
at com.googlecode.mp4parser.BasicContainer.next(BasicContainer.java:185)
at com.googlecode.mp4parser.BasicContainer.hasNext(BasicContainer.java:161)
at com.googlecode.mp4parser.util.LazyList.blowup(LazyList.java:30)
at com.googlecode.mp4parser.util.LazyList.size(LazyList.java:77)
at com.googlecode.mp4parser.BasicContainer.getBoxes(BasicContainer.java:80)
at com.googlecode.mp4parser.authoring.samples.DefaultMp4SampleList.<init>(DefaultMp4SampleList.java:36)
at com.coremedia.iso.boxes.mdat.SampleList.<init>(SampleList.java:33)
at com.googlecode.mp4parser.authoring.Mp4TrackImpl.<init>(Mp4TrackImpl.java:62)
at com.googlecode.mp4parser.authoring.container.mp4.MovieCreator.build(MovieCreator.java:57)
at com.googlecode.mp4parser.authoring.container.mp4.MovieCreator.build(MovieCreator.java:38)
Here is the Video with problem Video is made from android, and I'm not familiar with MP4 format, but seems like box header? is not correct, but it work well with 1.1.7 Thank you.
Hi, I guess you are also running on Android, right? try a different MovieCreator.create() call. I guess at the moment you are using MovieCreator.create(File) or MovieCreator.create(new FileDatasourceImpl("filename")). Please try the FileDataSourceViaHeapImpl implementation - at does not use virtual memory and might help
Best Regards, Sebastian
// tldr; The android operating system is 64 bits and therefore you have more or less unlimited (at least for practical purposes I consider 2^63 bytes unlimited) virtual memory at your disposal. The dalvik VM is only 32 bits and its address space is at max 2GB. This memory is typically fragmented a few KB allocated here, a few kilo or megabytes there. At some point - even though in theory there is still mem available - you can no longer allocate lets say 64MB in one pieve and that's when you run OOM.
2015-11-12 9:30 GMT+01:00 adreamer [email protected]:
After upgrading from 1.1.7 to later versions, OutOfMemoryError happens on MovieCreator.build() I think it's related with removing deferred mapping.
Log from 1.1.14
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 788249407 byte allocation with 16769200 free bytes and 477MB until OOM at java.nio.ByteBuffer.allocate(ByteBuffer.java:56) at com.googlecode.mp4parser.AbstractBox.parse(AbstractBox.java:110) at com.coremedia.iso.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at com.googlecode.mp4parser.BasicContainer.next(BasicContainer.java:185) at com.googlecode.mp4parser.BasicContainer.hasNext(BasicContainer.java:161) at com.googlecode.mp4parser.util.LazyList.blowup(LazyList.java:30) at com.googlecode.mp4parser.util.LazyList.size(LazyList.java:77) at com.googlecode.mp4parser.BasicContainer.getBoxes(BasicContainer.java:80) at com.googlecode.mp4parser.authoring.samples.DefaultMp4SampleList.
(DefaultMp4SampleList.java:36) at com.coremedia.iso.boxes.mdat.SampleList. (SampleList.java:33) at com.googlecode.mp4parser.authoring.Mp4TrackImpl. (Mp4TrackImpl.java:62) at com.googlecode.mp4parser.authoring.container.mp4.MovieCreator.build(MovieCreator.java:57) at com.googlecode.mp4parser.authoring.container.mp4.MovieCreator.build(MovieCreator.java:38) Here is the Video with problem https://drive.google.com/file/d/0B7G2iubXOjUEVndFZTU2YmVLcGc/view?usp=sharing Video is made from android, and I'm not familiar with MP4 format, but seems like box header? is not correct, but it work well with 1.1.7 Thank you.
— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/139.
ignore my answer for the moment. I'll check the vid.
2015-11-12 11:31 GMT+01:00 Sebastian Annies [email protected]:
Hi, I guess you are also running on Android, right? try a different MovieCreator.create() call. I guess at the moment you are using MovieCreator.create(File) or MovieCreator.create(new FileDatasourceImpl("filename")). Please try the FileDataSourceViaHeapImpl implementation - at does not use virtual memory and might help
Best Regards, Sebastian
// tldr; The android operating system is 64 bits and therefore you have more or less unlimited (at least for practical purposes I consider 2^63 bytes unlimited) virtual memory at your disposal. The dalvik VM is only 32 bits and its address space is at max 2GB. This memory is typically fragmented a few KB allocated here, a few kilo or megabytes there. At some point - even though in theory there is still mem available - you can no longer allocate lets say 64MB in one pieve and that's when you run OOM.
2015-11-12 9:30 GMT+01:00 adreamer [email protected]:
After upgrading from 1.1.7 to later versions, OutOfMemoryError happens on MovieCreator.build() I think it's related with removing deferred mapping.
Log from 1.1.14
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 788249407 byte allocation with 16769200 free bytes and 477MB until OOM at java.nio.ByteBuffer.allocate(ByteBuffer.java:56) at com.googlecode.mp4parser.AbstractBox.parse(AbstractBox.java:110) at com.coremedia.iso.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at com.googlecode.mp4parser.BasicContainer.next(BasicContainer.java:185) at com.googlecode.mp4parser.BasicContainer.hasNext(BasicContainer.java:161) at com.googlecode.mp4parser.util.LazyList.blowup(LazyList.java:30) at com.googlecode.mp4parser.util.LazyList.size(LazyList.java:77) at com.googlecode.mp4parser.BasicContainer.getBoxes(BasicContainer.java:80) at com.googlecode.mp4parser.authoring.samples.DefaultMp4SampleList.
(DefaultMp4SampleList.java:36) at com.coremedia.iso.boxes.mdat.SampleList. (SampleList.java:33) at com.googlecode.mp4parser.authoring.Mp4TrackImpl. (Mp4TrackImpl.java:62) at com.googlecode.mp4parser.authoring.container.mp4.MovieCreator.build(MovieCreator.java:57) at com.googlecode.mp4parser.authoring.container.mp4.MovieCreator.build(MovieCreator.java:38) Here is the Video with problem https://drive.google.com/file/d/0B7G2iubXOjUEVndFZTU2YmVLcGc/view?usp=sharing Video is made from android, and I'm not familiar with MP4 format, but seems like box header? is not correct, but it work well with 1.1.7 Thank you.
— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/139.
I got the same error when run this code: MovieBox moov = isoFile.getBoxes(MovieBox.class).get(0); mMoovSize = moov.getSize();
I met this issue when I try running on Android. And I found out that when in android, there will be a UnknownBox at last, and causing wrong content size to be pass to ByteBuffer Allocate, I bypass this logic. And met a stsc box entries zero problem. I upload my whole test project to Github, please have a look.
https://github.com/pepsin/VideoTest
The mp4 file seems irrelevant, I tried FFMPEG generated mp4 on mac, also tried android directly shooted mp4, all have the same problem. I will try running mp4parser on desktop to see if it is platform problem.
My bypass code are at those place:
//PropertyBoxParserImpl.java line 99-101
if (UnknownBox.class.equals(clazz)) {
return null;
}
//BasicContainer.java line 111-116
if (b != null) {
boxes.add(b);
contentProcessed += b.getSize();
} else {
break;
}
//AbstractBoxParser.java line 110-115
if (parsableBox != null) {
parsableBox.parse(byteChannel, header.get(), contentSize, this);
return parsableBox;
} else {
return null;
}
Hi, thanks for the demo project. Most people don't take the time and allow me to quickly reproduce the problem. I don't have the time to look at it today but one the first glance I was not able to see the aspectJ compilation step in your gradle build. Would you please try to use a pre compiled version from maven central?
Beste Grüße, Sebastian
2016-02-05 4:17 GMT+02:00 pepsin [email protected]:
I met this issue when I try running on Android. And I found out that when in android, there will be a UnknownBox at last, and causing wrong content size to be pass to ByteBuffer Allocate, I bypass this logic. And met a stsc box entries zero problem. I upload my whole test project to Github, please have a look.
https://github.com/pepsin/VideoTest
— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/139#issuecomment-180160291.
https://github.com/pepsin/VideoTest/tree/master/isoparser/libs https://github.com/pepsin/VideoTest/blob/master/isoparser/build.gradle
It's build by default include, and the aspectJ is grab from maven
I have the same issue on android with version 1.1.18. Tested with 1.1.7 works fine.
I'll try to do something about it today. Haven't yet found the time. Am 17.02.2016 5:17 vorm. schrieb "Michael Ding" [email protected]:
I have the same issue on android.
— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/139#issuecomment-184994499.
did anyone got the workaround?
To be honest: I stopped working on it when I was unable to reproduce it.
2016-03-09 13:15 GMT+02:00 AbhishekPantUK [email protected]:
Is anyone got the workaround?
— Reply to this email directly or view it on GitHub https://github.com/sannies/mp4parser/issues/139#issuecomment-194246180.
Same issue here, on android, using last version available for gradle, at line: MovieBox moov = isoFile.getBoxes(MovieBox.class).get(0);
Fatal Exception: java.lang.OutOfMemoryError at java.nio.ByteBuffer.allocate(ByteBuffer.java:56) at com.googlecode.mp4parser.AbstractBox.parse(AbstractBox.java:110) at com.coremedia.iso.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at com.googlecode.mp4parser.BasicContainer.next(BasicContainer.java:185) at com.googlecode.mp4parser.BasicContainer.hasNext(BasicContainer.java:161) at com.googlecode.mp4parser.util.LazyList.blowup(LazyList.java:30) at com.googlecode.mp4parser.util.LazyList.size(LazyList.java:77) at com.googlecode.mp4parser.BasicContainer.getBoxes(BasicContainer.java:80) at com.wevideo.mobile.android.util.MediaUtil.getOrientationMatrix(MediaUtil.java:291) It happens to quite a few users, and seems that it is 100% reproducible. I don't have the videos used to reproduce it. Is it similar to #151?
For some cases, the requested memory size is specified, and seems huge:
Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 895140620 byte allocation with 16777216 free bytes and 159MB until OOM at java.nio.ByteBuffer.allocate(ByteBuffer.java:56) at com.googlecode.mp4parser.AbstractBox.parse(AbstractBox.java:110) at com.coremedia.iso.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at com.googlecode.mp4parser.BasicContainer.next(BasicContainer.java:185) at com.googlecode.mp4parser.BasicContainer.hasNext(BasicContainer.java:161) at com.googlecode.mp4parser.util.LazyList.blowup(LazyList.java:30) at com.googlecode.mp4parser.util.LazyList.size(LazyList.java:77) at com.googlecode.mp4parser.BasicContainer.getBoxes(BasicContainer.java:80) at com.wevideo.mobile.android.util.MediaUtil.getOrientationMatrix(MediaUtil.java:291)
Even noticed requests for 2GB allocations.
I can replicate with the video from the OP on Samsung S3 and probably happens on other devices too, maybe all.
It seems that the following line was changed in AbstractBox.parse
:
this.content = ChannelHelper.readFully(readableByteChannel, contentSize);
to
content = ByteBuffer.allocate(l2i(contentSize));
Second one is causing trouble.
Please ignore the comment above. Anyway, reverting the AbstractBox file to the variant present in version 1.1.1 solves the issue. Can you please investigate?
I'm seeing this with 1.9.27. I've been using this mp4parser project for over a year with no issue until upgrading to the new version.
Here's one fork with a branch that fixes it on top of release 1.1.18, in case anyone needs it: https://github.com/bogru/mp4parser/tree/mp4parser-project-1.1.18-FixIssue139-OOM.
Thanks, bogru. Your changes to AbstractBox did the trick for me. Sannies, I'm having this problem using 1.1.18 on Mac OS. Happy to provide a sample file and sample code.
Just adding a me too to this. Having the same problem using 1.9.27 on Mac OS El Capitan.
I also have the same issue using 1.9.27 on Android 6.0.1. On Android 5.0 or 5.1 is everything ok, only on 6.0 I see the issue. Did anyone resolve it?
11 17:28:47.412 12924-12924/b.m.videoblog E/AndroidRuntime: FATAL EXCEPTION: main Process: b.m.videoblog, PID: 12924 java.lang.OutOfMemoryError: Failed to allocate a 1751411837 byte allocation with 14685664 free bytes and 170MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at java.nio.MemoryBlock.allocate(MemoryBlock.java:131) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:73) at org.mp4parser.support.AbstractBox.parse(AbstractBox.java:95) at org.mp4parser.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at org.mp4parser.BasicContainer.initContainer(BasicContainer.java:107) at org.mp4parser.boxes.iso14496.part12.MetaBox.parse(MetaBox.java:82) at org.mp4parser.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at org.mp4parser.BasicContainer.initContainer(BasicContainer.java:107) at org.mp4parser.support.AbstractContainerBox.parse(AbstractContainerBox.java:75) at org.mp4parser.AbstractBoxParser.parseBox(AbstractBoxParser.java:107) at org.mp4parser.BasicContainer.initContainer(BasicContainer.java:107) at org.mp4parser.IsoFile.<init>(IsoFile.java:55) at org.mp4parser.IsoFile.<init>(IsoFile.java:50) at org.mp4parser.muxer.container.mp4.MovieCreator.build(MovieCreator.java:54) at b.m.videoblog.maker.VideoFile.mergeVideo(VideoFile.java:159) at b.m.videoblog.maker.Maker.mergeFile(Maker.java:448) at b.m.videoblog.maker.Maker.setupPlayer(Maker.java:148) at b.m.videoblog.maker.States.MakerPlayerState.initialize(MakerPlayerState.java:20) at b.m.videoblog.maker.Maker.onSurfaceTextureAvailable(Maker.java:324) at android.view.TextureView.getHardwareLayer(TextureView.java:368) at android.view.View.updateDisplayListIfDirty(View.java:15244) at android.view.View.draw(View.java:16040) at android.view.ViewGroup.drawChild(ViewGroup.java:3610) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3400) at android.view.View.updateDisplayListIfDirty(View.java:15262) at android.view.View.draw(View.java:16040) at android.view.ViewGroup.drawChild(ViewGroup.java:3610) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3400) at android.view.View.updateDisplayListIfDirty(View.java:15262) at android.view.View.draw(View.java:16040) at android.view.ViewGroup.drawChild(ViewGroup.java:3610) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3400) at android.view.View.updateDisplayListIfDirty(View.java:15262) at android.view.View.draw(View.java:16040) at android.view.ViewGroup.drawChild(ViewGroup.java:3610) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3400) at android.view.View.updateDisplayListIfDirty(View.java:15262) at android.view.View.draw(View.java:16040) at android.view.ViewGroup.drawChild(ViewGroup.java:3610) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3400) at android.view.View.updateDisplayListIfDirty(View.java:15262) at android.view.View.draw(View.java:16040) at android.view.ViewGroup.drawChild(ViewGroup.java:3610) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3400) at android.view.View.draw(View.java:16273) at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2697) at android.view.View.updateDisplayListIfDirty(View.java:15267) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322) at android.view.ViewRootImpl.draw(ViewRootImpl.java:2619) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2438) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2071) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1111) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6017) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) at android.view.Choreographer.doCallbacks(Choreographer.java:670) at android.view.Choreographer.doFrame(Choreographer.java:606) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844) at android.os.Handler.handleCallback(Handler.java:
Attention everyone~: I just encountered this problem! It is so weird that mp4parser will allocate so much memory which the .mp4 file really do not need. After lots of tests, I notice that my own problem is origin from the .mp4 file itself! My file is created by myself on Android, I record the video to an .mp4 file by overriding an old file which name is the same as my new file. In this situation, maybe google code treat the file as usual then bug appears. So maybe the file is a bad one I think. My final solution is delete the old file before creating an new file, and in this case, the bug disappeared...
I meet the sample problem on android 5.1 os, the mp4parser version is 1.9.27. the exception stack is:
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 745463976 byte allocation
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at java.nio.MemoryBlock.allocate(MemoryBlock.java:131)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:73)
at org.mp4parser.support.AbstractBox.parse(AbstractBox.java:95)
at org.mp4parser.AbstractBoxParser.parseBox(AbstractBoxParser.java:107)
at org.mp4parser.BasicContainer.initContainer(BasicContainer.java:107)
at org.mp4parser.IsoFile.<init>(IsoFile.java:55)
at org.mp4parser.IsoFile.<init>(IsoFile.java:50)
at org.mp4parser.muxer.container.mp4.MovieCreator.build(MovieCreator.java:54)
at org.mp4parser.muxer.container.mp4.MovieCreator.build(MovieCreator.java:39)
at cn.ieclipse.af.demo.video.VideoUtil.parse(VideoUtil.java:70)
the deepest invoking of mp4parser is
@DoNotParseDetail
public void parse(ReadableByteChannel dataSource, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
content = ByteBuffer.allocateDirect(l2i(contentSize)); // AbstractBox.java:95
the video content length is only 465K. I tried another smaller mp4 (113K), the is no problem. So this issue associated with the video content lenghth?
Another test on PC. I debug it on Win7 64bit os and jdk 1.8. Found that when parsing the next box of "moov" of top container. the oom occurred. The file length is 912247, and the end of 'moov' is 912062, and next AbstractBoxParser#parse the size read is 1351044190 (wrong: exceed the file length, on Android OOM occured, but pc parsed to an UnknownBox ).
Test mp4 bellow, please rename .mp4.txt to .mp4
I know it has been 2 years, but have you ever solved this @adreamer? Has anyone else solved this? I'm having the same issue using mp4parser 1.9.27. I cannot share my source code, but I'm experiencing this error when I run this line with MovieCreator.build:
Movie movie = MovieCreator.build("/storage/emulated/0/DCIM/Camera/20170527_035751.mp4");
The result is this error:
java.lang.OutOfMemoryError: Failed to allocate a 1751411837 byte allocation with 16776608 free bytes and 360MB until OOM
Any help would be appreciated.
I ran into this last year. It's extremely frustrating and it seems very obvious what the problem is - the code simply tries to create an enormous buffer. Please look at bogru's comments above. He tracked down the precise commit where it was introduced. I used some of the code he posted here https://github.com/sannies/mp4parser/issues/205 to work around the problem. I have a hard time understanding why sannies is unable to reproduce this. I offered to provide a sample (the account brooksrbrown above), but he did not respond. I wish that he would take a good look at this problem. It is entirely fixable.
Can you give us a hand @sannies?
My workaround is to inject a version of AbstractBox.class into the library using the project. In my case, this is tika-app-1.13.jar. This only works on the 1.x branch of mp4parser, and as a result, I am in danger of getting stuck on this version of tika. I need to resolve this problem with mp4parser in what is otherwise a very useful library. I am happy to share source, but it would be much better to get this resolved in the master branch.
I have created a pull request that should fix "java.lang.OutOfMemoryError: Failed to allocate a 1751411832". It fixes parsing of MetaBox.
I did a workaround for the OutOfMemoryError, based on mp4parser 1.9.41: https://github.com/talklittle/mp4parser/commit/3f177d81bc5b637c93541d323f96f85907f9b20f#diff-e483fffed200eca459dc4f38d3969e48
It works on test file from https://github.com/sannies/mp4parser/issues/377#issuecomment-505616604 as well as in production Android app without reported issues so far.
The big hints were the comments saying that the broken header can parse to an UnknownBox with enough RAM, and importantly the bad header and UnknownBox tend to appear at the very end, last few hundred bytes of the video file.
The workaround ignores the bad memory size and forces the box to parse and add to the end of the Movie.
I'm hesitant to do a pull request because it may cause problems with potential UnknownBox found earlier in the source file. That said, I am not aware of any current video format hitting this problem.
@talklittle How did you manage to get the patched code working on your project? Any chance I can reference your fork from Gradle?
How did you manage to get the patched code working on your project? Any chance I can reference your fork from Gradle?
You can clone the Git repo, and install to your machine's local Maven repository using the "install" Maven task in the mp4parser project.
Then in your application's Gradle file:
repositories {
mavenLocal() {
content {
includeGroup 'org.mp4parser'
}
}
}
dependencies {
implementation 'org.mp4parser:muxer:1.9.41.talklittle1'
}