文章评分
次,平均分 :
[收起]
文章目录
之前一直有打算做一个局域网上基于UDP通信的视频通话软件,一直不知道视频流在网络上以怎样的形式传输,虽然知道几个视频流的编码格式,但是其实一直没有进行付诸实践; 最近在学习安卓手表开发时,在github上看到一个将手机的实时视频传输到手表的项目,发现一个似乎低级但是在局域网应该还是比较实用的局域网视频传输方法:直接将从摄像头获取的图像压缩以后进行发送。本项目GitHub主页:https://github.com/retravel/AndroidRealTimeVideo
获取摄像头实时图片、UDP发送图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
private void initCanmera() { int cameras = Camera.getNumberOfCameras(); Camera.CameraInfo info = new Camera.CameraInfo(); for (int i = 0; i < cameras; i++) { Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { camera = Camera.open(i); break; } } //没有前置摄像头 if (camera == null) camera = Camera.open(); try { camera.setPreviewDisplay(surfaceHolder); camera.setPreviewCallback(this); } catch (Exception e) { camera.release();//释放资源 camera = null; } } @Override public void onPreviewFrame(byte[] data, Camera camera) { Camera.Size previewSize = camera.getParameters().getPreviewSize(); int[] rgb = decodeYUV420SP(data, previewSize.width, previewSize.height); Bitmap bmp = Bitmap.createBitmap(rgb, previewSize.width, previewSize.height, Bitmap.Config.ARGB_8888); int smallWidth, smallHeight; int dimension = 200; if (previewSize.width > previewSize.height) { smallWidth = dimension; smallHeight = dimension * previewSize.height / previewSize.width; } else { smallHeight = dimension; smallWidth = dimension * previewSize.width / previewSize.height; } Matrix matrix = new Matrix(); matrix.postRotate(mCameraOrientation); Bitmap bmpSmall = Bitmap.createScaledBitmap(bmp, smallWidth, smallHeight, false); Bitmap bmpSmallRotated = Bitmap.createBitmap(bmpSmall, 0, 0, smallWidth, smallHeight, matrix, false); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bmpSmallRotated.compress(Bitmap.CompressFormat.WEBP, 80, baos); up.sendMsg(baos.toByteArray()); } @Override public void surfaceCreated(SurfaceHolder holder) { initCanmera(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { int currentCamera = Camera.CameraInfo.CAMERA_FACING_FRONT; Camera.Parameters parameters = camera.getParameters();//得到相机设置参数 Camera.Size size = camera.getParameters().getPreviewSize(); //获取预览大小 parameters.setPictureFormat(PixelFormat.JPEG);//设置图片格式 Camera.CameraInfo info = new Camera.CameraInfo(); camera.getCameraInfo(currentCamera, info); int rotation = this.getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int resultA = 0, resultB = 0; if (currentCamera == Camera.CameraInfo.CAMERA_FACING_BACK) { resultA = (info.orientation - degrees + 360) % 360; resultB = (info.orientation - degrees + 360) % 360; camera.setDisplayOrientation(resultA); } else { resultA = (360 + 360 - info.orientation - degrees) % 360; resultB = (info.orientation + degrees) % 360; camera.setDisplayOrientation(resultA); } camera.setPreviewCallback(this); parameters.setRotation(resultB); mCameraOrientation = resultB; camera.setParameters(parameters); camera.startPreview();//开始预览 } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } } |
UDP server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package cn.wangbaiyuan.androidsocketav; /** * Created by BrainWang on 2016/3/21. */ import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; /** * 基于UDP协议的服务器端,对来自客户端的数据包进行应答 * * @author <a href="http://wangbaiyuan">王柏元</a> */ public class UDPServer { /** * 端口 */ //int port=1888; DatagramSocket socket; String lastString = (-1 + ""); int sameTime = 0; public handleReceiveData callback; public UDPServer(int port) throws SocketException { socket = new DatagramSocket(port); //服务端DatagramSocket System.out.println("服务器启动。"); } public void setReceiveCallback(handleReceiveData call) { callback = call; } public void service() throws IOException { while (true) { DatagramPacket dp = new DatagramPacket(new byte[102400], 102400); socket.receive(dp); //接收客户端信息 byte[] data = dp.getData(); callback.handleReceive(data); } } public void start() throws SocketException, IOException { service(); } public void sendMsg(final byte[] data) { Thread send = new Thread(new Runnable() { @Override public void run() { try { if (socket != null) { SocketAddress socketAddres = new InetSocketAddress("192.168.1.110", 8804); socket.send(new DatagramPacket(data, data.length, socketAddres)); } } catch (IOException e) { e.printStackTrace(); } } }); send.start(); } } |

关注我的微信,获取文章更新
如果你觉得这篇文章对你有用,可以点击下面的“赞助作者”打赏作者!
转载注明原文出处:王柏元的博客>>https://wangbaiyuan.cn/local-area-network-lan-simple-udp-video-calls.html
网站不错。还是家门。已被奇草导航收录。