Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I used <a href="https://stackoverflow.com/users/749709/walta">walta</a>'s solution but I had some problems with YUV conversion, camera frames output sizes and crash on camera release.</p> <p>Finally the following code worked for me:</p> <pre><code>public class MySurfaceView extends SurfaceView implements Callback, Camera.PreviewCallback { private static final String TAG = "MySurfaceView"; private int width; private int height; private SurfaceHolder mHolder; private Camera mCamera; private int[] rgbints; private boolean isPreviewRunning = false; private int mMultiplyColor; public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); mHolder = getHolder(); mHolder.addCallback(this); mMultiplyColor = getResources().getColor(R.color.multiply_color); } // @Override // protected void onDraw(Canvas canvas) { // Log.w(this.getClass().getName(), "On Draw Called"); // } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { synchronized (this) { if (isPreviewRunning) return; this.setWillNotDraw(false); // This allows us to make our own draw calls to this canvas mCamera = Camera.open(); isPreviewRunning = true; Camera.Parameters p = mCamera.getParameters(); Size size = p.getPreviewSize(); width = size.width; height = size.height; p.setPreviewFormat(ImageFormat.NV21); showSupportedCameraFormats(p); mCamera.setParameters(p); rgbints = new int[width * height]; // try { mCamera.setPreviewDisplay(holder); } catch (IOException e) // { Log.e("Camera", "mCamera.setPreviewDisplay(holder);"); } mCamera.startPreview(); mCamera.setPreviewCallback(this); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { synchronized (this) { try { if (mCamera != null) { //mHolder.removeCallback(this); mCamera.setPreviewCallback(null); mCamera.stopPreview(); isPreviewRunning = false; mCamera.release(); } } catch (Exception e) { Log.e("Camera", e.getMessage()); } } } @Override public void onPreviewFrame(byte[] data, Camera camera) { // Log.d("Camera", "Got a camera frame"); if (!isPreviewRunning) return; Canvas canvas = null; if (mHolder == null) { return; } try { synchronized (mHolder) { canvas = mHolder.lockCanvas(null); int canvasWidth = canvas.getWidth(); int canvasHeight = canvas.getHeight(); decodeYUV(rgbints, data, width, height); // draw the decoded image, centered on canvas canvas.drawBitmap(rgbints, 0, width, canvasWidth-((width+canvasWidth)&gt;&gt;1), canvasHeight-((height+canvasHeight)&gt;&gt;1), width, height, false, null); // use some color filter canvas.drawColor(mMultiplyColor, Mode.MULTIPLY); } } catch (Exception e){ e.printStackTrace(); } finally { // do this in a finally so that if an exception is thrown // during the above, we don't leave the Surface in an // inconsistent state if (canvas != null) { mHolder.unlockCanvasAndPost(canvas); } } } /** * Decodes YUV frame to a buffer which can be use to create a bitmap. use * this for OS &lt; FROYO which has a native YUV decoder decode Y, U, and V * values on the YUV 420 buffer described as YCbCr_422_SP by Android * * @param rgb * the outgoing array of RGB bytes * @param fg * the incoming frame bytes * @param width * of source frame * @param height * of source frame * @throws NullPointerException * @throws IllegalArgumentException */ public void decodeYUV(int[] out, byte[] fg, int width, int height) throws NullPointerException, IllegalArgumentException { int sz = width * height; if (out == null) throw new NullPointerException("buffer out is null"); if (out.length &lt; sz) throw new IllegalArgumentException("buffer out size " + out.length + " &lt; minimum " + sz); if (fg == null) throw new NullPointerException("buffer 'fg' is null"); if (fg.length &lt; sz) throw new IllegalArgumentException("buffer fg size " + fg.length + " &lt; minimum " + sz * 3 / 2); int i, j; int Y, Cr = 0, Cb = 0; for (j = 0; j &lt; height; j++) { int pixPtr = j * width; final int jDiv2 = j &gt;&gt; 1; for (i = 0; i &lt; width; i++) { Y = fg[pixPtr]; if (Y &lt; 0) Y += 255; if ((i &amp; 0x1) != 1) { final int cOff = sz + jDiv2 * width + (i &gt;&gt; 1) * 2; Cb = fg[cOff]; if (Cb &lt; 0) Cb += 127; else Cb -= 128; Cr = fg[cOff + 1]; if (Cr &lt; 0) Cr += 127; else Cr -= 128; } int R = Y + Cr + (Cr &gt;&gt; 2) + (Cr &gt;&gt; 3) + (Cr &gt;&gt; 5); if (R &lt; 0) R = 0; else if (R &gt; 255) R = 255; int G = Y - (Cb &gt;&gt; 2) + (Cb &gt;&gt; 4) + (Cb &gt;&gt; 5) - (Cr &gt;&gt; 1) + (Cr &gt;&gt; 3) + (Cr &gt;&gt; 4) + (Cr &gt;&gt; 5); if (G &lt; 0) G = 0; else if (G &gt; 255) G = 255; int B = Y + Cb + (Cb &gt;&gt; 1) + (Cb &gt;&gt; 2) + (Cb &gt;&gt; 6); if (B &lt; 0) B = 0; else if (B &gt; 255) B = 255; out[pixPtr++] = 0xff000000 + (B &lt;&lt; 16) + (G &lt;&lt; 8) + R; } } } private void showSupportedCameraFormats(Parameters p) { List&lt;Integer&gt; supportedPictureFormats = p.getSupportedPreviewFormats(); Log.d(TAG, "preview format:" + cameraFormatIntToString(p.getPreviewFormat())); for (Integer x : supportedPictureFormats) { Log.d(TAG, "suppoterd format: " + cameraFormatIntToString(x.intValue())); } } private String cameraFormatIntToString(int format) { switch (format) { case PixelFormat.JPEG: return "JPEG"; case PixelFormat.YCbCr_420_SP: return "NV21"; case PixelFormat.YCbCr_422_I: return "YUY2"; case PixelFormat.YCbCr_422_SP: return "NV16"; case PixelFormat.RGB_565: return "RGB_565"; default: return "Unknown:" + format; } } } </code></pre> <p>To Use it, run from you activity's onCreate the following code:</p> <pre><code> SurfaceView surfaceView = new MySurfaceView(this, null); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); surfaceView.setLayoutParams(layoutParams); mRelativeLayout.addView(surfaceView); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload