summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp191
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h5
2 files changed, 174 insertions, 22 deletions
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 57db7e4..12e8fe6 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/OMXCodec.h>
#include <camera/ICamera.h>
#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
#include <surfaceflinger/ISurface.h>
#include <utils/Errors.h>
#include <sys/types.h>
@@ -88,6 +89,12 @@ status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
}
status_t StagefrightRecorder::setVideoSize(int width, int height) {
+ if (width <= 0 || height <= 0) {
+ LOGE("Invalid video size: %dx%d", width, height);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the dimension will be performed later
mVideoWidth = width;
mVideoHeight = height;
@@ -95,6 +102,12 @@ status_t StagefrightRecorder::setVideoSize(int width, int height) {
}
status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
+ if (frames_per_second <= 0 || frames_per_second > 30) {
+ LOGE("Invalid video frame rate: %d", frames_per_second);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the frame rate will be performed later
mFrameRate = frames_per_second;
return OK;
@@ -152,9 +165,9 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng
// Attempt to parse an int64 literal optionally surrounded by whitespace,
// returns true on success, false otherwise.
-static bool safe_strtoi64(const char *s, int32_t *val) {
+static bool safe_strtoi64(const char *s, int64_t *val) {
char *end;
- *val = static_cast<int32_t>(strtoll(s, &end, 10));
+ *val = strtoll(s, &end, 10);
if (end == s || errno == ERANGE) {
return false;
@@ -171,6 +184,18 @@ static bool safe_strtoi64(const char *s, int32_t *val) {
return *end == '\0';
}
+// Return true if the value is in [0, 0x007FFFFFFF]
+static bool safe_strtoi32(const char *s, int32_t *val) {
+ int64_t temp;
+ if (safe_strtoi64(s, &temp)) {
+ if (temp >= 0 && temp <= 0x007FFFFFFF) {
+ *val = static_cast<int32_t>(temp);
+ return true;
+ }
+ }
+ return false;
+}
+
// Trim both leading and trailing whitespace from the given string.
static void TrimString(String8 *s) {
size_t num_bytes = s->bytes();
@@ -191,85 +216,129 @@ static void TrimString(String8 *s) {
status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
LOGV("setParamAudioSamplingRate: %d", sampleRate);
+ if (sampleRate <= 0) {
+ LOGE("Invalid audio sampling rate: %d", sampleRate);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the sample rate will be performed later.
mSampleRate = sampleRate;
return OK;
}
status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
LOGV("setParamAudioNumberOfChannels: %d", channels);
+ if (channels <= 0 || channels >= 3) {
+ LOGE("Invalid number of audio channels: %d", channels);
+ }
+
+ // Additional check on the number of channels will be performed later.
mAudioChannels = channels;
return OK;
}
status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
LOGV("setParamAudioEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ LOGE("Invalid audio encoding bit rate: %d", bitRate);
+ return BAD_VALUE;
+ }
+
+ // The target bit rate may not be exactly the same as the requested.
+ // It depends on many factors, such as rate control, and the bit rate
+ // range that a specific encoder supports. The mismatch between the
+ // the target and requested bit rate will NOT be treated as an error.
mAudioBitRate = bitRate;
return OK;
}
status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
LOGV("setParamVideoEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ LOGE("Invalid video encoding bit rate: %d", bitRate);
+ return BAD_VALUE;
+ }
+
+ // The target bit rate may not be exactly the same as the requested.
+ // It depends on many factors, such as rate control, and the bit rate
+ // range that a specific encoder supports. The mismatch between the
+ // the target and requested bit rate will NOT be treated as an error.
mVideoBitRate = bitRate;
return OK;
}
-status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int32_t limit,
+status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit,
bool limit_is_duration) {
LOGV("setParamMaxDurationOrFileSize: limit (%d) for %s",
limit, limit_is_duration?"duration":"size");
+ if (limit_is_duration) { // limit is in ms
+ if (limit <= 1000) { // XXX: 1 second
+ LOGE("Max file duration is too short: %lld us", limit);
+ }
+ mMaxFileDurationUs = limit * 1000LL;
+ } else {
+ if (limit <= 1024) { // XXX: 1 kB
+ LOGE("Max file size is too small: %lld bytes", limit);
+ }
+ mMaxFileSizeBytes = limit;
+ }
return OK;
}
status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
LOGV("setParamInterleaveDuration: %d", durationUs);
+ if (durationUs <= 20000) { // XXX: 20 ms
+ LOGE("Audio/video interleave duration is too small: %d us", durationUs);
+ return BAD_VALUE;
+ }
mInterleaveDurationUs = durationUs;
return OK;
}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
if (key == "max-duration") {
- int32_t max_duration_ms;
+ int64_t max_duration_ms;
if (safe_strtoi64(value.string(), &max_duration_ms)) {
return setParamMaxDurationOrFileSize(
max_duration_ms, true /* limit_is_duration */);
}
} else if (key == "max-filesize") {
- int32_t max_filesize_bytes;
+ int64_t max_filesize_bytes;
if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
return setParamMaxDurationOrFileSize(
max_filesize_bytes, false /* limit is filesize */);
}
} else if (key == "audio-param-sampling-rate") {
int32_t sampling_rate;
- if (safe_strtoi64(value.string(), &sampling_rate)) {
+ if (safe_strtoi32(value.string(), &sampling_rate)) {
return setParamAudioSamplingRate(sampling_rate);
}
} else if (key == "audio-param-number-of-channels") {
int32_t number_of_channels;
- if (safe_strtoi64(value.string(), &number_of_channels)) {
+ if (safe_strtoi32(value.string(), &number_of_channels)) {
return setParamAudioNumberOfChannels(number_of_channels);
}
} else if (key == "audio-param-encoding-bitrate") {
int32_t audio_bitrate;
- if (safe_strtoi64(value.string(), &audio_bitrate)) {
+ if (safe_strtoi32(value.string(), &audio_bitrate)) {
return setParamAudioEncodingBitRate(audio_bitrate);
}
} else if (key == "video-param-encoding-bitrate") {
int32_t video_bitrate;
- if (safe_strtoi64(value.string(), &video_bitrate)) {
+ if (safe_strtoi32(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitRate(video_bitrate);
}
} else if (key == "param-interleave-duration-us") {
int32_t durationUs;
- if (safe_strtoi64(value.string(), &durationUs)) {
+ if (safe_strtoi32(value.string(), &durationUs)) {
return setParamInterleaveDuration(durationUs);
}
} else {
LOGE("setParameter: failed to find key %s", key.string());
- return BAD_VALUE;
}
- return OK;
+ return BAD_VALUE;
}
status_t StagefrightRecorder::setParameters(const String8 &params) {
@@ -332,6 +401,10 @@ status_t StagefrightRecorder::start() {
case OUTPUT_FORMAT_AMR_WB:
return startAMRRecording();
+ case OUTPUT_FORMAT_AAC_ADIF:
+ case OUTPUT_FORMAT_AAC_ADTS:
+ return startAACRecording();
+
default:
return UNKNOWN_ERROR;
}
@@ -377,6 +450,7 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
encMeta->setInt32(kKeyChannelCount, mAudioChannels);
encMeta->setInt32(kKeySampleRate, mSampleRate);
+ encMeta->setInt32(kKeyBitRate, mAudioBitRate);
OMXClient client;
CHECK_EQ(client.connect(), OK);
@@ -388,18 +462,55 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
return audioEncoder;
}
+status_t StagefrightRecorder::startAACRecording() {
+ CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF ||
+ mOutputFormat == OUTPUT_FORMAT_AAC_ADTS);
+
+ CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
+ CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
+ CHECK(mOutputFd >= 0);
+
+ CHECK(0 == "AACWriter is not implemented yet");
+
+ return OK;
+}
+
status_t StagefrightRecorder::startAMRRecording() {
- if (mAudioSource == AUDIO_SOURCE_LIST_END
- || mVideoSource != VIDEO_SOURCE_LIST_END) {
+ CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
+ mOutputFormat == OUTPUT_FORMAT_AMR_WB);
+
+ if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
+ if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
+ mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
+ LOGE("Invalid encoder %d used for AMRNB recording",
+ mAudioEncoder);
+ return UNKNOWN_ERROR;
+ }
+ if (mSampleRate != 8000) {
+ LOGE("Invalid sampling rate %d used for AMRNB recording",
+ mSampleRate);
+ return UNKNOWN_ERROR;
+ }
+ } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
+ if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ LOGE("Invlaid encoder %d used for AMRWB recording",
+ mAudioEncoder);
+ return UNKNOWN_ERROR;
+ }
+ if (mSampleRate != 16000) {
+ LOGE("Invalid sample rate %d used for AMRWB recording",
+ mSampleRate);
+ return UNKNOWN_ERROR;
+ }
+ }
+ if (mAudioChannels != 1) {
+ LOGE("Invalid number of audio channels %d used for amr recording",
+ mAudioChannels);
return UNKNOWN_ERROR;
}
- if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
- && mAudioEncoder != AUDIO_ENCODER_DEFAULT
- && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
- return UNKNOWN_ERROR;
- } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
- && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
+ LOGE("Invalid audio source: %d", mAudioSource);
return UNKNOWN_ERROR;
}
@@ -444,6 +555,36 @@ status_t StagefrightRecorder::startMPEG4Recording() {
|| mVideoSource == VIDEO_SOURCE_CAMERA) {
CHECK(mCamera != NULL);
+ if (mCamera == 0) {
+ mCamera = Camera::connect(0);
+ }
+ CHECK(mCamera != NULL);
+
+ // Set the actual video recording frame size
+ CameraParameters params(mCamera->getParameters());
+ params.setPreviewSize(mVideoWidth, mVideoHeight);
+ params.setPreviewFrameRate(mFrameRate);
+ String8 s = params.flatten();
+ CHECK_EQ(OK, mCamera->setParameters(s));
+ CameraParameters newCameraParams(mCamera->getParameters());
+
+ // Check on video frame size
+ int frameWidth = 0, frameHeight = 0;
+ newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
+ if (frameWidth < 0 || frameWidth != mVideoWidth ||
+ frameHeight < 0 || frameHeight != mVideoHeight) {
+ LOGE("Failed to set the video frame size to %dx%d",
+ mVideoWidth, mVideoHeight);
+ return UNKNOWN_ERROR;
+ }
+
+ // Check on video frame rate
+ int frameRate = newCameraParams.getPreviewFrameRate();
+ if (frameRate < 0 || (frameRate - mFrameRate) != 0) {
+ LOGE("Failed to set frame rate to %d", mFrameRate);
+ return UNKNOWN_ERROR;
+ }
+
sp<CameraSource> cameraSource =
CameraSource::CreateFromCamera(mCamera);
@@ -452,6 +593,9 @@ status_t StagefrightRecorder::startMPEG4Recording() {
cameraSource->setPreviewSurface(mPreviewSurface);
sp<MetaData> enc_meta = new MetaData;
+ enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
+ enc_meta->setInt32(kKeySampleRate, mFrameRate); // XXX: kKeySampleRate?
+
switch (mVideoEncoder) {
case VIDEO_ENCODER_H263:
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
@@ -491,7 +635,12 @@ status_t StagefrightRecorder::startMPEG4Recording() {
mWriter->addSource(encoder);
}
- ((MPEG4Writer *)mWriter.get())->setInterleaveDuration(mInterleaveDurationUs);
+ {
+ // MPEGWriter specific handling
+ MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); // mWriter is an MPEGWriter
+ writer->setInterleaveDuration(mInterleaveDurationUs);
+ }
+
mWriter->start();
return OK;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 3b99e91..b7d554b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -75,6 +75,8 @@ private:
int32_t mAudioChannels;
int32_t mSampleRate;
int32_t mInterleaveDurationUs;
+ int64_t mMaxFileSizeBytes;
+ int64_t mMaxFileDurationUs;
String8 mParams;
int mOutputFd;
@@ -82,6 +84,7 @@ private:
status_t startMPEG4Recording();
status_t startAMRRecording();
+ status_t startAACRecording();
sp<MediaSource> createAudioSource();
status_t setParameter(const String8 &key, const String8 &value);
status_t setParamVideoEncodingBitRate(int32_t bitRate);
@@ -89,7 +92,7 @@ private:
status_t setParamAudioNumberOfChannels(int32_t channles);
status_t setParamAudioSamplingRate(int32_t sampleRate);
status_t setParamInterleaveDuration(int32_t durationUs);
- status_t setParamMaxDurationOrFileSize(int32_t limit, bool limit_is_duration);
+ status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration);
StagefrightRecorder(const StagefrightRecorder &);
StagefrightRecorder &operator=(const StagefrightRecorder &);