Android的MediaRecorder框架介绍

第一部分 MediaRecorder概述
    Android
MediaRecorder包含了Audiovideo的记录功能,在Android的界面上,MusicVideo两个应用程序都是调用MediaRecorder实现的。
    MediaRecorder
在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaRecorder程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。
    
以开源的Android为例MediaRecorder的代码主要在以下的目录中:
JAVA
程序的路径:
/packages/apps/SoundRecorder/src/com/android/soundrecorder/SoundRecorder.java

JAVA Framework
的路径:
frameworks/base/media/java/android/media/MediaRecorder.java

JAVA
本地调用部分(JNI):
frameworks/base/media/jni/android_media_MediaRecorder.cpp
这部分内容编译成为目标是libmedia_jni.so

主要的头文件在以下的目录中:
frameworks/base/include/media/

多媒体底层库在以下的目录中:
frameworks/base/media/libmedia/ 
这部分的内容被编译成库libmedia.so

多媒体服务部分:
frameworks/base/media/libmediaplayerservice/
MediaRecorder
MeidaPlayer使用相同的服务。

基于OpenCore部分 

PVAuthor是基于OpenCoreAuthorEngineAndroid实现, 代码在以下路径中: external/opencore/android/author

这部分内容被编译成库libopencoreauthor.so

它实现的接口类是PVMediaRecorder.h,这个类基本上是一个封装,它需要处理三个方面的内容:

