通过MediaProjectionManager采集android屏幕视频流,app中搭建简单rtsp server与客户端通信,通过rtp 协议传输视频流,vlc等客户端来观看手机的屏幕实时视频
android 5.0 增加了 MediaProjectionManager,通过它我们可以简单的完成录屏的需求。
本文会简单介绍 MediaProjectionManager 的使用流程,通过 MediaCodec 获取到的 264 数据
通过调用 getSystemService 方法获取 MediaProjectionManager 的实例
/**
* 初始化MediaProjectionManager
* **/
private void InitMPManager(){
mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
}
获取到 MediaProjectionManager 的实例后, 通过 createScreenCaptureIntent 方法获取 Intnent,通过 startActivityForResult 启动 Intent
//开始截屏
private void StartScreenCapture(){
Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, REQUEST_CODE_A);
}
通过 startActivityForResult 启动 intent 后,在 onActivityResult 的回掉中获取 MediaProjection 的实例,这时候要开始初始化 MediaCodec 了,通过 MediaCodec 可以拿到 Surface 对像,通过 MediaProjection 对象的 createVirtualDisplay 方法,拿到 VirtureDisplay 对象,拿这个对象的时候,需要把 Surface 对象传进去。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
try {
MediaProjection mediaProjection =
mMediaProjectionManager.getMediaProjection(resultCode, data);
}
catch (Exception e){
}
}
try{
MediaFormat format = MediaFormat.createVideoFormat(Constant.MIME_TYPE,
Constant.VIDEO_WIDTH, Constant.VIDEO_HEIGHT);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, Constant.VIDEO_BITRATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, Constant.VIDEO_FRAMERATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, Constant.VIDEO_IFRAME_INTER);
mEncoder = MediaCodec.createEncoderByType(Constant.MIME_TYPE);
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mSurface = mEncoder.createInputSurface();
mEncoder.start();
}catch (IOException e){
}
mVirtualDisplay =mMediaProjection.createVirtualDisplay(TAG + "-display",
Constant.VIDEO_WIDTH,
Constant.VIDEO_HEIGHT,
Constant.VIDEO_DPI,
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
mSurface,
null, null);
通过 MediaCodec 获取 264 的代码,可以参考我的这个项目:Github
或者参考我之前的博客内容:android 编码 h264(二):MediaCodec 硬编码 h264(硬编码)
MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
while (outputBufferIndex >= 0){
ByteBuffer outputBuffer = mEncoder.getOutputBuffers()[outputBufferIndex];
byte[] outData = new byte[mBufferInfo.size];
outputBuffer.get(outData);
if(mBufferInfo.flags == 2){
configbyte = new byte[mBufferInfo.size];
configbyte = outData;
}else if(mBufferInfo.flags == 1){
byte[] keyframe = new byte[mBufferInfo.size + configbyte.length];
System.arraycopy(configbyte, 0, keyframe, 0, configbyte.length);
System.arraycopy(outData, 0, keyframe, configbyte.length, outData.length);
if(outputStream != null){
outputStream.write(keyframe, 0, keyframe.length);
}
}else{
if(outputStream != null){
outputStream.write(outData, 0, outData.length);
}
}
mEncoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
}
到此,就基本结束了,写这个是为了一个项目做基础准备的,这个项目要解决如下问题:
不知道大家有没有遇到过,app 开发完成后要给领导或者客户演示,如果领导在还好,如果不在,那么就会通过本地录像的方式来演示,我像通过 rtsp 或者 rtmp 流媒体的方式,将屏幕内容来实时的演示,目前项目才开始,代码会慢慢提交的。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。