/* ** ** Copyright (c) 2008 The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaRecorder" #include <utils/Log.h> #include <surfaceflinger/Surface.h> #include <media/mediarecorder.h> #include <binder/IServiceManager.h> #include <utils/String8.h> #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED namespace android { status_t MediaRecorder::setCamera(const sp<ICamera>& camera) { LOGV("setCamera(%p)", camera.get()); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { LOGE("setCamera called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setCamera(camera); if (OK != ret) { LOGV("setCamera failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } return ret; } status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface) { LOGV("setPreviewSurface(%p)", surface.get()); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } if (!mIsVideoSourceSet) { LOGE("try to set preview surface without setting the video source first"); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface()); if (OK != ret) { LOGV("setPreviewSurface failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } return ret; } status_t MediaRecorder::init() { LOGV("init"); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { LOGE("init called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->init(); if (OK != ret) { LOGV("init failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } ret = mMediaRecorder->setListener(this); if (OK != ret) { LOGV("setListener failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mCurrentState = MEDIA_RECORDER_INITIALIZED; return ret; } status_t MediaRecorder::setVideoSource(int vs) { LOGV("setVideoSource(%d)", vs); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (mIsVideoSourceSet) { LOGE("video source has already been set"); return INVALID_OPERATION; } if (mCurrentState & MEDIA_RECORDER_IDLE) { LOGV("Call init() since the media recorder is not initialized yet"); status_t ret = init(); if (OK != ret) { return ret; } } if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { LOGE("setVideoSource called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setVideoSource(vs); if (OK != ret) { LOGV("setVideoSource failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mIsVideoSourceSet = true; return ret; } status_t MediaRecorder::setAudioSource(int as) { LOGV("setAudioSource(%d)", as); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (mCurrentState & MEDIA_RECORDER_IDLE) { LOGV("Call init() since the media recorder is not initialized yet"); status_t ret = init(); if (OK != ret) { return ret; } } if (mIsAudioSourceSet) { LOGE("audio source has already been set"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { LOGE("setAudioSource called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setAudioSource(as); if (OK != ret) { LOGV("setAudioSource failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mIsAudioSourceSet = true; return ret; } status_t MediaRecorder::setOutputFormat(int of) { LOGV("setOutputFormat(%d)", of); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { LOGE("setOutputFormat called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START) { //first non-video output format LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setOutputFormat(of); if (OK != ret) { LOGE("setOutputFormat failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; return ret; } status_t MediaRecorder::setVideoEncoder(int ve) { LOGV("setVideoEncoder(%d)", ve); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!mIsVideoSourceSet) { LOGE("try to set the video encoder without setting the video source first"); return INVALID_OPERATION; } if (mIsVideoEncoderSet) { LOGE("video encoder has already been set"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setVideoEncoder(ve); if (OK != ret) { LOGV("setVideoEncoder failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mIsVideoEncoderSet = true; return ret; } status_t MediaRecorder::setAudioEncoder(int ae) { LOGV("setAudioEncoder(%d)", ae); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!mIsAudioSourceSet) { LOGE("try to set the audio encoder without setting the audio source first"); return INVALID_OPERATION; } if (mIsAudioEncoderSet) { LOGE("audio encoder has already been set"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setAudioEncoder(ae); if (OK != ret) { LOGV("setAudioEncoder failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mIsAudioEncoderSet = true; return ret; } status_t MediaRecorder::setOutputFile(const char* path) { LOGV("setOutputFile(%s)", path); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (mIsOutputFileSet) { LOGE("output file has already been set"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setOutputFile(path); if (OK != ret) { LOGV("setOutputFile failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mIsOutputFileSet = true; return ret; } status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (mIsOutputFileSet) { LOGE("output file has already been set"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); if (OK != ret) { LOGV("setOutputFile failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mIsOutputFileSet = true; return ret; } status_t MediaRecorder::setVideoSize(int width, int height) { LOGV("setVideoSize(%d, %d)", width, height); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setVideoSize called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } if (!mIsVideoSourceSet) { LOGE("try to set video size without setting video source first"); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setVideoSize(width, height); if (OK != ret) { LOGE("setVideoSize failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } return ret; } status_t MediaRecorder::setVideoFrameRate(int frames_per_second) { LOGV("setVideoFrameRate(%d)", frames_per_second); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } if (!mIsVideoSourceSet) { LOGE("try to set video frame rate without setting video source first"); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); if (OK != ret) { LOGE("setVideoFrameRate failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } return ret; } status_t MediaRecorder::setParameters(const String8& params) { LOGV("setParameters(%s)", params.string()); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } bool isInvalidState = (mCurrentState & (MEDIA_RECORDER_PREPARED | MEDIA_RECORDER_RECORDING | MEDIA_RECORDER_ERROR)); if (isInvalidState) { LOGE("setParameters is called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->setParameters(params); if (OK != ret) { LOGE("setParameters(%s) failed: %d", params.string(), ret); // Do not change our current state to MEDIA_RECORDER_ERROR, failures // of the only currently supported parameters, "max-duration" and // "max-filesize" are _not_ fatal. } return ret; } status_t MediaRecorder::prepare() { LOGV("prepare"); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { LOGE("prepare called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } if (mIsAudioSourceSet != mIsAudioEncoderSet) { if (mIsAudioSourceSet) { LOGE("audio source is set, but audio encoder is not set"); } else { // must not happen, since setAudioEncoder checks this already LOGE("audio encoder is set, but audio source is not set"); } return INVALID_OPERATION; } if (mIsVideoSourceSet != mIsVideoEncoderSet) { if (mIsVideoSourceSet) { LOGE("video source is set, but video encoder is not set"); } else { // must not happen, since setVideoEncoder checks this already LOGE("video encoder is set, but video source is not set"); } return INVALID_OPERATION; } status_t ret = mMediaRecorder->prepare(); if (OK != ret) { LOGE("prepare failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mCurrentState = MEDIA_RECORDER_PREPARED; return ret; } status_t MediaRecorder::getMaxAmplitude(int* max) { LOGV("getMaxAmplitude"); if(mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (mCurrentState & MEDIA_RECORDER_ERROR) { LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->getMaxAmplitude(max); if (OK != ret) { LOGE("getMaxAmplitude failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } return ret; } status_t MediaRecorder::start() { LOGV("start"); if (mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { LOGE("start called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->start(); if (OK != ret) { LOGE("start failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } mCurrentState = MEDIA_RECORDER_RECORDING; return ret; } status_t MediaRecorder::stop() { LOGV("stop"); if (mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { LOGE("stop called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->stop(); if (OK != ret) { LOGE("stop failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } // FIXME: // stop and reset are semantically different. // We treat them the same for now, and will change this in the future. doCleanUp(); mCurrentState = MEDIA_RECORDER_IDLE; return ret; } // Reset should be OK in any state status_t MediaRecorder::reset() { LOGV("reset"); if (mMediaRecorder == NULL) { LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } doCleanUp(); status_t ret = UNKNOWN_ERROR; switch(mCurrentState) { case MEDIA_RECORDER_IDLE: ret = OK; break; case MEDIA_RECORDER_RECORDING: case MEDIA_RECORDER_DATASOURCE_CONFIGURED: case MEDIA_RECORDER_PREPARED: case MEDIA_RECORDER_ERROR: { ret = doReset(); if (OK != ret) { return ret; // No need to continue } } // Intentional fall through case MEDIA_RECORDER_INITIALIZED: ret = close(); break; default: { LOGE("Unexpected non-existing state: %d", mCurrentState); break; } } return ret; } status_t MediaRecorder::close() { LOGV("close"); if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { LOGE("close called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } status_t ret = mMediaRecorder->close(); if (OK != ret) { LOGE("close failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return UNKNOWN_ERROR; } else { mCurrentState = MEDIA_RECORDER_IDLE; } return ret; } status_t MediaRecorder::doReset() { LOGV("doReset"); status_t ret = mMediaRecorder->reset(); if (OK != ret) { LOGE("doReset failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return ret; } else { mCurrentState = MEDIA_RECORDER_INITIALIZED; } return ret; } void MediaRecorder::doCleanUp() { LOGV("doCleanUp"); mIsAudioSourceSet = false; mIsVideoSourceSet = false; mIsAudioEncoderSet = false; mIsVideoEncoderSet = false; mIsOutputFileSet = false; } // Release should be OK in any state status_t MediaRecorder::release() { LOGV("release"); if (mMediaRecorder != NULL) { return mMediaRecorder->release(); } return INVALID_OPERATION; } MediaRecorder::MediaRecorder() { LOGV("constructor"); const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != NULL) { mMediaRecorder = service->createMediaRecorder(getpid()); } if (mMediaRecorder != NULL) { mCurrentState = MEDIA_RECORDER_IDLE; } doCleanUp(); } status_t MediaRecorder::initCheck() { return mMediaRecorder != 0 ? NO_ERROR : NO_INIT; } MediaRecorder::~MediaRecorder() { LOGV("destructor"); if (mMediaRecorder != NULL) { mMediaRecorder.clear(); } } status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener) { LOGV("setListener"); Mutex::Autolock _l(mLock); mListener = listener; return NO_ERROR; } void MediaRecorder::notify(int msg, int ext1, int ext2) { LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); sp<MediaRecorderListener> listener; mLock.lock(); listener = mListener; mLock.unlock(); if (listener != NULL) { Mutex::Autolock _l(mNotifyLock); LOGV("callback application"); listener->notify(msg, ext1, ext2); LOGV("back from callback"); } } void MediaRecorder::died() { LOGV("died"); notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0); } }; // namespace android