summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmediaplayerservice')
-rw-r--r--media/libmediaplayerservice/Android.mk13
-rw-r--r--media/libmediaplayerservice/FLACPlayer.cpp577
-rw-r--r--media/libmediaplayerservice/FLACPlayer.h100
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp9
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp10
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h1
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp42
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h5
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp4
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h1
10 files changed, 758 insertions, 4 deletions
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index cf97b23..ecd1d2e 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -13,7 +13,8 @@ LOCAL_SRC_FILES:= \
TestPlayerStub.cpp \
VorbisPlayer.cpp \
VorbisMetadataRetriever.cpp \
- MidiMetadataRetriever.cpp \
+ FLACPlayer.cpp \
+ MidiMetadataRetriever.cpp \
MidiFile.cpp
ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
@@ -40,12 +41,17 @@ LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libstagefright \
libstagefright_omx \
- libstagefright_color_conversion \
- libsurfaceflinger_client
+ libstagefright_color_conversion
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client
+endif
ifneq ($(BUILD_WITHOUT_PV),true)
LOCAL_SHARED_LIBRARIES += \
libopencore_player \
+ libFLAC \
libopencore_author
else
LOCAL_CFLAGS += -DNO_OPENCORE
@@ -56,6 +62,7 @@ LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_C_INCLUDES := \
+ external/flac/include \
$(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
diff --git a/media/libmediaplayerservice/FLACPlayer.cpp b/media/libmediaplayerservice/FLACPlayer.cpp
new file mode 100644
index 0000000..1f8e3b6
--- /dev/null
+++ b/media/libmediaplayerservice/FLACPlayer.cpp
@@ -0,0 +1,577 @@
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "FLACPlayer"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#include "FLACPlayer.h"
+
+#ifdef HAVE_GETTID
+static pid_t myTid() { return gettid(); }
+#else
+static pid_t myTid() { return getpid(); }
+#endif
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// TODO: Determine appropriate return codes
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+static status_t ERROR_NOT_SUPPORTED = -8;
+static status_t ERROR_NOT_READY = -16;
+static status_t STATE_INIT = 0;
+static status_t STATE_ERROR = 1;
+static status_t STATE_OPEN = 2;
+
+
+FLACPlayer::FLACPlayer() :
+ mTotalSamples(-1), mCurrentSample(0), mBytesPerSample(-1),
+ mChannels(-1), mSampleRate(-1), mAudioBuffer(NULL),
+ mAudioBufferSize(0), mAudioBufferFilled(0),
+ mState(STATE_ERROR), mStreamType(AudioSystem::MUSIC),
+ mLoop(false), mAndroidLoop(false), mExit(false), mPaused(false),
+ mRender(false), mRenderTid(-1)
+{
+ LOGV("constructor");
+}
+
+void FLACPlayer::onFirstRef()
+{
+ LOGV("onFirstRef");
+ // create playback thread
+ Mutex::Autolock l(mMutex);
+ createThreadEtc(renderThread, this, "FLAC decoder", ANDROID_PRIORITY_AUDIO);
+ mCondition.wait(mMutex);
+ if (mRenderTid > 0) {
+ LOGV("render thread(%d) started", mRenderTid);
+ mState = STATE_INIT;
+ }
+}
+
+status_t FLACPlayer::initCheck()
+{
+ if (mState != STATE_ERROR) return NO_ERROR;
+ return ERROR_NOT_READY;
+}
+
+FLACPlayer::~FLACPlayer() {
+ LOGV("FLACPlayer destructor");
+ release();
+}
+
+status_t FLACPlayer::setDataSource(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
+}
+
+status_t FLACPlayer::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ return setdatasource(NULL, fd, offset, length);
+}
+
+status_t FLACPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
+{
+ LOGV("setDataSource url=%s, fd=%d", path, fd);
+
+ // file still open?
+ Mutex::Autolock l(mMutex);
+ if (mState == STATE_OPEN) {
+ reset_nosync();
+ }
+
+ // open file and set paused state
+ if (path) {
+ mFile = fopen(path, "r");
+ } else {
+ mFile = fdopen(dup(fd), "r");
+ }
+ if (mFile == NULL) {
+ return ERROR_OPEN_FAILED;
+ }
+
+ struct stat sb;
+ int ret;
+ if (path) {
+ ret = stat(path, &sb);
+ } else {
+ ret = fstat(fd, &sb);
+ }
+ if (ret != 0) {
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ fseek(mFile, offset, SEEK_SET);
+
+ mDecoder = FLAC__stream_decoder_new();
+ if (mDecoder == NULL) {
+ LOGE("failed to allocate decoder\n");
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ FLAC__stream_decoder_set_md5_checking(mDecoder, false);
+ FLAC__stream_decoder_set_metadata_ignore_all(mDecoder);
+ FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_STREAMINFO);
+ FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+ FLAC__StreamDecoderInitStatus init_status;
+ init_status = FLAC__stream_decoder_init_FILE(mDecoder, mFile, vp_write, vp_metadata, vp_error, this);
+ if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ LOGE("FLAC__stream_decoder_init_FILE failed: [%d]\n", (int)init_status);
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) {
+ LOGE("FLAC__stream_decoder_process_until_end_of_metadata failed\n");
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ mState = STATE_OPEN;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::prepare()
+{
+ LOGV("prepare");
+ if (mState != STATE_OPEN ) {
+ return ERROR_NOT_OPEN;
+ }
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::prepareAsync() {
+ LOGV("prepareAsync");
+ // can't hold the lock here because of the callback
+ // it's safe because we don't change state
+ if (mState != STATE_OPEN) {
+ sendEvent(MEDIA_ERROR);
+ return NO_ERROR;
+ }
+ sendEvent(MEDIA_PREPARED);
+ return NO_ERROR;
+}
+
+void FLACPlayer::vp_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
+ FLACPlayer *self = (FLACPlayer *)client_data;
+
+ if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
+ self->mTotalSamples = metadata->data.stream_info.total_samples;
+ self->mBytesPerSample = metadata->data.stream_info.bits_per_sample / 8;
+ self->mChannels = metadata->data.stream_info.channels;
+ self->mSampleRate = metadata->data.stream_info.sample_rate;
+
+ if (self->mBytesPerSample != 2) {
+ LOGE("Can only support 16 bits per sample; input is %d\n", self->mBytesPerSample * 8);
+ self->mState = STATE_ERROR;
+ return;
+ }
+
+ self->mLengthInMsec = self->mTotalSamples / self->mSampleRate * 1000 +
+ self->mTotalSamples % self->mSampleRate / ( self->mSampleRate / 1000 );
+ } else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
+ for (unsigned int i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
+ char *ptr = (char *)metadata->data.vorbis_comment.comments[i].entry;
+
+ // does the comment start with ANDROID_LOOP_TAG
+ if (strncmp(ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
+ // read the value of the tag
+ char *val = ptr + strlen(ANDROID_LOOP_TAG) + 1;
+ self->mAndroidLoop = (strncmp(val, "true", 4) == 0);
+ }
+
+ LOGV_IF(self->mAndroidLoop, "looped sound");
+ }
+ }
+}
+
+void FLACPlayer::vp_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
+ LOGV("vp_error");
+ FLACPlayer *self = (FLACPlayer *)client_data;
+ self->sendEvent(MEDIA_ERROR);
+ self->mState = STATE_ERROR;
+}
+
+status_t FLACPlayer::start()
+{
+ LOGV("start\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+
+ mPaused = false;
+ mRender = true;
+
+ // wake up render thread
+ LOGV(" wakeup render thread\n");
+ mCondition.signal();
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::stop()
+{
+ LOGV("stop\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+ mPaused = true;
+ mRender = false;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::seekTo(int msec)
+{
+ LOGV("seekTo %d\n", msec);
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+
+ FLAC__uint64 target_sample = mTotalSamples * msec / mLengthInMsec;
+
+ if (mTotalSamples > 0 && target_sample >= mTotalSamples && target_sample > 0)
+ target_sample = mTotalSamples - 1;
+
+ if (!FLAC__stream_decoder_seek_absolute(mDecoder, target_sample)) {
+ LOGE("FLAC__stream_decoder_seek_absolute failed\n");
+ if (FLAC__stream_decoder_get_state(mDecoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
+ FLAC__stream_decoder_flush(mDecoder);
+ }
+ return ERROR_NOT_SUPPORTED;
+ }
+
+ mCurrentSample = target_sample;
+
+ sendEvent(MEDIA_SEEK_COMPLETE);
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::pause()
+{
+ LOGV("pause\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+ mPaused = true;
+ return NO_ERROR;
+}
+
+bool FLACPlayer::isPlaying()
+{
+ LOGV("isPlaying\n");
+ if (mState == STATE_OPEN) {
+ return mRender;
+ }
+ return false;
+}
+
+status_t FLACPlayer::getCurrentPosition(int* msec)
+{
+ LOGV("getCurrentPosition\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ LOGE("getCurrentPosition(): file not open");
+ return ERROR_NOT_OPEN;
+ }
+
+ *msec = (int)(mCurrentSample * 1000 / mSampleRate);
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::getDuration(int* duration)
+{
+ LOGV("getDuration\n");
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+
+ *duration = mLengthInMsec;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::release()
+{
+ LOGV("release\n");
+ Mutex::Autolock l(mMutex);
+ reset_nosync();
+
+ // TODO: timeout when thread won't exit
+ // wait for render thread to exit
+ if (mRenderTid > 0) {
+ mExit = true;
+ mCondition.signal();
+ mCondition.wait(mMutex);
+ }
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::reset()
+{
+ LOGV("reset\n");
+ Mutex::Autolock l(mMutex);
+ return reset_nosync();
+}
+
+// always call with lock held
+status_t FLACPlayer::reset_nosync()
+{
+ // close file
+ if (mFile != NULL) {
+ FLAC__stream_decoder_delete(mDecoder);
+ fclose(mFile);
+ mFile = NULL;
+ }
+ mState = STATE_ERROR;
+
+ mTotalSamples = -1;
+ mBytesPerSample = -1;
+ mChannels = -1;
+ mSampleRate = -1;
+ mLoop = false;
+ mAndroidLoop = false;
+ mPaused = false;
+ mRender = false;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::setLooping(int loop)
+{
+ LOGV("setLooping\n");
+ Mutex::Autolock l(mMutex);
+ mLoop = (loop != 0);
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::createOutputTrack() {
+ LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
+ mSampleRate, mChannels);
+ if (mAudioSink->open(mSampleRate, mChannels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
+ LOGE("mAudioSink open failed\n");
+ return ERROR_OPEN_FAILED;
+ }
+ return NO_ERROR;
+}
+
+FLAC__StreamDecoderWriteStatus FLACPlayer::vp_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) {
+ FLACPlayer *self = (FLACPlayer *)client_data;
+
+ const uint32_t bytes_per_sample = self->mBytesPerSample;
+ const uint32_t incr = bytes_per_sample * self->mChannels;
+ const uint32_t wide_samples = frame->header.blocksize;
+ const uint32_t frame_size = incr * wide_samples;
+
+ self->mCurrentSample = frame->header.number.sample_number;
+
+ uint32_t sample, wide_sample, channel;
+
+ if (self->mAudioBufferSize < frame_size) {
+ if (self->mAudioBuffer != NULL) {
+ delete [] self->mAudioBuffer;
+ }
+ self->mAudioBuffer = new FLAC__int8[frame_size];
+ self->mAudioBufferSize = frame_size;
+ }
+
+ FLAC__int8 *s8buffer = self->mAudioBuffer;
+ FLAC__int16 *s16buffer = (FLAC__int16 *)s8buffer;
+
+ // Interleave channel data like PCM
+ if (self->mChannels == 2) {
+ for (sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
+ s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
+ s16buffer[sample++] = (FLAC__int16)(buffer[1][wide_sample]);
+ }
+ } else if (self->mChannels == 1) {
+ for (sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
+ s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
+ }
+ } else {
+ for (sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
+ for (channel = 0; channel < self->mChannels; channel++, sample++) {
+ s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
+ }
+ }
+ }
+ self->mAudioBufferFilled = frame_size;
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+int FLACPlayer::renderThread(void* p) {
+ return ((FLACPlayer*)p)->render();
+}
+
+int FLACPlayer::render() {
+ int result = -1;
+ int temp;
+ int current_section = 0;
+ bool audioStarted = false;
+
+ LOGV("render\n");
+
+ // let main thread know we're ready
+ {
+ Mutex::Autolock l(mMutex);
+ mRenderTid = myTid();
+ mCondition.signal();
+ }
+
+ while (1) {
+ FLAC__bool status = true;
+ {
+ Mutex::Autolock l(mMutex);
+
+ // pausing?
+ if (mPaused) {
+ if (mAudioSink->ready()) mAudioSink->pause();
+ mRender = false;
+ audioStarted = false;
+ }
+
+ // nothing to render, wait for client thread to wake us up
+ if (!mExit && !mRender) {
+ LOGV("render - signal wait\n");
+ mCondition.wait(mMutex);
+ LOGV("render - signal rx'd\n");
+ }
+ if (mExit) break;
+
+ // We could end up here if start() is called, and before we get a
+ // chance to run, the app calls stop() or reset(). Re-check render
+ // flag so we don't try to render in stop or reset state.
+ if (!mRender) continue;
+
+ // create audio output track if necessary
+ if (!mAudioSink->ready()) {
+ LOGV("render - create output track\n");
+ if (createOutputTrack() != NO_ERROR)
+ break;
+ }
+
+
+ // start audio output if necessary
+ if (!audioStarted && !mPaused && !mExit) {
+ LOGV("render - starting audio\n");
+ mAudioSink->start();
+ audioStarted = true;
+ }
+
+ if (FLAC__stream_decoder_get_state(mDecoder) != FLAC__STREAM_DECODER_END_OF_STREAM) {
+ status = FLAC__stream_decoder_process_single(mDecoder);
+ } else {
+ // end of file, do we need to loop?
+ // ...
+ if (mLoop || mAndroidLoop) {
+ FLAC__stream_decoder_seek_absolute(mDecoder, 0);
+ mCurrentSample = 0;
+ status = FLAC__stream_decoder_process_single(mDecoder);
+ } else {
+ mAudioSink->stop();
+ audioStarted = false;
+ mRender = false;
+ mPaused = true;
+
+ FLAC__uint64 endpos;
+ if (!FLAC__stream_decoder_get_decode_position(mDecoder, &endpos)) {
+ endpos = 0;
+ }
+
+ LOGV("send MEDIA_PLAYBACK_COMPLETE\n");
+ sendEvent(MEDIA_PLAYBACK_COMPLETE);
+
+ // wait until we're started again
+ LOGV("playback complete - wait for signal\n");
+ mCondition.wait(mMutex);
+ LOGV("playback complete - signal rx'd\n");
+ if (mExit) break;
+
+ // if we're still at the end, restart from the beginning
+ if (mState == STATE_OPEN) {
+ FLAC__uint64 curpos;
+ if (FLAC__stream_decoder_get_decode_position(mDecoder, &curpos)) {
+ curpos = 0;
+ }
+ if (curpos == endpos) {
+ FLAC__stream_decoder_seek_absolute(mDecoder, 0);
+ mCurrentSample = 0;
+ }
+ status = FLAC__stream_decoder_process_single(mDecoder);
+ }
+ }
+ }
+ }
+
+ if (!status) {
+ LOGE("Error in FLAC decoder: %s\n", FLAC__stream_decoder_get_resolved_state_string(mDecoder));
+ sendEvent(MEDIA_ERROR);
+ break;
+ }
+
+ if (mAudioBufferFilled > 0) {
+ /* Be sure to clear mAudioBufferFilled even if there's an error. */
+ uint32_t toPlay = mAudioBufferFilled;
+ mAudioBufferFilled = 0;
+
+ if (!mAudioSink->write(mAudioBuffer, toPlay)) {
+ LOGE("Error in FLAC decoder: %s\n", FLAC__stream_decoder_get_resolved_state_string(mDecoder));
+ sendEvent(MEDIA_ERROR);
+ break;
+ }
+ }
+ }
+
+threadExit:
+ mAudioSink.clear();
+ if (mAudioBuffer != NULL) {
+ delete [] mAudioBuffer;
+ mAudioBuffer = NULL;
+ mAudioBufferSize = 0;
+ mAudioBufferFilled = 0;
+ }
+
+ // tell main thread goodbye
+ Mutex::Autolock l(mMutex);
+ mRenderTid = -1;
+ mCondition.signal();
+ return result;
+}
+
+} // end namespace android
diff --git a/media/libmediaplayerservice/FLACPlayer.h b/media/libmediaplayerservice/FLACPlayer.h
new file mode 100644
index 0000000..b7068c3
--- /dev/null
+++ b/media/libmediaplayerservice/FLACPlayer.h
@@ -0,0 +1,100 @@
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_FLACPLAYER_H
+#define ANDROID_FLACPLAYER_H
+
+#include <utils/threads.h>
+
+#include <media/MediaPlayerInterface.h>
+#include <media/AudioTrack.h>
+
+#include "FLAC/all.h"
+
+#define ANDROID_LOOP_TAG "ANDROID_LOOP"
+
+namespace android {
+
+class FLACPlayer : public MediaPlayerInterface {
+public:
+ FLACPlayer();
+ ~FLACPlayer();
+
+ virtual void onFirstRef();
+ virtual status_t initCheck();
+
+ virtual status_t setDataSource(
+ const char *uri, 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 prepare();
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t seekTo(int msec);
+ virtual status_t pause();
+ virtual bool isPlaying();
+ virtual status_t getCurrentPosition(int* msec);
+ virtual status_t getDuration(int* msec);
+ virtual status_t release();
+ virtual status_t reset();
+ virtual status_t setLooping(int loop);
+ virtual player_type playerType() { return FLAC_PLAYER; }
+ virtual status_t invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
+
+private:
+ status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length);
+ status_t reset_nosync();
+ status_t createOutputTrack();
+ static int renderThread(void*);
+ int render();
+
+ static void vp_metadata(const FLAC__StreamDecoder *, const FLAC__StreamMetadata *, void *);
+ static void vp_error(const FLAC__StreamDecoder *, const FLAC__StreamDecoderErrorStatus, void *);
+ static FLAC__StreamDecoderWriteStatus
+ vp_write(const FLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 * const[], void *);
+
+ FLAC__uint64 mTotalSamples;
+ FLAC__uint64 mCurrentSample;
+ uint32_t mBytesPerSample;
+ uint32_t mChannels;
+ uint32_t mSampleRate;
+ uint32_t mLengthInMsec;
+
+ FLAC__int8 * mAudioBuffer;
+ uint32_t mAudioBufferSize;
+ uint32_t mAudioBufferFilled;
+
+ Mutex mMutex;
+ Condition mCondition;
+ FILE* mFile;
+ FLAC__StreamDecoder* mDecoder;
+ status_t mState;
+ int mStreamType;
+ bool mLoop;
+ bool mAndroidLoop;
+ volatile bool mExit;
+ bool mPaused;
+ volatile bool mRender;
+ pid_t mRenderTid;
+};
+
+}; // namespace android
+
+#endif // ANDROID_FLACPLAYER_H
+
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 3e1f4a5..911d89f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -57,6 +57,7 @@
#include "MidiFile.h"
#include "VorbisPlayer.h"
+#include "FLACPlayer.h"
#include <media/PVPlayer.h>
#include "TestPlayerStub.h"
#include "StagefrightPlayer.h"
@@ -204,6 +205,7 @@ extmap FILE_EXTS [] = {
{".wmv", PV_PLAYER},
{".asf", PV_PLAYER},
#endif
+ {".flac", FLAC_PLAYER},
};
// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
@@ -719,6 +721,9 @@ player_type getPlayerType(int fd, int64_t offset, int64_t length)
}
#endif
+ if (ident == 0x43614c66) // 'fLaC'
+ return FLAC_PLAYER;
+
// Some kind of MIDI?
EAS_DATA_HANDLE easdata;
if (EAS_Init(&easdata) == EAS_SUCCESS) {
@@ -812,6 +817,10 @@ static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
LOGV("Create Test Player stub");
p = new TestPlayerStub();
break;
+ case FLAC_PLAYER:
+ LOGV(" create FLACPlayer");
+ p = new FLACPlayer();
+ break;
}
if (p != NULL) {
if (p->initCheck() == NO_ERROR) {
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 12de0d9..189d97d3 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -196,6 +196,16 @@ status_t MediaRecorderClient::setParameters(const String8& params) {
return mRecorder->setParameters(params);
}
+status_t MediaRecorderClient::setCameraParameters(const String8& params) {
+ LOGV("setCameraParameters(%s)", params.string());
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setCameraParameters(params);
+}
+
status_t MediaRecorderClient::prepare()
{
LOGV("prepare");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 805005d..4a6b9a1 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -40,6 +40,7 @@ public:
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8& params);
+ virtual status_t setCameraParameters(const String8& params);
virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 550b84d..070680e 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -28,8 +28,12 @@
#include <string.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
+#ifdef USE_ECLAIR_MEMORYDEALER
+#include <binder/MemoryDealer.h>
+#else
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
+#endif
#include <android_runtime/ActivityManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -63,6 +67,10 @@ MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
{
LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
mPid = pid;
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mThumbnailDealer = NULL;
+ mAlbumArtDealer = NULL;
+#endif
mThumbnail = NULL;
mAlbumArt = NULL;
mRetriever = NULL;
@@ -93,6 +101,10 @@ void MetadataRetrieverClient::disconnect()
LOGV("disconnect from pid %d", mPid);
Mutex::Autolock lock(mLock);
mRetriever.clear();
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mThumbnailDealer.clear();
+ mAlbumArtDealer.clear();
+#endif
mThumbnail.clear();
mAlbumArt.clear();
mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL;
@@ -239,6 +251,9 @@ sp<IMemory> MetadataRetrieverClient::captureFrame()
LOGV("captureFrame");
Mutex::Autolock lock(mLock);
mThumbnail.clear();
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mThumbnailDealer.clear();
+#endif
if (mRetriever == NULL) {
LOGE("retriever is not initialized");
return NULL;
@@ -249,15 +264,27 @@ sp<IMemory> MetadataRetrieverClient::captureFrame()
return NULL;
}
size_t size = sizeof(VideoFrame) + frame->mSize;
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mThumbnailDealer = new MemoryDealer(size);
+ if (mThumbnailDealer == NULL) {
+#else
sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
if (heap == NULL) {
+#endif
LOGE("failed to create MemoryDealer");
delete frame;
return NULL;
}
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mThumbnail = mThumbnailDealer->allocate(size);
+#else
mThumbnail = new MemoryBase(heap, 0, size);
+#endif
if (mThumbnail == NULL) {
LOGE("not enough memory for VideoFrame size=%u", size);
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mThumbnailDealer.clear();
+#endif
delete frame;
return NULL;
}
@@ -278,6 +305,9 @@ sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
LOGV("extractAlbumArt");
Mutex::Autolock lock(mLock);
mAlbumArt.clear();
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mAlbumArtDealer.clear();
+#endif
if (mRetriever == NULL) {
LOGE("retriever is not initialized");
return NULL;
@@ -288,15 +318,27 @@ sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
return NULL;
}
size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mAlbumArtDealer = new MemoryDealer(size);
+ if (mAlbumArtDealer == NULL) {
+#else
sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
if (heap == NULL) {
+#endif
LOGE("failed to create MemoryDealer object");
delete albumArt;
return NULL;
}
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mAlbumArt = mAlbumArtDealer->allocate(size);
+#else
mAlbumArt = new MemoryBase(heap, 0, size);
+#endif
if (mAlbumArt == NULL) {
LOGE("not enough memory for MediaAlbumArt size=%u", size);
+#ifdef USE_ECLAIR_MEMORYDEALER
+ mAlbumArtDealer.clear();
+#endif
delete albumArt;
return NULL;
}
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index 4aab94f..7e6d223 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -24,7 +24,6 @@
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <binder/IMemory.h>
-
#include <media/MediaMetadataRetrieverInterface.h>
@@ -63,6 +62,10 @@ private:
int mMode;
// Keep the shared memory copy of album art and capture frame (for thumbnail)
+#ifdef USE_ECLAIR_MEMORYDEALER
+ sp<MemoryDealer> mAlbumArtDealer;
+ sp<MemoryDealer> mThumbnailDealer;
+#endif
sp<IMemory> mAlbumArt;
sp<IMemory> mThumbnail;
};
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 531fd11..573932f 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -133,6 +133,10 @@ status_t StagefrightRecorder::setParameters(const String8 &params) {
return OK;
}
+status_t StagefrightRecorder::setCameraParameters(const String8 &params) {
+ return OK;
+}
+
status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) {
mListener = listener;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 7ec412d..e5a84c1 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -43,6 +43,7 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8& params);
+ virtual status_t setCameraParameters(const String8& params);
virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
virtual status_t prepare();
virtual status_t start();