summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-02 22:54:33 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-02 22:54:33 -0800
commit99ffda877980468a9ae31e013cd10fb3645df1b0 (patch)
treedbcbf90028d4e60763724ca1bac4a63af7170973 /media
parent925a349b45d1d16eaaca6a1f4827191831271ca0 (diff)
downloadframeworks_av-99ffda877980468a9ae31e013cd10fb3645df1b0.zip
frameworks_av-99ffda877980468a9ae31e013cd10fb3645df1b0.tar.gz
frameworks_av-99ffda877980468a9ae31e013cd10fb3645df1b0.tar.bz2
auto import from //depot/cupcake/@137055
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/AudioRecord.cpp25
-rw-r--r--media/libmedia/AudioTrack.cpp13
-rw-r--r--media/libmedia/IMediaRecorder.cpp22
-rw-r--r--media/libmedia/mediarecorder.cpp75
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp110
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp11
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h1
7 files changed, 250 insertions, 7 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index e833c85..7594ff0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -128,8 +128,23 @@ status_t AudioRecord::set(
return BAD_VALUE;
}
- // TODO: Get input frame count from hardware.
- int minFrameCount = 1024*2;
+ // validate framecount
+ size_t inputBuffSizeInBytes = -1;
+ if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
+ != NO_ERROR) {
+ LOGE("AudioSystem could not query the input buffer size.");
+ return NO_INIT;
+ }
+ if (inputBuffSizeInBytes == 0) {
+ LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
+ sampleRate, channelCount, format);
+ return BAD_VALUE;
+ }
+ int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+
+ // We use 2* size of input buffer for ping pong use of record buffer.
+ int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
+ LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
if (frameCount == 0) {
frameCount = minFrameCount;
@@ -144,7 +159,11 @@ status_t AudioRecord::set(
// open record channel
status_t status;
sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), streamType,
- sampleRate, format, channelCount, frameCount, flags, &status);
+ sampleRate, format,
+ channelCount,
+ frameCount,
+ ((uint16_t)flags) << 16,
+ &status);
if (record == 0) {
LOGE("AudioFlinger could not create record track, status: %d", status);
return status;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index f8520a7..2274521 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -168,6 +168,8 @@ status_t AudioTrack::set(
// Ensure that buffer depth covers at least audio hardware latency
uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+ if (minBufCount < 2) minBufCount = 2;
+
// When playing from shared buffer, playback will start even if last audioflinger
// block is partly filled.
if (sharedBuffer != 0 && minBufCount > 1) {
@@ -437,8 +439,8 @@ void AudioTrack::setSampleRate(int rate)
return;
}
// Resampler implementation limits input sampling rate to 2 x output sampling rate.
+ if (rate <= 0) rate = 1;
if (rate > afSamplingRate*2) rate = afSamplingRate*2;
-
if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
mCblk->sampleRate = rate;
@@ -466,10 +468,15 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount
if (loopStart >= loopEnd ||
loopEnd - loopStart > mFrameCount) {
- LOGW("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
+ LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
return BAD_VALUE;
}
- // TODO handle shared buffer here: limit loop end to framecount
+
+ if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) {
+ LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
+ loopStart, loopEnd, mFrameCount);
+ return BAD_VALUE;
+ }
cblk->loopStart = loopStart;
cblk->loopEnd = loopEnd;
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 507d03e..f187bf5 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -21,6 +21,7 @@
#include <utils/Parcel.h>
#include <ui/ISurface.h>
#include <ui/ICamera.h>
+#include <media/IMediaPlayerClient.h>
#include <media/IMediaRecorder.h>
namespace android {
@@ -44,7 +45,8 @@ enum {
SET_VIDEO_SIZE,
SET_VIDEO_FRAMERATE,
SET_PREVIEW_SURFACE,
- SET_CAMERA
+ SET_CAMERA,
+ SET_LISTENER
};
class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -176,6 +178,16 @@ public:
return reply.readInt32();
}
+ status_t setListener(const sp<IMediaPlayerClient>& listener)
+ {
+ LOGV("setListener(%p)", listener.get());
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ remote()->transact(SET_LISTENER, data, &reply);
+ return reply.readInt32();
+ }
+
status_t prepare()
{
LOGV("prepare");
@@ -373,6 +385,14 @@ status_t BnMediaRecorder::onTransact(
reply->writeInt32(setVideoFrameRate(frames_per_second));
return NO_ERROR;
} break;
+ case SET_LISTENER: {
+ LOGV("SET_LISTENER");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ sp<IMediaPlayerClient> listener =
+ interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+ reply->writeInt32(setListener(listener));
+ return NO_ERROR;
+ } break;
case SET_PREVIEW_SURFACE: {
LOGV("SET_PREVIEW_SURFACE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 4ab26ac..98aac39 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -58,6 +58,10 @@ status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface)
LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState);
return INVALID_OPERATION;
}
+ if (!mIsVideoSourceSet) {
+ LOGE("try to set preview surface without setting the video source first");
+ return INVALID_OPERATION;
+ }
status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface());
if (OK != ret) {
@@ -86,6 +90,14 @@ status_t MediaRecorder::init()
mCurrentState = MEDIA_RECORDER_ERROR;
return UNKNOWN_ERROR;
}
+
+ ret = mMediaRecorder->setListener(this);
+ if (OK != ret) {
+ LOGV("setListener failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return UNKNOWN_ERROR;
+ }
+
mCurrentState = MEDIA_RECORDER_INITIALIZED;
return ret;
}
@@ -167,6 +179,10 @@ status_t MediaRecorder::setOutputFormat(int of)
LOGE("setOutputFormat called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
}
+ if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_RAW_AMR) {
+ LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of);
+ return INVALID_OPERATION;
+ }
status_t ret = mMediaRecorder->setOutputFormat(of);
if (OK != ret) {
@@ -185,6 +201,10 @@ status_t MediaRecorder::setVideoEncoder(int ve)
LOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
}
+ if (!mIsVideoSourceSet) {
+ LOGE("try to set the video encoder without setting the video source first");
+ return INVALID_OPERATION;
+ }
if (mIsVideoEncoderSet) {
LOGE("video encoder has already been set");
return INVALID_OPERATION;
@@ -211,6 +231,10 @@ status_t MediaRecorder::setAudioEncoder(int ae)
LOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
}
+ if (!mIsAudioSourceSet) {
+ LOGE("try to set the audio encoder without setting the audio source first");
+ return INVALID_OPERATION;
+ }
if (mIsAudioEncoderSet) {
LOGE("audio encoder has already been set");
return INVALID_OPERATION;
@@ -293,6 +317,10 @@ status_t MediaRecorder::setVideoSize(int width, int height)
LOGE("setVideoSize called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
}
+ if (!mIsVideoSourceSet) {
+ LOGE("try to set video size without setting video source first");
+ return INVALID_OPERATION;
+ }
status_t ret = mMediaRecorder->setVideoSize(width, height);
if (OK != ret) {
@@ -314,6 +342,10 @@ status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
}
+ if (!mIsVideoSourceSet) {
+ LOGE("try to set video frame rate without setting video source first");
+ return INVALID_OPERATION;
+ }
status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second);
if (OK != ret) {
@@ -335,6 +367,23 @@ status_t MediaRecorder::prepare()
LOGE("prepare called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
}
+ if (mIsAudioSourceSet != mIsAudioEncoderSet) {
+ if (mIsAudioSourceSet) {
+ LOGE("audio source is set, but audio encoder is not set");
+ } else { // must not happen, since setAudioEncoder checks this already
+ LOGE("audio encoder is set, but audio source is not set");
+ }
+ return INVALID_OPERATION;
+ }
+
+ if (mIsVideoSourceSet != mIsVideoEncoderSet) {
+ if (mIsVideoSourceSet) {
+ LOGE("video source is set, but video encoder is not set");
+ } else { // must not happen, since setVideoEncoder checks this already
+ LOGE("video encoder is set, but video source is not set");
+ }
+ return INVALID_OPERATION;
+ }
status_t ret = mMediaRecorder->prepare();
if (OK != ret) {
@@ -538,5 +587,31 @@ MediaRecorder::~MediaRecorder()
}
}
+status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
+{
+ LOGV("setListener");
+ Mutex::Autolock _l(mLock);
+ mListener = listener;
+
+ return NO_ERROR;
+}
+
+void MediaRecorder::notify(int msg, int ext1, int ext2)
+{
+ LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
+
+ sp<MediaRecorderListener> listener;
+ mLock.lock();
+ listener = mListener;
+ mLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock _l(mNotifyLock);
+ LOGV("callback application");
+ listener->notify(msg, ext1, ext2);
+ LOGV("back from callback");
+ }
+}
+
}; // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 97e3536..40705c6 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -218,6 +218,104 @@ static int myTid() {
#endif
}
+#if defined(__arm__)
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+ size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+void memStatus(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ typedef struct {
+ size_t size;
+ size_t dups;
+ intptr_t * backtrace;
+ } AllocEntry;
+
+ uint8_t *info = NULL;
+ size_t overallSize = 0;
+ size_t infoSize = 0;
+ size_t totalMemory = 0;
+ size_t backtraceSize = 0;
+
+ get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+ if (info) {
+ uint8_t *ptr = info;
+ size_t count = overallSize / infoSize;
+
+ snprintf(buffer, SIZE, " Allocation count %i\n", count);
+ result.append(buffer);
+
+ AllocEntry * entries = new AllocEntry[count];
+
+ for (size_t i = 0; i < count; i++) {
+ // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+ AllocEntry *e = &entries[i];
+
+ e->size = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->dups = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+ ptr += sizeof(intptr_t) * backtraceSize;
+ }
+
+ // Now we need to sort the entries. They come sorted by size but
+ // not by stack trace which causes problems using diff.
+ bool moved;
+ do {
+ moved = false;
+ for (size_t i = 0; i < (count - 1); i++) {
+ AllocEntry *e1 = &entries[i];
+ AllocEntry *e2 = &entries[i+1];
+
+ bool swap = e1->size < e2->size;
+ if (e1->size == e2->size) {
+ for(size_t j = 0; j < backtraceSize; j++) {
+ if (e1->backtrace[j] == e2->backtrace[j]) {
+ continue;
+ }
+ swap = e1->backtrace[j] < e2->backtrace[j];
+ break;
+ }
+ }
+ if (swap) {
+ AllocEntry t = entries[i];
+ entries[i] = entries[i+1];
+ entries[i+1] = t;
+ moved = true;
+ }
+ }
+ } while (moved);
+
+ for (size_t i = 0; i < count; i++) {
+ AllocEntry *e = &entries[i];
+
+ snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups);
+ result.append(buffer);
+ for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+ if (ct) {
+ result.append(", ");
+ }
+ snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+ result.append(buffer);
+ }
+ result.append("\n");
+ }
+
+ delete[] entries;
+ free_malloc_leak_info(info);
+ }
+
+ write(fd, result.string(), result.size());
+}
+#endif
+
status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -300,6 +398,18 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
result.append(buffer);
result.append("\n");
}
+
+#if defined(__arm__)
+ bool dumpMem = false;
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == String16("-m")) {
+ dumpMem = true;
+ }
+ }
+ if (dumpMem) {
+ memStatus(fd, args);
+ }
+#endif
}
write(fd, result.string(), result.size());
return NO_ERROR;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index e8ba17f..4b45acb 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -258,5 +258,16 @@ MediaRecorderClient::~MediaRecorderClient()
release();
}
+status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener)
+{
+ LOGV("setListener");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setListener(listener);
+}
+
}; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 2b80c10..93fd802 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -39,6 +39,7 @@ public:
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
+ virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
virtual status_t start();