Merge "Revert "camera3: Update CameraMetadata vendor tag handling.""
diff --git a/cmds/screenrecord/Android.mk b/cmds/screenrecord/Android.mk
index 6ee2884..6747e60 100644
--- a/cmds/screenrecord/Android.mk
+++ b/cmds/screenrecord/Android.mk
@@ -41,6 +41,4 @@
 
 LOCAL_MODULE:= screenrecord
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index e2e389b..561ce02 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -23,8 +23,6 @@
 
 LOCAL_MODULE:= stagefright
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 ################################################################################
@@ -48,8 +46,6 @@
 
 LOCAL_MODULE:= record
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 ################################################################################
@@ -73,8 +69,6 @@
 
 LOCAL_MODULE:= recordvideo
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 
@@ -99,8 +93,6 @@
 
 LOCAL_MODULE:= audioloop
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 ################################################################################
@@ -124,8 +116,6 @@
 
 LOCAL_MODULE:= stream
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 ################################################################################
@@ -149,8 +139,6 @@
 
 LOCAL_MODULE:= sf2
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 ################################################################################
@@ -175,8 +163,6 @@
 
 LOCAL_MODULE:= codec
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
 
 ################################################################################
@@ -200,6 +186,4 @@
 
 LOCAL_MODULE:= muxer
 
-LOCAL_32_BIT_ONLY := true
-
 include $(BUILD_EXECUTABLE)
diff --git a/include/media/stagefright/ClockEstimator.h b/include/media/stagefright/ClockEstimator.h
new file mode 100644
index 0000000..2fd6e75
--- /dev/null
+++ b/include/media/stagefright/ClockEstimator.h
@@ -0,0 +1,110 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef CLOCK_ESTIMATOR_H_
+
+#define CLOCK_ESTIMATOR_H_
+
+
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+struct ClockEstimator : RefBase {
+    virtual double estimate(double x, double y) = 0;
+    virtual void reset() = 0;
+};
+
+struct WindowedLinearFitEstimator : ClockEstimator {
+    struct LinearFit {
+        /**
+         * Fit y = a * x + b, where each input has a weight
+         */
+        double mX;  // sum(w_i * x_i)
+        double mXX; // sum(w_i * x_i^2)
+        double mY;  // sum(w_i * y_i)
+        double mYY; // sum(w_i * y_i^2)
+        double mXY; // sum(w_i * x_i * y_i)
+        double mW;  // sum(w_i)
+
+        LinearFit();
+        void reset();
+        void combine(const LinearFit &lf);
+        void add(double x, double y, double w);
+        void scale(double w);
+        double interpolate(double x);
+        double size() const;
+
+        DISALLOW_EVIL_CONSTRUCTORS(LinearFit);
+    };
+
+    /**
+     * Estimator for f(x) = y' where input y' is noisy, but
+     * theoretically linear:
+     *
+     *      y' =~ y = a * x + b
+     *
+     * It uses linear fit regression over a tapering rolling window
+     * to get an estimate for y (from the current and past inputs
+     * (x, y')).
+     *
+     *     ____________
+     *    /|          |\
+     *   / |          | \
+     *  /  |          |  \   <--- new data (x, y')
+     * /   |   main   |   \
+     * <--><----------><-->
+     * tail            head
+     *
+     * weight is 1 under the main window, tapers exponentially by
+     * the factors given in the head and the tail.
+     *
+     * Assuming that x and y' are monotonic, that x is somewhat
+     * evenly sampled, and that a =~ 1, the estimated y is also
+     * going to be monotonic.
+     */
+    WindowedLinearFitEstimator(
+            size_t headLength = 5, double headFactor = 0.5,
+            size_t mainLength = 0, double tailFactor = 0.99);
+
+    virtual void reset();
+
+    // add a new sample (x -> y') and return an estimated value for the true y
+    virtual double estimate(double x, double y);
+
+private:
+    Vector<double> mXHistory; // circular buffer
+    Vector<double> mYHistory; // circular buffer
+    LinearFit mHead;
+    LinearFit mMain;
+    LinearFit mTail;
+    double mHeadFactorInv;
+    double mTailFactor;
+    double mFirstWeight;
+    size_t mHistoryLength;
+    size_t mHeadLength;
+    size_t mNumSamples;
+    size_t mSampleIx;
+
+    DISALLOW_EVIL_CONSTRUCTORS(WindowedLinearFitEstimator);
+};
+
+}; // namespace android
+
+#endif
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index ed10dea..661fde9 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -30,24 +30,13 @@
 
 #define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
 
