7

Jelly Bean에서 카메라 미리보기로 채워진 SurfaceTexture에서 Renderscript 할당을 만들 수 있습니까? 안드로이드 소스 트리 내에서 응용 프로그램을 빌드하고 있으므로 Allocation.setSurfaceTexture()와 같은 @hide API를 사용하면 좋습니다. 그러나 나는 RS Graphics deprecated API 사용을 피하고 싶습니다. 비슷한 질문 here은 완전히 답변을 얻지 못했고 JB 특정 적이 아닙니다. 아래의 코드하려고 할 때Camera Preview로 채워진 SurfaceTexture를 Renderscript 입력으로 Jelly Bean에서 할당

나는 다음과 같은 문제가 있습니다

  • 데이터는 Renderscript에 점점 내가 언제부터 updateTexImage()에있는, 항상 onFrameAvailable 콜백이 반복적으로 호출하려면 제로
  • 입니다 I Allocation.ioReceive()를 호출하면 처음부터 다시 호출되지 않으며 logcat에 "invalid EGLDisplay"가 있습니다. 그러나 나는 ioReceive()가 갈 방법이라고 생각했습니다. 내부적으로 updateTexImage()입니다.
  • 지원되는 할당 유형에는 RGBA8888이 포함되지만 NV21 (카메라 미리보기 형식)은 포함되지 않습니다. RS 코드는 이러한 방식으로 데이터 형식을 지정할 수 있습니까?

(필자가 요청한 VGA 해상도를 지원하는 장치를 알고 있습니다.)

public class SampleRSCPCActivity extends Activity implements SurfaceTexture.OnFrameAvailableListener { 
final static int DO_KERNEL = 0; 
private static final String TAG="SAMPLERSCP"; 
private static Camera mCamera; 
private Camera.Parameters mParams; 
private int mFrameWidth, mFrameHeight; 
private static SurfaceTexture mST; 
private RenderScript mRS; 
private Allocation mInAllocation; 
private Allocation mOutAllocation; 
private ScriptC_mono mScript; 

public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    Log.i(TAG, "onCreate()"); 
    createGUI(); 
    createCamera(); 
    createRSEnvironment(); 
} 

public void onPause() { 
    Log.i(TAG, "onPause"); 
    mCamera.stopPreview(); 
    mCamera.release(); 
    mCamera = null; 
    super.onPause(); 
} 

private void createCamera() { 
    mCamera = Camera.open(); 
    mParams = mCamera.getParameters(); 

    mFrameWidth = 640; 
    mFrameHeight = 480; 
    mParams.setPreviewSize(mFrameWidth, mFrameHeight); 
    mParams.setPreviewFormat(ImageFormat.NV21); 

    mCamera.setParameters(mParams); 
} 

private void createRSEnvironment() { 
    mRS = RenderScript.create(this); 
    mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono); 

    Type.Builder b = new Type.Builder(mRS, Element.U8(mRS)); 

    int usage = Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_INPUT; 
    mInAllocation = Allocation.createTyped(mRS, b.setX(mFrameWidth).setY(mFrameHeight).create(), usage); 
    mOutAllocation = Allocation.createTyped(mRS, b.setX(mFrameWidth).setY(mFrameHeight).create()); 

    Log.i(TAG, "Getting SurfaceTexture from input Allocation"); 
    mST = mInAllocation.getSurfaceTexture(); 

    mST.setOnFrameAvailableListener(this); 

    try { 
     Log.i(TAG, "Setting SurfaceTexture for camera preview"); 
     mCamera.setPreviewTexture(mST); 

     Log.i(TAG, "Starting preview"); 
     mCamera.startPreview(); 
     } catch (IOException e) { 
     Log.e(TAG, "Oops, something got wrong with setting the camera preview texture"); 
    } 
} 

private void createGUI() { 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
      WindowManager.LayoutParams.FLAG_FULLSCREEN); 

    setContentView(R.layout.main); 
} 

private Handler handler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     if (msg.what == DO_KERNEL) 
      Log.i(TAG, "Calling RS kernel"); 
      mST.updateTexImage(); 
      // mInAllocation.ioReceive(); 
      mScript.forEach_root(mInAllocation, mOutAllocation); 

      Log.i(TAG, "Finishing RS"); 
      mRS.finish(); 
      Log.i(TAG, "Ok"); 
    } 
}; 

public void onFrameAvailable(SurfaceTexture st) { 
    Log.i(TAG, "onFrameAvailable callback"); 
    handler.sendEmptyMessage(DO_KERNEL); 
} 

}는 RS 코드, 그냥 null이 아닌 데이터를 감지하는 매우 간단한 노력하고있다

:

void root(const uchar *v_in, uchar *v_out, uint32_t x, uint32_t y) { 

if (*v_in != 0) 
    rsDebug("input data non null !", *v_in); 
*v_out = (x/640) * 255; 

} 내 자신의 질문에

답변

6

다음 업 :

카메라로 채워진 SurfaceTexture에서 NV21 버퍼를 읽을 수 없다는 사실이 드러납니다. 나는 전문가를 위해 안드로이드 소스 코드를 수정해야만했다 : 전문가 용 : SurfaceTexture의 현재 버퍼를 얻은 다음 실제 버퍼 포인터를 얻기 위해 잠글 - 나는 RS 드라이버의 rsdAllocationIoReceive()에서 이것을 수행했다. 이것은 카메라에서 RS 로의 버퍼 복사를 피하기에 좋았을 것입니다.

최신 JB (MR1 버전)에는 카메라 미리보기에서 RS 처리를 수행하는 LivePreview라는 테스트 응용 프로그램이 있습니다. 그러나 응용 프로그램 할당 미리보기 콜백 버퍼를 사용하며 입력 할당에 이 복사됩니다.입니다. 재미있게 색 변환을 위해 새로운 ScriptIntrinsicRgbToYuv 클래스를 사용합니다. 변환의 대부분은 손으로 코딩 된 Neon 어셈블리이므로 아마도 매우 빠릅니다.

Mali가 지원되는 RS 드라이버가있는 Nexus 10이 GPU에서이 작업을 수행하는 경우에도이 기기를 사용하여 게임을 즐기기를 바랍니다. (기부자 환영 ;-)!)