[Android N]MediaRecorder系列之mediaRecorder与StagefrightRecorder

本文深入探讨了MediaRecorder的实现原理,介绍了MediaRecorder如何通过JNI调用底层CPP代码,并重点分析了StagefrightRecorder的作用及其如何整合录制和编码流程。

深入mediaRecorder的实现

因为java层的东西都是通过jni call到底层的cpp,所以我们之间拿cpp层的代码实现,开剖析这个mediaRecorder框架。

这里写图片描述

事实上,MediaRecorder只是一个壳,定义init,start等这些api,实际上的实现不在这里面,实际上call到StagefrightRecorder。这样的写法,也是android系统里面喜闻乐见的,因为这样可以对接到不同的东西。

StagefrightRecorder

看一眼MediaRecorder构造函数,就是可以找到其实MediaRecorde里面的init(),star()函数用到的mMediaRecorder指针,实际上是在指向StagefrightRecorder的一个对象。
所以当调用mMediaRecorder->init()实际上是call到StagefrightRecorder.init()

这里写图片描述

StagefrightRecorder就是一个整合器,他把record和encode的flow,完美的结合在一起,对于
StagefrightRecorder的理解,我后面通过录制一个ts视频流的一个例子来研究,则更容易理解。

使用 `MediaRecorder` 进行录屏时出现黑屏是一个较为常见的问题,尤其在 Android 平台上。其原因可能涉及多个层面,包括 Surface 的获取、区域控制、视频旋转角度设置、以及底层资源的协调等。 ### 黑屏问题的原因分析 1. **Surface 获取方式不当** 在录屏过程中,`MediaRecorder` 通常需要通过 `Surface` 来接收画面数据。如果获取的是全屏的 `Surface`,而实际显示内容并未完全渲染到该区域,则可能导致录制的画面为黑色[^1]。例如,在某些设备上,系统 UI 或状态栏未被正确包含在录制区域内,也可能造成黑屏现象。 2. **未正确设置视频旋转角度** 设备屏幕方向录制方向不一致时,若未调用 `MediaRecorder.setOrientationHint()` 设置合适的旋转角度,可能导致录制的视频方向错误或画面异常,表现为黑屏或画面错位[^1]。 3. **初始化顺序或参数配置错误** `MediaRecorder` 的初始化流程非常关键,若调用顺序错误(如未先调用 `setVideoSource()` 再调用 `setOutputFormat()`),或者设置了设备不支持的分辨率、编码格式等参数,也可能导致无法正常录制画面,从而出现黑屏[^2]。 4. **权限或上下文问题** 录屏功能通常需要申请特殊的权限(如 `CAPTURE_VIDEO_OUTPUT`),且需在特定的上下文中运行(如通过 `MediaProjection` 获取虚拟 Display)。如果权限未正确授予或上下文配置错误,会导致 `Surface` 无法正常输出图像数据。 5. **底层组件协同问题** 根据源码路径分析,`MediaRecorder` 涉及多个系统组件的协作,包括 `StagefrightRecorder.cpp`、`MPEG4Writer.cpp`、`Surface.cpp` 等模块。若其中某一环节未能正确处理图像缓冲区或写入逻辑,也会导致最终输出的视频为黑屏。 --- ### 解决方案建议 1. **确保正确获取并控制 `Surface` 区域** 应根据实际录屏需求,合理配置 `Surface` 的尺寸和位置。例如,通过 `MediaProjection` 创建虚拟 Display 时,应指定正确的宽高和裁剪区域,避免因区域不匹配导致黑屏。 2. **设置合适的视频旋转角度** 使用 `MediaRecorder.setOrientationHint(int degrees)` 方法设置正确的旋转角度,确保录制方向设备当前屏幕方向一致。常见值为 0、90、180、270 度。 3. **遵循正确的初始化流程** 示例代码如下: ```java mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024); mediaRecorder.setVideoFrameRate(30); CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight); mediaRecorder.setOutputFile(outputFilePath); mediaRecorder.prepare(); ``` 4. **检查并适配设备兼容性** 不同设备对分辨率、帧率、编码格式的支持程度不同。可以优先使用 `CamcorderProfile` 提供的标准配置,以提高兼容性。 5. **调试底层日志源码逻辑** 若问题仍存在,可结合系统日志(如 `logcat`)和源码路径中的关键类(如 `StagefrightRecorder.cpp`、`MPEG4Writer.cpp`)进行调试,确认图像数据是否成功传递至编码器并写入文件。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值