diff options
Diffstat (limited to 'media')
80 files changed, 903 insertions, 370 deletions
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk index 5d0a87c..2bb6dbe 100644 --- a/media/libeffects/downmix/Android.mk +++ b/media/libeffects/downmix/Android.mk @@ -13,7 +13,7 @@ LOCAL_MODULE:= libdownmix LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) LOCAL_LDLIBS += -ldl diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c index f779876..4ee05f2 100644 --- a/media/libeffects/downmix/EffectDownmix.c +++ b/media/libeffects/downmix/EffectDownmix.c @@ -707,7 +707,7 @@ int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t siz case DOWNMIX_PARAM_TYPE: if (size != sizeof(downmix_type_t)) { - ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %d, should be %d", + ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %zu, should be %zu", size, sizeof(downmix_type_t)); return -EINVAL; } @@ -760,7 +760,7 @@ int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pS case DOWNMIX_PARAM_TYPE: if (*pSize < sizeof(int16_t)) { - ALOGE("Downmix_getParameter invalid parameter size %d for DOWNMIX_PARAM_TYPE", *pSize); + ALOGE("Downmix_getParameter invalid parameter size %zu for DOWNMIX_PARAM_TYPE", *pSize); return -EINVAL; } pValue16 = (int16_t *)pValue; diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk index 60a6ce5..a932af7 100644 --- a/media/libeffects/factory/Android.mk +++ b/media/libeffects/factory/Android.mk @@ -9,7 +9,6 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils liblog -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) LOCAL_MODULE:= libeffects LOCAL_SHARED_LIBRARIES += libdl diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c index f8d6041..6d30d64 100644 --- a/media/libeffects/factory/EffectsFactory.c +++ b/media/libeffects/factory/EffectsFactory.c @@ -368,27 +368,21 @@ int EffectRelease(effect_handle_t handle) } if (e1 == NULL) { ret = -ENOENT; - pthread_mutex_unlock(&gLibLock); goto exit; } // release effect in library if (fx->lib == NULL) { ALOGW("EffectRelease() fx %p library already unloaded", handle); - pthread_mutex_unlock(&gLibLock); } else { pthread_mutex_lock(&fx->lib->lock); - // Releasing the gLibLock here as the list access is over as the - // effect is removed from the list. - // If the gLibLock is not released, we will have a deadlock situation - // since we call the sub effect release inside the EffectRelease of Proxy - pthread_mutex_unlock(&gLibLock); fx->lib->desc->release_effect(fx->subItfe); pthread_mutex_unlock(&fx->lib->lock); } free(fx); exit: + pthread_mutex_unlock(&gLibLock); return ret; } @@ -404,8 +398,8 @@ int EffectIsNullUuid(const effect_uuid_t *uuid) // is pointed by the first argument. It searches the gSubEffectList for the // matching uuid and then copies the corresponding sub effect descriptors // to the inout param -int EffectGetSubEffects(const effect_uuid_t *uuid, - effect_descriptor_t *pDescriptors, size_t size) +int EffectGetSubEffects(const effect_uuid_t *uuid, sub_effect_entry_t **pSube, + size_t size) { ALOGV("EffectGetSubEffects() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X" "%02X\n",uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, @@ -413,8 +407,7 @@ int EffectGetSubEffects(const effect_uuid_t *uuid, uuid->node[3],uuid->node[4],uuid->node[5]); // Check if the size of the desc buffer is large enough for 2 subeffects - if ((uuid == NULL) || (pDescriptors == NULL) || - (size < 2*sizeof(effect_descriptor_t))) { + if ((uuid == NULL) || (pSube == NULL) || (size < 2)) { ALOGW("NULL pointer or insufficient memory. Cannot query subeffects"); return -EINVAL; } @@ -432,11 +425,10 @@ int EffectGetSubEffects(const effect_uuid_t *uuid, list_elem_t *subefx = e->sub_elem; while (subefx != NULL) { subeffect = (sub_effect_entry_t*)subefx->object; - d = (effect_descriptor_t*)(subeffect->object); - pDescriptors[count++] = *d; + pSube[count++] = subeffect; subefx = subefx->next; } - ALOGV("EffectGetSubEffects end - copied the sub effect descriptors"); + ALOGV("EffectGetSubEffects end - copied the sub effect structures"); return count; } e = e->next; diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h index 147ff18..560b485 100644 --- a/media/libeffects/factory/EffectsFactory.h +++ b/media/libeffects/factory/EffectsFactory.h @@ -20,7 +20,7 @@ #include <cutils/log.h> #include <pthread.h> #include <dirent.h> -#include <media/EffectsFactoryApi.h> +#include <hardware/audio_effect.h> #if __cplusplus extern "C" { @@ -66,6 +66,32 @@ typedef struct sub_effect_entry_s { void *object; } sub_effect_entry_t; + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectGetSubEffects +// +// Description: Returns the descriptors of the sub effects of the effect +// whose uuid is pointed to by first argument. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// size: max number of sub_effect_entry_t * in pSube. +// +// Input/Output: +// pSube: address where to return the sub effect structures. +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pEffectUuid or pDescriptor +// -ENOENT no effect with this uuid found +// *pDescriptor: updated with the sub effect descriptors. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectGetSubEffects(const effect_uuid_t *pEffectUuid, + sub_effect_entry_t **pSube, + size_t size); + #if __cplusplus } // extern "C" #endif diff --git a/media/libeffects/loudness/Android.mk b/media/libeffects/loudness/Android.mk index dcb7b27..edf964e 100644 --- a/media/libeffects/loudness/Android.mk +++ b/media/libeffects/loudness/Android.mk @@ -14,7 +14,7 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libstlport -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libldnhncr LOCAL_C_INCLUDES := \ diff --git a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp index 91ed677..3c2b320 100644 --- a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp +++ b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp @@ -453,13 +453,13 @@ const struct effect_interface_s gLEInterface = { // This is the only symbol that needs to be exported __attribute__ ((visibility ("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { - tag : AUDIO_EFFECT_LIBRARY_TAG, - version : EFFECT_LIBRARY_API_VERSION, - name : "Loudness Enhancer Library", - implementor : "The Android Open Source Project", - create_effect : LELib_Create, - release_effect : LELib_Release, - get_descriptor : LELib_GetDescriptor, + .tag = AUDIO_EFFECT_LIBRARY_TAG, + .version = EFFECT_LIBRARY_API_VERSION, + .name = "Loudness Enhancer Library", + .implementor = "The Android Open Source Project", + .create_effect = LELib_Create, + .release_effect = LELib_Release, + .get_descriptor = LELib_GetDescriptor, }; }; // extern "C" diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c index c4767a8..e01c1c5 100644 --- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c @@ -25,6 +25,7 @@ #include "LVEQNB.h" #include "LVEQNB_Private.h" #include "InstAlloc.h" +#include <string.h> /* For memset */ /****************************************************************************************/ /* */ diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk index f1af389..68ba34c 100644 --- a/media/libeffects/lvm/wrapper/Android.mk +++ b/media/libeffects/lvm/wrapper/Android.mk @@ -13,7 +13,7 @@ LOCAL_CFLAGS += -fvisibility=hidden LOCAL_MODULE:= libbundlewrapper -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_STATIC_LIBRARIES += libmusicbundle @@ -42,7 +42,7 @@ LOCAL_CFLAGS += -fvisibility=hidden LOCAL_MODULE:= libreverbwrapper -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_STATIC_LIBRARIES += libreverb diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index 28d239a..58d7767 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -138,22 +138,22 @@ void Effect_getConfig (EffectContext *pContext, effect_config_t *pConfi int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue); int BassBoost_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue); int Virtualizer_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue); int Equalizer_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue); int Volume_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Effect_setEnabled(EffectContext *pContext, bool enabled); @@ -1758,7 +1758,7 @@ int32_t VolumeEnableStereoPosition(EffectContext *pContext, uint32_t enabled){ int BassBoost_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int32_t *pParamTemp = (int32_t *)pParam; @@ -1876,7 +1876,7 @@ int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue) int Virtualizer_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int32_t *pParamTemp = (int32_t *)pParam; @@ -1994,7 +1994,7 @@ int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValu //---------------------------------------------------------------------------- int Equalizer_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int bMute = 0; @@ -2252,7 +2252,7 @@ int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue) int Volume_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int bMute = 0; @@ -2830,7 +2830,7 @@ int Effect_command(effect_handle_t self, p->status = android::BassBoost_getParameter(pContext, p->data, - (size_t *)&p->vsize, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; @@ -2860,8 +2860,8 @@ int Effect_command(effect_handle_t self, int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); p->status = android::Virtualizer_getParameter(pContext, - (void *)p->data, - (size_t *)&p->vsize, + (void *)p->data, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; @@ -2925,7 +2925,7 @@ int Effect_command(effect_handle_t self, p->status = android::Volume_getParameter(pContext, (void *)p->data, - (size_t *)&p->vsize, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk index c344352..9e8cb83 100644 --- a/media/libeffects/preprocessing/Android.mk +++ b/media/libeffects/preprocessing/Android.mk @@ -5,7 +5,7 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libaudiopreprocessing LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_SRC_FILES:= \ PreProcessing.cpp diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp index d72eaf5..c56ff72 100644 --- a/media/libeffects/preprocessing/PreProcessing.cpp +++ b/media/libeffects/preprocessing/PreProcessing.cpp @@ -1233,8 +1233,8 @@ int PreProcessingFx_Process(effect_handle_t self, if (session->framesIn < session->frameCount) { return 0; } - size_t frIn = session->framesIn; - size_t frOut = session->apmFrameCount; + spx_uint32_t frIn = session->framesIn; + spx_uint32_t frOut = session->apmFrameCount; if (session->inChannelCount == 1) { speex_resampler_process_int(session->inResampler, 0, @@ -1290,8 +1290,8 @@ int PreProcessingFx_Process(effect_handle_t self, } if (session->outResampler != NULL) { - size_t frIn = session->apmFrameCount; - size_t frOut = session->frameCount; + spx_uint32_t frIn = session->apmFrameCount; + spx_uint32_t frOut = session->frameCount; if (session->inChannelCount == 1) { speex_resampler_process_int(session->outResampler, 0, @@ -1754,8 +1754,8 @@ int PreProcessingFx_ProcessReverse(effect_handle_t self, if (session->framesRev < session->frameCount) { return 0; } - size_t frIn = session->framesRev; - size_t frOut = session->apmFrameCount; + spx_uint32_t frIn = session->framesRev; + spx_uint32_t frOut = session->apmFrameCount; if (session->inChannelCount == 1) { speex_resampler_process_int(session->revResampler, 0, diff --git a/media/libeffects/proxy/Android.mk b/media/libeffects/proxy/Android.mk index 01b3be1..b438796 100644 --- a/media/libeffects/proxy/Android.mk +++ b/media/libeffects/proxy/Android.mk @@ -15,7 +15,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= libeffectproxy -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE_TAGS := optional @@ -28,7 +28,8 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libdl libeffects LOCAL_C_INCLUDES := \ system/media/audio_effects/include \ - bionic/libc/include + bionic/libc/include \ + frameworks/av/media/libeffects/factory include $(BUILD_SHARED_LIBRARY) diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp index dd4ad08..62d3fd3 100644 --- a/media/libeffects/proxy/EffectProxy.cpp +++ b/media/libeffects/proxy/EffectProxy.cpp @@ -56,6 +56,8 @@ int EffectProxyCreate(const effect_uuid_t *uuid, effect_handle_t *pHandle) { effect_descriptor_t* desc; + audio_effect_library_t** aeli; + sub_effect_entry_t** sube; EffectContext* pContext; if (pHandle == NULL || uuid == NULL) { ALOGE("EffectProxyCreate() called with NULL pointer"); @@ -74,31 +76,52 @@ int EffectProxyCreate(const effect_uuid_t *uuid, // Get the HW and SW sub effect descriptors from the effects factory desc = new effect_descriptor_t[SUB_FX_COUNT]; + aeli = new audio_effect_library_t*[SUB_FX_COUNT]; + sube = new sub_effect_entry_t*[SUB_FX_COUNT]; + pContext->sube = new sub_effect_entry_t*[SUB_FX_COUNT]; pContext->desc = new effect_descriptor_t[SUB_FX_COUNT]; - int retValue = EffectGetSubEffects(uuid, desc, - sizeof(effect_descriptor_t) * SUB_FX_COUNT); + pContext->aeli = new audio_effect_library_t*[SUB_FX_COUNT]; + int retValue = EffectGetSubEffects(uuid, sube, SUB_FX_COUNT); // EffectGetSubEffects returns the number of sub-effects copied. if (retValue != SUB_FX_COUNT) { ALOGE("EffectCreate() could not get the sub effects"); - delete desc; - delete pContext->desc; + delete[] sube; + delete[] desc; + delete[] aeli; + delete[] pContext->sube; + delete[] pContext->desc; + delete[] pContext->aeli; return -EINVAL; } // Check which is the HW descriptor and copy the descriptors // to the Context desc array // Also check if there is only one HW and one SW descriptor. // HW descriptor alone has the HW_TUNNEL flag. + desc[0] = *(effect_descriptor_t*)(sube[0])->object; + desc[1] = *(effect_descriptor_t*)(sube[1])->object; + aeli[0] = sube[0]->lib->desc; + aeli[1] = sube[1]->lib->desc; if ((desc[0].flags & EFFECT_FLAG_HW_ACC_TUNNEL) && !(desc[1].flags & EFFECT_FLAG_HW_ACC_TUNNEL)) { + pContext->sube[SUB_FX_OFFLOAD] = sube[0]; pContext->desc[SUB_FX_OFFLOAD] = desc[0]; + pContext->aeli[SUB_FX_OFFLOAD] = aeli[0]; + pContext->sube[SUB_FX_HOST] = sube[1]; pContext->desc[SUB_FX_HOST] = desc[1]; + pContext->aeli[SUB_FX_HOST] = aeli[1]; } else if ((desc[1].flags & EFFECT_FLAG_HW_ACC_TUNNEL) && !(desc[0].flags & EFFECT_FLAG_HW_ACC_TUNNEL)) { + pContext->sube[SUB_FX_HOST] = sube[0]; pContext->desc[SUB_FX_HOST] = desc[0]; + pContext->aeli[SUB_FX_HOST] = aeli[0]; + pContext->sube[SUB_FX_OFFLOAD] = sube[1]; pContext->desc[SUB_FX_OFFLOAD] = desc[1]; + pContext->aeli[SUB_FX_OFFLOAD] = aeli[1]; } - delete desc; + delete[] desc; + delete[] aeli; + delete[] sube; #if (LOG_NDEBUG == 0) effect_uuid_t uuid_print = pContext->desc[SUB_FX_HOST].uuid; ALOGV("EffectCreate() UUID of HOST: %08X-%04X-%04X-%04X-%02X%02X%02X%02X" @@ -128,13 +151,15 @@ int EffectProxyRelease(effect_handle_t handle) { return -EINVAL; } ALOGV("EffectRelease"); - delete pContext->desc; + delete[] pContext->desc; free(pContext->replyData); if (pContext->eHandle[SUB_FX_HOST]) - EffectRelease(pContext->eHandle[SUB_FX_HOST]); + pContext->aeli[SUB_FX_HOST]->release_effect(pContext->eHandle[SUB_FX_HOST]); if (pContext->eHandle[SUB_FX_OFFLOAD]) - EffectRelease(pContext->eHandle[SUB_FX_OFFLOAD]); + pContext->aeli[SUB_FX_OFFLOAD]->release_effect(pContext->eHandle[SUB_FX_OFFLOAD]); + delete[] pContext->aeli; + delete[] pContext->sube; delete pContext; pContext = NULL; return 0; @@ -187,7 +212,8 @@ int Effect_command(effect_handle_t self, } if (pContext->eHandle[SUB_FX_HOST] == NULL) { ALOGV("Effect_command() Calling HOST EffectCreate"); - status = EffectCreate(&pContext->desc[SUB_FX_HOST].uuid, + status = pContext->aeli[SUB_FX_HOST]->create_effect( + &pContext->desc[SUB_FX_HOST].uuid, pContext->sessionId, pContext->ioId, &(pContext->eHandle[SUB_FX_HOST])); if (status != NO_ERROR || (pContext->eHandle[SUB_FX_HOST] == NULL)) { @@ -197,11 +223,13 @@ int Effect_command(effect_handle_t self, } if (pContext->eHandle[SUB_FX_OFFLOAD] == NULL) { ALOGV("Effect_command() Calling OFFLOAD EffectCreate"); - status = EffectCreate(&pContext->desc[SUB_FX_OFFLOAD].uuid, + status = pContext->aeli[SUB_FX_OFFLOAD]->create_effect( + &pContext->desc[SUB_FX_OFFLOAD].uuid, pContext->sessionId, pContext->ioId, &(pContext->eHandle[SUB_FX_OFFLOAD])); if (status != NO_ERROR || (pContext->eHandle[SUB_FX_OFFLOAD] == NULL)) { ALOGV("Effect_command() Error creating HW effect"); + pContext->eHandle[SUB_FX_OFFLOAD] = NULL; // Do not return error here as SW effect is created // Return error if the CMD_OFFLOAD sends the index as OFFLOAD } @@ -233,11 +261,17 @@ int Effect_command(effect_handle_t self, // Update the DSP wrapper with the new ioHandle. // Pass the OFFLOAD command to the wrapper. // The DSP wrapper needs to handle this CMD - if (pContext->eHandle[SUB_FX_OFFLOAD]) - status = (*pContext->eHandle[SUB_FX_OFFLOAD])->command( - pContext->eHandle[SUB_FX_OFFLOAD], cmdCode, cmdSize, - pCmdData, replySize, pReplyData); - return status; + if (pContext->eHandle[SUB_FX_OFFLOAD]) { + ALOGV("Effect_command: Calling OFFLOAD command"); + return (*pContext->eHandle[SUB_FX_OFFLOAD])->command( + pContext->eHandle[SUB_FX_OFFLOAD], cmdCode, cmdSize, + pCmdData, replySize, pReplyData); + } + *(int*)pReplyData = NO_ERROR; + ALOGV("Effect_command OFFLOAD return 0, replyData %d", + *(int*)pReplyData); + + return NO_ERROR; } int index = pContext->index; @@ -329,11 +363,11 @@ int Effect_getDescriptor(effect_handle_t self, __attribute__ ((visibility ("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { - tag : AUDIO_EFFECT_LIBRARY_TAG, - version : EFFECT_LIBRARY_API_VERSION, - name : "Effect Proxy", - implementor : "AOSP", - create_effect : android::EffectProxyCreate, - release_effect : android::EffectProxyRelease, - get_descriptor : android::EffectProxyGetDescriptor, + .tag = AUDIO_EFFECT_LIBRARY_TAG, + .version = EFFECT_LIBRARY_API_VERSION, + .name = "Effect Proxy", + .implementor = "AOSP", + .create_effect = android::EffectProxyCreate, + .release_effect = android::EffectProxyRelease, + .get_descriptor = android::EffectProxyGetDescriptor, }; diff --git a/media/libeffects/proxy/EffectProxy.h b/media/libeffects/proxy/EffectProxy.h index acbe17e..046b93e 100644 --- a/media/libeffects/proxy/EffectProxy.h +++ b/media/libeffects/proxy/EffectProxy.h @@ -16,6 +16,8 @@ #include <hardware/audio.h> #include <hardware/audio_effect.h> +#include "EffectsFactory.h" + namespace android { enum { SUB_FX_HOST, // Index of HOST in the descriptor and handle arrays @@ -62,7 +64,9 @@ const struct effect_interface_s gEffectInterface = { struct EffectContext { const struct effect_interface_s *common_itfe; // Holds the itfe of the Proxy + sub_effect_entry_t** sube; // Points to the sub effects effect_descriptor_t* desc; // Points to the sub effect descriptors + audio_effect_library_t** aeli; // Points to the sub effect aeli effect_handle_t eHandle[SUB_FX_COUNT]; // The effect handles of the sub effects int index; // The index that is currently active - HOST or OFFLOAD int32_t sessionId; // The sessiond in which the effect is created. diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_ index 2954908..672ebba 100644 --- a/media/libeffects/testlibs/Android.mk_ +++ b/media/libeffects/testlibs/Android.mk_ @@ -11,7 +11,7 @@ LOCAL_CFLAGS+= -O2 LOCAL_SHARED_LIBRARIES := \ libcutils -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libreverbtest ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) @@ -47,7 +47,7 @@ LOCAL_CFLAGS+= -O2 LOCAL_SHARED_LIBRARIES := \ libcutils -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libequalizertest ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk index e196eb2..dd2d306 100644 --- a/media/libeffects/visualizer/Android.mk +++ b/media/libeffects/visualizer/Android.mk @@ -13,7 +13,7 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libdl -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libvisualizer LOCAL_C_INCLUDES := \ diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8033c2c..cc5b810 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -370,8 +370,8 @@ status_t AudioSystem::setVoiceVolume(float value) return af->setVoiceVolume(value); } -status_t AudioSystem::getRenderPosition(audio_io_handle_t output, size_t *halFrames, - size_t *dspFrames, audio_stream_type_t stream) +status_t AudioSystem::getRenderPosition(audio_io_handle_t output, uint32_t *halFrames, + uint32_t *dspFrames, audio_stream_type_t stream) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index fe5cd9e..a9d6993 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -101,7 +101,8 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -109,7 +110,8 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, - 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo); + 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, + offloadInfo, uid); } AudioTrack::AudioTrack( @@ -124,7 +126,8 @@ AudioTrack::AudioTrack( int notificationFrames, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -132,7 +135,7 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, - sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo); + sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, uid); } AudioTrack::~AudioTrack() @@ -169,7 +172,8 @@ status_t AudioTrack::set( bool threadCanCallJava, int sessionId, transfer_type transferType, - const audio_offload_info_t *offloadInfo) + const audio_offload_info_t *offloadInfo, + int uid) { switch (transferType) { case TRANSFER_DEFAULT: @@ -313,6 +317,11 @@ status_t AudioTrack::set( mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; mSessionId = sessionId; + if (uid == -1 || (IPCThreadState::self()->getCallingPid() != getpid())) { + mClientUid = IPCThreadState::self()->getCallingUid(); + } else { + mClientUid = uid; + } mAuxEffectId = 0; mFlags = flags; mCbf = cbf; @@ -594,6 +603,19 @@ uint32_t AudioTrack::getSampleRate() const } AutoMutex lock(mLock); + + // sample rate can be updated during playback by the offloaded decoder so we need to + // query the HAL and update if needed. +// FIXME use Proxy return channel to update the rate from server and avoid polling here + if (isOffloaded()) { + if (mOutput != 0) { + uint32_t sampleRate = 0; + status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate); + if (status == NO_ERROR) { + mSampleRate = sampleRate; + } + } + } return mSampleRate; } @@ -738,7 +760,7 @@ status_t AudioTrack::getPosition(uint32_t *position) const return NO_ERROR; } -status_t AudioTrack::getBufferPosition(size_t *position) +status_t AudioTrack::getBufferPosition(uint32_t *position) { if (mSharedBuffer == 0 || mIsTimed) { return INVALID_OPERATION; @@ -856,8 +878,15 @@ status_t AudioTrack::createTrack_l( } ALOGV("createTrack_l() output %d afLatency %d", output, afLatency); + if ((flags & AUDIO_OUTPUT_FLAG_FAST) && sampleRate != afSampleRate) { + ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client due to mismatching sample rate (%d vs %d)", + sampleRate, afSampleRate); + flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); + } + // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where - // n = 1 fast track; nBuffering is ignored + // n = 1 fast track with single buffering; nBuffering is ignored + // n = 2 fast track with double buffering // n = 2 normal track, no sample rate conversion // n = 3 normal track, with sample rate conversion // (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering) @@ -886,7 +915,7 @@ status_t AudioTrack::createTrack_l( // More than 2 channels does not require stronger alignment than stereo alignment <<= 1; } - if (((size_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { + if (((uintptr_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { ALOGE("Invalid buffer alignment: address %p, channel count %u", sharedBuffer->pointer(), mChannelCount); return BAD_VALUE; @@ -962,6 +991,7 @@ status_t AudioTrack::createTrack_l( tid, &mSessionId, mName, + mClientUid, &status); if (track == 0) { @@ -996,9 +1026,11 @@ status_t AudioTrack::createTrack_l( ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount); mAwaitBoost = true; if (sharedBuffer == 0) { - // double-buffering is not required for fast tracks, due to tighter scheduling - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount) { - mNotificationFramesAct = frameCount; + // Theoretically double-buffering is not required for fast tracks, + // due to tighter scheduling. But in practice, to accommodate kernels with + // scheduling jitter, and apps with computation jitter, we use double-buffering. + if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { + mNotificationFramesAct = frameCount/nBuffering; } } } else { @@ -1212,7 +1244,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { // Sanity-check: user is most-likely passing an error code, and it would // make the return value ambiguous (actualSize vs error). - ALOGE("AudioTrack::write(buffer=%p, size=%u (%d)", buffer, userSize, userSize); + ALOGE("AudioTrack::write(buffer=%p, size=%zu (%zd)", buffer, userSize, userSize); return BAD_VALUE; } @@ -1665,7 +1697,6 @@ status_t AudioTrack::restoreTrack_l(const char *from) // take the frames that will be lost by track recreation into account in saved position size_t position = mProxy->getPosition() + mProxy->getFramesFilled(); - mNewPosition = position + mUpdatePeriod; size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0; result = createTrack_l(mStreamType, mSampleRate, @@ -1756,7 +1787,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]); result.append(buffer); - snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, + snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%zu)\n", mFormat, mChannelCount, mFrameCount); result.append(buffer); snprintf(buffer, 255, " sample rate(%u), status(%d)\n", mSampleRate, mStatus); diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index da73d65..e898109 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -475,9 +475,14 @@ void StaticAudioTrackClientProxy::flush() void StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) { + // This can only happen on a 64-bit client + if (loopStart > UINT32_MAX || loopEnd > UINT32_MAX) { + // FIXME Should return an error status + return; + } StaticAudioTrackState newState; - newState.mLoopStart = loopStart; - newState.mLoopEnd = loopEnd; + newState.mLoopStart = (uint32_t) loopStart; + newState.mLoopEnd = (uint32_t) loopEnd; newState.mLoopCount = loopCount; mBufferPosition = loopStart; (void) mMutator.push(newState); @@ -487,7 +492,7 @@ size_t StaticAudioTrackClientProxy::getBufferPosition() { size_t bufferPosition; if (mMutator.ack()) { - bufferPosition = mCblk->u.mStatic.mBufferPosition; + bufferPosition = (size_t) mCblk->u.mStatic.mBufferPosition; if (bufferPosition > mFrameCount) { bufferPosition = mFrameCount; } @@ -506,7 +511,7 @@ ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCo { } -status_t ServerProxy::obtainBuffer(Buffer* buffer) +status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) { LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); if (mIsShutdown) { @@ -579,7 +584,11 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer) buffer->mRaw = part1 > 0 ? &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL; buffer->mNonContig = availToServer - part1; - mUnreleased = part1; + // After flush(), allow releaseBuffer() on a previously obtained buffer; + // see "Acknowledge any pending flush()" in audioflinger/Tracks.cpp. + if (!ackFlush) { + mUnreleased = part1; + } return part1 > 0 ? NO_ERROR : WOULD_BLOCK; } no_init: @@ -618,7 +627,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) if (half == 0) { half = 1; } - size_t minimum = cblk->mMinimum; + size_t minimum = (size_t) cblk->mMinimum; if (minimum == 0) { minimum = mIsOut ? half : 1; } else if (minimum > half) { @@ -756,12 +765,13 @@ ssize_t StaticAudioTrackServerProxy::pollPosition() mIsShutdown = true; return (ssize_t) NO_INIT; } - mCblk->u.mStatic.mBufferPosition = position; + // This may overflow, but client is not supposed to rely on it + mCblk->u.mStatic.mBufferPosition = (uint32_t) position; } return (ssize_t) position; } -status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer) +status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) { if (mIsShutdown) { buffer->mFrameCount = 0; @@ -832,7 +842,8 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) mPosition = newPosition; cblk->mServer += stepCount; - cblk->u.mStatic.mBufferPosition = newPosition; + // This may overflow, but client is not supposed to rely on it + cblk->u.mStatic.mBufferPosition = (uint32_t) newPosition; if (setFlags != 0) { (void) android_atomic_or(setFlags, &cblk->mFlags); // this would be a good place to wake a futex diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 448a82e..86ff8bd 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -96,6 +96,7 @@ public: pid_t tid, int *sessionId, String8& name, + int clientUid, status_t *status) { Parcel data, reply; @@ -121,6 +122,7 @@ public: lSessionId = *sessionId; } data.writeInt32(lSessionId); + data.writeInt32(clientUid); status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply); if (lStatus != NO_ERROR) { ALOGE("createTrack error: %s", strerror(-lStatus)); @@ -523,7 +525,7 @@ public: return reply.readInt32(); } - virtual status_t getRenderPosition(size_t *halFrames, size_t *dspFrames, + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_io_handle_t output) const { Parcel data, reply; @@ -544,7 +546,7 @@ public: return status; } - virtual size_t getInputFramesLost(audio_io_handle_t ioHandle) const + virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); @@ -762,6 +764,7 @@ status_t BnAudioFlinger::onTransact( audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); + int clientUid = data.readInt32(); String8 name; status_t status; sp<IAudioTrack> track; @@ -773,7 +776,7 @@ status_t BnAudioFlinger::onTransact( track = createTrack( (audio_stream_type_t) streamType, sampleRate, format, channelMask, frameCount, &flags, buffer, output, tid, - &sessionId, name, &status); + &sessionId, name, clientUid, &status); } reply->writeInt32(flags); reply->writeInt32(sessionId); @@ -1010,8 +1013,8 @@ status_t BnAudioFlinger::onTransact( case GET_RENDER_POSITION: { CHECK_INTERFACE(IAudioFlinger, data, reply); audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); - size_t halFrames; - size_t dspFrames; + uint32_t halFrames; + uint32_t dspFrames; status_t status = getRenderPosition(&halFrames, &dspFrames, output); reply->writeInt32(status); if (status == NO_ERROR) { diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp index 6a108ae..f004ca4 100644 --- a/media/libmedia/MemoryLeakTrackUtil.cpp +++ b/media/libmedia/MemoryLeakTrackUtil.cpp @@ -49,7 +49,7 @@ struct MyString8 { } void append(const char *s) { - strcat(mPtr, s); + strncat(mPtr, s, MAX_SIZE - size() - 1); } const char *string() const { @@ -60,6 +60,10 @@ struct MyString8 { return strlen(mPtr); } + void clear() { + *mPtr = '\0'; + } + private: char *mPtr; @@ -139,6 +143,9 @@ void dumpMemoryAddresses(int fd) } } while (moved); + write(fd, result.string(), result.size()); + result.clear(); + for (size_t i = 0; i < count; i++) { AllocEntry *e = &entries[i]; @@ -152,13 +159,14 @@ void dumpMemoryAddresses(int fd) result.append(buffer); } result.append("\n"); + + write(fd, result.string(), result.size()); + result.clear(); } delete[] entries; free_malloc_leak_info(info); } - - write(fd, result.string(), result.size()); } #else diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 9553458..a392b76 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -319,7 +319,7 @@ status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& ar result.append(" AudioCache\n"); if (mHeap != 0) { - snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d)\n", + snprintf(buffer, 255, " heap base(%p), size(%zu), flags(%d)\n", mHeap->getBase(), mHeap->getSize(), mHeap->getFlags()); result.append(buffer); } @@ -590,7 +590,7 @@ sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( } if (!p->hardwareOutput()) { - mAudioOutput = new AudioOutput(mAudioSessionId); + mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid()); static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); } @@ -1296,12 +1296,13 @@ Exit: #undef LOG_TAG #define LOG_TAG "AudioSink" -MediaPlayerService::AudioOutput::AudioOutput(int sessionId) +MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid) : mCallback(NULL), mCallbackCookie(NULL), mCallbackData(NULL), mBytesWritten(0), mSessionId(sessionId), + mUid(uid), mFlags(AUDIO_OUTPUT_FLAG_NONE) { ALOGV("AudioOutput(%d)", sessionId); mStreamType = AUDIO_STREAM_MUSIC; @@ -1549,7 +1550,8 @@ status_t MediaPlayerService::AudioOutput::open( 0, // notification frames mSessionId, AudioTrack::TRANSFER_CALLBACK, - offloadInfo); + offloadInfo, + mUid); } else { t = new AudioTrack( mStreamType, @@ -1558,10 +1560,13 @@ status_t MediaPlayerService::AudioOutput::open( channelMask, frameCount, flags, - NULL, - NULL, - 0, - mSessionId); + NULL, // callback + NULL, // user data + 0, // notification frames + mSessionId, + AudioTrack::TRANSFER_DEFAULT, + NULL, // offload info + mUid); } if ((t == 0) || (t->initCheck() != NO_ERROR)) { @@ -1808,6 +1813,12 @@ int MediaPlayerService::AudioOutput::getSessionId() const return mSessionId; } +uint32_t MediaPlayerService::AudioOutput::getSampleRate() const +{ + if (mTrack == 0) return 0; + return mTrack->getSampleRate(); +} + #undef LOG_TAG #define LOG_TAG "AudioCache" MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) : @@ -2010,6 +2021,14 @@ int MediaPlayerService::AudioCache::getSessionId() const return 0; } +uint32_t MediaPlayerService::AudioCache::getSampleRate() const +{ + if (mMsecsPerFrame == 0) { + return 0; + } + return (uint32_t)(1.e3 / mMsecsPerFrame); +} + void MediaPlayerService::addBatteryData(uint32_t params) { Mutex::Autolock lock(mLock); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 21f4117..9c084e1 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -72,7 +72,7 @@ class MediaPlayerService : public BnMediaPlayerService class CallbackData; public: - AudioOutput(int sessionId); + AudioOutput(int sessionId, int uid); virtual ~AudioOutput(); virtual bool ready() const { return mTrack != 0; } @@ -86,6 +86,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual status_t getPosition(uint32_t *position) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; virtual int getSessionId() const; + virtual uint32_t getSampleRate() const; virtual status_t open( uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, @@ -100,7 +101,10 @@ class MediaPlayerService : public BnMediaPlayerService virtual void flush(); virtual void pause(); virtual void close(); - void setAudioStreamType(audio_stream_type_t streamType) { mStreamType = streamType; } + void setAudioStreamType(audio_stream_type_t streamType) { + mStreamType = streamType; } + virtual audio_stream_type_t getAudioStreamType() const { return mStreamType; } + void setVolume(float left, float right); virtual status_t setPlaybackRatePermille(int32_t ratePermille); status_t setAuxEffectSendLevel(float level); @@ -135,6 +139,7 @@ class MediaPlayerService : public BnMediaPlayerService uint32_t mSampleRateHz; // sample rate of the content, as set in open() float mMsecsPerFrame; int mSessionId; + int mUid; float mSendLevel; int mAuxEffectId; static bool mIsOnEmulator; @@ -191,6 +196,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual status_t getPosition(uint32_t *position) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; virtual int getSessionId() const; + virtual uint32_t getSampleRate() const; virtual status_t open( uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, @@ -206,6 +212,9 @@ class MediaPlayerService : public BnMediaPlayerService virtual void pause() {} virtual void close() {} void setAudioStreamType(audio_stream_type_t streamType) {} + // stream type is not used for AudioCache + virtual audio_stream_type_t getAudioStreamType() const { return AUDIO_STREAM_DEFAULT; } + void setVolume(float left, float right) {} virtual status_t setPlaybackRatePermille(int32_t ratePermille) { return INVALID_OPERATION; } uint32_t sampleRate() const { return mSampleRate; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 095d5ca..4da74e1 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "StagefrightRecorder" +#include <inttypes.h> #include <utils/Log.h> #include "StagefrightRecorder.h" @@ -70,8 +71,9 @@ StagefrightRecorder::StagefrightRecorder() mOutputFd(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), - mStarted(false), mSurfaceMediaSource(NULL), - mCaptureTimeLapse(false) { + mCaptureTimeLapse(false), + mStarted(false), + mSurfaceMediaSource(NULL) { ALOGV("Constructor"); reset(); @@ -1089,7 +1091,22 @@ void StagefrightRecorder::clipVideoFrameWidth() { } } -status_t StagefrightRecorder::checkVideoEncoderCapabilities() { +status_t StagefrightRecorder::checkVideoEncoderCapabilities( + bool *supportsCameraSourceMetaDataMode) { + /* hardware codecs must support camera source meta data mode */ + Vector<CodecCapabilities> codecs; + OMXClient client; + CHECK_EQ(client.connect(), (status_t)OK); + QueryCodecs( + client.interface(), + (mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 : + mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 : + mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""), + false /* decoder */, true /* hwCodec */, &codecs); + *supportsCameraSourceMetaDataMode = codecs.size() > 0; + ALOGV("encoder %s camera source meta-data mode", + *supportsCameraSourceMetaDataMode ? "supports" : "DOES NOT SUPPORT"); + if (!mCaptureTimeLapse) { // Dont clip for time lapse capture as encoder will have enough // time to encode because of slow capture rate of time lapse. @@ -1307,7 +1324,9 @@ status_t StagefrightRecorder::setupSurfaceMediaSource() { status_t StagefrightRecorder::setupCameraSource( sp<CameraSource> *cameraSource) { status_t err = OK; - if ((err = checkVideoEncoderCapabilities()) != OK) { + bool encoderSupportsCameraSourceMetaDataMode; + if ((err = checkVideoEncoderCapabilities( + &encoderSupportsCameraSourceMetaDataMode)) != OK) { return err; } Size videoSize; @@ -1323,13 +1342,14 @@ status_t StagefrightRecorder::setupCameraSource( mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera( mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, videoSize, mFrameRate, mPreviewSurface, - mTimeBetweenTimeLapseFrameCaptureUs); + mTimeBetweenTimeLapseFrameCaptureUs, + encoderSupportsCameraSourceMetaDataMode); *cameraSource = mCameraSourceTimeLapse; } else { *cameraSource = CameraSource::CreateFromCamera( mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, videoSize, mFrameRate, - mPreviewSurface, true /*storeMetaDataInVideoBuffers*/); + mPreviewSurface, encoderSupportsCameraSourceMetaDataMode); } mCamera.clear(); mCameraProxy.clear(); @@ -1728,15 +1748,15 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat); result.append(buffer); - snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes); + snprintf(buffer, SIZE, " Max file size (bytes): %" PRId64 "\n", mMaxFileSizeBytes); result.append(buffer); - snprintf(buffer, SIZE, " Max file duration (us): %lld\n", mMaxFileDurationUs); + snprintf(buffer, SIZE, " Max file duration (us): %" PRId64 "\n", mMaxFileDurationUs); result.append(buffer); snprintf(buffer, SIZE, " File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32); result.append(buffer); snprintf(buffer, SIZE, " Interleave duration (us): %d\n", mInterleaveDurationUs); result.append(buffer); - snprintf(buffer, SIZE, " Progress notification: %lld us\n", mTrackEveryTimeDurationUs); + snprintf(buffer, SIZE, " Progress notification: %" PRId64 " us\n", mTrackEveryTimeDurationUs); result.append(buffer); snprintf(buffer, SIZE, " Audio\n"); result.append(buffer); diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index c864207..31f09e0 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -139,7 +139,8 @@ private: status_t startRTPRecording(); status_t startMPEG2TSRecording(); sp<MediaSource> createAudioSource(); - status_t checkVideoEncoderCapabilities(); + status_t checkVideoEncoderCapabilities( + bool *supportsCameraSourceMetaDataMode); status_t checkAudioEncoderCapabilities(); // Generic MediaSource set-up. Returns the appropriate // source (CameraSource or SurfaceMediaSource) diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index d8b35d7..f1782cc 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -201,7 +201,16 @@ void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) { switch (what) { case LiveSession::kWhatPrepared: { - notifyVideoSizeChanged(0, 0); + // notify the current size here if we have it, otherwise report an initial size of (0,0) + sp<AMessage> format = getFormat(false /* audio */); + int32_t width; + int32_t height; + if (format != NULL && + format->findInt32("width", &width) && format->findInt32("height", &height)) { + notifyVideoSizeChanged(width, height); + } else { + notifyVideoSizeChanged(0, 0); + } uint32_t flags = FLAG_CAN_PAUSE; if (mLiveSession->isSeekable()) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 750287f..3669a5b 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -32,6 +32,8 @@ #include "ATSParser.h" +#include "SoftwareRenderer.h" + #include <cutils/properties.h> // for property_get #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/foundation/ABuffer.h> @@ -146,6 +148,7 @@ NuPlayer::NuPlayer() : mUIDValid(false), mSourceFlags(0), mVideoIsAVC(false), + mNeedsSwRenderer(false), mAudioEOS(false), mVideoEOS(false), mScanSourcesPending(false), @@ -444,6 +447,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { ALOGV("kWhatStart"); mVideoIsAVC = false; + mNeedsSwRenderer = false; mAudioEOS = false; mVideoEOS = false; mSkipRenderingAudioUntilMediaTimeUs = -1; @@ -680,6 +684,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { notifyListener( MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight); + + if (mNeedsSwRenderer && mNativeWindow != NULL) { + int32_t colorFormat; + CHECK(codecRequest->findInt32("color-format", &colorFormat)); + + sp<MetaData> meta = new MetaData; + meta->setInt32(kKeyWidth, width); + meta->setInt32(kKeyHeight, height); + meta->setRect(kKeyCropRect, cropLeft, cropTop, cropRight, cropBottom); + meta->setInt32(kKeyColorFormat, colorFormat); + + mRenderer->setSoftRenderer( + new SoftwareRenderer(mNativeWindow->getNativeWindow(), meta)); + } } } else if (what == ACodec::kWhatShutdownCompleted) { ALOGV("%s shutdown completed", audio ? "audio" : "video"); @@ -703,8 +721,13 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mRenderer->queueEOS(audio, UNKNOWN_ERROR); } else if (what == ACodec::kWhatDrainThisBuffer) { renderBuffer(audio, codecRequest); - } else if (what != ACodec::kWhatComponentAllocated - && what != ACodec::kWhatComponentConfigured + } else if (what == ACodec::kWhatComponentAllocated) { + if (!audio) { + AString name; + CHECK(codecRequest->findString("componentName", &name)); + mNeedsSwRenderer = name.startsWith("OMX.google."); + } + } else if (what != ACodec::kWhatComponentConfigured && what != ACodec::kWhatBuffersAllocated) { ALOGV("Unhandled codec notification %d '%c%c%c%c'.", what, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 13350f3..590e1f2 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -116,6 +116,7 @@ private: sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; bool mVideoIsAVC; + bool mNeedsSwRenderer; sp<Decoder> mAudioDecoder; sp<Renderer> mRenderer; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 47834fd..239296e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "NuPlayerDriver" +#include <inttypes.h> #include <utils/Log.h> #include "NuPlayerDriver.h" @@ -499,7 +500,7 @@ status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const { FILE *out = fdopen(dup(fd), "w"); fprintf(out, " NuPlayer\n"); - fprintf(out, " numFramesTotal(%lld), numFramesDropped(%lld), " + fprintf(out, " numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), " "percentageDropped(%.2f)\n", mNumFramesTotal, mNumFramesDropped, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 3b2784b..bf5271e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -20,6 +20,8 @@ #include "NuPlayerRenderer.h" +#include "SoftwareRenderer.h" + #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> @@ -34,6 +36,7 @@ NuPlayer::Renderer::Renderer( const sp<AMessage> ¬ify, uint32_t flags) : mAudioSink(sink), + mSoftRenderer(NULL), mNotify(notify), mFlags(flags), mNumFramesWritten(0), @@ -57,6 +60,12 @@ NuPlayer::Renderer::Renderer( } NuPlayer::Renderer::~Renderer() { + delete mSoftRenderer; +} + +void NuPlayer::Renderer::setSoftRenderer(SoftwareRenderer *softRenderer) { + delete mSoftRenderer; + mSoftRenderer = softRenderer; } void NuPlayer::Renderer::queueBuffer( @@ -413,7 +422,12 @@ void NuPlayer::Renderer::onDrainVideoQueue() { ALOGV("video late by %lld us (%.2f secs)", mVideoLateByUs, mVideoLateByUs / 1E6); } else { - ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6); + ALOGV("rendering video at media time %.2f secs", + (mFlags & FLAG_REAL_TIME ? realTimeUs : + (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6); + if (mSoftRenderer != NULL) { + mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL); + } } entry->mNotifyConsumed->setInt32("render", !tooLate); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 94a05ea..9124e03 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -23,6 +23,7 @@ namespace android { struct ABuffer; +class SoftwareRenderer; struct NuPlayer::Renderer : public AHandler { enum Flags { @@ -56,6 +57,8 @@ struct NuPlayer::Renderer : public AHandler { kWhatMediaRenderingStart = 'mdrd', }; + void setSoftRenderer(SoftwareRenderer *softRenderer); + protected: virtual ~Renderer(); @@ -83,6 +86,7 @@ private: static const int64_t kMinPositionUpdateDelayUs; sp<MediaPlayerBase::AudioSink> mAudioSink; + SoftwareRenderer *mSoftRenderer; sp<AMessage> mNotify; uint32_t mFlags; List<QueueEntry> mAudioQueue; diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp index d31d947..2aae4dd 100644 --- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp +++ b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp @@ -86,7 +86,7 @@ struct StreamSource : public FragmentedMP4Parser::Source { total += n; } - ALOGV("read %ld bytes at offset %lld", n, mPosition); + ALOGV("read %ld bytes at offset %lld", total, mPosition); mPosition += total; diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp index de0ad28..3c61b60 100644 --- a/media/libnbaio/MonoPipe.cpp +++ b/media/libnbaio/MonoPipe.cpp @@ -183,7 +183,7 @@ ssize_t MonoPipe::write(const void *buffer, size_t count) } } if (ns > 0) { - const struct timespec req = {0, ns}; + const struct timespec req = {0, static_cast<long>(ns)}; nanosleep(&req, NULL); } // record the time that this write() completed diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp index 045bf64..d74a7a6 100644 --- a/media/libnbaio/NBLog.cpp +++ b/media/libnbaio/NBLog.cpp @@ -340,7 +340,7 @@ void NBLog::Reader::dump(int fd, size_t indent) if (i > 0) { lost += i; if (fd >= 0) { - fdprintf(fd, "%*swarning: lost %u bytes worth of events\n", indent, "", lost); + fdprintf(fd, "%*swarning: lost %zu bytes worth of events\n", indent, "", lost); } else { ALOGI("%*swarning: lost %u bytes worth of events\n", indent, "", lost); } diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp index a6f7cfb..c9bcaba 100644 --- a/media/libstagefright/AACWriter.cpp +++ b/media/libstagefright/AACWriter.cpp @@ -171,7 +171,7 @@ status_t AACWriter::reset() { void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); { status_t status = mSource->stop(); if (err == OK && @@ -200,7 +200,7 @@ bool AACWriter::exceedsFileDurationLimit() { // static void *AACWriter::ThreadWrapper(void *me) { - return (void *) static_cast<AACWriter *>(me)->threadFunc(); + return (void *)(uintptr_t)static_cast<AACWriter *>(me)->threadFunc(); } /* diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 1adab38..76a3358 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -1909,6 +1909,11 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { err = setupAVCEncoderParameters(msg); break; + case OMX_VIDEO_CodingVP8: + case OMX_VIDEO_CodingVP9: + err = setupVPXEncoderParameters(msg); + break; + default: break; } @@ -2240,6 +2245,17 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { return configureBitrate(bitrate, bitrateMode); } +status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { + int32_t bitrate; + if (!msg->findInt32("bitrate", &bitrate)) { + return INVALID_OPERATION; + } + + OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); + + return configureBitrate(bitrate, bitrateMode); +} + status_t ACodec::verifySupportForProfileAndLevel( int32_t profile, int32_t level) { OMX_VIDEO_PARAM_PROFILELEVELTYPE params; @@ -3072,11 +3088,16 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { /* these are unfilled buffers returned by client */ CHECK(msg->findInt32("err", &err)); - ALOGV("[%s] saw error %d instead of an input buffer", - mCodec->mComponentName.c_str(), err); + if (err == OK) { + /* buffers with no errors are returned on MediaCodec.flush */ + mode = KEEP_BUFFERS; + } else { + ALOGV("[%s] saw error %d instead of an input buffer", + mCodec->mComponentName.c_str(), err); + eos = true; + } buffer.clear(); - mode = KEEP_BUFFERS; } int32_t tmp; @@ -3394,7 +3415,7 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { int32_t render; if (mCodec->mNativeWindow != NULL && msg->findInt32("render", &render) && render != 0 - && (info->mData == NULL || info->mData->size() != 0)) { + && info->mData != NULL && info->mData->size() != 0) { // The client wants this buffer to be rendered. status_t err; diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index 8d5eec8..3fe247a 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -162,7 +162,7 @@ status_t AMRWriter::reset() { void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); { status_t status = mSource->stop(); if (err == OK && @@ -191,7 +191,7 @@ bool AMRWriter::exceedsFileDurationLimit() { // static void *AMRWriter::ThreadWrapper(void *me) { - return (void *) static_cast<AMRWriter *>(me)->threadFunc(); + return (void *)(uintptr_t) static_cast<AMRWriter *>(me)->threadFunc(); } status_t AMRWriter::threadFunc() { diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index a8a8786..05ee34e 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -721,16 +721,27 @@ int64_t AudioPlayer::getRealTimeUsLocked() const { return result + diffUs; } -int64_t AudioPlayer::getOutputPlayPositionUs_l() const +int64_t AudioPlayer::getOutputPlayPositionUs_l() { uint32_t playedSamples = 0; + uint32_t sampleRate; if (mAudioSink != NULL) { mAudioSink->getPosition(&playedSamples); + sampleRate = mAudioSink->getSampleRate(); } else { mAudioTrack->getPosition(&playedSamples); + sampleRate = mAudioTrack->getSampleRate(); + } + if (sampleRate != 0) { + mSampleRate = sampleRate; } - const int64_t playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate; + int64_t playedUs; + if (mSampleRate != 0) { + playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate; + } else { + playedUs = 0; + } // HAL position is relative to the first buffer we sent at mStartPosUs const int64_t renderedDuration = mStartPosUs + playedUs; diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index bdd842f..f0d1a14 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -236,10 +236,10 @@ status_t AudioSource::read( memset((uint8_t *) buffer->data(), 0, buffer->range_length()); } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) { int32_t autoRampDurationFrames = - (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; + ((int64_t)kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; //Need type casting int32_t autoRampStartFrames = - (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; + ((int64_t)kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; //Need type casting int32_t nFrames = mNumFramesReceived - autoRampStartFrames; rampVolume(nFrames, autoRampDurationFrames, @@ -308,7 +308,7 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { if (numLostBytes > 0) { // Loss of audio frames should happen rarely; thus the LOGW should // not cause a logging spam - ALOGW("Lost audio record data: %d bytes", numLostBytes); + ALOGW("Lost audio record data: %zu bytes", numLostBytes); } while (numLostBytes > 0) { diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index c912f75..29c007a 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -19,6 +19,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AwesomePlayer" #define ATRACE_TAG ATRACE_TAG_VIDEO +#include <inttypes.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -606,6 +607,9 @@ void AwesomePlayer::reset_l() { mWatchForAudioSeekComplete = false; mWatchForAudioEOS = false; + + mMediaRenderingStartGeneration = 0; + mStartGeneration = 0; } void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { @@ -722,7 +726,7 @@ void AwesomePlayer::onBufferingUpdate() { if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < kLowWaterMarkBytes)) { - ALOGI("cache is running low (< %d) , pausing.", + ALOGI("cache is running low (< %zu) , pausing.", kLowWaterMarkBytes); modifyFlags(CACHE_UNDERRUN, SET); pause_l(); @@ -731,12 +735,12 @@ void AwesomePlayer::onBufferingUpdate() { notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { if (mFlags & CACHE_UNDERRUN) { - ALOGI("cache has filled up (> %d), resuming.", + ALOGI("cache has filled up (> %zu), resuming.", kHighWaterMarkBytes); modifyFlags(CACHE_UNDERRUN, CLEAR); play_l(); } else if (mFlags & PREPARING) { - ALOGV("cache has filled up (> %d), prepare is done", + ALOGV("cache has filled up (> %zu), prepare is done", kHighWaterMarkBytes); finishAsyncPrepare_l(); } @@ -798,7 +802,7 @@ void AwesomePlayer::onBufferingUpdate() { } } - if (mFlags & (PLAYING | PREPARING)) { + if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) { postBufferingEvent_l(); } } @@ -895,6 +899,8 @@ status_t AwesomePlayer::play_l() { return OK; } + mMediaRenderingStartGeneration = ++mStartGeneration; + if (!(mFlags & PREPARED)) { status_t err = prepare_l(); @@ -1197,8 +1203,7 @@ void AwesomePlayer::initRenderer_l() { setVideoScalingMode_l(mVideoScalingMode); if (USE_SURFACE_ALLOC && !strncmp(component, "OMX.", 4) - && strncmp(component, "OMX.google.", 11) - && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) { + && strncmp(component, "OMX.google.", 11)) { // Hardware decoders avoid the CPU color conversion by decoding // directly to ANativeBuffers, so we must use a renderer that // just pushes those buffers to the ANativeWindow. @@ -1495,7 +1500,13 @@ status_t AwesomePlayer::initAudioDecoder() { // This doesn't guarantee that the hardware has a free stream // but it avoids us attempting to open (and re-open) an offload // stream to hardware that doesn't have the necessary codec - mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), isStreamingHTTP()); + audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; + if (mAudioSink != NULL) { + streamType = mAudioSink->getAudioStreamType(); + } + + mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), + isStreamingHTTP(), streamType); if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { ALOGV("createAudioPlayer: bypass OMX (raw)"); @@ -1927,7 +1938,7 @@ void AwesomePlayer::onVideoEvent() { ++mStats.mNumVideoFramesDropped; } - postVideoEvent_l(); + postVideoEvent_l(0); return; } } @@ -1967,6 +1978,41 @@ void AwesomePlayer::onVideoEvent() { return; } + /* get next frame time */ + if (wasSeeking == NO_SEEK) { + MediaSource::ReadOptions options; + for (;;) { + status_t err = mVideoSource->read(&mVideoBuffer, &options); + if (err != OK) { + // deal with any errors next time + CHECK(mVideoBuffer == NULL); + postVideoEvent_l(0); + return; + } + + if (mVideoBuffer->range_length() != 0) { + break; + } + + // Some decoders, notably the PV AVC software decoder + // return spurious empty buffers that we just want to ignore. + + mVideoBuffer->release(); + mVideoBuffer = NULL; + } + + { + Mutex::Autolock autoLock(mStatsLock); + ++mStats.mNumVideoFramesDecoded; + } + + int64_t nextTimeUs; + CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); + int64_t delayUs = nextTimeUs - ts->getRealTimeUs() + mTimeSourceDeltaUs; + postVideoEvent_l(delayUs > 10000 ? 10000 : delayUs < 0 ? 0 : delayUs); + return; + } + postVideoEvent_l(); } @@ -2051,7 +2097,10 @@ void AwesomePlayer::onCheckAudioStatus() { mSeekNotificationSent = true; } - mSeeking = NO_SEEK; + if (mVideoSource == NULL) { + // For video the mSeeking flag is always reset in finishSeekIfNecessary + mSeeking = NO_SEEK; + } notifyIfMediaStarted_l(); } @@ -2247,8 +2296,8 @@ status_t AwesomePlayer::finishSetDataSource_l() { sniffedMIME = tmp.string(); if (meta == NULL - || !meta->findInt64( - "meta-data-size", &metaDataSize)) { + || !meta->findInt64("meta-data-size", + reinterpret_cast<int64_t*>(&metaDataSize))) { metaDataSize = kHighWaterMarkBytes; } @@ -2535,12 +2584,12 @@ status_t AwesomePlayer::getTrackInfo(Parcel *reply) const { status_t AwesomePlayer::selectAudioTrack_l( const sp<MediaSource>& source, size_t trackIndex) { - ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags); + ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags); { Mutex::Autolock autoLock(mStatsLock); if ((ssize_t)trackIndex == mActiveAudioTrackIndex) { - ALOGI("Track %d is active. Does nothing.", trackIndex); + ALOGI("Track %zu is active. Does nothing.", trackIndex); return OK; } //mStats.mFlags = mFlags; @@ -2613,7 +2662,7 @@ status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { trackCount += mTextDriver->countExternalTracks(); } if (trackIndex >= trackCount) { - ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount); + ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount); return ERROR_OUT_OF_RANGE; } @@ -2625,14 +2674,14 @@ status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { isAudioTrack = !strncasecmp(mime, "audio/", 6); if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) { - ALOGE("Track %d is not either audio or timed text", trackIndex); + ALOGE("Track %zu is not either audio or timed text", trackIndex); return ERROR_UNSUPPORTED; } } if (isAudioTrack) { if (!select) { - ALOGE("Deselect an audio track (%d) is not supported", trackIndex); + ALOGE("Deselect an audio track (%zu) is not supported", trackIndex); return ERROR_UNSUPPORTED; } return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex); @@ -2770,7 +2819,7 @@ status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { fprintf(out, ", flags(0x%08x)", mStats.mFlags); if (mStats.mBitrate >= 0) { - fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate); + fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate); } fprintf(out, "\n"); @@ -2778,7 +2827,7 @@ status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { for (size_t i = 0; i < mStats.mTracks.size(); ++i) { const TrackStat &stat = mStats.mTracks.itemAt(i); - fprintf(out, " Track %d\n", i + 1); + fprintf(out, " Track %zu\n", i + 1); fprintf(out, " MIME(%s)", stat.mMIME.string()); if (!stat.mDecoderName.isEmpty()) { @@ -2790,8 +2839,8 @@ status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { if ((ssize_t)i == mStats.mVideoTrackIndex) { fprintf(out, " videoDimensions(%d x %d), " - "numVideoFramesDecoded(%lld), " - "numVideoFramesDropped(%lld)\n", + "numVideoFramesDecoded(%" PRId64 "), " + "numVideoFramesDropped(%" PRId64 ")\n", mStats.mVideoWidth, mStats.mVideoHeight, mStats.mNumVideoFramesDecoded, diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index 20214e8..5772316 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -41,13 +41,15 @@ CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera( Size videoSize, int32_t videoFrameRate, const sp<IGraphicBufferProducer>& surface, - int64_t timeBetweenFrameCaptureUs) { + int64_t timeBetweenFrameCaptureUs, + bool storeMetaDataInVideoBuffers) { CameraSourceTimeLapse *source = new CameraSourceTimeLapse(camera, proxy, cameraId, clientName, clientUid, videoSize, videoFrameRate, surface, - timeBetweenFrameCaptureUs); + timeBetweenFrameCaptureUs, + storeMetaDataInVideoBuffers); if (source != NULL) { if (source->initCheck() != OK) { @@ -67,9 +69,11 @@ CameraSourceTimeLapse::CameraSourceTimeLapse( Size videoSize, int32_t videoFrameRate, const sp<IGraphicBufferProducer>& surface, - int64_t timeBetweenFrameCaptureUs) + int64_t timeBetweenFrameCaptureUs, + bool storeMetaDataInVideoBuffers) : CameraSource(camera, proxy, cameraId, clientName, clientUid, - videoSize, videoFrameRate, surface, true), + videoSize, videoFrameRate, surface, + storeMetaDataInVideoBuffers), mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate), mLastTimeLapseFrameRealTimestampUs(0), mSkipCurrentFrame(false) { diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index fc6fd9c..97987e2 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -107,6 +107,7 @@ status_t DataSource::getSize(off64_t *size) { Mutex DataSource::gSnifferMutex; List<DataSource::SnifferFunc> DataSource::gSniffers; +bool DataSource::gSniffersRegistered = false; bool DataSource::sniff( String8 *mimeType, float *confidence, sp<AMessage> *meta) { @@ -114,7 +115,13 @@ bool DataSource::sniff( *confidence = 0.0f; meta->clear(); - Mutex::Autolock autoLock(gSnifferMutex); + { + Mutex::Autolock autoLock(gSnifferMutex); + if (!gSniffersRegistered) { + return false; + } + } + for (List<SnifferFunc>::iterator it = gSniffers.begin(); it != gSniffers.end(); ++it) { String8 newMimeType; @@ -133,9 +140,7 @@ bool DataSource::sniff( } // static -void DataSource::RegisterSniffer(SnifferFunc func) { - Mutex::Autolock autoLock(gSnifferMutex); - +void DataSource::RegisterSniffer_l(SnifferFunc func) { for (List<SnifferFunc>::iterator it = gSniffers.begin(); it != gSniffers.end(); ++it) { if (*it == func) { @@ -148,23 +153,29 @@ void DataSource::RegisterSniffer(SnifferFunc func) { // static void DataSource::RegisterDefaultSniffers() { - RegisterSniffer(SniffMPEG4); - RegisterSniffer(SniffMatroska); - RegisterSniffer(SniffOgg); - RegisterSniffer(SniffWAV); - RegisterSniffer(SniffFLAC); - RegisterSniffer(SniffAMR); - RegisterSniffer(SniffMPEG2TS); - RegisterSniffer(SniffMP3); - RegisterSniffer(SniffAAC); - RegisterSniffer(SniffMPEG2PS); - RegisterSniffer(SniffWVM); + Mutex::Autolock autoLock(gSnifferMutex); + if (gSniffersRegistered) { + return; + } + + RegisterSniffer_l(SniffMPEG4); + RegisterSniffer_l(SniffMatroska); + RegisterSniffer_l(SniffOgg); + RegisterSniffer_l(SniffWAV); + RegisterSniffer_l(SniffFLAC); + RegisterSniffer_l(SniffAMR); + RegisterSniffer_l(SniffMPEG2TS); + RegisterSniffer_l(SniffMP3); + RegisterSniffer_l(SniffAAC); + RegisterSniffer_l(SniffMPEG2PS); + RegisterSniffer_l(SniffWVM); char value[PROPERTY_VALUE_MAX]; if (property_get("drm.service.enabled", value, NULL) && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { - RegisterSniffer(SniffDRM); + RegisterSniffer_l(SniffDRM); } + gSniffersRegistered = true; } // static diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index cbc169b..6a33ce6 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -39,6 +39,7 @@ #include <utils/String8.h> #include <byteswap.h> +#include "include/ID3.h" namespace android { @@ -259,7 +260,7 @@ static void hexdump(const void *_data, size_t size) { const uint8_t *data = (const uint8_t *)_data; size_t offset = 0; while (offset < size) { - printf("0x%04x ", offset); + printf("0x%04zx ", offset); size_t n = size - offset; if (n > 16) { @@ -682,8 +683,9 @@ status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { } sinf->len = dataLen - 3; sinf->IPMPData = new char[sinf->len]; + data_offset += 2; - if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) { + if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) { return ERROR_IO; } data_offset += sinf->len; @@ -962,6 +964,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); int64_t paddingus = duration - (segment_duration + media_time); + if (paddingus < 0) { + // track duration from media header (which is what kKeyDuration is) might + // be slightly shorter than the segment duration, which would make the + // padding negative. Clamp to zero. + paddingus = 0; + } int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); } @@ -1379,19 +1387,33 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { } else { // No size was specified. Pick a conservatively large size. int32_t width, height; - if (mLastTrack->meta->findInt32(kKeyWidth, &width) && - mLastTrack->meta->findInt32(kKeyHeight, &height)) { - mLastTrack->meta->setInt32(kKeyMaxInputSize, width * height * 3 / 2); - } else { + if (!mLastTrack->meta->findInt32(kKeyWidth, &width) || + !mLastTrack->meta->findInt32(kKeyHeight, &height)) { ALOGE("No width or height, assuming worst case 1080p"); - mLastTrack->meta->setInt32(kKeyMaxInputSize, 3110400); + width = 1920; + height = 1080; + } + + const char *mime; + CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); + if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { + // AVC requires compression ratio of at least 2, and uses + // macroblocks + max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192; + } else { + // For all other formats there is no minimum compression + // ratio. Use compression ratio of 1. + max_size = width * height * 3 / 2; } + mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size); } *offset += chunk_size; - // Calculate average frame rate. + // NOTE: setting another piece of metadata invalidates any pointers (such as the + // mimetype) previously obtained, so don't cache them. const char *mime; CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); + // Calculate average frame rate. if (!strncasecmp("video/", mime, 6)) { size_t nSamples = mLastTrack->sampleTable->countSamples(); int64_t durationUs; @@ -1766,6 +1788,18 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { break; } + case FOURCC('I', 'D', '3', '2'): + { + if (chunk_data_size < 6) { + return ERROR_MALFORMED; + } + + parseID3v2MetaData(data_offset + 6); + + *offset += chunk_size; + break; + } + case FOURCC('-', '-', '-', '-'): { mLastCommentMean.clear(); @@ -2146,7 +2180,7 @@ status_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) { break; } - if (size >= 8 && metadataKey) { + if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) { if (metadataKey == kKeyAlbumArt) { mFileMetaData->setData( kKeyAlbumArt, MetaData::TYPE_NONE, @@ -2295,6 +2329,62 @@ status_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int dept return OK; } +void MPEG4Extractor::parseID3v2MetaData(off64_t offset) { + ID3 id3(mDataSource, true /* ignorev1 */, offset); + + if (id3.isValid()) { + struct Map { + int key; + const char *tag1; + const char *tag2; + }; + static const Map kMap[] = { + { kKeyAlbum, "TALB", "TAL" }, + { kKeyArtist, "TPE1", "TP1" }, + { kKeyAlbumArtist, "TPE2", "TP2" }, + { kKeyComposer, "TCOM", "TCM" }, + { kKeyGenre, "TCON", "TCO" }, + { kKeyTitle, "TIT2", "TT2" }, + { kKeyYear, "TYE", "TYER" }, + { kKeyAuthor, "TXT", "TEXT" }, + { kKeyCDTrackNumber, "TRK", "TRCK" }, + { kKeyDiscNumber, "TPA", "TPOS" }, + { kKeyCompilation, "TCP", "TCMP" }, + }; + static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); + + for (size_t i = 0; i < kNumMapEntries; ++i) { + if (!mFileMetaData->hasData(kMap[i].key)) { + ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1); + if (it->done()) { + delete it; + it = new ID3::Iterator(id3, kMap[i].tag2); + } + + if (it->done()) { + delete it; + continue; + } + + String8 s; + it->getString(&s); + delete it; + + mFileMetaData->setCString(kMap[i].key, s); + } + } + + size_t dataSize; + String8 mime; + const void *data = id3.getAlbumArt(&dataSize, &mime); + + if (data) { + mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize); + mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string()); + } + } +} + sp<MediaSource> MPEG4Extractor::getTrack(size_t index) { status_t err; if ((err = readMetaData()) != OK) { @@ -2398,6 +2488,11 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( return ERROR_MALFORMED; } + static uint32_t kSamplingRate[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350 + }; + ABitReader br(csd, csd_size); uint32_t objectType = br.getBits(5); @@ -2405,6 +2500,9 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( objectType = 32 + br.getBits(6); } + //keep AOT type + mLastTrack->meta->setInt32(kKeyAACAOT, objectType); + uint32_t freqIndex = br.getBits(4); int32_t sampleRate = 0; @@ -2417,29 +2515,30 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( numChannels = br.getBits(4); } else { numChannels = br.getBits(4); - if (objectType == 5) { - // SBR specific config per 14496-3 table 1.13 - freqIndex = br.getBits(4); - if (freqIndex == 15) { - if (csd_size < 8) { - return ERROR_MALFORMED; - } - sampleRate = br.getBits(24); - } + + if (freqIndex == 13 || freqIndex == 14) { + return ERROR_MALFORMED; } - if (sampleRate == 0) { - static uint32_t kSamplingRate[] = { - 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, 7350 - }; + sampleRate = kSamplingRate[freqIndex]; + } - if (freqIndex == 13 || freqIndex == 14) { + if (objectType == 5 || objectType == 29) { // SBR specific config per 14496-3 table 1.13 + uint32_t extFreqIndex = br.getBits(4); + int32_t extSampleRate; + if (extFreqIndex == 15) { + if (csd_size < 8) { return ERROR_MALFORMED; } - - sampleRate = kSamplingRate[freqIndex]; + extSampleRate = br.getBits(24); + } else { + if (extFreqIndex == 13 || extFreqIndex == 14) { + return ERROR_MALFORMED; + } + extSampleRate = kSamplingRate[extFreqIndex]; } + //TODO: save the extension sampling rate value in meta data => + // mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate); } if (numChannels == 0) { diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index a0f17b5..e7d3cc2 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MPEG4Writer" +#include <inttypes.h> #include <utils/Log.h> #include <arpa/inet.h> @@ -417,7 +418,7 @@ status_t MPEG4Writer::Track::dump( result.append(buffer); snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); result.append(buffer); - snprintf(buffer, SIZE, " duration encoded : %lld us\n", mTrackDurationUs); + snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); result.append(buffer); ::write(fd, result.string(), result.size()); return OK; @@ -1404,7 +1405,7 @@ void MPEG4Writer::Track::addOneSttsTableEntry( size_t sampleCount, int32_t duration) { if (duration == 0) { - ALOGW("0-duration samples found: %d", sampleCount); + ALOGW("0-duration samples found: %zu", sampleCount); } mSttsTableEntries->add(htonl(sampleCount)); mSttsTableEntries->add(htonl(duration)); @@ -1584,7 +1585,7 @@ void MPEG4Writer::writeAllChunks() { sendSessionSummary(); mChunkInfos.clear(); - ALOGD("%d chunks are written in the last batch", outstandingChunks); + ALOGD("%zu chunks are written in the last batch", outstandingChunks); } bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { @@ -1774,7 +1775,7 @@ status_t MPEG4Writer::Track::stop() { void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); { @@ -1797,7 +1798,7 @@ void *MPEG4Writer::Track::ThreadWrapper(void *me) { Track *track = static_cast<Track *>(me); status_t err = track->threadEntry(); - return (void *) err; + return (void *)(uintptr_t)err; } static void getNalUnitType(uint8_t byte, uint8_t* type) { @@ -1869,7 +1870,7 @@ status_t MPEG4Writer::Track::copyAVCCodecSpecificData( // 2 bytes for each of the parameter set length field // plus the 7 bytes for the header if (size < 4 + 7) { - ALOGE("Codec specific data length too short: %d", size); + ALOGE("Codec specific data length too short: %zu", size); return ERROR_MALFORMED; } @@ -1938,7 +1939,7 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData( } if (nSeqParamSets > 0x1F) { - ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); + ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); return ERROR_MALFORMED; } } @@ -1951,7 +1952,7 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData( return ERROR_MALFORMED; } if (nPicParamSets > 0xFF) { - ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); + ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); return ERROR_MALFORMED; } } @@ -1981,7 +1982,7 @@ status_t MPEG4Writer::Track::makeAVCCodecSpecificData( } if (size < 4) { - ALOGE("Codec specific data length too short: %d", size); + ALOGE("Codec specific data length too short: %zu", size); return ERROR_MALFORMED; } diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index e299caf..c4c47b3 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -1506,7 +1506,8 @@ void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { info->mOwnedByClient = false; if (portIndex == kPortIndexInput) { - msg->setInt32("err", ERROR_END_OF_STREAM); + /* no error, just returning buffers */ + msg->setInt32("err", OK); } msg->post(); } @@ -1679,7 +1680,7 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { return -EACCES; } - if (render && (info->mData == NULL || info->mData->size() != 0)) { + if (render && info->mData != NULL && info->mData->size() != 0) { info->mNotify->setInt32("render", true); if (mSoftRenderer != NULL) { diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp index ae6ae2d..74234a6 100644 --- a/media/libstagefright/MetaData.cpp +++ b/media/libstagefright/MetaData.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MetaData" +#include <inttypes.h> #include <utils/Log.h> #include <stdlib.h> @@ -89,6 +90,9 @@ bool MetaData::setRect( return setData(key, TYPE_RECT, &r, sizeof(r)); } +/** + * Note that the returned pointer becomes invalid when additional metadata is set. + */ bool MetaData::findCString(uint32_t key, const char **value) { uint32_t type; const void *data; @@ -218,6 +222,16 @@ bool MetaData::findData(uint32_t key, uint32_t *type, return true; } +bool MetaData::hasData(uint32_t key) const { + ssize_t i = mItems.indexOfKey(key); + + if (i < 0) { + return false; + } + + return true; +} + MetaData::typed_data::typed_data() : mType(0), mSize(0) { @@ -294,7 +308,7 @@ String8 MetaData::typed_data::asString() const { const void *data = storage(); switch(mType) { case TYPE_NONE: - out = String8::format("no type, size %d)", mSize); + out = String8::format("no type, size %zu)", mSize); break; case TYPE_C_STRING: out = String8::format("(char*) %s", (const char *)data); @@ -303,7 +317,7 @@ String8 MetaData::typed_data::asString() const { out = String8::format("(int32_t) %d", *(int32_t *)data); break; case TYPE_INT64: - out = String8::format("(int64_t) %lld", *(int64_t *)data); + out = String8::format("(int64_t) %" PRId64, *(int64_t *)data); break; case TYPE_FLOAT: out = String8::format("(float) %f", *(float *)data); @@ -320,7 +334,7 @@ String8 MetaData::typed_data::asString() const { } default: - out = String8::format("(unknown type %d, size %d)", mType, mSize); + out = String8::format("(unknown type %d, size %zu)", mType, mSize); if (mSize <= 48) { // if it's less than three lines of hex data, dump it AString foo; hexdump(data, mSize, 0, &foo); diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 7f56af8..43736ad 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -359,12 +359,7 @@ sp<MediaSource> OMXCodec::Create( observer->setCodec(codec); err = codec->configureCodec(meta); - if (err == OK) { - if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) { - codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime; - } - return codec; } @@ -1346,8 +1341,7 @@ OMXCodec::OMXCodec( mLeftOverBuffer(NULL), mPaused(false), mNativeWindow( - (!strncmp(componentName, "OMX.google.", 11) - || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode")) + (!strncmp(componentName, "OMX.google.", 11)) ? NULL : nativeWindow) { mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexOutput] = ENABLED; diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 19af4fb..fcd9a85 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "StagefrightMetadataRetriever" +#include <inttypes.h> #include <utils/Log.h> #include "include/StagefrightMetadataRetriever.h" @@ -488,7 +489,7 @@ void StagefrightMetadataRetriever::parseMetaData() { size_t numTracks = mExtractor->countTracks(); char tmp[32]; - sprintf(tmp, "%d", numTracks); + sprintf(tmp, "%zu", numTracks); mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); @@ -545,7 +546,7 @@ void StagefrightMetadataRetriever::parseMetaData() { } // The duration value is a string representing the duration in ms. - sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000); + sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000); mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); if (hasAudio) { @@ -573,7 +574,7 @@ void StagefrightMetadataRetriever::parseMetaData() { if (mSource->getSize(&sourceSize) == OK) { int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs); - sprintf(tmp, "%lld", avgBitRate); + sprintf(tmp, "%" PRId64, avgBitRate); mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); } } diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index 6a16bb4..0afac69 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -38,11 +38,14 @@ namespace android { +static int64_t kWakelockMinDelay = 100000ll; // 100ms + TimedEventQueue::TimedEventQueue() : mNextEventID(1), mRunning(false), mStopped(false), - mDeathRecipient(new PMDeathRecipient(this)) { + mDeathRecipient(new PMDeathRecipient(this)), + mWakeLockCount(0) { } TimedEventQueue::~TimedEventQueue() { @@ -87,9 +90,7 @@ void TimedEventQueue::stop(bool flush) { // some events may be left in the queue if we did not flush and the wake lock // must be released. - if (!mQueue.empty()) { - releaseWakeLock_l(); - } + releaseWakeLock_l(true /*force*/); mQueue.clear(); mRunning = false; @@ -126,13 +127,15 @@ TimedEventQueue::event_id TimedEventQueue::postTimedEvent( QueueItem item; item.event = event; item.realtime_us = realtime_us; + item.has_wakelock = false; if (it == mQueue.begin()) { mQueueHeadChangedCondition.signal(); } - if (mQueue.empty()) { + if (realtime_us > ALooper::GetNowUs() + kWakelockMinDelay) { acquireWakeLock_l(); + item.has_wakelock = true; } mQueue.insert(it, item); @@ -188,10 +191,10 @@ void TimedEventQueue::cancelEvents( ALOGV("cancelling event %d", (*it).event->eventID()); (*it).event->setEventID(0); - it = mQueue.erase(it); - if (mQueue.empty()) { + if ((*it).has_wakelock) { releaseWakeLock_l(); } + it = mQueue.erase(it); if (stopAfterFirstMatch) { return; } @@ -214,6 +217,7 @@ void TimedEventQueue::threadEntry() { for (;;) { int64_t now_us = 0; sp<Event> event; + bool wakeLocked = false; { Mutex::Autolock autoLock(mLock); @@ -280,28 +284,29 @@ void TimedEventQueue::threadEntry() { // removeEventFromQueue_l will return NULL. // Otherwise, the QueueItem will be removed // from the queue and the referenced event returned. - event = removeEventFromQueue_l(eventID); + event = removeEventFromQueue_l(eventID, &wakeLocked); } if (event != NULL) { // Fire event with the lock NOT held. event->fire(this, now_us); + if (wakeLocked) { + Mutex::Autolock autoLock(mLock); + releaseWakeLock_l(); + } } } } sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l( - event_id id) { + event_id id, bool *wakeLocked) { for (List<QueueItem>::iterator it = mQueue.begin(); it != mQueue.end(); ++it) { if ((*it).event->eventID() == id) { sp<Event> event = (*it).event; event->setEventID(0); - + *wakeLocked = (*it).has_wakelock; mQueue.erase(it); - if (mQueue.empty()) { - releaseWakeLock_l(); - } return event; } } @@ -313,51 +318,61 @@ sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l( void TimedEventQueue::acquireWakeLock_l() { - if (mWakeLockToken != 0) { - return; - } - if (mPowerManager == 0) { - // use checkService() to avoid blocking if power service is not up yet - sp<IBinder> binder = - defaultServiceManager()->checkService(String16("power")); - if (binder == 0) { - ALOGW("cannot connect to the power manager service"); - } else { - mPowerManager = interface_cast<IPowerManager>(binder); - binder->linkToDeath(mDeathRecipient); + if (mWakeLockCount == 0) { + CHECK(mWakeLockToken == 0); + if (mPowerManager == 0) { + // use checkService() to avoid blocking if power service is not up yet + sp<IBinder> binder = + defaultServiceManager()->checkService(String16("power")); + if (binder == 0) { + ALOGW("cannot connect to the power manager service"); + } else { + mPowerManager = interface_cast<IPowerManager>(binder); + binder->linkToDeath(mDeathRecipient); + } } - } - if (mPowerManager != 0) { - sp<IBinder> binder = new BBinder(); - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, - binder, - String16("TimedEventQueue"), - String16("media")); - IPCThreadState::self()->restoreCallingIdentity(token); - if (status == NO_ERROR) { - mWakeLockToken = binder; + if (mPowerManager != 0) { + sp<IBinder> binder = new BBinder(); + int64_t token = IPCThreadState::self()->clearCallingIdentity(); + status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, + binder, + String16("TimedEventQueue"), + String16("media")); + IPCThreadState::self()->restoreCallingIdentity(token); + if (status == NO_ERROR) { + mWakeLockToken = binder; + mWakeLockCount++; + } } + } else { + mWakeLockCount++; } } -void TimedEventQueue::releaseWakeLock_l() +void TimedEventQueue::releaseWakeLock_l(bool force) { - if (mWakeLockToken == 0) { + if (mWakeLockCount == 0) { return; } - if (mPowerManager != 0) { - int64_t token = IPCThreadState::self()->clearCallingIdentity(); - mPowerManager->releaseWakeLock(mWakeLockToken, 0); - IPCThreadState::self()->restoreCallingIdentity(token); + if (force) { + // Force wakelock release below by setting reference count to 1. + mWakeLockCount = 1; + } + if (--mWakeLockCount == 0) { + CHECK(mWakeLockToken != 0); + if (mPowerManager != 0) { + int64_t token = IPCThreadState::self()->clearCallingIdentity(); + mPowerManager->releaseWakeLock(mWakeLockToken, 0); + IPCThreadState::self()->restoreCallingIdentity(token); + } + mWakeLockToken.clear(); } - mWakeLockToken.clear(); } void TimedEventQueue::clearPowerManager() { Mutex::Autolock _l(mLock); - releaseWakeLock_l(); + releaseWakeLock_l(true /*force*/); mPowerManager.clear(); } diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index 4db8e80..216a329 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -540,7 +540,8 @@ const struct mime_conv_t* p = &mimeLookup[0]; return BAD_VALUE; } -bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, bool isStreaming) +bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, + bool isStreaming, audio_stream_type_t streamType) { const char *mime; CHECK(meta->findCString(kKeyMIMEType, &mime)); @@ -561,6 +562,17 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, bool isStreaming) return false; } + // check whether it is ELD/LD content -> no offloading + // FIXME: this should depend on audio DSP capabilities. mapMimeToAudioFormat() should use the + // metadata to refine the AAC format and the audio HAL should only list supported profiles. + int32_t aacaot = -1; + if (meta->findInt32(kKeyAACAOT, &aacaot)) { + if (aacaot == 23 || aacaot == 39 ) { + ALOGV("track of type '%s' is ELD/LD content", mime); + return false; + } + } + int32_t srate = -1; if (!meta->findInt32(kKeySampleRate, &srate)) { ALOGV("track of type '%s' does not publish sample rate", mime); @@ -594,7 +606,7 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, bool isStreaming) info.bit_rate = brate; - info.stream_type = AUDIO_STREAM_MUSIC; + info.stream_type = streamType; info.has_video = hasVideo; info.is_streaming = isStreaming; diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp index 4a21a3e..1d398fb 100644 --- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp @@ -593,6 +593,17 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter( mVideoHeight = def->format.video.nFrameHeight; mVideoFrameRate = def->format.video.xFramerate >> 16; mVideoColorFormat = def->format.video.eColorFormat; + + OMX_PARAM_PORTDEFINITIONTYPE *portDef = + &editPortInfo(0)->mDef; + portDef->format.video.nFrameWidth = mVideoWidth; + portDef->format.video.nFrameHeight = mVideoHeight; + portDef->format.video.xFramerate = def->format.video.xFramerate; + portDef->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE) mVideoColorFormat; + portDef = &editPortInfo(1)->mDef; + portDef->format.video.nFrameWidth = mVideoWidth; + portDef->format.video.nFrameHeight = mVideoHeight; } else { mVideoBitRate = def->format.video.nBitrate; } diff --git a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp index 0e3037f..d71c327 100644 --- a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp +++ b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp @@ -103,6 +103,15 @@ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream) { num_bits -= 8; byte = (current_word >> num_bits) & 0xFF; + if (stream->count_zeros == 2) + { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */ + if (byte <= 3) + { + *write_pnt++ = 0x3; + stream->write_pos++; + stream->count_zeros = 0; + } + } if (byte != 0) { *write_pnt++ = byte; @@ -114,12 +123,6 @@ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream) stream->count_zeros++; *write_pnt++ = byte; stream->write_pos++; - if (stream->count_zeros == 2) - { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */ - *write_pnt++ = 0x3; - stream->write_pos++; - stream->count_zeros = 0; - } } } diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp index e23f23d..fe9e7dc 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp @@ -96,7 +96,7 @@ int GetPredAdvancedBy0x0( offset = width - B_SIZE; /* offset for prev */ offset2 = (pred_width_rnd >> 1) - 4; /* offset for pred_block */ - tmp = (uint32)prev & 0x3; + tmp = (uintptr_t)prev & 0x3; pred_block -= offset2; /* preset */ if (tmp == 0) /* word-aligned */ @@ -203,7 +203,7 @@ int GetPredAdvancedBy0x1( /* Branch based on pixel location (half-pel or full-pel) for x and y */ pred_block -= offset2; /* preset */ - tmp = (uint32)prev & 3; + tmp = (uintptr_t)prev & 3; mask = 254; mask |= (mask << 8); mask |= (mask << 16); /* 0xFEFEFEFE */ @@ -532,7 +532,7 @@ int GetPredAdvancedBy1x0( /* Branch based on pixel location (half-pel or full-pel) for x and y */ pred_block -= offset2; /* preset */ - tmp = (uint32)prev & 3; + tmp = (uintptr_t)prev & 3; mask = 254; mask |= (mask << 8); mask |= (mask << 16); /* 0xFEFEFEFE */ @@ -884,7 +884,7 @@ int GetPredAdvancedBy1x1( mask |= (mask << 8); mask |= (mask << 16); /* 0x3f3f3f3f */ - tmp = (uint32)prev & 3; + tmp = (uintptr_t)prev & 3; pred_block -= 4; /* preset */ diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp index fa50eeb..fa4ae23 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp @@ -250,7 +250,7 @@ extern "C" out[40] = k4 ; /* row 5 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -455,7 +455,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -635,7 +635,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -846,7 +846,7 @@ extern "C" out[40] = k4 ; /* row 5 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -1033,7 +1033,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -1195,7 +1195,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp index 6fd41c3..0ad39a6 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp @@ -572,7 +572,7 @@ Int Sad8x8(UChar *cur, UChar *prev, Int width) cur2 = cur2 & (mask << 8); /* mask first and third bytes */ sum2 = sum2 + ((UInt)cur2 >> 8); } - while ((UInt)curInt < (UInt)end); + while ((uintptr_t)curInt < (uintptr_t)end); cur1 = sum4 - (sum2 << 8); /* get even-sum */ cur1 = cur1 + sum2; /* add 16 bit even-sum and odd-sum*/ @@ -611,7 +611,7 @@ Int getBlockSum(UChar *cur, Int width) load2 = load2 & (mask << 8); /* even bytes */ sum2 += ((UInt)load2 >> 8); /* sum even bytes, 16 bit */ } - while ((UInt)curInt < (UInt)end); + while ((uintptr_t)curInt < (uintptr_t)end); load1 = sum4 - (sum2 << 8); /* get even-sum */ load1 = load1 + sum2; /* add 16 bit even-sum and odd-sum*/ load1 = load1 + (load1 << 16); /* add upper and lower 16 bit sum */ diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp index b81d278..06e8926 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp @@ -1959,7 +1959,7 @@ void PutSkippedBlock(UChar *rec, UChar *prev, Int lx) dst += offset; src += offset; } - while ((UInt)src < (UInt)end); + while ((uintptr_t)src < (uintptr_t)end); return ; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h index ba77dfd..b865f23 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h +++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h @@ -85,7 +85,7 @@ extern "C" x9 = 0x80808080; /* const. */ - x8 = (uint32)ref & 0x3; + x8 = (uintptr_t)ref & 0x3; if (x8 == 3) goto SadMBOffset3; if (x8 == 2) diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 8375cac..5efe022 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -677,6 +677,9 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams( def->format.video.nFrameHeight = mHeight; def->format.video.xFramerate = port->format.video.xFramerate; def->format.video.eColorFormat = mColorFormat; + def = &editPortInfo(kOutputPortIndex)->mDef; + def->format.video.nFrameWidth = mWidth; + def->format.video.nFrameHeight = mHeight; return OMX_ErrorNone; } else if (port->nPortIndex == kOutputPortIndex) { diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h index cb3adda..216ad04 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h @@ -42,6 +42,7 @@ #include <stdio.h> #endif +#include <stdint.h> #include "basetype.h" #include "h264bsd_stream.h" #include "h264bsd_image.h" @@ -150,7 +151,7 @@ } #define ALIGN(ptr, bytePos) \ - (ptr + ( ((bytePos - (int)ptr) & (bytePos - 1)) / sizeof(*ptr) )) + (ptr + ( ((bytePos - (uintptr_t)ptr) & (bytePos - 1)) / sizeof(*ptr) )) extern const u32 h264bsdQpC[52]; diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index d4fd2b3..fc1353a 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -640,9 +640,6 @@ sp<M3UParser> LiveSession::fetchPlaylist( // playlist unchanged *unchanged = true; - ALOGV("Playlist unchanged, refresh state is now %d", - (int)mRefreshState); - return NULL; } diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index 243888c..5ef7c0f 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -416,22 +416,32 @@ static bool MakeURL(const char *baseURL, const char *url, AString *out) { } else { // URL is a relative path - size_t n = strlen(baseURL); - if (baseURL[n - 1] == '/') { - out->setTo(baseURL); - out->append(url); + // Check for a possible query string + const char *qsPos = strchr(baseURL, '?'); + size_t end; + if (qsPos != NULL) { + end = qsPos - baseURL; } else { - const char *slashPos = strrchr(baseURL, '/'); - - if (slashPos > &baseURL[6]) { - out->setTo(baseURL, slashPos - baseURL); - } else { - out->setTo(baseURL); + end = strlen(baseURL); + } + // Check for the last slash before a potential query string + for (ssize_t pos = end - 1; pos >= 0; pos--) { + if (baseURL[pos] == '/') { + end = pos; + break; } + } - out->append("/"); - out->append(url); + // Check whether the found slash actually is part of the path + // and not part of the "http://". + if (end > 6) { + out->setTo(baseURL, end); + } else { + out->setTo(baseURL); } + + out->append("/"); + out->append(url); } ALOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str()); @@ -608,7 +618,7 @@ status_t M3UParser::parseMetaDataDuration( if (meta->get() == NULL) { *meta = new AMessage; } - (*meta)->setInt64(key, (int64_t)x * 1E6); + (*meta)->setInt64(key, (int64_t)(x * 1E6)); return OK; } diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp index 34d671a..1ec4a40 100644 --- a/media/libstagefright/id3/ID3.cpp +++ b/media/libstagefright/id3/ID3.cpp @@ -56,14 +56,14 @@ private: DISALLOW_EVIL_CONSTRUCTORS(MemorySource); }; -ID3::ID3(const sp<DataSource> &source, bool ignoreV1) +ID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset) : mIsValid(false), mData(NULL), mSize(0), mFirstFrameOffset(0), mVersion(ID3_UNKNOWN), mRawSize(0) { - mIsValid = parseV2(source); + mIsValid = parseV2(source, offset); if (!mIsValid && !ignoreV1) { mIsValid = parseV1(source); @@ -79,7 +79,7 @@ ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1) mRawSize(0) { sp<MemorySource> source = new MemorySource(data, size); - mIsValid = parseV2(source); + mIsValid = parseV2(source, 0); if (!mIsValid && !ignoreV1) { mIsValid = parseV1(source); @@ -115,7 +115,7 @@ bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) { return true; } -bool ID3::parseV2(const sp<DataSource> &source) { +bool ID3::parseV2(const sp<DataSource> &source, off64_t offset) { struct id3_header { char id[3]; uint8_t version_major; @@ -126,7 +126,7 @@ struct id3_header { id3_header header; if (source->readAt( - 0, &header, sizeof(header)) != (ssize_t)sizeof(header)) { + offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) { return false; } @@ -185,7 +185,7 @@ struct id3_header { mSize = size; mRawSize = mSize + sizeof(header); - if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) { + if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) { free(mData); mData = NULL; diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp index bc4572c..b2f4188 100644 --- a/media/libstagefright/id3/testid3.cpp +++ b/media/libstagefright/id3/testid3.cpp @@ -33,7 +33,7 @@ static void hexdump(const void *_data, size_t size) { const uint8_t *data = (const uint8_t *)_data; size_t offset = 0; while (offset < size) { - printf("0x%04x ", offset); + printf("0x%04zx ", offset); size_t n = size - offset; if (n > 16) { @@ -101,7 +101,7 @@ void scanFile(const char *path) { const void *data = tag.getAlbumArt(&dataSize, &mime); if (data) { - printf("found album art: size=%d mime='%s'\n", dataSize, + printf("found album art: size=%zu mime='%s'\n", dataSize, mime.string()); hexdump(data, dataSize > 128 ? 128 : dataSize); diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h index cca83ab..e83f3ef 100644 --- a/media/libstagefright/include/ID3.h +++ b/media/libstagefright/include/ID3.h @@ -35,7 +35,7 @@ struct ID3 { ID3_V2_4, }; - ID3(const sp<DataSource> &source, bool ignoreV1 = false); + ID3(const sp<DataSource> &source, bool ignoreV1 = false, off64_t offset = 0); ID3(const uint8_t *data, size_t size, bool ignoreV1 = false); ~ID3(); @@ -86,7 +86,7 @@ private: size_t mRawSize; bool parseV1(const sp<DataSource> &source); - bool parseV2(const sp<DataSource> &source); + bool parseV2(const sp<DataSource> &source, off64_t offset); void removeUnsynchronization(); bool removeUnsynchronizationV2_4(bool iTunesHack); diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index bd5e4b9..7b4bc6d 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -97,6 +97,7 @@ private: status_t parseChunk(off64_t *offset, int depth); status_t parseITunesMetaData(off64_t offset, size_t size); status_t parse3GPPMetaData(off64_t offset, size_t size, int depth); + void parseID3v2MetaData(off64_t offset); status_t updateAudioTrackInfoFromESDS_MPEG4Audio( const void *esds_data, size_t esds_size); diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h index 4e49c83..3e84256 100644 --- a/media/libstagefright/include/TimedEventQueue.h +++ b/media/libstagefright/include/TimedEventQueue.h @@ -118,6 +118,7 @@ private: struct QueueItem { sp<Event> event; int64_t realtime_us; + bool has_wakelock; }; struct StopEvent : public TimedEventQueue::Event { @@ -139,14 +140,15 @@ private: sp<IPowerManager> mPowerManager; sp<IBinder> mWakeLockToken; const sp<PMDeathRecipient> mDeathRecipient; + uint32_t mWakeLockCount; static void *ThreadWrapper(void *me); void threadEntry(); - sp<Event> removeEventFromQueue_l(event_id id); + sp<Event> removeEventFromQueue_l(event_id id, bool *wakeLocked); void acquireWakeLock_l(); - void releaseWakeLock_l(); + void releaseWakeLock_l(bool force = false); TimedEventQueue(const TimedEventQueue &); TimedEventQueue &operator=(const TimedEventQueue &); diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index 9850a46..175a263 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -1193,7 +1193,10 @@ status_t ATSParser::parseTS(ABitReader *br) { unsigned sync_byte = br->getBits(8); CHECK_EQ(sync_byte, 0x47u); - MY_LOGV("transport_error_indicator = %u", br->getBits(1)); + if (br->getBits(1)) { // transport_error_indicator + // silently ignore. + return OK; + } unsigned payload_unit_start_indicator = br->getBits(1); ALOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator); diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index 8f9c9c8..e0ff0d1 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -604,7 +604,9 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() { dstOffset += pos.nalSize + 4; } +#if !LOG_NDEBUG ALOGV("accessUnit contains nal types %s", out.c_str()); +#endif const NALPosition &pos = nals.itemAt(nals.size() - 1); size_t nextScan = pos.nalOffset + pos.nalSize; diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index cf43e94..b8970ad 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -148,6 +148,18 @@ void GraphicBufferSource::omxExecuting() { } } +void GraphicBufferSource::omxIdle() { + ALOGV("omxIdle"); + + Mutex::Autolock autoLock(mMutex); + + if (mExecuting) { + // We are only interested in the transition from executing->idle, + // not loaded->idle. + mExecuting = false; + } +} + void GraphicBufferSource::omxLoaded(){ Mutex::Autolock autoLock(mMutex); if (!mExecuting) { @@ -194,7 +206,9 @@ void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) { void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { Mutex::Autolock autoLock(mMutex); - CHECK(mExecuting); // could this happen if app stop()s early? + if (!mExecuting) { + return; + } int cbi = findMatchingCodecBuffer_l(header); if (cbi < 0) { @@ -213,7 +227,12 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { // see if the GraphicBuffer reference was null, which should only ever // happen for EOS. if (codecBuffer.mGraphicBuffer == NULL) { - CHECK(mEndOfStream && mEndOfStreamSent); + if (!(mEndOfStream && mEndOfStreamSent)) { + // This can happen when broken code sends us the same buffer + // twice in a row. + ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer " + "(buffer emptied twice?)"); + } // No GraphicBuffer to deal with, no additional input or output is // expected, so just return. return; @@ -384,6 +403,23 @@ bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { if (mLatestSubmittedBufferId < 0 || mSuspended) { return false; } + if (mBufferSlot[mLatestSubmittedBufferId] == NULL) { + // This can happen if the remote side disconnects, causing + // onBuffersReleased() to NULL out our copy of the slots. The + // buffer is gone, so we have nothing to show. + // + // To be on the safe side we try to release the buffer. + ALOGD("repeatLatestSubmittedBuffer_l: slot was NULL"); + mBufferQueue->releaseBuffer( + mLatestSubmittedBufferId, + mLatestSubmittedBufferFrameNum, + EGL_NO_DISPLAY, + EGL_NO_SYNC_KHR, + Fence::NO_FENCE); + mLatestSubmittedBufferId = -1; + mLatestSubmittedBufferFrameNum = 0; + return false; + } int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h index 244a843..9e5eee6 100644 --- a/media/libstagefright/omx/GraphicBufferSource.h +++ b/media/libstagefright/omx/GraphicBufferSource.h @@ -69,6 +69,11 @@ public: // sitting in the BufferQueue, this will send them to the codec. void omxExecuting(); + // This is called when OMX transitions to OMX_StateIdle, indicating that + // the codec is meant to return all buffers back to the client for them + // to be freed. Do NOT submit any more buffers to the component. + void omxIdle(); + // This is called when OMX transitions to OMX_StateLoaded, indicating that // we are shutting down. void omxLoaded(); diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index 84a0e10..274f2eb 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -479,7 +479,7 @@ OMX_ERRORTYPE OMX::OnFillBufferDone( OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) { // mLock is already held. - node_id node = (node_id)++mNodeCounter; + node_id node = (node_id)(uintptr_t)++mNodeCounter; mNodeIDToInstance.add(node, instance); return node; diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 46e5d71..5f104fc 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -243,13 +243,18 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) { status_t OMXNodeInstance::sendCommand( OMX_COMMANDTYPE cmd, OMX_S32 param) { const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); - if (bufferSource != NULL - && cmd == OMX_CommandStateSet - && param == OMX_StateLoaded) { - // Initiating transition from Executing -> Loaded - // Buffers are about to be freed. - bufferSource->omxLoaded(); - setGraphicBufferSource(NULL); + if (bufferSource != NULL && cmd == OMX_CommandStateSet) { + if (param == OMX_StateIdle) { + // Initiating transition from Executing -> Idle + // ACodec is waiting for all buffers to be returned, do NOT + // submit any more buffers to the codec. + bufferSource->omxIdle(); + } else if (param == OMX_StateLoaded) { + // Initiating transition from Idle/Executing -> Loaded + // Buffers are about to be freed. + bufferSource->omxLoaded(); + setGraphicBufferSource(NULL); + } // fall through } diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp index 4bee808..44e4f9d 100644 --- a/media/libstagefright/omx/tests/OMXHarness.cpp +++ b/media/libstagefright/omx/tests/OMXHarness.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "OMXHarness" +#include <inttypes.h> #include <utils/Log.h> #include "OMXHarness.h" @@ -711,11 +712,11 @@ status_t Harness::testSeek( int64_t bufferTimeUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, &bufferTimeUs)); if (!CloseEnough(bufferTimeUs, actualSeekTimeUs)) { - printf("\n * Attempted seeking to %lld us (%.2f secs)", + printf("\n * Attempted seeking to %" PRId64 " us (%.2f secs)", requestedSeekTimeUs, requestedSeekTimeUs / 1E6); - printf("\n * Nearest keyframe is at %lld us (%.2f secs)", + printf("\n * Nearest keyframe is at %" PRId64 " us (%.2f secs)", actualSeekTimeUs, actualSeekTimeUs / 1E6); - printf("\n * Returned buffer was at %lld us (%.2f secs)\n\n", + printf("\n * Returned buffer was at %" PRId64 " us (%.2f secs)\n\n", bufferTimeUs, bufferTimeUs / 1E6); buffer->release(); diff --git a/media/libstagefright/tests/DummyRecorder.cpp b/media/libstagefright/tests/DummyRecorder.cpp index ac37b28..8f17088 100644 --- a/media/libstagefright/tests/DummyRecorder.cpp +++ b/media/libstagefright/tests/DummyRecorder.cpp @@ -61,7 +61,7 @@ status_t DummyRecorder::stop() { mSource->stop(); void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGV("Ending the reading thread"); return err; diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp index c674700..edcc087 100644 --- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp +++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp @@ -565,7 +565,7 @@ status_t TSPacketizer::packetize( } } - // size_t numPaddingBytes = sizeAvailableForPayload - numBytesOfPayload; + size_t numPaddingBytes = sizeAvailableForPayload - numBytesOfPayload; ALOGV("packet 1 contains %zd padding bytes and %zd bytes of payload", numPaddingBytes, numBytesOfPayload); diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp index 930f0b0..c4f87a0 100644 --- a/media/mtp/MtpDataPacket.cpp +++ b/media/mtp/MtpDataPacket.cpp @@ -331,7 +331,7 @@ void MtpDataPacket::putString(const char* s) { void MtpDataPacket::putString(const uint16_t* string) { int count = 0; - for (int i = 0; i < 256; i++) { + for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) { if (string[i]) count++; else diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp index 64dd45b..375ed9a 100644 --- a/media/mtp/MtpProperty.cpp +++ b/media/mtp/MtpProperty.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "MtpProperty" +#include <inttypes.h> #include "MtpDataPacket.h" #include "MtpDebug.h" #include "MtpProperty.h" @@ -385,10 +386,10 @@ void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) { buffer.appendFormat("%d", value.u.u32); break; case MTP_TYPE_INT64: - buffer.appendFormat("%lld", value.u.i64); + buffer.appendFormat("%" PRId64, value.u.i64); break; case MTP_TYPE_UINT64: - buffer.appendFormat("%lld", value.u.u64); + buffer.appendFormat("%" PRIu64, value.u.u64); break; case MTP_TYPE_INT128: buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1], diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp index fe8cf04..f3420a4 100644 --- a/media/mtp/MtpStringBuffer.cpp +++ b/media/mtp/MtpStringBuffer.cpp @@ -56,42 +56,47 @@ MtpStringBuffer::~MtpStringBuffer() { } void MtpStringBuffer::set(const char* src) { - int length = strlen(src); - if (length >= sizeof(mBuffer)) - length = sizeof(mBuffer) - 1; - memcpy(mBuffer, src, length); - // count the characters int count = 0; char ch; - while ((ch = *src++) != 0) { + char* dest = (char*)mBuffer; + + while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) { if ((ch & 0x80) == 0) { // single byte character + *dest++ = ch; } else if ((ch & 0xE0) == 0xC0) { // two byte character - if (! *src++) { + char ch1 = *src++; + if (! ch1) { // last character was truncated, so ignore last byte - length--; break; } + + *dest++ = ch; + *dest++ = ch1; } else if ((ch & 0xF0) == 0xE0) { // 3 byte char - if (! *src++) { + char ch1 = *src++; + if (! ch1) { // last character was truncated, so ignore last byte - length--; break; } - if (! *src++) { - // last character was truncated, so ignore last two bytes - length -= 2; + char ch2 = *src++; + if (! ch2) { + // last character was truncated, so ignore last byte break; } + + *dest++ = ch; + *dest++ = ch1; + *dest++ = ch2; } count++; } - mByteCount = length + 1; - mBuffer[length] = 0; + *dest++ = 0; + mByteCount = dest - (char*)mBuffer; mCharCount = count; } @@ -100,7 +105,7 @@ void MtpStringBuffer::set(const uint16_t* src) { uint16_t ch; uint8_t* dest = mBuffer; - while ((ch = *src++) != 0 && count < 255) { + while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) { if (ch >= 0x0800) { *dest++ = (uint8_t)(0xE0 | (ch >> 12)); *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h index cbc8307..e5150df 100644 --- a/media/mtp/MtpStringBuffer.h +++ b/media/mtp/MtpStringBuffer.h @@ -19,6 +19,9 @@ #include <stdint.h> +// Max Character number of a MTP String +#define MTP_STRING_MAX_CHARACTER_NUMBER 255 + namespace android { class MtpDataPacket; @@ -29,7 +32,7 @@ class MtpStringBuffer { private: // mBuffer contains string in UTF8 format // maximum 3 bytes/character, with 1 extra for zero termination - uint8_t mBuffer[255 * 3 + 1]; + uint8_t mBuffer[MTP_STRING_MAX_CHARACTER_NUMBER * 3 + 1]; int mCharCount; int mByteCount; |