Loading media/libmediaplayerservice/StagefrightRecorder.cpp +179 −151 Original line number Original line Diff line number Diff line Loading @@ -69,6 +69,7 @@ status_t StagefrightRecorder::setAudioSource(audio_source as) { LOGV("setAudioSource: %d", as); LOGV("setAudioSource: %d", as); if (as < AUDIO_SOURCE_DEFAULT || if (as < AUDIO_SOURCE_DEFAULT || as >= AUDIO_SOURCE_LIST_END) { as >= AUDIO_SOURCE_LIST_END) { LOGE("Invalid audio source: %d", as); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -85,6 +86,7 @@ status_t StagefrightRecorder::setVideoSource(video_source vs) { LOGV("setVideoSource: %d", vs); LOGV("setVideoSource: %d", vs); if (vs < VIDEO_SOURCE_DEFAULT || if (vs < VIDEO_SOURCE_DEFAULT || vs >= VIDEO_SOURCE_LIST_END) { vs >= VIDEO_SOURCE_LIST_END) { LOGE("Invalid video source: %d", vs); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -101,6 +103,7 @@ status_t StagefrightRecorder::setOutputFormat(output_format of) { LOGV("setOutputFormat: %d", of); LOGV("setOutputFormat: %d", of); if (of < OUTPUT_FORMAT_DEFAULT || if (of < OUTPUT_FORMAT_DEFAULT || of >= OUTPUT_FORMAT_LIST_END) { of >= OUTPUT_FORMAT_LIST_END) { LOGE("Invalid output format: %d", of); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -117,6 +120,7 @@ status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { LOGV("setAudioEncoder: %d", ae); LOGV("setAudioEncoder: %d", ae); if (ae < AUDIO_ENCODER_DEFAULT || if (ae < AUDIO_ENCODER_DEFAULT || ae >= AUDIO_ENCODER_LIST_END) { ae >= AUDIO_ENCODER_LIST_END) { LOGE("Invalid audio encoder: %d", ae); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -133,6 +137,7 @@ status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { LOGV("setVideoEncoder: %d", ve); LOGV("setVideoEncoder: %d", ve); if (ve < VIDEO_ENCODER_DEFAULT || if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) { ve >= VIDEO_ENCODER_LIST_END) { LOGE("Invalid video encoder: %d", ve); return BAD_VALUE; return BAD_VALUE; } } Loading Loading @@ -176,7 +181,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { LOGV("setCamera"); LOGV("setCamera"); if (camera == 0) { if (camera == 0) { LOGE("camera is NULL"); LOGE("camera is NULL"); return UNKNOWN_ERROR; return BAD_VALUE; } } int64_t token = IPCThreadState::self()->clearCallingIdentity(); int64_t token = IPCThreadState::self()->clearCallingIdentity(); Loading @@ -185,7 +190,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { if (mCamera == 0) { if (mCamera == 0) { LOGE("Unable to connect to camera"); LOGE("Unable to connect to camera"); IPCThreadState::self()->restoreCallingIdentity(token); IPCThreadState::self()->restoreCallingIdentity(token); return UNKNOWN_ERROR; return -EBUSY; } } LOGV("Connected to camera"); LOGV("Connected to camera"); Loading @@ -206,11 +211,11 @@ status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { } } status_t StagefrightRecorder::setOutputFile(const char *path) { 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 // We don't actually support this at all, as the media_server process // no longer has permissions to create files. // no longer has permissions to create files. return UNKNOWN_ERROR; return -EPERM; } } status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { Loading @@ -219,6 +224,11 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng CHECK_EQ(offset, 0); CHECK_EQ(offset, 0); CHECK_EQ(length, 0); CHECK_EQ(length, 0); if (fd < 0) { LOGE("Invalid file descriptor: %d", fd); return -EBADF; } if (mOutputFd >= 0) { if (mOutputFd >= 0) { ::close(mOutputFd); ::close(mOutputFd); } } Loading Loading @@ -294,6 +304,7 @@ status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { LOGV("setParamAudioNumberOfChannels: %d", channels); LOGV("setParamAudioNumberOfChannels: %d", channels); if (channels <= 0 || channels >= 3) { if (channels <= 0 || channels >= 3) { LOGE("Invalid number of audio channels: %d", channels); LOGE("Invalid number of audio channels: %d", channels); return BAD_VALUE; } } // Additional check on the number of channels will be performed later. // Additional check on the number of channels will be performed later. Loading Loading @@ -331,21 +342,23 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { return OK; return OK; } } status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit, status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) { bool limit_is_duration) { LOGV("setParamMaxFileDurationUs: %lld us", timeUs); LOGV("setParamMaxDurationOrFileSize: limit (%lld) for %s", if (timeUs <= 1000000LL) { // XXX: 1 second limit, limit_is_duration?"duration":"size"); LOGE("Max file duration is too short: %lld us", timeUs); if (limit_is_duration) { // limit is in ms return BAD_VALUE; if (limit <= 1000) { // XXX: 1 second LOGE("Max file duration is too short: %lld us", limit); } } mMaxFileDurationUs = limit * 1000LL; mMaxFileDurationUs = timeUs; } else { return OK; if (limit <= 1024) { // XXX: 1 kB LOGE("Max file size is too small: %lld bytes", limit); } } mMaxFileSizeBytes = limit; 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; return OK; } } Loading @@ -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, 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, 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) { status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) { LOGV("setParamVideoIFramesInterval: %d seconds", interval); LOGV("setParamVideoIFramesInterval: %d seconds", interval); mIFramesInterval = interval; mIFramesInterval = interval; Loading @@ -396,6 +409,7 @@ status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) { status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { LOGV("setParamTrackFrameStatus: %d", nFrames); LOGV("setParamTrackFrameStatus: %d", nFrames); if (nFrames <= 0) { if (nFrames <= 0) { LOGE("Invalid number of frames to track: %d", nFrames); return BAD_VALUE; return BAD_VALUE; } } mTrackEveryNumberOfFrames = nFrames; mTrackEveryNumberOfFrames = nFrames; Loading @@ -405,6 +419,7 @@ status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? LOGE("Tracking time duration too short: %lld us", timeDurationUs); return BAD_VALUE; return BAD_VALUE; } } mTrackEveryTimeDurationUs = timeDurationUs; mTrackEveryTimeDurationUs = timeDurationUs; Loading @@ -417,14 +432,12 @@ status_t StagefrightRecorder::setParameter( if (key == "max-duration") { if (key == "max-duration") { int64_t max_duration_ms; int64_t max_duration_ms; if (safe_strtoi64(value.string(), &max_duration_ms)) { if (safe_strtoi64(value.string(), &max_duration_ms)) { return setParamMaxDurationOrFileSize( return setParamMaxFileDurationUs(1000LL * max_duration_ms); max_duration_ms, true /* limit_is_duration */); } } } else if (key == "max-filesize") { } else if (key == "max-filesize") { int64_t max_filesize_bytes; int64_t max_filesize_bytes; if (safe_strtoi64(value.string(), &max_filesize_bytes)) { if (safe_strtoi64(value.string(), &max_filesize_bytes)) { return setParamMaxDurationOrFileSize( return setParamMaxFileSizeBytes(max_filesize_bytes); max_filesize_bytes, false /* limit is filesize */); } } } else if (key == "interleave-duration-us") { } else if (key == "interleave-duration-us") { int32_t durationUs; int32_t durationUs; Loading Loading @@ -528,7 +541,10 @@ status_t StagefrightRecorder::prepare() { } } status_t StagefrightRecorder::start() { status_t StagefrightRecorder::start() { CHECK(mOutputFd >= 0); if (mWriter != NULL) { if (mWriter != NULL) { LOGE("File writer is not avaialble"); return UNKNOWN_ERROR; return UNKNOWN_ERROR; } } Loading @@ -547,6 +563,7 @@ status_t StagefrightRecorder::start() { return startAACRecording(); return startAACRecording(); default: default: LOGE("Unsupported output file format: %d", mOutputFormat); return UNKNOWN_ERROR; return UNKNOWN_ERROR; } } } } Loading Loading @@ -610,7 +627,6 @@ status_t StagefrightRecorder::startAACRecording() { CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); CHECK(mOutputFd >= 0); CHECK(0 == "AACWriter is not implemented yet"); CHECK(0 == "AACWriter is not implemented yet"); Loading @@ -626,34 +642,34 @@ status_t StagefrightRecorder::startAMRRecording() { mAudioEncoder != AUDIO_ENCODER_AMR_NB) { mAudioEncoder != AUDIO_ENCODER_AMR_NB) { LOGE("Invalid encoder %d used for AMRNB recording", LOGE("Invalid encoder %d used for AMRNB recording", mAudioEncoder); mAudioEncoder); return UNKNOWN_ERROR; return BAD_VALUE; } } if (mSampleRate != 8000) { if (mSampleRate != 8000) { LOGE("Invalid sampling rate %d used for AMRNB recording", LOGE("Invalid sampling rate %d used for AMRNB recording", mSampleRate); mSampleRate); return UNKNOWN_ERROR; return BAD_VALUE; } } } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { LOGE("Invlaid encoder %d used for AMRWB recording", LOGE("Invlaid encoder %d used for AMRWB recording", mAudioEncoder); mAudioEncoder); return UNKNOWN_ERROR; return BAD_VALUE; } } if (mSampleRate != 16000) { if (mSampleRate != 16000) { LOGE("Invalid sample rate %d used for AMRWB recording", LOGE("Invalid sample rate %d used for AMRWB recording", mSampleRate); mSampleRate); return UNKNOWN_ERROR; return BAD_VALUE; } } } } if (mAudioChannels != 1) { if (mAudioChannels != 1) { LOGE("Invalid number of audio channels %d used for amr recording", LOGE("Invalid number of audio channels %d used for amr recording", mAudioChannels); mAudioChannels); return UNKNOWN_ERROR; return BAD_VALUE; } } if (mAudioSource >= AUDIO_SOURCE_LIST_END) { if (mAudioSource >= AUDIO_SOURCE_LIST_END) { LOGE("Invalid audio source: %d", mAudioSource); LOGE("Invalid audio source: %d", mAudioSource); return UNKNOWN_ERROR; return BAD_VALUE; } } sp<MediaSource> audioEncoder = createAudioSource(); sp<MediaSource> audioEncoder = createAudioSource(); Loading @@ -662,7 +678,6 @@ status_t StagefrightRecorder::startAMRRecording() { return UNKNOWN_ERROR; return UNKNOWN_ERROR; } } CHECK(mOutputFd >= 0); mWriter = new AMRWriter(dup(mOutputFd)); mWriter = new AMRWriter(dup(mOutputFd)); mWriter->addSource(audioEncoder); mWriter->addSource(audioEncoder); Loading Loading @@ -729,50 +744,7 @@ void StagefrightRecorder::clipVideoFrameWidth() { } } } } void StagefrightRecorder::clipVideoFrameHeight() { status_t StagefrightRecorder::setupCameraSource() { LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.min", mVideoEncoder); int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.max", mVideoEncoder); if (mVideoHeight < minFrameHeight) { LOGW("Intended video encoding frame height (%d) is too small" " and will be set to (%d)", mVideoHeight, minFrameHeight); mVideoHeight = minFrameHeight; } else if (mVideoHeight > maxFrameHeight) { LOGW("Intended video encoding frame height (%d) is too large" " and will be set to (%d)", mVideoHeight, maxFrameHeight); mVideoHeight = maxFrameHeight; } } status_t StagefrightRecorder::startMPEG4Recording() { mWriter = new MPEG4Writer(dup(mOutputFd)); int32_t totalBitRate = 0; // 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; } if (audioEncoder == NULL) { return UNKNOWN_ERROR; } totalBitRate += mAudioBitRate; mWriter->addSource(audioEncoder); } if (mVideoSource == VIDEO_SOURCE_DEFAULT || mVideoSource == VIDEO_SOURCE_CAMERA) { clipVideoBitRate(); clipVideoBitRate(); clipVideoFrameRate(); clipVideoFrameRate(); clipVideoFrameWidth(); clipVideoFrameWidth(); Loading @@ -789,7 +761,6 @@ status_t StagefrightRecorder::startMPEG4Recording() { mCamera->lock(); mCamera->lock(); } } // Set the actual video recording frame size // Set the actual video recording frame size CameraParameters params(mCamera->getParameters()); CameraParameters params(mCamera->getParameters()); params.setPreviewSize(mVideoWidth, mVideoHeight); params.setPreviewSize(mVideoWidth, mVideoHeight); Loading Loading @@ -818,10 +789,31 @@ status_t StagefrightRecorder::startMPEG4Recording() { CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); IPCThreadState::self()->restoreCallingIdentity(token); IPCThreadState::self()->restoreCallingIdentity(token); return OK; } sp<CameraSource> cameraSource = void StagefrightRecorder::clipVideoFrameHeight() { CameraSource::CreateFromCamera(mCamera); LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.min", mVideoEncoder); int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.max", mVideoEncoder); if (mVideoHeight < minFrameHeight) { LOGW("Intended video encoding frame height (%d) is too small" " and will be set to (%d)", mVideoHeight, minFrameHeight); mVideoHeight = minFrameHeight; } else if (mVideoHeight > maxFrameHeight) { LOGW("Intended video encoding frame height (%d) is too large" " and will be set to (%d)", mVideoHeight, maxFrameHeight); mVideoHeight = maxFrameHeight; } } status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) { status_t err = setupCameraSource(); if (err != OK) return err; sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera); CHECK(cameraSource != NULL); CHECK(cameraSource != NULL); sp<MetaData> enc_meta = new MetaData; sp<MetaData> enc_meta = new MetaData; Loading Loading @@ -863,29 +855,64 @@ status_t StagefrightRecorder::startMPEG4Recording() { OMXClient client; OMXClient client; CHECK_EQ(client.connect(), OK); CHECK_EQ(client.connect(), OK); sp<MediaSource> encoder = sp<MediaSource> encoder = OMXCodec::Create( OMXCodec::Create( client.interface(), enc_meta, client.interface(), enc_meta, true /* createEncoder */, cameraSource); true /* createEncoder */, cameraSource); if (encoder == NULL) { return UNKNOWN_ERROR; } CHECK(mOutputFd >= 0); writer->addSource(encoder); totalBitRate += mVideoBitRate; return OK; mWriter->addSource(encoder); } } { status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { // MPEGWriter specific handling sp<MediaSource> audioEncoder; MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); switch(mAudioEncoder) { writer->setInterleaveDuration(mInterleaveDurationUs); 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; } if (audioEncoder == NULL) { return UNKNOWN_ERROR; } writer->addSource(audioEncoder); return OK; } status_t StagefrightRecorder::startMPEG4Recording() { int32_t totalBitRate = 0; status_t err = OK; sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd)); // 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; } } reinterpret_cast<MPEG4Writer *>(writer.get())-> setInterleaveDuration(mInterleaveDurationUs); if (mMaxFileDurationUs != 0) { if (mMaxFileDurationUs != 0) { mWriter->setMaxFileDuration(mMaxFileDurationUs); writer->setMaxFileDuration(mMaxFileDurationUs); } } if (mMaxFileSizeBytes != 0) { if (mMaxFileSizeBytes != 0) { mWriter->setMaxFileSize(mMaxFileSizeBytes); writer->setMaxFileSize(mMaxFileSizeBytes); } } mWriter->setListener(mListener); sp<MetaData> meta = new MetaData; sp<MetaData> meta = new MetaData; meta->setInt64(kKeyTime, systemTime() / 1000); meta->setInt64(kKeyTime, systemTime() / 1000); meta->setInt32(kKeyFileType, mOutputFormat); meta->setInt32(kKeyFileType, mOutputFormat); Loading @@ -897,8 +924,9 @@ status_t StagefrightRecorder::startMPEG4Recording() { if (mTrackEveryTimeDurationUs > 0) { if (mTrackEveryTimeDurationUs > 0) { meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); } } mWriter->start(meta.get()); writer->setListener(mListener); return OK; mWriter = writer; return mWriter->start(meta.get()); } } status_t StagefrightRecorder::pause() { status_t StagefrightRecorder::pause() { Loading @@ -914,7 +942,7 @@ status_t StagefrightRecorder::stop() { LOGV("stop"); LOGV("stop"); if (mWriter != NULL) { if (mWriter != NULL) { mWriter->stop(); mWriter->stop(); mWriter = NULL; mWriter.clear(); } } if (mCamera != 0) { if (mCamera != 0) { Loading @@ -925,7 +953,7 @@ status_t StagefrightRecorder::stop() { mCamera->stopPreview(); mCamera->stopPreview(); } } mCamera->unlock(); mCamera->unlock(); mCamera = NULL; mCamera.clear(); IPCThreadState::self()->restoreCallingIdentity(token); IPCThreadState::self()->restoreCallingIdentity(token); mFlags = 0; mFlags = 0; } } Loading media/libmediaplayerservice/StagefrightRecorder.h +7 −1 Original line number Original line Diff line number Diff line Loading @@ -97,6 +97,11 @@ private: status_t startAMRRecording(); status_t startAMRRecording(); status_t startAACRecording(); status_t startAACRecording(); sp<MediaSource> createAudioSource(); 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 setParameter(const String8 &key, const String8 &value); status_t setParamAudioEncodingBitRate(int32_t bitRate); status_t setParamAudioEncodingBitRate(int32_t bitRate); status_t setParamAudioNumberOfChannels(int32_t channles); status_t setParamAudioNumberOfChannels(int32_t channles); Loading @@ -108,7 +113,8 @@ private: status_t setParamTrackFrameStatus(int32_t nFrames); status_t setParamTrackFrameStatus(int32_t nFrames); status_t setParamInterleaveDuration(int32_t durationUs); status_t setParamInterleaveDuration(int32_t durationUs); status_t setParam64BitFileOffset(bool use64BitFileOffset); 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 clipVideoBitRate(); void clipVideoFrameRate(); void clipVideoFrameRate(); void clipVideoFrameWidth(); void clipVideoFrameWidth(); Loading Loading
media/libmediaplayerservice/StagefrightRecorder.cpp +179 −151 Original line number Original line Diff line number Diff line Loading @@ -69,6 +69,7 @@ status_t StagefrightRecorder::setAudioSource(audio_source as) { LOGV("setAudioSource: %d", as); LOGV("setAudioSource: %d", as); if (as < AUDIO_SOURCE_DEFAULT || if (as < AUDIO_SOURCE_DEFAULT || as >= AUDIO_SOURCE_LIST_END) { as >= AUDIO_SOURCE_LIST_END) { LOGE("Invalid audio source: %d", as); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -85,6 +86,7 @@ status_t StagefrightRecorder::setVideoSource(video_source vs) { LOGV("setVideoSource: %d", vs); LOGV("setVideoSource: %d", vs); if (vs < VIDEO_SOURCE_DEFAULT || if (vs < VIDEO_SOURCE_DEFAULT || vs >= VIDEO_SOURCE_LIST_END) { vs >= VIDEO_SOURCE_LIST_END) { LOGE("Invalid video source: %d", vs); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -101,6 +103,7 @@ status_t StagefrightRecorder::setOutputFormat(output_format of) { LOGV("setOutputFormat: %d", of); LOGV("setOutputFormat: %d", of); if (of < OUTPUT_FORMAT_DEFAULT || if (of < OUTPUT_FORMAT_DEFAULT || of >= OUTPUT_FORMAT_LIST_END) { of >= OUTPUT_FORMAT_LIST_END) { LOGE("Invalid output format: %d", of); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -117,6 +120,7 @@ status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { LOGV("setAudioEncoder: %d", ae); LOGV("setAudioEncoder: %d", ae); if (ae < AUDIO_ENCODER_DEFAULT || if (ae < AUDIO_ENCODER_DEFAULT || ae >= AUDIO_ENCODER_LIST_END) { ae >= AUDIO_ENCODER_LIST_END) { LOGE("Invalid audio encoder: %d", ae); return BAD_VALUE; return BAD_VALUE; } } Loading @@ -133,6 +137,7 @@ status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { LOGV("setVideoEncoder: %d", ve); LOGV("setVideoEncoder: %d", ve); if (ve < VIDEO_ENCODER_DEFAULT || if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) { ve >= VIDEO_ENCODER_LIST_END) { LOGE("Invalid video encoder: %d", ve); return BAD_VALUE; return BAD_VALUE; } } Loading Loading @@ -176,7 +181,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { LOGV("setCamera"); LOGV("setCamera"); if (camera == 0) { if (camera == 0) { LOGE("camera is NULL"); LOGE("camera is NULL"); return UNKNOWN_ERROR; return BAD_VALUE; } } int64_t token = IPCThreadState::self()->clearCallingIdentity(); int64_t token = IPCThreadState::self()->clearCallingIdentity(); Loading @@ -185,7 +190,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { if (mCamera == 0) { if (mCamera == 0) { LOGE("Unable to connect to camera"); LOGE("Unable to connect to camera"); IPCThreadState::self()->restoreCallingIdentity(token); IPCThreadState::self()->restoreCallingIdentity(token); return UNKNOWN_ERROR; return -EBUSY; } } LOGV("Connected to camera"); LOGV("Connected to camera"); Loading @@ -206,11 +211,11 @@ status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { } } status_t StagefrightRecorder::setOutputFile(const char *path) { 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 // We don't actually support this at all, as the media_server process // no longer has permissions to create files. // no longer has permissions to create files. return UNKNOWN_ERROR; return -EPERM; } } status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { Loading @@ -219,6 +224,11 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng CHECK_EQ(offset, 0); CHECK_EQ(offset, 0); CHECK_EQ(length, 0); CHECK_EQ(length, 0); if (fd < 0) { LOGE("Invalid file descriptor: %d", fd); return -EBADF; } if (mOutputFd >= 0) { if (mOutputFd >= 0) { ::close(mOutputFd); ::close(mOutputFd); } } Loading Loading @@ -294,6 +304,7 @@ status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { LOGV("setParamAudioNumberOfChannels: %d", channels); LOGV("setParamAudioNumberOfChannels: %d", channels); if (channels <= 0 || channels >= 3) { if (channels <= 0 || channels >= 3) { LOGE("Invalid number of audio channels: %d", channels); LOGE("Invalid number of audio channels: %d", channels); return BAD_VALUE; } } // Additional check on the number of channels will be performed later. // Additional check on the number of channels will be performed later. Loading Loading @@ -331,21 +342,23 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { return OK; return OK; } } status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit, status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) { bool limit_is_duration) { LOGV("setParamMaxFileDurationUs: %lld us", timeUs); LOGV("setParamMaxDurationOrFileSize: limit (%lld) for %s", if (timeUs <= 1000000LL) { // XXX: 1 second limit, limit_is_duration?"duration":"size"); LOGE("Max file duration is too short: %lld us", timeUs); if (limit_is_duration) { // limit is in ms return BAD_VALUE; if (limit <= 1000) { // XXX: 1 second LOGE("Max file duration is too short: %lld us", limit); } } mMaxFileDurationUs = limit * 1000LL; mMaxFileDurationUs = timeUs; } else { return OK; if (limit <= 1024) { // XXX: 1 kB LOGE("Max file size is too small: %lld bytes", limit); } } mMaxFileSizeBytes = limit; 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; return OK; } } Loading @@ -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, 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, 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) { status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) { LOGV("setParamVideoIFramesInterval: %d seconds", interval); LOGV("setParamVideoIFramesInterval: %d seconds", interval); mIFramesInterval = interval; mIFramesInterval = interval; Loading @@ -396,6 +409,7 @@ status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) { status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { LOGV("setParamTrackFrameStatus: %d", nFrames); LOGV("setParamTrackFrameStatus: %d", nFrames); if (nFrames <= 0) { if (nFrames <= 0) { LOGE("Invalid number of frames to track: %d", nFrames); return BAD_VALUE; return BAD_VALUE; } } mTrackEveryNumberOfFrames = nFrames; mTrackEveryNumberOfFrames = nFrames; Loading @@ -405,6 +419,7 @@ status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? LOGE("Tracking time duration too short: %lld us", timeDurationUs); return BAD_VALUE; return BAD_VALUE; } } mTrackEveryTimeDurationUs = timeDurationUs; mTrackEveryTimeDurationUs = timeDurationUs; Loading @@ -417,14 +432,12 @@ status_t StagefrightRecorder::setParameter( if (key == "max-duration") { if (key == "max-duration") { int64_t max_duration_ms; int64_t max_duration_ms; if (safe_strtoi64(value.string(), &max_duration_ms)) { if (safe_strtoi64(value.string(), &max_duration_ms)) { return setParamMaxDurationOrFileSize( return setParamMaxFileDurationUs(1000LL * max_duration_ms); max_duration_ms, true /* limit_is_duration */); } } } else if (key == "max-filesize") { } else if (key == "max-filesize") { int64_t max_filesize_bytes; int64_t max_filesize_bytes; if (safe_strtoi64(value.string(), &max_filesize_bytes)) { if (safe_strtoi64(value.string(), &max_filesize_bytes)) { return setParamMaxDurationOrFileSize( return setParamMaxFileSizeBytes(max_filesize_bytes); max_filesize_bytes, false /* limit is filesize */); } } } else if (key == "interleave-duration-us") { } else if (key == "interleave-duration-us") { int32_t durationUs; int32_t durationUs; Loading Loading @@ -528,7 +541,10 @@ status_t StagefrightRecorder::prepare() { } } status_t StagefrightRecorder::start() { status_t StagefrightRecorder::start() { CHECK(mOutputFd >= 0); if (mWriter != NULL) { if (mWriter != NULL) { LOGE("File writer is not avaialble"); return UNKNOWN_ERROR; return UNKNOWN_ERROR; } } Loading @@ -547,6 +563,7 @@ status_t StagefrightRecorder::start() { return startAACRecording(); return startAACRecording(); default: default: LOGE("Unsupported output file format: %d", mOutputFormat); return UNKNOWN_ERROR; return UNKNOWN_ERROR; } } } } Loading Loading @@ -610,7 +627,6 @@ status_t StagefrightRecorder::startAACRecording() { CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); CHECK(mOutputFd >= 0); CHECK(0 == "AACWriter is not implemented yet"); CHECK(0 == "AACWriter is not implemented yet"); Loading @@ -626,34 +642,34 @@ status_t StagefrightRecorder::startAMRRecording() { mAudioEncoder != AUDIO_ENCODER_AMR_NB) { mAudioEncoder != AUDIO_ENCODER_AMR_NB) { LOGE("Invalid encoder %d used for AMRNB recording", LOGE("Invalid encoder %d used for AMRNB recording", mAudioEncoder); mAudioEncoder); return UNKNOWN_ERROR; return BAD_VALUE; } } if (mSampleRate != 8000) { if (mSampleRate != 8000) { LOGE("Invalid sampling rate %d used for AMRNB recording", LOGE("Invalid sampling rate %d used for AMRNB recording", mSampleRate); mSampleRate); return UNKNOWN_ERROR; return BAD_VALUE; } } } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { LOGE("Invlaid encoder %d used for AMRWB recording", LOGE("Invlaid encoder %d used for AMRWB recording", mAudioEncoder); mAudioEncoder); return UNKNOWN_ERROR; return BAD_VALUE; } } if (mSampleRate != 16000) { if (mSampleRate != 16000) { LOGE("Invalid sample rate %d used for AMRWB recording", LOGE("Invalid sample rate %d used for AMRWB recording", mSampleRate); mSampleRate); return UNKNOWN_ERROR; return BAD_VALUE; } } } } if (mAudioChannels != 1) { if (mAudioChannels != 1) { LOGE("Invalid number of audio channels %d used for amr recording", LOGE("Invalid number of audio channels %d used for amr recording", mAudioChannels); mAudioChannels); return UNKNOWN_ERROR; return BAD_VALUE; } } if (mAudioSource >= AUDIO_SOURCE_LIST_END) { if (mAudioSource >= AUDIO_SOURCE_LIST_END) { LOGE("Invalid audio source: %d", mAudioSource); LOGE("Invalid audio source: %d", mAudioSource); return UNKNOWN_ERROR; return BAD_VALUE; } } sp<MediaSource> audioEncoder = createAudioSource(); sp<MediaSource> audioEncoder = createAudioSource(); Loading @@ -662,7 +678,6 @@ status_t StagefrightRecorder::startAMRRecording() { return UNKNOWN_ERROR; return UNKNOWN_ERROR; } } CHECK(mOutputFd >= 0); mWriter = new AMRWriter(dup(mOutputFd)); mWriter = new AMRWriter(dup(mOutputFd)); mWriter->addSource(audioEncoder); mWriter->addSource(audioEncoder); Loading Loading @@ -729,50 +744,7 @@ void StagefrightRecorder::clipVideoFrameWidth() { } } } } void StagefrightRecorder::clipVideoFrameHeight() { status_t StagefrightRecorder::setupCameraSource() { LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.min", mVideoEncoder); int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.max", mVideoEncoder); if (mVideoHeight < minFrameHeight) { LOGW("Intended video encoding frame height (%d) is too small" " and will be set to (%d)", mVideoHeight, minFrameHeight); mVideoHeight = minFrameHeight; } else if (mVideoHeight > maxFrameHeight) { LOGW("Intended video encoding frame height (%d) is too large" " and will be set to (%d)", mVideoHeight, maxFrameHeight); mVideoHeight = maxFrameHeight; } } status_t StagefrightRecorder::startMPEG4Recording() { mWriter = new MPEG4Writer(dup(mOutputFd)); int32_t totalBitRate = 0; // 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; } if (audioEncoder == NULL) { return UNKNOWN_ERROR; } totalBitRate += mAudioBitRate; mWriter->addSource(audioEncoder); } if (mVideoSource == VIDEO_SOURCE_DEFAULT || mVideoSource == VIDEO_SOURCE_CAMERA) { clipVideoBitRate(); clipVideoBitRate(); clipVideoFrameRate(); clipVideoFrameRate(); clipVideoFrameWidth(); clipVideoFrameWidth(); Loading @@ -789,7 +761,6 @@ status_t StagefrightRecorder::startMPEG4Recording() { mCamera->lock(); mCamera->lock(); } } // Set the actual video recording frame size // Set the actual video recording frame size CameraParameters params(mCamera->getParameters()); CameraParameters params(mCamera->getParameters()); params.setPreviewSize(mVideoWidth, mVideoHeight); params.setPreviewSize(mVideoWidth, mVideoHeight); Loading Loading @@ -818,10 +789,31 @@ status_t StagefrightRecorder::startMPEG4Recording() { CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); IPCThreadState::self()->restoreCallingIdentity(token); IPCThreadState::self()->restoreCallingIdentity(token); return OK; } sp<CameraSource> cameraSource = void StagefrightRecorder::clipVideoFrameHeight() { CameraSource::CreateFromCamera(mCamera); LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.min", mVideoEncoder); int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( "enc.vid.height.max", mVideoEncoder); if (mVideoHeight < minFrameHeight) { LOGW("Intended video encoding frame height (%d) is too small" " and will be set to (%d)", mVideoHeight, minFrameHeight); mVideoHeight = minFrameHeight; } else if (mVideoHeight > maxFrameHeight) { LOGW("Intended video encoding frame height (%d) is too large" " and will be set to (%d)", mVideoHeight, maxFrameHeight); mVideoHeight = maxFrameHeight; } } status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) { status_t err = setupCameraSource(); if (err != OK) return err; sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera); CHECK(cameraSource != NULL); CHECK(cameraSource != NULL); sp<MetaData> enc_meta = new MetaData; sp<MetaData> enc_meta = new MetaData; Loading Loading @@ -863,29 +855,64 @@ status_t StagefrightRecorder::startMPEG4Recording() { OMXClient client; OMXClient client; CHECK_EQ(client.connect(), OK); CHECK_EQ(client.connect(), OK); sp<MediaSource> encoder = sp<MediaSource> encoder = OMXCodec::Create( OMXCodec::Create( client.interface(), enc_meta, client.interface(), enc_meta, true /* createEncoder */, cameraSource); true /* createEncoder */, cameraSource); if (encoder == NULL) { return UNKNOWN_ERROR; } CHECK(mOutputFd >= 0); writer->addSource(encoder); totalBitRate += mVideoBitRate; return OK; mWriter->addSource(encoder); } } { status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { // MPEGWriter specific handling sp<MediaSource> audioEncoder; MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); switch(mAudioEncoder) { writer->setInterleaveDuration(mInterleaveDurationUs); 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; } if (audioEncoder == NULL) { return UNKNOWN_ERROR; } writer->addSource(audioEncoder); return OK; } status_t StagefrightRecorder::startMPEG4Recording() { int32_t totalBitRate = 0; status_t err = OK; sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd)); // 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; } } reinterpret_cast<MPEG4Writer *>(writer.get())-> setInterleaveDuration(mInterleaveDurationUs); if (mMaxFileDurationUs != 0) { if (mMaxFileDurationUs != 0) { mWriter->setMaxFileDuration(mMaxFileDurationUs); writer->setMaxFileDuration(mMaxFileDurationUs); } } if (mMaxFileSizeBytes != 0) { if (mMaxFileSizeBytes != 0) { mWriter->setMaxFileSize(mMaxFileSizeBytes); writer->setMaxFileSize(mMaxFileSizeBytes); } } mWriter->setListener(mListener); sp<MetaData> meta = new MetaData; sp<MetaData> meta = new MetaData; meta->setInt64(kKeyTime, systemTime() / 1000); meta->setInt64(kKeyTime, systemTime() / 1000); meta->setInt32(kKeyFileType, mOutputFormat); meta->setInt32(kKeyFileType, mOutputFormat); Loading @@ -897,8 +924,9 @@ status_t StagefrightRecorder::startMPEG4Recording() { if (mTrackEveryTimeDurationUs > 0) { if (mTrackEveryTimeDurationUs > 0) { meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); } } mWriter->start(meta.get()); writer->setListener(mListener); return OK; mWriter = writer; return mWriter->start(meta.get()); } } status_t StagefrightRecorder::pause() { status_t StagefrightRecorder::pause() { Loading @@ -914,7 +942,7 @@ status_t StagefrightRecorder::stop() { LOGV("stop"); LOGV("stop"); if (mWriter != NULL) { if (mWriter != NULL) { mWriter->stop(); mWriter->stop(); mWriter = NULL; mWriter.clear(); } } if (mCamera != 0) { if (mCamera != 0) { Loading @@ -925,7 +953,7 @@ status_t StagefrightRecorder::stop() { mCamera->stopPreview(); mCamera->stopPreview(); } } mCamera->unlock(); mCamera->unlock(); mCamera = NULL; mCamera.clear(); IPCThreadState::self()->restoreCallingIdentity(token); IPCThreadState::self()->restoreCallingIdentity(token); mFlags = 0; mFlags = 0; } } Loading
media/libmediaplayerservice/StagefrightRecorder.h +7 −1 Original line number Original line Diff line number Diff line Loading @@ -97,6 +97,11 @@ private: status_t startAMRRecording(); status_t startAMRRecording(); status_t startAACRecording(); status_t startAACRecording(); sp<MediaSource> createAudioSource(); 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 setParameter(const String8 &key, const String8 &value); status_t setParamAudioEncodingBitRate(int32_t bitRate); status_t setParamAudioEncodingBitRate(int32_t bitRate); status_t setParamAudioNumberOfChannels(int32_t channles); status_t setParamAudioNumberOfChannels(int32_t channles); Loading @@ -108,7 +113,8 @@ private: status_t setParamTrackFrameStatus(int32_t nFrames); status_t setParamTrackFrameStatus(int32_t nFrames); status_t setParamInterleaveDuration(int32_t durationUs); status_t setParamInterleaveDuration(int32_t durationUs); status_t setParam64BitFileOffset(bool use64BitFileOffset); 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 clipVideoBitRate(); void clipVideoFrameRate(); void clipVideoFrameRate(); void clipVideoFrameWidth(); void clipVideoFrameWidth(); Loading