Out-Of-Memory errors from camera preview.

968 views
Skip to first unread message

Lachezar Dobrev

unread,
Sep 14, 2010, 7:56:11 AM9/14/10
to zx...@googlegroups.com
Slightly off-topic since it's probably Android specific, but
connected to the project.
* pardon the lengthy mail, please skip code and quote *

I am trying to integrate Bar-Code scanner in our application, but
since it's very interactive while scanning the Scan-Via-Intent
approach is not viable.

Hence-forth I made my own component that shows camera preview in the
background, and the required application components over that.
I use camera.setPreviewCallback(...), made my own brain-less
implementation of the LuminescenceSource.

However running on the Android 1.6 emulator I hit OOME rather
quickly (in a few seconds).

My preview processor is:

[code]
// Preview call-back implementation.
class PreviewDataCallback implements PreviewCallback {

volatile boolean working = false;

@Override
public void onPreviewFrame(byte[] data, Camera cam) {
// Avoid race condition
synchronized (this) {
if (working)
return;
working = true;
}

try {
Size size;
size = cam.getParameters().getPreviewSize();
processPreviewFrame(size.width, size.height, data);
} catch (Exception e) {
Log.e(LOGC, "Failed processing frame data", e);
} finally {
synchronized (this) {
working = false;
}
}
}
}

Reader reader = new Code128Reader();

protected synchronized void processPreviewFrame(int w, int h, byte[] d) {
LuminanceSource src;
src = new PreviewLuminanceSource(w, h, d);

Binarizer bin;
bin = new GlobalHistogramBinarizer(src);

BinaryBitmap img;
img = new BinaryBitmap(bin);

String data;
try {
Result res;
res = reader.decode(img);
data = res.getText();
// Processing follows.
} catch (...) {
// Process exceptional cases.
}
}
[/code]

I do not retain any explicit references to any of the objects
created in the processPreviewFrame(...) method.
However after a few seconds I see the log flooded with:

[quote]
ERROR/Camera-JNI(235): Couldn't allocate byte array for JPEG data
DEBUG/Camera-JNI(235): dataCallback(4, 0x78620)
INFO/dalvikvm-heap(235): Clamp target GC heap from 17.670MB to 16.000MB
DEBUG/dalvikvm(235): GC freed 14 objects / 688 bytes in 142ms
INFO/dalvikvm-heap(235): Forcing collection of SoftReferences for
271376-byte allocation
INFO/dalvikvm-heap(235): Clamp target GC heap from 17.670MB to 16.000MB
DEBUG/dalvikvm(235): GC freed 0 objects / 0 bytes in 91ms
ERROR/dalvikvm-heap(235): Out of memory on a 271376-byte allocation.
INFO/dalvikvm(235): "Binder Thread #3" prio=5 tid=15 RUNNABLE
INFO/dalvikvm(235): | group="main" sCount=0 dsCount=0 s=N
obj=0x437b4910 self=0x198980
INFO/dalvikvm(235): | sysTid=248 nice=0 sched=0/0 handle=1119848
INFO/dalvikvm(235): at dalvik.system.NativeStart.run(Native Method)
[/quote]

Have you met anything similar while developing the Capture Activity?

Running the SAME code under Android 2.1-update1 emulator does not
yield OOME, and works.

Sean Owen

unread,
Sep 14, 2010, 9:06:41 AM9/14/10
to zxing
What is the preview size, anything particularly large? It should be
like 240x320, that kind of size.

It seems like it has a 16MB heap going on? that seems tiny and doesn't
seem normal.

The OOM is coming from native camera code.

No I have never seen something like this, though we develop on real
phones.
The memory usage comes mostly from the preview image, and that should
never take more than a few hundred kilobytes.

Daniel Switkin

unread,
Sep 14, 2010, 10:38:17 AM9/14/10
to zx...@googlegroups.com
The 16MB heap is standard for Android Java apps, but as you point out, barcode scanning shouldn't come close to using that up.

Daniel

Lachezar Dobrev

unread,
Sep 14, 2010, 11:03:17 AM9/14/10
to zx...@googlegroups.com
Well... Preview size is... 480x320 (HVGA emulator, and phone too.)
This should mean, that a single preview shot is around 150K pixels,
which is 150K.

Like Daniel says 16MB heap is default on Android, and «SHOULD BE
ENOUGH FOR EVERYONE®»

Still this is way more than the 150K per frame.

I also noticed no such error when using Emulator with Android 2.1, just 1.6.
I also noticed, that on Android 2.1 I get the SAME pointer every
time a frame is available, while with 1.6 the pointer is different.

My HTC Legend (2.1 Update 1) also works as expected.

I will have to attribute this issue to a defect in the emulator,
since no one else has hit this error, and it does not manifest itself
on 2.1 and real life device. Pity I don't have an 1.6 device to test
on.

Thank you people, thank you people.

2010/9/14 Sean Owen <sro...@gmail.com>:

Lachezar Dobrev

unread,
Sep 14, 2010, 7:21:34 PM9/14/10
to zx...@googlegroups.com
I rewrote the code to use setOneShotPreviewCallback(...) and use a
Handler with a 200ms delay to reconnect. This seems to help seriously,
and also allows the application to be a bit more responsive. Haven't
figured out whether there are any side effects.

I had the opportunity to test my application on a HTC Hero (Android
1.5), and it exhibits no ill effects.

Licensing question: is it permissible to use the unmodified ZXing
core in a closed source private application?

2010/9/14 Lachezar Dobrev <l.do...@gmail.com>:

Sean Owen

unread,
Mar 6, 2013, 10:59:25 AM3/6/13
to zx...@googlegroups.com
Not sure what you're looking for. As he says it seemed like an emulator problem only. This thread is quite old, and the code has used oneShotPreviewCallback() for years, and no longer supports < 2.1 anyway.

On Wednesday, March 6, 2013 3:53:34 PM UTC, Henrik Gilvad wrote:
could you post some code for this fix? It's really nasty with ZXing on early Androids.


Reply all
Reply to author
Forward
0 new messages