MediaRecorder音视频框架
16lz
2021-01-23
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.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库
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接口
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()
3.4 IMediaRecorder.cpp--这部分采用了IBinder通信 源码路径:frameworks/av/media/libmedia/IMediaRecorder.cpp 3.4.1 首先得在枚举量中添加一个符号常量
3.5 MediaRecorderClient.cpp 源码路径:frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp 3.5.1 这里的mRecorder是MediaRecorderBase类变量指针,而MediaRecorderBase只是一个.h头文件。
它是一个基类,定义了函数原型,由StagefrightRecorder去继承实现,从这里看出接下来调到了StagefrightRecorder里面的setCamera具体实现。
3.6 StagefrightRecorder.cpp--看到了这里也就马上到尽头了,MPEG4Writer封装类就是在这里实例化的。
源码路径:frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp 3.6.1 mCamera这个全局首先会在setupCameraSource配置, setupCameraSource会在setupMediaSource进行调用,这里不co代码出来了。
3.7 MPEG4Writer.cpp--媒体文件封装类,这个cpp需要单独拿出来讲,所以这里不做过多介绍。阅读此封装类之前需要熟悉多媒体文件封装流程。
源码路径:frameworks/av/media/libstagefright/MPEG4Writer.cpp 源码路径:frameworks/av/include/media/stagefright/MPEG4Writer.h
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.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.hclass 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
更多相关文章
- Android 源码中添加自定义服务并提供给上层使用
- Android 依赖注入函数库Roboguice(一)
- Android中IntentService的使用及其源码解析
- android app 缓存路径
- Android 的反编译 (附愤怒的小鸟源码下载)
- android源码开发
- android launcher源码分析
- Android异步加载源码示例