diff options
author | Nipun Kwatra <nkwatra@google.com> | 2010-08-26 17:05:18 -0700 |
---|---|---|
committer | Nipun Kwatra <nkwatra@google.com> | 2010-08-31 10:38:49 -0700 |
commit | d7e7a3f98ffb5da7fe070de2e2dc3db338930b57 (patch) | |
tree | 4078ce59487fa9827b0a7bb868b19751592e9469 /media | |
parent | 6b2a75751d93fb2a4124e979603d79634ac017e0 (diff) | |
download | frameworks_base-d7e7a3f98ffb5da7fe070de2e2dc3db338930b57.zip frameworks_base-d7e7a3f98ffb5da7fe070de2e2dc3db338930b57.tar.gz frameworks_base-d7e7a3f98ffb5da7fe070de2e2dc3db338930b57.tar.bz2 |
Adding support for parallel recording sessions.
- Added setOutputFileAuxiliary to pass the auxiliary file descriptor. The java
interface through JNI will be checked in next.
- renamed setupCameraSource to setupCamera as the function just sets the camera.
- Added setupCameraSource which sets up the camera source. This functionality
was in setupVideoEncoder before.
- setupVideoEncoder now takes in a cameraSource instead of creating it on it
own.
- Refactored startMPEG4Recording() to use setupMPEG4Recording,
setupMPEG4MetaData.
- setupMPEG4Recording() takes in file descriptor, bitrates to setup a mpeg4
writer. This function can be called multiple times to setup multiple
writers.
- Added setupMPEG4MetaData() for setting up the meta data for mpeg4 writer.
startMPEG4Recording() now calls setupMPEG4Recording, setupMPEG4MetaData for
each recording session.
Change-Id: I07f5334a1ff8e12a36f58e94129fcfa6add2208b
Diffstat (limited to 'media')
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 202 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 29 | ||||
-rw-r--r-- | media/libstagefright/Android.mk | 3 |
3 files changed, 198 insertions, 36 deletions
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index a24e56c..bbbf45c 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -25,6 +25,7 @@ #include <media/stagefright/AMRWriter.h> #include <media/stagefright/CameraSource.h> #include <media/stagefright/CameraSourceTimeLapse.h> +#include <media/stagefright/MediaSourceSplitter.h> #include <media/stagefright/MPEG4Writer.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> @@ -46,8 +47,8 @@ namespace android { StagefrightRecorder::StagefrightRecorder() - : mWriter(NULL), - mOutputFd(-1) { + : mWriter(NULL), mWriterAux(NULL), + mOutputFd(-1), mOutputFdAux(-1) { LOGV("Constructor"); reset(); @@ -235,6 +236,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) { @@ -842,7 +861,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; } @@ -906,7 +932,7 @@ void StagefrightRecorder::clipVideoFrameWidth() { } } -status_t StagefrightRecorder::setupCameraSource() { +status_t StagefrightRecorder::setupCamera() { if (!mCaptureTimeLapse) { // Dont clip for time lapse capture as encoder will have enough // time to encode because of slow capture rate of time lapse. @@ -989,20 +1015,27 @@ void StagefrightRecorder::clipVideoFrameHeight() { } } -status_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) { - source->clear(); - - status_t err = setupCameraSource(); +status_t StagefrightRecorder::setupCameraSource(sp<CameraSource> *cameraSource) { + status_t err = setupCamera(); if (err != OK) return err; - sp<CameraSource> cameraSource = (mCaptureTimeLapse) ? + *cameraSource = (mCaptureTimeLapse) ? CameraSourceTimeLapse::CreateFromCamera(mCamera, mUseStillCameraForTimeLapse, mTimeBetweenTimeLapseFrameCaptureUs, mVideoWidth, mVideoHeight, mFrameRate): CameraSource::CreateFromCamera(mCamera); - CHECK(cameraSource != NULL); + CHECK(*cameraSource != NULL); + + return OK; +} + +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) { @@ -1087,51 +1120,128 @@ 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 audioBitRate, 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 (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) { err = setupAudioEncoder(writer); if (err != OK) return err; - totalBitRate += mAudioBitRate; + *totalBitRate += audioBitRate; } 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 (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) { + 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, mAudioBitRate, 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; + } + + int32_t totalBitrateAux; + err = setupMPEG4Recording(mCaptureAuxVideo, + mOutputFdAux, mAudioBitRateAux, mVideoBitRateAux, &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() { @@ -1140,12 +1250,28 @@ 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 (mCaptureAuxVideo) { + if (mWriterAux != NULL) { + mWriterAux->stop(); + mWriterAux.clear(); + } + } + if (mWriter != NULL) { err = mWriter->stop(); mWriter.clear(); @@ -1169,6 +1295,13 @@ status_t StagefrightRecorder::stop() { mOutputFd = -1; } + if (mCaptureAuxVideo) { + if (mOutputFdAux >= 0) { + ::close(mOutputFdAux); + mOutputFdAux = -1; + } + } + return err; } @@ -1195,9 +1328,11 @@ status_t StagefrightRecorder::reset() { mVideoHeight = 144; mFrameRate = 20; mVideoBitRate = 192000; + mVideoBitRateAux = 20000000; mSampleRate = 8000; mAudioChannels = 1; mAudioBitRate = 12200; + mAudioBitRateAux = 12200; mInterleaveDurationUs = 0; mIFramesIntervalSec = 1; mAudioSourceNode = 0; @@ -1214,9 +1349,12 @@ status_t StagefrightRecorder::reset() { mCaptureTimeLapse = false; mUseStillCameraForTimeLapse = true; mTimeBetweenTimeLapseFrameCaptureUs = -1; + mCaptureAuxVideo = false; + mCameraSourceSplitter = NULL; mEncoderProfiles = MediaProfiles::getInstance(); mOutputFd = -1; + mOutputFdAux = -1; mFlags = 0; return OK; @@ -1254,6 +1392,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); @@ -1274,6 +1414,8 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mAudioBitRate); result.append(buffer); + snprintf(buffer, SIZE, " Bit rate auxiliary (bps): %d\n", mAudioBitRateAux); + result.append(buffer); snprintf(buffer, SIZE, " Sampling rate (hz): %d\n", mSampleRate); result.append(buffer); snprintf(buffer, SIZE, " Number of channels: %d\n", mAudioChannels); @@ -1302,6 +1444,8 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate); result.append(buffer); + snprintf(buffer, SIZE, " Bit rate Auxiliary (bps): %d\n", mVideoBitRateAux); + result.append(buffer); ::write(fd, result.string(), result.size()); return OK; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 628e19b..d75a540 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -24,8 +24,11 @@ namespace android { class Camera; +class CameraSource; +class MediaSourceSplitter; struct MediaSource; struct MediaWriter; +class MetaData; struct AudioSource; class MediaProfiles; @@ -45,6 +48,7 @@ struct StagefrightRecorder : public MediaRecorderBase { 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(); @@ -65,7 +69,7 @@ private: sp<Camera> mCamera; sp<Surface> mPreviewSurface; sp<IMediaRecorderClient> mListener; - sp<MediaWriter> mWriter; + sp<MediaWriter> mWriter, mWriterAux; sp<AudioSource> mAudioSourceNode; audio_source mAudioSource; @@ -76,8 +80,8 @@ private: bool mUse64BitFileOffset; int32_t mVideoWidth, mVideoHeight; int32_t mFrameRate; - int32_t mVideoBitRate; - int32_t mAudioBitRate; + int32_t mVideoBitRate, mVideoBitRateAux; + int32_t mAudioBitRate, mAudioBitRateAux; int32_t mAudioChannels; int32_t mSampleRate; int32_t mInterleaveDurationUs; @@ -95,21 +99,34 @@ private: bool mCaptureTimeLapse; bool mUseStillCameraForTimeLapse; int64_t mTimeBetweenTimeLapseFrameCaptureUs; + bool mCaptureAuxVideo; + sp<MediaSourceSplitter> mCameraSourceSplitter; String8 mParams; - int mOutputFd; + int mOutputFd, mOutputFdAux; int32_t mFlags; MediaProfiles *mEncoderProfiles; + status_t setupMPEG4Recording( + bool useAuxiliaryCameraSource, + int outputFd, int32_t audioBitRate, 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(); sp<MediaSource> createAudioSource(); - status_t setupCameraSource(); + status_t setupCamera(); + 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); diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index b5a6327..6b7947e 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -10,7 +10,7 @@ LOCAL_SRC_FILES:= \ AudioSource.cpp \ AwesomePlayer.cpp \ CameraSource.cpp \ - CameraSourceTimeLapse.cpp \ + CameraSourceTimeLapse.cpp \ DataSource.cpp \ ESDS.cpp \ FileSource.cpp \ @@ -24,6 +24,7 @@ LOCAL_SRC_FILES:= \ MediaDefs.cpp \ MediaExtractor.cpp \ MediaSource.cpp \ + MediaSourceSplitter.cpp \ MetaData.cpp \ NuCachedSource2.cpp \ NuHTTPDataSource.cpp \ |