+// subset of possible audio_channel_mask_t values, and AUDIO_CHANNEL_OUT_* renamed to CHANNEL_MASK_*
 typedef enum {
-    CHANNEL_MASK_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD,
-    // like AUDIO_CHANNEL_OUT_QUAD with *_SIDE_* instead of *_BACK_*, same channel order
-    CHANNEL_MASK_QUAD_SIDE =
-            AUDIO_CHANNEL_OUT_FRONT_LEFT |
-            AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-            AUDIO_CHANNEL_OUT_SIDE_LEFT |
-            AUDIO_CHANNEL_OUT_SIDE_RIGHT,
-    CHANNEL_MASK_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1,
-    // like AUDIO_CHANNEL_OUT_5POINT1 with *_SIDE_* instead of *_BACK_*, same channel order
-    CHANNEL_MASK_5POINT1_SIDE =
-            AUDIO_CHANNEL_OUT_FRONT_LEFT |
-            AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-            AUDIO_CHANNEL_OUT_FRONT_CENTER |
-            AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-            AUDIO_CHANNEL_OUT_SIDE_LEFT |
-            AUDIO_CHANNEL_OUT_SIDE_RIGHT,
-    CHANNEL_MASK_7POINT1_SIDE_BACK = AUDIO_CHANNEL_OUT_7POINT1,
+    CHANNEL_MASK_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD_BACK,
+    CHANNEL_MASK_QUAD_SIDE = AUDIO_CHANNEL_OUT_QUAD_SIDE,
+    CHANNEL_MASK_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1_BACK,
+    CHANNEL_MASK_5POINT1_SIDE = AUDIO_CHANNEL_OUT_5POINT1_SIDE,
+    CHANNEL_MASK_7POINT1 = AUDIO_CHANNEL_OUT_7POINT1,
 } downmix_input_channel_mask_t;
 
 // effect_handle_t interface implementation for downmix effect
@@ -343,7 +332,7 @@
         case CHANNEL_MASK_5POINT1_SIDE:
             Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate);
             break;
-        case CHANNEL_MASK_7POINT1_SIDE_BACK:
+        case CHANNEL_MASK_7POINT1:
             Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
             break;
         default:
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index fbfd3da..dc4f90e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1005,7 +1005,8 @@
     sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType,
                                                       mSampleRate,
                                                       // AudioFlinger only sees 16-bit PCM
-                                                      mFormat == AUDIO_FORMAT_PCM_8_BIT ?
+                                                      mFormat == AUDIO_FORMAT_PCM_8_BIT &&
+                                                          !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT) ?
                                                               AUDIO_FORMAT_PCM_16_BIT : mFormat,
                                                       mChannelMask,
                                                       &temp,
@@ -1820,7 +1821,7 @@
 
     result.append(" AudioTrack::dump\n");
     snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n", mStreamType,
-            mVolume[0], mVolume[1]);
+            mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
     result.append(buffer);
     snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%zu)\n", mFormat,
             mChannelCount, mFrameCount);
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index eb813bd..1940fe7 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -106,7 +106,7 @@
         data.writeInt32(format);
         data.writeInt32(channelMask);
         size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0;
-        data.writeInt32(frameCount);
+        data.writeInt64(frameCount);
         track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT;
         data.writeInt32(lFlags);
         // haveSharedBuffer
