一.背景
在这个系列博客,博主给大家分享了如何基于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 BitmapFactoryOption***fo = new BitmapFactory.Options();
BitmapFactoryOption***fo.inPreferredConfig = Bitmap.Config.RGB_565;
bmp = BitmapFactory.decodeStream(inputstream,null,BitmapFactoryOption***fo);//从获取的流中构建出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(){}
}
图2 客户端控制页面