FastAndroidCamera
FastAndroidCamera copied to clipboard
Out Of Memory Exception
Using xamarin forms, I've implemented a custom renderer to show a camera preview in a tabbed page (snapchat like). When moving away from the page and back (a few times) I get a out of memory exception.
When the page is appearing the following gets called:
try
{
Console.WriteLine("OPENING");
var watch = System.Diagnostics.Stopwatch.StartNew();
camera = Camera.Open(0);
camera.SetDisplayOrientation(90);
var parameters = camera.GetParameters();
var bitsPerPixel = Android.Graphics.ImageFormat.GetBitsPerPixel(parameters.PreviewFormat);
int bufferSize = (parameters.PreviewSize.Width * parameters.PreviewSize.Height * bitsPerPixel) / 8;
for (uint i = 0; i < 4; ++i)
{
using (FastJavaByteArray buffer = new FastJavaByteArray(bufferSize))
{
// allocate new Java byte arrays for Android to use for preview frames
camera.AddCallbackBuffer(new FastJavaByteArray(bufferSize));
}
// The using block automatically calls Dispose() on the buffer, which is safe
// because it does not automaticaly destroy the Java byte array. It only releases
// our JNI reference to that array; the Android Camera (in Java land) still
// has its own reference to the array.
}
watch.Stop();
System.Diagnostics.Debug.WriteLine("Opening camera: {0}ms", watch.ElapsedMilliseconds);
}
When the page dissappears:
if(camera != null) {
camera.SetPreviewDisplay(null);
camera.StopPreview();
camera.SetNonMarshalingPreviewCallback(null);
camera.Release();
camera.Dispose();
camera = null;
}
The previewCallback:
public void OnPreviewFrame(IntPtr data, Camera camera)
{
using(FastJavaByteArray buff = new FastJavaByteArray(data))
{
camera.AddCallbackBuffer(buff);
}
}
Logs:
[art] Starting a blocking GC Alloc
[art] Starting a blocking GC Alloc
[art] Alloc sticky concurrent mark sweep GC freed 245(67KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 536us total 5.632ms
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 103MB to 96MB
[art] Alloc partial concurrent mark sweep GC freed 211(12KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 553us total 12.668ms
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 103MB to 96MB
[art] Alloc concurrent mark sweep GC freed 80(17KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 583us total 18.989ms
[art] Forcing collection of SoftReferences for 1012KB allocation
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 103MB to 96MB
[art] Alloc concurrent mark sweep GC freed 11(344B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 606us total 17.917ms
[art] Throwing OutOfMemoryError "Failed to allocate a 1036812 byte allocation with 573032 free bytes and 559KB until OOM"
[art] Starting a blocking GC Alloc
[art] Starting a blocking GC Alloc
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 103MB to 96MB
[art] Alloc partial concurrent mark sweep GC freed 6(192B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 605us total 12.669ms
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 103MB to 96MB
[art] Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 565us total 20.010ms
[art] Forcing collection of SoftReferences for 1012KB allocation
[art] Starting a blocking GC Alloc
[art] Clamp target GC heap from 103MB to 96MB
[art] Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 596us total 18.817ms
[art] Starting a blocking GC HomogeneousSpaceCompact
[art] Clamp target GC heap from 103MB to 96MB
[art] HomogeneousSpaceCompact marksweep + semispace GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 95MB/96MB, paused 35.955ms total 35.955ms
[art] Throwing OutOfMemoryError "Failed to allocate a 1036812 byte allocation with 565112 free bytes and 547KB until OOM"
Thread finished: <Thread Pool> #14
Thread started: <Thread Pool> #15
[art] art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI GetMethodID called with pending exception java.lang.OutOfMemoryError: Failed to allocate a 1036812 byte allocation with 565112 free bytes and 547KB until OOM
[art] art/runtime/java_vm_ext.cc:410] at void md5270abb39e60627f0f200893b490a1ade.FragmentContainer.n_setUserVisibleHint(boolean) (FragmentContainer.java:-2)
[art] art/runtime/java_vm_ext.cc:410] at void md5270abb39e60627f0f200893b490a1ade.FragmentContainer.setUserVisibleHint(boolean) (FragmentContainer.java:43)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(android.view.ViewGroup, int, java.lang.Object) (FragmentPagerAdapter.java:134)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.v4.view.ViewPager.populate(int) (ViewPager.java:1266)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.v4.view.ViewPager.setCurrentItemInternal(int, boolean, boolean, int) (ViewPager.java:668)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.v4.view.ViewPager.setCurrentItemInternal(int, boolean, boolean) (ViewPager.java:630)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.v4.view.ViewPager.setCurrentItem(int, boolean) (ViewPager.java:622)
[art] art/runtime/java_vm_ext.cc:410] at void md5270abb39e60627f0f200893b490a1ade.TabbedPageRenderer.n_onTabSelected(android.support.design.widget.TabLayout$Tab) (TabbedPageRenderer.java:-2)
[art] art/runtime/java_vm_ext.cc:410] at void md5270abb39e60627f0f200893b490a1ade.TabbedPageRenderer.onTabSelected(android.support.design.widget.TabLayout$Tab) (TabbedPageRenderer.java:87)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.design.widget.TabLayout.dispatchTabSelected(android.support.design.widget.TabLayout$Tab) (TabLayout.java:1164)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.design.widget.TabLayout.selectTab(android.support.design.widget.TabLayout$Tab, boolean) (TabLayout.java:1157)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.design.widget.TabLayout.selectTab(android.support.design.widget.TabLayout$Tab) (TabLayout.java:1127)
[art] art/runtime/java_vm_ext.cc:410] at void android.support.design.widget.TabLayout$Tab.select() (TabLayout.java:1426)
[art] art/runtime/java_vm_ext.cc:410] at boolean android.support.design.widget.TabLayout$TabView.performClick() (TabLayout.java:1536)
[art] art/runtime/java_vm_ext.cc:410] at void android.view.View$PerformClick.run() (View.java:21168)
[art] art/runtime/java_vm_ext.cc:410] at void android.os.Handler.handleCallback(android.os.Message) (Handler.java:746)
[art] art/runtime/java_vm_ext.cc:410] at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:95)
[art] art/runtime/java_vm_ext.cc:410] at void android.os.Looper.loop() (Looper.java:148)
[art] art/runtime/java_vm_ext.cc:410] at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:5443)
[art] art/runtime/java_vm_ext.cc:410] at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
[art] art/runtime/java_vm_ext.cc:410] at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:728)
[art] art/runtime/java_vm_ext.cc:410] at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:618)
Am I missing something ?
Xamarin.Forms: 2.3.4
@Vandersteen probably this object is being created twice and not being disposed. This was pointed out on another issue here.
using (FastJavaByteArray buffer = new FastJavaByteArray(bufferSize))
{
// allocate new Java byte arrays for Android to use for preview frames
camera.AddCallbackBuffer(new FastJavaByteArray(bufferSize));
}
Try this:
using (FastJavaByteArray buffer = new FastJavaByteArray(bufferSize))
{
// allocate new Java byte arrays for Android to use for preview frames
camera.AddCallbackBuffer(buffer);
}