@@ -128,7 +128,7 @@
         if (lStatus != NO_ERROR) {
             ALOGE("createTrack error: %s", strerror(-lStatus));
         } else {
-            frameCount = reply.readInt32();
+            frameCount = reply.readInt64();
             if (pFrameCount != NULL) {
                 *pFrameCount = frameCount;
             }
@@ -179,7 +179,7 @@
         data.writeInt32(format);
         data.writeInt32(channelMask);
         size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0;
-        data.writeInt32(frameCount);
+        data.writeInt64(frameCount);
         track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT;
         data.writeInt32(lFlags);
         data.writeInt32((int32_t) tid);
@@ -192,7 +192,7 @@
         if (lStatus != NO_ERROR) {
             ALOGE("openRecord error: %s", strerror(-lStatus));
         } else {
-            frameCount = reply.readInt32();
+            frameCount = reply.readInt64();
             if (pFrameCount != NULL) {
                 *pFrameCount = frameCount;
             }
@@ -248,7 +248,7 @@
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32((int32_t) output);
         remote()->transact(FRAME_COUNT, data, &reply);
-        return reply.readInt32();
+        return reply.readInt64();
     }
 
     virtual uint32_t latency(audio_io_handle_t output) const
@@ -398,7 +398,7 @@
         data.writeInt32(format);
         data.writeInt32(channelMask);
         remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
-        return reply.readInt32();
+        return reply.readInt64();
     }
 
     virtual audio_io_handle_t openOutput(audio_module_handle_t module,
@@ -769,7 +769,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         remote()->transact(GET_PRIMARY_OUTPUT_FRAME_COUNT, data, &reply);
-        return reply.readInt32();
+        return reply.readInt64();
     }
 
     virtual status_t setLowRamDevice(bool isLowRamDevice)
@@ -797,7 +797,7 @@
             uint32_t sampleRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
-            size_t frameCount = data.readInt32();
+            size_t frameCount = data.readInt64();
             track_flags_t flags = (track_flags_t) data.readInt32();
             bool haveSharedBuffer = data.readInt32() != 0;
             sp<IMemory> buffer;
@@ -821,7 +821,7 @@
                         &sessionId, clientUid, &status);
                 LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
             }
-            reply->writeInt32(frameCount);
+            reply->writeInt64(frameCount);
             reply->writeInt32(flags);
             reply->writeInt32(sessionId);
             reply->writeInt32(status);
@@ -834,7 +834,7 @@
             uint32_t sampleRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
-            size_t frameCount = data.readInt32();
+            size_t frameCount = data.readInt64();
             track_flags_t flags = (track_flags_t) data.readInt32();
             pid_t tid = (pid_t) data.readInt32();
             int sessionId = data.readInt32();
@@ -842,7 +842,7 @@
             sp<IAudioRecord> record = openRecord(input,
                     sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, &status);
             LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR));
-            reply->writeInt32(frameCount);
+            reply->writeInt64(frameCount);
             reply->writeInt32(flags);
             reply->writeInt32(sessionId);
             reply->writeInt32(status);
@@ -861,7 +861,7 @@
         } break;
         case FRAME_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( frameCount((audio_io_handle_t) data.readInt32()) );
+            reply->writeInt64( frameCount((audio_io_handle_t) data.readInt32()) );
             return NO_ERROR;
         } break;
         case LATENCY: {
@@ -960,7 +960,7 @@
             uint32_t sampleRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
-            reply->writeInt32( getInputBufferSize(sampleRate, format, channelMask) );
+            reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) );
             return NO_ERROR;
         } break;
         case OPEN_OUTPUT: {
@@ -1164,7 +1164,7 @@
         } break;
         case GET_PRIMARY_OUTPUT_FRAME_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32(getPrimaryOutputFrameCount());
+            reply->writeInt64(getPrimaryOutputFrameCount());
             return NO_ERROR;
         } break;
         case SET_LOW_RAM_DEVICE: {
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 3c0d4cf..1c299f7 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -55,7 +55,7 @@
             data.writeInt32(desc->samplingRate);
             data.writeInt32(desc->format);
             data.writeInt32(desc->channelMask);
-            data.writeInt32(desc->frameCount);
+            data.writeInt64(desc->frameCount);
             data.writeInt32(desc->latency);
         }
         remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
@@ -85,7 +85,7 @@
                 desc.samplingRate = data.readInt32();
                 desc.format = (audio_format_t) data.readInt32();
                 desc.channelMask = (audio_channel_mask_t) data.readInt32();
