Android 8.1/9.0 MTK Camera源码分析之录像快门声音控制流程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zimu_2080/article/details/86645435

前面已经针对拍照快门声音控制流程进行了分析,接下来分析一下录像快门声音的控制流程。

Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程

这两篇文章其实都是相对于手机系统ROM Camera开发过程中,针对ap层快门声音动态控制来说明的。

Android 8.1 Camera api1

早前在Android N以及之前,mtk源码中,/frameworks/base/core/java/android/hardware/Camera.java中是有定义可以控制录像快门声音的公开接口的。而到了Android O之后,camera.java便没有了直接控制的函数了。

由于enableRecordingSound 该接口在Camera.java中去掉了,需要自己添加,才能控制录像快门的音效。
key值为"rec-mute-ogg",调用set函数设置下去。

        /**
         * @hide
         * ljr add for control video shutter sound
         */
        private static final String KEY_MUTE_RECORDING_SOUND = "rec-mute-ogg";

		/**
         * <p>Whether the recording sound can be disabled.</p>
         *  ljr add for control video shutter sound
         * @hide
         */
        public void enableRecordingSound(String value) {
            if (value.equals("1") || value.equals("0")) {
                set(KEY_MUTE_RECORDING_SOUND, value);
            }
        }

录像快门声音,正常逻辑,一定是执行开始视频录制时进行播放的。所以这里可以先直接看"rec-mute-ogg"这个key被getValue的地方。
文件路径:frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp

startRecordingMode():

status_t CameraClient::startRecordingMode() {
    LOG1("startRecordingMode");
    status_t result = NO_ERROR;

    // if recording has been enabled, nothing needs to be done
    if (mHardware->recordingEnabled()) {
        return NO_ERROR;
    }

    // if preview has not been started, start preview first
    if (!mHardware->previewEnabled()) {
        result = startPreviewMode();
        if (result != NO_ERROR) {
            return result;
        }
    }

    // start recording mode
    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
    //这里拿到Camera Parameters对象,用作获取设置的参数
    CameraParameters params(mHardware->getParameters());
    int value = 0;
    value = params.getInt("rec-mute-ogg"); //通过params来获取rec-mute-ogg值
    if (value != 1) { //满足,调用sCameraService来进行声音播放
        sCameraService->playSound(CameraService::SOUND_RECORDING_START);
    }
    result = mHardware->startRecording(); //执行到hal的startRecording
    if (result != NO_ERROR) {
        ALOGE("mHardware->startRecording() failed with status %d", result);
    }
    return result;
}

stopRecording():

// stop recording mode
void CameraClient::stopRecording() {
    LOG1("stopRecording (pid %d)", getCallingPid());
    {
        Mutex::Autolock lock(mLock);
        if (checkPidAndHardware() != NO_ERROR) return;

        disableMsgType(CAMERA_MSG_VIDEO_FRAME);
		CameraParameters params(mHardware->getParameters());//通过params来获取rec-mute-ogg值
        int value = 0;
        value = params.getInt("rec-mute-ogg");
        if (value != 1) {//满足,调用sCameraService来进行声音播放
            sCameraService->playSound(CameraService::SOUND_RECORDING_STOP);
        }
        mHardware->stopRecording();//执行到hal的stopRecording

        mPreviewBuffer.clear();
    }

    {
        Mutex::Autolock l(mAvailableCallbackBuffersLock);
        if (!mAvailableCallbackBuffers.empty()) {
            mAvailableCallbackBuffers.clear();
        }
    }
}

CameraService.cpp中的playsound函数:

void CameraService::playSound(sound_kind kind) {
    ATRACE_CALL();

    LOG1("playSound(%d)", kind);
    Mutex::Autolock lock(mSoundLock);
    //!++
    waitloadSoundDone(); //资源加载
    //!--
    sp<MediaPlayer> player = mSoundPlayer[kind];
    if (player != 0) {
        player->seekTo(0);
        player->start();
    }
}

添加之后,在app中调用api控制录像声音:

parameters.enableRecordingSound(isShutterSoundOn ? "0" : "1");

Android 9.0 Camera api2

api2同样会方便很多,仅需在上层startRecording和stopRecording中控制即可。
mICameraContext.getSoundPlayback().play(ISoundPlayback.START_VIDEO_RECORDING);

    @Override
    public void startRecording() {
        LogHelper.i(TAG, "[startRecording] + ");
        mIsRecording = true;
        if(isShutterSoundOn()) { //ljr modify
               mICameraContext.getSoundPlayback().play(ISoundPlayback.START_VIDEO_RECORDING);
        }
        try {
            CaptureRequest.Builder builder = doCreateAndConfigRequest(true);
            setRepeatingRequest(builder);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        LogHelper.d(TAG, "[startRecording] - ");
    }

总结

Camera api2在快门声音这一点上确实比api1要简洁很多。可以做到完全在上层控制。

而在api1中,快门声音播放方式放到cameraservice中,主要原因还是设计上要做到快门声音与拍照结束进行同步,也就是说快门声音播放了,表明照片已经捕获成功。而如果在上层进行播放的话,是没有直接的回调来判断照片捕获成功的时机。但api2直接就给我们提供了captureSession的回调,可以用作判断,再把声音播放方式放在上层就简洁多了。

录像声音也是一样,放在cameraservice中,主要也是控制在真正执行recording函数之前播放,以免录像快门声音也被录制进视频中。而mtk在Android N之后的改变,去除camera.java的直接控制录像快门声音的接口,大概也是想让我们直接在上层调用StartRecording或StopRecording时直接控制就可以。

猜你喜欢

转载自blog.csdn.net/zimu_2080/article/details/86645435