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

xiaoxiao2021-02-27  380

前言:

利用手头的一块安卓开发板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);         }     }

转载请注明原文地址: https://www.6miu.com/read-2417.html

最新回复(0)