summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libeffects/downmix/Android.mk2
-rw-r--r--media/libeffects/factory/EffectsFactory.c20
-rw-r--r--media/libeffects/factory/EffectsFactory.h28
-rw-r--r--media/libeffects/loudness/Android.mk2
-rw-r--r--media/libeffects/loudness/EffectLoudnessEnhancer.cpp14
-rw-r--r--media/libeffects/lvm/wrapper/Android.mk4
-rw-r--r--media/libeffects/preprocessing/Android.mk2
-rw-r--r--media/libeffects/proxy/Android.mk5
-rw-r--r--media/libeffects/proxy/EffectProxy.cpp78
-rw-r--r--media/libeffects/proxy/EffectProxy.h4
-rw-r--r--media/libeffects/testlibs/Android.mk_4
-rw-r--r--media/libeffects/visualizer/Android.mk2
-rw-r--r--media/libmedia/AudioTrack.cpp45
-rw-r--r--media/libmedia/AudioTrackShared.cpp10
-rw-r--r--media/libmedia/IAudioFlinger.cpp5
-rw-r--r--media/libmedia/MemoryLeakTrackUtil.cpp14
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp33
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h13
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp31
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp11
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp27
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h1
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp16
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h4
-rw-r--r--media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp2
-rw-r--r--media/libnbaio/MonoPipe.cpp2
-rw-r--r--media/libstagefright/ACodec.cpp29
-rw-r--r--media/libstagefright/AudioPlayer.cpp15
-rw-r--r--media/libstagefright/AudioSource.cpp4
-rw-r--r--media/libstagefright/AwesomePlayer.cpp60
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp12
-rw-r--r--media/libstagefright/DataSource.cpp43
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp149
-rw-r--r--media/libstagefright/MediaCodec.cpp5
-rw-r--r--media/libstagefright/MetaData.cpp13
-rw-r--r--media/libstagefright/OMXCodec.cpp8
-rw-r--r--media/libstagefright/TimedEventQueue.cpp103
-rw-r--r--media/libstagefright/Utils.cpp16
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp3
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp36
-rw-r--r--media/libstagefright/id3/ID3.cpp12
-rw-r--r--media/libstagefright/include/ID3.h4
-rw-r--r--media/libstagefright/include/MPEG4Extractor.h1
-rw-r--r--media/libstagefright/include/TimedEventQueue.h6
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp5
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.cpp2
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.cpp40
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.h5
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp19
-rw-r--r--media/libstagefright/wifi-display/source/TSPacketizer.cpp2
-rw-r--r--media/mtp/MtpDataPacket.cpp2
-rw-r--r--media/mtp/MtpStringBuffer.cpp37
-rw-r--r--media/mtp/MtpStringBuffer.h5
54 files changed, 756 insertions, 262 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/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/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/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/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/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index fe5cd9e..0609a22 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;
}
@@ -857,7 +879,8 @@ status_t AudioTrack::createTrack_l(
ALOGV("createTrack_l() output %d afLatency %d", output, afLatency);
// 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)
@@ -962,6 +985,7 @@ status_t AudioTrack::createTrack_l(
tid,
&mSessionId,
mName,
+ mClientUid,
&status);
if (track == 0) {
@@ -996,9 +1020,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 {
@@ -1665,7 +1691,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,
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index da73d65..caa7900 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -506,7 +506,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 +579,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:
@@ -761,7 +765,7 @@ ssize_t StaticAudioTrackServerProxy::pollPosition()
return (ssize_t) position;
}
-status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer)
+status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
{
if (mIsShutdown) {
buffer->mFrameCount = 0;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 448a82e..acfaea0 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));
@@ -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);
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..9ac9105 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -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..f9d9020 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -70,8 +70,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 +1090,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 +1323,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 +1341,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();
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/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> &notify,
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/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/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..d7223d9 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,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index c912f75..aae6800 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -606,6 +606,9 @@ void AwesomePlayer::reset_l() {
mWatchForAudioSeekComplete = false;
mWatchForAudioEOS = false;
+
+ mMediaRenderingStartGeneration = 0;
+ mStartGeneration = 0;
}
void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -798,7 +801,7 @@ void AwesomePlayer::onBufferingUpdate() {
}
}
- if (mFlags & (PLAYING | PREPARING)) {
+ if (mFlags & (PLAYING | PREPARING | CACHE_UNDERRUN)) {
postBufferingEvent_l();
}
}
@@ -895,6 +898,8 @@ status_t AwesomePlayer::play_l() {
return OK;
}
+ mMediaRenderingStartGeneration = ++mStartGeneration;
+
if (!(mFlags & PREPARED)) {
status_t err = prepare_l();
@@ -1197,8 +1202,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 +1499,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 +1937,7 @@ void AwesomePlayer::onVideoEvent() {
++mStats.mNumVideoFramesDropped;
}
- postVideoEvent_l();
+ postVideoEvent_l(0);
return;
}
}
@@ -1967,6 +1977,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 +2096,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();
}
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..4f1c5b3 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 {
@@ -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/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..1daead7 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -89,6 +89,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 +221,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) {
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/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/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index bd12ddc..233db44 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -632,9 +632,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/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/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/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/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;