diff options
Diffstat (limited to 'media/libmediaplayerservice')
-rw-r--r-- | media/libmediaplayerservice/Android.mk | 13 | ||||
-rw-r--r-- | media/libmediaplayerservice/FLACPlayer.cpp | 577 | ||||
-rw-r--r-- | media/libmediaplayerservice/FLACPlayer.h | 100 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 9 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaRecorderClient.cpp | 10 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaRecorderClient.h | 1 | ||||
-rw-r--r-- | media/libmediaplayerservice/MetadataRetrieverClient.cpp | 42 | ||||
-rw-r--r-- | media/libmediaplayerservice/MetadataRetrieverClient.h | 5 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 4 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 1 |
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 ¶ms) { return OK; } +status_t StagefrightRecorder::setCameraParameters(const String8 ¶ms) { + 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(); |