栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MediaRecorder

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MediaRecorder

MediaRecorder 一、简介

使用MediaRecorder能够编写从设备麦克风与相机捕获音视频、保存音视频并(使用MediaPlayer)进行播放的应用。


(1) MediaRecorder

简单方便,不需要理会中间录制过程,结束录制后可以直接得到音频文件进行播放;录制的音频文件是经过压缩的,需要设置编码器;录制的音频文件可以用系统自带的播放器播放。

(2) AudioRecord

在声音录制过程中,可以处理采集的声音数据,如降噪、合成等。过程为一段一段进行录制然后得到数据分别进行处理。录制的是PCM格式的音频文件,需要用AudioTrack来播放,AudioTrack更接近底层。

二、权限申请

注意:在Android6.0以上权限动态申请


三、MediaRecorder状态机


四、基本使用
if (Textutils.equals(text, b:"开始")){
  btn_opt.setText("结束");
  Camera camera = Camera.open();
  //设置预览时摄像头的角度
  camera.setDisplayorientation(90);
  camera.unlock();
  mediaRecorder = new MediaRecorder();
  mediaRecorder.setCamera(camera);
  mediaRecorder.setAudioSource(MediaRecorder.AudioSource.NIC);//设置音频源麦克风
  mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CANIERA);//设备视频源摄像头
  mediaRecorder.setoutputFormat(NediaRecorder.OutputFormat.MPEG_4);//指定视频文件格式
  
  mediaRecorder.setAudioEncoder(NediaRecorder.AudioEncoder.AAC);
  mediaRecorder.setVideoEncoder(MediaRecorder. VideoEncoder.H264);
  //设置播放录像文件时的角度
  mediaRecorder.setOrientationHint(90);
  
  //设置视频鹚出文件
  mediaRecorder.setOutputFile(new File(getExternalFilesDir( type:""),child:"a.mp4" ).getAbsolutePath());
  mediaRecorder.setVideosize( width: 640,height:480);
  mediaRecorder.setPreviewDisplay(new Surface(textureView.getSurfaceTexture()));
  

  try{
    mediaRecorder.prepare();
  }catch (IOException e){
    e.printstackTrace();
  }
  mediaRecorder.start();
else {
  btn_opt.setText(“开始");
  mediaRecorder.stop();
  mediaRecorder.release();
  camera.stopPreview();
  camera.release();
}




五、MediaRecorder创建过程


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

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



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

void MediaPlayerService::instantiate() {
  defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());
}


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

(frameworksbasemediajavaandroidmediaMediaRecorder.java)


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



(3)继而调用mediarecorder.cpp的构造函数,它首先会从ServiceManager中获得MediaPlayerService服务,然后通过服务来创建recorder。这个recorder就是录音的真实实例。


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

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


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

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

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

sp MediaPlayerService::createMediaRecorder(){
pid_t pid = IPCThreadState::self()->getCallingPid();
sp recorder = new MediaRecorderClient(this, pid); wp w = recorder;
Mutex::Autolock lock(mLock);    
mMediaRecorderClients.add(w);
ALOGV("Create new media recorder client from pid %d", pid);
return recorder; }

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

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


							录音创建实例的时序图

六、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 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();


七、MediaRecorder实例创建过程总结

**MediaRecorder.java # new MediaRecorder(),构造函数里会调用到android_media_MediaRecorder.cpp **

**–> android_media_MediaRecorder.cpp # new MediaRecorder(),从而调用到mediarecorder.cpp **

**–> mediarecorder.cpp # getMediaPlayerService().createMediaRecorder(), getMediaPlayerService()实则是在ServiceManager中获得的BpMediaPlayerService,调用createMediaRecorder()其实是通过binder机制将CREATE_MEDIA_RECORDER消息发送出去 **

**–> IMediaPlayerService.cpp # createMediaRecorder(),这里其实都是BpMediaPlayerService正在执行remote() ->transact(CREATE_MEDIA_RECORDER),将CREATE_MEDIA_RECORDER消息通过binder发送出去 **

**–> IMediaPlayerService.cpp # onTransact(),这里是BnMediaPlayerService在进行处理,当消息为CREATE_MEDIA_RECORDER时,调用MediaPlayerService 中的createMediaRecorder函数 **

**–> MediaPlayerService.cpp # createMediaRecorder(),在里面创建MediaRecorderClient实例 **

–> MediaPlayerService.cpp # new StagefrightRecorder(),创建真正的录制对象。


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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/324780.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号