MediaRecorder音视频框架

来源:互联网 发布:用户标签数据库设计 编辑:程序博客网 时间:2024/04/29 23:33
MediaRecorder音视频框架
附几篇学习博客链接:
Camera视频加水印
JNI使用的数据结构JNINativeMethod详解
MPEG4Writer学习博客
Camera结构分析
Android高通平台Camera录制--MPEG4Writer.cpp 简单跟读

阅代码工具:Source Insight
一、API简要说明
1.1 它Android平台上的一套多媒体API,负责音视频编码。里面编码格式集成丰富,视频录制、录音都可以使用它。作为纯APP开发的话,了解一些音视频参数设置及设置顺序就可以使用了。如果是基于平台去做定制的话,就需要对整个框架流程需要一定的熟悉,假如要扩展一个新的接口,或者更改某个接口功能。那么接下来一起来跟读吧。

二、框架图


三、代码跟读流程分析
MediaRecorder.java—>android_media_MediaRecorder.cpp—>mediarecorder.cpp—>
IMediaRecorder.cpp—>MediaRecorderClient.cpp—>StagefrightRecorder.cpp—>MPEG4Writer.cpp

3.1MediaRecorder.java--SDK上封装的接口类
源码路径:frameworks/base/media/java/android/media/MediaRecorder.java
3.1.1 采用setCamera这个接口来进行跟读,注意Camera参数这个比较特殊。System.loadLibrary("media_jni");调用JNI编译出来的libmedia_jni.so库
public class MediaRecorder{    static {        System.loadLibrary("media_jni");        native_init();    }    ...    public native void setCamera(Camera c);    ...}

3.2 android_media_MediaRecorder.cpp--JNI接口类。库名:libmedia_jni.so
源码路径:frameworks/base/media/jni/android_media_MediaRecorder.cpp
3.2.1MediaRecorder.java里面setCamera的JNI接口
static void android_media_MediaRecorder_setCamera(JNIEnv* env, jobject thiz, jobject camera){    // we should not pass a null camera to get_native_camera() call.    if (camera == NULL) {        jniThrowNullPointerException(env, "camera object is a NULL pointer");        return;    }    sp<Camera> c = get_native_camera(env, camera, NULL);    if (c == NULL) {        // get_native_camera will throw an exception in this case        return;    }    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);    process_media_recorder_call(env, mr->setCamera(c->remote(), c->getRecordingProxy()),            "java/lang/RuntimeException", "setCamera failed.");}
3.2.2通过getMediaRecorder获取对象实例,调用下一层setCamera接口。const修饰类类型变量指针,表示其不可重新赋值,一次会话只能实例化一次内存地址。
static sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz){    Mutex::Autolock l(sLock);    MediaRecorder* const p = (MediaRecorder*)env->GetLongField(thiz, fields.context);    return sp<MediaRecorder>(p);}
3.2.3JNI里面添加函数需要注册
static JNINativeMethod gMethods[] = {    {"setCamera",            "(Landroid/hardware/Camera;)V",    (void *)android_media_MediaRecorder_setCamera},    ...};1、第一个字符串表示java层函数名2、()里面java层函数参数类型(L+包名;),括号外面是返回值类型V表示void3、JNI函数指针
// 注册位置// This function only registers the native methods, and is called from// JNI_OnLoad in android_media_MediaPlayer.cppint register_android_media_MediaRecorder(JNIEnv *env){    return AndroidRuntime::registerNativeMethods(env,                "android/media/MediaRecorder", gMethods, NELEM(gMethods));}

3.3 mediarecorder.cpp--就是上一层getMediaRecorder实例化的对象
源码路径:frameworks/av/media/libmedia/mediarecorder.cpp
3.3.1上面JNI中的android_media_MediaRecorder_setCamera函数mr->setCamera(c->remote(), c->getRecordingProxy()
status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy){    ALOGV("setCamera(%p,%p)", camera.get(), proxy.get());    if (mMediaRecorder == NULL) {        ALOGE("media recorder is not initialized yet");        return INVALID_OPERATION;    }    if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {        ALOGE("setCamera called in an invalid state(%d)", mCurrentState);        return INVALID_OPERATION;    }    status_t ret = mMediaRecorder->setCamera(camera, proxy);    if (OK != ret) {        ALOGV("setCamera failed: %d", ret);        mCurrentState = MEDIA_RECORDER_ERROR;        return ret;    }    return ret;}
3.3.2这部分不是JNI语法,已经是标准C++语法。所以必须要在头文件种声明函数原型。
结合头部文件可以看出,cpp函数里面调用到了IMediaRecorder对象中的setCamera
3.3.3源码路径:frameworks/av/include/media/mediarecorder.h
class MediaRecorder : public BnMediaRecorderClient,                      public virtual IMediaDeathNotifier{public:...    status_t    setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);...private:...    sp<IMediaRecorder>          mMediaRecorder;...};

