Merge "Extend downsampling ratios greater than 2:1" into lmp-dev
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index dd13fea..627f23b 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -87,6 +87,10 @@
node_id node, OMX_U32 portIndex, OMX_BOOL enable,
OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) = 0;
+ virtual status_t configureVideoTunnelMode(
+ node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0;
+
virtual status_t enableGraphicBuffers(
node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 3a6bb9e..eb31c77 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -234,6 +234,9 @@
status_t setComponentRole(bool isEncoder, const char *mime);
status_t configureCodec(const char *mime, const sp<AMessage> &msg);
+ status_t configureTunneledVideoPlayback(int64_t audioHwSync,
+ const sp<ANativeWindow> &nativeWindow);
+
status_t setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 5df232f..c583d32 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -54,6 +54,7 @@
GET_GRAPHIC_BUFFER_USAGE,
SET_INTERNAL_OPTION,
UPDATE_GRAPHIC_BUFFER_IN_META,
+ CONFIGURE_VIDEO_TUNNEL_MODE,
};
class BpOMX : public BpInterface<IOMX> {
@@ -368,6 +369,25 @@
return err;
}
+ virtual status_t configureVideoTunnelMode(
+ node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeInt32((int32_t)node);
+ data.writeInt32(portIndex);
+ data.writeInt32((int32_t)tunneled);
+ data.writeInt32(audioHwSync);
+ remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (sidebandHandle) {
+ *sidebandHandle = (native_handle_t *)reply.readNativeHandle();
+ }
+ return err;
+ }
+
+
virtual status_t allocateBuffer(
node_id node, OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data) {
@@ -804,6 +824,24 @@
return NO_ERROR;
}
+ case CONFIGURE_VIDEO_TUNNEL_MODE:
+ {
+ CHECK_OMX_INTERFACE(IOMX, data, reply);
+
+ node_id node = (node_id)data.readInt32();
+ OMX_U32 port_index = data.readInt32();
+ OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
+ OMX_U32 audio_hw_sync = data.readInt32();
+
+ native_handle_t *sideband_handle;
+ status_t err = configureVideoTunnelMode(
+ node, port_index, tunneled, audio_hw_sync, &sideband_handle);
+ reply->writeInt32(err);
+ reply->writeNativeHandle(sideband_handle);
+
+ return NO_ERROR;
+ }
+
case ALLOC_BUFFER:
{
CHECK_OMX_INTERFACE(IOMX, data, reply);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 503ce81..ac80da2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1224,77 +1224,99 @@
}
}
- // Always try to enable dynamic output buffers on native surface
sp<RefBase> obj;
int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
- obj != NULL;
+ obj != NULL;
mStoreMetaDataInOutputBuffers = false;
if (video && !encoder) {
inputFormat->setInt32("adaptive-playback", false);
}
if (!encoder && video && haveNativeWindow) {
- err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE);
- if (err != OK) {
- ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
- mComponentName.c_str(), err);
+ sp<NativeWindowWrapper> windowWrapper(
+ static_cast<NativeWindowWrapper *>(obj.get()));
+ sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
- // if adaptive playback has been requested, try JB fallback
- // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
- // LARGE MEMORY REQUIREMENT
+ int32_t tunneled;
+ if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
+ tunneled != 0) {
+ ALOGI("Configuring TUNNELED video playback.");
- // we will not do adaptive playback on software accessed
- // surfaces as they never had to respond to changes in the
- // crop window, and we don't trust that they will be able to.
- int usageBits = 0;
- bool canDoAdaptivePlayback;
-
- sp<NativeWindowWrapper> windowWrapper(
- static_cast<NativeWindowWrapper *>(obj.get()));
- sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
-
- if (nativeWindow->query(
- nativeWindow.get(),
- NATIVE_WINDOW_CONSUMER_USAGE_BITS,
- &usageBits) != OK) {
- canDoAdaptivePlayback = false;
- } else {
- canDoAdaptivePlayback =
- (usageBits &
- (GRALLOC_USAGE_SW_READ_MASK |
- GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
+ int64_t audioHwSync = 0;
+ if (!msg->findInt64("audio-hw-sync", &audioHwSync)) {
+ ALOGW("No Audio HW Sync provided for video tunnel");
+ }
+ err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
+ if (err != OK) {
+ ALOGE("configureTunneledVideoPlayback(%" PRId64 ",%p) failed!",
+ audioHwSync, nativeWindow.get());
+ return err;
}
- int32_t maxWidth = 0, maxHeight = 0;
- if (canDoAdaptivePlayback &&
- msg->findInt32("max-width", &maxWidth) &&
- msg->findInt32("max-height", &maxHeight)) {
- ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
- mComponentName.c_str(), maxWidth, maxHeight);
-
- err = mOMX->prepareForAdaptivePlayback(
- mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
- ALOGW_IF(err != OK,
- "[%s] prepareForAdaptivePlayback failed w/ err %d",
+ inputFormat->setInt32("adaptive-playback", true);
+ } else {
+ // Always try to enable dynamic output buffers on native surface
+ err = mOMX->storeMetaDataInBuffers(
+ mNode, kPortIndexOutput, OMX_TRUE);
+ if (err != OK) {
+ ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
mComponentName.c_str(), err);
- if (err == OK) {
- inputFormat->setInt32("max-width", maxWidth);
- inputFormat->setInt32("max-height", maxHeight);
- inputFormat->setInt32("adaptive-playback", true);
- }
- }
- // allow failure
- err = OK;
- } else {
- ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str());
- mStoreMetaDataInOutputBuffers = true;
- inputFormat->setInt32("adaptive-playback", true);
- }
+ // if adaptive playback has been requested, try JB fallback
+ // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
+ // LARGE MEMORY REQUIREMENT
- int32_t push;
- if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
- && push != 0) {
- mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
+ // we will not do adaptive playback on software accessed
+ // surfaces as they never had to respond to changes in the
+ // crop window, and we don't trust that they will be able to.
+ int usageBits = 0;
+ bool canDoAdaptivePlayback;
+
+ if (nativeWindow->query(
+ nativeWindow.get(),
+ NATIVE_WINDOW_CONSUMER_USAGE_BITS,
+ &usageBits) != OK) {
+ canDoAdaptivePlayback = false;
+ } else {
+ canDoAdaptivePlayback =
+ (usageBits &
+ (GRALLOC_USAGE_SW_READ_MASK |
+ GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
+ }
+
+ int32_t maxWidth = 0, maxHeight = 0;
+ if (canDoAdaptivePlayback &&
+ msg->findInt32("max-width", &maxWidth) &&
+ msg->findInt32("max-height", &maxHeight)) {
+ ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
+ mComponentName.c_str(), maxWidth, maxHeight);
+
+ err = mOMX->prepareForAdaptivePlayback(
+ mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
+ maxHeight);
+ ALOGW_IF(err != OK,
+ "[%s] prepareForAdaptivePlayback failed w/ err %d",
+ mComponentName.c_str(), err);
+
+ if (err == OK) {
+ inputFormat->setInt32("max-width", maxWidth);
+ inputFormat->setInt32("max-height", maxHeight);
+ inputFormat->setInt32("adaptive-playback", true);
+ }
+ }
+ // allow failure
+ err = OK;
+ } else {
+ ALOGV("[%s] storeMetaDataInBuffers succeeded",
+ mComponentName.c_str());
+ mStoreMetaDataInOutputBuffers = true;
+ inputFormat->setInt32("adaptive-playback", true);
+ }
+
+ int32_t push;
+ if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
+ && push != 0) {
+ mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
+ }
}
int32_t rotationDegrees;
@@ -1869,6 +1891,27 @@
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
}
+status_t ACodec::configureTunneledVideoPlayback(
+ int64_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
+ native_handle_t* sidebandHandle;
+
+ status_t err = mOMX->configureVideoTunnelMode(
+ mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
+ if (err != OK) {
+ ALOGE("configureVideoTunnelMode failed! (err %d).", err);
+ return err;
+ }
+
+ err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
+ if (err != OK) {
+ ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
+ sidebandHandle, err);
+ return err;
+ }
+
+ return OK;
+}
+
status_t ACodec::setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index aca21cf..ca031aa 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -78,6 +78,10 @@
node_id node, OMX_U32 port_index, OMX_BOOL enable,
OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
+ virtual status_t configureVideoTunnelMode(
+ node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
+
virtual status_t enableGraphicBuffers(
node_id node, OMX_U32 port_index, OMX_BOOL enable);
@@ -291,6 +295,13 @@
node, port_index, enable, maxFrameWidth, maxFrameHeight);
}
+status_t MuxOMX::configureVideoTunnelMode(
+ node_id node, OMX_U32 portIndex, OMX_BOOL enable,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
+ return getOMX(node)->configureVideoTunnelMode(
+ node, portIndex, enable, audioHwSync, sidebandHandle);
+}
+
status_t MuxOMX::enableGraphicBuffers(
node_id node, OMX_U32 port_index, OMX_BOOL enable) {
return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
index 8451195..f23b5a0 100644
--- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
@@ -29,6 +29,7 @@
.global Filt_6k_7k_asm
.extern voAWB_Copy
.extern fir_6k_7k
+ .hidden fir_6k_7k
Filt_6k_7k_asm:
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
index ac2dd13..deb7efc 100644
--- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
@@ -32,6 +32,7 @@
.section .text
.global pred_lt4_asm
.extern inter4_2
+ .hidden inter4_2
pred_lt4_asm:
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
index fc42a03..8df0caa 100644
--- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
@@ -28,6 +28,7 @@
.section .text
.global Filt_6k_7k_asm
.extern fir_6k_7k
+ .hidden fir_6k_7k
Filt_6k_7k_asm:
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
index 8d2aaf2..67be1ed 100644
--- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
@@ -29,6 +29,7 @@
.section .text
.global pred_lt4_asm
.extern inter4_2
+ .hidden inter4_2
pred_lt4_asm:
diff --git a/media/libstagefright/codecs/hevcdec/Android.mk b/media/libstagefright/codecs/hevcdec/Android.mk
index 960602f..c0c694e 100644
--- a/media/libstagefright/codecs/hevcdec/Android.mk
+++ b/media/libstagefright/codecs/hevcdec/Android.mk
@@ -20,6 +20,10 @@
LOCAL_SHARED_LIBRARIES += libutils
LOCAL_SHARED_LIBRARIES += liblog
+# We need this because the current asm generates the following link error:
+# requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
+# Bug: 16853291
+LOCAL_LDFLAGS := -Wl,-Bsymbolic
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
index b74c849..1140ed7 100644
--- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
@@ -35,6 +35,7 @@
.text
.extern pqmfSynthWin
+.hidden pqmfSynthWin
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
index 073dbba..bcc6b6b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
@@ -10,6 +10,22 @@
.fpu neon
.text
+ .extern armVCM4P10_CAVLCCoeffTokenTables
+ .extern armVCM4P10_SuffixToLevel
+ .extern armVCM4P10_CAVLCTotalZeros2x2Tables
+ .extern armVCM4P10_CAVLCTotalZeroTables
+ .extern armVCM4P10_CAVLCRunBeforeTables
+ .extern armVCM4P10_ZigZag_2x2
+ .extern armVCM4P10_ZigZag_4x4
+
+ .hidden armVCM4P10_CAVLCCoeffTokenTables
+ .hidden armVCM4P10_SuffixToLevel
+ .hidden armVCM4P10_CAVLCTotalZeros2x2Tables
+ .hidden armVCM4P10_CAVLCTotalZeroTables
+ .hidden armVCM4P10_CAVLCRunBeforeTables
+ .hidden armVCM4P10_ZigZag_2x2
+ .hidden armVCM4P10_ZigZag_4x4
+
.global armVCM4P10_DecodeCoeffsToPair
.func armVCM4P10_DecodeCoeffsToPair
armVCM4P10_DecodeCoeffsToPair:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
index 44eb428..5bc7875 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
@@ -20,6 +20,14 @@
.global armVCM4P10_QPModuloTable
.global armVCM4P10_VMatrixU16
+ .hidden armVCM4P10_QPDivTable
+ .hidden armVCM4P10_VMatrixQPModTable
+ .hidden armVCM4P10_PosToVCol4x4
+ .hidden armVCM4P10_PosToVCol2x2
+ .hidden armVCM4P10_VMatrix
+ .hidden armVCM4P10_QPModuloTable
+ .hidden armVCM4P10_VMatrixU16
+
armVCM4P10_PosToVCol4x4:
.byte 0, 2, 0, 2
.byte 2, 1, 2, 1
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index cd51bbf..e8c4970 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -75,6 +75,10 @@
node_id node, OMX_U32 portIndex, OMX_BOOL enable,
OMX_U32 max_frame_width, OMX_U32 max_frame_height);
+ virtual status_t configureVideoTunnelMode(
+ node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
+
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 3967dc6..dc6d410 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -62,6 +62,10 @@
OMX_U32 portIndex, OMX_BOOL enable,
OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
+ status_t configureVideoTunnelMode(
+ OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
+
status_t useBuffer(
OMX_U32 portIndex, const sp<IMemory> ¶ms,
OMX::buffer_id *buffer);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index cc4770a..41407e4 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -342,6 +342,13 @@
portIndex, enable, maxFrameWidth, maxFrameHeight);
}
+status_t OMX::configureVideoTunnelMode(
+ node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
+ return findInstance(node)->configureVideoTunnelMode(
+ portIndex, tunneled, audioHwSync, sidebandHandle);
+}
+
status_t OMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index d6ab109..efb27f5 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -460,6 +460,49 @@
return err;
}
+status_t OMXNodeInstance::configureVideoTunnelMode(
+ OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
+ native_handle_t **sidebandHandle) {
+ Mutex::Autolock autolock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.configureVideoTunnelMode");
+
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
+ if (err != OMX_ErrorNone) {
+ ALOGE("configureVideoTunnelMode extension is missing!");
+ return StatusFromOMXError(err);
+ }
+
+ ConfigureVideoTunnelModeParams tunnelParams;
+ tunnelParams.nSize = sizeof(tunnelParams);
+ tunnelParams.nVersion.s.nVersionMajor = 1;
+ tunnelParams.nVersion.s.nVersionMinor = 0;
+ tunnelParams.nVersion.s.nRevision = 0;
+ tunnelParams.nVersion.s.nStep = 0;
+
+ tunnelParams.nPortIndex = portIndex;
+ tunnelParams.bTunneled = tunneled;
+ tunnelParams.nAudioHwSync = audioHwSync;
+ err = OMX_SetParameter(mHandle, index, &tunnelParams);
+ if (err != OMX_ErrorNone) {
+ ALOGE("configureVideoTunnelMode failed! (err %d).", err);
+ return UNKNOWN_ERROR;
+ }
+
+ err = OMX_GetParameter(mHandle, index, &tunnelParams);
+ if (err != OMX_ErrorNone) {
+ ALOGE("GetVideoTunnelWindow failed! (err %d).", err);
+ return UNKNOWN_ERROR;
+ }
+ if (sidebandHandle) {
+ *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
+ }
+
+ return err;
+}
+
status_t OMXNodeInstance::useBuffer(
OMX_U32 portIndex, const sp<IMemory> ¶ms,
OMX::buffer_id *buffer) {
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 850fe86..9e59488 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -254,7 +254,7 @@
return NO_MEMORY;
}
- if (checkOutputsForDevice(device, state, outputs, address) != NO_ERROR) {
+ if (checkOutputsForDevice(devDesc, state, outputs, address) != NO_ERROR) {
mAvailableOutputDevices.remove(devDesc);
return INVALID_OPERATION;
}
@@ -275,7 +275,7 @@
// remove device from available output devices
mAvailableOutputDevices.remove(devDesc);
- checkOutputsForDevice(device, state, outputs, address);
+ checkOutputsForDevice(devDesc, state, outputs, address);
} break;
default:
@@ -2983,7 +2983,7 @@
patchDesc->mPatch.sinks[j].ext.device.address;
if (strncmp(patchAddr,
address.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
- ALOGV("checkOutputsForDevice(): adding opened output %d on same address %s",
+ ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
desc->mIoHandle, patchDesc->mPatch.sinks[j].ext.device.address);
outputs.add(desc->mIoHandle);
break;
@@ -2993,12 +2993,15 @@
}
}
-status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
+status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs,
const String8 address)
{
+ audio_devices_t device = devDesc->mDeviceType;
sp<AudioOutputDescriptor> desc;
+ // erase all current sample rates, formats and channel masks
+ devDesc->clearCapabilities();
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
// first list already open outputs that can be routed to this device
@@ -3047,6 +3050,9 @@
for (j = 0; j < outputs.size(); j++) {
desc = mOutputs.valueFor(outputs.itemAt(j));
if (!desc->isDuplicated() && desc->mProfile == profile) {
+ // matching profile: save the sample rates, format and channel masks supported
+ // by the profile in our device descriptor
+ devDesc->importAudioPort(profile);
break;
}
}
@@ -3196,6 +3202,8 @@
profile_index--;
} else {
outputs.add(output);
+ devDesc->importAudioPort(profile);
+
if (deviceDistinguishesOnAddress(device)) {
ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)",
device, address.string());
@@ -5575,15 +5583,21 @@
port->type = mType;
unsigned int i;
for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
- port->sample_rates[i] = mSamplingRates[i];
+ if (mSamplingRates[i] != 0) {
+ port->sample_rates[i] = mSamplingRates[i];
+ }
}
port->num_sample_rates = i;
for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) {
- port->channel_masks[i] = mChannelMasks[i];
+ if (mChannelMasks[i] != 0) {
+ port->channel_masks[i] = mChannelMasks[i];
+ }
}
port->num_channel_masks = i;
for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) {
- port->formats[i] = mFormats[i];
+ if (mFormats[i] != 0) {
+ port->formats[i] = mFormats[i];
+ }
}
port->num_formats = i;
@@ -5595,6 +5609,59 @@
port->num_gains = i;
}
+void AudioPolicyManager::AudioPort::importAudioPort(const sp<AudioPort> port) {
+ for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) {
+ const uint32_t rate = port->mSamplingRates.itemAt(k);
+ if (rate != 0) { // skip "dynamic" rates
+ bool hasRate = false;
+ for (size_t l = 0 ; l < mSamplingRates.size() ; l++) {
+ if (rate == mSamplingRates.itemAt(l)) {
+ hasRate = true;
+ break;
+ }
+ }
+ if (!hasRate) { // never import a sampling rate twice
+ mSamplingRates.add(rate);
+ }
+ }
+ }
+ for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) {
+ const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k);
+ if (mask != 0) { // skip "dynamic" masks
+ bool hasMask = false;
+ for (size_t l = 0 ; l < mChannelMasks.size() ; l++) {
+ if (mask == mChannelMasks.itemAt(l)) {
+ hasMask = true;
+ break;
+ }
+ }
+ if (!hasMask) { // never import a channel mask twice
+ mChannelMasks.add(mask);
+ }
+ }
+ }
+ for (size_t k = 0 ; k < port->mFormats.size() ; k++) {
+ const audio_format_t format = port->mFormats.itemAt(k);
+ if (format != 0) { // skip "dynamic" formats
+ bool hasFormat = false;
+ for (size_t l = 0 ; l < mFormats.size() ; l++) {
+ if (format == mFormats.itemAt(l)) {
+ hasFormat = true;
+ break;
+ }
+ }
+ if (!hasFormat) { // never import a channel mask twice
+ mFormats.add(format);
+ }
+ }
+ }
+}
+
+void AudioPolicyManager::AudioPort::clearCapabilities() {
+ mChannelMasks.clear();
+ mFormats.clear();
+ mSamplingRates.clear();
+}
void AudioPolicyManager::AudioPort::loadSamplingRates(char *name)
{
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index 95aab65..f071675 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -238,6 +238,9 @@
virtual void toAudioPort(struct audio_port *port) const;
+ void importAudioPort(const sp<AudioPort> port);
+ void clearCapabilities();
+
void loadSamplingRates(char *name);
void loadFormats(char *name);
void loadOutChannels(char *name);
@@ -628,7 +631,7 @@
// when a device is disconnected, checks if an output is not used any more and
// returns its handle if any.
// transfers the audio tracks and effects from one output thread to another accordingly.
- status_t checkOutputsForDevice(audio_devices_t device,
+ status_t checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
audio_policy_dev_state_t state,
SortedVector<audio_io_handle_t>& outputs,
const String8 address);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 046988e..5eb5181 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1368,7 +1368,8 @@
ATRACE_CALL();
ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
Mutex::Autolock icl(mBinderSerializationLock);
- if ( checkPid(__FUNCTION__) != OK) return String8();
+ // The camera service can unconditionally get the parameters at all times
+ if (getCallingPid() != mServicePid && checkPid(__FUNCTION__) != OK) return String8();
SharedParameters::ReadLock l(mParameters);
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 517226d..fb6b678 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -556,7 +556,8 @@
// get preview/capture parameters - key/value pairs
String8 CameraClient::getParameters() const {
Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return String8();
+ // The camera service can unconditionally get the parameters at all times
+ if (getCallingPid() != mServicePid && checkPidAndHardware() != NO_ERROR) return String8();
String8 params(mHardware->getParameters().flatten());
LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index c266213..bf3318e 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -155,7 +155,7 @@
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
params.previewWidth, params.previewHeight,
- callbackFormat, 0, &mCallbackStreamId);
+ callbackFormat, &mCallbackStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index 964d278..cda98be 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -73,11 +73,10 @@
}
// Find out buffer size for JPEG
- camera_metadata_ro_entry_t maxJpegSize =
- params.staticInfo(ANDROID_JPEG_MAX_SIZE);
- if (maxJpegSize.count == 0) {
- ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
- __FUNCTION__, mId);
+ ssize_t maxJpegSize = device->getJpegBufferSize(params.pictureWidth, params.pictureHeight);
+ if (maxJpegSize <= 0) {
+ ALOGE("%s: Camera %d: Jpeg buffer size (%zu) is invalid ",
+ __FUNCTION__, mId, maxJpegSize);
return INVALID_OPERATION;
}
@@ -91,8 +90,7 @@
mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer"));
mCaptureWindow = new Surface(producer);
// Create memory for API consumption
- mCaptureHeap = new MemoryHeapBase(maxJpegSize.data.i32[0], 0,
- "Camera2Client::CaptureHeap");
+ mCaptureHeap = new MemoryHeapBase(maxJpegSize, 0, "Camera2Client::CaptureHeap");
if (mCaptureHeap->getSize() == 0) {
ALOGE("%s: Camera %d: Unable to allocate memory for capture",
__FUNCTION__, mId);
@@ -134,8 +132,7 @@
// Create stream for HAL production
res = device->createStream(mCaptureWindow,
params.pictureWidth, params.pictureHeight,
- HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0],
- &mCaptureStreamId);
+ HAL_PIXEL_FORMAT_BLOB, &mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 911f55a..ab0af0d 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -181,8 +181,7 @@
if (mPreviewStreamId == NO_STREAM) {
res = device->createStream(mPreviewWindow,
params.previewWidth, params.previewHeight,
- CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0,
- &mPreviewStreamId);
+ CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
@@ -385,7 +384,7 @@
mRecordingFrameCount = 0;
res = device->createStream(mRecordingWindow,
params.videoWidth, params.videoHeight,
- CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0, &mRecordingStreamId);
+ CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mRecordingStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for recording: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 10463c1..8fb876e 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -183,8 +183,7 @@
(int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
res = device->createStream(mZslWindow,
params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
- streamType, 0,
- &mZslStreamId);
+ streamType, &mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index b8611f8..86f82a3 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -384,23 +384,7 @@
// after each call, but only once we are done with all.
int streamId = -1;
- if (format == HAL_PIXEL_FORMAT_BLOB) {
- // JPEG buffers need to be sized for maximum possible compressed size
- CameraMetadata staticInfo = mDevice->info();
- camera_metadata_entry_t entry = staticInfo.find(ANDROID_JPEG_MAX_SIZE);
- if (entry.count == 0) {
- ALOGE("%s: Camera %d: Can't find maximum JPEG size in "
- "static metadata!", __FUNCTION__, mCameraId);
- return INVALID_OPERATION;
- }
- int32_t maxJpegSize = entry.data.i32[0];
- res = mDevice->createStream(anw, width, height, format, maxJpegSize,
- &streamId);
- } else {
- // All other streams are a known size
- res = mDevice->createStream(anw, width, height, format, /*size*/0,
- &streamId);
- }
+ res = mDevice->createStream(anw, width, height, format, &streamId);
if (res == OK) {
mStreamMap.add(bufferProducer->asBinder(), streamId);
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 0f6d278..f8823a3 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -280,7 +280,7 @@
window = new Surface(bufferProducer);
}
- return mDevice->createStream(window, width, height, format, /*size*/1,
+ return mDevice->createStream(window, width, height, format,
streamId);
}
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 037695d..9e124b0 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -109,8 +109,7 @@
* other formats, the size parameter is ignored.
*/
virtual status_t createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, size_t size,
- int *id) = 0;
+ uint32_t width, uint32_t height, int format, int *id) = 0;
/**
* Create an input reprocess stream that uses buffers from an existing
@@ -156,6 +155,12 @@
virtual status_t waitUntilDrained() = 0;
/**
+ * Get Jpeg buffer size for a given jpeg resolution.
+ * Negative values are error codes.
+ */
+ virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const = 0;
+
+ /**
* Abstract class for HAL notification listeners
*/
class NotificationListener {
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 8c2520e..d473a76 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -242,13 +242,16 @@
}
status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, size_t size, int *id) {
+ uint32_t width, uint32_t height, int format, int *id) {
ATRACE_CALL();
status_t res;
ALOGV("%s: E", __FUNCTION__);
sp<StreamAdapter> stream = new StreamAdapter(mHal2Device);
-
+ size_t size = 0;
+ if (format == HAL_PIXEL_FORMAT_BLOB) {
+ size = getJpegBufferSize(width, height);
+ }
res = stream->connectToDevice(consumer, width, height, format, size);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
@@ -263,6 +266,17 @@
return OK;
}
+ssize_t Camera2Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
+ // Always give the max jpeg buffer size regardless of the actual jpeg resolution.
+ camera_metadata_ro_entry jpegBufMaxSize = mDeviceInfo.find(ANDROID_JPEG_MAX_SIZE);
+ if (jpegBufMaxSize.count == 0) {
+ ALOGE("%s: Camera %d: Can't find maximum JPEG size in static metadata!", __FUNCTION__, mId);
+ return BAD_VALUE;
+ }
+
+ return jpegBufMaxSize.data.i32[0];
+}
+
status_t Camera2Device::createReprocessStreamFromStream(int outputId, int *id) {
ATRACE_CALL();
status_t res;
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 46182f8..d0ca46e 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -57,8 +57,7 @@
virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
virtual status_t createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, size_t size,
- int *id);
+ uint32_t width, uint32_t height, int format, int *id);
virtual status_t createReprocessStreamFromStream(int outputId, int *id);
virtual status_t getStreamInfo(int id,
uint32_t *width, uint32_t *height, uint32_t *format);
@@ -79,6 +78,7 @@
// Flush implemented as just a wait
virtual status_t flush(int64_t *lastFrameNumber = NULL);
virtual uint32_t getDeviceVersion();
+ virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
private:
const int mId;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index a6214cc..ed350c1 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -793,12 +793,12 @@
}
status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, size_t size, int *id) {
+ uint32_t width, uint32_t height, int format, int *id) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
- ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d, size %zu",
- mId, mNextStreamId, width, height, format, size);
+ ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d",
+ mId, mNextStreamId, width, height, format);
status_t res;
bool wasActive = false;
@@ -832,10 +832,7 @@
sp<Camera3OutputStream> newStream;
if (format == HAL_PIXEL_FORMAT_BLOB) {
ssize_t jpegBufferSize = getJpegBufferSize(width, height);
- if (jpegBufferSize > 0) {
- ALOGV("%s: Overwrite Jpeg output buffer size from %zu to %zu",
- __FUNCTION__, size, jpegBufferSize);
- } else {
+ if (jpegBufferSize <= 0) {
SET_ERR_L("Invalid jpeg buffer size %zd", jpegBufferSize);
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index b1b0033..7656237 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -93,11 +93,9 @@
// Actual stream creation/deletion is delayed until first request is submitted
// If adding streams while actively capturing, will pause device before adding
- // stream, reconfiguring device, and unpausing. Note that, for JPEG stream, the
- // buffer size may be overwritten by an more accurate value calculated by Camera3Device.
+ // stream, reconfiguring device, and unpausing.
virtual status_t createStream(sp<ANativeWindow> consumer,
- uint32_t width, uint32_t height, int format, size_t size,
- int *id);
+ uint32_t width, uint32_t height, int format, int *id);
virtual status_t createInputStream(
uint32_t width, uint32_t height, int format,
int *id);
@@ -137,6 +135,8 @@
virtual uint32_t getDeviceVersion();
+ virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
+
// Methods called by subclasses
void notifyStatus(bool idle); // updates from StatusTracker
@@ -316,12 +316,6 @@
*/
Size getMaxJpegResolution() const;
- /**
- * Get Jpeg buffer size for a given jpeg resolution.
- * Negative values are error codes.
- */
- ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
-
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
uint32_t metadataTag;