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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user