2015-04-22 101 views
1

我正在將WiFi攝像頭直播到我的Android平板電腦。我有在一個線程中運行的圖像採集卡,它接着將像素並將它們傳遞給RenderScript以執行一些過濾處理(另一個線程)。我的輸出分配鏈接到Surface進行查看。使用Allocations和RenderScript的內存錯誤

該應用程序將定期崩潰與SIGSEGV故障,監視器說它發生在線程,GCDaemon或JNISurfaceTexture。我有2個內核,我正在運行(可切換),最終都會失敗。更基本的內核僅僅是一個像素[]從攝像機進入輸入分配,然後發送到RenderScript,然後使用.ioSend()將結果輸出分配給'forEach'調用。

如果我從攝像頭線程中獲取像素[]數組,並將其直接複製到輸出Allocation,並調用.ioSend(),它從不崩潰(即避開RenderScript調用)。我也可以創建另一個輸出分配(臨時一個),並將其用作'forEach'調用的返回輸出分配,將其複製到Surface鏈接的輸出分配,並且不會崩潰,儘管我的確在圖形中獲得了一些奇怪的像素化效果視頻。

我對RenderScript還是有點新意,但是可能會出現一些我不知道的線程安全問題?或者RS()中的一個bug?

這裏是我正在配置的輸入和輸出分配:

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); 

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

這裏是我的簡單的RGB內核:

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; 
} 

最後,我呼籲內核是:

mScript.forEach_toRgb_Color(mAllocationIn, mAllocationTemp); 

UPDATE

這裏是如何,我宣佈我TypeOUT:

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

而且,我在等待表面從onSurfaceTextureAvailable事件創建像這樣:

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

創建我的輸入和輸出分配後,我使用鎖存的'mSurface'來設置輸出分配的輸出表面,lik e這:

 mAllocationOut.setSurface(mSurface); 

我有mSurface聲明爲靜態,如果這有什麼區別。我嘗試過和沒有靜態,我仍然得到崩潰。

監視器輸出是在這裏:

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/[email protected]@boot.oat 
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) 

回答

0

問題在於您訪問輸入Allocation的方式。 Allocation中的每個元素都提供了全部4個組件。但是,它不能像這裏所做的那樣被當作一個數組來處理。試試這個:

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; 
} 
+0

好東西,很高興你能夠得到那個工作好。我猜你在做像素操作時是怎麼做的,所以我不驚訝它有一些麻煩。但是,解決你的問題(崩潰)的關鍵是正確使用'uchar4'作爲矢量而不是數組。 –

+0

無賴。我想我說得太快了。我剝離了我的RGB內核,只返回'uchar4 in',一段時間後我仍然崩潰。 –

+0

是否以'TypeIn'相同的方式創建'TypeOut'?用logcat(崩潰)輸出更新您的原始帖子。 –

0

也許有像你說的(你得到OOM試圖抓住這一點?)......你流的內容確實是一些致命的內存錯誤?也許你想要緩衝到很多...也許你給surfaceflinger一個太大的緩衝區...因爲你直接控制像素和緩衝區的大小,如果不仔細地做,可能會發生很多錯誤......你是否可能鎖定表面你的應用?這意味着你無法控制畫布的大小,因此不再控制緩衝區大小......如果io不能幫助你,但是你已經準備好搜索你在谷歌上的錯誤了嗎?