音视频6.3——安卓录屏实现编码成h264文件
音视频开发路线:
Android 音视频开发入门指南_Jhuster的专栏的技术博客_51CTO博客_android 音视频开发入门
demo地址:
GitHub - wygsqsj/videoPath: 音视频学习路线demo
录屏功能
录屏需要通过系统构建的Intent再通过startActivityForResult跳转,从回调中拿到MediaProjection,并为他指定Surface,我们的录屏数据就会写入到这个Surface中
1.获取录屏API
private MediaProjection mMediaProjection; //录屏api
private MediaProjectionManager mediaManager;
//google新版请求回调,用于替换startActivityForResult
private ActivityResultLauncher<Intent> resultLauncher;private void initMediaProjection() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mediaManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);//代替startActivityForResultresultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),result -> {if (result.getData() != null) {mMediaProjection = mediaManager.getMediaProjection(result.getResultCode(), result.getData());startDisplay();}});}
}@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)public void screenRecording(View view) {if (mScreenEncode.getText().toString().contains("开始录屏")) {resultLauncher.launch(mediaManager.createScreenCaptureIntent());} else {screenThread.stopEncode();mScreenEncode.setText("开始录屏");screenThread = null;}}
2.将MediaProjection传递给编码线程配置
out264File = new File(demo6Activity.getExternalFilesDir(Environment.DIRECTORY_MOVIES), "cameraOfScreen.h264");
out264File.createNewFile();
fos = new FileOutputStream(out264File);
//构建对应的MeidaFormat
MediaFormat mediaFormat = MediaFormat.createVideoFormat(encodeMine, width, height);
//注意此处要设置成surface类型
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
//比特率
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, width * height * 5);
//描述视频格式的帧速率
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
//关键帧之间的间隔,此处指定为1秒
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);//构建编码h264MediaCodec
encodeCodec = MediaCodec.createEncoderByType(encodeMine);
encodeCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
inputSurface = encodeCodec.createInputSurface();
initVirtualDisplay();
MediaCodec.BufferInfo encodeBufferInfo = new MediaCodec.BufferInfo();//用于描述解码得到的byte[]数据的相关信息
//启动编码器
encodeCodec.start();
MideaFormat的配置项也要相应的改变:
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void initVirtualDisplay() {mMediaProjection.createVirtualDisplay(LOG_TAG, //virtualDisplay 的名字,随意写width,height,demo6Activity.getResources().getDisplayMetrics().densityDpi, // virtualDisplay 的 dpi 值,这里都跟应用保持一致即可// 显示的标志位,不同的标志位DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,inputSurface, //获取内容的 surfacenull, //回调null); //回调执行的handler}
将MediaCodec构建的Surface传递给MediaProjection,这样MediaCodec只需要从OutPutBuffer中取出编码好的264数据即可,不再需要手动为MediaCodec输入数据了
3.取出数据写入文件
while (isEncode) {int outputIndex = encodeCodec.dequeueOutputBuffer(encodeBufferInfo, 10000);//返回当前筐的标记switch (outputIndex) {case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:Log.i(LOG_TAG, "输出的format已更改" + encodeCodec.getOutputFormat());break;case MediaCodec.INFO_TRY_AGAIN_LATER:Log.i(LOG_TAG, "超时,没获取到");break;case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:Log.i(LOG_TAG, "输出缓冲区已更改");break;default:Log.i(LOG_TAG, "获取到surface中的数据,当前解析后的数据长度为:" + encodeBufferInfo.size);//获取所有的筐ByteBuffer[] outputBuffers = encodeCodec.getOutputBuffers();//拿到当前装满火腿肠的筐ByteBuffer outputBuffer;if (Build.VERSION.SDK_INT >= 21) {outputBuffer = encodeCodec.getOutputBuffer(outputIndex);} else {outputBuffer = outputBuffers[outputIndex];}//将数据读取到outData中byte[] outData = new byte[encodeBufferInfo.size];outputBuffer.get(outData);//当前是初始化编解码器数据,不是媒体数据,sps、pps等初始化数据if (encodeBufferInfo.flags == BUFFER_FLAG_CODEC_CONFIG) {Log.i(LOG_TAG, "获取到初始化编解码器数据,长度为:" + encodeBufferInfo.size);configByte = new byte[encodeBufferInfo.size];configByte = outData;} else if (encodeBufferInfo.flags == BUFFER_FLAG_KEY_FRAME) {//当前的数据中包含关键帧数据Log.i(LOG_TAG, "获取到I帧数据,长度为:" + encodeBufferInfo.size);//将初始化数据和当前的关键帧数据合并后写入到h264文件中byte[] keyframe = new byte[encodeBufferInfo.size + configByte.length];System.arraycopy(configByte, 0, keyframe, 0, configByte.length);//把编码后的视频帧从编码器输出缓冲区中拷贝出来System.arraycopy(outData, 0, keyframe, configByte.length, outData.length);fos.write(keyframe, 0, keyframe.length);} else {//写到文件中fos.write(outData, 0, outData.length);}//把筐放回工厂里面encodeCodec.releaseOutputBuffer(outputIndex, false);break;}
}
音视频6.3——安卓录屏实现编码成h264文件相关推荐
- Android限制录制屏幕无声音,哪一个安卓录屏软件可以录制系统的声音
今天介绍的这款软件许多宝宝在之前就已经问过我很多次了,因为没有什么特别好用,所以一直就没有给大家推荐什么,直到今天才来给大家推荐,是因为小编使用了几天之后发现可以介绍给你们录屏大师,因为它操作起来挺简 ...
- android 盒子录屏apk,三种用于安卓录屏的解决方案
本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...
- 安卓录屏软件实现 开维PRA自动生成代码Ctrl.js
安卓录屏软件实现 需求: 1.安卓手机下录制用户操作 2.录制后的动作可以修改 实现原理: 1.利用无障碍权限录制屏幕 2.记录用户点击.滑动等操作 3.将用户的操作转换为Ctrl.js代码实现 录制 ...
- 安卓录屏怎么录?这些方法可以尝试
录屏是一种非常有用的功能,让我们可以轻松地记录下自己的操作,并与他人分享.在安卓设备上,录屏也变得越来越普遍.那么,我们应该如何录制安卓设备的屏幕呢? 安卓录屏的方法 首先,我们需要通过应用程序来实现 ...
- 关于安卓录屏的权限问题
关于安卓录屏的权限问题 首先,Android 4.4之前(不含4.4)是没有录屏功能的,所以在市面上所有的安卓录屏app里,你肯定看不到支持低于Android 4.4版本的安卓录屏app. 另外,An ...
- 视频加密后的录屏行为怎么做防范?
阿酷TONY / 原创 / 长沙2021-09-08 / 视频加密后的录屏行为怎么做防范?我们来了解一下常见的防止录屏操作方法有哪些. 1.防录屏(用户ID跑马灯) 防录屏跑马灯功能,是指通 ...
- 安卓录屏录麦克风ANE screenANE
点击下载 安卓录屏录麦克风ANE可以在AIR as3.0开发的安卓APP中捕获手机屏幕及麦克风,并录制成MP4文件.该演示程序演示了如何调用该ANE,运行后,可以录制一个10分钟的mp4文件,麦克风或 ...
- 计算机录屏幕和声音的软件是什么,可以录制屏幕视频声音的电脑录屏软件是什么?...
可以录制屏幕视频声音的电脑录屏软件是什么? 2019年10月30日 13:20作者:黄页编辑:黄页 分享 录制屏幕视频的声音,一直以来都是广大录屏用户的一项硬性需求.比方说:录制屏幕游戏时需要录制游戏 ...
- 抖音视频模板 创意手机竖屏宣传视频促销PR抖音素材 PR模板网
抖音视频模板 创意手机竖屏宣传视频促销PR抖音素材 Premiere模板素材网 分享您的想法,传播信息,与受众交流,销售产品的最具创意的方式. 高度可定制性使可以根据需要更改模板:更改文本,大小,照片 ...
最新文章
- 《Programming WPF》翻译 第3章 2.处理输入
- 第四百一十七天 how can I 坚持
- 积极打破消极思维模式
- HB-X打不开的解决办法
- [TypeScript] vs code TSLint常见错误解决方案
- 阿里云大数据计算服务MaxCompute命令行工具——odpscmd的操作使用
- Python list倒序遍历(reversed )
- 『雕虫小技』用 Zend Guard 加密 html 页面
- Android Wear 发布 4 年终改名,继续艰难存活
- Python读取Access数据库基本操作
- rapidminer java_RapidMiner在Java应用程序中的集成
- Echarts Map地图下钻至县级
- android 恢复出厂设置 时间,安卓恢复出厂设置
- ElasticSearch常用搜索命令整理(长期更新...)
- 80后的北漂IT人:你的未来在哪?该做好打算了!
- CSAPP-Architecture lab
- console和nsh的区别
- 在企业访客管理中引入人脸识别系统有哪些应用?
- scratch双语教师课件文档手册 3.scratch桌面舞台坐标系
- 项目一 国家电力项目思路总结
热门文章
- 复用形式之:委派(delegation)
- RK3399平台开发系列讲解(内核驱动外设篇)6.35、IAM20680陀螺仪介绍
- FPS网络游戏市场分析
- php读取种子信息,php – 发送获取torrent的种子和同伴的scrape请求
- 《C++捷径教程》学习笔记【一】:虚函数
- adxl345取出值怎么算角度_ADXL345测倾斜角(程序)
- WebGIS系列(一):坐标系
- 全国计算机一级office2016版,全国一级计算机基础及MS-Office应用课件2016版.ppt
- Biniware Run V6.1.0 快速启动工具中文版
- 计算机毕业设计Python+uniapp+安卓基于Android健康饮食搭配的设计与实现(WEB+APP+LW)