Android MediaRecorder架构详解

1. 简介
在android中录制音频有两种方式,MediaRecorder和AudioRecord。两者的区别如下:
(1) MediaRecorder
简单方便,不需要理会中间录制过程,结束录制后可以直接得到音频文件进行播放;录制的音频文件是经过压缩的,需要设置编码器;录制的音频文件可以用系统自带的播放器播放。
(2) AudioRecorder
在声音录制过程中,可以处理采集的声音数据,如降噪、合成等。过程为一段一段进行录制然后得到数据分别进行处理。录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。

本文主要详解MediaRecorder架构,从上层调到StagefrightRecorder的流程以及应用层录音接口调用的流程。(注:本次分析基于android4.4.2源码)

 

2. 应用层录音接口调用流程

(1)     调用new MediaRecorder()构造函数得到实例。

(2)     调用setOutputFormat()设定媒体文件的输出格式。

(3)     调用setAudioSource()设定音频的录入源以及调用setAudioEncoder()设定音频的编码方式。

(4)     调用setOutputFile()设定记录的媒体文件保存的路径。

(5)     调用prepare()准备录制。

(6)     调用start()开始录制。

(7)     记录完成后,调用stop()停止录制。

 

3. 应用层调到StagefrightRecorder的流程

如图1所示,MediaRecorder在运行时,可以分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现IPC通讯。

  Android MediaRecorder架构详解

 图1 录音从Java层调到StagefrightRecorder的流程图

 

(1) 手机启动时会启动进程/system/bin/mediaserver。该进程会把media相关服务注册到ServiceManager中,如MediaPlayerService。

(/frameworks/av/media/mediaserver/main_mediaserver.cpp)

 Android MediaRecorder架构详解

 

 

 

 

 

(/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp)

 Android MediaRecorder架构详解

 

 

(2)应用层创建MediaRecorder实例:mMediaRecorder = new MediaRecorder(); 调用SDK中MediaRecorder.java

(frameworks\base\media\java\android\media\MediaRecorder.java)

 Android MediaRecorder架构详解

 

 

 

 

 

 

 

 

通过JNI方式调用到framework层android_media_MediaRecorder.cpp。

(\frameworks\base\media\jni\android_media_MediaRecorder.cpp)

 Android MediaRecorder架构详解

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(3) 继而调用mediarecorder.cpp的构造函数,它首先会从ServiceManager中获得MediaPlayerService服务,然

后通过服务来创建recorder。这个recorder就是录音的真实实例。

 (frameworks\av\media\libmedia\mediarecorder.cpp)

 Android MediaRecorder架构详解

 

 

 

 

 

 

 

(4) 通过getMediaPlayerService得到的service其实是BpMediaPlayerService,它和mediaserver进程中的BnMediaPlayerService是相对应的,共同负责进程间binder通信。BpMediaPlayerService中的createMediaRecorder其实是通过binder机制将CREATE_MEDIA_RECORDER消息发送出去。

(/frameworks/av/media/libmedia/IMediaPlayerService.cpp)

 Android MediaRecorder架构详解

 

 

 

 

(5)在BnMediaPlayerService中,通过onTransact()来处理接收到的消息,并返回结果。当接收消息中的code为CREATE_MEDIA_RECORDER时,调用MediaPlayerService 中的createMediaRecorder函数。在该函数中创建了一个MediaRecorderClient的实例,也就是说MediaPlayerService会为每个client应用进程创建一个相应的MediaRecorderClient的实例,来提供服务。

(/frameworks/av/media/libmedia/IMediaPlayerService.cpp)

 Android MediaRecorder架构详解

 

 

 

 

 

 

 Android MediaRecorder架构详解

 

 

 

 Android MediaRecorder架构详解

 

(/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp)

 Android MediaRecorder架构详解

 

 

 

(6)如此MediaRecorder.cpp就得到了一个recorder的实例,对它来说这个实例和本地的其他类的实例没什么用法上的区别,但其实这个实例是运行在另外一个进程中。实现这种假象的就是binder机制。在MediaRecorderClient的构造函数中,才会真正的创建StagefrightRecorder的具体实例,即真正的录制对象,使用的StageFright多媒体框架。在android 4.0以后只有StagefrightRecorder一个录制框架。在2.2、2.3中还存在另外一个录制对象PVMediaRecorder,使用的是OpenCore框架实现录音或录像。

(/frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp)

 Android MediaRecorder架构详解

 

 

 

图2是录音创建实例的时序图

 Android MediaRecorder架构详解

图2 录音创建实例的时序图

 

4. Application Framework层与libraries层录音函数对应关系

mMediaRecorder = new MediaRecorder();

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);

mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);

mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

mMediaRecorder.setOutputFile(recordFile.getAbsolutePath());

mMediaRecorder.prepare(); 

mMediaRecorder.start();

