[Android N]MediaRecorder系列之mediaRecorder与StagefrightRecorder

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深入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视频流的一个例子来研究,则更容易理解。

<think>我们之前已经讨论过,在Android系统中,Framework层的MediaRecorder(Java/Kotlin API)通过JNI调用Libraries层的原生代码。但需要明确的是,Libraries层中并没有一个名为"MediaRecorder"的类直接对应,而是由多个模块协同工作,包括libmedia中的相关部分,以及更底层的AudioFlinger服务等。 具体到录音功能: - 当使用**MediaRecorder**进行录音时,Framework层的MediaRecorder最终会调用到Libraries层的**StagefrightRecorder**(在libstagefright中)或类似实现(不同Android版本可能不同),而StagefrightRecorder内部会调用**AudioSource**(AudioRecord相关)来获取音频数据。 - 但若开发者直接使用**AudioRecord**类,则是另一条路径:Framework层的AudioRecord通过JNI调用Libraries层的**AudioRecord**(C++类),直接AudioFlinger交互获取原始PCM数据。 因此,针对问题:Framework层的MediaRecorder在录音时,**既不是直接调用Libraries层的MediaRecorder(因为Libraries层没有同名类),也不是直接调用Libraries层的AudioRecord**,而是通过调用Libraries层的**StagefrightRecorder**,再由StagefrightRecorder内部创建并管理一个**AudioSource**对象(该对象封装了AudioRecord底层类似的功能)来获取音频数据。 ### 详细流程 1. **Framework层**:`android.media.MediaRecorder.start()` 2. **JNI层**:调用`android_media_MediaRecorder_start()`(在`android_media_MediaRecorder.cpp`中) 3. **Libraries层**: - JNI函数调用`MediaRecorderClient::start()`(这是一个Binder客户端代理,通过IPC调用MediaPlayerService) - `MediaPlayerService`创建`StagefrightRecorder`实例并调用其`start()`方法。 4. **音频采集**: - `StagefrightRecorder::start()`内部根据配置创建音频源: ```cpp // StagefrightRecorder.cpp (简化) status_t StagefrightRecorder::start() { // 创建AudioSource sp<AudioSource> audioSource = new AudioSource(...); // 将audioSource连接到编码器 mWriter->addSource(audioSource); } ``` - `AudioSource`是`StagefrightRecorder`的内部组件,它通过`AudioRecord`底层接口(`libaudioclient`)获取原始音频流。 ### 关键点 - **间接依赖AudioRecord**:虽然Framework层的MediaRecorder不直接调用Libraries层的AudioRecord,但底层通过`AudioSource`(其实现基于`libaudioclient`的`AudioRecord`)获取数据。 - **为什么不用同名类?** Libraries层没有"MediaRecorder"类,而是由`MediaRecorderClient`(代理)、`StagefrightRecorder`(功能实现)等共同完成。 ### 总结 Framework层的`MediaRecorder`在录音时: 1. 通过JNI调用Native层的媒体服务(如`MediaPlayerService`)。 2. 由`StagefrightRecorder`处理具体逻辑,它内部使用`AudioSource`(封装了类似`AudioRecord`的底层音频采集功能)获取数据。 因此,**Framework层的MediaRecorder依赖于Libraries层的StagefrightRecorder(而非同名类),而StagefrightRecorder内部使用AudioSource,后者基于Libraries层的AudioRecord实现**。 §§相关问题§§ 1. StagefrightRecorderAndroid媒体框架中的主要作用是什么? 2. AudioSource和AudioRecord在底层实现上有何区别联系? 3. 为什么Android设计成MediaRecorder不直接调用AudioRecord而是通过StagefrightRecorder? 4. 使用MediaRecorder和直接使用AudioRecord在性能上有何差异? 5. MediaPlayerService在MediaRecorder的工作流程中扮演什么角色?</think>在Android系统中,Framework层的`MediaRecorder`在录音功能实现上,**主要调用Libraries层的`AudioRecord`而非直接调用同名类**。以下是具体协同机制: ### 关键调用关系 1. **Framework层入口** `android.media.MediaRecorder`的Java/Kotlin API(如`start()`)是开发者直接调用的接口。 2. **JNI桥接层** 通过`android_media_MediaRecorder.cpp`将调用转发到Native层: ```cpp // JNI映射 static const JNINativeMethod gMethods[] = { {"_start", "()V", (void *)android_media_MediaRecorder_start} }; ``` 3. **Libraries层核心调用** - **实际调用对象**:Framework层最终调用`AudioRecord`(位于`libaudioclient`) - **调用路径**: ```mermaid graph LR A[MediaRecorder.start] --> B[JNI _start] B --> C[StagefrightRecorder::start] C --> D[创建AudioSource] D --> E[AudioSource::start] E --> F[AudioRecord::start] ``` 4. **音频数据流** `AudioRecord`直接`AudioFlinger`服务交互,通过共享内存获取原始PCM数据: ```cpp // AudioSource.cpp status_t AudioSource::start() { mRecord->start(); // mRecord是AudioRecord对象 } ``` ### 为什么不是同名类? - **Libraries层无直接对应类**: Android Native层没有名为`MediaRecorder`的类,功能由多个组件协作: - `StagefrightRecorder`:处理媒体封装(如MP4/3GP) - `AudioSource`:音频采集接口 - `AudioRecord`:实际音频流处理核心 - **设计分离原因**: 1. **功能解耦**: - `MediaRecorder`处理高层逻辑(格式封装/状态管理) - `AudioRecord`专注底层音频流(低延迟/硬件交互) 2. **复用性**: `AudioRecord`可被`MediaRecorder`和`AudioRecord` API共用 3. **性能优化**: 直接操作音频流避免多层封装开销 ### 工作流程示例 ```plaintext 应用层 │ ▼ Framework MediaRecorder (Java) │ ▼ (JNI) StagefrightRecorder (C++) → 配置封装格式 │ ▼ 创建AudioSource │ ▼ 调用AudioRecord (C++) → 从AudioFlinger获取PCM │ ▼ 编码器 → 写入文件 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值