diff options
author | James Dong <jdong@google.com> | 2010-07-01 14:11:01 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-07-01 14:11:01 -0700 |
commit | 65c83b906d01c3c1493d0547757dbb16d4c3722a (patch) | |
tree | 3d23f348cad6c1a73eff4fcbc69477adc9b0d254 /media | |
parent | c7dacb7374e04c003b0764e7c348765b629c18cb (diff) | |
parent | 7b06de6d5a3128cc58e85b705e877d236cd32450 (diff) | |
download | frameworks_base-65c83b906d01c3c1493d0547757dbb16d4c3722a.zip frameworks_base-65c83b906d01c3c1493d0547757dbb16d4c3722a.tar.gz frameworks_base-65c83b906d01c3c1493d0547757dbb16d4c3722a.tar.bz2 |
Merge "Refactor Stagefright::StartMPEG4Recording()" into gingerbread
Diffstat (limited to 'media')
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 330 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 8 |
2 files changed, 186 insertions, 152 deletions
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 8bc6e9a..91c5b92 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -69,6 +69,7 @@ status_t StagefrightRecorder::setAudioSource(audio_source as) { LOGV("setAudioSource: %d", as); if (as < AUDIO_SOURCE_DEFAULT || as >= AUDIO_SOURCE_LIST_END) { + LOGE("Invalid audio source: %d", as); return BAD_VALUE; } @@ -85,6 +86,7 @@ status_t StagefrightRecorder::setVideoSource(video_source vs) { LOGV("setVideoSource: %d", vs); if (vs < VIDEO_SOURCE_DEFAULT || vs >= VIDEO_SOURCE_LIST_END) { + LOGE("Invalid video source: %d", vs); return BAD_VALUE; } @@ -101,6 +103,7 @@ status_t StagefrightRecorder::setOutputFormat(output_format of) { LOGV("setOutputFormat: %d", of); if (of < OUTPUT_FORMAT_DEFAULT || of >= OUTPUT_FORMAT_LIST_END) { + LOGE("Invalid output format: %d", of); return BAD_VALUE; } @@ -117,6 +120,7 @@ status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { LOGV("setAudioEncoder: %d", ae); if (ae < AUDIO_ENCODER_DEFAULT || ae >= AUDIO_ENCODER_LIST_END) { + LOGE("Invalid audio encoder: %d", ae); return BAD_VALUE; } @@ -133,6 +137,7 @@ status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { LOGV("setVideoEncoder: %d", ve); if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) { + LOGE("Invalid video encoder: %d", ve); return BAD_VALUE; } @@ -176,7 +181,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { LOGV("setCamera"); if (camera == 0) { LOGE("camera is NULL"); - return UNKNOWN_ERROR; + return BAD_VALUE; } int64_t token = IPCThreadState::self()->clearCallingIdentity(); @@ -185,7 +190,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { if (mCamera == 0) { LOGE("Unable to connect to camera"); IPCThreadState::self()->restoreCallingIdentity(token); - return UNKNOWN_ERROR; + return -EBUSY; } LOGV("Connected to camera"); @@ -206,11 +211,11 @@ status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { } status_t StagefrightRecorder::setOutputFile(const char *path) { - LOGE("setOutputFile(const char*) should not be called"); + LOGE("setOutputFile(const char*) must not be called"); // We don't actually support this at all, as the media_server process // no longer has permissions to create files. - return UNKNOWN_ERROR; + return -EPERM; } status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { @@ -219,6 +224,11 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng CHECK_EQ(offset, 0); CHECK_EQ(length, 0); + if (fd < 0) { + LOGE("Invalid file descriptor: %d", fd); + return -EBADF; + } + if (mOutputFd >= 0) { ::close(mOutputFd); } @@ -294,6 +304,7 @@ status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { LOGV("setParamAudioNumberOfChannels: %d", channels); if (channels <= 0 || channels >= 3) { LOGE("Invalid number of audio channels: %d", channels); + return BAD_VALUE; } // Additional check on the number of channels will be performed later. @@ -331,21 +342,23 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { return OK; } -status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit, - bool limit_is_duration) { - LOGV("setParamMaxDurationOrFileSize: limit (%lld) for %s", - limit, limit_is_duration?"duration":"size"); - if (limit_is_duration) { // limit is in ms - if (limit <= 1000) { // XXX: 1 second - LOGE("Max file duration is too short: %lld us", limit); - } - mMaxFileDurationUs = limit * 1000LL; - } else { - if (limit <= 1024) { // XXX: 1 kB - LOGE("Max file size is too small: %lld bytes", limit); - } - mMaxFileSizeBytes = limit; +status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) { + LOGV("setParamMaxFileDurationUs: %lld us", timeUs); + if (timeUs <= 1000000LL) { // XXX: 1 second + LOGE("Max file duration is too short: %lld us", timeUs); + return BAD_VALUE; } + mMaxFileDurationUs = timeUs; + return OK; +} + +status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) { + LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes); + if (bytes <= 1024) { // XXX: 1 kB + LOGE("Max file size is too small: %lld bytes", bytes); + return BAD_VALUE; + } + mMaxFileSizeBytes = bytes; return OK; } @@ -370,7 +383,7 @@ status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { // If interval < 0, only the first frame is I frame, and rest are all P frames // If interval == 0, all frames are encoded as I frames. No P frames -// If interval > 0, it is the time spacing between 2 neighboring I frames +// If interval > 0, it is the time spacing (seconds) between 2 neighboring I frames status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) { LOGV("setParamVideoIFramesInterval: %d seconds", interval); mIFramesInterval = interval; @@ -396,6 +409,7 @@ status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) { status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { LOGV("setParamTrackFrameStatus: %d", nFrames); if (nFrames <= 0) { + LOGE("Invalid number of frames to track: %d", nFrames); return BAD_VALUE; } mTrackEveryNumberOfFrames = nFrames; @@ -405,6 +419,7 @@ status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? + LOGE("Tracking time duration too short: %lld us", timeDurationUs); return BAD_VALUE; } mTrackEveryTimeDurationUs = timeDurationUs; @@ -417,14 +432,12 @@ status_t StagefrightRecorder::setParameter( if (key == "max-duration") { int64_t max_duration_ms; if (safe_strtoi64(value.string(), &max_duration_ms)) { - return setParamMaxDurationOrFileSize( - max_duration_ms, true /* limit_is_duration */); + return setParamMaxFileDurationUs(1000LL * max_duration_ms); } } else if (key == "max-filesize") { int64_t max_filesize_bytes; if (safe_strtoi64(value.string(), &max_filesize_bytes)) { - return setParamMaxDurationOrFileSize( - max_filesize_bytes, false /* limit is filesize */); + return setParamMaxFileSizeBytes(max_filesize_bytes); } } else if (key == "interleave-duration-us") { int32_t durationUs; @@ -528,7 +541,10 @@ status_t StagefrightRecorder::prepare() { } status_t StagefrightRecorder::start() { + CHECK(mOutputFd >= 0); + if (mWriter != NULL) { + LOGE("File writer is not avaialble"); return UNKNOWN_ERROR; } @@ -547,6 +563,7 @@ status_t StagefrightRecorder::start() { return startAACRecording(); default: + LOGE("Unsupported output file format: %d", mOutputFormat); return UNKNOWN_ERROR; } } @@ -610,7 +627,6 @@ status_t StagefrightRecorder::startAACRecording() { CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); - CHECK(mOutputFd >= 0); CHECK(0 == "AACWriter is not implemented yet"); @@ -626,34 +642,34 @@ status_t StagefrightRecorder::startAMRRecording() { mAudioEncoder != AUDIO_ENCODER_AMR_NB) { LOGE("Invalid encoder %d used for AMRNB recording", mAudioEncoder); - return UNKNOWN_ERROR; + return BAD_VALUE; } if (mSampleRate != 8000) { LOGE("Invalid sampling rate %d used for AMRNB recording", mSampleRate); - return UNKNOWN_ERROR; + return BAD_VALUE; } } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { LOGE("Invlaid encoder %d used for AMRWB recording", mAudioEncoder); - return UNKNOWN_ERROR; + return BAD_VALUE; } if (mSampleRate != 16000) { LOGE("Invalid sample rate %d used for AMRWB recording", mSampleRate); - return UNKNOWN_ERROR; + return BAD_VALUE; } } if (mAudioChannels != 1) { LOGE("Invalid number of audio channels %d used for amr recording", mAudioChannels); - return UNKNOWN_ERROR; + return BAD_VALUE; } if (mAudioSource >= AUDIO_SOURCE_LIST_END) { LOGE("Invalid audio source: %d", mAudioSource); - return UNKNOWN_ERROR; + return BAD_VALUE; } sp<MediaSource> audioEncoder = createAudioSource(); @@ -662,7 +678,6 @@ status_t StagefrightRecorder::startAMRRecording() { return UNKNOWN_ERROR; } - CHECK(mOutputFd >= 0); mWriter = new AMRWriter(dup(mOutputFd)); mWriter->addSource(audioEncoder); @@ -729,6 +744,54 @@ void StagefrightRecorder::clipVideoFrameWidth() { } } +status_t StagefrightRecorder::setupCameraSource() { + clipVideoBitRate(); + clipVideoFrameRate(); + clipVideoFrameWidth(); + clipVideoFrameHeight(); + + int64_t token = IPCThreadState::self()->clearCallingIdentity(); + if (mCamera == 0) { + mCamera = Camera::connect(mCameraId); + if (mCamera == 0) { + LOGE("Camera connection could not be established."); + return -EBUSY; + } + mFlags &= ~FLAGS_HOT_CAMERA; + mCamera->lock(); + } + + // Set the actual video recording frame size + CameraParameters params(mCamera->getParameters()); + params.setPreviewSize(mVideoWidth, mVideoHeight); + params.setPreviewFrameRate(mFrameRate); + String8 s = params.flatten(); + CHECK_EQ(OK, mCamera->setParameters(s)); + CameraParameters newCameraParams(mCamera->getParameters()); + + // Check on video frame size + int frameWidth = 0, frameHeight = 0; + newCameraParams.getPreviewSize(&frameWidth, &frameHeight); + if (frameWidth < 0 || frameWidth != mVideoWidth || + frameHeight < 0 || frameHeight != mVideoHeight) { + LOGE("Failed to set the video frame size to %dx%d", + mVideoWidth, mVideoHeight); + IPCThreadState::self()->restoreCallingIdentity(token); + return UNKNOWN_ERROR; + } + + // Check on video frame rate + int frameRate = newCameraParams.getPreviewFrameRate(); + if (frameRate < 0 || (frameRate - mFrameRate) != 0) { + LOGE("Failed to set frame rate to %d fps. The actual " + "frame rate is %d", mFrameRate, frameRate); + } + + CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); + IPCThreadState::self()->restoreCallingIdentity(token); + return OK; +} + void StagefrightRecorder::clipVideoFrameHeight() { LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( @@ -746,146 +809,110 @@ void StagefrightRecorder::clipVideoFrameHeight() { } } -status_t StagefrightRecorder::startMPEG4Recording() { - mWriter = new MPEG4Writer(dup(mOutputFd)); - int32_t totalBitRate = 0; +status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) { + status_t err = setupCameraSource(); + if (err != OK) return err; - // Add audio source first if it exists - if (mAudioSource != AUDIO_SOURCE_LIST_END) { - sp<MediaSource> audioEncoder; - switch(mAudioEncoder) { - case AUDIO_ENCODER_AMR_NB: - case AUDIO_ENCODER_AMR_WB: - case AUDIO_ENCODER_AAC: - audioEncoder = createAudioSource(); - break; - default: - LOGE("Unsupported audio encoder: %d", mAudioEncoder); - return UNKNOWN_ERROR; - } + sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera); + CHECK(cameraSource != NULL); - if (audioEncoder == NULL) { - return UNKNOWN_ERROR; - } - totalBitRate += mAudioBitRate; - mWriter->addSource(audioEncoder); - } - if (mVideoSource == VIDEO_SOURCE_DEFAULT - || mVideoSource == VIDEO_SOURCE_CAMERA) { - - clipVideoBitRate(); - clipVideoFrameRate(); - clipVideoFrameWidth(); - clipVideoFrameHeight(); - - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - if (mCamera == 0) { - mCamera = Camera::connect(mCameraId); - if (mCamera == 0) { - LOGE("Camera connection could not be established."); - return -EBUSY; - } - mFlags &= ~FLAGS_HOT_CAMERA; - mCamera->lock(); - } - - - // Set the actual video recording frame size - CameraParameters params(mCamera->getParameters()); - params.setPreviewSize(mVideoWidth, mVideoHeight); - params.setPreviewFrameRate(mFrameRate); - String8 s = params.flatten(); - CHECK_EQ(OK, mCamera->setParameters(s)); - CameraParameters newCameraParams(mCamera->getParameters()); - - // Check on video frame size - int frameWidth = 0, frameHeight = 0; - newCameraParams.getPreviewSize(&frameWidth, &frameHeight); - if (frameWidth < 0 || frameWidth != mVideoWidth || - frameHeight < 0 || frameHeight != mVideoHeight) { - LOGE("Failed to set the video frame size to %dx%d", - mVideoWidth, mVideoHeight); - IPCThreadState::self()->restoreCallingIdentity(token); - return UNKNOWN_ERROR; - } - - // Check on video frame rate - int frameRate = newCameraParams.getPreviewFrameRate(); - if (frameRate < 0 || (frameRate - mFrameRate) != 0) { - LOGE("Failed to set frame rate to %d fps. The actual " - "frame rate is %d", mFrameRate, frameRate); - } + sp<MetaData> enc_meta = new MetaData; + enc_meta->setInt32(kKeyBitRate, mVideoBitRate); + enc_meta->setInt32(kKeySampleRate, mFrameRate); - CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); - IPCThreadState::self()->restoreCallingIdentity(token); + switch (mVideoEncoder) { + case VIDEO_ENCODER_H263: + enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); + break; - sp<CameraSource> cameraSource = - CameraSource::CreateFromCamera(mCamera); + case VIDEO_ENCODER_MPEG_4_SP: + enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); + break; - CHECK(cameraSource != NULL); + case VIDEO_ENCODER_H264: + enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); + break; - sp<MetaData> enc_meta = new MetaData; - enc_meta->setInt32(kKeyBitRate, mVideoBitRate); - enc_meta->setInt32(kKeySampleRate, mFrameRate); + default: + CHECK(!"Should not be here, unsupported video encoding."); + break; + } - switch (mVideoEncoder) { - case VIDEO_ENCODER_H263: - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); - break; + sp<MetaData> meta = cameraSource->getFormat(); - case VIDEO_ENCODER_MPEG_4_SP: - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); - break; + int32_t width, height, stride, sliceHeight; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + CHECK(meta->findInt32(kKeyStride, &stride)); + CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); - case VIDEO_ENCODER_H264: - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); - break; + enc_meta->setInt32(kKeyWidth, width); + enc_meta->setInt32(kKeyHeight, height); + enc_meta->setInt32(kKeyIFramesInterval, mIFramesInterval); + enc_meta->setInt32(kKeyStride, stride); + enc_meta->setInt32(kKeySliceHeight, sliceHeight); - default: - CHECK(!"Should not be here, unsupported video encoding."); - break; - } + OMXClient client; + CHECK_EQ(client.connect(), OK); - sp<MetaData> meta = cameraSource->getFormat(); + sp<MediaSource> encoder = OMXCodec::Create( + client.interface(), enc_meta, + true /* createEncoder */, cameraSource); + if (encoder == NULL) { + return UNKNOWN_ERROR; + } - int32_t width, height, stride, sliceHeight; - CHECK(meta->findInt32(kKeyWidth, &width)); - CHECK(meta->findInt32(kKeyHeight, &height)); - CHECK(meta->findInt32(kKeyStride, &stride)); - CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); + writer->addSource(encoder); + return OK; +} - enc_meta->setInt32(kKeyWidth, width); - enc_meta->setInt32(kKeyHeight, height); - enc_meta->setInt32(kKeyIFramesInterval, mIFramesInterval); - enc_meta->setInt32(kKeyStride, stride); - enc_meta->setInt32(kKeySliceHeight, sliceHeight); +status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { + sp<MediaSource> audioEncoder; + switch(mAudioEncoder) { + case AUDIO_ENCODER_AMR_NB: + case AUDIO_ENCODER_AMR_WB: + case AUDIO_ENCODER_AAC: + audioEncoder = createAudioSource(); + break; + default: + LOGE("Unsupported audio encoder: %d", mAudioEncoder); + return UNKNOWN_ERROR; + } - OMXClient client; - CHECK_EQ(client.connect(), OK); + if (audioEncoder == NULL) { + return UNKNOWN_ERROR; + } + writer->addSource(audioEncoder); + return OK; +} - sp<MediaSource> encoder = - OMXCodec::Create( - client.interface(), enc_meta, - true /* createEncoder */, cameraSource); +status_t StagefrightRecorder::startMPEG4Recording() { + int32_t totalBitRate = 0; + status_t err = OK; + sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd)); - CHECK(mOutputFd >= 0); + // Add audio source first if it exists + if (mAudioSource != AUDIO_SOURCE_LIST_END) { + err = setupAudioEncoder(writer); + if (err != OK) return err; + totalBitRate += mAudioBitRate; + } + if (mVideoSource == VIDEO_SOURCE_DEFAULT + || mVideoSource == VIDEO_SOURCE_CAMERA) { + err = setupVideoEncoder(writer); + if (err != OK) return err; totalBitRate += mVideoBitRate; - mWriter->addSource(encoder); } - { - // MPEGWriter specific handling - MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); - writer->setInterleaveDuration(mInterleaveDurationUs); - } + reinterpret_cast<MPEG4Writer *>(writer.get())-> + setInterleaveDuration(mInterleaveDurationUs); if (mMaxFileDurationUs != 0) { - mWriter->setMaxFileDuration(mMaxFileDurationUs); + writer->setMaxFileDuration(mMaxFileDurationUs); } if (mMaxFileSizeBytes != 0) { - mWriter->setMaxFileSize(mMaxFileSizeBytes); + writer->setMaxFileSize(mMaxFileSizeBytes); } - mWriter->setListener(mListener); sp<MetaData> meta = new MetaData; meta->setInt64(kKeyTime, systemTime() / 1000); meta->setInt32(kKeyFileType, mOutputFormat); @@ -897,8 +924,9 @@ status_t StagefrightRecorder::startMPEG4Recording() { if (mTrackEveryTimeDurationUs > 0) { meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); } - mWriter->start(meta.get()); - return OK; + writer->setListener(mListener); + mWriter = writer; + return mWriter->start(meta.get()); } status_t StagefrightRecorder::pause() { @@ -914,7 +942,7 @@ status_t StagefrightRecorder::stop() { LOGV("stop"); if (mWriter != NULL) { mWriter->stop(); - mWriter = NULL; + mWriter.clear(); } if (mCamera != 0) { @@ -925,7 +953,7 @@ status_t StagefrightRecorder::stop() { mCamera->stopPreview(); } mCamera->unlock(); - mCamera = NULL; + mCamera.clear(); IPCThreadState::self()->restoreCallingIdentity(token); mFlags = 0; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index f4488b6..cb05571 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -97,6 +97,11 @@ private: status_t startAMRRecording(); status_t startAACRecording(); sp<MediaSource> createAudioSource(); + status_t setupCameraSource(); + status_t setupAudioEncoder(const sp<MediaWriter>& writer); + status_t setupVideoEncoder(const sp<MediaWriter>& writer); + + // Encoding parameter handling utilities status_t setParameter(const String8 &key, const String8 &value); status_t setParamAudioEncodingBitRate(int32_t bitRate); status_t setParamAudioNumberOfChannels(int32_t channles); @@ -108,7 +113,8 @@ private: status_t setParamTrackFrameStatus(int32_t nFrames); status_t setParamInterleaveDuration(int32_t durationUs); status_t setParam64BitFileOffset(bool use64BitFileOffset); - status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration); + status_t setParamMaxFileDurationUs(int64_t timeUs); + status_t setParamMaxFileSizeBytes(int64_t bytes); void clipVideoBitRate(); void clipVideoFrameRate(); void clipVideoFrameWidth(); |