手把手教大家将Dragonboard 410c打造成一个IP camera

来源:互联网 发布:市场花园知乎 编辑:程序博客网 时间:2024/06/05 14:51

前言:

利用手头的一块安卓开发板dragonboard 410c 变成一个远程监控摄像头。这里使用Java创建开发板camera客户端和远程服务上的监控界面。

实现方法考虑几点:
创建一个Android自定义的摄像头应用
把preview的数据发送到服务端
preview的NV21数据解码
把图像画出来

Android摄像头,Socket链接,服务端图像显示
创建preview回调函数:

private Camera.PreviewCallback mPreviewCallback = new PreviewCallback() {         @Override        public void onPreviewFrame(byte[] data, Camera camera) {            // TODO Auto-generated method stub            synchronized (mQueue) {                if (mQueue.size() == MAX_BUFFER) {                    mQueue.poll();                }                mQueue.add(data);            }        }    };

注册回调函数:

try {            mCamera.setPreviewCallback(mPreviewCallback);            mCamera.setPreviewDisplay(mHolder);            mCamera.startPreview();         } catch (Exception e){            Log.d(TAG, "Error starting camera preview: " + e.getMessage());        }

停止释放摄像头:

public void onPause() {        if (mCamera != null) {            mCamera.setPreviewCallback(null);            mCamera.stopPreview();        }        resetBuff();    }

使用AlertDialog来设置服务器IP地址:

private void setting() {        LayoutInflater factory = LayoutInflater.from(this);        final View textEntryView = factory.inflate(R.layout.server_setting, null);        AlertDialog dialog =  new AlertDialog.Builder(IPCamera.this)            .setIconAttribute(android.R.attr.alertDialogIcon)            .setTitle(R.string.setting_title)            .setView(textEntryView)            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {                public void onClick(DialogInterface dialog, int whichButton) {                     EditText ipEdit = (EditText)textEntryView.findViewById(R.id.ip_edit);                    EditText portEdit = (EditText)textEntryView.findViewById(R.id.port_edit);                    mIP = ipEdit.getText().toString();                    mPort = Integer.parseInt(portEdit.getText().toString());                     Toast.makeText(IPCamera.this, "New address: " + mIP + ":" + mPort, Toast.LENGTH_LONG).show();                }            })            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {                public void onClick(DialogInterface dialog, int whichButton) {                     /* User clicked cancel so do some stuff */                }            })            .create();        dialog.show();    }


启动线程来创建socket链接,发送JSON数据和每一帧的图像数据:

mSocket = new Socket();mSocket.connect(new InetSocketAddress(mIP, mPort), 10000);BufferedOutputStream outputStream = new BufferedOutputStream(mSocket.getOutputStream());BufferedInputStream inputStream = new BufferedInputStream(mSocket.getInputStream()); JsonObject jsonObj = new JsonObject();    jsonObj.addProperty("type", "data");    jsonObj.addProperty("length", mCameraPreview.getPreviewLength());    jsonObj.addProperty("width", mCameraPreview.getPreviewWidth());    jsonObj.addProperty("height", mCameraPreview.getPreviewHeight());     byte[] buff = new byte[256];    int len = 0;    String msg = null;    outputStream.write(jsonObj.toString().getBytes());    outputStream.flush();     while ((len = inputStream.read(buff)) != -1) {        msg = new String(buff, 0, len);         // JSON analysis        JsonParser parser = new JsonParser();        boolean isJSON = true;        JsonElement element = null;        try {            element =  parser.parse(msg);        }        catch (JsonParseException e) {            Log.e(TAG, "exception: " + e);            isJSON = false;        }        if (isJSON && element != null) {            JsonObject obj = element.getAsJsonObject();            element = obj.get("state");            if (element != null && element.getAsString().equals("ok")) {                // send data                while (true) {                    outputStream.write(mCameraPreview.getImageBuffer());                    outputStream.flush();                     if (Thread.currentThread().isInterrupted())                        break;                }                 break;            }        }        else {            break;        }    }     outputStream.close();    inputStream.close();

服务端接收数据:

public int fillBuffer(byte[] data, int off, int len, LinkedList<byte[]> YUVQueue) {        mTotalLength += len;        mByteArrayOutputStream.write(data, off, len);         if (mTotalLength == mFrameLength) {             synchronized (YUVQueue) {                YUVQueue.add(mByteArrayOutputStream.toByteArray());                mByteArrayOutputStream.reset();            }             mTotalLength = 0;                     System.out.println("received file");        }         return 0;    }
 

NV21解码:

public static int[] convertYUVtoRGB(byte[] yuv, int width, int height)            throws NullPointerException, IllegalArgumentException {                int[] out = new int[width * height];        int sz = width * height;         int i, j;        int Y, Cr = 0, Cb = 0;        for (j = 0; j < height; j++) {            int pixPtr = j * width;            final int jDiv2 = j >> 1;            for (i = 0; i < width; i++) {                Y = yuv[pixPtr];                if (Y < 0)                    Y += 255;                if ((i & 0x1) != 1) {                    final int cOff = sz + jDiv2 * width + (i >> 1) * 2;                    Cb = yuv[cOff];                    if (Cb < 0)                        Cb += 127;                    else                        Cb -= 128;                    Cr = yuv[cOff + 1];                    if (Cr < 0)                        Cr += 127;                    else                        Cr -= 128;                }                int R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);                if (R < 0)                    R = 0;                else if (R > 255)                    R = 255;                int G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1)                        + (Cr >> 3) + (Cr >> 4) + (Cr >> 5);                if (G < 0)                    G = 0;                else if (G > 255)                    G = 255;                int B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);                if (B < 0)                    B = 0;                else if (B > 255)                    B = 255;                out[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R;            }        }         return out;    }
 

使用Swing绘制BufferedImage

BufferedImage bufferedImage = null;int[] rgbArray = Utils.convertYUVtoRGB(data, mWidth, mHeight);bufferedImage = new BufferedImage(mWidth, mHeight, BufferedImage.TYPE_USHORT_565_RGB);bufferedImage.setRGB(0, 0, mWidth, mHeight, rgbArray, 0, mWidth);
 
 
       synchronized (mQueue) {            if (mQueue.size() > 0) {                mLastFrame = mQueue.poll();            }           }        if (mLastFrame != null) {            g.drawImage(mLastFrame, 0, 0, null);        }        else if (mImage != null) {            g.drawImage(mImage, 0, 0, null);        }    }




0 0
原创粉丝点击