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表示void
3、JNI函数指针
// 注册位置
// This function only registers the native methods, and is called from
// JNI_OnLoad in android_media_MediaPlayer.cpp
int 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