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> &params,
             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> &params,
             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> &params,
         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> &params,
         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;