-                desc.frameCount = data.readInt32();
+                desc.frameCount = data.readInt64();
                 desc.latency = data.readInt32();
                 param2 = &desc;
             }
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index ffc21fc..265bb1b 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -118,7 +118,7 @@
     virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
-        data.writeInt32(size);
+        data.writeInt64(size);
         status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER,
                                              data, &reply);
         if (status == NO_ERROR) {
@@ -238,7 +238,7 @@
         case ALLOCATE_TIMED_BUFFER: {
             CHECK_INTERFACE(IAudioTrack, data, reply);
             sp<IMemory> buffer;
-            status_t status = allocateTimedBuffer(data.readInt32(), &buffer);
+            status_t status = allocateTimedBuffer(data.readInt64(), &buffer);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->writeStrongBinder(buffer->asBinder());
diff --git a/media/libmedia/IMediaLogService.cpp b/media/libmedia/IMediaLogService.cpp
index 33239a7..8a66c7c 100644
--- a/media/libmedia/IMediaLogService.cpp
+++ b/media/libmedia/IMediaLogService.cpp
@@ -43,7 +43,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor());
         data.writeStrongBinder(shared->asBinder());
-        data.writeInt32((int32_t) size);
+        data.writeInt64((int64_t) size);
         data.writeCString(name);
         status_t status = remote()->transact(REGISTER_WRITER, data, &reply);
         // FIXME ignores status
@@ -71,7 +71,7 @@
         case REGISTER_WRITER: {
             CHECK_INTERFACE(IMediaLogService, data, reply);
             sp<IMemory> shared = interface_cast<IMemory>(data.readStrongBinder());
-            size_t size = (size_t) data.readInt32();
+            size_t size = (size_t) data.readInt64();
             const char *name = data.readCString();
             registerWriter(shared, size, name);
             return NO_ERROR;
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index c7d9d51..432d890 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -101,7 +101,7 @@
             data.writeInt32(0);
         } else {
             // serialize the headers
-            data.writeInt32(headers->size());
+            data.writeInt64(headers->size());
             for (size_t i = 0; i < headers->size(); ++i) {
                 data.writeString8(headers->keyAt(i));
                 data.writeString8(headers->valueAt(i));
@@ -212,8 +212,8 @@
             const char* srcUrl = data.readCString();
 
             KeyedVector<String8, String8> headers;
-            int32_t numHeaders = data.readInt32();
-            for (int i = 0; i < numHeaders; ++i) {
+            size_t numHeaders = (size_t) data.readInt64();
+            for (size_t i = 0; i < numHeaders; ++i) {
                 String8 key = data.readString8();
                 String8 value = data.readString8();
                 headers.add(key, value);
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 71ce320..9c13848 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -140,7 +140,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
-        data.writeInt32(size);
+        data.writeInt64(size);
         data.write(params, size);
         remote()->transact(GET_PARAMETER, data, &reply);
 
@@ -161,7 +161,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
-        data.writeInt32(size);
+        data.writeInt64(size);
         data.write(params, size);
         remote()->transact(SET_PARAMETER, data, &reply);
 
@@ -175,7 +175,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
-        data.writeInt32(size);
+        data.writeInt64(size);
         data.write(params, size);
         remote()->transact(GET_CONFIG, data, &reply);
 
@@ -196,7 +196,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
-        data.writeInt32(size);
+        data.writeInt64(size);
         data.write(params, size);
         remote()->transact(SET_CONFIG, data, &reply);
 
@@ -375,7 +375,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
         data.writeInt32(port_index);
-        data.writeInt32(size);
+        data.writeInt64(size);
         remote()->transact(ALLOC_BUFFER, data, &reply);
 
         status_t err = reply.readInt32();
@@ -484,7 +484,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeIntPtr((intptr_t)node);
         data.writeInt32(port_index);
-        data.writeInt32(size);
+        data.writeInt64(size);
         data.write(optionData, size);
         data.writeInt32(type);
         remote()->transact(SET_INTERNAL_OPTION, data, &reply);
@@ -596,7 +596,7 @@
             node_id node = (void*)data.readIntPtr();
             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
 
-            size_t size = data.readInt32();
+            size_t size = data.readInt64();
 
             void *params = malloc(size);
             data.read(params, size);
@@ -810,7 +810,7 @@
 
             node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
-            size_t size = data.readInt32();
+            size_t size = data.readInt64();
 
             buffer_id buffer;
             void *buffer_data;
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index 68ffca8..fe2cc61 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -62,7 +62,7 @@
     virtual void setBuffers(const Vector<sp<IMemory> > &buffers) {
         Parcel data, reply;
         data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(buffers.size()));
+        data.writeInt64(static_cast<int64_t>(buffers.size()));
         for (size_t i = 0; i < buffers.size(); ++i) {
             data.writeStrongBinder(buffers.itemAt(i)->asBinder());
         }
@@ -72,7 +72,7 @@
     virtual void onBufferAvailable(size_t index) {
         Parcel data, reply;
         data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(index));
+        data.writeInt64(static_cast<int64_t>(index));
         remote()->transact(
                 ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
     }
@@ -102,7 +102,7 @@
         case SET_BUFFERS:
         {
             CHECK_INTERFACE(IStreamSource, data, reply);
-            size_t n = static_cast<size_t>(data.readInt32());
+            size_t n = static_cast<size_t>(data.readInt64());
             Vector<sp<IMemory> > buffers;
             for (size_t i = 0; i < n; ++i) {
                 sp<IMemory> mem =
@@ -117,7 +117,7 @@
         case ON_BUFFER_AVAILABLE:
         {
             CHECK_INTERFACE(IStreamSource, data, reply);
-            onBufferAvailable(static_cast<size_t>(data.readInt32()));
+            onBufferAvailable(static_cast<size_t>(data.readInt64()));
             break;
         }
 
@@ -145,8 +145,8 @@
     virtual void queueBuffer(size_t index, size_t size) {
         Parcel data, reply;
         data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(index));
-        data.writeInt32(static_cast<int32_t>(size));
+        data.writeInt64(static_cast<int64_t>(index));
+        data.writeInt64(static_cast<int64_t>(size));
 
         remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
     }
@@ -177,8 +177,8 @@
         case QUEUE_BUFFER:
         {
             CHECK_INTERFACE(IStreamListener, data, reply);
-            size_t index = static_cast<size_t>(data.readInt32());
-            size_t size = static_cast<size_t>(data.readInt32());
+            size_t index = static_cast<size_t>(data.readInt64());
+            size_t size = static_cast<size_t>(data.readInt64());
 
             queueBuffer(index, size);
             break;
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
index f004ca4..66f7161 100644
--- a/media/libmedia/MemoryLeakTrackUtil.cpp
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -17,6 +17,7 @@
 #include <media/MemoryLeakTrackUtil.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
 
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index 96738a7..4d9a1fa 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -343,7 +343,7 @@
     String8 timestamp, body;
     lost += i;
     if (lost > 0) {
-        body.appendFormat("warning: lost %u bytes worth of events", lost);
+        body.appendFormat("warning: lost %zu bytes worth of events", lost);
         // TODO timestamp empty here, only other choice to wait for the first timestamp event in the
         //      log to push it out.  Consider keeping the timestamp/body between calls to readAt().
         dumpLine(timestamp, body);
@@ -354,7 +354,7 @@
         maxSec /= 10;
     }
     if (maxSec >= 0) {
-        timestamp.appendFormat("[%*s]", width + 4, "");
+        timestamp.appendFormat("[%*s]", (int) width + 4, "");
     }
     bool deferredTimestamp = false;
     while (i < avail) {
@@ -364,7 +364,7 @@
         size_t advance = length + 3;
         switch (event) {
         case EVENT_STRING:
-            body.appendFormat("%.*s", length, (const char *) data);
+            body.appendFormat("%.*s", (int) length, (const char *) data);
             break;
         case EVENT_TIMESTAMP: {
             // already checked that length == sizeof(struct timespec);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index f11791c..5bca317 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -17,6 +17,8 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ACodec"
 
+#include <utils/Trace.h>
+
 #include <media/stagefright/ACodec.h>
 
 #include <binder/MemoryDealer.h>
@@ -3681,6 +3683,7 @@
     if (mCodec->mNativeWindow != NULL
             && msg->findInt32("render", &render) && render != 0
             && info->mData != NULL && info->mData->size() != 0) {
+        ATRACE_NAME("render");
         // The client wants this buffer to be rendered.
 
         status_t err;
@@ -3693,6 +3696,10 @@
             info->mStatus = BufferInfo::OWNED_BY_US;
         }
     } else {
+        if (mCodec->mNativeWindow != NULL &&
+            (info->mData == NULL || info->mData->size() != 0)) {
+            ATRACE_NAME("frame-drop");
+        }
         info->mStatus = BufferInfo::OWNED_BY_US;
     }
 
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 714b5e0..d9e39ff 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -14,6 +14,7 @@
         AwesomePlayer.cpp                 \
         CameraSource.cpp                  \
         CameraSourceTimeLapse.cpp         \
+        ClockEstimator.cpp                \
         DataSource.cpp                    \
         DataURISource.cpp                 \
         DRMExtractor.cpp                  \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 6e5003f..8d3032b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -42,6 +42,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/timedtext/TimedTextDriver.h>
 #include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/ClockEstimator.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -231,6 +232,8 @@
                               &AwesomePlayer::onAudioTearDownEvent);
     mAudioTearDownEventPending = false;
 
+    mClockEstimator = new WindowedLinearFitEstimator();
+
     reset();
 }
 
@@ -1866,21 +1869,28 @@
     TimeSource *ts =
         ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
             ? &mSystemTimeSource : mTimeSource;
+    int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs();
+    int64_t looperTimeUs = ALooper::GetNowUs();
 
     if (mFlags & FIRST_FRAME) {
         modifyFlags(FIRST_FRAME, CLEAR);
         mSinceLastDropped = 0;
-        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
+        mClockEstimator->reset();
+        mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs;
     }
 
     int64_t realTimeUs, mediaTimeUs;
     if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
         && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
+        ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")",
+              mTimeSourceDeltaUs, realTimeUs - mediaTimeUs,
+              mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs));
+        ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3);
         mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
     }
 
     if (wasSeeking == SEEK_VIDEO_ONLY) {
-        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
+        int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs;
 
         int64_t latenessUs = nowUs - timeUs;
 
@@ -1891,12 +1901,13 @@
         }
     }
 
+    int64_t latenessUs = 0;
     if (wasSeeking == NO_SEEK) {
         // Let's display the first frame after seeking right away.
 
-        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
+        int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs;
 
-        int64_t latenessUs = nowUs - timeUs;
+        latenessUs = nowUs - timeUs;
 
         ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
 
@@ -1950,9 +1961,9 @@
             }
         }
 
-        if (latenessUs < -10000) {
-            // We're more than 10ms early.
-            postVideoEvent_l(10000);
+        if (latenessUs < -30000) {
+            // We're more than 30ms early, schedule at most 20 ms before time due
+            postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000);
             return;
         }
     }
