Search code examples
androidallocationsegmentation-faultrenderscript

Memory errors using Allocations and RenderScript


I am working on live streaming a WiFi camera to my Android tablet. I have the frame grabber running in a Thread, which in turn takes the pixels and passes them to RenderScript to do some filter processing (another Thread). My output Allocation is linked to a Surface for viewing.

The app will crash periodically with SIGSEGV faults, the monitor says it's happening in either a Thread, GCDaemon or JNISurfaceTexture. I have 2 kernels I am currently running (switchable) and both will fail eventually. The more basic kernel is just a pixel [] from the camera into the input Allocation, where it is sent to RenderScript and then the result output Allocation of the 'forEach' call is sent to the surface using .ioSend().

If I take the pixel [] array from the camera thread and copy it directly to the output Allocation, and call .ioSend(), it never crashes (i.e. circumventing RenderScript calls). I can also create another output allocation (temp one) and use this as the return output allocation of the 'forEach' call, copy this to the Surface linked output Allocation and it will not crash, although I do get some strange pixelation effects in the video.

I'm still a bit new to RenderScript but could there be some thread safety issues I am not aware of? Or perhaps a bug in RS()?

Here is how I am configuring the input and output Allocations:

 android.renderscript.Element elemIN = android.renderscript.Element.createPixel(mRS, android.renderscript.Element.DataType.UNSIGNED_8, android.renderscript.Element.DataKind.PIXEL_RGBA);
        Type.Builder TypeIn = new Type.Builder( mRS, elemIN );

        mAllocationIn = Allocation.createTyped( mRS,
            TypeIn.setX( videoWidth ).setY( videoHeight ).create(),   
            Allocation.MipmapControl.MIPMAP_NONE,    
            Allocation.USAGE_SCRIPT );

and

  mAllocationOut = Allocation.createTyped( mRS, TypeOUT.setX( videoWidth ).setY( videoHeight ).create(),   
            Allocation.MipmapControl.MIPMAP_NONE,    
            ( Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT ) );  

Here is my simple RGB kernel:

 uchar4 __attribute__((kernel)) toRgb_Color( uchar4 in ) {
    float4 ndviPixel;
    uchar4 out;

    ndviPixel.r = ( float )( in[0] / 255.0 );
    ndviPixel.g = ( float )( in[1] / 255.0 );
    ndviPixel.b = ( float )( in[2] / 255.0 );
    ndviPixel.a = 1.0f;

    out = rsPackColorTo8888(ndviPixel);
    ndviPixel = 0;

    return out;
}

Lastly, my call to the kernel is:

mScript.forEach_toRgb_Color( mAllocationIn, mAllocationTemp );

UPDATE

Here's how I'm declaring my TypeOUT:

  mAllocationOut = Allocation.createTyped( mRS, TypeOUT.setX( videoWidth ).setY( videoHeight ).create(),   
            Allocation.MipmapControl.MIPMAP_NONE,    
            ( Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT ) ); 

Also, I am waiting for the surface to be created from the onSurfaceTextureAvailable event like so:

  public void onSurfaceTextureAvailable( SurfaceTexture surfaceTexture, int width, int height ) {
      mSurface = new Surface( surfaceTexture );
}

After I create my input and output allocations, I use the latched 'mSurface' to set the output surface of the output allocation, like this:

        mAllocationOut.setSurface( mSurface );

I have mSurface declared as static if that makes any difference. I've tried to with and without static and I still get the crash.

Monitor output is here:

04-23 12:59:54.752: A/libc(15192): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 15230 (Thread-1697)
04-23 12:59:54.853: I/DEBUG(189): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
04-23 12:59:54.853: I/DEBUG(189): Build fingerprint: 'nvidia/wx_na_wf/shieldtablet:5.0.1/LRX22C/29979_515.3274:user/release-keys'
04-23 12:59:54.853: I/DEBUG(189): Revision: '0'
04-23 12:59:54.853: I/DEBUG(189): ABI: 'arm'
04-23 12:59:54.854: I/DEBUG(189): pid: 15192, tid: 15230, name: Thread-1697  >>> helios.android <<<
04-23 12:59:54.854: I/DEBUG(189): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
04-23 12:59:54.876: I/DEBUG(189):     r0 6f81a568  r1 00000001  r2 00000000  r3 00000000
04-23 12:59:54.877: I/DEBUG(189):     r4 630a3200  r5 6f81a568  r6 00000000  r7 00000001
04-23 12:59:54.877: I/DEBUG(189):     r8 12c24000  r9 7c9a0f40  sl 7e86d404  fp 00000008
04-23 12:59:54.877: I/DEBUG(189):     ip 7f8e1a10  sp 7f8e1970  lr 4211475d  pc 420d3f72  cpsr 200f0030
04-23 12:59:54.878: I/DEBUG(189): backtrace:
04-23 12:59:54.878: I/DEBUG(189):     #00 pc 000d3f72  /system/lib/libart.so (void std::__1::__tree_remove<std::__1::__tree_node_base<void*>*>(std::__1::__tree_node_base<void*>*, std::__1::__tree_node_base<void*>*)+205)
04-23 12:59:54.878: I/DEBUG(189):     #01 pc 00114759  /system/lib/libart.so (art::gc::allocator::RosAlloc::RefillRun(art::Thread*, unsigned int)+232)
04-23 12:59:54.878: I/DEBUG(189):     #02 pc 00114973  /system/lib/libart.so (art::gc::allocator::RosAlloc::AllocFromRun(art::Thread*, unsigned int, unsigned int*)+490)
04-23 12:59:54.879: I/DEBUG(189):     #03 pc 0028ba97  /system/lib/libart.so (artAllocObjectFromCodeInitializedRosAlloc+98)
04-23 12:59:54.879: I/DEBUG(189):     #04 pc 000a23cb  /system/lib/libart.so (art_quick_alloc_object_initialized_rosalloc+10)
04-23 12:59:54.879: I/DEBUG(189):     #05 pc 001d6359  /data/dalvik-cache/arm/system@[email protected]
04-23 12:59:55.360: I/DEBUG(189): Tombstone written to: /data/tombstones/tombstone_01
04-23 12:59:55.361: I/BootReceiver(659): Copying /data/tombstones/tombstone_01 to DropBox (SYSTEM_TOMBSTONE)

Solution

  • The issue is the way you are accessing the input Allocation. Each element in the Allocation is provided with all 4 components. But, it cannot be treated as an array as done here. Try this instead:

    uchar4 __attribute__((kernel)) toRgb_Color( uchar4 in ) {
        float4 tmpPixel = convert_float4(in);
    
        //  This copy is most likely unnecessary, but done for
        //  completeness.
        float4 ndviPixel.r = tmpPixel.x;
               ndviPixel.g = tmpPixel.y;
               ndviPixel.b = tmpPixel.z;
               ndviPixel.a = 255.0;
        uchar4 out = rsPackColorTo8888(ndviPixel);
        return out;
    }