Android30分钟 DIY搭建局域网视频直播演示Demo

        如今移动直播如火如荼的一片大火。而直播技术也层出不穷,各类开源的,收费的直播SDK平台也很多。以上全部种种,虽然能够快速的实现直播功能,但对于本身技术的积累和学习并无什么好处。本例子经过不借助任何框架。纯手打代码的模式。全部代码皆可编辑查看方便本身学习和积累。服务器

       手机直播的原理很简单。就是经过手机带有的Camera模块。获取到Camera的数据,而后经过网络,发送到服务器。服务器再经过广播,推送到其余客户端。主要涉及到采集数据,发送数据,广播数据,客户端接受数据,再显示数据。以下图所示,视频直播离不开视频采集,原始的视频数据太大了,须要进行视频处理,处理后再压缩,节省宝贵的宽带,最后进行推流,推出去。网络


       以上,说的很简单。其实实际操做起来,有好多技术问题要处理。普通的手机若是打开数据录像,10s的数据就有100多兆。如何处理这样的数据就设计到编码问题。这是一个比较大的坑。另外,还有就是带宽问题了。不管你编码压缩的多好,用户量若是上去,其带宽使用是至关可观。不一样地域,不一样电信提供商的都要考虑。另外就是服务器并发推送的处理。10万个用户和500万的用户视频推送处理是个不小的挑战。而本文对于以上问题都不作讨论。仅仅是个局域网手机直播demo。架构

代码架构并发


      先说下实现原理。经过调用Android Camera,经过onReviewListener进行数据的获取。框架

camera.setPreviewCallback(new Camera.PreviewCallback() {

					@Override
					public void onPreviewFrame(byte[] data, Camera camera) {
						//获取当前的屏幕预览的像素 长与高
						int mWidth = camera.getParameters().getPreviewSize().width;
						int mHeight = camera.getParameters().getPreviewSize().height;
						Log.e(TAG, "mWidth >" + mWidth + " mHeight" + mHeight);
						Log.e(TAG, "data length >" + data.length);
						// int[] buf = imageUtilEngine.decodeYUV420SP(data,
						// mWidth,
						// mHeight);

						// 对要发送的数据进行封装 进行 TLV 格式的封装 TAG L length V 长度
						// TAG 为: width 0xF0 0xFF, height 0xF1 0xFF, data 0xF2
						// 0xFF
						// 为了方便查询 0xF0 0xFF 为 开始标志位 。+(width 4位)+(height 4位)+
						// (data长度 4 位) + data
						
						//对获取的数据进行打包处理
						int length = 2 + 4 + 4 + 4 + data.length;
						ByteBuffer bb = ByteBuffer.allocate(length);

						bb.put(new byte[] { (byte) 0xF0, (byte) 0xFF });

						bb.put(Utils.intToBytes2(mWidth));
						bb.put(Utils.intToBytes2(mHeight));
						bb.put(Utils.intToBytes2(data.length));

						bb.put(data);
						//执行发送命令操做
						sendData(bb.array());
					}
				});

以上是一种获取预览信息的方式。除了此种方式,还有经过MediaRecorder的方式。获取视频信息。ide

还有一种直接把SurfaceView引用传下去,使用NDK调用Camera,直接获取数据源信息。学习

此种方式效率最高。可是这是Android工程师要求熟练NDK操做。编码

考虑过没,那个预览得到的数据是什么数据?spa

这个是大名鼎鼎的YUV数据。你搜索下这种数据格式。它算是各类视频流获取的第一手数据。原生数据。.net

对于YUV数据如何在客户端显示出来呢?这就是另外一个问题了。理论上SurfaceView能够直接显示的。可是Java层并无提供

相关接口。你须要调用NDK层里实现。





没写完,待续

代码工程:

http://download.csdn.net/detail/a315823806/9699223