@@ -1966,6 +1977,8 @@
 
     if (mVideoRenderer != NULL) {
         mSinceLastDropped++;
+        mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs);
+
         mVideoRenderer->render(mVideoBuffer);
         if (!mVideoRenderingStarted) {
             mVideoRenderingStarted = true;
@@ -2015,14 +2028,26 @@
 
         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);
+        systemTimeUs = mSystemTimeSource.getRealTimeUs();
+        int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs;
+        ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3);
+        ALOGV("next frame in %" PRId64, delayUs);
+        // try to schedule 30ms before time due
+        postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000));
         return;
     }
 
     postVideoEvent_l();
 }
 
+int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) {
+    if (ts == &mSystemTimeSource) {
+        return systemTimeUs;
+    } else {
+        return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs());
+    }
+}
+
 void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
     ATRACE_CALL();
 
diff --git a/media/libstagefright/ClockEstimator.cpp b/media/libstagefright/ClockEstimator.cpp
new file mode 100644
index 0000000..34d1e42
--- /dev/null
+++ b/media/libstagefright/ClockEstimator.cpp
@@ -0,0 +1,177 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClockEstimator"
+#include <utils/Log.h>
+
+#include <math.h>
+#include <media/stagefright/ClockEstimator.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+WindowedLinearFitEstimator::WindowedLinearFitEstimator(
+        size_t headLength, double headFactor, size_t mainLength, double tailFactor)
+    : mHeadFactorInv(1. / headFactor),
+      mTailFactor(tailFactor),
+      mHistoryLength(mainLength + headLength),
+      mHeadLength(headLength) {
+    reset();
+    mXHistory.resize(mHistoryLength);
+    mYHistory.resize(mHistoryLength);
+    mFirstWeight = pow(headFactor, mHeadLength);
+}
+
+WindowedLinearFitEstimator::LinearFit::LinearFit() {
+    reset();
+}
+
+void WindowedLinearFitEstimator::LinearFit::reset() {
+    mX = mXX = mY = mYY = mXY = mW = 0.;
+}
+
+double WindowedLinearFitEstimator::LinearFit::size() const {
+    double s = mW * mW + mX * mX + mY * mY + mXX * mXX + mXY * mXY + mYY * mYY;
+    if (s > 1e72) {
+        // 1e72 corresponds to clock monotonic time of about 8 years
+        ALOGW("estimator is overflowing: w=%g x=%g y=%g xx=%g xy=%g yy=%g",
+              mW, mX, mY, mXX, mXY, mYY);
+    }
+    return s;
+}
+
+void WindowedLinearFitEstimator::LinearFit::add(double x, double y, double w) {
+    mW += w;
+    mX += w * x;
+    mY += w * y;
+    mXX += w * x * x;
+    mXY += w * x * y;
+    mYY += w * y * y;
+}
+
+void WindowedLinearFitEstimator::LinearFit::combine(const LinearFit &lf) {
+    mW += lf.mW;
+    mX += lf.mX;
+    mY += lf.mY;
+    mXX += lf.mXX;
+    mXY += lf.mXY;
+    mYY += lf.mYY;
+}
+
+void WindowedLinearFitEstimator::LinearFit::scale(double w) {
+    mW *= w;
+    mX *= w;
+    mY *= w;
+    mXX *= w;
+    mXY *= w;
+    mYY *= w;
+}
+
+double WindowedLinearFitEstimator::LinearFit::interpolate(double x) {
+    double div = mW * mXX - mX * mX;
+    if (fabs(div) < 1e-5 * mW * mW) {
+        // this only should happen on the first value
+        return x;
+        // assuming a = 1, we could also return x + (mY - mX) / mW;
+    }
+    double a_div = (mW * mXY - mX * mY);
+    double b_div = (mXX * mY - mX * mXY);
+    ALOGV("a=%.4g b=%.4g in=%g out=%g",
+            a_div / div, b_div / div, x, (a_div * x + b_div) / div);
+    return (a_div * x + b_div) / div;
+}
+
+double WindowedLinearFitEstimator::estimate(double x, double y) {
+    /*
+     * TODO: We could update the head by adding the new sample to it
+     * and amplifying it, but this approach can lead to unbounded
+     * error. Instead, we recalculate the head at each step, which
+     * is computationally more expensive. We could balance the two
+     * methods by recalculating just before the error becomes
+     * significant.
+     */
+    const bool update_head = false;
+    if (update_head) {
+        // add new sample to the head
+        mHead.scale(mHeadFactorInv); // amplify head
+        mHead.add(x, y, mFirstWeight);
+    }
+
+    /*
+     * TRICKY: place elements into the circular buffer at decreasing
+     * indices, so that we can access past elements by addition
+     * (thereby avoiding potentially negative indices.)
+     */
+    if (mNumSamples >= mHeadLength) {
+        // move last head sample from head to the main window
+        size_t lastHeadIx = (mSampleIx + mHeadLength) % mHistoryLength;
+        if (update_head) {
+            mHead.add(mXHistory[lastHeadIx], mYHistory[lastHeadIx], -1.); // remove
+        }
+        mMain.add(mXHistory[lastHeadIx], mYHistory[lastHeadIx], 1.);
+        if (mNumSamples >= mHistoryLength) {
+            // move last main sample from main window to tail
+            mMain.add(mXHistory[mSampleIx], mYHistory[mSampleIx], -1.); // remove
+            mTail.add(mXHistory[mSampleIx], mYHistory[mSampleIx], 1.);
+            mTail.scale(mTailFactor); // attenuate tail
+        }
+    }
+
+    mXHistory.editItemAt(mSampleIx) = x;
+    mYHistory.editItemAt(mSampleIx) = y;
+    if (mNumSamples < mHistoryLength) {
+        ++mNumSamples;
+    }
+
+    // recalculate head unless we were using the update method
+    if (!update_head) {
+        mHead.reset();
+        double w = mFirstWeight;
+        for (size_t headIx = 0; headIx < mHeadLength && headIx < mNumSamples; ++headIx) {
+            size_t ix = (mSampleIx + headIx) % mHistoryLength;
+            mHead.add(mXHistory[ix], mYHistory[ix], w);
+            w *= mHeadFactorInv;
+        }
+    }
+
+    if (mSampleIx > 0) {
+        --mSampleIx;
+    } else {
+        mSampleIx = mHistoryLength - 1;
+    }
+
+    // return estimation result
+    LinearFit total;
+    total.combine(mHead);
+    total.combine(mMain);
+    total.combine(mTail);
+    return total.interpolate(x);
+}
+
+void WindowedLinearFitEstimator::reset() {
+    mHead.reset();
+    mMain.reset();
+    mTail.reset();
+    mNumSamples = 0;
+    mSampleIx = mHistoryLength - 1;
+}
+
+}; // namespace android
+
+
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 515e4d3..8f356b6 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -355,7 +355,12 @@
         outHeader->nFlags = 0;
         int err = vorbis_dsp_synthesis(mState, &pack, 1);
         if (err != 0) {
+            // FIXME temporary workaround for log spam
+#if !defined(__arm__) && !defined(__aarch64__)
+            ALOGV("vorbis_dsp_synthesis returned %d", err);
+#else
             ALOGW("vorbis_dsp_synthesis returned %d", err);
+#endif
         } else {
             numFrames = vorbis_dsp_pcmout(
                     mState, (int16_t *)outHeader->pBuffer,
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index a81bbba..77d65e0 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -32,6 +32,7 @@
 namespace android {
 
 struct AudioPlayer;
+struct ClockEstimator;
 struct DataSource;
 struct MediaBuffer;
 struct MediaExtractor;
@@ -236,6 +237,7 @@
 
     MediaBuffer *mVideoBuffer;
 
+    sp<ClockEstimator> mClockEstimator;
     sp<HTTPBase> mConnectingDataSource;
     sp<NuCachedSource2> mCachedSource;
 
@@ -296,6 +298,7 @@
 
     bool getBitrate(int64_t *bitrate);
 
+    int64_t estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs);
     void finishSeekIfNecessary(int64_t videoTimeUs);
     void ensureCacheIsFetching_l();
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 755d480..eb00c82 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -541,10 +541,8 @@
         goto Exit;
     }
 
-    // client is responsible for conversion of 8-bit PCM to 16-bit PCM,
-    // and we don't yet support 8.24 or 32-bit PCM
-    if (!audio_is_valid_format(format) ||
-            (audio_is_linear_pcm(format) && format != AUDIO_FORMAT_PCM_16_BIT)) {
+    // further format checks are performed by createTrack_l() depending on the thread type
+    if (!audio_is_valid_format(format)) {
         ALOGE("createTrack() invalid format %#x", format);
         lStatus = BAD_VALUE;
         goto Exit;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2f874f5..16d6f42 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1936,9 +1936,6 @@
                 if (msg->message.error.error_code == CAMERA3_MSG_ERROR_DEVICE) {
                     listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
                                           resultExtras);
-                } else {
-                    listener->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE,
-                                          resultExtras);
                 }
             } else {
                 ALOGE("Camera %d: %s: no listener available", mId, __FUNCTION__);