3.4 IMediaRecorder.cpp--这部分采用了IBinder通信
源码路径:frameworks/av/media/libmedia/IMediaRecorder.cpp
3.4.1首先得在枚举量中添加一个符号常量
enum {    RELEASE = IBinder::FIRST_CALL_TRANSACTION,...    SET_CAMERA,...};
3.4.2实现函数部分
class BpMediaRecorder: public BpInterface<IMediaRecorder>{public:...    status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)    {        ALOGV("setCamera(%p,%p)", camera.get(), proxy.get());        Parcel data, reply;        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());        data.writeStrongBinder(camera->asBinder());        data.writeStrongBinder(proxy->asBinder());        remote()->transact(SET_CAMERA, data, &reply);        return reply.readInt32();    }...};
3.4.3transact调用
status_t BnMediaRecorder::onTransact(                                     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    switch (code) {        case SET_CAMERA: {            ALOGV("SET_CAMERA");            CHECK_INTERFACE(IMediaRecorder, data, reply);            sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());            sp<ICameraRecordingProxy> proxy =                interface_cast<ICameraRecordingProxy>(data.readStrongBinder());            reply->writeInt32(setCamera(camera, proxy));            return NO_ERROR;        } break;        default:            return BBinder::onTransact(code, data, reply, flags);    }}
3.4.4 函数原型
源码路径:frameworks/av/include/media/IMediaRecorder.h
class IMediaRecorder: public IInterface{public:    ...    virtual status_t setCamera(const sp<ICamera>& camera,                               const sp<ICameraRecordingProxy>& proxy) = 0;    ...};

3.5 MediaRecorderClient.cpp
源码路径:frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp
3.5.1这里的mRecorder是MediaRecorderBase类变量指针,而MediaRecorderBase只是一个.h头文件。
它是一个基类,定义了函数原型,由StagefrightRecorder去继承实现,从这里看出接下来调到了StagefrightRecorder里面的setCamera具体实现。
status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,                                        const sp<ICameraRecordingProxy>& proxy){    ALOGV("setCamera");    Mutex::Autolock lock(mLock);    if (mRecorder == NULL) {        ALOGE("recorder is not initialized");        return NO_INIT;    }    return mRecorder->setCamera(camera, proxy);}
3.5.2 MediaRecorderClient.cpp函数原型
源码路径:frameworks/av/media/libmediaplayerservice/MediaRecorderClient.h
class MediaRecorderClient : public BnMediaRecorder{public:    virtual     status_t   setCamera(const sp<ICamera>& camera,                                    const sp<ICameraRecordingProxy>& proxy);    ...    MediaRecorderBase      *mRecorder;};

3.6 StagefrightRecorder.cpp--看到了这里也就马上到尽头了,MPEG4Writer封装类就是在这里实例化的。
源码路径:frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp
3.6.1mCamera这个全局首先会在setupCameraSource配置,setupCameraSource会在setupMediaSource进行调用,这里不co代码出来了。
status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera,                                        const sp<ICameraRecordingProxy> &proxy) {    ALOGV("setCamera");    if (camera == 0) {        ALOGE("camera is NULL");        return BAD_VALUE;    }    if (proxy == 0) {        ALOGE("camera proxy is NULL");        return BAD_VALUE;    }    mCamera = camera;    mCameraProxy = proxy;    return OK;}
3.6.2实例化文件封装类,准备进入封装流程
status_t StagefrightRecorder::setupMPEG4orWEBMRecording() {    ...    writer = new MPEG4Writer(mOutputFd);    ...    // 实例化对象之后调用setupMediaSource把参数设置下去}
3.6.3 函数原型:
源码路径:frameworks/av/media/libmediaplayerservice/StagefrightRecorder.h
<span style="font-size:14px;">struct StagefrightRecorder : public MediaRecorderBase {    ...    virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);    ...}</span>
3.6.4 跟读到这差不多了,根据流程可以添加自己想要添加的接口了。从这里就可以调用到MPEG4Writer.cpp
例如:
status_t StagefrightRecorder::test() {    if (mWriter == NULL) {        ALOGE("File writer is not avaialble");    }    mWriter->test();    return OK;}

3.7 MPEG4Writer.cpp--媒体文件封装类,这个cpp需要单独拿出来讲,所以这里不做过多介绍。阅读此封装类之前需要熟悉多媒体文件封装流程。
源码路径:frameworks/av/media/libstagefright/MPEG4Writer.cpp
源码路径:frameworks/av/include/media/stagefright/MPEG4Writer.h

0 0
原创粉丝点击