音频的输入环节(Audio Input

视频的输入(Camera

视频的预览(使用ISurface

其中实现PVMediaRecorder.h的类是PVMediaRecorder.cppauthordriver.hauthordriver.cpp是具体实现,android_audio_input.*android_camera_input.*是两个PvmiMIOControl的实现PvmiMIOControl最终会构建成一个Node.。它们是Active Source类型的Node,因此它们需要实现PvmiMediaTransfer::writeComplete()函数。

android_audio_input.*是作为音频输入的实现,它基于AndroidAudio系统构建,主要使用media/AudioRecord.h接口àAudioRecord.cpp

 

第二部分 MediaRecorder的接口与架构

      MediaRecorder的各个可以用下图的表示:
 
    MediaRecorder部分的头文件在frameworks/base/include/media/目录中,这个目录是和libmedia.so库源文件的目录frameworks/base/media/libmedia/相对应的。主要的头文件有以下几个:

■    mediarecorder.h mediarecorder的上层接口

■    IMediaRecorder.h  MediaRecorder的服务部分实现接口

■    PVMediaRecorder.h MediaRecorder的下层接口,由OpenCore实现

      在这些头文件MediaRecorder.h提供了对上层的接口,而其他的几个头文件都是提供一些接口类(即包含了纯虚函数的类),这些接口类必须被实现类继承才能够使用。

整个MediaRecorder库和调用的关系如下图所示:     整个MediaRecorder在运行的时候,可以大致上分成ClientServer两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现IPC通讯。注意MediaRecorder中不需要使用callback,这点和MediaPlayer的架构有一定的区别,因此并不需要一个MediaRecorderClient的类。

MediaRecorder C语言上层的接口在mediarecorder.h 中,定义一个MediaRecorder类:

复制代码

1.                  class MediaRecorder

2.                  {

3.                  public:

4.                      MediaRecorder();

5.                      ~MediaRecorder();

6.                      status_t    initCheck();

7.                      status_t    setCamera(const sp<ICamera>& camera);

8.                      status_t    setPreviewSurface(const sp<Surface>& surface);

9.                      status_t    setVideoSource(int vs);

10.                   status_t    setAudioSource(int as);

11.                   status_t    setOutputFormat(int of);

12.                   status_t    setVideoEncoder(int ve);

13.                   status_t    setAudioEncoder(int ae);

14.                   status_t    setOutputFile(const char* path);

15.                   status_t    setVideoSize(int width, int height);

16.                   status_t    setVideoFrameRate(int frames_per_second);

17.                   status_t    prepare();

18.                   status_t    getMaxAmplitude(int* max);

19.                   status_t    start();

20.                   status_t    stop();

21.                   status_t    reset();

22.                   status_t    init();

23.                   status_t    close();

24.                   status_t    release();

25.               };

    meidarecorder的上层接口中,基本不涉及数据流的处理,但是需要设置两个重要的部分,一个是输入的设备ICamera,另一个是ICamera的预览(previewSurface

复制代码

1.                      status_t    setCamera(const sp<ICamera>& camera);

2.                      status_t    setPreviewSurface(const sp<Surface>& surface);

    这两个类需要通过上层的接口设置,其中设置的Surface在下层的处理中也会被设置到ICamera的接口中,ICamera则作为这种meidarecorder视频输入的设备,在meidarecorder底层的实现中,通过这个Icamera获取视频流。
prepare()
start()stop()reset()等几个函数用于设置控制媒体记录的运行。
    
另外的几个接口用于设置音频、视频的输入和格式,输出的格式。

第三部分 PVAuthor的架构

    PVAuthor是基于OpenCoreAuthorEngineAndroid实现, 代码在以下路径中:
external/opencore/android/author/
    
它实现的接口类是PVMediaRecorder.h,这个类基本上是一个封装,它需要处理三个方面的内容:
    
音频的输入环节(Audio Input
    
视频的输入(Camera
    
视频的预览(使用ISurface


     其中实现PVMediaRecorder.h的类是PVMediaRecorder.cppauthordriver.hauthordriver.cpp是具体实现,android_audio_input.*android_camera_input.*是两个PvmiMIOControl的实现,PvmiMIOControl最终会构建成一个Node.。它们是Active Source类型的Node,因此它们需要实现PvmiMediaTransfer::writeComplete()函数。
    
AndroidCameraInput内部会建立一个Camera(可以不使用从外部得到的方式);AndroidCameraInput::SetPreviewSurface的函数用于得到一个外部的ISurface,这个Surface将被设置到Camera中,作为Camera的预览。
    android_audio_input.*
是作为音频输入的实现,它基于AndroidAudio系统构建,主要使用media/AudioRecord.h接口。

第四部分 Android MediaRecorderCamera的关系

    从功能的角度MediaRecorder一般包含音频,视频记录,视频预览的功能,Camera包含了取景区预览,静态图像捕获的功能。
    
Android中,应用程序自上而下分成JAVA应用,JAVA框架,JNIC框架,具体实现几个部分。多媒体方面的程序尤其是这样。
    MediaRecorder
CameraAndroid中都有自上而下的架构,它们在顶层JAVA应用层,共用一个应用程序Camera(其中的程序也是独立的),在JAVA框架和JNI层是独立的,主要的联系在于CamerC框架以下的内容被MediaRecorder实现(也就是PVAuthor)所调用,作为MediaRecorder实现的视频输入设备,它的作用是负责传输视频数据和提供显示预览。本身Camera C框架以下的代码基本提供了取景器预览(Preview)、视频数据流获取、静止图像获取三方面的功能,MediaRecorder实现使用其取景器预览和视频数据流获取的功能,而CameraJNI使用其取景器预览和静止图像获取两方面的功能。

3.4 Camera服务libcameraservice.so

 

    frameworks/base/camera/libcameraservice/ 用于实现一个Camera的服务,这个服务是继承ICameraService的具体实现。
    
在这里的Android.mk文件中,使用宏USE_CAMERA_STUB决定是否使用真的Camera,如果宏为真,则使用CameraHardwareStub.cppFakeCamera.cpp构造一个假的Camera,如果为假则使用CameraService.cpp构造一个实际上的Camera服务。
    CameraService.cpp
是继承BnCameraService 的实现,在这个类的内部又定义了类ClientCameraService::Client继承了BnCamera。在运作的过程中CameraService::connect()函数用于得到一个CameraService::Client,在使用过程中,主要是通过调用这个类的接口来实现完成Camera的功能,由于CameraService::Client本身继承了BnCamera类,而BnCamera类是继承了ICamera,因此这个类是可以被当成ICamera来使用的。
    CameraService
CameraService::Client两个类的结果如下所示:

复制代码

1.                  class CameraService : public BnCameraService

2.                  {  

3.                      class Client : public BnCamera {};

4.                      wp<Client>                  mClient;

5.                  }


    CameraService中的一个静态函数instantiate()用于初始化一个Camera服务,函数如下所示:

复制代码

1.                  void CameraService::instantiate() {

2.                      defaultServiceManager()->addService(

3.                              String16("media.camera"), new CameraService());

4.                  }


    事实上,CameraService::instantiate()这个函数注册了一个名称为"media.camera"的服务,这个服务和Camera.cpp中调用的名称相对应。
    Camera
整个运作机制是:在Camera.cpp中可以调用ICameraService的接口,这时实际上调用的是BpCameraService,而BpCameraService又通过Binder机制和BnCameraService实现两个进程的通讯。而BpCameraService的实现就是这里的CameraService。因此,Camera.cpp虽然是在另外一个进程中运行,但是调用ICameraService的接口就像直接调用一样,从connect()中可以得到一个ICamera类型的指针,真个指针的实现实际上是CameraService::Client
    
而这些Camera功能的具体实现,就是CameraService::Client所实现的了,其构造函数如下所示:

复制代码

1.                  CameraService::Client::Client(const sp<CameraService>& cameraService,

2.                          const sp<ICameraClient>& cameraClient) :

3.                      mCameraService(cameraService), mCameraClient(cameraClient), mHardware(0)

4.                  {

5.                      mHardware = openCameraHardware();

6.                      mHasFrameCallback = false;

7.                  }


    构造函数中,调用openCameraHardware()得到一个CameraHardwareInterface类型的指针,并作为其成员mHardware。以后对实际的Camera的操作都通过对这个指针进行。这是一个简单的直接调用关系。
    
事实上,真正的Camera功能己通过实现CameraHardwareInterface类来完成。在这个库当中CameraHardwareStub.hCameraHardwareStub.cpp两个文件定义了一个桩模块的接口,在没有Camera硬件的情况下使用,例如在仿真器的情况下使用的文件就是CameraHardwareStub.cpp和它依赖的文件FakeCamera.cpp
CameraHardwareStub
类的结构如下所示:

复制代码

1.                  class CameraHardwareStub : public CameraHardwareInterface {

2.                      class PreviewThread : public Thread {

3.                      };

4.                  };


    在类CameraHardwareStub当中,包含一个线程类PreviewThread,这个线程用于处理PreView,即负责刷新取景器的内容。实际的Camera硬件接口通常可以通过对v4l2 捕获驱动的调用来实现,同时还需要一个JPEG编码程序将从驱动中取出的数据编码成JPEG文件。

 

发布了1 篇原创文章 · 获赞 2 · 访问量 29万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览