本文共 4519 字,大约阅读时间需要 15 分钟。
一.背景
在这个系列博客,博主给大家分享了如何基于Dragonboard410c制作遥控炮台的原型机,考虑到我们这个产品的趣味性,博主觉得纯粹处于第三视角去控制炮台瞄准射击的方式稍显单调,于是决定为其添加一双“眼睛”,让体验者以第一视角直接进入炮台“角色”,达到“沉浸式“的体验效果!
二.实时视频
1.硬件组装:保持与炮身视角平行,可方便后续的视野校正。
图1 炮台
2.软件添加实时视频传输:
(1).主机端:在原有的服务器基础上加入motion系统,具体可参考博主之前发过的博客:http://blog.csdn.net/ad3600/article/details/62422756
(2).客户端:
在原来的控制客户端基础上添加远程视频接受及实时播放页面,核心实现代码如下:
package com.boss.xiao.Ideas;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;public class MySurfaceView extends SurfaceView implements Callback, Runnable { private SurfaceHolder sfh; private Canvas canvas; URL videoUrl; private String url; HttpURLConnection conn; Bitmap bmp; private Paint p; InputStream inputstream=null; private Bitmap mBitmap; private static int mScreenWidth; private static int mScreenHeight; float myEyesDistance; int numberOfFaceDetected; Paint myPaint = new Paint(); public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); initialize(); p = new Paint(); p.setAntiAlias(true); myPaint.setColor(Color.GREEN); myPaint.setStyle(Paint.Style.STROKE); myPaint.setStrokeWidth(3); sfh = this.getHolder(); sfh.addCallback(this); this.setKeepScreenOn(true); setFocusable(true); this.getWidth(); this.getHeight(); } private void initialize() { DisplayMetrics dm = new DisplayMetrics(); dm = getResources().getDisplayMetrics(); mScreenWidth = dm.widthPixels; mScreenHeight = dm.heightPixels; } class DrawVideo extends Thread { public DrawVideo() {} public void run() { while (true) { try { videoUrl=new URL(url); conn = (HttpURLConnection)videoUrl.openConnection(); conn.connect(); inputstream = conn.getInputStream(); //获取流 BitmapFactory.Options BitmapFactoryOptionsbfo = new BitmapFactory.Options(); BitmapFactoryOptionsbfo.inPreferredConfig = Bitmap.Config.RGB_565; bmp = BitmapFactory.decodeStream(inputstream,null,BitmapFactoryOptionsbfo);//从获取的流中构建出BMP图像 mBitmap = Bitmap.createScaledBitmap(bmp, mScreenWidth, mScreenHeight, true); canvas = sfh.lockCanvas(); canvas.drawColor(Color.WHITE); canvas.drawBitmap(mBitmap, 0,0, null);//把BMP图像画在画布上 sfh.unlockCanvasAndPost(canvas);//画完一副图像,解锁画布 } catch (Exception ex) { ex.printStackTrace(); } finally {} } } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){} public void surfaceDestroyed(SurfaceHolder holder){} public void GetCameraIP(String p){url=p; Log.e("GetCameraIP ="+p,"xiao");} public void run() { while (true) { try { Log.e("DrawVideo ============","xiao"); videoUrl=new URL(url); conn = (HttpURLConnection)videoUrl.openConnection(); conn.connect(); inputstream = conn.getInputStream(); //获取流 bmp = BitmapFactory.decodeStream(inputstream);//从获取的流中构建出BMP图像 mBitmap = Bitmap.createScaledBitmap(bmp, mScreenWidth, mScreenHeight, true); canvas = sfh.lockCanvas(); canvas.drawColor(Color.WHITE); canvas.drawBitmap(mBitmap, 0,0, null);//把BMP图像画在画布上 sfh.unlockCanvasAndPost(canvas);//画完一副图像,解锁画布 } catch (Exception ex) { ex.printStackTrace(); } finally { } } } public void surfaceCreated(SurfaceHolder holder) { new DrawVideo().start(); } public void drowblack(){} }