diff options
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/Android.mk | 4 | ||||
-rw-r--r-- | media/libmedia/AudioEffect.cpp | 55 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 14 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 1 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 16 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayer.cpp | 39 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayerService.cpp | 38 | ||||
-rw-r--r-- | media/libmedia/IMediaRecorder.cpp | 25 | ||||
-rw-r--r-- | media/libmedia/IOMX.cpp | 273 | ||||
-rw-r--r-- | media/libmedia/IStreamSource.cpp | 186 | ||||
-rw-r--r-- | media/libmedia/MediaProfiles.cpp | 139 | ||||
-rw-r--r-- | media/libmedia/MediaScanner.cpp | 64 | ||||
-rw-r--r-- | media/libmedia/mediaplayer.cpp | 23 | ||||
-rw-r--r-- | media/libmedia/mediarecorder.cpp | 30 |
14 files changed, 582 insertions, 325 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 2e5cbe3..74fb531 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \ IMediaRecorderClient.cpp \ IMediaPlayer.cpp \ IMediaRecorder.cpp \ + IStreamSource.cpp \ Metadata.cpp \ mediarecorder.cpp \ IMediaMetadataRetriever.cpp \ @@ -35,7 +36,8 @@ LOCAL_SRC_FILES:= \ fixedfft.cpp.arm LOCAL_SHARED_LIBRARIES := \ - libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client + libui libcutils libutils libbinder libsonivox libicuuc libexpat \ + libsurfaceflinger_client libcamera_client libstagefright_foundation LOCAL_MODULE:= libmedia diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 88b8c86..aadeba5 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -27,7 +27,6 @@ #include <media/AudioEffect.h> #include <utils/Log.h> -#include <cutils/atomic.h> #include <binder/IPCThreadState.h> @@ -207,18 +206,22 @@ status_t AudioEffect::setEnabled(bool enabled) return INVALID_OPERATION; } - if (enabled) { - LOGV("enable %p", this); - if (android_atomic_or(1, &mEnabled) == 0) { - return mIEffect->enable(); + status_t status = NO_ERROR; + + AutoMutex lock(mLock); + if (enabled != mEnabled) { + if (enabled) { + LOGV("enable %p", this); + status = mIEffect->enable(); + } else { + LOGV("disable %p", this); + status = mIEffect->disable(); } - } else { - LOGV("disable %p", this); - if (android_atomic_and(~1, &mEnabled) == 1) { - return mIEffect->disable(); + if (status == NO_ERROR) { + mEnabled = enabled; } } - return NO_ERROR; + return status; } status_t AudioEffect::command(uint32_t cmdCode, @@ -232,26 +235,26 @@ status_t AudioEffect::command(uint32_t cmdCode, return INVALID_OPERATION; } - if ((cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) && - (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL)) { - return BAD_VALUE; + if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) { + if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) { + return NO_ERROR; + } + if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) { + return BAD_VALUE; + } + mLock.lock(); } status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData); - if (status != NO_ERROR) { - return status; - } if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) { - status = *(status_t *)replyData; - if (status != NO_ERROR) { - return status; + if (status == NO_ERROR) { + status = *(status_t *)replyData; } - if (cmdCode == EFFECT_CMD_ENABLE) { - android_atomic_or(1, &mEnabled); - } else { - android_atomic_and(~1, &mEnabled); + if (status == NO_ERROR) { + mEnabled = (cmdCode == EFFECT_CMD_ENABLE); } + mLock.unlock(); } return status; @@ -370,11 +373,7 @@ void AudioEffect::enableStatusChanged(bool enabled) { LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf); if (mStatus == ALREADY_EXISTS) { - if (enabled) { - android_atomic_or(1, &mEnabled); - } else { - android_atomic_and(~1, &mEnabled); - } + mEnabled = enabled; if (mCbf) { mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled); } diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a6c515c..1d6ffa0 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -35,7 +35,6 @@ #include <binder/Parcel.h> #include <binder/IPCThreadState.h> #include <utils/Timers.h> -#include <cutils/atomic.h> #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) @@ -282,7 +281,9 @@ status_t AudioRecord::start() t->mLock.lock(); } - if (android_atomic_or(1, &mActive) == 0) { + AutoMutex lock(mLock); + if (mActive == 0) { + mActive = 1; ret = mAudioRecord->start(); if (ret == DEAD_OBJECT) { LOGV("start() dead IAudioRecord: creating a new one"); @@ -302,8 +303,7 @@ status_t AudioRecord::start() setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); } } else { - LOGV("start() failed"); - android_atomic_and(~1, &mActive); + mActive = 0; } } @@ -322,9 +322,11 @@ status_t AudioRecord::stop() if (t != 0) { t->mLock.lock(); - } + } - if (android_atomic_and(~1, &mActive) == 1) { + AutoMutex lock(mLock); + if (mActive == 1) { + mActive = 0; mCblk->cv.signal(); mAudioRecord->stop(); // the record head position will reset to 0, so if a marker is set, we need diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9c2a8ba..1a3fcd6 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -835,6 +835,7 @@ const char *AudioParameter::keySamplingRate = "sampling_rate"; const char *AudioParameter::keyFormat = "format"; const char *AudioParameter::keyChannels = "channels"; const char *AudioParameter::keyFrameCount = "frame_count"; +const char *AudioParameter::keyInputSource = "input_source"; AudioParameter::AudioParameter(const String8& keyValuePairs) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 587c8ff..c1bed59 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -35,7 +35,6 @@ #include <binder/Parcel.h> #include <binder/IPCThreadState.h> #include <utils/Timers.h> -#include <cutils/atomic.h> #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) @@ -312,7 +311,9 @@ void AudioTrack::start() t->mLock.lock(); } - if (android_atomic_or(1, &mActive) == 0) { + AutoMutex lock(mLock); + if (mActive == 0) { + mActive = 1; mNewPosition = mCblk->server + mUpdatePeriod; mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; @@ -344,7 +345,7 @@ void AudioTrack::start() } if (status != NO_ERROR) { LOGV("start() failed"); - android_atomic_and(~1, &mActive); + mActive = 0; if (t != 0) { t->requestExit(); } else { @@ -367,7 +368,9 @@ void AudioTrack::stop() t->mLock.lock(); } - if (android_atomic_and(~1, &mActive) == 1) { + AutoMutex lock(mLock); + if (mActive == 1) { + mActive = 0; mCblk->cv.signal(); mAudioTrack->stop(); // Cancel loops (If we are in the middle of a loop, playback @@ -407,7 +410,6 @@ void AudioTrack::flush() mMarkerReached = false; mUpdatePeriod = 0; - if (!mActive) { mAudioTrack->flush(); // Release AudioTrack callback thread in case it was waiting for new buffers @@ -419,7 +421,9 @@ void AudioTrack::flush() void AudioTrack::pause() { LOGV("pause"); - if (android_atomic_and(~1, &mActive) == 1) { + AutoMutex lock(mLock); + if (mActive == 1) { + mActive = 0; mAudioTrack->pause(); } } diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index 0f55b19..c287c0a 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -22,6 +22,7 @@ #include <media/IMediaPlayer.h> #include <surfaceflinger/ISurface.h> +#include <surfaceflinger/Surface.h> namespace android { @@ -43,8 +44,6 @@ enum { INVOKE, SET_METADATA_FILTER, GET_METADATA, - SUSPEND, - RESUME, SET_AUX_EFFECT_SEND_LEVEL, ATTACH_AUX_EFFECT }; @@ -65,11 +64,11 @@ public: remote()->transact(DISCONNECT, data, &reply); } - status_t setVideoSurface(const sp<ISurface>& surface) + status_t setVideoSurface(const sp<Surface>& surface) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - data.writeStrongBinder(surface->asBinder()); + Surface::writeToParcel(surface, &data); remote()->transact(SET_VIDEO_SURFACE, data, &reply); return reply.readInt32(); } @@ -204,26 +203,6 @@ public: return reply->readInt32(); } - status_t suspend() { - Parcel request; - request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - - Parcel reply; - remote()->transact(SUSPEND, request, &reply); - - return reply.readInt32(); - } - - status_t resume() { - Parcel request; - request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - - Parcel reply; - remote()->transact(RESUME, request, &reply); - - return reply.readInt32(); - } - status_t setAuxEffectSendLevel(float level) { Parcel data, reply; @@ -258,7 +237,7 @@ status_t BnMediaPlayer::onTransact( } break; case SET_VIDEO_SURFACE: { CHECK_INTERFACE(IMediaPlayer, data, reply); - sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder()); + sp<Surface> surface = Surface::readFromParcel(data); reply->writeInt32(setVideoSurface(surface)); return NO_ERROR; } break; @@ -341,16 +320,6 @@ status_t BnMediaPlayer::onTransact( reply->writeInt32(setMetadataFilter(data)); return NO_ERROR; } break; - case SUSPEND: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(suspend()); - return NO_ERROR; - } break; - case RESUME: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(resume()); - return NO_ERROR; - } break; case GET_METADATA: { CHECK_INTERFACE(IMediaPlayer, data, reply); const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply); diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 4abfa75..77199e1 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -23,6 +23,7 @@ #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/IOMX.h> +#include <media/IStreamSource.h> #include <utils/Errors.h> // for status_t @@ -31,6 +32,7 @@ namespace android { enum { CREATE_URL = IBinder::FIRST_CALL_TRANSACTION, CREATE_FD, + CREATE_STREAM, DECODE_URL, DECODE_FD, CREATE_MEDIA_RECORDER, @@ -107,6 +109,21 @@ public: return interface_cast<IMediaPlayer>(reply.readStrongBinder());; } + virtual sp<IMediaPlayer> create( + pid_t pid, const sp<IMediaPlayerClient> &client, + const sp<IStreamSource> &source, int audioSessionId) { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(pid)); + data.writeStrongBinder(client->asBinder()); + data.writeStrongBinder(source->asBinder()); + data.writeInt32(static_cast<int32_t>(audioSessionId)); + + remote()->transact(CREATE_STREAM, data, &reply); + + return interface_cast<IMediaPlayer>(reply.readStrongBinder());; + } + virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) { Parcel data, reply; @@ -184,6 +201,27 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(player->asBinder()); return NO_ERROR; } break; + case CREATE_STREAM: + { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + + pid_t pid = static_cast<pid_t>(data.readInt32()); + + sp<IMediaPlayerClient> client = + interface_cast<IMediaPlayerClient>(data.readStrongBinder()); + + sp<IStreamSource> source = + interface_cast<IStreamSource>(data.readStrongBinder()); + + int audioSessionId = static_cast<int>(data.readInt32()); + + sp<IMediaPlayer> player = + create(pid, client, source, audioSessionId); + + reply->writeStrongBinder(player->asBinder()); + return OK; + break; + } case DECODE_URL: { CHECK_INTERFACE(IMediaPlayerService, data, reply); const char* url = data.readCString(); diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 947ff34..59cd1b7 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -19,7 +19,7 @@ #define LOG_TAG "IMediaRecorder" #include <utils/Log.h> #include <binder/Parcel.h> -#include <surfaceflinger/ISurface.h> +#include <surfaceflinger/Surface.h> #include <camera/ICamera.h> #include <media/IMediaRecorderClient.h> #include <media/IMediaRecorder.h> @@ -43,6 +43,7 @@ enum { SET_AUDIO_ENCODER, SET_OUTPUT_FILE_PATH, SET_OUTPUT_FILE_FD, + SET_OUTPUT_FILE_AUXILIARY_FD, SET_VIDEO_SIZE, SET_VIDEO_FRAMERATE, SET_PARAMETERS, @@ -69,12 +70,12 @@ public: return reply.readInt32(); } - status_t setPreviewSurface(const sp<ISurface>& surface) + status_t setPreviewSurface(const sp<Surface>& surface) { LOGV("setPreviewSurface(%p)", surface.get()); Parcel data, reply; data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeStrongBinder(surface->asBinder()); + Surface::writeToParcel(surface, &data); remote()->transact(SET_PREVIEW_SURFACE, data, &reply); return reply.readInt32(); } @@ -159,6 +160,15 @@ public: return reply.readInt32(); } + status_t setOutputFileAuxiliary(int fd) { + LOGV("setOutputFileAuxiliary(%d)", fd); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeFileDescriptor(fd); + remote()->transact(SET_OUTPUT_FILE_AUXILIARY_FD, data, &reply); + return reply.readInt32(); + } + status_t setVideoSize(int width, int height) { LOGV("setVideoSize(%dx%d)", width, height); @@ -377,6 +387,13 @@ status_t BnMediaRecorder::onTransact( ::close(fd); return NO_ERROR; } break; + case SET_OUTPUT_FILE_AUXILIARY_FD: { + LOGV("SET_OUTPUT_FILE_AUXILIARY_FD"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int fd = dup(data.readFileDescriptor()); + reply->writeInt32(setOutputFileAuxiliary(fd)); + return NO_ERROR; + } break; case SET_VIDEO_SIZE: { LOGV("SET_VIDEO_SIZE"); CHECK_INTERFACE(IMediaRecorder, data, reply); @@ -409,7 +426,7 @@ status_t BnMediaRecorder::onTransact( case SET_PREVIEW_SURFACE: { LOGV("SET_PREVIEW_SURFACE"); CHECK_INTERFACE(IMediaRecorder, data, reply); - sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder()); + sp<Surface> surface = Surface::readFromParcel(data); reply->writeInt32(setPreviewSurface(surface)); return NO_ERROR; } break; diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index ae6c2bf..af67175 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -5,6 +5,7 @@ #include <binder/IMemory.h> #include <binder/Parcel.h> #include <media/IOMX.h> +#include <media/stagefright/foundation/ADebug.h> #include <surfaceflinger/ISurface.h> #include <surfaceflinger/Surface.h> @@ -21,59 +22,19 @@ enum { SET_PARAMETER, GET_CONFIG, SET_CONFIG, + ENABLE_GRAPHIC_BUFFERS, USE_BUFFER, + USE_GRAPHIC_BUFFER, + STORE_META_DATA_IN_BUFFERS, ALLOC_BUFFER, ALLOC_BUFFER_WITH_BACKUP, FREE_BUFFER, FILL_BUFFER, EMPTY_BUFFER, GET_EXTENSION_INDEX, - CREATE_RENDERER, OBSERVER_ON_MSG, - RENDERER_RENDER, }; -sp<IOMXRenderer> IOMX::createRenderer( - const sp<Surface> &surface, - const char *componentName, - OMX_COLOR_FORMATTYPE colorFormat, - size_t encodedWidth, size_t encodedHeight, - size_t displayWidth, size_t displayHeight, - int32_t rotationDegrees) { - return createRenderer( - surface->getISurface(), - componentName, colorFormat, encodedWidth, encodedHeight, - displayWidth, displayHeight, - rotationDegrees); -} - -sp<IOMXRenderer> IOMX::createRendererFromJavaSurface( - JNIEnv *env, jobject javaSurface, - const char *componentName, - OMX_COLOR_FORMATTYPE colorFormat, - size_t encodedWidth, size_t encodedHeight, - size_t displayWidth, size_t displayHeight, - int32_t rotationDegrees) { - jclass surfaceClass = env->FindClass("android/view/Surface"); - if (surfaceClass == NULL) { - LOGE("Can't find android/view/Surface"); - return NULL; - } - - jfieldID surfaceID = env->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I"); - if (surfaceID == NULL) { - LOGE("Can't find Surface.mSurface"); - return NULL; - } - - sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID); - - return createRenderer( - surface, componentName, colorFormat, encodedWidth, - encodedHeight, displayWidth, displayHeight, - rotationDegrees); -} - class BpOMX : public BpInterface<IOMX> { public: BpOMX(const sp<IBinder> &impl) @@ -220,6 +181,19 @@ public: return reply.readInt32(); } + virtual status_t enableGraphicBuffers( + node_id node, OMX_U32 port_index, OMX_BOOL enable) { + Parcel data, reply; + data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); + data.writeIntPtr((intptr_t)node); + data.writeInt32(port_index); + data.writeInt32((uint32_t)enable); + remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply); + + status_t err = reply.readInt32(); + return err; + } + virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, buffer_id *buffer) { @@ -242,6 +216,42 @@ public: return err; } + + virtual status_t useGraphicBuffer( + node_id node, OMX_U32 port_index, + const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { + Parcel data, reply; + data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); + data.writeIntPtr((intptr_t)node); + data.writeInt32(port_index); + data.write(*graphicBuffer); + remote()->transact(USE_GRAPHIC_BUFFER, data, &reply); + + status_t err = reply.readInt32(); + if (err != OK) { + *buffer = 0; + + return err; + } + + *buffer = (void*)reply.readIntPtr(); + + return err; + } + + virtual status_t storeMetaDataInBuffers( + node_id node, OMX_U32 port_index, OMX_BOOL enable) { + Parcel data, reply; + data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); + data.writeIntPtr((intptr_t)node); + data.writeInt32(port_index); + data.writeInt32((uint32_t)enable); + remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); + + status_t err = reply.readInt32(); + return err; + } + virtual status_t allocateBuffer( node_id node, OMX_U32 port_index, size_t size, buffer_id *buffer, void **buffer_data) { @@ -347,30 +357,6 @@ public: return err; } - - virtual sp<IOMXRenderer> createRenderer( - const sp<ISurface> &surface, - const char *componentName, - OMX_COLOR_FORMATTYPE colorFormat, - size_t encodedWidth, size_t encodedHeight, - size_t displayWidth, size_t displayHeight, - int32_t rotationDegrees) { - Parcel data, reply; - data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - - data.writeStrongBinder(surface->asBinder()); - data.writeCString(componentName); - data.writeInt32(colorFormat); - data.writeInt32(encodedWidth); - data.writeInt32(encodedHeight); - data.writeInt32(displayWidth); - data.writeInt32(displayHeight); - data.writeInt32(rotationDegrees); - - remote()->transact(CREATE_RENDERER, data, &reply); - - return interface_cast<IOMXRenderer>(reply.readStrongBinder()); - } }; IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); @@ -464,6 +450,9 @@ status_t BnOMX::onTransact( } case GET_PARAMETER: + case SET_PARAMETER: + case GET_CONFIG: + case SET_CONFIG: { CHECK_INTERFACE(IOMX, data, reply); @@ -472,15 +461,30 @@ status_t BnOMX::onTransact( size_t size = data.readInt32(); - // XXX I am not happy with this but Parcel::readInplace didn't work. void *params = malloc(size); data.read(params, size); - status_t err = getParameter(node, index, params, size); + status_t err; + switch (code) { + case GET_PARAMETER: + err = getParameter(node, index, params, size); + break; + case SET_PARAMETER: + err = setParameter(node, index, params, size); + break; + case GET_CONFIG: + err = getConfig(node, index, params, size); + break; + case SET_CONFIG: + err = setConfig(node, index, params, size); + break; + default: + TRESPASS(); + } reply->writeInt32(err); - if (err == OK) { + if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) { reply->write(params, size); } @@ -490,80 +494,72 @@ status_t BnOMX::onTransact( return NO_ERROR; } - case SET_PARAMETER: + case ENABLE_GRAPHIC_BUFFERS: { CHECK_INTERFACE(IOMX, data, reply); node_id node = (void*)data.readIntPtr(); - OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); - - size_t size = data.readInt32(); - void *params = const_cast<void *>(data.readInplace(size)); + OMX_U32 port_index = data.readInt32(); + OMX_BOOL enable = (OMX_BOOL)data.readInt32(); - reply->writeInt32(setParameter(node, index, params, size)); + status_t err = enableGraphicBuffers(node, port_index, enable); + reply->writeInt32(err); return NO_ERROR; } - case GET_CONFIG: + case USE_BUFFER: { CHECK_INTERFACE(IOMX, data, reply); node_id node = (void*)data.readIntPtr(); - OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); - - size_t size = data.readInt32(); - - // XXX I am not happy with this but Parcel::readInplace didn't work. - void *params = malloc(size); - data.read(params, size); - - status_t err = getConfig(node, index, params, size); + OMX_U32 port_index = data.readInt32(); + sp<IMemory> params = + interface_cast<IMemory>(data.readStrongBinder()); + buffer_id buffer; + status_t err = useBuffer(node, port_index, params, &buffer); reply->writeInt32(err); if (err == OK) { - reply->write(params, size); + reply->writeIntPtr((intptr_t)buffer); } - free(params); - params = NULL; - return NO_ERROR; } - case SET_CONFIG: + case USE_GRAPHIC_BUFFER: { CHECK_INTERFACE(IOMX, data, reply); node_id node = (void*)data.readIntPtr(); - OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); + OMX_U32 port_index = data.readInt32(); + sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); + data.read(*graphicBuffer); - size_t size = data.readInt32(); - void *params = const_cast<void *>(data.readInplace(size)); + buffer_id buffer; + status_t err = useGraphicBuffer( + node, port_index, graphicBuffer, &buffer); + reply->writeInt32(err); - reply->writeInt32(setConfig(node, index, params, size)); + if (err == OK) { + reply->writeIntPtr((intptr_t)buffer); + } return NO_ERROR; } - case USE_BUFFER: + case STORE_META_DATA_IN_BUFFERS: { CHECK_INTERFACE(IOMX, data, reply); node_id node = (void*)data.readIntPtr(); OMX_U32 port_index = data.readInt32(); - sp<IMemory> params = - interface_cast<IMemory>(data.readStrongBinder()); + OMX_BOOL enable = (OMX_BOOL)data.readInt32(); - buffer_id buffer; - status_t err = useBuffer(node, port_index, params, &buffer); + status_t err = storeMetaDataInBuffers(node, port_index, enable); reply->writeInt32(err); - if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); - } - return NO_ERROR; } @@ -672,35 +668,6 @@ status_t BnOMX::onTransact( return OK; } - case CREATE_RENDERER: - { - CHECK_INTERFACE(IOMX, data, reply); - - sp<ISurface> isurface = - interface_cast<ISurface>(data.readStrongBinder()); - - const char *componentName = data.readCString(); - - OMX_COLOR_FORMATTYPE colorFormat = - static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32()); - - size_t encodedWidth = (size_t)data.readInt32(); - size_t encodedHeight = (size_t)data.readInt32(); - size_t displayWidth = (size_t)data.readInt32(); - size_t displayHeight = (size_t)data.readInt32(); - int32_t rotationDegrees = data.readInt32(); - - sp<IOMXRenderer> renderer = - createRenderer(isurface, componentName, colorFormat, - encodedWidth, encodedHeight, - displayWidth, displayHeight, - rotationDegrees); - - reply->writeStrongBinder(renderer->asBinder()); - - return OK; - } - default: return BBinder::onTransact(code, data, reply, flags); } @@ -746,44 +713,4 @@ status_t BnOMXObserver::onTransact( } } -//////////////////////////////////////////////////////////////////////////////// - -class BpOMXRenderer : public BpInterface<IOMXRenderer> { -public: - BpOMXRenderer(const sp<IBinder> &impl) - : BpInterface<IOMXRenderer>(impl) { - } - - virtual void render(IOMX::buffer_id buffer) { - Parcel data, reply; - data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)buffer); - - // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous - // so that the caller knows when to recycle the buffer. - remote()->transact(RENDERER_RENDER, data, &reply); - } -}; - -IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer"); - -status_t BnOMXRenderer::onTransact( - uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { - switch (code) { - case RENDERER_RENDER: - { - CHECK_INTERFACE(IOMXRenderer, data, reply); - - IOMX::buffer_id buffer = (void*)data.readIntPtr(); - - render(buffer); - - return NO_ERROR; - } - - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - } // namespace android diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp new file mode 100644 index 0000000..5069002 --- /dev/null +++ b/media/libmedia/IStreamSource.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2010 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 "IStreamSource" +#include <utils/Log.h> + +#include <media/IStreamSource.h> +#include <media/stagefright/foundation/AMessage.h> + +#include <binder/IMemory.h> +#include <binder/Parcel.h> + +namespace android { + +enum { + // IStreamSource + SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, + SET_BUFFERS, + ON_BUFFER_AVAILABLE, + + // IStreamListener + QUEUE_BUFFER, + ISSUE_COMMAND, +}; + +struct BpStreamSource : public BpInterface<IStreamSource> { + BpStreamSource(const sp<IBinder> &impl) + : BpInterface<IStreamSource>(impl) { + } + + virtual void setListener(const sp<IStreamListener> &listener) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(SET_LISTENER, data, &reply); + } + + virtual void setBuffers(const Vector<sp<IMemory> > &buffers) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(buffers.size())); + for (size_t i = 0; i < buffers.size(); ++i) { + data.writeStrongBinder(buffers.itemAt(i)->asBinder()); + } + remote()->transact(SET_BUFFERS, data, &reply); + } + + virtual void onBufferAvailable(size_t index) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(index)); + remote()->transact( + ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(StreamSource, "android.hardware.IStreamSource"); + +status_t BnStreamSource::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case SET_LISTENER: + { + CHECK_INTERFACE(IStreamSource, data, reply); + setListener( + interface_cast<IStreamListener>(data.readStrongBinder())); + break; + } + + case SET_BUFFERS: + { + CHECK_INTERFACE(IStreamSource, data, reply); + size_t n = static_cast<size_t>(data.readInt32()); + Vector<sp<IMemory> > buffers; + for (size_t i = 0; i < n; ++i) { + sp<IMemory> mem = + interface_cast<IMemory>(data.readStrongBinder()); + + buffers.push(mem); + } + setBuffers(buffers); + break; + } + + case ON_BUFFER_AVAILABLE: + { + CHECK_INTERFACE(IStreamSource, data, reply); + onBufferAvailable(static_cast<size_t>(data.readInt32())); + break; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } + + return OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +struct BpStreamListener : public BpInterface<IStreamListener> { + BpStreamListener(const sp<IBinder> &impl) + : BpInterface<IStreamListener>(impl) { + } + + virtual void queueBuffer(size_t index, size_t size) { + Parcel data, reply; + data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(index)); + data.writeInt32(static_cast<int32_t>(size)); + + remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual void issueCommand( + Command cmd, bool synchronous, const sp<AMessage> &msg) { + Parcel data, reply; + data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(cmd)); + data.writeInt32(static_cast<int32_t>(synchronous)); + + if (msg != NULL) { + data.writeInt32(1); + msg->writeToParcel(&data); + } else { + data.writeInt32(0); + } + + remote()->transact(ISSUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(StreamListener, "android.hardware.IStreamListener"); + +status_t BnStreamListener::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case QUEUE_BUFFER: + { + CHECK_INTERFACE(IStreamListener, data, reply); + size_t index = static_cast<size_t>(data.readInt32()); + size_t size = static_cast<size_t>(data.readInt32()); + + queueBuffer(index, size); + break; + } + + case ISSUE_COMMAND: + { + CHECK_INTERFACE(IStreamListener, data, reply); + Command cmd = static_cast<Command>(data.readInt32()); + + bool synchronous = static_cast<bool>(data.readInt32()); + + sp<AMessage> msg; + + if (data.readInt32()) { + msg = AMessage::FromParcel(data); + } + + issueCommand(cmd, synchronous, msg); + break; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } + + return OK; +} + +} // namespace android diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 3869389..9ad63f0 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -59,8 +59,21 @@ const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = { }; const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { + {"low", CAMCORDER_QUALITY_LOW}, {"high", CAMCORDER_QUALITY_HIGH}, - {"low", CAMCORDER_QUALITY_LOW} + {"qcif", CAMCORDER_QUALITY_QCIF}, + {"cif", CAMCORDER_QUALITY_CIF}, + {"480p", CAMCORDER_QUALITY_480P}, + {"720p", CAMCORDER_QUALITY_720P}, + {"1080p", CAMCORDER_QUALITY_1080P}, + + {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW}, + {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH}, + {"timelapseqcif", CAMCORDER_QUALITY_TIME_LAPSE_QCIF}, + {"timelapsecif", CAMCORDER_QUALITY_TIME_LAPSE_CIF}, + {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P}, + {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P}, + {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P} }; /*static*/ void @@ -411,24 +424,57 @@ MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles) } /*static*/ MediaProfiles::CamcorderProfile* -MediaProfiles::createDefaultCamcorderHighProfile() +MediaProfiles::createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality) { MediaProfiles::VideoCodec *videoCodec = - new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20); + new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 1000000, 176, 144, 20); + + AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); + CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; + profile->mCameraId = 0; + profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; + profile->mQuality = quality; + profile->mDuration = 60; + profile->mVideoCodec = videoCodec; + profile->mAudioCodec = audioCodec; + return profile; +} + +/*static*/ MediaProfiles::CamcorderProfile* +MediaProfiles::createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality) +{ + MediaProfiles::VideoCodec *videoCodec = + new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 20000000, 720, 480, 20); AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; profile->mCameraId = 0; profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; - profile->mQuality = CAMCORDER_QUALITY_HIGH; + profile->mQuality = quality; profile->mDuration = 60; profile->mVideoCodec = videoCodec; profile->mAudioCodec = audioCodec; return profile; } +/*static*/ void +MediaProfiles::createDefaultCamcorderTimeLapseLowProfiles( + MediaProfiles::CamcorderProfile **lowTimeLapseProfile, + MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile) { + *lowTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(CAMCORDER_QUALITY_TIME_LAPSE_LOW); + *lowSpecificTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(CAMCORDER_QUALITY_TIME_LAPSE_QCIF); +} + +/*static*/ void +MediaProfiles::createDefaultCamcorderTimeLapseHighProfiles( + MediaProfiles::CamcorderProfile **highTimeLapseProfile, + MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile) { + *highTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(CAMCORDER_QUALITY_TIME_LAPSE_HIGH); + *highSpecificTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(CAMCORDER_QUALITY_TIME_LAPSE_480P); +} + /*static*/ MediaProfiles::CamcorderProfile* -MediaProfiles::createDefaultCamcorderLowProfile() +MediaProfiles::createDefaultCamcorderQcifProfile(camcorder_quality quality) { MediaProfiles::VideoCodec *videoCodec = new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20); @@ -439,18 +485,72 @@ MediaProfiles::createDefaultCamcorderLowProfile() MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; profile->mCameraId = 0; profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; - profile->mQuality = CAMCORDER_QUALITY_LOW; + profile->mQuality = quality; profile->mDuration = 30; profile->mVideoCodec = videoCodec; profile->mAudioCodec = audioCodec; return profile; } +/*static*/ MediaProfiles::CamcorderProfile* +MediaProfiles::createDefaultCamcorderCifProfile(camcorder_quality quality) +{ + MediaProfiles::VideoCodec *videoCodec = + new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20); + + AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); + CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; + profile->mCameraId = 0; + profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; + profile->mQuality = quality; + profile->mDuration = 60; + profile->mVideoCodec = videoCodec; + profile->mAudioCodec = audioCodec; + return profile; +} + +/*static*/ void +MediaProfiles::createDefaultCamcorderLowProfiles( + MediaProfiles::CamcorderProfile **lowProfile, + MediaProfiles::CamcorderProfile **lowSpecificProfile) { + *lowProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_LOW); + *lowSpecificProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_QCIF); +} + +/*static*/ void +MediaProfiles::createDefaultCamcorderHighProfiles( + MediaProfiles::CamcorderProfile **highProfile, + MediaProfiles::CamcorderProfile **highSpecificProfile) { + *highProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_HIGH); + *highSpecificProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_CIF); +} + /*static*/ void MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles) { - profiles->mCamcorderProfiles.add(createDefaultCamcorderHighProfile()); - profiles->mCamcorderProfiles.add(createDefaultCamcorderLowProfile()); + // low camcorder profiles. + MediaProfiles::CamcorderProfile *lowProfile, *lowSpecificProfile; + createDefaultCamcorderLowProfiles(&lowProfile, &lowSpecificProfile); + profiles->mCamcorderProfiles.add(lowProfile); + profiles->mCamcorderProfiles.add(lowSpecificProfile); + + // high camcorder profiles. + MediaProfiles::CamcorderProfile* highProfile, *highSpecificProfile; + createDefaultCamcorderHighProfiles(&highProfile, &highSpecificProfile); + profiles->mCamcorderProfiles.add(highProfile); + profiles->mCamcorderProfiles.add(highSpecificProfile); + + // low camcorder time lapse profiles. + MediaProfiles::CamcorderProfile *lowTimeLapseProfile, *lowSpecificTimeLapseProfile; + createDefaultCamcorderTimeLapseLowProfiles(&lowTimeLapseProfile, &lowSpecificTimeLapseProfile); + profiles->mCamcorderProfiles.add(lowTimeLapseProfile); + profiles->mCamcorderProfiles.add(lowSpecificTimeLapseProfile); + + // high camcorder time lapse profiles. + MediaProfiles::CamcorderProfile *highTimeLapseProfile, *highSpecificTimeLapseProfile; + createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, &highSpecificTimeLapseProfile); + profiles->mCamcorderProfiles.add(highTimeLapseProfile); + profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile); } /*static*/ void @@ -668,13 +768,8 @@ Vector<audio_decoder> MediaProfiles::getAudioDecoders() const return decoders; // copy out } -int MediaProfiles::getCamcorderProfileParamByName(const char *name, - int cameraId, - camcorder_quality quality) const +int MediaProfiles::getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const { - LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d", - name, cameraId, quality); - int index = -1; for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) { if (mCamcorderProfiles[i]->mCameraId == cameraId && @@ -683,6 +778,17 @@ int MediaProfiles::getCamcorderProfileParamByName(const char *name, break; } } + return index; +} + +int MediaProfiles::getCamcorderProfileParamByName(const char *name, + int cameraId, + camcorder_quality quality) const +{ + LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d", + name, cameraId, quality); + + int index = getCamcorderProfileIndex(cameraId, quality); if (index == -1) { LOGE("The given camcorder profile camera %d quality %d is not found", cameraId, quality); @@ -705,6 +811,11 @@ int MediaProfiles::getCamcorderProfileParamByName(const char *name, return -1; } +bool MediaProfiles::hasCamcorderProfile(int cameraId, camcorder_quality quality) const +{ + return (getCamcorderProfileIndex(cameraId, quality) != -1); +} + Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const { Vector<int> result; diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp index c5112a5..5ec573e 100644 --- a/media/libmedia/MediaScanner.cpp +++ b/media/libmedia/MediaScanner.cpp @@ -48,8 +48,7 @@ const char *MediaScanner::locale() const { } status_t MediaScanner::processDirectory( - const char *path, const char *extensions, - MediaScannerClient &client, + const char *path, MediaScannerClient &client, ExceptionCheck exceptionCheck, void *exceptionEnv) { int pathLength = strlen(path); if (pathLength >= PATH_MAX) { @@ -72,38 +71,20 @@ status_t MediaScanner::processDirectory( status_t result = doProcessDirectory( - pathBuffer, pathRemaining, extensions, client, - exceptionCheck, exceptionEnv); + pathBuffer, pathRemaining, client, exceptionCheck, exceptionEnv); free(pathBuffer); return result; } -static bool fileMatchesExtension(const char* path, const char* extensions) { - const char* extension = strrchr(path, '.'); - if (!extension) return false; - ++extension; // skip the dot - if (extension[0] == 0) return false; - - while (extensions[0]) { - const char* comma = strchr(extensions, ','); - size_t length = (comma ? comma - extensions : strlen(extensions)); - if (length == strlen(extension) && strncasecmp(extension, extensions, length) == 0) return true; - extensions += length; - if (extensions[0] == ',') ++extensions; - } - - return false; -} - status_t MediaScanner::doProcessDirectory( - char *path, int pathRemaining, const char *extensions, - MediaScannerClient &client, ExceptionCheck exceptionCheck, - void *exceptionEnv) { + char *path, int pathRemaining, MediaScannerClient &client, + ExceptionCheck exceptionCheck, void *exceptionEnv) { // place to copy file or directory name char* fileSpot = path + strlen(path); struct dirent* entry; + struct stat statbuf; // ignore directories that contain a ".nomedia" file if (pathRemaining >= 8 /* strlen(".nomedia") */ ) { @@ -133,12 +114,18 @@ status_t MediaScanner::doProcessDirectory( continue; } + int nameLength = strlen(name); + if (nameLength + 1 > pathRemaining) { + // path too long! + continue; + } + strcpy(fileSpot, name); + int type = entry->d_type; if (type == DT_UNKNOWN) { // If the type is unknown, stat() the file instead. // This is sometimes necessary when accessing NFS mounted filesystems, but // could be needed in other cases well. - struct stat statbuf; if (stat(path, &statbuf) == 0) { if (S_ISREG(statbuf.st_mode)) { type = DT_REG; @@ -150,34 +137,29 @@ status_t MediaScanner::doProcessDirectory( } } if (type == DT_REG || type == DT_DIR) { - int nameLength = strlen(name); - bool isDirectory = (type == DT_DIR); - - if (nameLength > pathRemaining || (isDirectory && nameLength + 1 > pathRemaining)) { - // path too long! - continue; - } - - strcpy(fileSpot, name); - if (isDirectory) { + if (type == DT_DIR) { // ignore directories with a name that starts with '.' // for example, the Mac ".Trashes" directory if (name[0] == '.') continue; + // report the directory to the client + if (stat(path, &statbuf) == 0) { + client.scanFile(path, statbuf.st_mtime, 0, true); + } + + // and now process its contents strcat(fileSpot, "/"); - int err = doProcessDirectory(path, pathRemaining - nameLength - 1, extensions, client, exceptionCheck, exceptionEnv); + int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client, + exceptionCheck, exceptionEnv); if (err) { // pass exceptions up - ignore other errors if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure; LOGE("Error processing '%s' - skipping\n", path); continue; } - } else if (fileMatchesExtension(path, extensions)) { - struct stat statbuf; + } else { stat(path, &statbuf); - if (statbuf.st_size > 0) { - client.scanFile(path, statbuf.st_mtime, statbuf.st_size); - } + client.scanFile(path, statbuf.st_mtime, statbuf.st_size, false); if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure; } } diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index cc41e66..87c8fe4 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -172,16 +172,6 @@ status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply) return INVALID_OPERATION; } -status_t MediaPlayer::suspend() { - Mutex::Autolock _l(mLock); - return mPlayer->suspend(); -} - -status_t MediaPlayer::resume() { - Mutex::Autolock _l(mLock); - return mPlayer->resume(); -} - status_t MediaPlayer::setMetadataFilter(const Parcel& filter) { LOGD("setMetadataFilter"); @@ -207,10 +197,8 @@ status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) LOGV("setVideoSurface"); Mutex::Autolock _l(mLock); if (mPlayer == 0) return NO_INIT; - if (surface != NULL) - return mPlayer->setVideoSurface(surface->getISurface()); - else - return mPlayer->setVideoSurface(NULL); + + return mPlayer->setVideoSurface(surface); } // must call with lock held @@ -449,6 +437,9 @@ status_t MediaPlayer::reset() } else { mCurrentState = MEDIA_PLAYER_IDLE; } + // setDataSource has to be called again to create a + // new mediaplayer. + mPlayer = 0; return ret; } clear_l(); @@ -616,7 +607,9 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) case MEDIA_INFO: // ext1: Media framework error code. // ext2: Implementation dependant error code. - LOGW("info/warning (%d, %d)", ext1, ext2); + if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) { + LOGW("info/warning (%d, %d)", ext1, ext2); + } break; case MEDIA_SEEK_COMPLETE: LOGV("Received seek complete"); diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index e20e3ba..fd575fe 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -65,7 +65,7 @@ status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface) return INVALID_OPERATION; } - status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface()); + status_t ret = mMediaRecorder->setPreviewSurface(surface); if (OK != ret) { LOGV("setPreviewSurface failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; @@ -308,6 +308,32 @@ status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) return ret; } +status_t MediaRecorder::setOutputFileAuxiliary(int fd) +{ + LOGV("setOutputFileAuxiliary(%d)", fd); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mIsAuxiliaryOutputFileSet) { + LOGE("output file has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd); + if (OK != ret) { + LOGV("setOutputFileAuxiliary failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return ret; + } + mIsAuxiliaryOutputFileSet = true; + return ret; +} + status_t MediaRecorder::setVideoSize(int width, int height) { LOGV("setVideoSize(%d, %d)", width, height); @@ -571,6 +597,7 @@ void MediaRecorder::doCleanUp() mIsAudioEncoderSet = false; mIsVideoEncoderSet = false; mIsOutputFileSet = false; + mIsAuxiliaryOutputFileSet = false; } // Release should be OK in any state @@ -643,4 +670,3 @@ void MediaRecorder::died() } }; // namespace android - |