mMediaRecorder.stop();

mMediaRecorder.release();

 

sp<MediaRecorder> mr = new MediaRecorder();

mr->setAudioSource(1);  //MIC = 1

mr->setOutputFormat(0); //DEFAULT = 0;

mr->setAudioEncoder(0);//DEFAULT = 0;

mr->setOutputFile(fos.getFD(), 0, 0);

mr->prepare();

mr->start();

mr->stop();

mr->release();

 

5. 总结

通过对android mediarecorder架构的详解,了解各模块调用的流程,不仅可以实现在应用层调用录音接口进行录音,还能直接调用libraries层录音接口函数进行C层录音。同时,若需要监控录音,则可以Hook系统进程/system/bin/mediaserver的ioctl函数,从而拦截该进程的binder通信过程,通过解析binder通信数据包,就可以监控到手机中所有录音软件的录音行为。

 

6. 参考资料

[1]Android录音MediaRecorder/AudioRecorder相关总结:

http://www.360doc.com/content/12/0919/19/10764837_237084032.shtml

[2]MediaRecorder和AudioRecord的区别和联系:

http://blog.csdn.net/ameyume/article/details/7885744

[3]MediaRecorder类介绍:http://blog.csdn.net/mark_dev/article/details/7249415

[4]AndroidXRef:http://androidxref.com/

 

周梦婷

2014/12/5

原创文章,作者:admin,如若转载,请注明出处:https://www.isclab.org.cn/2014/12/07/android-mediarecorder%e6%9e%b6%e6%9e%84%e8%af%a6%e8%a7%a3/

(5)
adminadmin
上一篇 2014年12月1日
下一篇 2014年12月11日

相关推荐

  • TCP之可靠数据传输

          TCP协议是面向连接的可靠数据传输协议,如何在不可靠协议IP协议的上层实现可靠数据传输,主要通过差错检验、分…

    学术报告 2018年4月10日
    1.3K
  • 基于神经网络的源代码表示方法

    简介:神经网络算法在自然语言和计算机视觉等领域取得了快速发展和成熟应用,且在程序分析领域也具有广泛应用,如代码克隆检测、程序分类、漏洞分析和代码搜索等任务。然而不同的程序源代码表示…

    2020年7月19日
    1.8K
  • 敏感文本数据脱敏方法

    本次报告对文本数据的脱敏方法展开介绍,介绍了目前常用的文本数据脱敏方法,重点讲解了文本数据泛化脱敏的基本概念,详细阐述了文本泛化脱敏方法和文本差分隐私噪声扰动脱敏方法,最后对比了文…

    2022年5月30日
    2.5K
  • 代码异味检测

    本次学术报告对以往实验室软件系统/代码质量评估的研究方向做了一个总结并引出新的概念:代码异味检测。针对代码异味概念,生成原因和研究最新的方向进行了探讨。同时结合两篇论文,从多异味检…

    2023年6月5日
    1.6K
  • 动态网络嵌入方法研究

    传统的网络表示一般使用高维的稀疏向量,但是局限在于难以度量节点间的相似性,而一般的静态网络嵌入方法,忽略网络的动态演化过程,因此提出了基于动态网络的嵌入方法学习。本次将基于深度自编…

    2021年6月14日
    1.5K
  • 面向NIDS的流量对抗样本检测

    在AI攻击复杂性和密集性不断提升的大背景下,ML-NIIDS面临巨大挑战,其中流量对抗样本严重威胁其安全稳定。本次报告从NIDS的迭代发展,聚焦到对抗性安全威胁,再引出主流流量对抗…

    2023年10月23日
    1.4K
  • 文本安全

    动态规划——最小编辑代价 序列标注模型 命名实体识别简介 文本表示方法(一)——空间向量模型 文本表示方法(二)——潜在语义分析 文本表示方法(三)——topic models i…

    学术报告 2014年10月18日
    1.1K
  • 音频事件识别参数优化方法

    目前音频处理领域各种系统的参数优化研究,通常把系统的各个层次(一般包括特征提取、特征向量生成、模型训练等)割裂开来进行相互独立的参数寻优,再将独立寻优结果进行简单组合,构成系统的参…

    2015年1月28日
    1.3K
  • 走近特定音频识别(之四)—— 训练和识别

    上篇文章介绍了“识别”和“检索”的区别和关系,从这篇开始,我们将从更近的距离接触特定音频识别,本文将向大家介绍特定音频识别系统的基本构成。     一个典型的特定音频识别系统的原理…

    2014年10月28日
    1.4K
  • 深度学习模型校准技术

    深度学习模型校准技术是模型预测可靠性的重要保障手段之一,其通过正则化或后处理方法调节模型对样本实例上的置信度,使其与预测的真实概率良好匹配。本次报告介绍了深度学习模型校准的基本概念…

    2024年7月2日
    1.6K