MediaRecorder音视频框架 附几篇学习博客链接: Camera视频加水印
JNI使用的数据结构JNINativeMethod详解
MPEG4Writer学习博客
Camera结构分析
Android高通平台Camera录制--MPEG4Writer.cpp 简单跟读

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

二、框架图 MediaRecorder音视频框架_第1张图片

三、代码跟读流程分析 MediaRecorder.java—>android_media_MediaRecorder.cpp—>mediarecorder.cpp—> IMediaRecorder.cpp—>MediaRecorderClient.cpp—>StagefrightRecorder.cpp—>MPEG4Writer.cpp
3.1 MediaRecorder.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.1 MediaRecorder.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 c = get_native_camera(env, camera, NULL);    if (c == NULL) {        // get_native_camera will throw an exception in this case        return;    }    sp 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 getMediaRecorder(JNIEnv* env, jobject thiz){    Mutex::Autolock l(sLock);    MediaRecorder* const p = (MediaRecorder*)env->GetLongField(thiz, fields.context);    return sp(p);}
3.2.3 JNI里面添加函数需要注册
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& camera, const sp& 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& camera, const sp& proxy);...private:...    sp          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{public:...    status_t setCamera(const sp& camera, const sp& 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.3 transact调用
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 camera = interface_cast(data.readStrongBinder());            sp proxy =                interface_cast(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& camera,                               const sp& 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& camera,                                        const sp& 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& camera,                                    const sp& proxy);    ...    MediaRecorderBase      *mRecorder;};

3.6  StagefrightRecorder.cpp--看到了这里也就马上到尽头了,MPEG4Writer封装类就是在这里实例化的。
源码路径:frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp 3.6.1 mCamera这个全局首先会在setupCameraSource配置, setupCameraSource会在setupMediaSource进行调用,这里不co代码出来了。
status_t StagefrightRecorder::setCamera(const sp &camera,                                        const sp &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
struct StagefrightRecorder : public MediaRecorderBase {    ...    virtual status_t setCamera(const sp& camera, const sp& proxy);    ...}
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

更多相关文章

  1. Android 源码中添加自定义服务并提供给上层使用
  2. Android 依赖注入函数库Roboguice(一)
  3. Android中IntentService的使用及其源码解析
  4. android app 缓存路径
  5. Android 的反编译 (附愤怒的小鸟源码下载)
  6. android源码开发
  7. android launcher源码分析
  8. Android异步加载源码示例

随机推荐

  1. Android(安卓)AlertDialog背景透明
  2. android仿照ipone的弹性效果
  3. android 自定义对话框宽不能占满父layout
  4. android new feature on 4.2
  5. android 颜色(color)
  6. Install ADB And Fastboot Android(安卓)
  7. Android文件合并时,打包出错
  8. 【Android深入解析】Manifest配置文件解
  9. android 自定义水平的ProgressBar
  10. android 程序崩溃后重启