通过MediaRecorder源码学习系统源码定位

找到加载的so库

public class MediaRecorder implements AudioRouting,
                                      AudioRecordingMonitor,
                                      AudioRecordingMonitorClient,
                                      MicrophoneDirection
{
    static {
        System.loadLibrary("media_jni");
        native_init();
    }

定位到media_jni源码

media_jni的目录:
告诉你个规律吧!java文件的包名来找到它的JNI文件名。 比如mediaplayer.java 属于android.media.mediaplayer 包 那么JNI 文件就是android_media_mediaplayer.cpp 注意看包名和JNI文件名的对应关系 路径是framework\media\base\jni\

/frameworks/base/media/jni/android_media_MediaRecorder.cpp
然后上面这个类主要是调用/frameworks/av/media/libmedia/mediarecorder.cpp
需要注意一个问题,就是java的native方法名不一定和cpp文件里的一致
在这里插入图片描述

源码跟踪

  • 我们要查找的是prepare方法,按照上面的规律是在android_media_MediaRecorder.cpp。找到定位到该方法
static void
android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
{
    ALOGV("prepare");
    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    if (mr == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    }

    jobject surface = env->GetObjectField(thiz, fields.surface);
    if (surface != NULL) {
        const sp<Surface> native_surface = get_surface(env, surface);

        // The application may misbehave and
        // the preview surface becomes unavailable
        if (native_surface.get() == 0) {
            ALOGE("Application lost the surface");
            jniThrowException(env, "java/io/IOException", "invalid preview surface");
            return;
        }

        ALOGI("prepare: surface=%p", native_surface.get());
        if (process_media_recorder_call(env, mr->setPreviewSurface(native_surface->getIGraphicBufferProducer()), "java/lang/RuntimeException", "setPreviewSurface failed.")) {
            return;
        }
    }
    process_media_recorder_call(env, mr->prepare(), "java/io/IOException", "prepare failed.");
}


可以知道,这里调用到了MediaRecorder

  • 搜索并打开MediaRecorder.cpp
status_t MediaRecorder::prepare()
{
    ALOGV("prepare");
    if (mMediaRecorder == NULL) {
        ALOGE("media recorder is not initialized yet");
        return INVALID_OPERATION;
    }
    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
        ALOGE("prepare called in an invalid state: %d", mCurrentState);
        return INVALID_OPERATION;
    }
    if (mIsAudioSourceSet != mIsAudioEncoderSet) {
        if (mIsAudioSourceSet) {
            ALOGE("audio source is set, but audio encoder is not set");
        } else {  // must not happen, since setAudioEncoder checks this already
            ALOGE("audio encoder is set, but audio source is not set");
        }
        return INVALID_OPERATION;
    }

    if (mIsVideoSourceSet != mIsVideoEncoderSet) {
        if (mIsVideoSourceSet) {
            ALOGE("video source is set, but video encoder is not set");
        } else {  // must not happen, since setVideoEncoder checks this already
            ALOGE("video encoder is set, but video source is not set");
        }
        return INVALID_OPERATION;
    }

    status_t ret = mMediaRecorder->prepare();
    if (OK != ret) {
        ALOGE("prepare failed: %d", ret);
        mCurrentState = MEDIA_RECORDER_ERROR;
        return ret;
    }
    mCurrentState = MEDIA_RECORDER_PREPARED;
    return ret;
}

里面定位到了mMediaRecorder变量

  • 通过头文件定位到mediarecorder.h
#include <media/mediarecorder.h>
  • 在framew下搜索并打开该文件,找到该变量
    在这里插入图片描述
  • 明显是去到了IMediaRecorder,依旧在framework下搜索IMediaRecorder
    在这里插入图片描述
    明显源码就在IMediaRecorder.cpp中

感谢参考:https://blog.51cto.com/u_4259297/2161337
感谢参考:https://blog.csdn.net/tq501501/article/details/117444705
转载注明:https://blog.csdn.net/u014614038/article/details/117731557

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在 Android 平台上,要录制系统声音需要使用 MediaProjection API 和 AudioRecord API。 首先,你需要请求用户授权使用 MediaProjection API。可以通过以下代码启动授权对话框: ```java private static final int REQUEST_MEDIA_PROJECTION = 1; private MediaProjectionManager mMediaProjectionManager; // 在 onCreate() 方法中初始化 mMediaProjectionManager mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); // 启动授权对话框 startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION); ``` 当用户授权后,可以在 onActivityResult() 方法中获取到 MediaProjection 对象: ```java private MediaProjection mMediaProjection; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == RESULT_OK) { mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data); // 开始录制 startRecord(); } } ``` 接下来,可以使用 AudioRecord API 来录制系统声音。需要注意的是,录制系统声音需要 root 权限,或者使用系统签名的应用程序。 以下是录制系统声音的示例代码: ```java private static final int SAMPLE_RATE = 44100; private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO; private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; private AudioRecord mAudioRecord; private byte[] mBuffer; private boolean mIsRecording; private void startRecord() { int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT); mBuffer = new byte[minBufferSize]; mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.REMOTE_SUBMIX, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, minBufferSize); mAudioRecord.startRecording(); mIsRecording = true; new Thread(new Runnable() { @Override public void run() { FileOutputStream fos = null; try { fos = new FileOutputStream(new File(getExternalFilesDir(null), "record.pcm")); while (mIsRecording) { int readSize = mAudioRecord.read(mBuffer, 0, mBuffer.length); if (readSize > 0) { fos.write(mBuffer, 0, readSize); fos.flush(); } } } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }).start(); } private void stopRecord() { mIsRecording = false; mAudioRecord.stop(); mAudioRecord.release(); mAudioRecord = null; } ``` 上述代码中使用了 AudioRecord.getMinBufferSize() 方法获取最小缓冲区大小,然后创建了一个 AudioRecord 对象,并使用 startRecording() 方法开始录制。 录制过程中,使用 read() 方法从 AudioRecord 中读取数据,然后将数据写入到本地文件中。 最后,使用 stop() 方法停止录制,并释放资。 需要注意的是,上述代码中使用了 REMOTE_SUBMIX 作为录音,这是 Android 4.4 及以上版本中新增的一种录音,可以录制系统声音。 如果你的设备不支持 REMOTE_SUBMIX 录音,可以尝试使用其他录音,比如 MIC、VOICE_COMMUNICATION 等。不过,这些录音可能无法录制系统声音,需要根据具体情况进行选择。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值