MediaRecorder音视频框架
来源:互联网 发布:用户标签数据库设计 编辑:程序博客网 时间:2024/04/29 23:33
MediaRecorder音视频框架
附几篇学习博客链接:
Camera视频加水印
JNI使用的数据结构JNINativeMethod详解
MPEG4Writer学习博客
JNI使用的数据结构JNINativeMethod详解
MPEG4Writer学习博客
Camera结构分析
Android高通平台Camera录制--MPEG4Writer.cpp 简单跟读
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));}
源码路径: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;...};
源码路径: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具体实现。
它是一个基类,定义了函数原型,由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;};
源码路径: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;}
源码路径:frameworks/av/media/libstagefright/MPEG4Writer.cpp
源码路径:frameworks/av/include/media/stagefright/MPEG4Writer.h
0 0
- MediaRecorder音视频框架
- 使用MediaRecorder录制音视频
- Android多媒体-MediaRecorder 录制音视频
- Android MediaRecorder之音/视频采集
- Android音视频之MediaRecorder音视频录制
- MediaRecorder录制视频
- 视频刻录代码MediaRecorder
- 视频录制MediaRecorder
- MediaRecorder录制视频
- MediaRecorder录制视频
- 录制视频之MediaRecorder
- Android MediaRecorder视频录制
- MediaRecorder 录制视频
- 录制视频(Surfaceview+MediaRecorder)
- 视频录制-MediaRecorder
- MediaRecorder录制视频
- MediaRecorder之视频录制
- Android MediaRecorder录制视频
- Ubuntu中安装vim插件
- 用微信小应用写了一个简单的健康列表的小案例
- JavaScript判断变量类型:typeof函数与constructor属性异同
- 第九周项目4——-广义表算法库及应用(2)
- Kernel启动流程源码解析 7 rest_init()
- MediaRecorder音视频框架
- winpcap 中出现c:\codes\include\pcap-stdinc.h(79) : error C2144: syn..错误时
- 三种XML解析方式的简单使用
- Yii运用coreseek进行全文检索
- BFS广度优先搜索——入门
- php实时输出内容
- java的运算符
- HDU 5469 Antonidas dfs减枝
- 笔记-CCNA与网络安全 第7章 交换和VLAN