diff options
Diffstat (limited to 'media/libmediaplayerservice')
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 10 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaRecorderClient.cpp | 14 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaRecorderClient.h | 4 | ||||
-rw-r--r-- | media/libmediaplayerservice/MidiFile.h | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightPlayer.cpp | 11 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightPlayer.h | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 448 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 54 | ||||
-rw-r--r-- | media/libmediaplayerservice/TestPlayerStub.h | 5 |
10 files changed, 411 insertions, 144 deletions
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index c43e9bb..80922d6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -891,7 +891,15 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64 return mStatus; } -status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface) +status_t MediaPlayerService::Client::setVideoISurface(const sp<ISurface>& surface) +{ + LOGV("[%d] setVideoISurface(%p)", mConnId, surface.get()); + sp<MediaPlayerBase> p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->setVideoISurface(surface); +} + +status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface) { LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get()); sp<MediaPlayerBase> p = getPlayer(); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 4492e20..c4e78f7 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -206,7 +206,8 @@ private: // IMediaPlayer interface virtual void disconnect(); - virtual status_t setVideoSurface(const sp<ISurface>& surface); + virtual status_t setVideoISurface(const sp<ISurface>& surface); + virtual status_t setVideoSurface(const sp<Surface>& surface); virtual status_t prepareAsync(); virtual status_t start(); virtual status_t stop(); diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 19915f1..be6a8be 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -70,7 +70,7 @@ status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera) return mRecorder->setCamera(camera); } -status_t MediaRecorderClient::setPreviewSurface(const sp<ISurface>& surface) +status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface) { LOGV("setPreviewSurface"); Mutex::Autolock lock(mLock); @@ -164,6 +164,17 @@ status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t leng return mRecorder->setOutputFile(fd, offset, length); } +status_t MediaRecorderClient::setOutputFileAuxiliary(int fd) +{ + LOGV("setOutputFileAuxiliary(%d)", fd); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NO_INIT; + } + return mRecorder->setOutputFileAuxiliary(fd); +} + status_t MediaRecorderClient::setVideoSize(int width, int height) { LOGV("setVideoSize(%dx%d)", width, height); @@ -337,4 +348,3 @@ status_t MediaRecorderClient::dump(int fd, const Vector<String16>& args) const { } }; // namespace android - diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 1d1913d..fded98e 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -29,7 +29,7 @@ class MediaRecorderClient : public BnMediaRecorder { public: virtual status_t setCamera(const sp<ICamera>& camera); - virtual status_t setPreviewSurface(const sp<ISurface>& surface); + virtual status_t setPreviewSurface(const sp<Surface>& surface); virtual status_t setVideoSource(int vs); virtual status_t setAudioSource(int as); virtual status_t setOutputFormat(int of); @@ -37,6 +37,7 @@ public: virtual status_t setAudioEncoder(int ae); virtual status_t setOutputFile(const char* path); virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); + virtual status_t setOutputFileAuxiliary(int fd); virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); virtual status_t setParameters(const String8& params); @@ -66,4 +67,3 @@ private: }; // namespace android #endif // ANDROID_MEDIARECORDERCLIENT_H - diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 4a60ece..06e4b70 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -35,7 +35,8 @@ public: const char* path, const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; } + virtual status_t setVideoISurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; } + virtual status_t setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; } virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index 6bded09..b3e2da0 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -44,13 +44,20 @@ status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length return mPlayer->setDataSource(dup(fd), offset, length); } -status_t StagefrightPlayer::setVideoSurface(const sp<ISurface> &surface) { - LOGV("setVideoSurface"); +status_t StagefrightPlayer::setVideoISurface(const sp<ISurface> &surface) { + LOGV("setVideoISurface"); mPlayer->setISurface(surface); return OK; } +status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) { + LOGV("setVideoSurface"); + + mPlayer->setSurface(surface); + return OK; +} + status_t StagefrightPlayer::prepare() { return mPlayer->prepare(); } diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index 781eb44..dd37102 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -35,7 +35,8 @@ public: const char *url, const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp<ISurface> &surface); + virtual status_t setVideoISurface(const sp<ISurface> &surface); + virtual status_t setVideoSurface(const sp<Surface> &surface); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index d37d83d..ec2449d 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -20,10 +20,12 @@ #include "StagefrightRecorder.h" -#include <binder/IPCThreadState.h> #include <media/stagefright/AudioSource.h> #include <media/stagefright/AMRWriter.h> #include <media/stagefright/CameraSource.h> +#include <media/stagefright/VideoSourceDownSampler.h> +#include <media/stagefright/CameraSourceTimeLapse.h> +#include <media/stagefright/MediaSourceSplitter.h> #include <media/stagefright/MPEG2TSWriter.h> #include <media/stagefright/MPEG4Writer.h> #include <media/stagefright/MediaDebug.h> @@ -33,21 +35,20 @@ #include <media/stagefright/OMXCodec.h> #include <media/MediaProfiles.h> #include <camera/ICamera.h> -#include <camera/Camera.h> #include <camera/CameraParameters.h> -#include <surfaceflinger/ISurface.h> +#include <surfaceflinger/Surface.h> #include <utils/Errors.h> #include <sys/types.h> -#include <unistd.h> #include <ctype.h> +#include <unistd.h> #include "ARTPWriter.h" namespace android { StagefrightRecorder::StagefrightRecorder() - : mWriter(NULL), - mOutputFd(-1) { + : mWriter(NULL), mWriterAux(NULL), + mOutputFd(-1), mOutputFdAux(-1) { LOGV("Constructor"); reset(); @@ -182,26 +183,11 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { return BAD_VALUE; } - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - mFlags &= ~FLAGS_HOT_CAMERA; - mCamera = Camera::create(camera); - if (mCamera == 0) { - LOGE("Unable to connect to camera"); - IPCThreadState::self()->restoreCallingIdentity(token); - return -EBUSY; - } - - LOGV("Connected to camera"); - if (mCamera->previewEnabled()) { - LOGV("camera is hot"); - mFlags |= FLAGS_HOT_CAMERA; - } - IPCThreadState::self()->restoreCallingIdentity(token); - + mCamera = camera; return OK; } -status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { +status_t StagefrightRecorder::setPreviewSurface(const sp<Surface> &surface) { LOGV("setPreviewSurface: %p", surface.get()); mPreviewSurface = surface; @@ -235,6 +221,24 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng return OK; } +status_t StagefrightRecorder::setOutputFileAuxiliary(int fd) { + LOGV("setOutputFileAuxiliary: %d", fd); + + if (fd < 0) { + LOGE("Invalid file descriptor: %d", fd); + return -EBADF; + } + + mCaptureAuxVideo = true; + + if (mOutputFdAux >= 0) { + ::close(mOutputFdAux); + } + mOutputFdAux = dup(fd); + + return OK; +} + // Attempt to parse an int64 literal optionally surrounded by whitespace, // returns true on success, false otherwise. static bool safe_strtoi64(const char *s, int64_t *val) { @@ -474,6 +478,68 @@ status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) { return OK; } +status_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) { + LOGV("setParamTimeLapseEnable: %d", timeLapseEnable); + + if(timeLapseEnable == 0) { + mCaptureTimeLapse = false; + } else if (timeLapseEnable == 1) { + mCaptureTimeLapse = true; + } else { + return BAD_VALUE; + } + return OK; +} + +status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) { + LOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs); + + // Not allowing time more than a day + if (timeUs <= 0 || timeUs > 86400*1E6) { + LOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs); + return BAD_VALUE; + } + + mTimeBetweenTimeLapseFrameCaptureUs = timeUs; + return OK; +} + +status_t StagefrightRecorder::setParamAuxVideoWidth(int32_t width) { + LOGV("setParamAuxVideoWidth : %d", width); + + if (width <= 0) { + LOGE("Width (%d) is not positive", width); + return BAD_VALUE; + } + + mAuxVideoWidth = width; + return OK; +} + +status_t StagefrightRecorder::setParamAuxVideoHeight(int32_t height) { + LOGV("setParamAuxVideoHeight : %d", height); + + if (height <= 0) { + LOGE("Height (%d) is not positive", height); + return BAD_VALUE; + } + + mAuxVideoHeight = height; + return OK; +} + +status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) { + LOGV("StagefrightRecorder::setParamAuxVideoEncodingBitRate: %d", bitRate); + + if (bitRate <= 0) { + LOGE("Invalid video encoding bit rate: %d", bitRate); + return BAD_VALUE; + } + + mAuxVideoBitRate = bitRate; + return OK; +} + status_t StagefrightRecorder::setParameter( const String8 &key, const String8 &value) { LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); @@ -557,6 +623,32 @@ status_t StagefrightRecorder::setParameter( if (safe_strtoi32(value.string(), &timeScale)) { return setParamVideoTimeScale(timeScale); } + } else if (key == "time-lapse-enable") { + int32_t timeLapseEnable; + if (safe_strtoi32(value.string(), &timeLapseEnable)) { + return setParamTimeLapseEnable(timeLapseEnable); + } + } else if (key == "time-between-time-lapse-frame-capture") { + int64_t timeBetweenTimeLapseFrameCaptureMs; + if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) { + return setParamTimeBetweenTimeLapseFrameCapture( + 1000LL * timeBetweenTimeLapseFrameCaptureMs); + } + } else if (key == "video-aux-param-width") { + int32_t auxWidth; + if (safe_strtoi32(value.string(), &auxWidth)) { + return setParamAuxVideoWidth(auxWidth); + } + } else if (key == "video-aux-param-height") { + int32_t auxHeight; + if (safe_strtoi32(value.string(), &auxHeight)) { + return setParamAuxVideoHeight(auxHeight); + } + } else if (key == "video-aux-param-encoding-bitrate") { + int32_t auxVideoBitRate; + if (safe_strtoi32(value.string(), &auxVideoBitRate)) { + return setParamAuxVideoEncodingBitRate(auxVideoBitRate); + } } else { LOGE("setParameter: failed to find key %s", key.string()); } @@ -790,7 +882,14 @@ status_t StagefrightRecorder::startRTPRecording() { if (mAudioSource != AUDIO_SOURCE_LIST_END) { source = createAudioSource(); } else { - status_t err = setupVideoEncoder(&source); + + sp<CameraSource> cameraSource; + status_t err = setupCameraSource(&cameraSource); + if (err != OK) { + return err; + } + + err = setupVideoEncoder(cameraSource, mVideoBitRate, &source); if (err != OK) { return err; } @@ -826,8 +925,14 @@ status_t StagefrightRecorder::startMPEG2TSRecording() { return ERROR_UNSUPPORTED; } + sp<CameraSource> cameraSource; + status_t err = setupCameraSource(&cameraSource); + if (err != OK) { + return err; + } + sp<MediaSource> encoder; - status_t err = setupVideoEncoder(&encoder); + err = setupVideoEncoder(cameraSource, mVideoBitRate, &encoder); if (err != OK) { return err; @@ -900,57 +1005,15 @@ 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(); - if (OK != mCamera->setParameters(s)) { - LOGE("Could not change settings." - " Someone else is using camera %d?", mCameraId); - return -EBUSY; - } - 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; +status_t StagefrightRecorder::checkVideoEncoderCapabilities() { + if (!mCaptureTimeLapse) { + // Dont clip for time lapse capture as encoder will have enough + // time to encode because of slow capture rate of time lapse. + clipVideoBitRate(); + clipVideoFrameRate(); + clipVideoFrameWidth(); + clipVideoFrameHeight(); } - - // 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); - } - - // This CHECK is good, since we just passed the lock/unlock - // check earlier by calling mCamera->setParameters(). - CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); - IPCThreadState::self()->restoreCallingIdentity(token); return OK; } @@ -971,17 +1034,33 @@ void StagefrightRecorder::clipVideoFrameHeight() { } } -status_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) { - source->clear(); +status_t StagefrightRecorder::setupCameraSource(sp<CameraSource> *cameraSource) { + Size videoSize; + videoSize.width = mVideoWidth; + videoSize.height = mVideoHeight; + if (mCaptureTimeLapse) { + mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera( + mCamera, mCameraId, + videoSize, mFrameRate, mPreviewSurface, + mTimeBetweenTimeLapseFrameCaptureUs); + *cameraSource = mCameraSourceTimeLapse; + } else { + *cameraSource = CameraSource::CreateFromCamera( + mCamera, mCameraId, videoSize, mFrameRate, mPreviewSurface); + } + CHECK(*cameraSource != NULL); - status_t err = setupCameraSource(); - if (err != OK) return err; + return OK; +} - sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera); - CHECK(cameraSource != NULL); +status_t StagefrightRecorder::setupVideoEncoder( + sp<MediaSource> cameraSource, + int32_t videoBitRate, + sp<MediaSource> *source) { + source->clear(); sp<MetaData> enc_meta = new MetaData; - enc_meta->setInt32(kKeyBitRate, mVideoBitRate); + enc_meta->setInt32(kKeyBitRate, videoBitRate); enc_meta->setInt32(kKeySampleRate, mFrameRate); switch (mVideoEncoder) { @@ -1025,14 +1104,24 @@ status_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) { } if (mVideoEncoderLevel != -1) { enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel); + } else if (mCaptureTimeLapse) { + // Check if we are using high resolution and/or high bitrate and + // set appropriate level for the software AVCEncoder. + if ((width * height >= 921600) // 720p + || (videoBitRate >= 20000000)) { + enc_meta->setInt32(kKeyVideoLevel, 50); + } } OMXClient client; CHECK_EQ(client.connect(), OK); + // Use software codec for time lapse + uint32_t encoder_flags = (mCaptureTimeLapse) ? OMXCodec::kPreferSoftwareCodecs : 0; sp<MediaSource> encoder = OMXCodec::Create( client.interface(), enc_meta, - true /* createEncoder */, cameraSource); + true /* createEncoder */, cameraSource, + NULL, encoder_flags); if (encoder == NULL) { return UNKNOWN_ERROR; } @@ -1063,51 +1152,147 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { return OK; } -status_t StagefrightRecorder::startMPEG4Recording() { - int32_t totalBitRate = 0; +status_t StagefrightRecorder::setupMPEG4Recording( + bool useSplitCameraSource, + int outputFd, + int32_t videoWidth, int32_t videoHeight, + int32_t videoBitRate, + int32_t *totalBitRate, + sp<MediaWriter> *mediaWriter) { + mediaWriter->clear(); + *totalBitRate = 0; status_t err = OK; - sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd)); + sp<MediaWriter> writer = new MPEG4Writer(dup(outputFd)); // Add audio source first if it exists - if (mAudioSource != AUDIO_SOURCE_LIST_END) { + if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) { err = setupAudioEncoder(writer); if (err != OK) return err; - totalBitRate += mAudioBitRate; + *totalBitRate += mAudioBitRate; } if (mVideoSource == VIDEO_SOURCE_DEFAULT || mVideoSource == VIDEO_SOURCE_CAMERA) { + + sp<MediaSource> cameraMediaSource; + if (useSplitCameraSource) { + LOGV("Using Split camera source"); + cameraMediaSource = mCameraSourceSplitter->createClient(); + } else { + sp<CameraSource> cameraSource; + err = setupCameraSource(&cameraSource); + cameraMediaSource = cameraSource; + } + if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) { + // Use downsampling from the original source. + cameraMediaSource = + new VideoSourceDownSampler(cameraMediaSource, videoWidth, videoHeight); + } + if (err != OK) { + return err; + } + sp<MediaSource> encoder; - err = setupVideoEncoder(&encoder); - if (err != OK) return err; + err = setupVideoEncoder(cameraMediaSource, videoBitRate, &encoder); + if (err != OK) { + return err; + } + writer->addSource(encoder); - totalBitRate += mVideoBitRate; + *totalBitRate += videoBitRate; } if (mInterleaveDurationUs > 0) { reinterpret_cast<MPEG4Writer *>(writer.get())-> setInterleaveDuration(mInterleaveDurationUs); } - if (mMaxFileDurationUs != 0) { writer->setMaxFileDuration(mMaxFileDurationUs); } if (mMaxFileSizeBytes != 0) { writer->setMaxFileSize(mMaxFileSizeBytes); } - sp<MetaData> meta = new MetaData; - meta->setInt64(kKeyTime, systemTime() / 1000); - meta->setInt32(kKeyFileType, mOutputFormat); - meta->setInt32(kKeyBitRate, totalBitRate); - meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); + + writer->setListener(mListener); + *mediaWriter = writer; + return OK; +} + +void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate, + sp<MetaData> *meta) { + (*meta)->setInt64(kKeyTime, startTimeUs); + (*meta)->setInt32(kKeyFileType, mOutputFormat); + (*meta)->setInt32(kKeyBitRate, totalBitRate); + (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); if (mMovieTimeScale > 0) { - meta->setInt32(kKeyTimeScale, mMovieTimeScale); + (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale); } if (mTrackEveryTimeDurationUs > 0) { - meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); + (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); } - writer->setListener(mListener); - mWriter = writer; - return mWriter->start(meta.get()); +} + +status_t StagefrightRecorder::startMPEG4Recording() { + if (mCaptureAuxVideo) { + if (!mCaptureTimeLapse) { + LOGE("Auxiliary video can be captured only in time lapse mode"); + return UNKNOWN_ERROR; + } + LOGV("Creating MediaSourceSplitter"); + sp<CameraSource> cameraSource; + status_t err = setupCameraSource(&cameraSource); + if (err != OK) { + return err; + } + mCameraSourceSplitter = new MediaSourceSplitter(cameraSource); + } else { + mCameraSourceSplitter = NULL; + } + + int32_t totalBitRate; + status_t err = setupMPEG4Recording(mCaptureAuxVideo, + mOutputFd, mVideoWidth, mVideoHeight, + mVideoBitRate, &totalBitRate, &mWriter); + if (err != OK) { + return err; + } + + int64_t startTimeUs = systemTime() / 1000; + sp<MetaData> meta = new MetaData; + setupMPEG4MetaData(startTimeUs, totalBitRate, &meta); + + err = mWriter->start(meta.get()); + if (err != OK) { + return err; + } + + if (mCaptureAuxVideo) { + CHECK(mOutputFdAux >= 0); + if (mWriterAux != NULL) { + LOGE("Auxiliary File writer is not avaialble"); + return UNKNOWN_ERROR; + } + if ((mAuxVideoWidth > mVideoWidth) || (mAuxVideoHeight > mVideoHeight) || + ((mAuxVideoWidth == mVideoWidth) && mAuxVideoHeight == mVideoHeight)) { + LOGE("Auxiliary video size (%d x %d) same or larger than the main video size (%d x %d)", + mAuxVideoWidth, mAuxVideoHeight, mVideoWidth, mVideoHeight); + return UNKNOWN_ERROR; + } + + int32_t totalBitrateAux; + err = setupMPEG4Recording(mCaptureAuxVideo, + mOutputFdAux, mAuxVideoWidth, mAuxVideoHeight, + mAuxVideoBitRate, &totalBitrateAux, &mWriterAux); + if (err != OK) { + return err; + } + + sp<MetaData> metaAux = new MetaData; + setupMPEG4MetaData(startTimeUs, totalBitrateAux, &metaAux); + + return mWriterAux->start(metaAux.get()); + } + + return OK; } status_t StagefrightRecorder::pause() { @@ -1116,28 +1301,36 @@ status_t StagefrightRecorder::pause() { return UNKNOWN_ERROR; } mWriter->pause(); + + if (mCaptureAuxVideo) { + if (mWriterAux == NULL) { + return UNKNOWN_ERROR; + } + mWriterAux->pause(); + } + return OK; } status_t StagefrightRecorder::stop() { LOGV("stop"); status_t err = OK; - if (mWriter != NULL) { - err = mWriter->stop(); - mWriter.clear(); + + if (mCaptureTimeLapse && mCameraSourceTimeLapse != NULL) { + mCameraSourceTimeLapse->startQuickReadReturns(); + mCameraSourceTimeLapse = NULL; } - if (mCamera != 0) { - LOGV("Disconnect camera"); - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - if ((mFlags & FLAGS_HOT_CAMERA) == 0) { - LOGV("Camera was cold when we started, stopping preview"); - mCamera->stopPreview(); + if (mCaptureAuxVideo) { + if (mWriterAux != NULL) { + mWriterAux->stop(); + mWriterAux.clear(); } - mCamera->unlock(); - mCamera.clear(); - IPCThreadState::self()->restoreCallingIdentity(token); - mFlags = 0; + } + + if (mWriter != NULL) { + err = mWriter->stop(); + mWriter.clear(); } if (mOutputFd >= 0) { @@ -1145,6 +1338,13 @@ status_t StagefrightRecorder::stop() { mOutputFd = -1; } + if (mCaptureAuxVideo) { + if (mOutputFdAux >= 0) { + ::close(mOutputFdAux); + mOutputFdAux = -1; + } + } + return err; } @@ -1169,8 +1369,11 @@ status_t StagefrightRecorder::reset() { mVideoEncoder = VIDEO_ENCODER_H263; mVideoWidth = 176; mVideoHeight = 144; + mAuxVideoWidth = 176; + mAuxVideoHeight = 144; mFrameRate = 20; mVideoBitRate = 192000; + mAuxVideoBitRate = 192000; mSampleRate = 8000; mAudioChannels = 1; mAudioBitRate = 12200; @@ -1187,10 +1390,15 @@ status_t StagefrightRecorder::reset() { mMaxFileDurationUs = 0; mMaxFileSizeBytes = 0; mTrackEveryTimeDurationUs = 0; + mCaptureTimeLapse = false; + mTimeBetweenTimeLapseFrameCaptureUs = -1; + mCaptureAuxVideo = false; + mCameraSourceSplitter = NULL; + mCameraSourceTimeLapse = NULL; mEncoderProfiles = MediaProfiles::getInstance(); mOutputFd = -1; - mFlags = 0; + mOutputFdAux = -1; return OK; } @@ -1227,6 +1435,8 @@ status_t StagefrightRecorder::dump( snprintf(buffer, SIZE, " Recorder: %p\n", this); snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd); result.append(buffer); + snprintf(buffer, SIZE, " Output file Auxiliary (fd %d):\n", mOutputFdAux); + result.append(buffer); snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat); result.append(buffer); snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes); @@ -1259,8 +1469,6 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " Camera Id: %d\n", mCameraId); result.append(buffer); - snprintf(buffer, SIZE, " Camera flags: %d\n", mFlags); - result.append(buffer); snprintf(buffer, SIZE, " Encoder: %d\n", mVideoEncoder); result.append(buffer); snprintf(buffer, SIZE, " Encoder profile: %d\n", mVideoEncoderProfile); @@ -1271,10 +1479,14 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight); result.append(buffer); + snprintf(buffer, SIZE, " Aux Frame size (pixels): %dx%d\n", mAuxVideoWidth, mAuxVideoHeight); + result.append(buffer); snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate); result.append(buffer); snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate); result.append(buffer); + snprintf(buffer, SIZE, " Aux Bit rate (bps): %d\n", mAuxVideoBitRate); + result.append(buffer); ::write(fd, result.string(), result.size()); return OK; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index ad0dfa0..7d2549f 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -19,13 +19,18 @@ #define STAGEFRIGHT_RECORDER_H_ #include <media/MediaRecorderBase.h> +#include <camera/CameraParameters.h> #include <utils/String8.h> namespace android { class Camera; +class CameraSource; +class CameraSourceTimeLapse; +class MediaSourceSplitter; struct MediaSource; struct MediaWriter; +class MetaData; struct AudioSource; class MediaProfiles; @@ -42,9 +47,10 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); virtual status_t setCamera(const sp<ICamera>& camera); - virtual status_t setPreviewSurface(const sp<ISurface>& surface); + virtual status_t setPreviewSurface(const sp<Surface>& surface); virtual status_t setOutputFile(const char *path); virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); + virtual status_t setOutputFileAuxiliary(int fd); virtual status_t setParameters(const String8& params); virtual status_t setListener(const sp<IMediaRecorderClient>& listener); virtual status_t prepare(); @@ -57,15 +63,10 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t dump(int fd, const Vector<String16>& args) const; private: - enum CameraFlags { - FLAGS_SET_CAMERA = 1L << 0, - FLAGS_HOT_CAMERA = 1L << 1, - }; - - sp<Camera> mCamera; - sp<ISurface> mPreviewSurface; + sp<ICamera> mCamera; + sp<Surface> mPreviewSurface; sp<IMediaRecorderClient> mListener; - sp<MediaWriter> mWriter; + sp<MediaWriter> mWriter, mWriterAux; sp<AudioSource> mAudioSourceNode; audio_source mAudioSource; @@ -75,8 +76,9 @@ private: video_encoder mVideoEncoder; bool mUse64BitFileOffset; int32_t mVideoWidth, mVideoHeight; + int32_t mAuxVideoWidth, mAuxVideoHeight; int32_t mFrameRate; - int32_t mVideoBitRate; + int32_t mVideoBitRate, mAuxVideoBitRate; int32_t mAudioBitRate; int32_t mAudioChannels; int32_t mSampleRate; @@ -92,21 +94,39 @@ private: int64_t mMaxFileDurationUs; int64_t mTrackEveryTimeDurationUs; + bool mCaptureTimeLapse; + int64_t mTimeBetweenTimeLapseFrameCaptureUs; + bool mCaptureAuxVideo; + sp<MediaSourceSplitter> mCameraSourceSplitter; + sp<CameraSourceTimeLapse> mCameraSourceTimeLapse; + String8 mParams; - int mOutputFd; - int32_t mFlags; + int mOutputFd, mOutputFdAux; MediaProfiles *mEncoderProfiles; + status_t setupMPEG4Recording( + bool useSplitCameraSource, + int outputFd, + int32_t videoWidth, int32_t videoHeight, + int32_t videoBitRate, + int32_t *totalBitRate, + sp<MediaWriter> *mediaWriter); + void setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate, + sp<MetaData> *meta); status_t startMPEG4Recording(); status_t startAMRRecording(); status_t startAACRecording(); status_t startRTPRecording(); status_t startMPEG2TSRecording(); sp<MediaSource> createAudioSource(); - status_t setupCameraSource(); + status_t checkVideoEncoderCapabilities(); + status_t setupCameraSource(sp<CameraSource> *cameraSource); status_t setupAudioEncoder(const sp<MediaWriter>& writer); - status_t setupVideoEncoder(sp<MediaSource> *source); + status_t setupVideoEncoder( + sp<MediaSource> cameraSource, + int32_t videoBitRate, + sp<MediaSource> *source); // Encoding parameter handling utilities status_t setParameter(const String8 &key, const String8 &value); @@ -114,6 +134,11 @@ private: status_t setParamAudioNumberOfChannels(int32_t channles); status_t setParamAudioSamplingRate(int32_t sampleRate); status_t setParamAudioTimeScale(int32_t timeScale); + status_t setParamTimeLapseEnable(int32_t timeLapseEnable); + status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs); + status_t setParamAuxVideoHeight(int32_t height); + status_t setParamAuxVideoWidth(int32_t width); + status_t setParamAuxVideoEncodingBitRate(int32_t bitRate); status_t setParamVideoEncodingBitRate(int32_t bitRate); status_t setParamVideoIFramesInterval(int32_t seconds); status_t setParamVideoEncoderProfile(int32_t profile); @@ -138,4 +163,3 @@ private: } // namespace android #endif // STAGEFRIGHT_RECORDER_H_ - diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 6e6c3cd..5eaf592 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -75,7 +75,10 @@ class TestPlayerStub : public MediaPlayerInterface { // All the methods below wrap the mPlayer instance. - virtual status_t setVideoSurface(const android::sp<android::ISurface>& s) { + virtual status_t setVideoISurface(const android::sp<android::ISurface>& s) { + return mPlayer->setVideoISurface(s); + } + virtual status_t setVideoSurface(const android::sp<android::Surface>& s) { return mPlayer->setVideoSurface(s); } virtual status_t prepare() {return mPlayer->prepare();} |